From 88c0b5d425c1be62b3a2a54ab4d1c45a59172ca7 Mon Sep 17 00:00:00 2001 From: Xidorn Quan Date: Tue, 25 Oct 2016 17:25:10 +1100 Subject: [PATCH 01/60] Bug 1310123 - Move values of static constants in nsStyleStruct to the header. r=mats MozReview-Commit-ID: J5Fp0iAEnkg --HG-- extra : rebase_source : 51870f9798ba6e34ee809421589c09c1d5ec584f --- layout/style/nsStyleStruct.cpp | 6 ------ layout/style/nsStyleStruct.h | 8 +++++--- 2 files changed, 5 insertions(+), 9 deletions(-) diff --git a/layout/style/nsStyleStruct.cpp b/layout/style/nsStyleStruct.cpp index 9d76b0832a36..7e755e25f3db 100644 --- a/layout/style/nsStyleStruct.cpp +++ b/layout/style/nsStyleStruct.cpp @@ -45,11 +45,6 @@ static_assert((((1 << nsStyleStructID_Length) - 1) & ~(NS_STYLE_INHERIT_MASK)) == 0, "Not enough bits in NS_STYLE_INHERIT_MASK"); -// These are the limits that we choose to clamp grid line numbers to. -// http://dev.w3.org/csswg/css-grid/#overlarge-grids -const int32_t nsStyleGridLine::kMinLine = -10000; -const int32_t nsStyleGridLine::kMaxLine = 10000; - static bool EqualURIs(nsIURI *aURI1, nsIURI *aURI2) { @@ -822,7 +817,6 @@ nsStyleXUL::CalcDifference(const nsStyleXUL& aNewData) const // -------------------- // nsStyleColumn // -/* static */ const uint32_t nsStyleColumn::kMaxColumnCount = 1000; nsStyleColumn::nsStyleColumn(StyleStructContext aContext) : mColumnCount(NS_STYLE_COLUMN_COUNT_AUTO) diff --git a/layout/style/nsStyleStruct.h b/layout/style/nsStyleStruct.h index b9ac3ff32771..5a7e85197a30 100644 --- a/layout/style/nsStyleStruct.h +++ b/layout/style/nsStyleStruct.h @@ -1593,9 +1593,11 @@ struct nsStyleGridLine int32_t mInteger; // 0 means not provided nsString mLineName; // Empty string means not provided. + // These are the limits that we choose to clamp grid line numbers to. + // http://dev.w3.org/csswg/css-grid/#overlarge-grids // mInteger is clamped to this range: - static const int32_t kMinLine; - static const int32_t kMaxLine; + static const int32_t kMinLine = -10000; + static const int32_t kMaxLine = 10000; nsStyleGridLine() : mHasSpan(false) @@ -3467,7 +3469,7 @@ struct MOZ_NEEDS_MEMMOVABLE_MEMBERS nsStyleColumn * This is the maximum number of columns we can process. It's used in both * nsColumnSetFrame and nsRuleNode. */ - static const uint32_t kMaxColumnCount; + static const uint32_t kMaxColumnCount = 1000; uint32_t mColumnCount; // [reset] see nsStyleConsts.h nsStyleCoord mColumnWidth; // [reset] coord, auto From 945fecae1112322b53e338c5c7753e8880a14865 Mon Sep 17 00:00:00 2001 From: Mike Conley Date: Tue, 25 Oct 2016 13:57:44 -0400 Subject: [PATCH 02/60] Bug 1303067 - Enable unsubmitted crash notification for more users. r=Felipe MozReview-Commit-ID: 8pK5DKBcrX3 --HG-- extra : rebase_source : 0a0a18aaff8b3c9bab04a564358c9433872ddfdd --- browser/app/profile/firefox.js | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/browser/app/profile/firefox.js b/browser/app/profile/firefox.js index 554be0af3321..92d00cab4c6f 100644 --- a/browser/app/profile/firefox.js +++ b/browser/app/profile/firefox.js @@ -1543,10 +1543,10 @@ pref("webchannel.allowObject.urlWhitelist", "https://accounts.firefox.com https: // Whether or not the browser should scan for unsubmitted // crash reports, and then show a notification for submitting // those reports. -#ifdef RELEASE_OR_BETA -pref("browser.crashReports.unsubmittedCheck.enabled", false); -#else +#ifdef EARLY_BETA_OR_EARLIER pref("browser.crashReports.unsubmittedCheck.enabled", true); +#else +pref("browser.crashReports.unsubmittedCheck.enabled", false); #endif // chancesUntilSuppress is how many times we'll show the unsubmitted From 78c3624c288fbdeb5ce2a9bd0f451aef1d5557e6 Mon Sep 17 00:00:00 2001 From: Francesco Pischedda Date: Sat, 15 Oct 2016 09:45:22 +0200 Subject: [PATCH 03/60] Bug 1285555 - [flake8] Automatically install/update flake8 package to correct version r=ahal Changed flake8 installation strategy, try to update it using testings/lint/flake8_requirements.txt moved flake8_requirements to tools/lint/flake8 directory extracted common pip invocations to _run_pip function minor fixes fixed calls to check_process (concatenating list to tuple) removed update_pip function and its error message variable if flake8 installation reports and error print pip command output - replaced out with e.output in print function MozReview-Commit-ID: Fmq22aL8dMq --HG-- extra : rebase_source : 2e2f942c1ffab012795c632ceacf6debf0dc1407 --- testing/docker/lint/Dockerfile | 2 + testing/docker/lint/system-setup.sh | 13 +---- tools/lint/flake8.lint | 70 +++++++++++++++++++---- tools/lint/flake8/flake8_requirements.txt | 4 ++ tools/lint/mach_commands.py | 1 + 5 files changed, 66 insertions(+), 24 deletions(-) create mode 100644 tools/lint/flake8/flake8_requirements.txt diff --git a/testing/docker/lint/Dockerfile b/testing/docker/lint/Dockerfile index ddda87a4e1d5..7e9b41214cf0 100644 --- a/testing/docker/lint/Dockerfile +++ b/testing/docker/lint/Dockerfile @@ -14,6 +14,8 @@ ADD topsrcdir/testing/mozharness/external_tools/robustcheckout.py /usr/local/mer # %include testing/docker/recipes/install-mercurial.sh ADD topsrcdir/testing/docker/recipes/install-mercurial.sh /build/install-mercurial.sh ADD system-setup.sh /tmp/system-setup.sh +# %include tools/lint/flake8/flake8_requirements.txt +ADD topsrcdir/tools/lint/flake8/flake8_requirements.txt /tmp/flake8_requirements.txt RUN bash /tmp/system-setup.sh # %include testing/docker/recipes/run-task diff --git a/testing/docker/lint/system-setup.sh b/testing/docker/lint/system-setup.sh index 9f8052a2d81a..2a2fc6bdd5a4 100644 --- a/testing/docker/lint/system-setup.sh +++ b/testing/docker/lint/system-setup.sh @@ -61,19 +61,8 @@ npm -v ### cd /setup -cat >requirements.txt <<'EOF' -flake8==2.5.4 \ - --hash=sha256:fb5a67af4024622287a76abf6b7fe4fb3cfacf765a790976ce64f52c44c88e4a -mccabe==0.4.0 \ - --hash=sha256:cbc2938f6c01061bc6d21d0c838c2489664755cb18676f0734d7617f4577d09e -pep8==1.7.0 \ - --hash=sha256:4fc2e478addcf17016657dff30b2d8d611e8341fac19ccf2768802f6635d7b8a -pyflakes==1.2.3 \ - --hash=sha256:e87bac26c62ea5b45067cc89e4a12f56e1483f1f2cda17e7c9b375b9fd2f40da -EOF -pip install --require-hashes -r requirements.txt +pip install --require-hashes -r /tmp/flake8_requirements.txt cd / rm -rf /setup - diff --git a/tools/lint/flake8.lint b/tools/lint/flake8.lint index f85389162e8f..22545b31d132 100644 --- a/tools/lint/flake8.lint +++ b/tools/lint/flake8.lint @@ -7,6 +7,7 @@ import json import os import signal +import subprocess import which from mozprocess import ProcessHandler @@ -14,13 +15,22 @@ from mozprocess import ProcessHandler from mozlint import result +here = os.path.abspath(os.path.dirname(__file__)) +FLAKE8_REQUIREMENTS_PATH = os.path.join(here, 'flake8', 'flake8_requirements.txt') + FLAKE8_NOT_FOUND = """ Could not find flake8! Install flake8 and try again. - $ pip install flake8 -""".strip() + $ pip install -U --require-hashes -r {} +""".strip().format(FLAKE8_REQUIREMENTS_PATH) +FLAKE8_INSTALL_ERROR = """ +Unable to install correct version of flake8 +Try to install it manually with: + $ pip install -U --require-hashes -r {} +""".strip().format(FLAKE8_REQUIREMENTS_PATH) + LINE_OFFSETS = { # continuation line under-indented for hanging indent 'E121': (-1, 2), @@ -83,17 +93,54 @@ def run_process(cmdargs): proc.kill() -def lint(files, **lintargs): +def get_flake8_binary(): + """ + Returns the path of the first flake8 binary available + if not found returns None + """ binary = os.environ.get('FLAKE8') - if not binary: - try: - binary = which.which('flake8') - except which.WhichError: - pass + if binary: + return binary - if not binary: - print(FLAKE8_NOT_FOUND) - return [] + try: + return which.which('flake8') + except which.WhichError: + return None + + +def _run_pip(*args): + """ + Helper function that runs pip with subprocess + """ + try: + subprocess.check_output(['pip'] + list(args), + stderr=subprocess.STDOUT) + return True + except subprocess.CalledProcessError as e: + print(e.output) + return False + + +def reinstall_flake8(): + """ + Try to install flake8 at the target version, returns True on success + otherwise prints the otuput of the pip command and returns False + """ + if _run_pip('install', '-U', + '--require-hashes', '-r', + FLAKE8_REQUIREMENTS_PATH): + return True + + return False + + +def lint(files, **lintargs): + + if not reinstall_flake8(): + print(FLAKE8_INSTALL_ERROR) + return 1 + + binary = get_flake8_binary() cmdargs = [ binary, @@ -119,7 +166,6 @@ def lint(files, **lintargs): if exclude: cmdargs += ['--exclude', ','.join(lintargs['exclude'])] - if no_config: run_process(cmdargs+no_config) diff --git a/tools/lint/flake8/flake8_requirements.txt b/tools/lint/flake8/flake8_requirements.txt new file mode 100644 index 000000000000..df927d826217 --- /dev/null +++ b/tools/lint/flake8/flake8_requirements.txt @@ -0,0 +1,4 @@ +flake8==2.5.4 --hash=sha256:fb5a67af4024622287a76abf6b7fe4fb3cfacf765a790976ce64f52c44c88e4a +mccabe==0.4.0 --hash=sha256:cbc2938f6c01061bc6d21d0c838c2489664755cb18676f0734d7617f4577d09e +pep8==1.7.0 --hash=sha256:4fc2e478addcf17016657dff30b2d8d611e8341fac19ccf2768802f6635d7b8a +pyflakes==1.2.3 --hash=sha256:e87bac26c62ea5b45067cc89e4a12f56e1483f1f2cda17e7c9b375b9fd2f40da diff --git a/tools/lint/mach_commands.py b/tools/lint/mach_commands.py index e95337bfbe8e..f0f3c9bdf686 100644 --- a/tools/lint/mach_commands.py +++ b/tools/lint/mach_commands.py @@ -39,6 +39,7 @@ class MachCommands(MachCommandBase): from mozlint import cli lintargs['exclude'] = ['obj*'] cli.SEARCH_PATHS.append(here) + self._activate_virtualenv() return cli.run(*runargs, **lintargs) @Command('eslint', category='devenv', From 8cfa990adf983f7d0343b2982dc8ad68e89f3cb4 Mon Sep 17 00:00:00 2001 From: Aaron Klotz Date: Tue, 25 Oct 2016 15:43:40 -0600 Subject: [PATCH 04/60] Bug 1311834: Make MainThreadInvoker use a spin loop on multiprocessor machines; r=jimm MozReview-Commit-ID: 5xKdm7Z4oKs --HG-- extra : rebase_source : f71e3b762501d8e24446ba8913c841cfe03a277b --- ipc/mscom/MainThreadInvoker.cpp | 118 ++++++++++++++++++++++---------- ipc/mscom/MainThreadInvoker.h | 10 +-- ipc/mscom/moz.build | 1 + 3 files changed, 85 insertions(+), 44 deletions(-) diff --git a/ipc/mscom/MainThreadInvoker.cpp b/ipc/mscom/MainThreadInvoker.cpp index 9e57d9a29ebc..cab62a727928 100644 --- a/ipc/mscom/MainThreadInvoker.cpp +++ b/ipc/mscom/MainThreadInvoker.cpp @@ -9,35 +9,89 @@ #include "GeckoProfiler.h" #include "MainThreadUtils.h" #include "mozilla/Assertions.h" +#include "mozilla/Atomics.h" #include "mozilla/ClearOnShutdown.h" #include "mozilla/DebugOnly.h" #include "mozilla/HangMonitor.h" #include "mozilla/RefPtr.h" +#include "nsServiceManagerUtils.h" +#include "nsSystemInfo.h" #include "private/prpriv.h" // For PR_GetThreadID #include "WinUtils.h" +// This gives us compiler intrinsics for the x86 PAUSE instruction +#if defined(_MSC_VER) +#include +#pragma intrinsic(_mm_pause) +#define CPU_PAUSE() _mm_pause() +#elif defined(__GNUC__) || defined(__clang__) +#define CPU_PAUSE() __builtin_ia32_pause() +#endif + +static bool sIsMulticore; + namespace { -class SyncRunnable : public mozilla::Runnable +/** + * SyncRunnable implements different code paths depending on whether or not + * we are running on a multiprocessor system. In the multiprocessor case, we + * leave the thread in a spin loop while waiting for the main thread to execute + * our runnable. Since spinning is pointless in the uniprocessor case, we block + * on an event that is set by the main thread once it has finished the runnable. + */ +class MOZ_RAII SyncRunnable { public: - SyncRunnable(HANDLE aEvent, already_AddRefed&& aRunnable) - : mDoneEvent(aEvent) + explicit SyncRunnable(already_AddRefed&& aRunnable) + : mDoneEvent(sIsMulticore ? nullptr : + ::CreateEventW(nullptr, FALSE, FALSE, nullptr)) + , mDone(false) , mRunnable(aRunnable) { - MOZ_ASSERT(aEvent); + MOZ_ASSERT(sIsMulticore || mDoneEvent); MOZ_ASSERT(mRunnable); } - NS_IMETHOD Run() override + ~SyncRunnable() + { + if (mDoneEvent) { + ::CloseHandle(mDoneEvent); + } + } + + void Run() { mRunnable->Run(); - ::SetEvent(mDoneEvent); - return NS_OK; + + if (mDoneEvent) { + ::SetEvent(mDoneEvent); + } else { + mDone = true; + } + } + + bool WaitUntilComplete() + { + if (mDoneEvent) { + HANDLE handles[] = {mDoneEvent, + mozilla::mscom::MainThreadInvoker::GetTargetThread()}; + DWORD waitResult = ::WaitForMultipleObjects(mozilla::ArrayLength(handles), + handles, FALSE, INFINITE); + return waitResult == WAIT_OBJECT_0; + } + + while (!mDone) { + // The PAUSE instruction is a hint to the CPU that we're doing a spin + // loop. It is a no-op on older processors that don't support it, so + // it is safe to use here without any CPUID checks. + CPU_PAUSE(); + } + return true; } private: HANDLE mDoneEvent; + mozilla::Atomic mDone; nsCOMPtr mRunnable; }; @@ -56,67 +110,60 @@ MainThreadInvoker::InitStatics() if (NS_FAILED(rv)) { return false; } + PRThread* mainPrThread = nullptr; rv = mainThread->GetPRThread(&mainPrThread); if (NS_FAILED(rv)) { return false; } + PRUint32 tid = ::PR_GetThreadID(mainPrThread); sMainThread = ::OpenThread(SYNCHRONIZE | THREAD_SET_CONTEXT, FALSE, tid); + + nsCOMPtr infoService = do_GetService(NS_SYSTEMINFO_CONTRACTID); + if (infoService) { + uint32_t cpuCount; + nsresult rv = infoService->GetPropertyAsUint32(NS_LITERAL_STRING("cpucount"), + &cpuCount); + sIsMulticore = NS_SUCCEEDED(rv) && cpuCount > 1; + } + return !!sMainThread; } MainThreadInvoker::MainThreadInvoker() - : mDoneEvent(::CreateEventW(nullptr, FALSE, FALSE, nullptr)) { static const bool gotStatics = InitStatics(); MOZ_ASSERT(gotStatics); } -MainThreadInvoker::~MainThreadInvoker() -{ - if (mDoneEvent) { - ::CloseHandle(mDoneEvent); - } -} - bool -MainThreadInvoker::WaitForCompletion(DWORD aTimeout) -{ - HANDLE handles[] = {mDoneEvent, sMainThread}; - DWORD waitResult = ::WaitForMultipleObjects(ArrayLength(handles), handles, - FALSE, aTimeout); - return waitResult == WAIT_OBJECT_0; -} - -bool -MainThreadInvoker::Invoke(already_AddRefed&& aRunnable, - DWORD aTimeout) +MainThreadInvoker::Invoke(already_AddRefed&& aRunnable) { nsCOMPtr runnable(Move(aRunnable)); if (!runnable) { return false; } + if (NS_IsMainThread()) { runnable->Run(); return true; } - RefPtr wrappedRunnable(new SyncRunnable(mDoneEvent, - runnable.forget())); - // Make sure that wrappedRunnable remains valid while sitting in the APC queue - wrappedRunnable->AddRef(); + + SyncRunnable syncRunnable(runnable.forget()); + if (!::QueueUserAPC(&MainThreadAPC, sMainThread, - reinterpret_cast(wrappedRunnable.get()))) { - // Enqueue failed so cancel the above AddRef - wrappedRunnable->Release(); + reinterpret_cast(&syncRunnable))) { return false; } + // We should ensure a call to NtTestAlert() is made on the main thread so // that the main thread will check for APCs during event processing. If we // omit this then the main thread will not check its APC queue until it is // idle. widget::WinUtils::SetAPCPending(); - return WaitForCompletion(aTimeout); + + return syncRunnable.WaitUntilComplete(); } /* static */ VOID CALLBACK @@ -125,8 +172,7 @@ MainThreadInvoker::MainThreadAPC(ULONG_PTR aParam) GeckoProfilerWakeRAII wakeProfiler; mozilla::HangMonitor::NotifyActivity(mozilla::HangMonitor::kGeneralActivity); MOZ_ASSERT(NS_IsMainThread()); - RefPtr runnable(already_AddRefed( - reinterpret_cast(aParam))); + auto runnable = reinterpret_cast(aParam); runnable->Run(); } diff --git a/ipc/mscom/MainThreadInvoker.h b/ipc/mscom/MainThreadInvoker.h index 526d5e8317a9..4bd1f803fcbf 100644 --- a/ipc/mscom/MainThreadInvoker.h +++ b/ipc/mscom/MainThreadInvoker.h @@ -21,21 +21,15 @@ class MainThreadInvoker { public: MainThreadInvoker(); - ~MainThreadInvoker(); - bool WaitForCompletion(DWORD aTimeout = INFINITE); - bool Invoke(already_AddRefed&& aRunnable, - DWORD aTimeout = INFINITE); - HANDLE GetTargetThread() const { return sMainThread; } + bool Invoke(already_AddRefed&& aRunnable); + static HANDLE GetTargetThread() { return sMainThread; } private: static bool InitStatics(); static VOID CALLBACK MainThreadAPC(ULONG_PTR aParam); - HANDLE mDoneEvent; - static HANDLE sMainThread; - static StaticRefPtr sAlertRunnable; }; } // namespace mscom diff --git a/ipc/mscom/moz.build b/ipc/mscom/moz.build index 68e63ccea355..cd0b1b639953 100644 --- a/ipc/mscom/moz.build +++ b/ipc/mscom/moz.build @@ -49,6 +49,7 @@ if CONFIG['ACCESSIBILITY']: ] LOCAL_INCLUDES += [ + '/xpcom/base', '/xpcom/build', ] From 3d795f2c3ec45645980b4d4164330f6bab564dfb Mon Sep 17 00:00:00 2001 From: Mantaroh Yoshinaga Date: Wed, 19 Oct 2016 15:16:51 +0900 Subject: [PATCH 05/60] Bug 1287983 part 1 - Add transitionstart/transitionrun event handlers. r=masayuki,smaug This transitionstart and transitionrun event is defined in editor's draft of CSS Transition Level 2. https://drafts.csswg.org/css-transitions-2/#transition-events MozReview-Commit-ID: 6c0GqlaOOPZ --HG-- extra : rebase_source : 9d16572634a388da25e16096f06087e808ec57ae --- dom/base/nsGkAtomList.h | 2 ++ dom/events/EventNameList.h | 8 ++++++++ dom/webidl/EventHandler.webidl | 2 ++ widget/EventMessageList.h | 2 ++ 4 files changed, 14 insertions(+) diff --git a/dom/base/nsGkAtomList.h b/dom/base/nsGkAtomList.h index 9a22e161b56d..b3961e6a8e09 100644 --- a/dom/base/nsGkAtomList.h +++ b/dom/base/nsGkAtomList.h @@ -938,6 +938,8 @@ GK_ATOM(ontouchend, "ontouchend") GK_ATOM(ontouchmove, "ontouchmove") GK_ATOM(ontouchcancel, "ontouchcancel") GK_ATOM(ontransitionend, "ontransitionend") +GK_ATOM(ontransitionrun, "ontransitionrun") +GK_ATOM(ontransitionstart, "ontransitionstart") GK_ATOM(onunderflow, "onunderflow") GK_ATOM(onunload, "onunload") GK_ATOM(onupdatefound, "onupdatefound") diff --git a/dom/events/EventNameList.h b/dom/events/EventNameList.h index 944a8f18087e..6a3eb9f50eee 100644 --- a/dom/events/EventNameList.h +++ b/dom/events/EventNameList.h @@ -979,6 +979,14 @@ NON_IDL_EVENT(MozEdgeUICompleted, eSimpleGestureEventClass) // CSS Transition & Animation events: +EVENT(transitionstart, + eTransitionStart, + EventNameType_All, + eTransitionEventClass) +EVENT(transitionrun, + eTransitionRun, + EventNameType_All, + eTransitionEventClass) EVENT(transitionend, eTransitionEnd, EventNameType_All, diff --git a/dom/webidl/EventHandler.webidl b/dom/webidl/EventHandler.webidl index 6a44414efc4e..d8f93bbed29c 100644 --- a/dom/webidl/EventHandler.webidl +++ b/dom/webidl/EventHandler.webidl @@ -132,6 +132,8 @@ interface GlobalEventHandlers { attribute EventHandler onanimationiteration; attribute EventHandler onanimationstart; attribute EventHandler ontransitionend; + attribute EventHandler ontransitionrun; + attribute EventHandler ontransitionstart; // CSS-Animation and CSS-Transition legacy handlers. // This handler isn't standard. diff --git a/widget/EventMessageList.h b/widget/EventMessageList.h index cef8e5c52ae0..f02e30c94cbb 100644 --- a/widget/EventMessageList.h +++ b/widget/EventMessageList.h @@ -334,6 +334,8 @@ NS_EVENT_MESSAGE(eGestureNotify) NS_EVENT_MESSAGE(eScrolledAreaChanged) // CSS Transition & Animation events: +NS_EVENT_MESSAGE(eTransitionStart) +NS_EVENT_MESSAGE(eTransitionRun) NS_EVENT_MESSAGE(eTransitionEnd) NS_EVENT_MESSAGE(eAnimationStart) NS_EVENT_MESSAGE(eAnimationEnd) From b4aef51ba4f0fee6ff4b5ab4f4c0f1e37566ea03 Mon Sep 17 00:00:00 2001 From: Mantaroh Yoshinaga Date: Wed, 19 Oct 2016 15:16:51 +0900 Subject: [PATCH 06/60] Bug 1287983 part 2 - Add transitionstart/transitionrun event handling. r=birtles The specification of CSS-Transition event is as follow: https://drafts.csswg.org/css-transitions-2/#transition-events MozReview-Commit-ID: CWgsRRLhnXp --HG-- extra : rebase_source : 5687d30293c1a5dd2c8dd52b1a77d2b2b3e171a4 --- layout/style/nsTransitionManager.cpp | 141 ++++++++++++++++++++++++--- layout/style/nsTransitionManager.h | 24 ++++- 2 files changed, 149 insertions(+), 16 deletions(-) diff --git a/layout/style/nsTransitionManager.cpp b/layout/style/nsTransitionManager.cpp index ded41b412796..5f94b64d1a58 100644 --- a/layout/style/nsTransitionManager.cpp +++ b/layout/style/nsTransitionManager.cpp @@ -46,6 +46,16 @@ using mozilla::dom::KeyframeEffectReadOnly; using namespace mozilla; using namespace mozilla::css; +typedef mozilla::ComputedTiming::AnimationPhase AnimationPhase; + +namespace { +struct TransitionEventParams { + EventMessage mMessage; + StickyTimeDuration mElapsedTime; + TimeStamp mTimeStamp; +}; +} // anonymous namespace + double ElementPropertyTransition::CurrentValuePortion() const { @@ -172,12 +182,8 @@ CSSTransition::UpdateTiming(SeekFlag aSeekFlag, SyncNotifyFlag aSyncNotifyFlag) void CSSTransition::QueueEvents() { - AnimationPlayState playState = PlayState(); - bool newlyFinished = !mWasFinishedOnLastTick && - playState == AnimationPlayState::Finished; - mWasFinishedOnLastTick = playState == AnimationPlayState::Finished; - - if (!newlyFinished || !mEffect || !mOwningElement.IsSet()) { + if (!mEffect || + !mOwningElement.IsSet()) { return; } @@ -191,13 +197,124 @@ CSSTransition::QueueEvents() return; } + ComputedTiming computedTiming = mEffect->GetComputedTiming(); + const StickyTimeDuration zeroDuration; + StickyTimeDuration intervalStartTime = + std::max(std::min(StickyTimeDuration(-mEffect->SpecifiedTiming().mDelay), + computedTiming.mActiveDuration), zeroDuration); + StickyTimeDuration intervalEndTime = + std::max(std::min((EffectEnd() - mEffect->SpecifiedTiming().mDelay), + computedTiming.mActiveDuration), zeroDuration); + + // TimeStamps to use for ordering the events when they are dispatched. We + // use a TimeStamp so we can compare events produced by different elements, + // perhaps even with different timelines. + // The zero timestamp is for transitionrun events where we ignore the delay + // for the purpose of ordering events. + TimeStamp zeroTimeStamp = AnimationTimeToTimeStamp(zeroDuration); + TimeStamp startTimeStamp = ElapsedTimeToTimeStamp(intervalStartTime); + TimeStamp endTimeStamp = ElapsedTimeToTimeStamp(intervalEndTime); + + TransitionPhase currentPhase; + if (mPendingState != PendingState::NotPending && + (mPreviousTransitionPhase == TransitionPhase::Idle || + mPreviousTransitionPhase == TransitionPhase::Pending)) + { + currentPhase = TransitionPhase::Pending; + } else { + currentPhase = static_cast(computedTiming.mPhase); + } + + AutoTArray events; + switch (mPreviousTransitionPhase) { + case TransitionPhase::Idle: + if (currentPhase == TransitionPhase::Pending || + currentPhase == TransitionPhase::Before) { + events.AppendElement(TransitionEventParams{ eTransitionRun, + intervalStartTime, + zeroTimeStamp }); + } else if (currentPhase == TransitionPhase::Active) { + events.AppendElement(TransitionEventParams{ eTransitionRun, + intervalStartTime, + zeroTimeStamp }); + events.AppendElement(TransitionEventParams{ eTransitionStart, + intervalStartTime, + startTimeStamp }); + } else if (currentPhase == TransitionPhase::After) { + events.AppendElement(TransitionEventParams{ eTransitionRun, + intervalStartTime, + zeroTimeStamp }); + events.AppendElement(TransitionEventParams{ eTransitionStart, + intervalStartTime, + startTimeStamp }); + events.AppendElement(TransitionEventParams{ eTransitionEnd, + intervalEndTime, + endTimeStamp }); + } + break; + + case TransitionPhase::Pending: + case TransitionPhase::Before: + if (currentPhase == TransitionPhase::Active) { + events.AppendElement(TransitionEventParams{ eTransitionStart, + intervalStartTime, + startTimeStamp }); + } else if (currentPhase == TransitionPhase::After) { + events.AppendElement(TransitionEventParams{ eTransitionStart, + intervalStartTime, + startTimeStamp }); + events.AppendElement(TransitionEventParams{ eTransitionEnd, + intervalEndTime, + endTimeStamp }); + } + break; + + case TransitionPhase::Active: + if (currentPhase == TransitionPhase::After) { + events.AppendElement(TransitionEventParams{ eTransitionEnd, + intervalEndTime, + endTimeStamp }); + } else if (currentPhase == TransitionPhase::Before) { + events.AppendElement(TransitionEventParams{ eTransitionEnd, + intervalStartTime, + startTimeStamp }); + } + break; + + case TransitionPhase::After: + if (currentPhase == TransitionPhase::Active) { + events.AppendElement(TransitionEventParams{ eTransitionStart, + intervalEndTime, + startTimeStamp }); + } else if (currentPhase == TransitionPhase::Before) { + events.AppendElement(TransitionEventParams{ eTransitionStart, + intervalEndTime, + startTimeStamp }); + events.AppendElement(TransitionEventParams{ eTransitionEnd, + intervalStartTime, + endTimeStamp }); + } + break; + } + mPreviousTransitionPhase = currentPhase; + nsTransitionManager* manager = presContext->TransitionManager(); - manager->QueueEvent(TransitionEventInfo(owningElement, owningPseudoType, - TransitionProperty(), - mEffect->GetComputedTiming() - .mDuration, - AnimationTimeToTimeStamp(EffectEnd()), - this)); + for (const TransitionEventParams& evt : events) { + manager->QueueEvent(TransitionEventInfo(owningElement, owningPseudoType, + evt.mMessage, + TransitionProperty(), + evt.mElapsedTime, + evt.mTimeStamp, + this)); + } +} + +TimeStamp +CSSTransition::ElapsedTimeToTimeStamp( + const StickyTimeDuration& aElapsedTime) const +{ + return AnimationTimeToTimeStamp(aElapsedTime + + mEffect->SpecifiedTiming().mDelay); } void diff --git a/layout/style/nsTransitionManager.h b/layout/style/nsTransitionManager.h index aa82daddc4c6..9a61dafa0865 100644 --- a/layout/style/nsTransitionManager.h +++ b/layout/style/nsTransitionManager.h @@ -8,6 +8,7 @@ #ifndef nsTransitionManager_h_ #define nsTransitionManager_h_ +#include "mozilla/ComputedTiming.h" #include "mozilla/ContentEvents.h" #include "mozilla/EffectCompositor.h" // For EffectCompositor::CascadeLevel #include "mozilla/MemoryReporting.h" @@ -119,7 +120,7 @@ class CSSTransition final : public Animation public: explicit CSSTransition(nsIGlobalObject* aGlobal) : dom::Animation(aGlobal) - , mWasFinishedOnLastTick(false) + , mPreviousTransitionPhase(TransitionPhase::Idle) , mNeedsNewAnimationIndexWhenRun(false) , mTransitionProperty(eCSSProperty_UNKNOWN) { @@ -226,6 +227,10 @@ protected: void QueueEvents(); + // Converts an TransitionEvent's elapsedTime value to an equivalent TimeStamp + // that can be used to sort events by when they occurred. + TimeStamp ElapsedTimeToTimeStamp(const StickyTimeDuration& aElapsedTime) const; + // The (pseudo-)element whose computed transition-property refers to this // transition (if any). // @@ -245,7 +250,17 @@ protected: // For (b) and (c) the owning element will return !IsSet(). OwningElementRef mOwningElement; - bool mWasFinishedOnLastTick; + // The 'transition phase' used to determine which transition events need + // to be queued on this tick. + // See: https://drafts.csswg.org/css-transitions-2/#transition-phase + enum class TransitionPhase { + Idle = static_cast(ComputedTiming::AnimationPhase::Null), + Before = static_cast(ComputedTiming::AnimationPhase::Before), + Active = static_cast(ComputedTiming::AnimationPhase::Active), + After = static_cast(ComputedTiming::AnimationPhase::After), + Pending + }; + TransitionPhase mPreviousTransitionPhase; // When true, indicates that when this transition next leaves the idle state, // its animation index should be updated. @@ -287,13 +302,14 @@ struct TransitionEventInfo { TransitionEventInfo(dom::Element* aElement, CSSPseudoElementType aPseudoType, + EventMessage aMessage, nsCSSPropertyID aProperty, StickyTimeDuration aDuration, const TimeStamp& aTimeStamp, dom::Animation* aAnimation) : mElement(aElement) , mAnimation(aAnimation) - , mEvent(true, eTransitionEnd) + , mEvent(true, aMessage) , mTimeStamp(aTimeStamp) { // XXX Looks like nobody initialize WidgetEvent::time @@ -309,7 +325,7 @@ struct TransitionEventInfo { TransitionEventInfo(const TransitionEventInfo& aOther) : mElement(aOther.mElement) , mAnimation(aOther.mAnimation) - , mEvent(true, eTransitionEnd) + , mEvent(aOther.mEvent) , mTimeStamp(aOther.mTimeStamp) { mEvent.AssignTransitionEventData(aOther.mEvent, false); From 7cf9216ef7a1e545410ec71faa9c8d5a549e20a7 Mon Sep 17 00:00:00 2001 From: Mantaroh Yoshinaga Date: Wed, 19 Oct 2016 15:16:52 +0900 Subject: [PATCH 07/60] Bug 1287983 part 3 - Add transitionstart/transitionrun test. r=birtles Specification is as follow. https://drafts.csswg.org/css-transitions-2/#eventdef-transitionevent-transitionstart MozReview-Commit-ID: 1RXlhrQzdko --HG-- extra : rebase_source : 93f3f0cc59a6570cd5001337e10c7b38aec90a77 --- ...st_animations_event_handler_attribute.html | 13 ++- .../test/test_animations_event_order.html | 102 +++++++++++++++--- 2 files changed, 97 insertions(+), 18 deletions(-) diff --git a/layout/style/test/test_animations_event_handler_attribute.html b/layout/style/test/test_animations_event_handler_attribute.html index 80159324d48e..23a749daa89f 100644 --- a/layout/style/test/test_animations_event_handler_attribute.html +++ b/layout/style/test/test_animations_event_handler_attribute.html @@ -90,15 +90,22 @@ targets.forEach(div => { div.remove(); }); // 2. Test CSS Transition event handlers. -advance_clock(0); -var targets = createAndRegisterTargets([ 'ontransitionend' ]); +var targets = createAndRegisterTargets([ 'ontransitionrun', + 'ontransitionstart', + 'ontransitionend' ]); targets.forEach(div => { - div.style.transition = 'margin-left 100ms'; + div.style.transition = 'margin-left 100ms 200ms'; getComputedStyle(div).marginLeft; // flush div.style.marginLeft = "200px"; getComputedStyle(div).marginLeft; // flush }); +advance_clock(0); +checkReceivedEvents("transitionrun", targets); + +advance_clock(200); +checkReceivedEvents("transitionstart", targets); + advance_clock(100); checkReceivedEvents("transitionend", targets); diff --git a/layout/style/test/test_animations_event_order.html b/layout/style/test/test_animations_event_order.html index 24a3d3d845eb..f948bf0a5bfb 100644 --- a/layout/style/test/test_animations_event_order.html +++ b/layout/style/test/test_animations_event_order.html @@ -46,6 +46,8 @@ var gDisplay = document.getElementById('display'); [ 'animationstart', 'animationiteration', 'animationend', + 'transitionrun', + 'transitionstart', 'transitionend' ] .forEach(event => gDisplay.addEventListener(event, @@ -322,9 +324,13 @@ getComputedStyle(divs[0]).marginLeft; advance_clock(0); advance_clock(10000); -checkEventOrder([ divs[0], 'transitionend' ], +checkEventOrder([ divs[0], 'transitionrun' ], + [ divs[0], 'transitionstart' ], + [ divs[1], 'transitionrun' ], + [ divs[1], 'transitionstart' ], + [ divs[0], 'transitionend' ], [ divs[1], 'transitionend' ], - 'Simultaneous transitionend on siblings'); + 'Simultaneous transitionrun/start/end on siblings'); divs.forEach(div => div.remove()); divs = []; @@ -360,10 +366,16 @@ getComputedStyle(divs[0]).marginLeft; advance_clock(0); advance_clock(10000); -checkEventOrder([ divs[0], 'transitionend' ], +checkEventOrder([ divs[0], 'transitionrun' ], + [ divs[0], 'transitionstart' ], + [ divs[2], 'transitionrun' ], + [ divs[2], 'transitionstart' ], + [ divs[1], 'transitionrun' ], + [ divs[1], 'transitionstart' ], + [ divs[0], 'transitionend' ], [ divs[2], 'transitionend' ], [ divs[1], 'transitionend' ], - 'Simultaneous transitionend on children'); + 'Simultaneous transitionrun/start/end on children'); divs.forEach(div => div.remove()); divs = []; @@ -408,11 +420,19 @@ getComputedStyle(divs[0]).marginLeft; advance_clock(0); advance_clock(10000); -checkEventOrder([ divs[0], 'transitionend' ], +checkEventOrder([ divs[0], 'transitionrun' ], + [ divs[0], 'transitionstart' ], + [ divs[0], '::before', 'transitionrun' ], + [ divs[0], '::before', 'transitionstart' ], + [ divs[0], '::after', 'transitionrun' ], + [ divs[0], '::after', 'transitionstart' ], + [ divs[1], 'transitionrun' ], + [ divs[1], 'transitionstart' ], + [ divs[0], 'transitionend' ], [ divs[0], '::before', 'transitionend' ], [ divs[0], '::after', 'transitionend' ], [ divs[1], 'transitionend' ], - 'Simultaneous transitionend on pseudo-elements'); + 'Simultaneous transitionrun/start/end on pseudo-elements'); divs.forEach(div => div.remove()); divs = []; @@ -441,9 +461,13 @@ getComputedStyle(divs[0]).marginLeft; advance_clock(0); advance_clock(10000); -checkEventOrder([ divs[1], 'transitionend' ], +checkEventOrder([ divs[0], 'transitionrun' ], + [ divs[0], 'transitionstart' ], + [ divs[1], 'transitionrun' ], + [ divs[1], 'transitionstart' ], + [ divs[1], 'transitionend' ], [ divs[0], 'transitionend' ], - 'Sorting of transitionend events by time'); + 'Sorting of transitionrun/start/end events by time'); divs.forEach(div => div.remove()); divs = []; @@ -466,11 +490,16 @@ divs.forEach(div => div.style.marginLeft = '100px'); getComputedStyle(divs[0]).marginLeft; advance_clock(0); -advance_clock(10000); +advance_clock(10 * 1000); -checkEventOrder([ divs[1], 'transitionend' ], +checkEventOrder([ divs[0], 'transitionrun' ], + [ divs[1], 'transitionrun' ], + [ divs[1], 'transitionstart' ], + [ divs[0], 'transitionstart' ], + [ divs[1], 'transitionend' ], [ divs[0], 'transitionend' ], - 'Sorting of transitionend events by time (including delay)'); + 'Sorting of transitionrun/start/end events by time' + + '(including delay)'); divs.forEach(div => div.remove()); divs = []; @@ -491,9 +520,14 @@ getComputedStyle(div).marginLeft; advance_clock(0); advance_clock(10000); -checkEventOrder([ 'margin-left', 'transitionend' ], +checkEventOrder([ 'margin-left', 'transitionrun' ], + [ 'margin-left', 'transitionstart' ], + [ 'opacity', 'transitionrun' ], + [ 'opacity', 'transitionstart' ], + [ 'margin-left', 'transitionend' ], [ 'opacity', 'transitionend' ], - 'Sorting of transitionend events by transition-property'); + 'Sorting of transitionrun/start/end events by ' + + 'transition-property') div.remove(); div = undefined; @@ -518,7 +552,11 @@ getComputedStyle(divs[0]).marginLeft; advance_clock(0); advance_clock(10000); -checkEventOrder([ divs[0], 'transitionend' ], +checkEventOrder([ divs[0], 'transitionrun' ], + [ divs[0], 'transitionstart' ], + [ divs[1], 'transitionrun' ], + [ divs[1], 'transitionstart' ], + [ divs[0], 'transitionend' ], [ divs[1], 'transitionend' ], 'Transition events are sorted by document position first, ' + 'before transition-property'); @@ -542,7 +580,11 @@ getComputedStyle(div).marginLeft; advance_clock(0); advance_clock(10000); -checkEventOrder([ 'opacity', 'transitionend' ], +checkEventOrder([ 'margin-left', 'transitionrun' ], + [ 'margin-left', 'transitionstart' ], + [ 'opacity', 'transitionrun' ], + [ 'opacity', 'transitionstart' ], + [ 'opacity', 'transitionend' ], [ 'margin-left', 'transitionend' ], 'Transition events are sorted by time first, before ' + 'transition-property'); @@ -550,6 +592,36 @@ checkEventOrder([ 'opacity', 'transitionend' ], div.remove(); div = undefined; +// 4i. Test sorting transitions by document position (negative delay) + +divs = [ document.createElement('div'), + document.createElement('div') ]; +divs.forEach((div, i) => { + gDisplay.appendChild(div); + div.style.marginLeft = '0px'; + div.setAttribute('id', 'div' + i); +}); + +divs[0].style.transition = 'margin-left 10s 5s'; +divs[1].style.transition = 'margin-left 10s'; + +getComputedStyle(divs[0]).marginLeft; +divs.forEach(div => div.style.marginLeft = '100px'); +getComputedStyle(divs[0]).marginLeft; + +advance_clock(0); +advance_clock(15 * 1000); + +checkEventOrder([ divs[0], 'transitionrun' ], + [ divs[1], 'transitionrun' ], + [ divs[1], 'transitionstart' ], + [ divs[0], 'transitionstart' ], + [ divs[1], 'transitionend' ], + [ divs[0], 'transitionend' ], + 'Simultaneous transitionrun/start/end on siblings'); + +divs.forEach(div => div.remove()); +divs = []; SpecialPowers.DOMWindowUtils.restoreNormalRefresh(); From f48cb567a69d6b4e8749465e54c3787af2a338b3 Mon Sep 17 00:00:00 2001 From: Mantaroh Yoshinaga Date: Wed, 19 Oct 2016 15:16:52 +0900 Subject: [PATCH 08/60] Bug 1287983 part 4 - Add transition event handler test for checking elapsed time. r=birtles MozReview-Commit-ID: KwtsVbII95v --HG-- extra : rebase_source : 5204130473f452d2bca028f34ca2d4199aa18206 --- .../file_csstransition-events.html | 182 ++++++++++++++++++ .../test_csstransition-events.html | 14 ++ dom/animation/test/mochitest.ini | 2 + 3 files changed, 198 insertions(+) create mode 100644 dom/animation/test/css-transitions/file_csstransition-events.html create mode 100644 dom/animation/test/css-transitions/test_csstransition-events.html diff --git a/dom/animation/test/css-transitions/file_csstransition-events.html b/dom/animation/test/css-transitions/file_csstransition-events.html new file mode 100644 index 000000000000..4e71b4e88a9a --- /dev/null +++ b/dom/animation/test/css-transitions/file_csstransition-events.html @@ -0,0 +1,182 @@ + + +Tests for CSS-Transition events + + + + + + diff --git a/dom/animation/test/css-transitions/test_csstransition-events.html b/dom/animation/test/css-transitions/test_csstransition-events.html new file mode 100644 index 000000000000..92559ad67912 --- /dev/null +++ b/dom/animation/test/css-transitions/test_csstransition-events.html @@ -0,0 +1,14 @@ + + + + +
+ diff --git a/dom/animation/test/mochitest.ini b/dom/animation/test/mochitest.ini index 1e3c9f60c187..7728ecfd3a66 100644 --- a/dom/animation/test/mochitest.ini +++ b/dom/animation/test/mochitest.ini @@ -28,6 +28,7 @@ support-files = css-transitions/file_animation-pausing.html css-transitions/file_animation-ready.html css-transitions/file_animation-starttime.html + css-transitions/file_csstransition-events.html css-transitions/file_csstransition-transitionproperty.html css-transitions/file_document-get-animations.html css-transitions/file_effect-target.html @@ -80,6 +81,7 @@ skip-if = buildapp == 'mulet' [css-transitions/test_animation-pausing.html] [css-transitions/test_animation-ready.html] [css-transitions/test_animation-starttime.html] +[css-transitions/test_csstransition-events.html] [css-transitions/test_csstransition-transitionproperty.html] [css-transitions/test_document-get-animations.html] [css-transitions/test_effect-target.html] From ed9cb5c860a4f3890150101ad7f5ad227ac08efb Mon Sep 17 00:00:00 2001 From: Mantaroh Yoshinaga Date: Wed, 19 Oct 2016 15:16:52 +0900 Subject: [PATCH 09/60] Bug 1287983 part 5 - Clarify the function name of creating transition. r=hiro MozReview-Commit-ID: AW5qD8uBQxf --HG-- extra : rebase_source : 5cc8b81bec1db0b40b420bc539f03f6307879cb0 --- layout/base/RestyleManager.cpp | 26 ++++++++++--------- layout/base/RestyleManager.h | 10 +++---- layout/base/nsCSSFrameConstructor.cpp | 12 ++++----- layout/generic/nsFrame.cpp | 2 +- layout/style/nsStyleSet.cpp | 2 +- layout/style/nsTransitionManager.cpp | 23 ++++++++-------- layout/style/nsTransitionManager.h | 18 ++++++------- layout/style/test/test_transitions.html | 2 +- .../test/test_transitions_and_reframes.html | 2 +- .../test/test_transitions_and_restyles.html | 2 +- 10 files changed, 51 insertions(+), 48 deletions(-) diff --git a/layout/base/RestyleManager.cpp b/layout/base/RestyleManager.cpp index 8e5936c979cb..c9e1ede3c8d4 100644 --- a/layout/base/RestyleManager.cpp +++ b/layout/base/RestyleManager.cpp @@ -185,7 +185,7 @@ RestyleManager::ReframingStyleContexts::ReframingStyleContexts( RestyleManager::ReframingStyleContexts::~ReframingStyleContexts() { // Before we go away, we need to flush out any frame construction that - // was enqueued, so that we start transitions. + // was enqueued, so that we initiate transitions. // Note that this is a little bit evil in that we're calling into code // that calls our member functions from our destructor, but it's at // the beginning of our destructor, so it shouldn't be too bad. @@ -990,11 +990,11 @@ RestyleManager::PostRebuildAllStyleDataEvent(nsChangeHint aExtraHint, // aContent must be the content for the frame in question, which may be // :before/:after content /* static */ bool -RestyleManager::TryStartingTransition(nsPresContext* aPresContext, - nsIContent* aContent, - nsStyleContext* aOldStyleContext, - RefPtr* - aNewStyleContext /* inout */) +RestyleManager::TryInitiatingTransition(nsPresContext* aPresContext, + nsIContent* aContent, + nsStyleContext* aOldStyleContext, + RefPtr* + aNewStyleContext /* inout */) { if (!aContent || !aContent->IsElement()) { return false; @@ -1257,11 +1257,11 @@ RestyleManager::ReparentStyleContext(nsIFrame* aFrame) // ReparentStyleContext, since we call it during frame // construction rather than in response to dynamic changes. // Also see the comment at the start of - // nsTransitionManager::ConsiderStartingTransition. + // nsTransitionManager::ConsiderInitiatingTransition. #if 0 if (!copyFromContinuation) { - TryStartingTransition(mPresContext, aFrame->GetContent(), - oldContext, &newContext); + TryInitiatingTransition(mPresContext, aFrame->GetContent(), + oldContext, &newContext); } #endif @@ -2964,10 +2964,12 @@ ElementRestyler::RestyleSelf(nsIFrame* aSelf, } } else { bool changedStyle = - RestyleManager::TryStartingTransition(mPresContext, aSelf->GetContent(), - oldContext, &newContext); + RestyleManager::TryInitiatingTransition(mPresContext, + aSelf->GetContent(), + oldContext, &newContext); if (changedStyle) { - LOG_RESTYLE_CONTINUE("TryStartingTransition changed the new style context"); + LOG_RESTYLE_CONTINUE("TryInitiatingTransition changed the new style " + "context"); result = RestyleResult::eContinue; canStopWithStyleChange = false; } diff --git a/layout/base/RestyleManager.h b/layout/base/RestyleManager.h index e495b823358d..e22fe9058110 100644 --- a/layout/base/RestyleManager.h +++ b/layout/base/RestyleManager.h @@ -208,18 +208,18 @@ public: } /** - * Try starting a transition for an element or a ::before or ::after + * Try initiating a transition for an element or a ::before or ::after * pseudo-element, given an old and new style context. This may * change the new style context if a transition is started. Returns - * true iff it does change aNewStyleContext. + * true if it does change aNewStyleContext. * * For the pseudo-elements, aContent must be the anonymous content * that we're creating for that pseudo-element, not the real element. */ static bool - TryStartingTransition(nsPresContext* aPresContext, nsIContent* aContent, - nsStyleContext* aOldStyleContext, - RefPtr* aNewStyleContext /* inout */); + TryInitiatingTransition(nsPresContext* aPresContext, nsIContent* aContent, + nsStyleContext* aOldStyleContext, + RefPtr* aNewStyleContext /* inout */); // AnimationsWithDestroyedFrame is used to stop animations and transitions // on elements that have no frame at the end of the restyling process. diff --git a/layout/base/nsCSSFrameConstructor.cpp b/layout/base/nsCSSFrameConstructor.cpp index da8a5b1c230c..d09e562c69dc 100644 --- a/layout/base/nsCSSFrameConstructor.cpp +++ b/layout/base/nsCSSFrameConstructor.cpp @@ -1874,10 +1874,10 @@ nsCSSFrameConstructor::CreateGeneratedContentItem(nsFrameConstructorState& aStat if (rsc) { nsStyleContext* oldStyleContext = rsc->Get(container, aPseudoElement); if (oldStyleContext) { - RestyleManager::TryStartingTransition(aState.mPresContext, - container, - oldStyleContext, - &pseudoStyleContext); + RestyleManager::TryInitiatingTransition(aState.mPresContext, + container, + oldStyleContext, + &pseudoStyleContext); } else { aState.mPresContext->TransitionManager()-> PruneCompletedTransitions(container, aPseudoElement, @@ -5049,8 +5049,8 @@ nsCSSFrameConstructor::ResolveStyleContext(nsStyleContext* aParentStyleContext, rsc->Get(aContent, CSSPseudoElementType::NotPseudo); nsPresContext* presContext = mPresShell->GetPresContext(); if (oldStyleContext) { - RestyleManager::TryStartingTransition(presContext, aContent, - oldStyleContext, &result); + RestyleManager::TryInitiatingTransition(presContext, aContent, + oldStyleContext, &result); } else if (aContent->IsElement()) { presContext->TransitionManager()-> PruneCompletedTransitions(aContent->AsElement(), diff --git a/layout/generic/nsFrame.cpp b/layout/generic/nsFrame.cpp index d0666d91db42..fb0e957837b9 100644 --- a/layout/generic/nsFrame.cpp +++ b/layout/generic/nsFrame.cpp @@ -685,7 +685,7 @@ nsFrame::DestroyFrom(nsIFrame* aDestructRoot) if (presContext->RestyleManager()->IsGecko()) { // stylo: ServoRestyleManager does not handle transitions yet, and when // it does it probably won't need to track reframed style contexts to - // start transitions correctly. + // initiate transitions correctly. RestyleManager::ReframingStyleContexts* rsc = presContext->RestyleManager()->AsGecko()->GetReframingStyleContexts(); if (rsc) { diff --git a/layout/style/nsStyleSet.cpp b/layout/style/nsStyleSet.cpp index 8189427c7381..414eee4d43be 100644 --- a/layout/style/nsStyleSet.cpp +++ b/layout/style/nsStyleSet.cpp @@ -2231,7 +2231,7 @@ nsStyleSet::ReparentStyleContext(nsStyleContext* aStyleContext, { MOZ_ASSERT(aStyleContext, "aStyleContext must not be null"); - // This short-circuit is OK because we don't call TryStartingTransition + // This short-circuit is OK because we don't call TryInitatingTransition // during style reresolution if the style context pointer hasn't changed. if (aStyleContext->GetParent() == aNewParentContext) { RefPtr ret = aStyleContext; diff --git a/layout/style/nsTransitionManager.cpp b/layout/style/nsTransitionManager.cpp index 5f94b64d1a58..4991fcca9d3d 100644 --- a/layout/style/nsTransitionManager.cpp +++ b/layout/style/nsTransitionManager.cpp @@ -459,7 +459,7 @@ nsTransitionManager::StyleContextChanged(dom::Element *aElement, return; } - // NOTE: Things in this function (and ConsiderStartingTransition) + // NOTE: Things in this function (and ConsiderInitiatingTransition) // should never call PeekStyleData because we don't preserve gotten // structs across reframes. @@ -609,22 +609,23 @@ nsTransitionManager::UpdateTransitions( for (nsCSSPropertyID p = nsCSSPropertyID(0); p < eCSSProperty_COUNT_no_shorthands; p = nsCSSPropertyID(p + 1)) { - ConsiderStartingTransition(p, t, aElement, aElementTransitions, - aOldStyleContext, aNewStyleContext, - &startedAny, &whichStarted); + ConsiderInitiatingTransition(p, t, aElement, aElementTransitions, + aOldStyleContext, aNewStyleContext, + &startedAny, &whichStarted); } } else if (nsCSSProps::IsShorthand(property)) { CSSPROPS_FOR_SHORTHAND_SUBPROPERTIES(subprop, property, CSSEnabledState::eForAllContent) { - ConsiderStartingTransition(*subprop, t, aElement, aElementTransitions, - aOldStyleContext, aNewStyleContext, - &startedAny, &whichStarted); + ConsiderInitiatingTransition(*subprop, t, aElement, + aElementTransitions, + aOldStyleContext, aNewStyleContext, + &startedAny, &whichStarted); } } else { - ConsiderStartingTransition(property, t, aElement, aElementTransitions, - aOldStyleContext, aNewStyleContext, - &startedAny, &whichStarted); + ConsiderInitiatingTransition(property, t, aElement, aElementTransitions, + aOldStyleContext, aNewStyleContext, + &startedAny, &whichStarted); } } } @@ -711,7 +712,7 @@ nsTransitionManager::UpdateTransitions( } void -nsTransitionManager::ConsiderStartingTransition( +nsTransitionManager::ConsiderInitiatingTransition( nsCSSPropertyID aProperty, const StyleTransition& aTransition, dom::Element* aElement, diff --git a/layout/style/nsTransitionManager.h b/layout/style/nsTransitionManager.h index 9a61dafa0865..f17ab6741489 100644 --- a/layout/style/nsTransitionManager.h +++ b/layout/style/nsTransitionManager.h @@ -353,7 +353,7 @@ public: /** * StyleContextChanged * - * To be called from RestyleManager::TryStartingTransition when the + * To be called from RestyleManager::TryInitiatingTransition when the * style of an element has changed, to initiate transitions from * that style change. For style contexts with :before and :after * pseudos, aElement is expected to be the generated before/after @@ -426,14 +426,14 @@ protected: nsStyleContext* aNewStyleContext); void - ConsiderStartingTransition(nsCSSPropertyID aProperty, - const mozilla::StyleTransition& aTransition, - mozilla::dom::Element* aElement, - CSSTransitionCollection*& aElementTransitions, - nsStyleContext* aOldStyleContext, - nsStyleContext* aNewStyleContext, - bool* aStartedAny, - nsCSSPropertyIDSet* aWhichStarted); + ConsiderInitiatingTransition(nsCSSPropertyID aProperty, + const mozilla::StyleTransition& aTransition, + mozilla::dom::Element* aElement, + CSSTransitionCollection*& aElementTransitions, + nsStyleContext* aOldStyleContext, + nsStyleContext* aNewStyleContext, + bool* aStartedAny, + nsCSSPropertyIDSet* aWhichStarted); nsTArray GetTransitionKeyframes( nsStyleContext* aStyleContext, diff --git a/layout/style/test/test_transitions.html b/layout/style/test/test_transitions.html index 36a3228a0c7c..e36d53418303 100644 --- a/layout/style/test/test_transitions.html +++ b/layout/style/test/test_transitions.html @@ -118,7 +118,7 @@ var timingFunctions = { var div = document.getElementById("display"); -// Set up all the elements on which we are going to start transitions. +// Set up all the elements on which we are going to initiate transitions. // We have two reference elements to check the expected timing range. // They both have 8s linear transitions from 0 to 1000px. diff --git a/layout/style/test/test_transitions_and_reframes.html b/layout/style/test/test_transitions_and_reframes.html index 833919f0c892..b4213dbdddb1 100644 --- a/layout/style/test/test_transitions_and_reframes.html +++ b/layout/style/test/test_transitions_and_reframes.html @@ -187,7 +187,7 @@ var tests = [ dynamic_change_transition:true, start_from_none:false }, // Recheck starting from display:none. Note that these tests all fail, // although we could get *some* of them to pass by calling - // RestyleManager::TryStartingTransition from + // RestyleManager::TryInitiatingTransition from // ElementRestyler::RestyleUndisplayedChildren. { element:"e1", test_child:false, pseudo:"", passes:false, dynamic_change_transition:false, start_from_none:true }, diff --git a/layout/style/test/test_transitions_and_restyles.html b/layout/style/test/test_transitions_and_restyles.html index 80f54370cb6e..68085a712884 100644 --- a/layout/style/test/test_transitions_and_restyles.html +++ b/layout/style/test/test_transitions_and_restyles.html @@ -32,7 +32,7 @@ var p = document.getElementById("display"); var cs = getComputedStyle(p, ""); advance_clock(0); cs.width; // flush -p.style.width = "1000px"; // start transition +p.style.width = "1000px"; // initiate transition is(cs.width, "0px", "transition at 0ms"); // flush (and test) advance_clock(100); is(cs.width, "100px", "transition at 100ms"); // flush From cf59836baef935bbc624c6b90d9e0b7ef18247de Mon Sep 17 00:00:00 2001 From: Mantaroh Yoshinaga Date: Wed, 19 Oct 2016 15:16:52 +0900 Subject: [PATCH 10/60] Bug 1287983 part 6 - Integrate ElapsedTimeToTimeStamp function to the Animation class. r=birtles MozReview-Commit-ID: 43AGaTYQoqn --HG-- extra : rebase_source : 728380db2c6f3e035d05b6c746d2c0f08a1369b7 --- dom/animation/Animation.cpp | 9 +++++++++ dom/animation/Animation.h | 4 ++++ layout/style/nsAnimationManager.cpp | 8 -------- layout/style/nsAnimationManager.h | 4 ---- layout/style/nsTransitionManager.cpp | 8 -------- layout/style/nsTransitionManager.h | 4 ---- 6 files changed, 13 insertions(+), 24 deletions(-) diff --git a/dom/animation/Animation.cpp b/dom/animation/Animation.cpp index ebe9addb21b8..6dd583ed1e94 100644 --- a/dom/animation/Animation.cpp +++ b/dom/animation/Animation.cpp @@ -718,6 +718,15 @@ Animation::AnimationTimeToTimeStamp(const StickyTimeDuration& aTime) const return result; } +TimeStamp +Animation::ElapsedTimeToTimeStamp( + const StickyTimeDuration& aElapsedTime) const +{ + return AnimationTimeToTimeStamp(aElapsedTime + + mEffect->SpecifiedTiming().mDelay); +} + + // https://w3c.github.io/web-animations/#silently-set-the-current-time void Animation::SilentlySetCurrentTime(const TimeDuration& aSeekTime) diff --git a/dom/animation/Animation.h b/dom/animation/Animation.h index a3e4252c3587..c59d7d6ce03b 100644 --- a/dom/animation/Animation.h +++ b/dom/animation/Animation.h @@ -255,6 +255,10 @@ public: */ TimeStamp AnimationTimeToTimeStamp(const StickyTimeDuration& aTime) const; + // Converts an AnimationEvent's elapsedTime value to an equivalent TimeStamp + // that can be used to sort events by when they occurred. + TimeStamp ElapsedTimeToTimeStamp(const StickyTimeDuration& aElapsedTime) const; + bool IsPausedOrPausing() const { return PlayState() == AnimationPlayState::Paused || diff --git a/layout/style/nsAnimationManager.cpp b/layout/style/nsAnimationManager.cpp index ce9082f5a3c2..ed2b5afc7f9f 100644 --- a/layout/style/nsAnimationManager.cpp +++ b/layout/style/nsAnimationManager.cpp @@ -281,14 +281,6 @@ CSSAnimation::UpdateTiming(SeekFlag aSeekFlag, SyncNotifyFlag aSyncNotifyFlag) Animation::UpdateTiming(aSeekFlag, aSyncNotifyFlag); } -TimeStamp -CSSAnimation::ElapsedTimeToTimeStamp(const StickyTimeDuration& - aElapsedTime) const -{ - return AnimationTimeToTimeStamp(aElapsedTime + - mEffect->SpecifiedTiming().mDelay); -} - ////////////////////////// nsAnimationManager //////////////////////////// NS_IMPL_CYCLE_COLLECTION(nsAnimationManager, mEventDispatcher) diff --git a/layout/style/nsAnimationManager.h b/layout/style/nsAnimationManager.h index 8eddf9d52109..abe3aeeb8819 100644 --- a/layout/style/nsAnimationManager.h +++ b/layout/style/nsAnimationManager.h @@ -178,10 +178,6 @@ protected: std::max(TimeDuration(), mEffect->SpecifiedTiming().mDelay * -1) : TimeDuration(); } - // Converts an AnimationEvent's elapsedTime value to an equivalent TimeStamp - // that can be used to sort events by when they occurred. - TimeStamp ElapsedTimeToTimeStamp(const StickyTimeDuration& aElapsedTime) - const; nsString mAnimationName; diff --git a/layout/style/nsTransitionManager.cpp b/layout/style/nsTransitionManager.cpp index 4991fcca9d3d..d40e26a82e5a 100644 --- a/layout/style/nsTransitionManager.cpp +++ b/layout/style/nsTransitionManager.cpp @@ -309,14 +309,6 @@ CSSTransition::QueueEvents() } } -TimeStamp -CSSTransition::ElapsedTimeToTimeStamp( - const StickyTimeDuration& aElapsedTime) const -{ - return AnimationTimeToTimeStamp(aElapsedTime + - mEffect->SpecifiedTiming().mDelay); -} - void CSSTransition::Tick() { diff --git a/layout/style/nsTransitionManager.h b/layout/style/nsTransitionManager.h index f17ab6741489..56ec61572b26 100644 --- a/layout/style/nsTransitionManager.h +++ b/layout/style/nsTransitionManager.h @@ -227,10 +227,6 @@ protected: void QueueEvents(); - // Converts an TransitionEvent's elapsedTime value to an equivalent TimeStamp - // that can be used to sort events by when they occurred. - TimeStamp ElapsedTimeToTimeStamp(const StickyTimeDuration& aElapsedTime) const; - // The (pseudo-)element whose computed transition-property refers to this // transition (if any). // From e04fc55c0926cc0dea4e1fb0f443edb54ec6606f Mon Sep 17 00:00:00 2001 From: Mantaroh Yoshinaga Date: Fri, 21 Oct 2016 11:37:53 +0900 Subject: [PATCH 11/60] Bug 1287983 part 7 - Add negative delay tests for CSS-Transitions event. r=birtles MozReview-Commit-ID: KOVljOtRqFt --HG-- extra : rebase_source : 324e0075339a99e7abadb82f3033ec7e4e7175e8 --- .../file_csstransition-events.html | 45 ++++++++++++++++++- 1 file changed, 43 insertions(+), 2 deletions(-) diff --git a/dom/animation/test/css-transitions/file_csstransition-events.html b/dom/animation/test/css-transitions/file_csstransition-events.html index 4e71b4e88a9a..5011bc1309bd 100644 --- a/dom/animation/test/css-transitions/file_csstransition-events.html +++ b/dom/animation/test/css-transitions/file_csstransition-events.html @@ -32,9 +32,10 @@ TransitionEventHandler.prototype.clear = function() { this.transitionend = undefined; }; -function setupTransition(t) { +function setupTransition(t, transitionStyle) { var div, watcher, handler, transition; - div = addDiv(t, { style: 'transition: margin-left 100s 100s' }); + transitionStyle = transitionStyle || 'transition: margin-left 100s 100s'; + div = addDiv(t, { style: transitionStyle }); watcher = new EventWatcher(t, div, [ 'transitionrun', 'transitionstart', 'transitionend' ]); @@ -176,6 +177,46 @@ promise_test(function(t) { }); }, 'After -> Active'); +promise_test(function(t) { + var [transition, watcher, handler] = + setupTransition(t, 'transition: margin-left 100s -50s'); + + return watcher.wait_for([ 'transitionrun', + 'transitionstart' ]).then(function() { + assert_equals(handler.transitionrun, 50.0); + assert_equals(handler.transitionstart, 50.0); + transition.finish(); + return watcher.wait_for('transitionend'); + }).then(function(evt) { + assert_equals(evt.elapsedTime, 100.0); + }); +}, 'Calculating the interval start and end time with negative start delay.'); + +promise_test(function(t) { + var [transition, watcher, handler] = setupTransition(t); + + return watcher.wait_for('transitionrun').then(function(evt) { + // We can't set the end delay via generated effect timing. + // Because CSS-Transition use the AnimationEffectTimingReadOnly. + transition.effect = new KeyframeEffect(handler.target, + { marginleft: [ '0px', '100px' ]}, + { duration: 100 * MS_PER_SEC, + endDelay: -50 * MS_PER_SEC }); + // Seek to Before and play. + transition.cancel(); + transition.play(); + return watcher.wait_for('transitionstart'); + }).then(function() { + assert_equals(handler.transitionstart, 0.0); + + // Seek to After phase. + transition.finish(); + return watcher.wait_for('transitionend'); + }).then(function(evt) { + assert_equals(evt.elapsedTime, 50.0); + }); +}, 'Calculating the interval start and end time with negative end delay.'); + done(); From e12c1e71550896162302aec1ec80684ea8a8b8ff Mon Sep 17 00:00:00 2001 From: Wes Kocher Date: Tue, 25 Oct 2016 16:54:45 -0700 Subject: [PATCH 12/60] Backed out changeset 9b715399e585 (bug 1310123) for build failures a=backout CLOSED TREE --- layout/style/nsStyleStruct.cpp | 6 ++++++ layout/style/nsStyleStruct.h | 8 +++----- 2 files changed, 9 insertions(+), 5 deletions(-) diff --git a/layout/style/nsStyleStruct.cpp b/layout/style/nsStyleStruct.cpp index 7e755e25f3db..9d76b0832a36 100644 --- a/layout/style/nsStyleStruct.cpp +++ b/layout/style/nsStyleStruct.cpp @@ -45,6 +45,11 @@ static_assert((((1 << nsStyleStructID_Length) - 1) & ~(NS_STYLE_INHERIT_MASK)) == 0, "Not enough bits in NS_STYLE_INHERIT_MASK"); +// These are the limits that we choose to clamp grid line numbers to. +// http://dev.w3.org/csswg/css-grid/#overlarge-grids +const int32_t nsStyleGridLine::kMinLine = -10000; +const int32_t nsStyleGridLine::kMaxLine = 10000; + static bool EqualURIs(nsIURI *aURI1, nsIURI *aURI2) { @@ -817,6 +822,7 @@ nsStyleXUL::CalcDifference(const nsStyleXUL& aNewData) const // -------------------- // nsStyleColumn // +/* static */ const uint32_t nsStyleColumn::kMaxColumnCount = 1000; nsStyleColumn::nsStyleColumn(StyleStructContext aContext) : mColumnCount(NS_STYLE_COLUMN_COUNT_AUTO) diff --git a/layout/style/nsStyleStruct.h b/layout/style/nsStyleStruct.h index 5a7e85197a30..b9ac3ff32771 100644 --- a/layout/style/nsStyleStruct.h +++ b/layout/style/nsStyleStruct.h @@ -1593,11 +1593,9 @@ struct nsStyleGridLine int32_t mInteger; // 0 means not provided nsString mLineName; // Empty string means not provided. - // These are the limits that we choose to clamp grid line numbers to. - // http://dev.w3.org/csswg/css-grid/#overlarge-grids // mInteger is clamped to this range: - static const int32_t kMinLine = -10000; - static const int32_t kMaxLine = 10000; + static const int32_t kMinLine; + static const int32_t kMaxLine; nsStyleGridLine() : mHasSpan(false) @@ -3469,7 +3467,7 @@ struct MOZ_NEEDS_MEMMOVABLE_MEMBERS nsStyleColumn * This is the maximum number of columns we can process. It's used in both * nsColumnSetFrame and nsRuleNode. */ - static const uint32_t kMaxColumnCount = 1000; + static const uint32_t kMaxColumnCount; uint32_t mColumnCount; // [reset] see nsStyleConsts.h nsStyleCoord mColumnWidth; // [reset] coord, auto From 8f782c9d566a41976a6a4817cb902fec535f8a17 Mon Sep 17 00:00:00 2001 From: "Nils Ohlmeier [:drno]" Date: Fri, 30 Sep 2016 00:00:54 -0700 Subject: [PATCH 13/60] Bug 1306714: Use RFC 7983 detection for DTLS packets. r=mt MozReview-Commit-ID: L1BYAFmJOug --HG-- extra : rebase_source : 33d52ee88d646803014d9e20c3b6969833ebda15 --- media/mtransport/transportlayerdtls.cpp | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/media/mtransport/transportlayerdtls.cpp b/media/mtransport/transportlayerdtls.cpp index 18c5bdedbf8e..2abbf83d659b 100644 --- a/media/mtransport/transportlayerdtls.cpp +++ b/media/mtransport/transportlayerdtls.cpp @@ -983,6 +983,11 @@ void TransportLayerDtls::PacketReceived(TransportLayer* layer, return; } + // not DTLS per RFC 7983 + if (data[0] < 20 || data[0] > 63) { + return; + } + nspr_io_adapter_->PacketReceived(data, len); // If we're still connecting, try to handshake @@ -994,7 +999,6 @@ void TransportLayerDtls::PacketReceived(TransportLayer* layer, if (state_ == TS_OPEN) { // nICEr uses a 9216 bytes buffer to allow support for jumbo frames unsigned char buf[9216]; - int32_t rv; // One packet might contain several DTLS packets do { From 29f62bce5f304616bbc1724e921f79a2cdd4aff3 Mon Sep 17 00:00:00 2001 From: Shih-Chiang Chien Date: Mon, 24 Oct 2016 19:11:26 +0800 Subject: [PATCH 14/60] Bug 1311944 - notify device disconnect only when session termination. r=smaug MozReview-Commit-ID: JNVDv3L2r6t --HG-- extra : rebase_source : fee7609838a3c0f4b681f9ee9daed5857addeccf --- dom/presentation/PresentationSessionInfo.cpp | 10 ++++++---- .../PresentationSessionChromeScript1UA.js | 4 +++- .../file_presentation_1ua_receiver.html | 7 ++++++- ...st_presentation_1ua_sender_and_receiver.js | 20 +++++++++++++++++++ .../mochitest/test_presentation_terminate.js | 19 ++++++++++++++---- ...on_terminate_establish_connection_error.js | 9 +++++++++ 6 files changed, 59 insertions(+), 10 deletions(-) diff --git a/dom/presentation/PresentationSessionInfo.cpp b/dom/presentation/PresentationSessionInfo.cpp index 9e025489d39b..686c40b6c37f 100644 --- a/dom/presentation/PresentationSessionInfo.cpp +++ b/dom/presentation/PresentationSessionInfo.cpp @@ -1230,10 +1230,6 @@ PresentationPresentingInfo::Shutdown(nsresult aReason) mTimer->Cancel(); } - if (mDevice) { - mDevice->Disconnect(); - } - mDevice = nullptr; mLoadingCallback = nullptr; mRequesterDescription = nullptr; mPendingCandidates.Clear(); @@ -1395,6 +1391,12 @@ PresentationPresentingInfo::UntrackFromService() Unused << NS_WARN_IF(!static_cast(mContentParent.get())->SendNotifyPresentationReceiverCleanUp(mSessionId)); } + // Receiver device might need clean up after session termination. + if (mDevice) { + mDevice->Disconnect(); + } + mDevice = nullptr; + // Remove the session info (and the in-process responding info if there's any). nsCOMPtr service = do_GetService(PRESENTATION_SERVICE_CONTRACTID); diff --git a/dom/presentation/tests/mochitest/PresentationSessionChromeScript1UA.js b/dom/presentation/tests/mochitest/PresentationSessionChromeScript1UA.js index df4d66733f64..82d7362b2958 100644 --- a/dom/presentation/tests/mochitest/PresentationSessionChromeScript1UA.js +++ b/dom/presentation/tests/mochitest/PresentationSessionChromeScript1UA.js @@ -169,7 +169,9 @@ const mockDevice = { sendAsyncMessage('control-channel-established'); return mockControlChannelOfSender; }, - disconnect: function() {}, + disconnect: function() { + sendAsyncMessage('device-disconnected'); + }, isRequestedUrlSupported: function(requestedUrl) { return true; }, diff --git a/dom/presentation/tests/mochitest/file_presentation_1ua_receiver.html b/dom/presentation/tests/mochitest/file_presentation_1ua_receiver.html index a1ab6f650236..c5cf9f5c03d2 100644 --- a/dom/presentation/tests/mochitest/file_presentation_1ua_receiver.html +++ b/dom/presentation/tests/mochitest/file_presentation_1ua_receiver.html @@ -155,7 +155,12 @@ function testConnectionClosed() { function testReconnectConnection() { return new Promise(function(aResolve, aReject) { info('Receiver: --- testReconnectConnection ---'); - command('forward-command', JSON.stringify({ name: 'ready-to-reconnect' })); + window.addEventListener('hashchange', function hashchangeHandler(evt) { + var message = JSON.parse(decodeURIComponent(window.location.hash.substring(1))); + if (message.type === 'prepare-for-reconnect') { + command('forward-command', JSON.stringify({ name: 'ready-to-reconnect' })); + } + }); connection.onconnect = function() { connection.onconnect = null; ok(true, "The connection is reconnected.") diff --git a/dom/presentation/tests/mochitest/test_presentation_1ua_sender_and_receiver.js b/dom/presentation/tests/mochitest/test_presentation_1ua_sender_and_receiver.js index 5dfd140c81d0..8576d6d03986 100644 --- a/dom/presentation/tests/mochitest/test_presentation_1ua_sender_and_receiver.js +++ b/dom/presentation/tests/mochitest/test_presentation_1ua_sender_and_receiver.js @@ -230,6 +230,24 @@ function testCloseConnection() { aResolve(); }; }), + new Promise(function(aResolve, aReject) { + let timeout = setTimeout(function() { + gScript.removeMessageListener('device-disconnected', + deviceDisconnectedHandler); + ok(true, "terminate after close should not trigger device.disconnect"); + aResolve(); + }, 3000); + + function deviceDisconnectedHandler() { + gScript.removeMessageListener('device-disconnected', + deviceDisconnectedHandler); + ok(false, "terminate after close should not trigger device.disconnect"); + clearTimeout(timeout); + aResolve(); + } + + gScript.addMessageListener('device-disconnected', deviceDisconnectedHandler); + }), new Promise(function(aResolve, aReject) { gScript.addMessageListener('receiver-closed', function onReceiverClosed() { gScript.removeMessageListener('receiver-closed', onReceiverClosed); @@ -294,6 +312,8 @@ function testReconnect() { aReject(); }); }); + + postMessageToIframe('prepare-for-reconnect'); }); } diff --git a/dom/presentation/tests/mochitest/test_presentation_terminate.js b/dom/presentation/tests/mochitest/test_presentation_terminate.js index efa85cdce015..1998190b2162 100644 --- a/dom/presentation/tests/mochitest/test_presentation_terminate.js +++ b/dom/presentation/tests/mochitest/test_presentation_terminate.js @@ -146,10 +146,21 @@ function testConnectionTerminate() { gScript.removeMessageListener('sender-terminate', senderTerminateHandler); - receiverIframe.addEventListener('mozbrowserclose', function() { - ok(true, 'observe receiver page closing'); - aResolve(); - }); + Promise.all([ + new Promise((resolve) => { + gScript.addMessageListener('device-disconnected', function deviceDisconnectedHandler() { + gScript.removeMessageListener('device-disconnected', deviceDisconnectedHandler); + ok(true, 'observe device disconnect'); + resolve(); + }); + }), + new Promise((resolve) => { + receiverIframe.addEventListener('mozbrowserclose', function() { + ok(true, 'observe receiver page closing'); + resolve(); + }); + }), + ]).then(aResolve); gScript.sendAsyncMessage('trigger-on-terminate-request'); }); diff --git a/dom/presentation/tests/mochitest/test_presentation_terminate_establish_connection_error.js b/dom/presentation/tests/mochitest/test_presentation_terminate_establish_connection_error.js index 0471029fea64..b003bc4ff2f1 100644 --- a/dom/presentation/tests/mochitest/test_presentation_terminate_establish_connection_error.js +++ b/dom/presentation/tests/mochitest/test_presentation_terminate_establish_connection_error.js @@ -137,6 +137,15 @@ function testConnectionTerminate() { aResolve(); }; }), + new Promise(function(aResolve, aReject) { + function deviceDisconnectedHandler() { + gScript.removeMessageListener('device-disconnected', deviceDisconnectedHandler); + ok(true, 'should not receive device disconnect'); + aResolve(); + } + + gScript.addMessageListener('device-disconnected', deviceDisconnectedHandler); + }), new Promise(function(aResolve, aReject) { receiverIframe.addEventListener('mozbrowserclose', function() { ok(true, 'observe receiver page closing'); From 0c1268b3036c528343c5a0a6164705a797c1d575 Mon Sep 17 00:00:00 2001 From: Andreas Pehrson Date: Mon, 24 Oct 2016 08:01:41 +0200 Subject: [PATCH 15/60] Bug 1312332 - Use stopVideo as intended. r=jib MozReview-Commit-ID: JreGgjDwfam --HG-- extra : rebase_source : 3bcf591250ea92e245446ddb2c34a937afd63939 --- dom/media/MediaManager.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dom/media/MediaManager.cpp b/dom/media/MediaManager.cpp index e5e6d6e2ca47..76b46e492e9a 100644 --- a/dom/media/MediaManager.cpp +++ b/dom/media/MediaManager.cpp @@ -3628,7 +3628,7 @@ GetUserMediaCallbackMediaStreamListener::NotifyChromeOfTrackStops() "If there's a pending stop for video, there must be a video device"); if ((stopAudio || mAudioStopped || !mAudioDevice) && - (stopAudio || mVideoStopped || !mVideoDevice)) { + (stopVideo || mVideoStopped || !mVideoDevice)) { // All tracks stopped. Stop(); return; From 3f9cd43050339439453d5840cbe16f2ef8acbf28 Mon Sep 17 00:00:00 2001 From: Masayuki Nakano Date: Tue, 25 Oct 2016 14:57:10 +0900 Subject: [PATCH 16/60] Bug 1312451 Remove unnecessary empty line from .cpp files under editor/txmgr r=smaug The .cpp files under editor/txmgr have a lot of unnecessary empty lines and they make reading the code more difficult because fewer lines can be displayed in screen. This patch removes such unnecessary lines and C like variable declarations at start of some methods because they also waste lines and make them unclear where is the first user of them. MozReview-Commit-ID: GXGkdoLJ4Jw --HG-- extra : rebase_source : 449e191553cff8c875565802d930abe2a6dba4a6 --- editor/txmgr/nsTransactionItem.cpp | 52 +--------- editor/txmgr/nsTransactionList.cpp | 21 ---- editor/txmgr/nsTransactionManager.cpp | 144 ++------------------------ 3 files changed, 13 insertions(+), 204 deletions(-) diff --git a/editor/txmgr/nsTransactionItem.cpp b/editor/txmgr/nsTransactionItem.cpp index ef6a9bc2ee66..afea20a0be42 100644 --- a/editor/txmgr/nsTransactionItem.cpp +++ b/editor/txmgr/nsTransactionItem.cpp @@ -21,7 +21,6 @@ nsTransactionItem::nsTransactionItem(nsITransaction *aTransaction) nsTransactionItem::~nsTransactionItem() { delete mRedoStack; - delete mUndoStack; } @@ -72,7 +71,6 @@ nsTransactionItem::AddChild(nsTransactionItem *aTransactionItem) } mUndoStack->Push(aTransactionItem); - return NS_OK; } @@ -87,9 +85,7 @@ nsresult nsTransactionItem::GetIsBatch(bool *aIsBatch) { NS_ENSURE_TRUE(aIsBatch, NS_ERROR_NULL_POINTER); - *aIsBatch = !mTransaction; - return NS_OK; } @@ -101,18 +97,14 @@ nsTransactionItem::GetNumberOfChildren(int32_t *aNumChildren) *aNumChildren = 0; int32_t ui = 0; - int32_t ri = 0; - nsresult rv = GetNumberOfUndoItems(&ui); - NS_ENSURE_SUCCESS(rv, rv); + int32_t ri = 0; rv = GetNumberOfRedoItems(&ri); - NS_ENSURE_SUCCESS(rv, rv); *aNumChildren = ui + ri; - return NS_OK; } @@ -125,9 +117,7 @@ nsTransactionItem::GetChild(int32_t aIndex, nsTransactionItem **aChild) int32_t numItems = 0; nsresult rv = GetNumberOfChildren(&numItems); - NS_ENSURE_SUCCESS(rv, rv); - if (aIndex < 0 || aIndex >= numItems) { return NS_ERROR_FAILURE; } @@ -136,9 +126,7 @@ nsTransactionItem::GetChild(int32_t aIndex, nsTransactionItem **aChild) // so the child first added would be at the bottom of the undo // stack, or if there are no items on the undo stack, it would // be at the top of the redo stack. - rv = GetNumberOfUndoItems(&numItems); - NS_ENSURE_SUCCESS(rv, rv); if (numItems > 0 && aIndex < numItems) { @@ -150,13 +138,10 @@ nsTransactionItem::GetChild(int32_t aIndex, nsTransactionItem **aChild) } // Adjust the index for the redo stack: - aIndex -= numItems; rv = GetNumberOfRedoItems(&numItems); - NS_ENSURE_SUCCESS(rv, rv); - NS_ENSURE_TRUE(mRedoStack && numItems != 0 && aIndex < numItems, NS_ERROR_FAILURE); RefPtr child = mRedoStack->GetItem(aIndex); @@ -177,7 +162,6 @@ nsresult nsTransactionItem::UndoTransaction(nsTransactionManager *aTxMgr) { nsresult rv = UndoChildren(aTxMgr); - if (NS_FAILED(rv)) { RecoverFromUndoError(aTxMgr); return rv; @@ -188,7 +172,6 @@ nsTransactionItem::UndoTransaction(nsTransactionManager *aTxMgr) } rv = mTransaction->UndoTransaction(); - if (NS_FAILED(rv)) { RecoverFromUndoError(aTxMgr); return rv; @@ -200,48 +183,38 @@ nsTransactionItem::UndoTransaction(nsTransactionManager *aTxMgr) nsresult nsTransactionItem::UndoChildren(nsTransactionManager *aTxMgr) { - RefPtr item; - int32_t sz = 0; - if (mUndoStack) { if (!mRedoStack && mUndoStack) { mRedoStack = new nsTransactionStack(nsTransactionStack::FOR_REDO); } /* Undo all of the transaction items children! */ - sz = mUndoStack->GetSize(); + int32_t sz = mUndoStack->GetSize(); nsresult rv = NS_OK; while (sz-- > 0) { - item = mUndoStack->Peek(); - + RefPtr item = mUndoStack->Peek(); if (!item) { return NS_ERROR_FAILURE; } nsCOMPtr t = item->GetTransaction(); - bool doInterrupt = false; - rv = aTxMgr->WillUndoNotify(t, &doInterrupt); - if (NS_FAILED(rv)) { return rv; } - if (doInterrupt) { return NS_OK; } rv = item->UndoTransaction(aTxMgr); - if (NS_SUCCEEDED(rv)) { item = mUndoStack->Pop(); mRedoStack->Push(item.forget()); } nsresult rv2 = aTxMgr->DidUndoNotify(t, rv); - if (NS_SUCCEEDED(rv)) { rv = rv2; } @@ -261,12 +234,10 @@ nsTransactionItem::RedoTransaction(nsTransactionManager *aTxMgr) nsCOMPtr transaction(mTransaction); if (transaction) { nsresult rv = transaction->RedoTransaction(); - NS_ENSURE_SUCCESS(rv, rv); } nsresult rv = RedoChildren(aTxMgr); - if (NS_FAILED(rv)) { RecoverFromRedoError(aTxMgr); return rv; @@ -278,8 +249,6 @@ nsTransactionItem::RedoTransaction(nsTransactionManager *aTxMgr) nsresult nsTransactionItem::RedoChildren(nsTransactionManager *aTxMgr) { - RefPtr item; - if (!mRedoStack) { return NS_OK; } @@ -289,28 +258,22 @@ nsTransactionItem::RedoChildren(nsTransactionManager *aTxMgr) nsresult rv = NS_OK; while (sz-- > 0) { - item = mRedoStack->Peek(); - + RefPtr item = mRedoStack->Peek(); if (!item) { return NS_ERROR_FAILURE; } nsCOMPtr t = item->GetTransaction(); - bool doInterrupt = false; - rv = aTxMgr->WillRedoNotify(t, &doInterrupt); - if (NS_FAILED(rv)) { return rv; } - if (doInterrupt) { return NS_OK; } rv = item->RedoTransaction(aTxMgr); - if (NS_SUCCEEDED(rv)) { item = mRedoStack->Pop(); mUndoStack->Push(item.forget()); @@ -318,7 +281,6 @@ nsTransactionItem::RedoChildren(nsTransactionManager *aTxMgr) // XXX Shouldn't this DidRedoNotify()? (bug 1311626) nsresult rv2 = aTxMgr->DidUndoNotify(t, rv); - if (NS_SUCCEEDED(rv)) { rv = rv2; } @@ -360,26 +322,20 @@ nsTransactionItem::GetNumberOfRedoItems(int32_t *aNumItems) nsresult nsTransactionItem::RecoverFromUndoError(nsTransactionManager *aTxMgr) { - // // If this method gets called, we never got to the point where we // successfully called UndoTransaction() for the transaction item itself. // Just redo any children that successfully called undo! - // return RedoChildren(aTxMgr); } nsresult nsTransactionItem::RecoverFromRedoError(nsTransactionManager *aTxMgr) { - // // If this method gets called, we already successfully called // RedoTransaction() for the transaction item itself. Undo all // the children that successfully called RedoTransaction(), // then undo the transaction item itself. - // - nsresult rv = UndoChildren(aTxMgr); - if (NS_FAILED(rv)) { return rv; } diff --git a/editor/txmgr/nsTransactionList.cpp b/editor/txmgr/nsTransactionList.cpp index c17c4c3faec1..0745eb5ff371 100644 --- a/editor/txmgr/nsTransactionList.cpp +++ b/editor/txmgr/nsTransactionList.cpp @@ -46,7 +46,6 @@ NS_IMETHODIMP nsTransactionList::GetNumItems(int32_t *aNumItems) *aNumItems = 0; nsCOMPtr txMgr = do_QueryReferent(mTxnMgr); - NS_ENSURE_TRUE(txMgr, NS_ERROR_FAILURE); if (mTxnStack) { @@ -65,18 +64,15 @@ NS_IMETHODIMP nsTransactionList::ItemIsBatch(int32_t aIndex, bool *aIsBatch) *aIsBatch = false; nsCOMPtr txMgr = do_QueryReferent(mTxnMgr); - NS_ENSURE_TRUE(txMgr, NS_ERROR_FAILURE); RefPtr item; - if (mTxnStack) { item = mTxnStack->GetItem(aIndex); } else if (mTxnItem) { nsresult rv = mTxnItem->GetChild(aIndex, getter_AddRefs(item)); NS_ENSURE_SUCCESS(rv, rv); } - NS_ENSURE_TRUE(item, NS_ERROR_FAILURE); return item->GetIsBatch(aIsBatch); @@ -87,11 +83,9 @@ NS_IMETHODIMP nsTransactionList::GetData(int32_t aIndex, nsISupports ***aData) { nsCOMPtr txMgr = do_QueryReferent(mTxnMgr); - NS_ENSURE_TRUE(txMgr, NS_ERROR_FAILURE); RefPtr item; - if (mTxnStack) { item = mTxnStack->GetItem(aIndex); } else if (mTxnItem) { @@ -100,17 +94,14 @@ NS_IMETHODIMP nsTransactionList::GetData(int32_t aIndex, } nsCOMArray& data = item->GetData(); - nsISupports** ret = static_cast(moz_xmalloc(data.Count() * sizeof(nsISupports*))); for (int32_t i = 0; i < data.Count(); i++) { NS_ADDREF(ret[i] = data[i]); } - *aLength = data.Count(); *aData = ret; - return NS_OK; } @@ -121,22 +112,18 @@ NS_IMETHODIMP nsTransactionList::GetItem(int32_t aIndex, nsITransaction **aItem) *aItem = 0; nsCOMPtr txMgr = do_QueryReferent(mTxnMgr); - NS_ENSURE_TRUE(txMgr, NS_ERROR_FAILURE); RefPtr item; - if (mTxnStack) { item = mTxnStack->GetItem(aIndex); } else if (mTxnItem) { nsresult rv = mTxnItem->GetChild(aIndex, getter_AddRefs(item)); NS_ENSURE_SUCCESS(rv, rv); } - NS_ENSURE_TRUE(item, NS_ERROR_FAILURE); *aItem = item->GetTransaction().take(); - return NS_OK; } @@ -147,18 +134,15 @@ NS_IMETHODIMP nsTransactionList::GetNumChildrenForItem(int32_t aIndex, int32_t * *aNumChildren = 0; nsCOMPtr txMgr = do_QueryReferent(mTxnMgr); - NS_ENSURE_TRUE(txMgr, NS_ERROR_FAILURE); RefPtr item; - if (mTxnStack) { item = mTxnStack->GetItem(aIndex); } else if (mTxnItem) { nsresult rv = mTxnItem->GetChild(aIndex, getter_AddRefs(item)); NS_ENSURE_SUCCESS(rv, rv); } - NS_ENSURE_TRUE(item, NS_ERROR_FAILURE); return item->GetNumberOfChildren(aNumChildren); @@ -171,25 +155,20 @@ NS_IMETHODIMP nsTransactionList::GetChildListForItem(int32_t aIndex, nsITransact *aTxnList = 0; nsCOMPtr txMgr = do_QueryReferent(mTxnMgr); - NS_ENSURE_TRUE(txMgr, NS_ERROR_FAILURE); RefPtr item; - if (mTxnStack) { item = mTxnStack->GetItem(aIndex); } else if (mTxnItem) { nsresult rv = mTxnItem->GetChild(aIndex, getter_AddRefs(item)); NS_ENSURE_SUCCESS(rv, rv); } - NS_ENSURE_TRUE(item, NS_ERROR_FAILURE); *aTxnList = (nsITransactionList *)new nsTransactionList(txMgr, item); - NS_ENSURE_TRUE(*aTxnList, NS_ERROR_OUT_OF_MEMORY); NS_ADDREF(*aTxnList); - return NS_OK; } diff --git a/editor/txmgr/nsTransactionManager.cpp b/editor/txmgr/nsTransactionManager.cpp index 9e2e00745fe9..10f9c3d0643d 100644 --- a/editor/txmgr/nsTransactionManager.cpp +++ b/editor/txmgr/nsTransactionManager.cpp @@ -64,17 +64,14 @@ nsTransactionManager::DoTransaction(nsITransaction *aTransaction) bool doInterrupt = false; nsresult rv = WillDoNotify(aTransaction, &doInterrupt); - if (NS_FAILED(rv)) { return rv; } - if (doInterrupt) { return NS_OK; } rv = BeginTransaction(aTransaction, nullptr); - if (NS_FAILED(rv)) { DidDoNotify(aTransaction, rv); return rv; @@ -83,7 +80,6 @@ nsTransactionManager::DoTransaction(nsITransaction *aTransaction) rv = EndTransaction(false); nsresult rv2 = DidDoNotify(aTransaction, rv); - if (NS_SUCCEEDED(rv)) { rv = rv2; } @@ -99,7 +95,6 @@ nsTransactionManager::UndoTransaction() // It is illegal to call UndoTransaction() while the transaction manager is // executing a transaction's DoTransaction() method! If this happens, // the UndoTransaction() request is ignored, and we return NS_ERROR_FAILURE. - if (!mDoStack.IsEmpty()) { return NS_ERROR_FAILURE; } @@ -107,35 +102,28 @@ nsTransactionManager::UndoTransaction() // Peek at the top of the undo stack. Don't remove the transaction // until it has successfully completed. RefPtr tx = mUndoStack.Peek(); - - // Bail if there's nothing on the stack. if (!tx) { + // Bail if there's nothing on the stack. return NS_OK; } nsCOMPtr t = tx->GetTransaction(); - bool doInterrupt = false; - nsresult rv = WillUndoNotify(t, &doInterrupt); - if (NS_FAILED(rv)) { return rv; } - if (doInterrupt) { return NS_OK; } rv = tx->UndoTransaction(this); - if (NS_SUCCEEDED(rv)) { tx = mUndoStack.Pop(); mRedoStack.Push(tx.forget()); } nsresult rv2 = DidUndoNotify(t, rv); - if (NS_SUCCEEDED(rv)) { rv = rv2; } @@ -151,7 +139,6 @@ nsTransactionManager::RedoTransaction() // It is illegal to call RedoTransaction() while the transaction manager is // executing a transaction's DoTransaction() method! If this happens, // the RedoTransaction() request is ignored, and we return NS_ERROR_FAILURE. - if (!mDoStack.IsEmpty()) { return NS_ERROR_FAILURE; } @@ -159,35 +146,28 @@ nsTransactionManager::RedoTransaction() // Peek at the top of the redo stack. Don't remove the transaction // until it has successfully completed. RefPtr tx = mRedoStack.Peek(); - - // Bail if there's nothing on the stack. if (!tx) { + // Bail if there's nothing on the stack. return NS_OK; } nsCOMPtr t = tx->GetTransaction(); - bool doInterrupt = false; - nsresult rv = WillRedoNotify(t, &doInterrupt); - if (NS_FAILED(rv)) { return rv; } - if (doInterrupt) { return NS_OK; } rv = tx->RedoTransaction(this); - if (NS_SUCCEEDED(rv)) { tx = mRedoStack.Pop(); mUndoStack.Push(tx.forget()); } nsresult rv2 = DidRedoNotify(t, rv); - if (NS_SUCCEEDED(rv)) { rv = rv2; } @@ -201,11 +181,9 @@ NS_IMETHODIMP nsTransactionManager::Clear() { nsresult rv = ClearRedoStack(); - if (NS_FAILED(rv)) { return rv; } - return ClearUndoStack(); } @@ -216,15 +194,11 @@ nsTransactionManager::BeginBatch(nsISupports* aData) // a dummy transaction item on the do stack. This dummy transaction item // will be popped off the do stack, and then pushed on the undo stack // in EndBatch(). - bool doInterrupt = false; - nsresult rv = WillBeginBatchNotify(&doInterrupt); - if (NS_FAILED(rv)) { return rv; } - if (doInterrupt) { return NS_OK; } @@ -232,7 +206,6 @@ nsTransactionManager::BeginBatch(nsISupports* aData) rv = BeginTransaction(0, aData); nsresult rv2 = DidBeginBatchNotify(rv); - if (NS_SUCCEEDED(rv)) { rv = rv2; } @@ -255,34 +228,26 @@ nsTransactionManager::EndBatch(bool aAllowEmpty) // transaction, it should be nullptr. This may not be true in the // future when we allow users to execute a transaction when beginning // a batch!!!! - RefPtr tx = mDoStack.Peek(); - nsCOMPtr ti; if (tx) { ti = tx->GetTransaction(); } - if (!tx || ti) { return NS_ERROR_FAILURE; } bool doInterrupt = false; - nsresult rv = WillEndBatchNotify(&doInterrupt); - if (NS_FAILED(rv)) { return rv; } - if (doInterrupt) { return NS_OK; } rv = EndTransaction(aAllowEmpty); - nsresult rv2 = DidEndBatchNotify(rv); - if (NS_SUCCEEDED(rv)) { rv = rv2; } @@ -310,45 +275,35 @@ NS_IMETHODIMP nsTransactionManager::GetMaxTransactionCount(int32_t *aMaxCount) { NS_ENSURE_TRUE(aMaxCount, NS_ERROR_NULL_POINTER); - *aMaxCount = mMaxTransactionCount; - return NS_OK; } NS_IMETHODIMP nsTransactionManager::SetMaxTransactionCount(int32_t aMaxCount) { - int32_t numUndoItems = 0, numRedoItems = 0, total = 0; - // It is illegal to call SetMaxTransactionCount() while the transaction // manager is executing a transaction's DoTransaction() method because // the undo and redo stacks might get pruned! If this happens, the // SetMaxTransactionCount() request is ignored, and we return // NS_ERROR_FAILURE. - if (!mDoStack.IsEmpty()) { return NS_ERROR_FAILURE; } // If aMaxCount is less than zero, the user wants unlimited // levels of undo! No need to prune the undo or redo stacks! - if (aMaxCount < 0) { mMaxTransactionCount = -1; return NS_OK; } - numUndoItems = mUndoStack.GetSize(); - - numRedoItems = mRedoStack.GetSize(); - - total = numUndoItems + numRedoItems; - // If aMaxCount is greater than the number of transactions that currently // exist on the undo and redo stack, there is no need to prune the // undo or redo stacks! - + int32_t numUndoItems = mUndoStack.GetSize(); + int32_t numRedoItems = mRedoStack.GetSize(); + int32_t total = numUndoItems + numRedoItems; if (aMaxCount > total) { mMaxTransactionCount = aMaxCount; return NS_OK; @@ -356,32 +311,25 @@ nsTransactionManager::SetMaxTransactionCount(int32_t aMaxCount) // Try getting rid of some transactions on the undo stack! Start at // the bottom of the stack and pop towards the top. - while (numUndoItems > 0 && (numRedoItems + numUndoItems) > aMaxCount) { RefPtr tx = mUndoStack.PopBottom(); - if (!tx) { return NS_ERROR_FAILURE; } - --numUndoItems; } // If necessary, get rid of some transactions on the redo stack! Start at // the bottom of the stack and pop towards the top. - while (numRedoItems > 0 && (numRedoItems + numUndoItems) > aMaxCount) { RefPtr tx = mRedoStack.PopBottom(); - if (!tx) { return NS_ERROR_FAILURE; } - --numRedoItems; } mMaxTransactionCount = aMaxCount; - return NS_OK; } @@ -397,11 +345,9 @@ already_AddRefed nsTransactionManager::PeekUndoStack() { RefPtr tx = mUndoStack.Peek(); - if (!tx) { return nullptr; } - return tx->GetTransaction(); } @@ -417,11 +363,9 @@ already_AddRefed nsTransactionManager::PeekRedoStack() { RefPtr tx = mRedoStack.Peek(); - if (!tx) { return nullptr; } - return tx->GetTransaction(); } @@ -431,9 +375,7 @@ nsTransactionManager::GetUndoList(nsITransactionList **aTransactionList) NS_ENSURE_TRUE(aTransactionList, NS_ERROR_NULL_POINTER); *aTransactionList = (nsITransactionList *)new nsTransactionList(this, &mUndoStack); - NS_IF_ADDREF(*aTransactionList); - return (! *aTransactionList) ? NS_ERROR_OUT_OF_MEMORY : NS_OK; } @@ -443,9 +385,7 @@ nsTransactionManager::GetRedoList(nsITransactionList **aTransactionList) NS_ENSURE_TRUE(aTransactionList, NS_ERROR_NULL_POINTER); *aTransactionList = (nsITransactionList *)new nsTransactionList(this, &mRedoStack); - NS_IF_ADDREF(*aTransactionList); - return (! *aTransactionList) ? NS_ERROR_OUT_OF_MEMORY : NS_OK; } @@ -474,7 +414,6 @@ nsTransactionManager::BatchTopUndo() nsCOMArray& previousData = previousUndo->GetData(); NS_ENSURE_TRUE(previousData.AppendObjects(lastData), NS_ERROR_UNEXPECTED); lastData.Clear(); - return rv; } @@ -493,7 +432,6 @@ NS_IMETHODIMP nsTransactionManager::AddListener(nsITransactionListener *aListener) { NS_ENSURE_TRUE(aListener, NS_ERROR_NULL_POINTER); - return mListeners.AppendObject(aListener) ? NS_OK : NS_ERROR_FAILURE; } @@ -501,7 +439,6 @@ NS_IMETHODIMP nsTransactionManager::RemoveListener(nsITransactionListener *aListener) { NS_ENSURE_TRUE(aListener, NS_ERROR_NULL_POINTER); - return mListeners.RemoveObject(aListener) ? NS_OK : NS_ERROR_FAILURE; } @@ -524,16 +461,13 @@ nsTransactionManager::WillDoNotify(nsITransaction *aTransaction, bool *aInterrup { for (int32_t i = 0, lcount = mListeners.Count(); i < lcount; i++) { nsITransactionListener* listener = mListeners[i]; - NS_ENSURE_TRUE(listener, NS_ERROR_FAILURE); nsresult rv = listener->WillDo(this, aTransaction, aInterrupt); - if (NS_FAILED(rv) || *aInterrupt) { return rv; } } - return NS_OK; } @@ -542,16 +476,13 @@ nsTransactionManager::DidDoNotify(nsITransaction *aTransaction, nsresult aDoResu { for (int32_t i = 0, lcount = mListeners.Count(); i < lcount; i++) { nsITransactionListener* listener = mListeners[i]; - NS_ENSURE_TRUE(listener, NS_ERROR_FAILURE); nsresult rv = listener->DidDo(this, aTransaction, aDoResult); - if (NS_FAILED(rv)) { return rv; } } - return NS_OK; } @@ -560,16 +491,13 @@ nsTransactionManager::WillUndoNotify(nsITransaction *aTransaction, bool *aInterr { for (int32_t i = 0, lcount = mListeners.Count(); i < lcount; i++) { nsITransactionListener* listener = mListeners[i]; - NS_ENSURE_TRUE(listener, NS_ERROR_FAILURE); nsresult rv = listener->WillUndo(this, aTransaction, aInterrupt); - if (NS_FAILED(rv) || *aInterrupt) { return rv; } } - return NS_OK; } @@ -578,16 +506,13 @@ nsTransactionManager::DidUndoNotify(nsITransaction *aTransaction, nsresult aUndo { for (int32_t i = 0, lcount = mListeners.Count(); i < lcount; i++) { nsITransactionListener* listener = mListeners[i]; - NS_ENSURE_TRUE(listener, NS_ERROR_FAILURE); nsresult rv = listener->DidUndo(this, aTransaction, aUndoResult); - if (NS_FAILED(rv)) { return rv; } } - return NS_OK; } @@ -596,16 +521,13 @@ nsTransactionManager::WillRedoNotify(nsITransaction *aTransaction, bool *aInterr { for (int32_t i = 0, lcount = mListeners.Count(); i < lcount; i++) { nsITransactionListener* listener = mListeners[i]; - NS_ENSURE_TRUE(listener, NS_ERROR_FAILURE); nsresult rv = listener->WillRedo(this, aTransaction, aInterrupt); - if (NS_FAILED(rv) || *aInterrupt) { return rv; } } - return NS_OK; } @@ -614,16 +536,13 @@ nsTransactionManager::DidRedoNotify(nsITransaction *aTransaction, nsresult aRedo { for (int32_t i = 0, lcount = mListeners.Count(); i < lcount; i++) { nsITransactionListener* listener = mListeners[i]; - NS_ENSURE_TRUE(listener, NS_ERROR_FAILURE); nsresult rv = listener->DidRedo(this, aTransaction, aRedoResult); - if (NS_FAILED(rv)) { return rv; } } - return NS_OK; } @@ -632,16 +551,13 @@ nsTransactionManager::WillBeginBatchNotify(bool *aInterrupt) { for (int32_t i = 0, lcount = mListeners.Count(); i < lcount; i++) { nsITransactionListener* listener = mListeners[i]; - NS_ENSURE_TRUE(listener, NS_ERROR_FAILURE); nsresult rv = listener->WillBeginBatch(this, aInterrupt); - if (NS_FAILED(rv) || *aInterrupt) { return rv; } } - return NS_OK; } @@ -650,16 +566,13 @@ nsTransactionManager::DidBeginBatchNotify(nsresult aResult) { for (int32_t i = 0, lcount = mListeners.Count(); i < lcount; i++) { nsITransactionListener* listener = mListeners[i]; - NS_ENSURE_TRUE(listener, NS_ERROR_FAILURE); nsresult rv = listener->DidBeginBatch(this, aResult); - if (NS_FAILED(rv)) { return rv; } } - return NS_OK; } @@ -668,16 +581,13 @@ nsTransactionManager::WillEndBatchNotify(bool *aInterrupt) { for (int32_t i = 0, lcount = mListeners.Count(); i < lcount; i++) { nsITransactionListener* listener = mListeners[i]; - NS_ENSURE_TRUE(listener, NS_ERROR_FAILURE); nsresult rv = listener->WillEndBatch(this, aInterrupt); - if (NS_FAILED(rv) || *aInterrupt) { return rv; } } - return NS_OK; } @@ -686,16 +596,13 @@ nsTransactionManager::DidEndBatchNotify(nsresult aResult) { for (int32_t i = 0, lcount = mListeners.Count(); i < lcount; i++) { nsITransactionListener* listener = mListeners[i]; - NS_ENSURE_TRUE(listener, NS_ERROR_FAILURE); nsresult rv = listener->DidEndBatch(this, aResult); - if (NS_FAILED(rv)) { return rv; } } - return NS_OK; } @@ -704,16 +611,13 @@ nsTransactionManager::WillMergeNotify(nsITransaction *aTop, nsITransaction *aTra { for (int32_t i = 0, lcount = mListeners.Count(); i < lcount; i++) { nsITransactionListener* listener = mListeners[i]; - NS_ENSURE_TRUE(listener, NS_ERROR_FAILURE); nsresult rv = listener->WillMerge(this, aTop, aTransaction, aInterrupt); - if (NS_FAILED(rv) || *aInterrupt) { return rv; } } - return NS_OK; } @@ -725,17 +629,14 @@ nsTransactionManager::DidMergeNotify(nsITransaction *aTop, { for (int32_t i = 0, lcount = mListeners.Count(); i < lcount; i++) { nsITransactionListener* listener = mListeners[i]; - NS_ENSURE_TRUE(listener, NS_ERROR_FAILURE); nsresult rv = listener->DidMerge(this, aTop, aTransaction, aDidMerge, aMergeResult); - if (NS_FAILED(rv)) { return rv; } } - return NS_OK; } @@ -746,25 +647,22 @@ nsTransactionManager::BeginTransaction(nsITransaction *aTransaction, // XXX: POSSIBLE OPTIMIZATION // We could use a factory that pre-allocates/recycles transaction items. RefPtr tx = new nsTransactionItem(aTransaction); + if (!tx) { + return NS_ERROR_OUT_OF_MEMORY; + } if (aData) { nsCOMArray& data = tx->GetData(); data.AppendObject(aData); } - if (!tx) { - return NS_ERROR_OUT_OF_MEMORY; - } - mDoStack.Push(tx); nsresult rv = tx->DoTransaction(); - if (NS_FAILED(rv)) { tx = mDoStack.Pop(); return rv; } - return NS_OK; } @@ -772,21 +670,16 @@ nsresult nsTransactionManager::EndTransaction(bool aAllowEmpty) { RefPtr tx = mDoStack.Pop(); - if (!tx) { return NS_ERROR_FAILURE; } nsCOMPtr tint = tx->GetTransaction(); - if (!tint && !aAllowEmpty) { - int32_t nc = 0; - // If we get here, the transaction must be a dummy batch transaction // created by BeginBatch(). If it contains no children, get rid of it! - + int32_t nc = 0; tx->GetNumberOfChildren(&nc); - if (!nc) { return NS_OK; } @@ -794,13 +687,11 @@ nsTransactionManager::EndTransaction(bool aAllowEmpty) // Check if the transaction is transient. If it is, there's nothing // more to do, just return. - bool isTransient = false; nsresult rv = NS_OK; if (tint) { rv = tint->GetIsTransient(&isTransient); } - if (NS_FAILED(rv) || isTransient || !mMaxTransactionCount) { // XXX: Should we be clearing the redo stack if the transaction // is transient and there is nothing on the do stack? @@ -810,50 +701,37 @@ nsTransactionManager::EndTransaction(bool aAllowEmpty) // Check if there is a transaction on the do stack. If there is, // the current transaction is a "sub" transaction, and should // be added to the transaction at the top of the do stack. - RefPtr top = mDoStack.Peek(); if (top) { return top->AddChild(tx); // XXX: What do we do if this fails? } // The transaction succeeded, so clear the redo stack. - rv = ClearRedoStack(); - if (NS_FAILED(rv)) { // XXX: What do we do if this fails? } // Check if we can coalesce this transaction with the one at the top // of the undo stack. - top = mUndoStack.Peek(); - if (tint && top) { bool didMerge = false; nsCOMPtr topTransaction = top->GetTransaction(); - if (topTransaction) { - bool doInterrupt = false; - rv = WillMergeNotify(topTransaction, tint, &doInterrupt); - NS_ENSURE_SUCCESS(rv, rv); if (!doInterrupt) { rv = topTransaction->Merge(tint, &didMerge); - nsresult rv2 = DidMergeNotify(topTransaction, tint, didMerge, rv); - if (NS_SUCCEEDED(rv)) { rv = rv2; } - if (NS_FAILED(rv)) { // XXX: What do we do if this fails? } - if (didMerge) { return rv; } @@ -863,16 +741,12 @@ nsTransactionManager::EndTransaction(bool aAllowEmpty) // Check to see if we've hit the max level of undo. If so, // pop the bottom transaction off the undo stack and release it! - int32_t sz = mUndoStack.GetSize(); - if (mMaxTransactionCount > 0 && sz >= mMaxTransactionCount) { RefPtr overflow = mUndoStack.PopBottom(); } // Push the transaction on the undo stack: - mUndoStack.Push(tx.forget()); - return NS_OK; } From 7999bc1f1651d16b38278b7e3aff413ed050a316 Mon Sep 17 00:00:00 2001 From: Masayuki Nakano Date: Tue, 25 Oct 2016 15:07:42 +0900 Subject: [PATCH 17/60] Bug 1311621 Fix odd indent of editor/composer/nsComposerRegistration.cpp r=smaug MozReview-Commit-ID: L4y0UNS6xFb --HG-- extra : rebase_source : 116b2c82384ae03d23d243fe2a41e50c7012f4f9 --- editor/composer/nsComposerRegistration.cpp | 30 +++++++++++----------- 1 file changed, 15 insertions(+), 15 deletions(-) diff --git a/editor/composer/nsComposerRegistration.cpp b/editor/composer/nsComposerRegistration.cpp index faf6dfad7530..7a0b3a4406cc 100644 --- a/editor/composer/nsComposerRegistration.cpp +++ b/editor/composer/nsComposerRegistration.cpp @@ -57,19 +57,19 @@ static nsresult nsComposeTxtSrvFilterConstructor(nsISupports *aOuter, REFNSIID aIID, void **aResult, bool aIsForMail) { - *aResult = nullptr; - if (aOuter) { - return NS_ERROR_NO_AGGREGATION; - } - nsComposeTxtSrvFilter * inst = new nsComposeTxtSrvFilter(); - if (!inst) { - return NS_ERROR_OUT_OF_MEMORY; - } - NS_ADDREF(inst); - inst->Init(aIsForMail); - nsresult rv = inst->QueryInterface(aIID, aResult); - NS_RELEASE(inst); - return rv; + *aResult = nullptr; + if (aOuter) { + return NS_ERROR_NO_AGGREGATION; + } + nsComposeTxtSrvFilter * inst = new nsComposeTxtSrvFilter(); + if (!inst) { + return NS_ERROR_OUT_OF_MEMORY; + } + NS_ADDREF(inst); + inst->Init(aIsForMail); + nsresult rv = inst->QueryInterface(aIID, aResult); + NS_RELEASE(inst); + return rv; } static nsresult @@ -77,7 +77,7 @@ nsComposeTxtSrvFilterConstructorForComposer(nsISupports *aOuter, REFNSIID aIID, void **aResult) { - return nsComposeTxtSrvFilterConstructor(aOuter, aIID, aResult, false); + return nsComposeTxtSrvFilterConstructor(aOuter, aIID, aResult, false); } static nsresult @@ -85,7 +85,7 @@ nsComposeTxtSrvFilterConstructorForMail(nsISupports *aOuter, REFNSIID aIID, void **aResult) { - return nsComposeTxtSrvFilterConstructor(aOuter, aIID, aResult, true); + return nsComposeTxtSrvFilterConstructor(aOuter, aIID, aResult, true); } From 35966d289317daf2f10bc3a15d64811d825e73ef Mon Sep 17 00:00:00 2001 From: Mark Hammond Date: Tue, 25 Oct 2016 13:47:33 +1100 Subject: [PATCH 18/60] Bug 1312642 - PlacesSyncUtils should pass SOURCE_SYNC to PlacesUtils.bookmarks.reorder. r=kitcambridge MozReview-Commit-ID: 4EsnU7LSWDG --HG-- extra : rebase_source : 6c82b86c4098e4276e110aa481863c648c67ecc8 --- toolkit/components/places/PlacesSyncUtils.jsm | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/toolkit/components/places/PlacesSyncUtils.jsm b/toolkit/components/places/PlacesSyncUtils.jsm index 8cef1c5d4757..b80e3526cd2f 100644 --- a/toolkit/components/places/PlacesSyncUtils.jsm +++ b/toolkit/components/places/PlacesSyncUtils.jsm @@ -128,7 +128,8 @@ const BookmarkSyncUtils = PlacesSyncUtils.bookmarks = Object.freeze({ return undefined; } let orderedChildrenGuids = childSyncIds.map(BookmarkSyncUtils.syncIdToGuid); - return PlacesUtils.bookmarks.reorder(parentGuid, orderedChildrenGuids); + return PlacesUtils.bookmarks.reorder(parentGuid, orderedChildrenGuids, + { source: SOURCE_SYNC }); }), /** From 144c0a5d23ef2ee99d5a3ec974786332f8ec921c Mon Sep 17 00:00:00 2001 From: Michelangelo De Simone Date: Wed, 12 Oct 2016 15:19:09 -0700 Subject: [PATCH 19/60] Bug 1309719 - Remove DOM/telephony and related code. r=ehsan+251051 MozReview-Commit-ID: Gv3vnyH4Csi --HG-- extra : rebase_source : 6267f92bc9104bace982297474dc978a06dff5ba --- b2g/components/ContentPermissionPrompt.js | 21 - b2g/installer/package-manifest.in | 7 - browser/installer/package-manifest.in | 1 - dom/apps/PermissionsTable.jsm | 5 - dom/base/Navigator.cpp | 20 - dom/base/Navigator.h | 3 - dom/ipc/ContentChild.cpp | 15 - dom/ipc/ContentChild.h | 4 - dom/ipc/ContentParent.cpp | 21 - dom/ipc/ContentParent.h | 4 - dom/ipc/PContent.ipdl | 4 - dom/moz.build | 1 - dom/permission/tests/mochitest-ril.ini | 1 - dom/permission/tests/test_telephony.html | 32 - dom/telephony/CallsList.cpp | 76 - dom/telephony/CallsList.h | 53 - dom/telephony/MMICall.cpp | 79 - dom/telephony/MMICall.h | 59 - dom/telephony/Telephony.cpp | 870 ------ dom/telephony/Telephony.h | 245 -- dom/telephony/TelephonyCall.cpp | 454 --- dom/telephony/TelephonyCall.h | 217 -- dom/telephony/TelephonyCallGroup.cpp | 469 --- dom/telephony/TelephonyCallGroup.h | 140 - dom/telephony/TelephonyCallId.cpp | 76 - dom/telephony/TelephonyCallId.h | 82 - dom/telephony/TelephonyCallInfo.cpp | 141 - dom/telephony/TelephonyCallInfo.h | 67 - dom/telephony/TelephonyCallback.cpp | 36 - dom/telephony/TelephonyCallback.h | 39 - dom/telephony/TelephonyCommon.h | 37 - dom/telephony/TelephonyDialCallback.cpp | 246 -- dom/telephony/TelephonyDialCallback.h | 57 - dom/telephony/USSDSession.cpp | 128 - dom/telephony/USSDSession.h | 66 - dom/telephony/gonk/DialNumberUtils.jsm | 110 - dom/telephony/gonk/TelephonyAudioService.js | 151 - .../gonk/TelephonyAudioService.manifest | 6 - dom/telephony/gonk/TelephonyService.js | 2514 ----------------- dom/telephony/gonk/TelephonyService.manifest | 3 - dom/telephony/gonk/TelephonyUtils.jsm | 109 - dom/telephony/gonk/USSDReceivedWrapper.js | 82 - .../gonk/USSDReceivedWrapper.manifest | 2 - dom/telephony/ipc/PTelephony.ipdl | 169 -- dom/telephony/ipc/PTelephonyRequest.ipdl | 81 - dom/telephony/ipc/TelephonyChild.cpp | 271 -- dom/telephony/ipc/TelephonyChild.h | 100 - dom/telephony/ipc/TelephonyIPCSerializer.h | 160 -- dom/telephony/ipc/TelephonyIPCService.cpp | 425 --- dom/telephony/ipc/TelephonyIPCService.h | 48 - dom/telephony/ipc/TelephonyParent.cpp | 523 ---- dom/telephony/ipc/TelephonyParent.h | 140 - dom/telephony/ipc/TelephonyTypes.ipdlh | 31 - dom/telephony/moz.build | 81 - dom/telephony/nsIGonkTelephonyService.idl | 27 - dom/telephony/nsITelephonyAudioService.idl | 31 - dom/telephony/nsITelephonyCallInfo.idl | 81 - dom/telephony/nsITelephonyMessenger.idl | 54 - dom/telephony/nsITelephonyService.idl | 255 -- dom/telephony/test/marionette/head.js | 1677 ----------- dom/telephony/test/marionette/manifest.ini | 69 - .../test/marionette/test_TelephonyUtils.js | 100 - .../test_audiomanager_phonestate.js | 94 - .../test/marionette/test_call_mute.js | 21 - .../test/marionette/test_call_presentation.js | 71 - .../test/marionette/test_cdma_call_waiting.js | 288 -- .../marionette/test_conference_add_error.js | 71 - .../test_conference_add_twice_error.js | 48 - .../test_conference_remove_error.js | 68 - .../test_conference_three_hangup_one.js | 35 - .../test_conference_three_remove_one.js | 39 - .../marionette/test_conference_two_calls.js | 28 - .../test_conference_two_hangup_all.js | 54 - .../test_conference_two_hangup_one.js | 33 - .../test_conference_two_hold_resume.js | 40 - .../test_conference_two_remove_one.js | 35 - .../test/marionette/test_consecutive_hold.js | 52 - .../test/marionette/test_crash_emulator.js | 26 - .../test_dsds_connection_conflict.js | 51 - .../test/marionette/test_dsds_normal_call.js | 78 - dom/telephony/test/marionette/test_dtmf.js | 69 - .../test/marionette/test_emergency.js | 39 - .../test/marionette/test_emergency_label.js | 72 - ...test_gsm_cdma_incoming_basic_operations.js | 170 -- ...test_gsm_cdma_outgoing_basic_operations.js | 174 -- .../marionette/test_incall_mmi_call_hold.js | 88 - .../test_incall_mmi_call_waiting.js | 77 - .../marionette/test_incall_mmi_conference.js | 90 - .../test/marionette/test_incall_mmi_imei.js | 38 - .../test_incoming_already_connected.js | 47 - .../marionette/test_incoming_already_held.js | 45 - ...t_incoming_answer_hangup_oncallschanged.js | 30 - .../marionette/test_incoming_onstatechange.js | 34 - .../test/marionette/test_mmi_call_barring.js | 98 - .../marionette/test_mmi_call_forwarding.js | 190 -- .../test/marionette/test_mmi_call_waiting.js | 44 - .../test_mmi_change_barring_password.js | 100 - .../test/marionette/test_mmi_change_pin.js | 113 - .../test/marionette/test_mmi_change_pin2.js | 105 - .../test/marionette/test_mmi_clip.js | 42 - .../test/marionette/test_mmi_clir.js | 44 - .../test/marionette/test_mmi_imei.js | 30 - .../test/marionette/test_mmi_unlock_puk.js | 157 - .../test/marionette/test_mmi_unlock_puk2.js | 44 - .../test/marionette/test_mmi_ussd.js | 23 - .../test/marionette/test_modem_switch_tech.js | 54 - .../test/marionette/test_multiple_hold.js | 61 - .../marionette/test_outgoing_already_held.js | 41 - ...t_outgoing_answer_hangup_oncallschanged.js | 40 - .../test_outgoing_answer_radio_off.js | 26 - .../marionette/test_outgoing_auto_hold.js | 93 - .../marionette/test_outgoing_badNumber.js | 40 - .../test/marionette/test_outgoing_busy.js | 28 - .../test/marionette/test_outgoing_from_stk.js | 65 - .../marionette/test_outgoing_onstatechange.js | 38 - .../marionette/test_outgoing_radio_off.js | 57 - .../test_outgoing_when_two_calls_on_line.js | 32 - dom/telephony/test/marionette/test_ready.js | 35 - .../marionette/test_redundant_operations.js | 49 - .../marionette/test_swap_held_and_active.js | 42 - ...est_system_message_telephony_call_ended.js | 104 - .../test_telephony_dsds_default_service_id.js | 127 - .../test/marionette/test_temporary_clir.js | 22 - dom/telephony/test/xpcshell/header_helpers.js | 9 - dom/telephony/test/xpcshell/test_parseMMI.js | 271 -- dom/telephony/test/xpcshell/xpcshell.ini | 5 - dom/webidl/CallEvent.webidl | 16 - dom/webidl/CallGroupErrorEvent.webidl | 20 - dom/webidl/CallsList.webidl | 11 - dom/webidl/MMICall.webidl | 12 - dom/webidl/Navigator.webidl | 5 - dom/webidl/Telephony.webidl | 77 - dom/webidl/TelephonyCall.webidl | 133 - dom/webidl/TelephonyCallGroup.webidl | 42 - dom/webidl/TelephonyCallId.webidl | 35 - dom/webidl/USSDReceivedEvent.webidl | 22 - dom/webidl/USSDSession.webidl | 16 - dom/webidl/moz.build | 10 - layout/build/moz.build | 1 - layout/build/nsLayoutModule.cpp | 8 - modules/libpref/init/all.js | 10 - .../harness/marionette/tests/webapi-tests.ini | 1 - 142 files changed, 15829 deletions(-) delete mode 100644 dom/permission/tests/test_telephony.html delete mode 100644 dom/telephony/CallsList.cpp delete mode 100644 dom/telephony/CallsList.h delete mode 100644 dom/telephony/MMICall.cpp delete mode 100644 dom/telephony/MMICall.h delete mode 100644 dom/telephony/Telephony.cpp delete mode 100644 dom/telephony/Telephony.h delete mode 100644 dom/telephony/TelephonyCall.cpp delete mode 100644 dom/telephony/TelephonyCall.h delete mode 100644 dom/telephony/TelephonyCallGroup.cpp delete mode 100644 dom/telephony/TelephonyCallGroup.h delete mode 100644 dom/telephony/TelephonyCallId.cpp delete mode 100644 dom/telephony/TelephonyCallId.h delete mode 100644 dom/telephony/TelephonyCallInfo.cpp delete mode 100644 dom/telephony/TelephonyCallInfo.h delete mode 100644 dom/telephony/TelephonyCallback.cpp delete mode 100644 dom/telephony/TelephonyCallback.h delete mode 100644 dom/telephony/TelephonyCommon.h delete mode 100644 dom/telephony/TelephonyDialCallback.cpp delete mode 100644 dom/telephony/TelephonyDialCallback.h delete mode 100644 dom/telephony/USSDSession.cpp delete mode 100644 dom/telephony/USSDSession.h delete mode 100644 dom/telephony/gonk/DialNumberUtils.jsm delete mode 100644 dom/telephony/gonk/TelephonyAudioService.js delete mode 100644 dom/telephony/gonk/TelephonyAudioService.manifest delete mode 100644 dom/telephony/gonk/TelephonyService.js delete mode 100644 dom/telephony/gonk/TelephonyService.manifest delete mode 100644 dom/telephony/gonk/TelephonyUtils.jsm delete mode 100644 dom/telephony/gonk/USSDReceivedWrapper.js delete mode 100644 dom/telephony/gonk/USSDReceivedWrapper.manifest delete mode 100644 dom/telephony/ipc/PTelephony.ipdl delete mode 100644 dom/telephony/ipc/PTelephonyRequest.ipdl delete mode 100644 dom/telephony/ipc/TelephonyChild.cpp delete mode 100644 dom/telephony/ipc/TelephonyChild.h delete mode 100644 dom/telephony/ipc/TelephonyIPCSerializer.h delete mode 100644 dom/telephony/ipc/TelephonyIPCService.cpp delete mode 100644 dom/telephony/ipc/TelephonyIPCService.h delete mode 100644 dom/telephony/ipc/TelephonyParent.cpp delete mode 100644 dom/telephony/ipc/TelephonyParent.h delete mode 100644 dom/telephony/ipc/TelephonyTypes.ipdlh delete mode 100644 dom/telephony/moz.build delete mode 100644 dom/telephony/nsIGonkTelephonyService.idl delete mode 100644 dom/telephony/nsITelephonyAudioService.idl delete mode 100644 dom/telephony/nsITelephonyCallInfo.idl delete mode 100644 dom/telephony/nsITelephonyMessenger.idl delete mode 100644 dom/telephony/nsITelephonyService.idl delete mode 100644 dom/telephony/test/marionette/head.js delete mode 100644 dom/telephony/test/marionette/manifest.ini delete mode 100644 dom/telephony/test/marionette/test_TelephonyUtils.js delete mode 100644 dom/telephony/test/marionette/test_audiomanager_phonestate.js delete mode 100644 dom/telephony/test/marionette/test_call_mute.js delete mode 100644 dom/telephony/test/marionette/test_call_presentation.js delete mode 100644 dom/telephony/test/marionette/test_cdma_call_waiting.js delete mode 100644 dom/telephony/test/marionette/test_conference_add_error.js delete mode 100644 dom/telephony/test/marionette/test_conference_add_twice_error.js delete mode 100644 dom/telephony/test/marionette/test_conference_remove_error.js delete mode 100644 dom/telephony/test/marionette/test_conference_three_hangup_one.js delete mode 100644 dom/telephony/test/marionette/test_conference_three_remove_one.js delete mode 100644 dom/telephony/test/marionette/test_conference_two_calls.js delete mode 100644 dom/telephony/test/marionette/test_conference_two_hangup_all.js delete mode 100644 dom/telephony/test/marionette/test_conference_two_hangup_one.js delete mode 100644 dom/telephony/test/marionette/test_conference_two_hold_resume.js delete mode 100644 dom/telephony/test/marionette/test_conference_two_remove_one.js delete mode 100644 dom/telephony/test/marionette/test_consecutive_hold.js delete mode 100644 dom/telephony/test/marionette/test_crash_emulator.js delete mode 100644 dom/telephony/test/marionette/test_dsds_connection_conflict.js delete mode 100644 dom/telephony/test/marionette/test_dsds_normal_call.js delete mode 100644 dom/telephony/test/marionette/test_dtmf.js delete mode 100644 dom/telephony/test/marionette/test_emergency.js delete mode 100644 dom/telephony/test/marionette/test_emergency_label.js delete mode 100644 dom/telephony/test/marionette/test_gsm_cdma_incoming_basic_operations.js delete mode 100644 dom/telephony/test/marionette/test_gsm_cdma_outgoing_basic_operations.js delete mode 100644 dom/telephony/test/marionette/test_incall_mmi_call_hold.js delete mode 100644 dom/telephony/test/marionette/test_incall_mmi_call_waiting.js delete mode 100644 dom/telephony/test/marionette/test_incall_mmi_conference.js delete mode 100644 dom/telephony/test/marionette/test_incall_mmi_imei.js delete mode 100644 dom/telephony/test/marionette/test_incoming_already_connected.js delete mode 100644 dom/telephony/test/marionette/test_incoming_already_held.js delete mode 100644 dom/telephony/test/marionette/test_incoming_answer_hangup_oncallschanged.js delete mode 100644 dom/telephony/test/marionette/test_incoming_onstatechange.js delete mode 100644 dom/telephony/test/marionette/test_mmi_call_barring.js delete mode 100644 dom/telephony/test/marionette/test_mmi_call_forwarding.js delete mode 100644 dom/telephony/test/marionette/test_mmi_call_waiting.js delete mode 100644 dom/telephony/test/marionette/test_mmi_change_barring_password.js delete mode 100644 dom/telephony/test/marionette/test_mmi_change_pin.js delete mode 100644 dom/telephony/test/marionette/test_mmi_change_pin2.js delete mode 100644 dom/telephony/test/marionette/test_mmi_clip.js delete mode 100644 dom/telephony/test/marionette/test_mmi_clir.js delete mode 100644 dom/telephony/test/marionette/test_mmi_imei.js delete mode 100644 dom/telephony/test/marionette/test_mmi_unlock_puk.js delete mode 100644 dom/telephony/test/marionette/test_mmi_unlock_puk2.js delete mode 100644 dom/telephony/test/marionette/test_mmi_ussd.js delete mode 100644 dom/telephony/test/marionette/test_modem_switch_tech.js delete mode 100644 dom/telephony/test/marionette/test_multiple_hold.js delete mode 100644 dom/telephony/test/marionette/test_outgoing_already_held.js delete mode 100644 dom/telephony/test/marionette/test_outgoing_answer_hangup_oncallschanged.js delete mode 100644 dom/telephony/test/marionette/test_outgoing_answer_radio_off.js delete mode 100644 dom/telephony/test/marionette/test_outgoing_auto_hold.js delete mode 100644 dom/telephony/test/marionette/test_outgoing_badNumber.js delete mode 100644 dom/telephony/test/marionette/test_outgoing_busy.js delete mode 100644 dom/telephony/test/marionette/test_outgoing_from_stk.js delete mode 100644 dom/telephony/test/marionette/test_outgoing_onstatechange.js delete mode 100644 dom/telephony/test/marionette/test_outgoing_radio_off.js delete mode 100644 dom/telephony/test/marionette/test_outgoing_when_two_calls_on_line.js delete mode 100644 dom/telephony/test/marionette/test_ready.js delete mode 100644 dom/telephony/test/marionette/test_redundant_operations.js delete mode 100644 dom/telephony/test/marionette/test_swap_held_and_active.js delete mode 100644 dom/telephony/test/marionette/test_system_message_telephony_call_ended.js delete mode 100644 dom/telephony/test/marionette/test_telephony_dsds_default_service_id.js delete mode 100644 dom/telephony/test/marionette/test_temporary_clir.js delete mode 100644 dom/telephony/test/xpcshell/header_helpers.js delete mode 100644 dom/telephony/test/xpcshell/test_parseMMI.js delete mode 100644 dom/telephony/test/xpcshell/xpcshell.ini delete mode 100644 dom/webidl/CallEvent.webidl delete mode 100644 dom/webidl/CallGroupErrorEvent.webidl delete mode 100644 dom/webidl/CallsList.webidl delete mode 100644 dom/webidl/MMICall.webidl delete mode 100644 dom/webidl/Telephony.webidl delete mode 100644 dom/webidl/TelephonyCall.webidl delete mode 100644 dom/webidl/TelephonyCallGroup.webidl delete mode 100644 dom/webidl/TelephonyCallId.webidl delete mode 100644 dom/webidl/USSDReceivedEvent.webidl delete mode 100644 dom/webidl/USSDSession.webidl diff --git a/b2g/components/ContentPermissionPrompt.js b/b2g/components/ContentPermissionPrompt.js index a82406a78610..e11b1b458566 100644 --- a/b2g/components/ContentPermissionPrompt.js +++ b/b2g/components/ContentPermissionPrompt.js @@ -33,11 +33,6 @@ var secMan = Cc["@mozilla.org/scriptsecuritymanager;1"].getService(Ci.nsIScriptS var permissionSpecificChecker = {}; -XPCOMUtils.defineLazyServiceGetter(this, - "TelephonyService", - "@mozilla.org/telephony/telephonyservice;1", - "nsITelephonyService"); - XPCOMUtils.defineLazyModuleGetter(this, "SystemAppProxy", "resource://gre/modules/SystemAppProxy.jsm"); @@ -454,22 +449,6 @@ ContentPermissionPrompt.prototype = { permissionSpecificChecker["audio-capture"] = function(request) { let forbid = false; - try { - // nsITelephonyService.enumerateCalls is synchronous. - TelephonyService.enumerateCalls({ - QueryInterface: XPCOMUtils.generateQI([Ci.nsITelephonyListener]), - enumerateCallStateComplete: function() {}, - enumerateCallState: function(callInfo) { - if (callInfo.callState == Ci.nsITelephonyService.CALL_STATE_CONNECTED) { - forbid = true; - } - }, - }); - } catch (e) { - // No restriction if Telephony service doesn't exist. - return false; - } - if (forbid) { request.cancel(); } diff --git a/b2g/installer/package-manifest.in b/b2g/installer/package-manifest.in index ed011c7e0f34..2591efd3ac30 100644 --- a/b2g/installer/package-manifest.in +++ b/b2g/installer/package-manifest.in @@ -193,7 +193,6 @@ @RESPATH@/components/dom_mobilemessage.xpt @RESPATH@/components/dom_storage.xpt @RESPATH@/components/dom_stylesheets.xpt -@RESPATH@/components/dom_telephony.xpt @RESPATH@/components/dom_threads.xpt @RESPATH@/components/dom_traversal.xpt @RESPATH@/components/dom_tv.xpt @@ -468,13 +467,7 @@ @RESPATH@/components/StkCmdFactory.manifest @RESPATH@/components/RILSystemMessengerHelper.js @RESPATH@/components/RILSystemMessengerHelper.manifest -@RESPATH@/components/TelephonyAudioService.js -@RESPATH@/components/TelephonyAudioService.manifest -@RESPATH@/components/USSDReceivedWrapper.js -@RESPATH@/components/USSDReceivedWrapper.manifest #ifndef DISABLE_MOZ_RIL_GEOLOC -@RESPATH@/components/TelephonyService.js -@RESPATH@/components/TelephonyService.manifest #endif #endif // MOZ_WIDGET_GONK && MOZ_B2G_RIL diff --git a/browser/installer/package-manifest.in b/browser/installer/package-manifest.in index 2f2c65ad48db..e2fa0b067f54 100644 --- a/browser/installer/package-manifest.in +++ b/browser/installer/package-manifest.in @@ -210,7 +210,6 @@ @RESPATH@/components/dom_sidebar.xpt @RESPATH@/components/dom_storage.xpt @RESPATH@/components/dom_stylesheets.xpt -@RESPATH@/components/dom_telephony.xpt @RESPATH@/components/dom_traversal.xpt #ifdef MOZ_WEBSPEECH @RESPATH@/components/dom_webspeechrecognition.xpt diff --git a/dom/apps/PermissionsTable.jsm b/dom/apps/PermissionsTable.jsm index f6ce950a18cb..dba3a60fdbf6 100644 --- a/dom/apps/PermissionsTable.jsm +++ b/dom/apps/PermissionsTable.jsm @@ -121,11 +121,6 @@ this.PermissionsTable = { geolocation: { privileged: ALLOW_ACTION, certified: ALLOW_ACTION }, - telephony: { - app: DENY_ACTION, - privileged: DENY_ACTION, - certified: ALLOW_ACTION - }, browser: { app: DENY_ACTION, privileged: ALLOW_ACTION, diff --git a/dom/base/Navigator.cpp b/dom/base/Navigator.cpp index a0b3ea665bff..9f73dd108cad 100644 --- a/dom/base/Navigator.cpp +++ b/dom/base/Navigator.cpp @@ -47,7 +47,6 @@ #include "mozilla/dom/ServiceWorkerContainer.h" #include "mozilla/dom/StorageManager.h" #include "mozilla/dom/TCPSocket.h" -#include "mozilla/dom/Telephony.h" #include "mozilla/dom/VRDisplay.h" #include "mozilla/dom/workers/RuntimeService.h" #include "mozilla/Hal.h" @@ -216,7 +215,6 @@ NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(Navigator) NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mBatteryPromise) NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mPowerManager) NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mIccManager) - NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mTelephony) NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mInputPortManager) NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mConnection) NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mStorageManager) @@ -291,10 +289,6 @@ Navigator::Invalidate() mIccManager = nullptr; } - if (mTelephony) { - mTelephony = nullptr; - } - if (mInputPortManager) { mInputPortManager = nullptr; } @@ -1624,20 +1618,6 @@ Navigator::RequestWakeLock(const nsAString &aTopic, ErrorResult& aRv) return pmService->NewWakeLock(aTopic, mWindow, aRv); } -Telephony* -Navigator::GetMozTelephony(ErrorResult& aRv) -{ - if (!mTelephony) { - if (!mWindow) { - aRv.Throw(NS_ERROR_UNEXPECTED); - return nullptr; - } - mTelephony = Telephony::Create(mWindow, aRv); - } - - return mTelephony; -} - InputPortManager* Navigator::GetInputPortManager(ErrorResult& aRv) { diff --git a/dom/base/Navigator.h b/dom/base/Navigator.h index f19dad9c1d69..39980121325b 100644 --- a/dom/base/Navigator.h +++ b/dom/base/Navigator.h @@ -84,7 +84,6 @@ class MobileConnectionArray; class PowerManager; class IccManager; -class Telephony; class InputPortManager; class DeviceStorageAreaListener; class Presentation; @@ -222,7 +221,6 @@ public: DesktopNotificationCenter* GetMozNotification(ErrorResult& aRv); IccManager* GetMozIccManager(ErrorResult& aRv); - Telephony* GetMozTelephony(ErrorResult& aRv); InputPortManager* GetInputPortManager(ErrorResult& aRv); already_AddRefed MozTCPSocket(); network::Connection* GetConnection(ErrorResult& aRv); @@ -323,7 +321,6 @@ private: RefPtr mBatteryPromise; RefPtr mPowerManager; RefPtr mIccManager; - RefPtr mTelephony; RefPtr mInputPortManager; RefPtr mConnection; #ifdef MOZ_B2G_RIL diff --git a/dom/ipc/ContentChild.cpp b/dom/ipc/ContentChild.cpp index 806efa234c27..c324b5246c1a 100644 --- a/dom/ipc/ContentChild.cpp +++ b/dom/ipc/ContentChild.cpp @@ -189,7 +189,6 @@ #include "nsDeviceStorage.h" #include "DomainPolicy.h" #include "mozilla/dom/ipc/StructuredCloneData.h" -#include "mozilla/dom/telephony/PTelephonyChild.h" #include "mozilla/dom/time/DateCacheCleaner.h" #include "mozilla/net/NeckoMessageUtils.h" #include "mozilla/widget/PuppetBidiKeyboard.h" @@ -207,7 +206,6 @@ using namespace mozilla::dom::devicestorage; using namespace mozilla::dom::icc; using namespace mozilla::dom::ipc; using namespace mozilla::dom::mobileconnection; -using namespace mozilla::dom::telephony; using namespace mozilla::dom::workers; using namespace mozilla::media; using namespace mozilla::embedding; @@ -1979,19 +1977,6 @@ bool ContentChild::DeallocPHandlerServiceChild(PHandlerServiceChild* aHandlerSer return true; } -PTelephonyChild* -ContentChild::AllocPTelephonyChild() -{ - MOZ_CRASH("No one should be allocating PTelephonyChild actors"); -} - -bool -ContentChild::DeallocPTelephonyChild(PTelephonyChild* aActor) -{ - delete aActor; - return true; -} - media::PMediaChild* ContentChild::AllocPMediaChild() { diff --git a/dom/ipc/ContentChild.h b/dom/ipc/ContentChild.h index 5627391b6d4a..603f111025f9 100644 --- a/dom/ipc/ContentChild.h +++ b/dom/ipc/ContentChild.h @@ -335,10 +335,6 @@ public: virtual bool DeallocPHandlerServiceChild(PHandlerServiceChild*) override; - virtual PTelephonyChild* AllocPTelephonyChild() override; - - virtual bool DeallocPTelephonyChild(PTelephonyChild*) override; - virtual PMediaChild* AllocPMediaChild() override; virtual bool DeallocPMediaChild(PMediaChild* aActor) override; diff --git a/dom/ipc/ContentParent.cpp b/dom/ipc/ContentParent.cpp index 7535ab49257d..dd997c81315a 100644 --- a/dom/ipc/ContentParent.cpp +++ b/dom/ipc/ContentParent.cpp @@ -68,7 +68,6 @@ #include "mozilla/dom/PushNotifier.h" #include "mozilla/dom/FlyWebPublishedServerIPC.h" #include "mozilla/dom/quota/QuotaManagerService.h" -#include "mozilla/dom/telephony/TelephonyParent.h" #include "mozilla/dom/time/DateCacheCleaner.h" #include "mozilla/embedding/printingui/PrintingParent.h" #include "mozilla/gfx/gfxVars.h" @@ -291,7 +290,6 @@ using namespace mozilla::dom::devicestorage; using namespace mozilla::dom::icc; using namespace mozilla::dom::power; using namespace mozilla::dom::mobileconnection; -using namespace mozilla::dom::telephony; using namespace mozilla::media; using namespace mozilla::embedding; using namespace mozilla::gfx; @@ -3430,25 +3428,6 @@ ContentParent::DeallocPHandlerServiceParent(PHandlerServiceParent* aHandlerServi return true; } -PTelephonyParent* -ContentParent::AllocPTelephonyParent() -{ - if (!AssertAppProcessPermission(this, "telephony")) { - return nullptr; - } - - TelephonyParent* actor = new TelephonyParent(); - NS_ADDREF(actor); - return actor; -} - -bool -ContentParent::DeallocPTelephonyParent(PTelephonyParent* aActor) -{ - static_cast(aActor)->Release(); - return true; -} - media::PMediaParent* ContentParent::AllocPMediaParent() { diff --git a/dom/ipc/ContentParent.h b/dom/ipc/ContentParent.h index 03fe75601a12..21386fb7bfc1 100644 --- a/dom/ipc/ContentParent.h +++ b/dom/ipc/ContentParent.h @@ -843,10 +843,6 @@ private: virtual bool DeallocPHandlerServiceParent(PHandlerServiceParent*) override; - virtual PTelephonyParent* AllocPTelephonyParent() override; - - virtual bool DeallocPTelephonyParent(PTelephonyParent*) override; - virtual PMediaParent* AllocPMediaParent() override; virtual bool DeallocPMediaParent(PMediaParent* aActor) override; diff --git a/dom/ipc/PContent.ipdl b/dom/ipc/PContent.ipdl index 4a24f804a7b6..7934ed7fc79b 100644 --- a/dom/ipc/PContent.ipdl +++ b/dom/ipc/PContent.ipdl @@ -44,7 +44,6 @@ include protocol PScreenManager; include protocol PSharedBufferManager; include protocol PSpeechSynthesis; include protocol PStorage; -include protocol PTelephony; include protocol PTestShell; include protocol PJavaScript; include protocol PRemoteSpellcheckEngine; @@ -372,7 +371,6 @@ nested(upto inside_cpow) sync protocol PContent manages PScreenManager; manages PSpeechSynthesis; manages PStorage; - manages PTelephony; manages PTestShell; manages PJavaScript; manages PRemoteSpellcheckEngine; @@ -819,8 +817,6 @@ parent: nested(inside_cpow) async PStorage(); - async PTelephony(); - async PMedia(); async PBluetooth(); diff --git a/dom/moz.build b/dom/moz.build index ba0d541aa502..6ec229fde158 100644 --- a/dom/moz.build +++ b/dom/moz.build @@ -93,7 +93,6 @@ DIRS += [ 'messagechannel', 'promise', 'smil', - 'telephony', 'url', 'inputmethod', 'webidl', diff --git a/dom/permission/tests/mochitest-ril.ini b/dom/permission/tests/mochitest-ril.ini index bb14a2bbffd7..2a2c15e2d33d 100644 --- a/dom/permission/tests/mochitest-ril.ini +++ b/dom/permission/tests/mochitest-ril.ini @@ -1,4 +1,3 @@ [test_cellbroadcast.html] [test_mobileconnection.html] [test_networkstats-manage.html] -[test_telephony.html] diff --git a/dom/permission/tests/test_telephony.html b/dom/permission/tests/test_telephony.html deleted file mode 100644 index 1c0917ec6926..000000000000 --- a/dom/permission/tests/test_telephony.html +++ /dev/null @@ -1,32 +0,0 @@ - - - - - - Test for Bug 815105 - - - - -Mozilla Bug 815105 -

- -
-
-
-
- - - diff --git a/dom/telephony/CallsList.cpp b/dom/telephony/CallsList.cpp deleted file mode 100644 index 0530f26ffdfe..000000000000 --- a/dom/telephony/CallsList.cpp +++ /dev/null @@ -1,76 +0,0 @@ -/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ -/* vim: set ts=8 sts=2 et sw=2 tw=80: */ -/* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ - -#include "CallsList.h" -#include "mozilla/dom/CallsListBinding.h" - -#include "Telephony.h" -#include "TelephonyCall.h" -#include "TelephonyCallGroup.h" - -using namespace mozilla::dom; - -NS_IMPL_CYCLE_COLLECTION_WRAPPERCACHE(CallsList, - mTelephony, - mGroup) - -NS_IMPL_CYCLE_COLLECTING_ADDREF(CallsList) -NS_IMPL_CYCLE_COLLECTING_RELEASE(CallsList) - -NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(CallsList) - NS_WRAPPERCACHE_INTERFACE_MAP_ENTRY - NS_INTERFACE_MAP_ENTRY(nsISupports) -NS_INTERFACE_MAP_END - -CallsList::CallsList(Telephony* aTelephony, TelephonyCallGroup* aGroup) -: mTelephony(aTelephony), mGroup(aGroup) -{ - MOZ_ASSERT(mTelephony); -} - -CallsList::~CallsList() -{ -} - -nsPIDOMWindowInner* -CallsList::GetParentObject() const -{ - return mTelephony->GetOwner(); -} - -JSObject* -CallsList::WrapObject(JSContext* aCx, JS::Handle aGivenProto) -{ - return CallsListBinding::Wrap(aCx, this, aGivenProto); -} - -already_AddRefed -CallsList::Item(uint32_t aIndex) const -{ - RefPtr call; - call = mGroup ? mGroup->CallsArray().SafeElementAt(aIndex) : - mTelephony->CallsArray().SafeElementAt(aIndex); - - return call.forget(); -} - -uint32_t -CallsList::Length() const -{ - return mGroup ? mGroup->CallsArray().Length() : - mTelephony->CallsArray().Length(); -} - -already_AddRefed -CallsList::IndexedGetter(uint32_t aIndex, bool& aFound) const -{ - RefPtr call; - call = mGroup ? mGroup->CallsArray().SafeElementAt(aIndex) : - mTelephony->CallsArray().SafeElementAt(aIndex); - aFound = call ? true : false; - - return call.forget(); -} diff --git a/dom/telephony/CallsList.h b/dom/telephony/CallsList.h deleted file mode 100644 index 611e36b54344..000000000000 --- a/dom/telephony/CallsList.h +++ /dev/null @@ -1,53 +0,0 @@ -/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ -/* vim: set ts=8 sts=2 et sw=2 tw=80: */ -/* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ - -#ifndef mozilla_dom_telephony_CallsList_h__ -#define mozilla_dom_telephony_CallsList_h__ - -#include "mozilla/dom/telephony/TelephonyCommon.h" - -#include "nsWrapperCache.h" - -namespace mozilla { -namespace dom { - -class CallsList final : public nsISupports, - public nsWrapperCache -{ - RefPtr mTelephony; - RefPtr mGroup; - -public: - NS_DECL_CYCLE_COLLECTING_ISUPPORTS - NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_CLASS(CallsList) - - explicit CallsList(Telephony* aTelephony, TelephonyCallGroup* aGroup = nullptr); - - nsPIDOMWindowInner* - GetParentObject() const; - - // WrapperCache - virtual JSObject* - WrapObject(JSContext* aCx, JS::Handle aGivenProto) override; - - // CallsList WebIDL - already_AddRefed - Item(uint32_t aIndex) const; - - uint32_t - Length() const; - - already_AddRefed - IndexedGetter(uint32_t aIndex, bool& aFound) const; - -private: - ~CallsList(); -}; - -} // namespace dom -} // namespace mozilla - -#endif // mozilla_dom_telephony_CallsList_h__ diff --git a/dom/telephony/MMICall.cpp b/dom/telephony/MMICall.cpp deleted file mode 100644 index 24c5bdfadcac..000000000000 --- a/dom/telephony/MMICall.cpp +++ /dev/null @@ -1,79 +0,0 @@ -/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ -/* vim: set ts=8 sts=2 et sw=2 tw=80: */ -/* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ - -#include "mozilla/dom/MMICall.h" - -#include "mozilla/dom/MMICallBinding.h" -#include "nsIGlobalObject.h" - -using namespace mozilla::dom; -using mozilla::ErrorResult; - -NS_IMPL_CYCLE_COLLECTION_WRAPPERCACHE(MMICall, mWindow) -NS_IMPL_CYCLE_COLLECTING_ADDREF(MMICall) -NS_IMPL_CYCLE_COLLECTING_RELEASE(MMICall) -NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(MMICall) - NS_WRAPPERCACHE_INTERFACE_MAP_ENTRY - NS_INTERFACE_MAP_ENTRY(nsISupports) -NS_INTERFACE_MAP_END - -MMICall::MMICall(nsPIDOMWindowInner* aWindow, const nsAString& aServiceCode) - : mWindow(aWindow), mServiceCode(aServiceCode) -{ - nsCOMPtr global = do_QueryInterface(mWindow); - if (!global) { - return; - } - - ErrorResult rv; - RefPtr promise = Promise::Create(global, rv); - if (rv.Failed()) { - rv.SuppressException(); - return; - } - - mPromise = promise; -} - -MMICall::~MMICall() -{ -} - -nsPIDOMWindowInner* -MMICall::GetParentObject() const -{ - return mWindow; -} - -JSObject* -MMICall::WrapObject(JSContext* aCx, JS::Handle aGivenProto) -{ - return MMICallBinding::Wrap(aCx, this, aGivenProto); -} - -void -MMICall::NotifyResult(JS::Handle aResult) -{ - if (!mPromise) { - return; - } - - mPromise->MaybeResolve(aResult); -} - -// WebIDL - -already_AddRefed -MMICall::GetResult(ErrorResult& aRv) -{ - if (!mPromise) { - aRv.Throw(NS_ERROR_UNEXPECTED); - return nullptr; - } - - RefPtr promise = mPromise; - return promise.forget(); -} diff --git a/dom/telephony/MMICall.h b/dom/telephony/MMICall.h deleted file mode 100644 index 0cf1e0445a0b..000000000000 --- a/dom/telephony/MMICall.h +++ /dev/null @@ -1,59 +0,0 @@ -/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ -/* vim: set ts=8 sts=2 et sw=2 tw=80: */ -/* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ - -#ifndef mozilla_dom_MMICall_h -#define mozilla_dom_MMICall_h - -#include "mozilla/Attributes.h" -#include "mozilla/ErrorResult.h" -#include "mozilla/dom/BindingDeclarations.h" -#include "mozilla/dom/Promise.h" -#include "mozilla/dom/ToJSValue.h" -#include "nsCOMPtr.h" -#include "nsCycleCollectionParticipant.h" -#include "nsJSUtils.h" -#include "nsWrapperCache.h" - -struct JSContext; -class nsPIDOMWindowInner; - -namespace mozilla { -namespace dom { - -class MMICall final : public nsISupports, - public nsWrapperCache -{ -public: - NS_DECL_CYCLE_COLLECTING_ISUPPORTS - NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_CLASS(MMICall) - - MMICall(nsPIDOMWindowInner* aWindow, const nsAString& aServiceCode); - - nsPIDOMWindowInner* - GetParentObject() const; - - virtual JSObject* - WrapObject(JSContext* aCx, JS::Handle aGivenProto) override; - - void - NotifyResult(JS::Handle aResult); - - // WebIDL - already_AddRefed - GetResult(ErrorResult& aRv); - -private: - ~MMICall(); - - nsCOMPtr mWindow; - nsString mServiceCode; - RefPtr mPromise; -}; - -} // namespace dom -} // namespace mozilla - -#endif // mozilla_dom_MMICall_h diff --git a/dom/telephony/Telephony.cpp b/dom/telephony/Telephony.cpp deleted file mode 100644 index e78ee18d0699..000000000000 --- a/dom/telephony/Telephony.cpp +++ /dev/null @@ -1,870 +0,0 @@ -/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ -/* vim: set ts=8 sts=2 et sw=2 tw=80: */ -/* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ - -#include "Telephony.h" - -#include "mozilla/Preferences.h" -#include "mozilla/dom/CallEvent.h" -#include "mozilla/dom/MozMobileConnectionBinding.h" -#include "mozilla/dom/Promise.h" -#include "mozilla/dom/TelephonyBinding.h" -#include "mozilla/Unused.h" - -#include "nsCharSeparatedTokenizer.h" -#include "nsContentUtils.h" -#include "nsIPermissionManager.h" -#include "nsIURI.h" -#include "nsPIDOMWindow.h" -#include "nsServiceManagerUtils.h" -#include "nsThreadUtils.h" - -#include "CallsList.h" -#include "TelephonyCall.h" -#include "TelephonyCallGroup.h" -#include "TelephonyCallId.h" -#include "TelephonyDialCallback.h" - -// Service instantiation -#include "ipc/TelephonyIPCService.h" -#if defined(MOZ_WIDGET_GONK) && defined(MOZ_B2G_RIL) -#include "nsIGonkTelephonyService.h" -#endif -#include "nsXULAppAPI.h" // For XRE_GetProcessType() - -using namespace mozilla::dom; -using namespace mozilla::dom::telephony; -using mozilla::ErrorResult; - -class Telephony::Listener : public nsITelephonyListener -{ - Telephony* mTelephony; - - virtual ~Listener() {} - -public: - NS_DECL_ISUPPORTS - NS_FORWARD_SAFE_NSITELEPHONYLISTENER(mTelephony) - - explicit Listener(Telephony* aTelephony) - : mTelephony(aTelephony) - { - MOZ_ASSERT(mTelephony); - } - - void - Disconnect() - { - MOZ_ASSERT(mTelephony); - mTelephony = nullptr; - } -}; - -Telephony::Telephony(nsPIDOMWindowInner* aOwner) - : DOMEventTargetHelper(aOwner), - mIsAudioStartPlaying(false), - mHaveDispatchedInterruptBeginEvent(false), - mMuted(AudioChannelService::IsAudioChannelMutedByDefault()) -{ - MOZ_ASSERT(aOwner); - nsCOMPtr global = do_QueryInterface(aOwner); - MOZ_ASSERT(global); - - ErrorResult rv; - RefPtr promise = Promise::Create(global, rv); - MOZ_ASSERT(!rv.Failed()); - - mReadyPromise = promise; -} - -Telephony::~Telephony() -{ - Shutdown(); -} - -void -Telephony::Shutdown() -{ - if (mListener) { - mListener->Disconnect(); - - if (mService) { - mService->UnregisterListener(mListener); - mService = nullptr; - } - - mListener = nullptr; - } -} - -JSObject* -Telephony::WrapObject(JSContext* aCx, JS::Handle aGivenProto) -{ - return TelephonyBinding::Wrap(aCx, this, aGivenProto); -} - -// static -already_AddRefed -Telephony::Create(nsPIDOMWindowInner* aOwner, ErrorResult& aRv) -{ - NS_ASSERTION(aOwner, "Null owner!"); - - nsCOMPtr ril = - do_GetService(TELEPHONY_SERVICE_CONTRACTID); - if (!ril) { - aRv.Throw(NS_ERROR_UNEXPECTED); - return nullptr; - } - - nsCOMPtr sgo = do_QueryInterface(aOwner); - if (!sgo) { - aRv.Throw(NS_ERROR_UNEXPECTED); - return nullptr; - } - - nsCOMPtr scriptContext = sgo->GetContext(); - if (!scriptContext) { - aRv.Throw(NS_ERROR_UNEXPECTED); - return nullptr; - } - - RefPtr telephony = new Telephony(aOwner); - - telephony->mService = ril; - telephony->mListener = new Listener(telephony); - telephony->mCallsList = new CallsList(telephony); - telephony->mGroup = TelephonyCallGroup::Create(telephony); - - nsresult rv = ril->EnumerateCalls(telephony->mListener); - if (NS_FAILED(rv)) { - aRv.Throw(rv); - return nullptr; - } - - return telephony.forget(); -} - -// static -bool -Telephony::IsValidNumber(const nsAString& aNumber) -{ - return !aNumber.IsEmpty(); -} - -// static -uint32_t -Telephony::GetNumServices() { - return mozilla::Preferences::GetInt("ril.numRadioInterfaces", 1); -} - -// static -bool -Telephony::IsValidServiceId(uint32_t aServiceId) -{ - return aServiceId < GetNumServices(); -} - -uint32_t -Telephony::GetServiceId(const Optional& aServiceId, - bool aGetIfActiveCall) -{ - if (aServiceId.WasPassed()) { - return aServiceId.Value(); - } else if (aGetIfActiveCall) { - nsTArray > &calls = mCalls; - if (mGroup->IsActive()) { - calls = mGroup->CallsArray(); - } - for (uint32_t i = 0; i < calls.Length(); i++) { - if (calls[i]->IsActive()) { - return calls[i]->mServiceId; - } - } - } - - uint32_t serviceId = 0; - mService->GetDefaultServiceId(&serviceId); - return serviceId; -} - -already_AddRefed -Telephony::DialInternal(uint32_t aServiceId, const nsAString& aNumber, - bool aEmergency, ErrorResult& aRv) -{ - nsCOMPtr global = do_QueryInterface(GetOwner()); - if (!global) { - return nullptr; - } - - RefPtr promise = Promise::Create(global, aRv); - if (aRv.Failed()) { - return nullptr; - } - - if (!IsValidNumber(aNumber) || !IsValidServiceId(aServiceId)) { - promise->MaybeReject(NS_ERROR_DOM_INVALID_ACCESS_ERR); - return promise.forget(); - } - - nsCOMPtr callback = - new TelephonyDialCallback(GetOwner(), this, promise); - - nsresult rv = mService->Dial(aServiceId, aNumber, aEmergency, callback); - if (NS_FAILED(rv)) { - promise->MaybeReject(NS_ERROR_DOM_INVALID_STATE_ERR); - return promise.forget(); - } - - return promise.forget(); -} - -already_AddRefed -Telephony::CreateCallId(nsITelephonyCallInfo *aInfo) -{ - nsAutoString number; - nsAutoString name; - uint16_t numberPresentation; - uint16_t namePresentation; - - aInfo->GetNumber(number); - aInfo->GetName(name); - aInfo->GetNumberPresentation(&numberPresentation); - aInfo->GetNamePresentation(&namePresentation); - - return CreateCallId(number, numberPresentation, name, namePresentation); -} - -already_AddRefed -Telephony::CreateCallId(const nsAString& aNumber, uint16_t aNumberPresentation, - const nsAString& aName, uint16_t aNamePresentation) -{ - RefPtr id = - new TelephonyCallId(GetOwner(), aNumber, aNumberPresentation, - aName, aNamePresentation); - - return id.forget(); -} - -already_AddRefed -Telephony::CreateCall(TelephonyCallId* aId, uint32_t aServiceId, - uint32_t aCallIndex, TelephonyCallState aState, - bool aEmergency, bool aConference, - bool aSwitchable, bool aMergeable) -{ - // We don't have to create an already ended call. - if (aState == TelephonyCallState::Disconnected) { - return nullptr; - } - - RefPtr call = - TelephonyCall::Create(this, aId, aServiceId, aCallIndex, aState, - aEmergency, aConference, aSwitchable, aMergeable); - - NS_ASSERTION(call, "This should never fail!"); - NS_ASSERTION(aConference ? mGroup->CallsArray().Contains(call) - : mCalls.Contains(call), - "Should have auto-added new call!"); - - return call.forget(); -} - -nsresult -Telephony::NotifyEvent(const nsAString& aType) -{ - return DispatchCallEvent(aType, nullptr); -} - -nsresult -Telephony::NotifyCallsChanged(TelephonyCall* aCall) -{ - return DispatchCallEvent(NS_LITERAL_STRING("callschanged"), aCall); -} - -already_AddRefed -Telephony::GetCall(uint32_t aServiceId, uint32_t aCallIndex) -{ - RefPtr call; - - for (uint32_t i = 0; i < mCalls.Length(); i++) { - RefPtr& tempCall = mCalls[i]; - if (tempCall->ServiceId() == aServiceId && - tempCall->CallIndex() == aCallIndex) { - call = tempCall; - break; - } - } - - return call.forget(); -} - -already_AddRefed -Telephony::GetCallFromEverywhere(uint32_t aServiceId, uint32_t aCallIndex) -{ - RefPtr call = GetCall(aServiceId, aCallIndex); - - if (!call) { - call = mGroup->GetCall(aServiceId, aCallIndex); - } - - return call.forget(); -} - -nsresult -Telephony::HandleCallInfo(nsITelephonyCallInfo* aInfo) -{ - uint32_t serviceId; - uint32_t callIndex; - uint16_t callState; - bool isEmergency; - bool isConference; - bool isSwitchable; - bool isMergeable; - - aInfo->GetClientId(&serviceId); - aInfo->GetCallIndex(&callIndex); - aInfo->GetCallState(&callState); - aInfo->GetIsEmergency(&isEmergency); - aInfo->GetIsConference(&isConference); - aInfo->GetIsSwitchable(&isSwitchable); - aInfo->GetIsMergeable(&isMergeable); - - TelephonyCallState state = TelephonyCall::ConvertToTelephonyCallState(callState); - - RefPtr call = GetCallFromEverywhere(serviceId, callIndex); - // Handle a newly created call. - if (!call) { - RefPtr id = CreateCallId(aInfo); - call = CreateCall(id, serviceId, callIndex, state, isEmergency, - isConference, isSwitchable, isMergeable); - // The newly created call is an incoming call. - if (call && - state == TelephonyCallState::Incoming) { - nsresult rv = DispatchCallEvent(NS_LITERAL_STRING("incoming"), call); - NS_ENSURE_SUCCESS(rv, rv); - } - return NS_OK; - } - - // Update an existing call - call->UpdateEmergency(isEmergency); - call->UpdateSwitchable(isSwitchable); - call->UpdateMergeable(isMergeable); - - nsAutoString number; - aInfo->GetNumber(number); - RefPtr id = call->Id(); - id->UpdateNumber(number); - - nsAutoString disconnectedReason; - aInfo->GetDisconnectedReason(disconnectedReason); - - // State changed. - if (call->State() != state) { - if (state == TelephonyCallState::Disconnected) { - call->UpdateDisconnectedReason(disconnectedReason); - call->ChangeState(TelephonyCallState::Disconnected); - return NS_OK; - } - - // We don't fire the statechange event on a call in conference here. - // Instead, the event will be fired later in - // TelephonyCallGroup::ChangeState(). Thus the sequence of firing the - // statechange events is guaranteed: first on TelephonyCallGroup then on - // individual TelephonyCall objects. - bool fireEvent = !isConference; - call->ChangeStateInternal(state, fireEvent); - } - - // Group changed. - RefPtr group = call->GetGroup(); - - if (!group && isConference) { - // Add to conference. - NS_ASSERTION(mCalls.Contains(call), "Should in mCalls"); - mGroup->AddCall(call); - RemoveCall(call); - } else if (group && !isConference) { - // Remove from conference. - NS_ASSERTION(mGroup->CallsArray().Contains(call), "Should in mGroup"); - mGroup->RemoveCall(call); - AddCall(call); - } - - return NS_OK; -} - -NS_IMPL_CYCLE_COLLECTION_CLASS(Telephony) - -NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_INHERITED(Telephony, - DOMEventTargetHelper) - NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mCalls) - NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mCallsList) - NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mGroup) - NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mReadyPromise) -NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END - -NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN_INHERITED(Telephony, - DOMEventTargetHelper) - tmp->Shutdown(); - NS_IMPL_CYCLE_COLLECTION_UNLINK(mCalls) - NS_IMPL_CYCLE_COLLECTION_UNLINK(mCallsList) - NS_IMPL_CYCLE_COLLECTION_UNLINK(mGroup) - NS_IMPL_CYCLE_COLLECTION_UNLINK(mReadyPromise) -NS_IMPL_CYCLE_COLLECTION_UNLINK_END - -NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION_INHERITED(Telephony) - // Telephony does not expose nsITelephonyListener. mListener is the exposed - // nsITelephonyListener and forwards the calls it receives to us. -NS_INTERFACE_MAP_END_INHERITING(DOMEventTargetHelper) - -NS_IMPL_ADDREF_INHERITED(Telephony, DOMEventTargetHelper) -NS_IMPL_RELEASE_INHERITED(Telephony, DOMEventTargetHelper) - -NS_IMPL_ISUPPORTS(Telephony::Listener, nsITelephonyListener) - -// Telephony WebIDL - -already_AddRefed -Telephony::Dial(const nsAString& aNumber, const Optional& aServiceId, - ErrorResult& aRv) -{ - uint32_t serviceId = GetServiceId(aServiceId); - RefPtr promise = DialInternal(serviceId, aNumber, false, aRv); - return promise.forget(); -} - -already_AddRefed -Telephony::DialEmergency(const nsAString& aNumber, - const Optional& aServiceId, - ErrorResult& aRv) -{ - uint32_t serviceId = GetServiceId(aServiceId); - RefPtr promise = DialInternal(serviceId, aNumber, true, aRv); - return promise.forget(); -} - -already_AddRefed -Telephony::SendTones(const nsAString& aDTMFChars, - uint32_t aPauseDuration, - uint32_t aToneDuration, - const Optional& aServiceId, - ErrorResult& aRv) -{ - uint32_t serviceId = GetServiceId(aServiceId, - true /* aGetIfActiveCall */); - - nsCOMPtr global = do_QueryInterface(GetOwner()); - if (!global) { - return nullptr; - } - - RefPtr promise = Promise::Create(global, aRv); - if (aRv.Failed()) { - return nullptr; - } - - if (aDTMFChars.IsEmpty()) { - NS_WARNING("Empty tone string will be ignored"); - promise->MaybeReject(NS_ERROR_DOM_INVALID_ACCESS_ERR); - return promise.forget(); - } - - if (!IsValidServiceId(serviceId)) { - aRv.Throw(NS_ERROR_INVALID_ARG); - promise->MaybeReject(NS_ERROR_DOM_INVALID_ACCESS_ERR); - return promise.forget(); - } - - nsCOMPtr callback = - new TelephonyCallback(promise); - - aRv = mService->SendTones(serviceId, aDTMFChars, aPauseDuration, - aToneDuration, callback); - return promise.forget(); -} - -void -Telephony::StartTone(const nsAString& aDTMFChar, - const Optional& aServiceId, - ErrorResult& aRv) -{ - uint32_t serviceId = GetServiceId(aServiceId, - true /* aGetIfActiveCall */); - - if (aDTMFChar.IsEmpty()) { - NS_WARNING("Empty tone string will be ignored"); - return; - } - - if (aDTMFChar.Length() > 1 || !IsValidServiceId(serviceId)) { - aRv.Throw(NS_ERROR_INVALID_ARG); - return; - } - - aRv = mService->StartTone(serviceId, aDTMFChar); -} - -void -Telephony::StopTone(const Optional& aServiceId, ErrorResult& aRv) -{ - uint32_t serviceId = GetServiceId(aServiceId, - true /* aGetIfActiveCall */); - - if (!IsValidServiceId(serviceId)) { - aRv.Throw(NS_ERROR_INVALID_ARG); - return; - } - - aRv = mService->StopTone(serviceId); -} - -void -Telephony::OwnAudioChannel(ErrorResult& aRv) -{ - if (mAudioAgent) { - return; - } - - mAudioAgent = do_CreateInstance("@mozilla.org/audiochannelagent;1"); - MOZ_ASSERT(mAudioAgent); - aRv = mAudioAgent->Init(GetParentObject(), - (int32_t)AudioChannel::Telephony, this); - if (NS_WARN_IF(aRv.Failed())) { - return; - } - aRv = HandleAudioAgentState(); - if (NS_WARN_IF(aRv.Failed())) { - return; - } -} - -nsresult -Telephony::HandleAudioAgentState() -{ - if (!mAudioAgent) { - return NS_OK; - } - - Nullable activeCall; - GetActive(activeCall); - nsresult rv; - // Only stop the agent when there's no call. - if ((!mCalls.Length() && !mGroup->CallsArray().Length()) && - mIsAudioStartPlaying) { - mIsAudioStartPlaying = false; - rv = mAudioAgent->NotifyStoppedPlaying(); - mAudioAgent = nullptr; - if (NS_WARN_IF(NS_FAILED(rv))) { - return rv; - } - } else if (!activeCall.IsNull() && !mIsAudioStartPlaying) { - mIsAudioStartPlaying = true; - AudioPlaybackConfig config; - rv = mAudioAgent->NotifyStartedPlaying(&config, - AudioChannelService::AudibleState::eAudible); - if (NS_WARN_IF(NS_FAILED(rv))) { - return rv; - } - - // In B2G, the system app manages audio playback policy. If there is a new - // sound want to be playback, it must wait for the permission from the - // system app. It means that the sound would be muted first, and then be - // unmuted. For telephony, the behaviors are hold() first, then resume(). - // However, the telephony service can't handle all these requests within a - // short period. The telephony service would reject our resume request, - // because the modem have not changed the call state yet. It causes that - // the telephony can't be resumed. Therefore, we don't mute the telephony - // at the beginning. - rv = WindowVolumeChanged(1.0, false); - if (NS_WARN_IF(NS_FAILED(rv))) { - return rv; - } - - rv = WindowSuspendChanged(config.mSuspend); - if (NS_WARN_IF(NS_FAILED(rv))) { - return rv; - } - } - return NS_OK; -} - -bool -Telephony::GetMuted(ErrorResult& aRv) const -{ - bool muted = false; - aRv = mService->GetMicrophoneMuted(&muted); - - return muted; -} - -void -Telephony::SetMuted(bool aMuted, ErrorResult& aRv) -{ - aRv = mService->SetMicrophoneMuted(aMuted); -} - -bool -Telephony::GetSpeakerEnabled(ErrorResult& aRv) const -{ - bool enabled = false; - aRv = mService->GetSpeakerEnabled(&enabled); - - return enabled; -} - -void -Telephony::SetSpeakerEnabled(bool aEnabled, ErrorResult& aRv) -{ - aRv = mService->SetSpeakerEnabled(aEnabled); -} - -void -Telephony::GetActive(Nullable& aValue) -{ - if (mGroup->IsActive()) { - aValue.SetValue().SetAsTelephonyCallGroup() = mGroup; - return; - } - - // Search for the active call. - for (uint32_t i = 0; i < mCalls.Length(); i++) { - if (mCalls[i]->IsActive()) { - aValue.SetValue().SetAsTelephonyCall() = mCalls[i]; - return; - } - } - - // Nothing active found. - aValue.SetNull(); -} - -already_AddRefed -Telephony::Calls() const -{ - RefPtr list = mCallsList; - return list.forget(); -} - -already_AddRefed -Telephony::ConferenceGroup() const -{ - RefPtr group = mGroup; - return group.forget(); -} - -already_AddRefed -Telephony::GetReady(ErrorResult& aRv) const -{ - if (!mReadyPromise) { - aRv.Throw(NS_ERROR_UNEXPECTED); - return nullptr; - } - - RefPtr promise = mReadyPromise; - return promise.forget(); -} - -// nsIAudioChannelAgentCallback - -NS_IMETHODIMP -Telephony::WindowVolumeChanged(float aVolume, bool aMuted) -{ - // It's impossible to put all the calls on-hold in the multi-call case. - if (mCalls.Length() > 1 || - (mCalls.Length() == 1 && mGroup->CallsArray().Length())) { - return NS_ERROR_FAILURE; - } - - ErrorResult rv; - nsCOMPtr global = do_QueryInterface(GetOwner()); - RefPtr promise = Promise::Create(global, rv); - if (NS_WARN_IF(rv.Failed())) { - return rv.StealNSResult(); - } - - bool isSingleCall = mCalls.Length(); - if (isSingleCall && mCalls[0]->Switchable()) { - if (aMuted && (mCalls[0]->State() == TelephonyCallState::Connected)) { - Unused << mCalls[0]->Hold(rv); - } else if (!aMuted && (mCalls[0]->State() == TelephonyCallState::Held)) { - Unused << mCalls[0]->Resume(rv); - } - } else { - if (aMuted && (mGroup->State() == TelephonyCallGroupState::Connected)) { - Unused << mGroup->Hold(rv); - } else if (!aMuted && (mGroup->State() == TelephonyCallGroupState::Held)) { - Unused << mGroup->Resume(rv); - } - } - if (NS_WARN_IF(rv.Failed())) { - return rv.StealNSResult(); - } - - // These events will be triggered when the telephony is interrupted by other - // audio channel. - if (mMuted != aMuted) { - mMuted = aMuted; - // We should not dispatch "mozinterruptend" when the system app initializes - // the telephony audio from muted to unmuted at the first time. The event - // "mozinterruptend" must be dispatched after the "mozinterruptbegin". - if (!mHaveDispatchedInterruptBeginEvent && mMuted) { - DispatchTrustedEvent(NS_LITERAL_STRING("mozinterruptbegin")); - mHaveDispatchedInterruptBeginEvent = mMuted; - } else if (mHaveDispatchedInterruptBeginEvent && !mMuted) { - DispatchTrustedEvent(NS_LITERAL_STRING("mozinterruptend")); - mHaveDispatchedInterruptBeginEvent = mMuted; - } - } - - return NS_OK; -} - -NS_IMETHODIMP -Telephony::WindowSuspendChanged(nsSuspendedTypes aSuspend) -{ - // Not support yet. - return NS_OK; -} - -NS_IMETHODIMP -Telephony::WindowAudioCaptureChanged(bool aCapture) -{ - // Do nothing, it's useless for the telephony object. - return NS_OK; -} - -// nsITelephonyListener - -NS_IMETHODIMP -Telephony::CallStateChanged(uint32_t aLength, nsITelephonyCallInfo** aAllInfo) -{ - // Update call state - nsresult rv; - for (uint32_t i = 0; i < aLength; ++i) { - rv = HandleCallInfo(aAllInfo[i]); - if (NS_WARN_IF(NS_FAILED(rv))) { - return rv; - } - } - - // Update conference state - mGroup->ChangeState(); - - rv = HandleAudioAgentState(); - if (NS_WARN_IF(NS_FAILED(rv))) { - return rv; - } - return NS_OK; -} - -NS_IMETHODIMP -Telephony::EnumerateCallState(nsITelephonyCallInfo* aInfo) -{ - return HandleCallInfo(aInfo); -} - -NS_IMETHODIMP -Telephony::EnumerateCallStateComplete() -{ - // Set conference state. - mGroup->ChangeState(); - - HandleAudioAgentState(); - if (mReadyPromise) { - mReadyPromise->MaybeResolveWithUndefined(); - } - - if (NS_FAILED(mService->RegisterListener(mListener))) { - NS_WARNING("Failed to register listener!"); - } - return NS_OK; -} - -NS_IMETHODIMP -Telephony::SupplementaryServiceNotification(uint32_t aServiceId, - int32_t aCallIndex, - uint16_t aNotification) -{ - RefPtr associatedCall; - if (!mCalls.IsEmpty()) { - associatedCall = GetCall(aServiceId, aCallIndex); - } - - nsresult rv; - switch (aNotification) { - case nsITelephonyService::NOTIFICATION_REMOTE_HELD: - rv = DispatchCallEvent(NS_LITERAL_STRING("remoteheld"), associatedCall); - break; - case nsITelephonyService::NOTIFICATION_REMOTE_RESUMED: - rv = DispatchCallEvent(NS_LITERAL_STRING("remoteresumed"), associatedCall); - break; - default: - NS_ERROR("Got a bad notification!"); - return NS_ERROR_UNEXPECTED; - } - - NS_ENSURE_SUCCESS(rv, rv); - return NS_OK; -} - -NS_IMETHODIMP -Telephony::NotifyCdmaCallWaiting(uint32_t aServiceId, const nsAString& aNumber, - uint16_t aNumberPresentation, - const nsAString& aName, - uint16_t aNamePresentation) -{ - MOZ_ASSERT(mCalls.Length() == 1); - - RefPtr callToNotify = mCalls[0]; - MOZ_ASSERT(callToNotify && callToNotify->ServiceId() == aServiceId); - - RefPtr id = - new TelephonyCallId(GetOwner(), aNumber, aNumberPresentation, aName, - aNamePresentation); - callToNotify->UpdateSecondId(id); - DispatchCallEvent(NS_LITERAL_STRING("callschanged"), callToNotify); - return NS_OK; -} - -NS_IMETHODIMP -Telephony::NotifyConferenceError(const nsAString& aName, - const nsAString& aMessage) -{ - mGroup->NotifyError(aName, aMessage); - return NS_OK; -} - -nsresult -Telephony::DispatchCallEvent(const nsAString& aType, - TelephonyCall* aCall) -{ - // If it is an incoming event, the call should not be null. - MOZ_ASSERT(!aType.EqualsLiteral("incoming") || aCall); - - CallEventInit init; - init.mBubbles = false; - init.mCancelable = false; - init.mCall = aCall; - - RefPtr event = CallEvent::Constructor(this, aType, init); - - return DispatchTrustedEvent(event); -} - -already_AddRefed -NS_CreateTelephonyService() -{ - nsCOMPtr service; - - if (XRE_IsContentProcess()) { - service = new mozilla::dom::telephony::TelephonyIPCService(); - } else { -#if defined(MOZ_WIDGET_GONK) && defined(MOZ_B2G_RIL) - service = do_CreateInstance(GONK_TELEPHONY_SERVICE_CONTRACTID); -#endif - } - - return service.forget(); -} diff --git a/dom/telephony/Telephony.h b/dom/telephony/Telephony.h deleted file mode 100644 index fc952ffc8955..000000000000 --- a/dom/telephony/Telephony.h +++ /dev/null @@ -1,245 +0,0 @@ -/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ -/* vim: set ts=8 sts=2 et sw=2 tw=80: */ -/* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ - -#ifndef mozilla_dom_telephony_telephony_h__ -#define mozilla_dom_telephony_telephony_h__ - -#include "AudioChannelService.h" - -#include "mozilla/dom/BindingDeclarations.h" -#include "mozilla/dom/Promise.h" -#include "mozilla/dom/telephony/TelephonyCommon.h" - -#include "nsITelephonyCallInfo.h" -#include "nsITelephonyService.h" - -// Need to include TelephonyCall.h because we have inline methods that -// assume they see the definition of TelephonyCall. -#include "TelephonyCall.h" - -class nsPIDOMWindowInner; - -namespace mozilla { -namespace dom { -namespace telephony { - -class TelephonyDialCallback; - -} // namespace telephony - -class OwningTelephonyCallOrTelephonyCallGroup; - -class Telephony final : public DOMEventTargetHelper, - public nsIAudioChannelAgentCallback, - private nsITelephonyListener -{ - /** - * Class Telephony doesn't actually expose nsITelephonyListener. - * Instead, it owns an nsITelephonyListener derived instance mListener - * and passes it to nsITelephonyService. The onreceived events are first - * delivered to mListener and then forwarded to its owner, Telephony. See - * also bug 775997 comment #51. - */ - class Listener; - - friend class telephony::TelephonyDialCallback; - - // The audio agent is needed to communicate with the audio channel service. - nsCOMPtr mAudioAgent; - nsCOMPtr mService; - RefPtr mListener; - - nsTArray > mCalls; - RefPtr mCallsList; - - RefPtr mGroup; - - RefPtr mReadyPromise; - - bool mIsAudioStartPlaying; - bool mHaveDispatchedInterruptBeginEvent; - bool mMuted; - -public: - NS_DECL_ISUPPORTS_INHERITED - NS_DECL_NSIAUDIOCHANNELAGENTCALLBACK - NS_DECL_NSITELEPHONYLISTENER - NS_REALLY_FORWARD_NSIDOMEVENTTARGET(DOMEventTargetHelper) - NS_DECL_CYCLE_COLLECTION_CLASS_INHERITED(Telephony, - DOMEventTargetHelper) - - nsPIDOMWindowInner* - GetParentObject() const - { - return GetOwner(); - } - - // WrapperCache - virtual JSObject* - WrapObject(JSContext* aCx, JS::Handle aGivenProto) override; - - // WebIDL - already_AddRefed - Dial(const nsAString& aNumber, const Optional& aServiceId, - ErrorResult& aRv); - - already_AddRefed - DialEmergency(const nsAString& aNumber, const Optional& aServiceId, - ErrorResult& aRv); - - already_AddRefed - SendTones(const nsAString& aDTMFChars, - uint32_t aPauseDuration, - uint32_t aToneDuration, - const Optional& aServiceId, - ErrorResult& aRv); - - void - StartTone(const nsAString& aDTMFChar, const Optional& aServiceId, - ErrorResult& aRv); - - void - StopTone(const Optional& aServiceId, ErrorResult& aRv); - - // In the audio channel architecture, the system app needs to know the state - // of every audio channel, including the telephony. Therefore, when a - // telephony call is activated , the audio channel service would notify the - // system app about that. And we need an agent to communicate with the audio - // channel service. We would follow the call states to make a correct - // notification. - void - OwnAudioChannel(ErrorResult& aRv); - - bool - GetMuted(ErrorResult& aRv) const; - - void - SetMuted(bool aMuted, ErrorResult& aRv); - - bool - GetSpeakerEnabled(ErrorResult& aRv) const; - - void - SetSpeakerEnabled(bool aEnabled, ErrorResult& aRv); - - void - GetActive(Nullable& aValue); - - already_AddRefed - Calls() const; - - already_AddRefed - ConferenceGroup() const; - - already_AddRefed - GetReady(ErrorResult& aRv) const; - - IMPL_EVENT_HANDLER(incoming) - IMPL_EVENT_HANDLER(callschanged) - IMPL_EVENT_HANDLER(remoteheld) - IMPL_EVENT_HANDLER(remoteresumed) - - static already_AddRefed - Create(nsPIDOMWindowInner* aOwner, ErrorResult& aRv); - - void - AddCall(TelephonyCall* aCall) - { - NS_ASSERTION(!mCalls.Contains(aCall), "Already know about this one!"); - mCalls.AppendElement(aCall); - NotifyCallsChanged(aCall); - } - - void - RemoveCall(TelephonyCall* aCall) - { - NS_ASSERTION(mCalls.Contains(aCall), "Didn't know about this one!"); - mCalls.RemoveElement(aCall); - NotifyCallsChanged(aCall); - } - - nsITelephonyService* - Service() const - { - return mService; - } - - const nsTArray >& - CallsArray() const - { - return mCalls; - } - -private: - explicit Telephony(nsPIDOMWindowInner* aOwner); - ~Telephony(); - - void - Shutdown(); - - static bool - IsValidNumber(const nsAString& aNumber); - - static uint32_t - GetNumServices(); - - static bool - IsValidServiceId(uint32_t aServiceId); - - uint32_t - GetServiceId(const Optional& aServiceId, - bool aGetIfActiveCall = false); - - already_AddRefed - DialInternal(uint32_t aServiceId, const nsAString& aNumber, bool aEmergency, - ErrorResult& aRv); - - already_AddRefed - CreateCallId(nsITelephonyCallInfo *aInfo); - - already_AddRefed - CreateCallId(const nsAString& aNumber, - uint16_t aNumberPresentation = nsITelephonyService::CALL_PRESENTATION_ALLOWED, - const nsAString& aName = EmptyString(), - uint16_t aNamePresentation = nsITelephonyService::CALL_PRESENTATION_ALLOWED); - - already_AddRefed - CreateCall(TelephonyCallId* aId, - uint32_t aServiceId, - uint32_t aCallIndex, - TelephonyCallState aState, - bool aEmergency = false, - bool aConference = false, - bool aSwitchable = true, - bool aMergeable = true); - - nsresult - NotifyEvent(const nsAString& aType); - - nsresult - NotifyCallsChanged(TelephonyCall* aCall); - - nsresult - DispatchCallEvent(const nsAString& aType, TelephonyCall* aCall); - - already_AddRefed - GetCall(uint32_t aServiceId, uint32_t aCallIndex); - - already_AddRefed - GetCallFromEverywhere(uint32_t aServiceId, uint32_t aCallIndex); - - nsresult - HandleCallInfo(nsITelephonyCallInfo* aInfo); - - // Check the call states to decide whether need to send the notificaiton. - nsresult - HandleAudioAgentState(); -}; - -} // namespace dom -} // namespace mozilla - -#endif // mozilla_dom_telephony_telephony_h__ diff --git a/dom/telephony/TelephonyCall.cpp b/dom/telephony/TelephonyCall.cpp deleted file mode 100644 index 9c68dc51522f..000000000000 --- a/dom/telephony/TelephonyCall.cpp +++ /dev/null @@ -1,454 +0,0 @@ -/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ -/* vim: set ts=8 sts=2 et sw=2 tw=80: */ -/* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ - -#include "TelephonyCall.h" -#include "mozilla/dom/CallEvent.h" -#include "mozilla/dom/TelephonyCallBinding.h" -#include "mozilla/dom/telephony/TelephonyCallback.h" - -#include "mozilla/dom/DOMError.h" -#include "nsPrintfCString.h" - -#include "Telephony.h" -#include "TelephonyCallGroup.h" - -#ifdef CONVERT_STRING_TO_NULLABLE_ENUM -#undef CONVERT_STRING_TO_NULLABLE_ENUM -#endif - -#define CONVERT_STRING_TO_NULLABLE_ENUM(_string, _enumType, _enum) \ -{ \ - _enum.SetNull(); \ - \ - uint32_t i = 0; \ - for (const EnumEntry* entry = _enumType##Values::strings; \ - entry->value; \ - ++entry, ++i) { \ - if (_string.EqualsASCII(entry->value)) { \ - _enum.SetValue(static_cast<_enumType>(i)); \ - break; \ - } \ - } \ -} - -#ifdef TELEPHONY_CALL_STATE -#undef TELEPHONY_CALL_STATE -#endif - -#define TELEPHONY_CALL_STATE(_state) \ - (TelephonyCallStateValues::strings[static_cast(_state)].value) - -using namespace mozilla::dom; -using namespace mozilla::dom::telephony; -using mozilla::ErrorResult; - -// static -TelephonyCallState -TelephonyCall::ConvertToTelephonyCallState(uint32_t aCallState) -{ - switch (aCallState) { - case nsITelephonyService::CALL_STATE_DIALING: - return TelephonyCallState::Dialing; - case nsITelephonyService::CALL_STATE_ALERTING: - return TelephonyCallState::Alerting; - case nsITelephonyService::CALL_STATE_CONNECTED: - return TelephonyCallState::Connected; - case nsITelephonyService::CALL_STATE_HELD: - return TelephonyCallState::Held; - case nsITelephonyService::CALL_STATE_DISCONNECTED: - return TelephonyCallState::Disconnected; - case nsITelephonyService::CALL_STATE_INCOMING: - return TelephonyCallState::Incoming; - } - - NS_NOTREACHED("Unknown state!"); - return TelephonyCallState::Disconnected; -} - -// static -already_AddRefed -TelephonyCall::Create(Telephony* aTelephony, - TelephonyCallId* aId, - uint32_t aServiceId, - uint32_t aCallIndex, - TelephonyCallState aState, - bool aEmergency, - bool aConference, - bool aSwitchable, - bool aMergeable) -{ - NS_ASSERTION(aTelephony, "Null aTelephony pointer!"); - NS_ASSERTION(aId, "Null aId pointer!"); - NS_ASSERTION(aCallIndex >= 1, "Invalid call index!"); - - RefPtr call = new TelephonyCall(aTelephony->GetOwner()); - - call->mTelephony = aTelephony; - call->mId = aId; - call->mServiceId = aServiceId; - call->mCallIndex = aCallIndex; - call->mEmergency = aEmergency; - call->mGroup = aConference ? aTelephony->ConferenceGroup() : nullptr; - call->mSwitchable = aSwitchable; - call->mMergeable = aMergeable; - call->mError = nullptr; - - call->ChangeStateInternal(aState, false); - return call.forget(); -} - -TelephonyCall::TelephonyCall(nsPIDOMWindowInner* aOwner) - : DOMEventTargetHelper(aOwner), - mLive(false) -{ -} - -TelephonyCall::~TelephonyCall() -{ -} - -JSObject* -TelephonyCall::WrapObject(JSContext* aCx, JS::Handle aGivenProto) -{ - return TelephonyCallBinding::Wrap(aCx, this, aGivenProto); -} - -void -TelephonyCall::ChangeStateInternal(TelephonyCallState aState, bool aFireEvents) -{ - RefPtr kungFuDeathGrip(this); - - // Update current state - mState = aState; - - // Handle disconnected calls - if (mState == TelephonyCallState::Disconnected) { - NS_ASSERTION(mLive, "Should be live!"); - mLive = false; - if (mGroup) { - mGroup->RemoveCall(this); - } else { - mTelephony->RemoveCall(this); - } - } else if (!mLive) { // Handle newly added calls - mLive = true; - if (mGroup) { - mGroup->AddCall(this); - } else { - mTelephony->AddCall(this); - } - } - - // Dispatch call state changed and call state event - if (aFireEvents) { - NotifyStateChanged(); - } -} - -nsresult -TelephonyCall::NotifyStateChanged() -{ - // Since |mState| can be changed after statechange handler called back here, - // we must save current state. Maybe we should figure out something smarter. - TelephonyCallState prevState = mState; - - nsresult res = DispatchCallEvent(NS_LITERAL_STRING("statechange"), this); - if (NS_FAILED(res)) { - NS_WARNING("Failed to dispatch specific event!"); - } - - // Check whether |mState| remains the same after the statechange handler. - if (mState != prevState) { - NS_WARNING("Call State has changed by statechange handler!"); - return res; - } - - res = DispatchCallEvent(NS_ConvertASCIItoUTF16(TELEPHONY_CALL_STATE(mState)), - this); - if (NS_FAILED(res)) { - NS_WARNING("Failed to dispatch a specific event!"); - } - - return res; -} - -nsresult -TelephonyCall::DispatchCallEvent(const nsAString& aType, - TelephonyCall* aCall) -{ - MOZ_ASSERT(aCall); - - CallEventInit init; - init.mBubbles = false; - init.mCancelable = false; - init.mCall = aCall; - - RefPtr event = CallEvent::Constructor(this, aType, init); - - return DispatchTrustedEvent(event); -} - -already_AddRefed -TelephonyCall::CreatePromise(ErrorResult& aRv) -{ - nsCOMPtr global = do_QueryInterface(GetOwner()); - if (!global) { - aRv.Throw(NS_ERROR_FAILURE); - return nullptr; - } - - RefPtr promise = Promise::Create(global, aRv); - if (aRv.Failed()) { - return nullptr; - } - - return promise.forget(); -} - -void -TelephonyCall::NotifyError(const nsAString& aError) -{ - // Set the error string - NS_ASSERTION(!mError, "Already have an error?"); - - mError = new DOMError(GetOwner(), aError); - - nsresult rv = DispatchCallEvent(NS_LITERAL_STRING("error"), this); - if (NS_FAILED(rv)) { - NS_WARNING("Failed to dispatch error event!"); - } -} - -void -TelephonyCall::UpdateDisconnectedReason(const nsAString& aDisconnectedReason) -{ - NS_ASSERTION(Substring(aDisconnectedReason, - aDisconnectedReason.Length() - 5).EqualsLiteral("Error"), - "Disconnected reason should end with 'Error'"); - - if (!mDisconnectedReason.IsNull()) { - return; - } - - // There is no 'Error' suffix in the corresponding enum. We should skip - // that part for comparison. - CONVERT_STRING_TO_NULLABLE_ENUM( - Substring(aDisconnectedReason, 0, aDisconnectedReason.Length() - 5), - TelephonyCallDisconnectedReason, - mDisconnectedReason); - - if (!aDisconnectedReason.EqualsLiteral("NormalCallClearingError")) { - NotifyError(aDisconnectedReason); - } -} - -void -TelephonyCall::ChangeGroup(TelephonyCallGroup* aGroup) -{ - mGroup = aGroup; - - nsresult rv = DispatchCallEvent(NS_LITERAL_STRING("groupchange"), this); - if (NS_FAILED(rv)) { - NS_WARNING("Failed to dispatch error event!"); - } -} - -NS_IMPL_CYCLE_COLLECTION_INHERITED(TelephonyCall, - DOMEventTargetHelper, - mTelephony, - mError, - mGroup, - mId, - mSecondId); - -NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION_INHERITED(TelephonyCall) -NS_INTERFACE_MAP_END_INHERITING(DOMEventTargetHelper) - -NS_IMPL_ADDREF_INHERITED(TelephonyCall, DOMEventTargetHelper) -NS_IMPL_RELEASE_INHERITED(TelephonyCall, DOMEventTargetHelper) - -// TelephonyCall WebIDL - -already_AddRefed -TelephonyCall::Id() const -{ - RefPtr id = mId; - return id.forget(); -} - -already_AddRefed -TelephonyCall::GetSecondId() const -{ - RefPtr id = mSecondId; - return id.forget(); -} - -already_AddRefed -TelephonyCall::GetError() const -{ - RefPtr error = mError; - return error.forget(); -} - -already_AddRefed -TelephonyCall::GetGroup() const -{ - RefPtr group = mGroup; - return group.forget(); -} - -already_AddRefed -TelephonyCall::Answer(ErrorResult& aRv) -{ - RefPtr promise = CreatePromise(aRv); - if (!promise) { - return nullptr; - } - - if (mState != TelephonyCallState::Incoming) { - NS_WARNING(nsPrintfCString("Answer on non-incoming call is rejected!" - " (State: %s)", - TELEPHONY_CALL_STATE(mState)).get()); - promise->MaybeReject(NS_ERROR_DOM_INVALID_STATE_ERR); - return promise.forget(); - } - - nsCOMPtr callback = new TelephonyCallback(promise); - aRv = mTelephony->Service()->AnswerCall(mServiceId, mCallIndex, callback); - NS_ENSURE_TRUE(!aRv.Failed(), nullptr); - - return promise.forget(); -} - -already_AddRefed -TelephonyCall::HangUp(ErrorResult& aRv) -{ - RefPtr promise = CreatePromise(aRv); - if (!promise) { - return nullptr; - } - - if (mState == TelephonyCallState::Disconnected) { - NS_WARNING(nsPrintfCString("HangUp on a disconnected call is rejected!" - " (State: %s)", - TELEPHONY_CALL_STATE(mState)).get()); - promise->MaybeReject(NS_ERROR_DOM_INVALID_STATE_ERR); - return promise.forget(); - } - - nsCOMPtr callback = new TelephonyCallback(promise); - aRv = mState == TelephonyCallState::Incoming ? - mTelephony->Service()->RejectCall(mServiceId, mCallIndex, callback) : - mTelephony->Service()->HangUpCall(mServiceId, mCallIndex, callback); - NS_ENSURE_TRUE(!aRv.Failed(), nullptr); - - return promise.forget(); -} - -already_AddRefed -TelephonyCall::Hold(ErrorResult& aRv) -{ - RefPtr promise = CreatePromise(aRv); - if (!promise) { - return nullptr; - } - - nsCOMPtr callback = new TelephonyCallback(promise); - aRv = Hold(callback); - if (NS_WARN_IF(aRv.Failed() && - !aRv.ErrorCodeIs(NS_ERROR_DOM_INVALID_STATE_ERR))) { - return nullptr; - } - - return promise.forget(); -} - -nsresult -TelephonyCall::Hold(nsITelephonyCallback* aCallback) -{ - if (mState != TelephonyCallState::Connected) { - NS_WARNING(nsPrintfCString("Hold non-connected call is rejected!" - " (State: %s)", - TELEPHONY_CALL_STATE(mState)).get()); - aCallback->NotifyError(NS_LITERAL_STRING("InvalidStateError")); - return NS_ERROR_DOM_INVALID_STATE_ERR; - } - - if (mGroup) { - NS_WARNING("Hold a call in conference is rejected!"); - aCallback->NotifyError(NS_LITERAL_STRING("InvalidStateError")); - return NS_ERROR_DOM_INVALID_STATE_ERR; - } - - if (!mSwitchable) { - NS_WARNING("Hold a non-switchable call is rejected!"); - aCallback->NotifyError(NS_LITERAL_STRING("InvalidStateError")); - return NS_ERROR_DOM_INVALID_STATE_ERR; - } - - nsresult rv = mTelephony->Service()->HoldCall(mServiceId, mCallIndex, aCallback); - if (NS_WARN_IF(NS_FAILED(rv))) { - return NS_ERROR_FAILURE; - } - - if (mSecondId) { - // No state transition when we switch two numbers within one TelephonyCall - // object. Otherwise, the state here will be inconsistent with the backend - // RIL and will never be right. - return NS_OK; - } - - return NS_OK; -} - -already_AddRefed -TelephonyCall::Resume(ErrorResult& aRv) -{ - RefPtr promise = CreatePromise(aRv); - if (!promise) { - return nullptr; - } - - nsCOMPtr callback = new TelephonyCallback(promise); - aRv = Resume(callback); - if (NS_WARN_IF(aRv.Failed() && - !aRv.ErrorCodeIs(NS_ERROR_DOM_INVALID_STATE_ERR))) { - return nullptr; - } - - return promise.forget(); -} - -nsresult -TelephonyCall::Resume(nsITelephonyCallback* aCallback) -{ - if (mState != TelephonyCallState::Held) { - NS_WARNING(nsPrintfCString("Resume non-held call is rejected!" - " (State: %s)", - TELEPHONY_CALL_STATE(mState)).get()); - aCallback->NotifyError(NS_LITERAL_STRING("InvalidStateError")); - return NS_ERROR_DOM_INVALID_STATE_ERR; - } - - if (mGroup) { - NS_WARNING("Resume a call in conference is rejected!"); - aCallback->NotifyError(NS_LITERAL_STRING("InvalidStateError")); - return NS_ERROR_DOM_INVALID_STATE_ERR; - } - - if (!mSwitchable) { - NS_WARNING("Resume a non-switchable call is rejected!"); - aCallback->NotifyError(NS_LITERAL_STRING("InvalidStateError")); - return NS_ERROR_DOM_INVALID_STATE_ERR; - } - - nsresult rv = mTelephony->Service()->ResumeCall(mServiceId, mCallIndex, aCallback); - if (NS_WARN_IF(NS_FAILED(rv))) { - return NS_ERROR_FAILURE; - } - - return NS_OK; -} diff --git a/dom/telephony/TelephonyCall.h b/dom/telephony/TelephonyCall.h deleted file mode 100644 index 59174e7161e3..000000000000 --- a/dom/telephony/TelephonyCall.h +++ /dev/null @@ -1,217 +0,0 @@ -/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ -/* vim: set ts=8 sts=2 et sw=2 tw=80: */ -/* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ - -#ifndef mozilla_dom_telephony_telephonycall_h__ -#define mozilla_dom_telephony_telephonycall_h__ - -#include "mozilla/dom/DOMError.h" -#include "mozilla/dom/Promise.h" -#include "mozilla/dom/TelephonyCallBinding.h" -#include "mozilla/dom/TelephonyCallId.h" -#include "mozilla/dom/telephony/TelephonyCommon.h" - -#include "nsITelephonyService.h" - -class nsPIDOMWindowInner; - -namespace mozilla { -namespace dom { - -class TelephonyCall final : public DOMEventTargetHelper -{ - MOZ_INIT_OUTSIDE_CTOR RefPtr mTelephony; - MOZ_INIT_OUTSIDE_CTOR RefPtr mGroup; - - MOZ_INIT_OUTSIDE_CTOR RefPtr mId; - RefPtr mSecondId; - - MOZ_INIT_OUTSIDE_CTOR uint32_t mServiceId; - MOZ_INIT_OUTSIDE_CTOR TelephonyCallState mState; - MOZ_INIT_OUTSIDE_CTOR bool mEmergency; - MOZ_INIT_OUTSIDE_CTOR RefPtr mError; - Nullable mDisconnectedReason; - - MOZ_INIT_OUTSIDE_CTOR bool mSwitchable; - MOZ_INIT_OUTSIDE_CTOR bool mMergeable; - - MOZ_INIT_OUTSIDE_CTOR uint32_t mCallIndex; - bool mLive; - -public: - NS_DECL_ISUPPORTS_INHERITED - NS_REALLY_FORWARD_NSIDOMEVENTTARGET(DOMEventTargetHelper) - NS_DECL_CYCLE_COLLECTION_CLASS_INHERITED(TelephonyCall, - DOMEventTargetHelper) - friend class Telephony; - - nsPIDOMWindowInner* - GetParentObject() const - { - return GetOwner(); - } - - // WrapperCache - virtual JSObject* - WrapObject(JSContext* aCx, JS::Handle aGivenProto) override; - - // WebIDL - already_AddRefed - Id() const; - - already_AddRefed - GetSecondId() const; - - TelephonyCallState - State() const - { - return mState; - } - - bool - Emergency() const - { - return mEmergency; - } - - bool - Switchable() const - { - return mSwitchable; - } - - bool - Mergeable() const - { - return mMergeable; - } - - bool - IsActive() const - { - return mState == TelephonyCallState::Dialing || - mState == TelephonyCallState::Alerting || - mState == TelephonyCallState::Connected; - } - - already_AddRefed - GetError() const; - - Nullable - GetDisconnectedReason() const - { - return mDisconnectedReason; - } - - already_AddRefed - GetGroup() const; - - already_AddRefed - Answer(ErrorResult& aRv); - - already_AddRefed - HangUp(ErrorResult& aRv); - - already_AddRefed - Hold(ErrorResult& aRv); - - already_AddRefed - Resume(ErrorResult& aRv); - - IMPL_EVENT_HANDLER(statechange) - IMPL_EVENT_HANDLER(dialing) - IMPL_EVENT_HANDLER(alerting) - IMPL_EVENT_HANDLER(connected) - IMPL_EVENT_HANDLER(disconnected) - IMPL_EVENT_HANDLER(held) - IMPL_EVENT_HANDLER(error) - IMPL_EVENT_HANDLER(groupchange) - - static TelephonyCallState - ConvertToTelephonyCallState(uint32_t aCallState); - - static already_AddRefed - Create(Telephony* aTelephony, TelephonyCallId* aId, - uint32_t aServiceId, uint32_t aCallIndex, TelephonyCallState aState, - bool aEmergency = false, bool aConference = false, - bool aSwitchable = true, bool aMergeable = true); - - void - ChangeState(TelephonyCallState aState) - { - ChangeStateInternal(aState, true); - } - - nsresult - NotifyStateChanged(); - - uint32_t - ServiceId() const - { - return mServiceId; - } - - uint32_t - CallIndex() const - { - return mCallIndex; - } - - void - UpdateEmergency(bool aEmergency) - { - mEmergency = aEmergency; - } - - void - UpdateSwitchable(bool aSwitchable) { - mSwitchable = aSwitchable; - } - - void - UpdateMergeable(bool aMergeable) { - mMergeable = aMergeable; - } - - void - UpdateSecondId(TelephonyCallId* aId) { - mSecondId = aId; - } - - void - NotifyError(const nsAString& aError); - - void - UpdateDisconnectedReason(const nsAString& aDisconnectedReason); - - void - ChangeGroup(TelephonyCallGroup* aGroup); - -private: - explicit TelephonyCall(nsPIDOMWindowInner* aOwner); - - ~TelephonyCall(); - - nsresult - Hold(nsITelephonyCallback* aCallback); - - nsresult - Resume(nsITelephonyCallback* aCallback); - - void - ChangeStateInternal(TelephonyCallState aState, bool aFireEvents); - - nsresult - DispatchCallEvent(const nsAString& aType, - TelephonyCall* aCall); - - already_AddRefed - CreatePromise(ErrorResult& aRv); -}; - -} // namespace dom -} // namespace mozilla - -#endif // mozilla_dom_telephony_telephonycall_h__ diff --git a/dom/telephony/TelephonyCallGroup.cpp b/dom/telephony/TelephonyCallGroup.cpp deleted file mode 100644 index eb80af3eef4f..000000000000 --- a/dom/telephony/TelephonyCallGroup.cpp +++ /dev/null @@ -1,469 +0,0 @@ -/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ -/* vim: set ts=8 sts=2 et sw=2 tw=80: */ -/* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ - -#include "TelephonyCallGroup.h" - -#include "CallsList.h" -#include "Telephony.h" -#include "mozilla/dom/CallEvent.h" -#include "mozilla/dom/CallGroupErrorEvent.h" -#include "mozilla/dom/telephony/TelephonyCallback.h" - -#include "nsPrintfCString.h" - -#ifdef TELEPHONY_GROUP_STATE -#undef TELEPHONY_GROUP_STATE -#endif - -#define TELEPHONY_GROUP_STATE(_state) \ - (TelephonyCallGroupStateValues::strings[static_cast(_state)].value) - -using namespace mozilla::dom; -using namespace mozilla::dom::telephony; -using mozilla::ErrorResult; - -TelephonyCallGroup::TelephonyCallGroup(nsPIDOMWindowInner* aOwner) - : DOMEventTargetHelper(aOwner) -{ -} - -TelephonyCallGroup::~TelephonyCallGroup() -{ -} - -// static -already_AddRefed -TelephonyCallGroup::Create(Telephony* aTelephony) -{ - NS_ASSERTION(aTelephony, "Null telephony!"); - - RefPtr group = - new TelephonyCallGroup(aTelephony->GetOwner()); - - group->mTelephony = aTelephony; - group->mState = TelephonyCallGroupState::_empty; - group->mCallsList = new CallsList(aTelephony, group); - - return group.forget(); -} - -JSObject* -TelephonyCallGroup::WrapObject(JSContext* aCx, JS::Handle aGivenProto) -{ - return TelephonyCallGroupBinding::Wrap(aCx, this, aGivenProto); -} - -void -TelephonyCallGroup::AddCall(TelephonyCall* aCall) -{ - NS_ASSERTION(!mCalls.Contains(aCall), "Already know about this one!"); - mCalls.AppendElement(aCall); - aCall->ChangeGroup(this); - NotifyCallsChanged(aCall); -} - -void -TelephonyCallGroup::RemoveCall(TelephonyCall* aCall) -{ - NS_ASSERTION(mCalls.Contains(aCall), "Didn't know about this one!"); - mCalls.RemoveElement(aCall); - aCall->ChangeGroup(nullptr); - NotifyCallsChanged(aCall); -} - -nsresult -TelephonyCallGroup::NotifyError(const nsAString& aName, const nsAString& aMessage) -{ - CallGroupErrorEventInit init; - init.mBubbles = false; - init.mCancelable = false; - init.mName = aName; - init.mMessage = aMessage; - - RefPtr event = - CallGroupErrorEvent::Constructor(this, NS_LITERAL_STRING("error"), init); - - return DispatchTrustedEvent(event); -} - -void -TelephonyCallGroup::ChangeState() -{ - MOZ_ASSERT(mCalls.Length() != 1); - if (mCalls.Length() == 0) { - ChangeStateInternal(TelephonyCallGroupState::_empty); - return; - } - - TelephonyCallState state = mCalls[0]->State(); - for (uint32_t i = 1; i < mCalls.Length(); i++) { - if (mCalls[i]->State() != state) { - MOZ_ASSERT(false, "Various call states are found in a call group!"); - ChangeStateInternal(TelephonyCallGroupState::_empty); - return; - } - } - - TelephonyCallGroupState groupState = TelephonyCallGroupState::_empty; - switch (state) { - case TelephonyCallState::Connected: - groupState = TelephonyCallGroupState::Connected; - break; - case TelephonyCallState::Held: - groupState = TelephonyCallGroupState::Held; - break; - default: - NS_NOTREACHED(nsPrintfCString("Invavild call state for a call group(%s)!", - TELEPHONY_CALL_STATE(state)).get()); - } - - ChangeStateInternal(groupState); -} - -void -TelephonyCallGroup::ChangeStateInternal(TelephonyCallGroupState aState) -{ - if (mState == aState) { - return; - } - - // Update Current State - mState = aState; - - // Dispatch related events - NotifyStateChanged(); -} - -nsresult -TelephonyCallGroup::NotifyStateChanged() -{ - // Since |mState| can be changed after statechange handler called back here, - // we must save current state. Maybe we should figure out something smarter. - TelephonyCallGroupState prevState = mState; - - nsresult res = DispatchCallEvent(NS_LITERAL_STRING("statechange"), nullptr); - if (NS_FAILED(res)) { - NS_WARNING("Failed to dispatch specific event!"); - } - - // Check whether |mState| remains the same after the statechange handler. - // Besides, If there is no conference call at all, then we dont't have to - // dispatch the state evnet. - if (mState == prevState) { - res = DispatchCallEvent(NS_ConvertASCIItoUTF16(TELEPHONY_GROUP_STATE(mState)), - nullptr); - if (NS_FAILED(res)) { - NS_WARNING("Failed to dispatch specific event!"); - } - } - - // Notify each call within to dispatch call state change event - for (uint32_t index = 0; index < mCalls.Length(); index++) { - if (NS_FAILED(mCalls[index]->NotifyStateChanged())){ - res = NS_ERROR_FAILURE; - } - } - - return res; -} - -nsresult -TelephonyCallGroup::NotifyCallsChanged(TelephonyCall* aCall) -{ - return DispatchCallEvent(NS_LITERAL_STRING("callschanged"), aCall); -} - -nsresult -TelephonyCallGroup::DispatchCallEvent(const nsAString& aType, - TelephonyCall* aCall) -{ - CallEventInit init; - init.mBubbles = false; - init.mCancelable = false; - init.mCall = aCall; - - RefPtr event = CallEvent::Constructor(this, aType, init); - return DispatchTrustedEvent(event); -} - -already_AddRefed -TelephonyCallGroup::CreatePromise(ErrorResult& aRv) -{ - nsCOMPtr global = do_QueryInterface(GetOwner()); - if (!global) { - aRv.Throw(NS_ERROR_FAILURE); - return nullptr; - } - - RefPtr promise = Promise::Create(global, aRv); - if (aRv.Failed()) { - return nullptr; - } - - return promise.forget(); -} - -bool -TelephonyCallGroup::CanConference(const TelephonyCall& aCall, - const TelephonyCall* aSecondCall) -{ - if (!aCall.Mergeable()) { - return false; - } - - if (!aSecondCall) { - MOZ_ASSERT(!mCalls.IsEmpty()); - return (mState == TelephonyCallGroupState::Connected && - aCall.State() == TelephonyCallState::Held) || - (mState == TelephonyCallGroupState::Held && - aCall.State() == TelephonyCallState::Connected); - } - - MOZ_ASSERT(mState != TelephonyCallGroupState::_empty); - - if (aCall.ServiceId() != aSecondCall->ServiceId()) { - return false; - } - - if (!aSecondCall->Mergeable()) { - return false; - } - - return (aCall.State() == TelephonyCallState::Connected && - aSecondCall->State() == TelephonyCallState::Held) || - (aCall.State() == TelephonyCallState::Held && - aSecondCall->State() == TelephonyCallState::Connected); -} - -already_AddRefed -TelephonyCallGroup::GetCall(uint32_t aServiceId, uint32_t aCallIndex) -{ - RefPtr call; - - for (uint32_t index = 0; index < mCalls.Length(); index++) { - RefPtr& tempCall = mCalls[index]; - if (tempCall->ServiceId() == aServiceId && - tempCall->CallIndex() == aCallIndex) { - call = tempCall; - break; - } - } - - return call.forget(); -} - -NS_IMPL_CYCLE_COLLECTION_CLASS(TelephonyCallGroup) - -NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_INHERITED(TelephonyCallGroup, - DOMEventTargetHelper) - NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mCalls) - NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mCallsList) - NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mTelephony) -NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END - -NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN_INHERITED(TelephonyCallGroup, - DOMEventTargetHelper) - NS_IMPL_CYCLE_COLLECTION_UNLINK(mCalls) - NS_IMPL_CYCLE_COLLECTION_UNLINK(mCallsList) - NS_IMPL_CYCLE_COLLECTION_UNLINK(mTelephony) -NS_IMPL_CYCLE_COLLECTION_UNLINK_END - -NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION_INHERITED(TelephonyCallGroup) -NS_INTERFACE_MAP_END_INHERITING(DOMEventTargetHelper) - -NS_IMPL_ADDREF_INHERITED(TelephonyCallGroup, DOMEventTargetHelper) -NS_IMPL_RELEASE_INHERITED(TelephonyCallGroup, DOMEventTargetHelper) - -// WebIDL -already_AddRefed -TelephonyCallGroup::Calls() const -{ - RefPtr list = mCallsList; - return list.forget(); -} - -already_AddRefed -TelephonyCallGroup::Add(TelephonyCall& aCall, - ErrorResult& aRv) -{ - MOZ_ASSERT(!mCalls.IsEmpty()); - - RefPtr promise = CreatePromise(aRv); - if (!promise) { - return nullptr; - } - - if (!CanConference(aCall, nullptr)) { - promise->MaybeReject(NS_ERROR_NOT_AVAILABLE); - return promise.forget(); - } - - nsCOMPtr callback = new TelephonyCallback(promise); - aRv = mTelephony->Service()->ConferenceCall(aCall.ServiceId(), callback); - NS_ENSURE_TRUE(!aRv.Failed(), nullptr); - - return promise.forget(); -} - -already_AddRefed -TelephonyCallGroup::Add(TelephonyCall& aCall, - TelephonyCall& aSecondCall, - ErrorResult& aRv) -{ - RefPtr promise = CreatePromise(aRv); - if (!promise) { - return nullptr; - } - - if (!CanConference(aCall, &aSecondCall)) { - promise->MaybeReject(NS_ERROR_NOT_AVAILABLE); - return promise.forget(); - } - - nsCOMPtr callback = new TelephonyCallback(promise); - aRv = mTelephony->Service()->ConferenceCall(aCall.ServiceId(), callback); - NS_ENSURE_TRUE(!aRv.Failed(), nullptr); - - return promise.forget(); -} - -already_AddRefed -TelephonyCallGroup::Remove(TelephonyCall& aCall, ErrorResult& aRv) -{ - MOZ_ASSERT(!mCalls.IsEmpty()); - - RefPtr promise = CreatePromise(aRv); - if (!promise) { - return nullptr; - } - - if (mState != TelephonyCallGroupState::Connected) { - NS_WARNING("Remove call from a non-connected call group. Ignore!"); - promise->MaybeReject(NS_ERROR_DOM_INVALID_STATE_ERR); - return promise.forget(); - } - - uint32_t serviceId = aCall.ServiceId(); - uint32_t callIndex = aCall.CallIndex(); - - RefPtr call = GetCall(serviceId, callIndex); - if (!call) { - NS_WARNING("Didn't have this call. Ignore!"); - promise->MaybeReject(NS_ERROR_NOT_AVAILABLE); - return promise.forget(); - } - - nsCOMPtr callback = new TelephonyCallback(promise); - aRv = mTelephony->Service()->SeparateCall(serviceId, callIndex, callback); - NS_ENSURE_TRUE(!aRv.Failed(), nullptr); - - return promise.forget(); -} - -already_AddRefed -TelephonyCallGroup::HangUp(ErrorResult& aRv) -{ - MOZ_ASSERT(!mCalls.IsEmpty()); - - RefPtr promise = CreatePromise(aRv); - if (!promise) { - return nullptr; - } - - if (mState == TelephonyCallGroupState::_empty) { - NS_WARNING(nsPrintfCString("We don't have a call group now!" - " (State: %s)", - TELEPHONY_GROUP_STATE(mState)).get()); - promise->MaybeReject(NS_ERROR_DOM_INVALID_STATE_ERR); - return promise.forget(); - } - - nsCOMPtr callback = new TelephonyCallback(promise); - aRv = mTelephony->Service()->HangUpConference(mCalls[0]->ServiceId(), - callback); - NS_ENSURE_TRUE(!aRv.Failed(), nullptr); - return promise.forget(); -} - -already_AddRefed -TelephonyCallGroup::Hold(ErrorResult& aRv) -{ - MOZ_ASSERT(!mCalls.IsEmpty()); - - RefPtr promise = CreatePromise(aRv); - if (!promise) { - return nullptr; - } - - nsCOMPtr callback = new TelephonyCallback(promise); - aRv = Hold(callback); - if (NS_WARN_IF(aRv.Failed() && - !aRv.ErrorCodeIs(NS_ERROR_DOM_INVALID_STATE_ERR))) { - return nullptr; - } - - return promise.forget(); -} - -nsresult -TelephonyCallGroup::Hold(nsITelephonyCallback* aCallback) -{ - if (mState != TelephonyCallGroupState::Connected) { - NS_WARNING(nsPrintfCString("Resume non-connected call group is rejected!" - " (State: %s)", - TELEPHONY_GROUP_STATE(mState)).get()); - aCallback->NotifyError(NS_LITERAL_STRING("InvalidStateError")); - return NS_ERROR_DOM_INVALID_STATE_ERR; - } - - nsresult rv = mTelephony->Service()->HoldConference(mCalls[0]->ServiceId(), - aCallback); - if (NS_WARN_IF(NS_FAILED(rv))) { - return NS_ERROR_FAILURE; - } - - return NS_OK; -} - -already_AddRefed -TelephonyCallGroup::Resume(ErrorResult& aRv) -{ - MOZ_ASSERT(!mCalls.IsEmpty()); - - RefPtr promise = CreatePromise(aRv); - if (!promise) { - return nullptr; - } - - nsCOMPtr callback = new TelephonyCallback(promise); - aRv = Resume(callback); - if (NS_WARN_IF(aRv.Failed() && - !aRv.ErrorCodeIs(NS_ERROR_DOM_INVALID_STATE_ERR))) { - return nullptr; - } - - return promise.forget(); -} - -nsresult -TelephonyCallGroup::Resume(nsITelephonyCallback* aCallback) -{ - if (mState != TelephonyCallGroupState::Held) { - NS_WARNING(nsPrintfCString("Resume non-held call group is rejected!" - " (State: %s)", - TELEPHONY_GROUP_STATE(mState)).get()); - aCallback->NotifyError(NS_LITERAL_STRING("InvalidStateError")); - return NS_ERROR_DOM_INVALID_STATE_ERR; - } - - nsresult rv = mTelephony->Service()->ResumeConference(mCalls[0]->ServiceId(), - aCallback); - if (NS_WARN_IF(NS_FAILED(rv))) { - return NS_ERROR_FAILURE; - } - - return NS_OK; -} diff --git a/dom/telephony/TelephonyCallGroup.h b/dom/telephony/TelephonyCallGroup.h deleted file mode 100644 index 5c1336a879cf..000000000000 --- a/dom/telephony/TelephonyCallGroup.h +++ /dev/null @@ -1,140 +0,0 @@ -/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ -/* vim: set ts=8 sts=2 et sw=2 tw=80: */ -/* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ - -#ifndef mozilla_dom_telephony_telephonycallgroup_h__ -#define mozilla_dom_telephony_telephonycallgroup_h__ - -#include "mozilla/dom/Promise.h" -#include "mozilla/dom/TelephonyCallGroupBinding.h" -#include "mozilla/dom/telephony/TelephonyCommon.h" - -namespace mozilla { -namespace dom { - -class TelephonyCallGroup final : public DOMEventTargetHelper -{ - RefPtr mTelephony; - - nsTArray > mCalls; - - RefPtr mCallsList; - - MOZ_INIT_OUTSIDE_CTOR TelephonyCallGroupState mState; - -public: - NS_DECL_ISUPPORTS_INHERITED - NS_DECL_CYCLE_COLLECTION_CLASS_INHERITED(TelephonyCallGroup, - DOMEventTargetHelper) - - friend class Telephony; - - nsPIDOMWindowInner* - GetParentObject() const - { - return GetOwner(); - } - - // WrapperCache - virtual JSObject* - WrapObject(JSContext* aCx, JS::Handle aGivenProto) override; - - // WebIDL interface - already_AddRefed - Calls() const; - - already_AddRefed - Add(TelephonyCall& aCall, ErrorResult& aRv); - - already_AddRefed - Add(TelephonyCall& aCall, TelephonyCall& aSecondCall, ErrorResult& aRv); - - already_AddRefed - Remove(TelephonyCall& aCall, ErrorResult& aRv); - - already_AddRefed - HangUp(ErrorResult& aRv); - - already_AddRefed - Hold(ErrorResult& aRv); - - already_AddRefed - Resume(ErrorResult& aRv); - - TelephonyCallGroupState - State() const - { - return mState; - } - - bool - IsActive() { - return mState == TelephonyCallGroupState::Connected; - } - - IMPL_EVENT_HANDLER(statechange) - IMPL_EVENT_HANDLER(connected) - IMPL_EVENT_HANDLER(held) - IMPL_EVENT_HANDLER(callschanged) - IMPL_EVENT_HANDLER(error) - - static already_AddRefed - Create(Telephony* aTelephony); - - void - AddCall(TelephonyCall* aCall); - - void - RemoveCall(TelephonyCall* aCall); - - already_AddRefed - GetCall(uint32_t aServiceId, uint32_t aCallIndex); - - const nsTArray >& - CallsArray() const - { - return mCalls; - } - - // Update its call state according to the calls wihtin itself. - void - ChangeState(); - - nsresult - NotifyError(const nsAString& aName, const nsAString& aMessage); - -private: - explicit TelephonyCallGroup(nsPIDOMWindowInner* aOwner); - ~TelephonyCallGroup(); - - nsresult - Hold(nsITelephonyCallback* aCallback); - - nsresult - Resume(nsITelephonyCallback* aCallback); - - nsresult - NotifyStateChanged(); - - nsresult - NotifyCallsChanged(TelephonyCall* aCall); - - void - ChangeStateInternal(TelephonyCallGroupState aState); - - nsresult - DispatchCallEvent(const nsAString& aType, - TelephonyCall* aCall); - - already_AddRefed - CreatePromise(ErrorResult& aRv); - - bool CanConference(const TelephonyCall& aCall, const TelephonyCall* aSecondCall); -}; - -} // namespace dom -} // namespace mozilla - -#endif // mozilla_dom_telephony_telephonycallgroup_h__ diff --git a/dom/telephony/TelephonyCallId.cpp b/dom/telephony/TelephonyCallId.cpp deleted file mode 100644 index 12b2cdca80bf..000000000000 --- a/dom/telephony/TelephonyCallId.cpp +++ /dev/null @@ -1,76 +0,0 @@ -/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ -/* vim: set ts=8 sts=2 et sw=2 tw=80: */ -/* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ - -#include "TelephonyCallId.h" - -#include "nsITelephonyService.h" - -namespace mozilla { -namespace dom { - -TelephonyCallId::TelephonyCallId(nsPIDOMWindowInner* aWindow, - const nsAString& aNumber, - uint16_t aNumberPresentation, - const nsAString& aName, - uint16_t aNamePresentation) -: mWindow(aWindow), mNumber(aNumber), mNumberPresentation(aNumberPresentation), - mName(aName), mNamePresentation(aNamePresentation) -{ -} - -TelephonyCallId::~TelephonyCallId() -{ -} - -JSObject* -TelephonyCallId::WrapObject(JSContext* aCx, JS::Handle aGivenProto) -{ - return TelephonyCallIdBinding::Wrap(aCx, this, aGivenProto); -} - -CallIdPresentation -TelephonyCallId::GetPresentationStr(uint16_t aPresentation) const -{ - switch (aPresentation) { - case nsITelephonyService::CALL_PRESENTATION_ALLOWED: - return CallIdPresentation::Allowed; - case nsITelephonyService::CALL_PRESENTATION_RESTRICTED: - return CallIdPresentation::Restricted; - case nsITelephonyService::CALL_PRESENTATION_UNKNOWN: - return CallIdPresentation::Unknown; - case nsITelephonyService::CALL_PRESENTATION_PAYPHONE: - return CallIdPresentation::Payphone; - default: - MOZ_CRASH("Bad presentation!"); - } -} - -NS_IMPL_CYCLE_COLLECTION_WRAPPERCACHE(TelephonyCallId, mWindow) - -NS_IMPL_CYCLE_COLLECTING_ADDREF(TelephonyCallId) -NS_IMPL_CYCLE_COLLECTING_RELEASE(TelephonyCallId) - -NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(TelephonyCallId) - NS_WRAPPERCACHE_INTERFACE_MAP_ENTRY - NS_INTERFACE_MAP_ENTRY(nsISupports) -NS_INTERFACE_MAP_END - -// WebIDL - -CallIdPresentation -TelephonyCallId::NumberPresentation() const -{ - return GetPresentationStr(mNumberPresentation); -} - -CallIdPresentation -TelephonyCallId::NamePresentation() const -{ - return GetPresentationStr(mNamePresentation); -} - -} // namespace dom -} // namespace mozilla diff --git a/dom/telephony/TelephonyCallId.h b/dom/telephony/TelephonyCallId.h deleted file mode 100644 index 70756f0023f6..000000000000 --- a/dom/telephony/TelephonyCallId.h +++ /dev/null @@ -1,82 +0,0 @@ -/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ -/* vim: set ts=8 sts=2 et sw=2 tw=80: */ -/* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ - -#ifndef mozilla_dom_TelephonyCallId_h -#define mozilla_dom_TelephonyCallId_h - -#include "mozilla/dom/TelephonyCallIdBinding.h" -#include "mozilla/dom/telephony/TelephonyCommon.h" - -#include "nsWrapperCache.h" - -class nsPIDOMWindowInner; - -namespace mozilla { -namespace dom { - -class TelephonyCallId final : public nsISupports, - public nsWrapperCache -{ -public: - NS_DECL_CYCLE_COLLECTING_ISUPPORTS - NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_CLASS(TelephonyCallId) - - TelephonyCallId(nsPIDOMWindowInner* aWindow, const nsAString& aNumber, - uint16_t aNumberPresentation, const nsAString& aName, - uint16_t aNamePresentation); - - nsPIDOMWindowInner* - GetParentObject() const - { - return mWindow; - } - - virtual JSObject* - WrapObject(JSContext* aCx, JS::Handle aGivenProto) override; - - // WebIDL - - void - GetNumber(nsString& aNumber) const - { - aNumber.Assign(mNumber); - } - - CallIdPresentation - NumberPresentation() const; - - void - GetName(nsString& aName) const - { - aName.Assign(mName); - } - - CallIdPresentation - NamePresentation() const; - - void - UpdateNumber(const nsAString& aNumber) - { - mNumber = aNumber; - } - -private: - ~TelephonyCallId(); - - nsCOMPtr mWindow; - nsString mNumber; - uint16_t mNumberPresentation; - nsString mName; - uint16_t mNamePresentation; - - CallIdPresentation - GetPresentationStr(uint16_t aPresentation) const; -}; - -} // namespace dom -} // namespace mozilla - -#endif // mozilla_dom_TelephonyCallId_h diff --git a/dom/telephony/TelephonyCallInfo.cpp b/dom/telephony/TelephonyCallInfo.cpp deleted file mode 100644 index 8ad6923f8c21..000000000000 --- a/dom/telephony/TelephonyCallInfo.cpp +++ /dev/null @@ -1,141 +0,0 @@ -/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ -/* vim: set ts=8 sts=2 et sw=2 tw=80: */ -/* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this file, - * You can obtain one at http://mozilla.org/MPL/2.0/. */ - -#include "mozilla/dom/telephony/TelephonyCallInfo.h" - -namespace mozilla { -namespace dom { -namespace telephony { - -NS_IMPL_ISUPPORTS(TelephonyCallInfo, nsITelephonyCallInfo) - -TelephonyCallInfo::TelephonyCallInfo(uint32_t aClientId, - uint32_t aCallIndex, - uint16_t aCallState, - const nsAString& aDisconnectedReason, - - const nsAString& aNumber, - uint16_t aNumberPresentation, - const nsAString& aName, - uint16_t aNamePresentation, - - bool aIsOutgoing, - bool aIsEmergency, - bool aIsConference, - bool aIsSwitchable, - bool aIsMergeable) - : mClientId(aClientId), - mCallIndex(aCallIndex), - mCallState(aCallState), - mDisconnectedReason(aDisconnectedReason), - - mNumber(aNumber), - mNumberPresentation(aNumberPresentation), - mName(aName), - mNamePresentation(aNamePresentation), - - mIsOutgoing(aIsOutgoing), - mIsEmergency(aIsEmergency), - mIsConference(aIsConference), - mIsSwitchable(aIsSwitchable), - mIsMergeable(aIsMergeable) -{ -} - -NS_IMETHODIMP -TelephonyCallInfo::GetClientId(uint32_t* aClientId) -{ - *aClientId = mClientId; - return NS_OK; -} - -NS_IMETHODIMP -TelephonyCallInfo::GetCallIndex(uint32_t* aCallIndex) -{ - *aCallIndex = mCallIndex; - return NS_OK; -} - -NS_IMETHODIMP -TelephonyCallInfo::GetCallState(uint16_t* aCallState) -{ - *aCallState = mCallState; - return NS_OK; -} - -NS_IMETHODIMP -TelephonyCallInfo::GetDisconnectedReason(nsAString& aDisconnectedReason) -{ - aDisconnectedReason = mDisconnectedReason; - return NS_OK; -} - -NS_IMETHODIMP -TelephonyCallInfo::GetNumber(nsAString& aNumber) -{ - aNumber = mNumber; - return NS_OK; -} - -NS_IMETHODIMP -TelephonyCallInfo::GetNumberPresentation(uint16_t* aNumberPresentation) -{ - *aNumberPresentation = mNumberPresentation; - return NS_OK; -} - -NS_IMETHODIMP -TelephonyCallInfo::GetName(nsAString& aName) -{ - aName = mName; - return NS_OK; -} - -NS_IMETHODIMP -TelephonyCallInfo::GetNamePresentation(uint16_t* aNamePresentation) -{ - *aNamePresentation = mNamePresentation; - return NS_OK; -} - -NS_IMETHODIMP -TelephonyCallInfo::GetIsOutgoing(bool* aIsOutgoing) -{ - *aIsOutgoing = mIsOutgoing; - return NS_OK; -} - -NS_IMETHODIMP -TelephonyCallInfo::GetIsEmergency(bool* aIsEmergency) -{ - *aIsEmergency = mIsEmergency; - return NS_OK; -} - -NS_IMETHODIMP -TelephonyCallInfo::GetIsConference(bool* aIsConference) -{ - *aIsConference = mIsConference; - return NS_OK; -} - -NS_IMETHODIMP -TelephonyCallInfo::GetIsSwitchable(bool* aIsSwitchable) -{ - *aIsSwitchable = mIsSwitchable; - return NS_OK; -} - -NS_IMETHODIMP -TelephonyCallInfo::GetIsMergeable(bool* aIsMergeable) -{ - *aIsMergeable = mIsMergeable; - return NS_OK; -} - -} // namespace telephony -} // namespace dom -} // namespace mozilla diff --git a/dom/telephony/TelephonyCallInfo.h b/dom/telephony/TelephonyCallInfo.h deleted file mode 100644 index 81be49aa5b6b..000000000000 --- a/dom/telephony/TelephonyCallInfo.h +++ /dev/null @@ -1,67 +0,0 @@ -/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ -/* vim: set ts=8 sts=2 et sw=2 tw=80: */ -/* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this file, - * You can obtain one at http://mozilla.org/MPL/2.0/. */ - -#ifndef mozilla_dom_TelephonyCallInfo_h -#define mozilla_dom_TelephonyCallInfo_h - -#include "nsITelephonyCallInfo.h" -#include "nsString.h" -#include "mozilla/Attributes.h" - -namespace mozilla { -namespace dom { -namespace telephony { - -class TelephonyCallInfo final : public nsITelephonyCallInfo -{ -public: - NS_DECL_ISUPPORTS - NS_DECL_NSITELEPHONYCALLINFO - - TelephonyCallInfo(uint32_t aClientId, - uint32_t aCallIndex, - uint16_t aCallState, - const nsAString& aDisconnectedReason, - - const nsAString& aNumber, - uint16_t aNumberPresentation, - const nsAString& aName, - uint16_t aNamePresentation, - - bool aIsOutgoing, - bool aIsEmergency, - bool aIsConference, - bool aIsSwitchable, - bool aIsMergeable); - -private: - // Don't try to use the default constructor. - TelephonyCallInfo() {} - - ~TelephonyCallInfo() {} - - uint32_t mClientId; - uint32_t mCallIndex; - uint16_t mCallState; - nsString mDisconnectedReason; - - nsString mNumber; - uint16_t mNumberPresentation; - nsString mName; - uint16_t mNamePresentation; - - bool mIsOutgoing; - bool mIsEmergency; - bool mIsConference; - bool mIsSwitchable; - bool mIsMergeable; -}; - -} // namespace telephony -} // namespace dom -} // namespace mozilla - -#endif // mozilla_dom_TelephonyCallInfo_h diff --git a/dom/telephony/TelephonyCallback.cpp b/dom/telephony/TelephonyCallback.cpp deleted file mode 100644 index 5cea35bb5eca..000000000000 --- a/dom/telephony/TelephonyCallback.cpp +++ /dev/null @@ -1,36 +0,0 @@ -/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ -/* vim: set ts=8 sts=2 et sw=2 tw=80: */ -/* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this file, - * You can obtain one at http://mozilla.org/MPL/2.0/. */ - -#include "TelephonyCallback.h" - -#include "mozilla/dom/Promise.h" -#include "nsJSUtils.h" - -using namespace mozilla::dom; -using namespace mozilla::dom::telephony; - -NS_IMPL_ISUPPORTS(TelephonyCallback, nsITelephonyCallback) - -TelephonyCallback::TelephonyCallback(Promise* aPromise) - : mPromise(aPromise) -{ -} - -// nsITelephonyCallback - -NS_IMETHODIMP -TelephonyCallback::NotifySuccess() -{ - mPromise->MaybeResolveWithUndefined(); - return NS_OK; -} - -NS_IMETHODIMP -TelephonyCallback::NotifyError(const nsAString& aError) -{ - mPromise->MaybeRejectBrokenly(aError); - return NS_OK; -} diff --git a/dom/telephony/TelephonyCallback.h b/dom/telephony/TelephonyCallback.h deleted file mode 100644 index 534ec1714c0a..000000000000 --- a/dom/telephony/TelephonyCallback.h +++ /dev/null @@ -1,39 +0,0 @@ -/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ -/* vim: set ts=8 sts=2 et sw=2 tw=80: */ -/* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this file, - * You can obtain one at http://mozilla.org/MPL/2.0/. */ - -#ifndef mozilla_dom_TelephonyCallback_h -#define mozilla_dom_TelephonyCallback_h - -#include "nsCOMPtr.h" -#include "nsITelephonyService.h" - -namespace mozilla { -namespace dom { - -class Promise; - -namespace telephony { - -class TelephonyCallback : public nsITelephonyCallback -{ -public: - NS_DECL_ISUPPORTS - NS_DECL_NSITELEPHONYCALLBACK - - explicit TelephonyCallback(Promise* aPromise); - -protected: - virtual ~TelephonyCallback() {} - -protected: - RefPtr mPromise; -}; - -} // namespace telephony -} // namespace dom -} // namespace mozilla - -#endif // mozilla_dom_TelephonyCallback_h diff --git a/dom/telephony/TelephonyCommon.h b/dom/telephony/TelephonyCommon.h deleted file mode 100644 index 1524f1f9acd0..000000000000 --- a/dom/telephony/TelephonyCommon.h +++ /dev/null @@ -1,37 +0,0 @@ -/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ -/* vim: set ts=8 sts=2 et sw=2 tw=80: */ -/* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ - -#ifndef mozilla_dom_telephony_telephonycommon_h__ -#define mozilla_dom_telephony_telephonycommon_h__ - -#include "mozilla/Attributes.h" -#include "mozilla/DOMEventTargetHelper.h" -#include "mozilla/ErrorResult.h" -#include "nsCOMPtr.h" -#include "nsCycleCollectionParticipant.h" -#include "nsDebug.h" -#include "nsString.h" -#include "nsTArray.h" - -#define BEGIN_TELEPHONY_NAMESPACE \ - namespace mozilla { namespace dom { namespace telephony { -#define END_TELEPHONY_NAMESPACE \ - } /* namespace telephony */ } /* namespace dom */ } /* namespace mozilla */ -#define USING_TELEPHONY_NAMESPACE \ - using namespace mozilla::dom::telephony; - -namespace mozilla { -namespace dom { - -class CallsList; -class Telephony; -class TelephonyCall; -class TelephonyCallGroup; - -} // namespace dom -} // namespace mozilla - -#endif // mozilla_dom_telephony_telephonycommon_h__ diff --git a/dom/telephony/TelephonyDialCallback.cpp b/dom/telephony/TelephonyDialCallback.cpp deleted file mode 100644 index 139eb2697e21..000000000000 --- a/dom/telephony/TelephonyDialCallback.cpp +++ /dev/null @@ -1,246 +0,0 @@ -/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ -/* vim: set ts=8 sts=2 et sw=2 tw=80: */ -/* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this file, - * You can obtain one at http://mozilla.org/MPL/2.0/. */ - -#include "TelephonyDialCallback.h" - -#include "mozilla/dom/MozMobileConnectionBinding.h" -#include "nsIMobileCallForwardingOptions.h" -#include "nsIMobileConnectionService.h" - -using namespace mozilla::dom; -using namespace mozilla::dom::telephony; - -NS_IMPL_ISUPPORTS_INHERITED(TelephonyDialCallback, TelephonyCallback, - nsITelephonyDialCallback) - -TelephonyDialCallback::TelephonyDialCallback(nsPIDOMWindowInner* aWindow, - Telephony* aTelephony, - Promise* aPromise) - : TelephonyCallback(aPromise), mWindow(aWindow), mTelephony(aTelephony) -{ - MOZ_ASSERT(mTelephony); -} - -nsresult -TelephonyDialCallback::NotifyDialMMISuccess(JSContext* aCx, - const MozMMIResult& aResult) -{ - JS::Rooted jsResult(aCx); - - if (!ToJSValue(aCx, aResult, &jsResult)) { - JS_ClearPendingException(aCx); - return NS_ERROR_TYPE_ERR; - } - - mMMICall->NotifyResult(jsResult); - return NS_OK; -} - -// nsITelephonyDialCallback - -NS_IMETHODIMP -TelephonyDialCallback::NotifyDialMMI(const nsAString& aServiceCode) -{ - mServiceCode.Assign(aServiceCode); - - mMMICall = new MMICall(mWindow, aServiceCode); - mPromise->MaybeResolve(mMMICall); - return NS_OK; -} - -NS_IMETHODIMP -TelephonyDialCallback::NotifyDialCallSuccess(uint32_t aClientId, - uint32_t aCallIndex, - const nsAString& aNumber) -{ - RefPtr id = mTelephony->CreateCallId(aNumber); - RefPtr call = - mTelephony->CreateCall(id, aClientId, aCallIndex, - TelephonyCallState::Dialing); - - mPromise->MaybeResolve(call); - return NS_OK; -} - -NS_IMETHODIMP -TelephonyDialCallback::NotifyDialMMISuccess(const nsAString& aStatusMessage) -{ - AutoJSAPI jsapi; - if (NS_WARN_IF(!jsapi.Init(mWindow))) { - return NS_ERROR_FAILURE; - } - - JSContext* cx = jsapi.cx(); - - RootedDictionary result(cx); - result.mSuccess = true; - result.mServiceCode.Assign(mServiceCode); - result.mStatusMessage.Assign(aStatusMessage); - - return NotifyDialMMISuccess(cx, result); -} - -NS_IMETHODIMP -TelephonyDialCallback::NotifyDialMMISuccessWithInteger(const nsAString& aStatusMessage, - uint16_t aAdditionalInformation) -{ - AutoJSAPI jsapi; - if (NS_WARN_IF(!jsapi.Init(mWindow))) { - return NS_ERROR_FAILURE; - } - - JSContext* cx = jsapi.cx(); - - RootedDictionary result(cx); - result.mSuccess = true; - result.mServiceCode.Assign(mServiceCode); - result.mStatusMessage.Assign(aStatusMessage); - result.mAdditionalInformation.Construct().SetAsUnsignedShort() = aAdditionalInformation; - - return NotifyDialMMISuccess(cx, result); -} - -NS_IMETHODIMP -TelephonyDialCallback::NotifyDialMMISuccessWithStrings(const nsAString& aStatusMessage, - uint32_t aCount, - const char16_t** aAdditionalInformation) -{ - AutoJSAPI jsapi; - if (NS_WARN_IF(!jsapi.Init(mWindow))) { - return NS_ERROR_FAILURE; - } - - JSContext* cx = jsapi.cx(); - - RootedDictionary result(cx); - result.mSuccess = true; - result.mServiceCode.Assign(mServiceCode); - result.mStatusMessage.Assign(aStatusMessage); - - nsTArray additionalInformation; - nsString* infos = additionalInformation.AppendElements(aCount); - for (uint32_t i = 0; i < aCount; i++) { - infos[i].Rebind(aAdditionalInformation[i], - nsCharTraits::length(aAdditionalInformation[i])); - } - - JS::Rooted jsAdditionalInformation(cx); - if (!ToJSValue(cx, additionalInformation, &jsAdditionalInformation)) { - JS_ClearPendingException(cx); - return NS_ERROR_TYPE_ERR; - } - - result.mAdditionalInformation.Construct().SetAsObject() = - &jsAdditionalInformation.toObject(); - - return NotifyDialMMISuccess(cx, result); -} - -NS_IMETHODIMP -TelephonyDialCallback::NotifyDialMMISuccessWithCallForwardingOptions(const nsAString& aStatusMessage, - uint32_t aCount, - nsIMobileCallForwardingOptions** aResults) -{ - AutoJSAPI jsapi; - if (NS_WARN_IF(!jsapi.Init(mWindow))) { - return NS_ERROR_FAILURE; - } - - JSContext* cx = jsapi.cx(); - - RootedDictionary result(cx); - result.mSuccess = true; - result.mServiceCode.Assign(mServiceCode); - result.mStatusMessage.Assign(aStatusMessage); - - nsTArray additionalInformation; - for (uint32_t i = 0; i < aCount; i++) { - MozCallForwardingOptions options; - - bool active = false; - aResults[i]->GetActive(&active); - options.mActive.Construct(active); - - int16_t action = nsIMobileConnection::CALL_FORWARD_ACTION_UNKNOWN; - aResults[i]->GetAction(&action); - if (action != nsIMobileConnection::CALL_FORWARD_ACTION_UNKNOWN) { - options.mAction.Construct(action); - } - - int16_t reason = nsIMobileConnection::CALL_FORWARD_REASON_UNKNOWN; - aResults[i]->GetReason(&reason); - if (reason != nsIMobileConnection::CALL_FORWARD_REASON_UNKNOWN) { - options.mReason.Construct(reason); - } - - nsAutoString number; - aResults[i]->GetNumber(number); - options.mNumber.Construct(number.get()); - - int16_t timeSeconds = -1; - aResults[i]->GetTimeSeconds(&timeSeconds); - if (timeSeconds >= 0) { - options.mTimeSeconds.Construct(timeSeconds); - } - - int16_t serviceClass = nsIMobileConnection::ICC_SERVICE_CLASS_NONE; - aResults[i]->GetServiceClass(&serviceClass); - if (serviceClass != nsIMobileConnection::ICC_SERVICE_CLASS_NONE) { - options.mServiceClass.Construct(serviceClass); - } - - additionalInformation.AppendElement(options); - } - - JS::Rooted jsAdditionalInformation(cx); - if (!ToJSValue(cx, additionalInformation, &jsAdditionalInformation)) { - JS_ClearPendingException(cx); - return NS_ERROR_TYPE_ERR; - } - - result.mAdditionalInformation.Construct().SetAsObject() = - &jsAdditionalInformation.toObject(); - - return NotifyDialMMISuccess(cx, result); -} - -NS_IMETHODIMP -TelephonyDialCallback::NotifyDialMMIError(const nsAString& aError) -{ - AutoJSAPI jsapi; - if (NS_WARN_IF(!jsapi.Init(mWindow))) { - return NS_ERROR_FAILURE; - } - - JSContext* cx = jsapi.cx(); - - RootedDictionary result(cx); - result.mSuccess = false; - result.mServiceCode.Assign(mServiceCode); - result.mStatusMessage.Assign(aError); - - return NotifyDialMMISuccess(cx, result); -} - -NS_IMETHODIMP -TelephonyDialCallback::NotifyDialMMIErrorWithInfo(const nsAString& aError, - uint16_t aInfo) -{ - AutoJSAPI jsapi; - if (NS_WARN_IF(!jsapi.Init(mWindow))) { - return NS_ERROR_FAILURE; - } - - JSContext* cx = jsapi.cx(); - - RootedDictionary result(cx); - result.mSuccess = false; - result.mServiceCode.Assign(mServiceCode); - result.mStatusMessage.Assign(aError); - result.mAdditionalInformation.Construct().SetAsUnsignedShort() = aInfo; - - return NotifyDialMMISuccess(cx, result); -} diff --git a/dom/telephony/TelephonyDialCallback.h b/dom/telephony/TelephonyDialCallback.h deleted file mode 100644 index d896042948bb..000000000000 --- a/dom/telephony/TelephonyDialCallback.h +++ /dev/null @@ -1,57 +0,0 @@ -/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ -/* vim: set ts=8 sts=2 et sw=2 tw=80: */ -/* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this file, - * You can obtain one at http://mozilla.org/MPL/2.0/. */ - -#ifndef mozilla_dom_TelephonyDialCallback_h -#define mozilla_dom_TelephonyDialCallback_h - -#include "Telephony.h" -#include "mozilla/dom/MMICall.h" -#include "mozilla/dom/MozMobileConnectionBinding.h" -#include "mozilla/dom/Promise.h" -#include "mozilla/dom/ToJSValue.h" -#include "mozilla/dom/telephony/TelephonyCallback.h" -#include "nsCOMPtr.h" -#include "nsITelephonyService.h" -#include "nsJSUtils.h" -#include "nsString.h" - -class nsPIDOMWindowInner; - -namespace mozilla { -namespace dom { -namespace telephony { - -class TelephonyDialCallback final : public TelephonyCallback, - public nsITelephonyDialCallback -{ -public: - NS_DECL_ISUPPORTS_INHERITED - NS_DECL_NSITELEPHONYDIALCALLBACK - - TelephonyDialCallback(nsPIDOMWindowInner* aWindow, Telephony* aTelephony, - Promise* aPromise); - - NS_FORWARD_NSITELEPHONYCALLBACK(TelephonyCallback::) - -private: - ~TelephonyDialCallback() {} - - nsresult - NotifyDialMMISuccess(JSContext* aCx, const MozMMIResult& aResult); - - - nsCOMPtr mWindow; - RefPtr mTelephony; - - nsString mServiceCode; - RefPtr mMMICall; -}; - -} // namespace telephony -} // namespace dom -} // namespace mozilla - -#endif // mozilla_dom_TelephonyDialCallback_h diff --git a/dom/telephony/USSDSession.cpp b/dom/telephony/USSDSession.cpp deleted file mode 100644 index 0dc4d43fa518..000000000000 --- a/dom/telephony/USSDSession.cpp +++ /dev/null @@ -1,128 +0,0 @@ -/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ -/* vim: set ts=8 sts=2 et sw=2 tw=80: */ -/* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ - -#include "mozilla/dom/USSDSession.h" - -#include "mozilla/dom/USSDSessionBinding.h" -#include "mozilla/dom/telephony/TelephonyCallback.h" -#include "nsIGlobalObject.h" -#include "nsServiceManagerUtils.h" - -using namespace mozilla::dom; -using namespace mozilla::dom::telephony; -using mozilla::ErrorResult; - -NS_IMPL_CYCLE_COLLECTION_WRAPPERCACHE(USSDSession, mWindow) -NS_IMPL_CYCLE_COLLECTING_ADDREF(USSDSession) -NS_IMPL_CYCLE_COLLECTING_RELEASE(USSDSession) -NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(USSDSession) - NS_WRAPPERCACHE_INTERFACE_MAP_ENTRY - NS_INTERFACE_MAP_ENTRY(nsISupports) -NS_INTERFACE_MAP_END - -USSDSession::USSDSession(nsPIDOMWindowInner* aWindow, - nsITelephonyService* aService, - uint32_t aServiceId) - : mWindow(aWindow), mService(aService), mServiceId(aServiceId) -{ -} - -USSDSession::~USSDSession() -{ -} - -nsPIDOMWindowInner* -USSDSession::GetParentObject() const -{ - return mWindow; -} - -JSObject* -USSDSession::WrapObject(JSContext* aCx, JS::Handle aGivenProto) -{ - return USSDSessionBinding::Wrap(aCx, this, aGivenProto); -} - -already_AddRefed -USSDSession::CreatePromise(ErrorResult& aRv) -{ - if (!mService) { - aRv.Throw(NS_ERROR_FAILURE); - return nullptr; - } - - nsCOMPtr global = do_QueryInterface(mWindow); - if (!global) { - aRv.Throw(NS_ERROR_FAILURE); - return nullptr; - } - - RefPtr promise = Promise::Create(global, aRv); - if (aRv.Failed()) { - return nullptr; - } - - return promise.forget(); -} - -// WebIDL - -already_AddRefed -USSDSession::Constructor(const GlobalObject& aGlobal, uint32_t aServiceId, - ErrorResult& aRv) -{ - nsCOMPtr window = do_QueryInterface(aGlobal.GetAsSupports()); - if (!window) { - aRv.Throw(NS_ERROR_UNEXPECTED); - return nullptr; - } - - nsCOMPtr ril = - do_GetService(TELEPHONY_SERVICE_CONTRACTID); - if (!ril) { - aRv.Throw(NS_ERROR_UNEXPECTED); - return nullptr; - } - - RefPtr session = new USSDSession(window, ril, aServiceId); - return session.forget(); -} - -already_AddRefed -USSDSession::Send(const nsAString& aUssd, ErrorResult& aRv) -{ - RefPtr promise = CreatePromise(aRv); - if (!promise) { - return nullptr; - } - - nsCOMPtr callback = new TelephonyCallback(promise); - - nsresult rv = mService->SendUSSD(mServiceId, aUssd, callback); - if (NS_FAILED(rv)) { - promise->MaybeReject(NS_ERROR_DOM_INVALID_STATE_ERR); - } - - return promise.forget(); -} - -already_AddRefed -USSDSession::Cancel(ErrorResult& aRv) -{ - RefPtr promise = CreatePromise(aRv); - if (!promise) { - return nullptr; - } - - nsCOMPtr callback = new TelephonyCallback(promise); - - nsresult rv = mService->CancelUSSD(mServiceId, callback); - if (NS_FAILED(rv)) { - promise->MaybeReject(NS_ERROR_DOM_INVALID_STATE_ERR); - } - - return promise.forget(); -} diff --git a/dom/telephony/USSDSession.h b/dom/telephony/USSDSession.h deleted file mode 100644 index 17f87cd9135a..000000000000 --- a/dom/telephony/USSDSession.h +++ /dev/null @@ -1,66 +0,0 @@ -/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ -/* vim: set ts=8 sts=2 et sw=2 tw=80: */ -/* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ - -#ifndef mozilla_dom_USSDSession_h -#define mozilla_dom_USSDSession_h - -#include "mozilla/Attributes.h" -#include "mozilla/ErrorResult.h" -#include "mozilla/dom/BindingDeclarations.h" -#include "mozilla/dom/Promise.h" -#include "nsCOMPtr.h" -#include "nsCycleCollectionParticipant.h" -#include "nsITelephonyService.h" -#include "nsPIDOMWindow.h" -#include "nsWrapperCache.h" - -struct JSContext; - -namespace mozilla { -namespace dom { - -class USSDSession final : public nsISupports, - public nsWrapperCache -{ -public: - NS_DECL_CYCLE_COLLECTING_ISUPPORTS - NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_CLASS(USSDSession) - - USSDSession(nsPIDOMWindowInner* aWindow, nsITelephonyService* aService, - uint32_t aServiceId); - - nsPIDOMWindowInner* - GetParentObject() const; - - virtual JSObject* - WrapObject(JSContext* aCx, JS::Handle aGivenProto) override; - - // WebIDL - static already_AddRefed - Constructor(const GlobalObject& aGlobal, uint32_t aServiceId, - ErrorResult& aRv); - - already_AddRefed - Send(const nsAString& aUssd, ErrorResult& aRv); - - already_AddRefed - Cancel(ErrorResult& aRv); - -private: - ~USSDSession(); - - already_AddRefed - CreatePromise(ErrorResult& aRv); - - nsCOMPtr mWindow; - nsCOMPtr mService; - uint32_t mServiceId; -}; - -} // namespace dom -} // namespace mozilla - -#endif // mozilla_dom_USSDSession_h diff --git a/dom/telephony/gonk/DialNumberUtils.jsm b/dom/telephony/gonk/DialNumberUtils.jsm deleted file mode 100644 index 5945b7d25982..000000000000 --- a/dom/telephony/gonk/DialNumberUtils.jsm +++ /dev/null @@ -1,110 +0,0 @@ -/* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this file, - * You can obtain one at http://mozilla.org/MPL/2.0/. */ - -"use strict"; - -this.EXPORTED_SYMBOLS = ["DialNumberUtils"]; - -const {classes: Cc, interfaces: Ci, utils: Cu, results: Cr} = Components; - -Cu.import("resource://gre/modules/systemlibs.js"); - -const DEFAULT_EMERGENCY_NUMBERS = ["112", "911"]; - -const MMI_MATCH_GROUP_FULL_MMI = 1; -const MMI_MATCH_GROUP_PROCEDURE = 2; -const MMI_MATCH_GROUP_SERVICE_CODE = 3; -const MMI_MATCH_GROUP_SIA = 4; -const MMI_MATCH_GROUP_SIB = 5; -const MMI_MATCH_GROUP_SIC = 6; -const MMI_MATCH_GROUP_PWD_CONFIRM = 7; -const MMI_MATCH_GROUP_DIALING_NUMBER = 8; - -this.DialNumberUtils = { - /** - * Check a given number against the list of emergency numbers provided by the - * RIL. - */ - isEmergency: function(aNumber) { - // Check ril provided numbers first. - let numbers = libcutils.property_get("ril.ecclist") || - libcutils.property_get("ro.ril.ecclist"); - if (numbers) { - numbers = numbers.split(","); - } else { - // No ecclist system property, so use our own list. - numbers = DEFAULT_EMERGENCY_NUMBERS; - } - return numbers.indexOf(aNumber) != -1; - }, - - _mmiRegExp: (function() { - // Procedure, which could be *, #, *#, **, ## - let procedure = "(\\*[*#]?|##?)"; - - // Service code, which is a 2 or 3 digits that uniquely specifies the - // Supplementary Service associated with the MMI code. - let serviceCode = "(\\d{2,3})"; - - // Supplementary Information SIA, SIB and SIC. - // Where a particular service request does not require any SI, "*SI" is - // not entered. The use of SIA, SIB and SIC is optional and shall be - // entered in any of the following formats: - // - *SIA*SIB*SIC# - // - *SIA*SIB# - // - *SIA**SIC# - // - *SIA# - // - **SIB*SIC# - // - ***SIC# - // - // Also catch the additional NEW_PASSWORD for the case of a password - // registration procedure. Ex: - // - * 03 * ZZ * OLD_PASSWORD * NEW_PASSWORD * NEW_PASSWORD # - // - ** 03 * ZZ * OLD_PASSWORD * NEW_PASSWORD * NEW_PASSWORD # - // - * 03 ** OLD_PASSWORD * NEW_PASSWORD * NEW_PASSWORD # - // - ** 03 ** OLD_PASSWORD * NEW_PASSWORD * NEW_PASSWORD # - let si = "\\*([^*#]*)"; - let allSi = ""; - for (let i = 0; i < 4; ++i) { - allSi = "(?:" + si + allSi + ")?"; - } - - let fullmmi = "(" + procedure + serviceCode + allSi + "#)"; - - // Dial string after the #. - let optionalDialString = "([^#]+)?"; - - return new RegExp("^" + fullmmi + optionalDialString + "$"); - })(), - - /** - * Check parse the given string as an MMI code. - * - * An MMI code should be: - * - Activation (*SC*SI#). - * - Deactivation (#SC*SI#). - * - Interrogation (*#SC*SI#). - * - Registration (**SC*SI#). - * - Erasure (##SC*SI#). - * where SC = Service Code (2 or 3 digits) and SI = Supplementary Info - * (variable length). - */ - parseMMI: function(aString) { - let matches = this._mmiRegExp.exec(aString); - if (matches) { - return { - fullMMI: matches[MMI_MATCH_GROUP_FULL_MMI], - procedure: matches[MMI_MATCH_GROUP_PROCEDURE], - serviceCode: matches[MMI_MATCH_GROUP_SERVICE_CODE], - sia: matches[MMI_MATCH_GROUP_SIA], - sib: matches[MMI_MATCH_GROUP_SIB], - sic: matches[MMI_MATCH_GROUP_SIC], - pwd: matches[MMI_MATCH_GROUP_PWD_CONFIRM], - dialNumber: matches[MMI_MATCH_GROUP_DIALING_NUMBER] - }; - } - - return null; - } -}; diff --git a/dom/telephony/gonk/TelephonyAudioService.js b/dom/telephony/gonk/TelephonyAudioService.js deleted file mode 100644 index 9a58181dac4c..000000000000 --- a/dom/telephony/gonk/TelephonyAudioService.js +++ /dev/null @@ -1,151 +0,0 @@ -/* -*- indent-tabs-mode: nil; js-indent-level: 2 -*- */ -/* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this file, - * You can obtain one at http://mozilla.org/MPL/2.0/. */ - -"use strict"; - -const {classes: Cc, interfaces: Ci, utils: Cu, results: Cr} = Components; - -Cu.import("resource://gre/modules/Services.jsm"); -Cu.import("resource://gre/modules/XPCOMUtils.jsm"); - -const nsIAudioManager = Ci.nsIAudioManager; -const nsITelephonyAudioService = Ci.nsITelephonyAudioService; - -const NS_PREFBRANCH_PREFCHANGE_TOPIC_ID = "nsPref:changed"; -const kPrefRilDebuggingEnabled = "ril.debugging.enabled"; - -const AUDIO_STATE_NAME = [ - "PHONE_STATE_NORMAL", - "PHONE_STATE_RINGTONE", - "PHONE_STATE_IN_CALL" -]; - -var DEBUG; -function debug(s) { - dump("TelephonyAudioService: " + s + "\n"); -} - -XPCOMUtils.defineLazyGetter(this, "RIL", function () { - let obj = {}; - Cu.import("resource://gre/modules/ril_consts.js", obj); - return obj; -}); - -XPCOMUtils.defineLazyGetter(this, "gAudioManager", function getAudioManager() { - try { - return Cc["@mozilla.org/telephony/audiomanager;1"] - .getService(nsIAudioManager); - } catch (ex) { - //TODO on the phone this should not fall back as silently. - - // Fake nsIAudioManager implementation so that we can run the telephony - // code in a non-Gonk build. - if (DEBUG) debug("Using fake audio manager."); - return { - microphoneMuted: false, - masterVolume: 1.0, - masterMuted: false, - phoneState: nsIAudioManager.PHONE_STATE_CURRENT, - _forceForUse: {}, - - setForceForUse: function(usage, force) { - this._forceForUse[usage] = force; - }, - - getForceForUse: function(usage) { - return this._forceForUse[usage] || nsIAudioManager.FORCE_NONE; - } - }; - } -}); - -function TelephonyAudioService() { - this._updateDebugFlag(); - Services.prefs.addObserver(kPrefRilDebuggingEnabled, this, false); -} -TelephonyAudioService.prototype = { - classDescription: "TelephonyAudioService", - classID: Components.ID("{c8605499-cfec-4cb5-a082-5f1f56d42adf}"), - contractID: "@mozilla.org/telephony/audio-service;1", - QueryInterface: XPCOMUtils.generateQI([Ci.nsITelephonyAudioService, - Ci.nsIObserver]), - - _updateDebugFlag: function() { - try { - DEBUG = RIL.DEBUG_RIL || - Services.prefs.getBoolPref(kPrefRilDebuggingEnabled); - } catch (e) {} - }, - - /** - * nsITelephonyAudioService interface. - */ - - get microphoneMuted() { - return gAudioManager.microphoneMuted; - }, - - set microphoneMuted(aMuted) { - if (aMuted == this.microphoneMuted) { - return; - } - gAudioManager.microphoneMuted = aMuted; - }, - - get speakerEnabled() { - let force = gAudioManager.getForceForUse(nsIAudioManager.USE_COMMUNICATION); - return (force == nsIAudioManager.FORCE_SPEAKER); - }, - - set speakerEnabled(aEnabled) { - if (aEnabled == this.speakerEnabled) { - return; - } - let force = aEnabled ? nsIAudioManager.FORCE_SPEAKER : - nsIAudioManager.FORCE_NONE; - gAudioManager.setForceForUse(nsIAudioManager.USE_COMMUNICATION, force); - }, - - setPhoneState: function(aState) { - switch (aState) { - case nsITelephonyAudioService.PHONE_STATE_NORMAL: - gAudioManager.phoneState = nsIAudioManager.PHONE_STATE_NORMAL; - break; - case nsITelephonyAudioService.PHONE_STATE_RINGTONE: - gAudioManager.phoneState = nsIAudioManager.PHONE_STATE_RINGTONE; - break; - case nsITelephonyAudioService.PHONE_STATE_IN_CALL: - gAudioManager.phoneState = nsIAudioManager.PHONE_STATE_IN_CALL; - if (this.speakerEnabled) { - gAudioManager.setForceForUse(nsIAudioManager.USE_COMMUNICATION, - nsIAudioManager.FORCE_SPEAKER); - } - break; - default: - throw new Error("Unknown audioPhoneState: " + aState); - } - - if (DEBUG) { - debug("Put audio system into " + AUDIO_STATE_NAME[aState] + ": " + - aState + ", result is: " + gAudioManager.phoneState); - } - }, - - /** - * nsIObserver interface. - */ - - observe: function(aSubject, aTopic, aData) { - switch (aTopic) { - case NS_PREFBRANCH_PREFCHANGE_TOPIC_ID: - if (aData === kPrefRilDebuggingEnabled) { - this._updateDebugFlag(); - } - break; - } - } -}; - -this.NSGetFactory = XPCOMUtils.generateNSGetFactory([TelephonyAudioService]); diff --git a/dom/telephony/gonk/TelephonyAudioService.manifest b/dom/telephony/gonk/TelephonyAudioService.manifest deleted file mode 100644 index 4f140739091b..000000000000 --- a/dom/telephony/gonk/TelephonyAudioService.manifest +++ /dev/null @@ -1,6 +0,0 @@ -# This Source Code Form is subject to the terms of the Mozilla Public -# License, v. 2.0. If a copy of the MPL was not distributed with this -# file, You can obtain one at http://mozilla.org/MPL/2.0/. - -component {c8605499-cfec-4cb5-a082-5f1f56d42adf} TelephonyAudioService.js -contract @mozilla.org/telephony/audio-service;1 {c8605499-cfec-4cb5-a082-5f1f56d42adf} diff --git a/dom/telephony/gonk/TelephonyService.js b/dom/telephony/gonk/TelephonyService.js deleted file mode 100644 index caa102c64222..000000000000 --- a/dom/telephony/gonk/TelephonyService.js +++ /dev/null @@ -1,2514 +0,0 @@ -/* -*- indent-tabs-mode: nil; js-indent-level: 2 -*- */ -/* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this file, - * You can obtain one at http://mozilla.org/MPL/2.0/. */ - -"use strict"; - -const {classes: Cc, interfaces: Ci, utils: Cu, results: Cr} = Components; - -Cu.import("resource://gre/modules/XPCOMUtils.jsm"); -Cu.import("resource://gre/modules/Services.jsm"); -Cu.import("resource://gre/modules/Promise.jsm"); - -/* global RIL */ -XPCOMUtils.defineLazyGetter(this, "RIL", function () { - let obj = {}; - Cu.import("resource://gre/modules/ril_consts.js", obj); - return obj; -}); - -const GONK_TELEPHONYSERVICE_CONTRACTID = - "@mozilla.org/telephony/gonktelephonyservice;1"; - -const GONK_TELEPHONYSERVICE_CID = - Components.ID("{67d26434-d063-4d28-9f48-5b3189788155}"); -const TELEPHONYCALLINFO_CID = - Components.ID("{d9e8b358-a02c-4cf3-9fc7-816c2e8d46e4}"); - -const NS_XPCOM_SHUTDOWN_OBSERVER_ID = "xpcom-shutdown"; - -const NS_PREFBRANCH_PREFCHANGE_TOPIC_ID = "nsPref:changed"; - -const kPrefRilNumRadioInterfaces = "ril.numRadioInterfaces"; -const kPrefRilDebuggingEnabled = "ril.debugging.enabled"; -const kPrefDefaultServiceId = "dom.telephony.defaultServiceId"; - -const nsITelephonyAudioService = Ci.nsITelephonyAudioService; -const nsITelephonyService = Ci.nsITelephonyService; -const nsIMobileConnection = Ci.nsIMobileConnection; - -const CALL_WAKELOCK_TIMEOUT = 5000; - -// In CDMA, RIL only hold one call index. We need to fake a second call index -// in TelephonyService for 3-way calling. -const CDMA_FIRST_CALL_INDEX = 1; -const CDMA_SECOND_CALL_INDEX = 2; - -const DIAL_ERROR_INVALID_STATE_ERROR = "InvalidStateError"; -const DIAL_ERROR_OTHER_CONNECTION_IN_USE = "OtherConnectionInUse"; -const DIAL_ERROR_BAD_NUMBER = RIL.GECKO_CALL_ERROR_BAD_NUMBER; -const DIAL_ERROR_RADIO_NOT_AVAILABLE = RIL.GECKO_ERROR_RADIO_NOT_AVAILABLE; - -const TONES_GAP_DURATION = 70; - -const EMERGENCY_CALL_DEFAULT_CLIENT_ID = 0; - -// Consts for MMI. -// MMI procedure as defined in TS.22.030 6.5.2 -const MMI_PROCEDURE_ACTIVATION = "*"; -const MMI_PROCEDURE_DEACTIVATION = "#"; -const MMI_PROCEDURE_INTERROGATION = "*#"; -const MMI_PROCEDURE_REGISTRATION = "**"; -const MMI_PROCEDURE_ERASURE = "##"; - -XPCOMUtils.defineConstant(this, "MMI_PROCEDURE_ACTIVATION", MMI_PROCEDURE_ACTIVATION); -XPCOMUtils.defineConstant(this, "MMI_PROCEDURE_DEACTIVATION", MMI_PROCEDURE_DEACTIVATION); -XPCOMUtils.defineConstant(this, "MMI_PROCEDURE_INTERROGATION", MMI_PROCEDURE_INTERROGATION); -XPCOMUtils.defineConstant(this, "MMI_PROCEDURE_REGISTRATION", MMI_PROCEDURE_REGISTRATION); -XPCOMUtils.defineConstant(this, "MMI_PROCEDURE_ERASURE", MMI_PROCEDURE_ERASURE); - -// MMI call forwarding service codes as defined in TS.22.030 Annex B -const MMI_SC_CFU = "21"; -const MMI_SC_CF_BUSY = "67"; -const MMI_SC_CF_NO_REPLY = "61"; -const MMI_SC_CF_NOT_REACHABLE = "62"; -const MMI_SC_CF_ALL = "002"; -const MMI_SC_CF_ALL_CONDITIONAL = "004"; - -// MMI service codes for PIN/PIN2/PUK/PUK2 management as defined in TS.22.030 -// sec 6.6 -const MMI_SC_PIN = "04"; -const MMI_SC_PIN2 = "042"; -const MMI_SC_PUK = "05"; -const MMI_SC_PUK2 = "052"; - -// MMI service code for IMEI presentation as defined in TS.22.030 sec 6.7 -const MMI_SC_IMEI = "06"; - -// MMI call waiting service code -const MMI_SC_CALL_WAITING = "43"; - -// MMI service code for registration new password as defined in TS 22.030 6.5.4 -const MMI_SC_CHANGE_PASSWORD = "03"; -const MMI_ZZ_BARRING_SERVICE = "330"; - -// MMI call barring service codes -const MMI_SC_BAOC = "33"; -const MMI_SC_BAOIC = "331"; -const MMI_SC_BAOICxH = "332"; -const MMI_SC_BAIC = "35"; -const MMI_SC_BAICr = "351"; -const MMI_SC_BA_ALL = "330"; -const MMI_SC_BA_MO = "333"; -const MMI_SC_BA_MT = "353"; - -// MMI called line presentation service codes -const MMI_SC_CLIP = "30"; -const MMI_SC_CLIR = "31"; - -// MMI service code key strings. -const MMI_KS_SC_CALL_BARRING = "scCallBarring"; -const MMI_KS_SC_CALL_FORWARDING = "scCallForwarding"; -const MMI_KS_SC_CLIP = "scClip"; -const MMI_KS_SC_CLIR = "scClir"; -const MMI_KS_SC_PWD = "scPwd"; -const MMI_KS_SC_CALL_WAITING = "scCallWaiting"; -const MMI_KS_SC_PIN = "scPin"; -const MMI_KS_SC_PIN2 = "scPin2"; -const MMI_KS_SC_PUK = "scPuk"; -const MMI_KS_SC_PUK2 = "scPuk2"; -const MMI_KS_SC_CHANGE_PASSWORD = "scChangePassword"; -const MMI_KS_SC_IMEI = "scImei"; -const MMI_KS_SC_USSD = "scUssd"; -const MMI_KS_SC_CALL = "scCall"; - -// MMI error messages key strings. -const MMI_ERROR_KS_ERROR = "emMmiError"; -const MMI_ERROR_KS_NOT_SUPPORTED = "emMmiErrorNotSupported"; -const MMI_ERROR_KS_INVALID_ACTION = "emMmiErrorInvalidAction"; -const MMI_ERROR_KS_MISMATCH_PIN = "emMmiErrorMismatchPin"; -const MMI_ERROR_KS_MISMATCH_PASSWORD = "emMmiErrorMismatchPassword"; -const MMI_ERROR_KS_BAD_PIN = "emMmiErrorBadPin"; -const MMI_ERROR_KS_BAD_PUK = "emMmiErrorBadPuk"; -const MMI_ERROR_KS_INVALID_PIN = "emMmiErrorInvalidPin"; -const MMI_ERROR_KS_INVALID_PASSWORD = "emMmiErrorInvalidPassword"; -const MMI_ERROR_KS_NEEDS_PUK = "emMmiErrorNeedsPuk"; -const MMI_ERROR_KS_SIM_BLOCKED = "emMmiErrorSimBlocked"; - -// MMI status message. -const MMI_SM_KS_PASSWORD_CHANGED = "smPasswordChanged"; -const MMI_SM_KS_PIN_CHANGED = "smPinChanged"; -const MMI_SM_KS_PIN2_CHANGED = "smPin2Changed"; -const MMI_SM_KS_PIN_UNBLOCKED = "smPinUnblocked"; -const MMI_SM_KS_PIN2_UNBLOCKED = "smPin2Unblocked"; -const MMI_SM_KS_SERVICE_ENABLED = "smServiceEnabled"; -const MMI_SM_KS_SERVICE_ENABLED_FOR = "smServiceEnabledFor"; -const MMI_SM_KS_SERVICE_DISABLED = "smServiceDisabled"; -const MMI_SM_KS_SERVICE_REGISTERED = "smServiceRegistered"; -const MMI_SM_KS_SERVICE_ERASED = "smServiceErased"; -const MMI_SM_KS_SERVICE_INTERROGATED = "smServiceInterrogated"; -const MMI_SM_KS_SERVICE_NOT_PROVISIONED = "smServiceNotProvisioned"; -const MMI_SM_KS_CLIR_PERMANENT = "smClirPermanent"; -const MMI_SM_KS_CLIR_DEFAULT_ON_NEXT_CALL_ON = "smClirDefaultOnNextCallOn"; -const MMI_SM_KS_CLIR_DEFAULT_ON_NEXT_CALL_OFF = "smClirDefaultOnNextCallOff"; -const MMI_SM_KS_CLIR_DEFAULT_OFF_NEXT_CALL_ON = "smClirDefaultOffNextCallOn"; -const MMI_SM_KS_CLIR_DEFAULT_OFF_NEXT_CALL_OFF = "smClirDefaultOffNextCallOff"; -const MMI_SM_KS_CALL_CONTROL = "smCallControl"; - -// MMI Service class -const MMI_KS_SERVICE_CLASS_VOICE = "serviceClassVoice"; -const MMI_KS_SERVICE_CLASS_DATA = "serviceClassData"; -const MMI_KS_SERVICE_CLASS_FAX = "serviceClassFax"; -const MMI_KS_SERVICE_CLASS_SMS = "serviceClassSms"; -const MMI_KS_SERVICE_CLASS_DATA_SYNC = "serviceClassDataSync"; -const MMI_KS_SERVICE_CLASS_DATA_ASYNC = "serviceClassDataAsync"; -const MMI_KS_SERVICE_CLASS_PACKET = "serviceClassPacket"; -const MMI_KS_SERVICE_CLASS_PAD = "serviceClassPad"; - -// States of USSD Session : DONE -> ONGOING [-> CANCELLING] -> DONE -const USSD_SESSION_DONE = "DONE"; -const USSD_SESSION_ONGOING = "ONGOING"; -const USSD_SESSION_CANCELLING = "CANCELLING"; - -const MMI_PROC_TO_CF_ACTION = {}; -MMI_PROC_TO_CF_ACTION[MMI_PROCEDURE_ACTIVATION] = Ci.nsIMobileConnection.CALL_FORWARD_ACTION_ENABLE; -MMI_PROC_TO_CF_ACTION[MMI_PROCEDURE_DEACTIVATION] = Ci.nsIMobileConnection.CALL_FORWARD_ACTION_DISABLE; -MMI_PROC_TO_CF_ACTION[MMI_PROCEDURE_INTERROGATION] = Ci.nsIMobileConnection.CALL_FORWARD_ACTION_QUERY_STATUS; -MMI_PROC_TO_CF_ACTION[MMI_PROCEDURE_REGISTRATION] = Ci.nsIMobileConnection.CALL_FORWARD_ACTION_REGISTRATION; -MMI_PROC_TO_CF_ACTION[MMI_PROCEDURE_ERASURE] = Ci.nsIMobileConnection.CALL_FORWARD_ACTION_ERASURE; - -const MMI_SC_TO_CF_REASON = {}; -MMI_SC_TO_CF_REASON[MMI_SC_CFU] = Ci.nsIMobileConnection.CALL_FORWARD_REASON_UNCONDITIONAL; -MMI_SC_TO_CF_REASON[MMI_SC_CF_BUSY] = Ci.nsIMobileConnection.CALL_FORWARD_REASON_MOBILE_BUSY; -MMI_SC_TO_CF_REASON[MMI_SC_CF_NO_REPLY] = Ci.nsIMobileConnection.CALL_FORWARD_REASON_NO_REPLY; -MMI_SC_TO_CF_REASON[MMI_SC_CF_NOT_REACHABLE] = Ci.nsIMobileConnection.CALL_FORWARD_REASON_NOT_REACHABLE; -MMI_SC_TO_CF_REASON[MMI_SC_CF_ALL] = Ci.nsIMobileConnection.CALL_FORWARD_REASON_ALL_CALL_FORWARDING; -MMI_SC_TO_CF_REASON[MMI_SC_CF_ALL_CONDITIONAL] = Ci.nsIMobileConnection.CALL_FORWARD_REASON_ALL_CONDITIONAL_CALL_FORWARDING; - -const MMI_SC_TO_LOCK_TYPE = {}; -MMI_SC_TO_LOCK_TYPE[MMI_SC_PIN] = Ci.nsIIcc.CARD_LOCK_TYPE_PIN; -MMI_SC_TO_LOCK_TYPE[MMI_SC_PIN2] = Ci.nsIIcc.CARD_LOCK_TYPE_PIN2; -MMI_SC_TO_LOCK_TYPE[MMI_SC_PUK] = Ci.nsIIcc.CARD_LOCK_TYPE_PUK; -MMI_SC_TO_LOCK_TYPE[MMI_SC_PUK2] = Ci.nsIIcc.CARD_LOCK_TYPE_PUK2; - -const MMI_PROC_TO_CLIR_ACTION = {}; -MMI_PROC_TO_CLIR_ACTION[MMI_PROCEDURE_ACTIVATION] = Ci.nsIMobileConnection.CLIR_INVOCATION; -MMI_PROC_TO_CLIR_ACTION[MMI_PROCEDURE_DEACTIVATION] = Ci.nsIMobileConnection.CLIR_SUPPRESSION; - -const MMI_SC_TO_CB_PROGRAM = {}; -MMI_SC_TO_CB_PROGRAM[MMI_SC_BAOC] = Ci.nsIMobileConnection.CALL_BARRING_PROGRAM_ALL_OUTGOING; -MMI_SC_TO_CB_PROGRAM[MMI_SC_BAOIC] = Ci.nsIMobileConnection.CALL_BARRING_PROGRAM_OUTGOING_INTERNATIONAL; -MMI_SC_TO_CB_PROGRAM[MMI_SC_BAOICxH] = Ci.nsIMobileConnection.CALL_BARRING_PROGRAM_OUTGOING_INTERNATIONAL_EXCEPT_HOME; -MMI_SC_TO_CB_PROGRAM[MMI_SC_BAIC] = Ci.nsIMobileConnection.CALL_BARRING_PROGRAM_ALL_INCOMING; -MMI_SC_TO_CB_PROGRAM[MMI_SC_BAICr] = Ci.nsIMobileConnection.CALL_BARRING_PROGRAM_INCOMING_ROAMING; -MMI_SC_TO_CB_PROGRAM[MMI_SC_BA_ALL] = Ci.nsIMobileConnection.CALL_BARRING_PROGRAM_ALL_SERVICE; -MMI_SC_TO_CB_PROGRAM[MMI_SC_BA_MO] = Ci.nsIMobileConnection.CALL_BARRING_PROGRAM_OUTGOING_SERVICE; -MMI_SC_TO_CB_PROGRAM[MMI_SC_BA_MT] = Ci.nsIMobileConnection.CALL_BARRING_PROGRAM_INCOMING_SERVICE; - -const CF_ACTION_TO_STATUS_MESSAGE = {}; -CF_ACTION_TO_STATUS_MESSAGE[Ci.nsIMobileConnection.CALL_FORWARD_ACTION_ENABLE] = MMI_SM_KS_SERVICE_ENABLED; -CF_ACTION_TO_STATUS_MESSAGE[Ci.nsIMobileConnection.CALL_FORWARD_ACTION_DISABLE] = MMI_SM_KS_SERVICE_DISABLED; -CF_ACTION_TO_STATUS_MESSAGE[Ci.nsIMobileConnection.CALL_FORWARD_ACTION_REGISTRATION] = MMI_SM_KS_SERVICE_REGISTERED; -CF_ACTION_TO_STATUS_MESSAGE[Ci.nsIMobileConnection.CALL_FORWARD_ACTION_ERASURE] = MMI_SM_KS_SERVICE_ERASED; - -const LOCK_TYPE_TO_STATUS_MESSAGE = {}; -LOCK_TYPE_TO_STATUS_MESSAGE[Ci.nsIIcc.CARD_LOCK_TYPE_PIN] = MMI_SM_KS_PIN_CHANGED; -LOCK_TYPE_TO_STATUS_MESSAGE[Ci.nsIIcc.CARD_LOCK_TYPE_PIN2] = MMI_SM_KS_PIN2_CHANGED; -LOCK_TYPE_TO_STATUS_MESSAGE[Ci.nsIIcc.CARD_LOCK_TYPE_PUK] = MMI_SM_KS_PIN_UNBLOCKED; -LOCK_TYPE_TO_STATUS_MESSAGE[Ci.nsIIcc.CARD_LOCK_TYPE_PUK2] = MMI_SM_KS_PIN2_UNBLOCKED; - -const CLIR_ACTION_TO_STATUS_MESSAGE = {}; -CLIR_ACTION_TO_STATUS_MESSAGE[Ci.nsIMobileConnection.CLIR_INVOCATION] = MMI_SM_KS_SERVICE_ENABLED; -CLIR_ACTION_TO_STATUS_MESSAGE[Ci.nsIMobileConnection.CLIR_SUPPRESSION] = MMI_SM_KS_SERVICE_DISABLED; - -const MMI_KS_SERVICE_CLASS_MAPPING = {}; -MMI_KS_SERVICE_CLASS_MAPPING[Ci.nsIMobileConnection.ICC_SERVICE_CLASS_VOICE] = MMI_KS_SERVICE_CLASS_VOICE; -MMI_KS_SERVICE_CLASS_MAPPING[Ci.nsIMobileConnection.ICC_SERVICE_CLASS_DATA] = MMI_KS_SERVICE_CLASS_DATA; -MMI_KS_SERVICE_CLASS_MAPPING[Ci.nsIMobileConnection.ICC_SERVICE_CLASS_FAX] = MMI_KS_SERVICE_CLASS_FAX; -MMI_KS_SERVICE_CLASS_MAPPING[Ci.nsIMobileConnection.ICC_SERVICE_CLASS_SMS] = MMI_KS_SERVICE_CLASS_SMS; -MMI_KS_SERVICE_CLASS_MAPPING[Ci.nsIMobileConnection.ICC_SERVICE_CLASS_DATA_SYNC] = MMI_KS_SERVICE_CLASS_DATA_SYNC; -MMI_KS_SERVICE_CLASS_MAPPING[Ci.nsIMobileConnection.ICC_SERVICE_CLASS_DATA_ASYNC] = MMI_KS_SERVICE_CLASS_DATA_ASYNC; -MMI_KS_SERVICE_CLASS_MAPPING[Ci.nsIMobileConnection.ICC_SERVICE_CLASS_PACKET] = MMI_KS_SERVICE_CLASS_PACKET; -MMI_KS_SERVICE_CLASS_MAPPING[Ci.nsIMobileConnection.ICC_SERVICE_CLASS_PAD] = MMI_KS_SERVICE_CLASS_PAD; - -var DEBUG; -function debug(s) { - dump("TelephonyService: " + s + "\n"); -} - -/* global gRadioInterfaceLayer */ -XPCOMUtils.defineLazyGetter(this, "gRadioInterfaceLayer", function() { - let ril = { numRadioInterfaces: 0 }; - try { - ril = Cc["@mozilla.org/ril;1"].getService(Ci.nsIRadioInterfaceLayer); - } catch(e) {} - return ril; -}); - -/* global gPowerManagerService */ -XPCOMUtils.defineLazyServiceGetter(this, "gPowerManagerService", - "@mozilla.org/power/powermanagerservice;1", - "nsIPowerManagerService"); - -/* global gTelephonyMessenger */ -XPCOMUtils.defineLazyServiceGetter(this, "gTelephonyMessenger", - "@mozilla.org/ril/system-messenger-helper;1", - "nsITelephonyMessenger"); - -/* global gAudioService */ -XPCOMUtils.defineLazyServiceGetter(this, "gAudioService", - "@mozilla.org/telephony/audio-service;1", - "nsITelephonyAudioService"); - -/* global gGonkMobileConnectionService */ -XPCOMUtils.defineLazyServiceGetter(this, "gGonkMobileConnectionService", - "@mozilla.org/mobileconnection/mobileconnectionservice;1", - "nsIGonkMobileConnectionService"); - -/* global gIccService */ -XPCOMUtils.defineLazyServiceGetter(this, "gIccService", - "@mozilla.org/icc/iccservice;1", - "nsIIccService"); - - -/* global PhoneNumberUtils */ -XPCOMUtils.defineLazyModuleGetter(this, "PhoneNumberUtils", - "resource://gre/modules/PhoneNumberUtils.jsm"); - -/* global DialNumberUtils */ -XPCOMUtils.defineLazyModuleGetter(this, "DialNumberUtils", - "resource://gre/modules/DialNumberUtils.jsm"); - -function TelephonyCallInfo(aCall) { - this.clientId = aCall.clientId; - this.callIndex = aCall.callIndex; - this.callState = aCall.state; - this.disconnectedReason = aCall.disconnectedReason || ""; - - this.number = aCall.number; - this.numberPresentation = aCall.numberPresentation; - this.name = aCall.name; - this.namePresentation = aCall.namePresentation; - - this.isOutgoing = aCall.isOutgoing; - this.isEmergency = aCall.isEmergency; - this.isConference = aCall.isConference; - this.isSwitchable = aCall.isSwitchable; - this.isMergeable = aCall.isMergeable; -} -TelephonyCallInfo.prototype = { - QueryInterface: XPCOMUtils.generateQI([Ci.nsITelephonyCallInfo]), - classID: TELEPHONYCALLINFO_CID, - classInfo: XPCOMUtils.generateCI({ - classID: TELEPHONYCALLINFO_CID, - classDescription: "TelephonyCallInfo", - interfaces: [Ci.nsITelephonyCallInfo] - }), - - // nsITelephonyCallInfo - - clientId: 0, - callIndex: 0, - callState: nsITelephonyService.CALL_STATE_UNKNOWN, - disconnectedReason: "", - - number: "", - numberPresentation: nsITelephonyService.CALL_PRESENTATION_ALLOWED, - name: "", - namePresentation: nsITelephonyService.CALL_PRESENTATION_ALLOWED, - - isOutgoing: true, - isEmergency: false, - isConference: false, - isSwitchable: true, - isMergeable: true -}; - -function Call(aClientId, aCallIndex) { - this.clientId = aClientId; - this.callIndex = aCallIndex; -} -Call.prototype = { - clientId: 0, - callIndex: 0, - state: nsITelephonyService.CALL_STATE_UNKNOWN, - number: "", - numberPresentation: nsITelephonyService.CALL_PRESENTATION_ALLOWED, - name: "", - namePresentation: nsITelephonyService.CALL_PRESENTATION_ALLOWED, - isOutgoing: true, - isEmergency: false, - isConference: false, - isSwitchable: true, - isMergeable: true, - started: null -}; - -function MobileConnectionListener() {} -MobileConnectionListener.prototype = { - QueryInterface: XPCOMUtils.generateQI([Ci.nsIMobileConnectionListener]), - - // nsIMobileConnectionListener - - notifyVoiceChanged: function() {}, - notifyDataChanged: function() {}, - notifyDataError: function(message) {}, - notifyCFStateChanged: function(action, reason, number, timeSeconds, serviceClass) {}, - notifyEmergencyCbModeChanged: function(active, timeoutMs) {}, - notifyOtaStatusChanged: function(status) {}, - notifyRadioStateChanged: function() {}, - notifyClirModeChanged: function(mode) {}, - notifyLastKnownNetworkChanged: function() {}, - notifyLastKnownHomeNetworkChanged: function() {}, - notifyNetworkSelectionModeChanged: function() {}, - notifyDeviceIdentitiesChanged: function() {} -}; - -function TelephonyService() { - this._numClients = gRadioInterfaceLayer.numRadioInterfaces; - this._listeners = []; - - this._isDialing = false; - this._cachedDialRequest = null; - this._currentCalls = {}; - this._audioStates = []; - this._ussdSessions = []; - - this._cdmaCallWaitingNumber = null; - - this._updateDebugFlag(); - this.defaultServiceId = this._getDefaultServiceId(); - - Services.prefs.addObserver(kPrefRilDebuggingEnabled, this, false); - Services.prefs.addObserver(kPrefDefaultServiceId, this, false); - - Services.obs.addObserver(this, NS_XPCOM_SHUTDOWN_OBSERVER_ID, false); - - for (let i = 0; i < this._numClients; ++i) { - this._audioStates[i] = nsITelephonyAudioService.PHONE_STATE_NORMAL; - this._ussdSessions[i] = USSD_SESSION_DONE; - this._currentCalls[i] = {}; - this._enumerateCallsForClient(i); - } -} -TelephonyService.prototype = { - classID: GONK_TELEPHONYSERVICE_CID, - classInfo: XPCOMUtils.generateCI({classID: GONK_TELEPHONYSERVICE_CID, - contractID: GONK_TELEPHONYSERVICE_CONTRACTID, - classDescription: "TelephonyService", - interfaces: [Ci.nsITelephonyService, - Ci.nsIGonkTelephonyService], - flags: Ci.nsIClassInfo.SINGLETON}), - QueryInterface: XPCOMUtils.generateQI([Ci.nsITelephonyService, - Ci.nsIGonkTelephonyService, - Ci.nsIObserver]), - - // The following attributes/functions are used for acquiring/releasing the - // CPU wake lock when the RIL handles the incoming call. Note that we need - // a timer to bound the lock's life cycle to avoid exhausting the battery. - _callRingWakeLock: null, - _callRingWakeLockTimer: null, - - /** - * USSD session flags. - * Only one USSD session may exist at a time, and the session is assumed - * to exist until: - * a) There's a call to cancelUSSD() - * b) Receiving a session end unsolicited event. - */ - _ussdSessions: null, - - _acquireCallRingWakeLock: function() { - if (!this._callRingWakeLock) { - if (DEBUG) debug("Acquiring a CPU wake lock for handling incoming call."); - this._callRingWakeLock = gPowerManagerService.newWakeLock("cpu"); - } - if (!this._callRingWakeLockTimer) { - if (DEBUG) debug("Creating a timer for releasing the CPU wake lock."); - this._callRingWakeLockTimer = - Cc["@mozilla.org/timer;1"].createInstance(Ci.nsITimer); - } - if (DEBUG) debug("Setting the timer for releasing the CPU wake lock."); - this._callRingWakeLockTimer - .initWithCallback(this._releaseCallRingWakeLock.bind(this), - CALL_WAKELOCK_TIMEOUT, Ci.nsITimer.TYPE_ONE_SHOT); - }, - - _releaseCallRingWakeLock: function() { - if (DEBUG) debug("Releasing the CPU wake lock for handling incoming call."); - if (this._callRingWakeLockTimer) { - this._callRingWakeLockTimer.cancel(); - } - if (this._callRingWakeLock) { - this._callRingWakeLock.unlock(); - this._callRingWakeLock = null; - } - }, - - _getClient: function(aClientId) { - return gRadioInterfaceLayer.getRadioInterface(aClientId); - }, - - _sendToRilWorker: function(aClientId, aType, aMessage, aCallback) { - this._getClient(aClientId).sendWorkerMessage(aType, aMessage, aCallback); - }, - - _isGsmTechGroup: function(aType) { - switch (aType) { - case null: // Handle unknown as gsm. - case "gsm": - case "gprs": - case "edge": - case "umts": - case "hsdpa": - case "hsupa": - case "hspa": - case "hspa+": - case "lte": - return true; - default: - return false; - } - }, - - _isCdmaClient: function(aClientId) { - let type = gGonkMobileConnectionService.getItemByServiceId(aClientId).voice.type; - return !this._isGsmTechGroup(type); - }, - - _isEmergencyOnly: function(aClientId) { - return gGonkMobileConnectionService.getItemByServiceId(aClientId).voice.emergencyCallsOnly; - }, - - _isRadioOn: function(aClientId) { - let connection = gGonkMobileConnectionService.getItemByServiceId(aClientId); - return connection.radioState === nsIMobileConnection.MOBILE_RADIO_STATE_ENABLED; - }, - - // An array of nsITelephonyListener instances. - _listeners: null, - _notifyAllListeners: function(aMethodName, aArgs) { - let listeners = this._listeners.slice(); - for (let listener of listeners) { - if (this._listeners.indexOf(listener) == -1) { - // Listener has been unregistered in previous run. - continue; - } - - let handler = listener[aMethodName]; - try { - handler.apply(listener, aArgs); - } catch (e) { - debug("listener for " + aMethodName + " threw an exception: " + e); - } - } - }, - - _computeAudioStateForClient: function(aClientId) { - let indexes = Object.keys(this._currentCalls[aClientId]); - if (!indexes.length) { - return nsITelephonyAudioService.PHONE_STATE_NORMAL; - } - - let firstCall = this._currentCalls[aClientId][indexes[0]]; - if (indexes.length === 1 && - firstCall.state === nsITelephonyService.CALL_STATE_INCOMING) { - return nsITelephonyAudioService.PHONE_STATE_RINGTONE; - } - - return nsITelephonyAudioService.PHONE_STATE_IN_CALL; - }, - - _updateAudioState: function(aClientId) { - this._audioStates[aClientId] = this._computeAudioStateForClient(aClientId); - - if (this._audioStates.some(state => state === nsITelephonyAudioService.PHONE_STATE_IN_CALL)) { - gAudioService.setPhoneState(nsITelephonyAudioService.PHONE_STATE_IN_CALL); - } else if (this._audioStates.some(state => state === nsITelephonyAudioService.PHONE_STATE_RINGTONE)) { - gAudioService.setPhoneState(nsITelephonyAudioService.PHONE_STATE_RINGTONE); - } else { - gAudioService.setPhoneState(nsITelephonyAudioService.PHONE_STATE_NORMAL); - } - }, - - _formatInternationalNumber: function(aNumber, aToa) { - if (aNumber && aToa == RIL.TOA_INTERNATIONAL && aNumber[0] != "+") { - return "+" + aNumber; - } - - return aNumber; - }, - - _convertRILCallState: function(aState) { - switch (aState) { - case RIL.CALL_STATE_UNKNOWN: - return nsITelephonyService.CALL_STATE_UNKNOWN; - case RIL.CALL_STATE_ACTIVE: - return nsITelephonyService.CALL_STATE_CONNECTED; - case RIL.CALL_STATE_HOLDING: - return nsITelephonyService.CALL_STATE_HELD; - case RIL.CALL_STATE_DIALING: - return nsITelephonyService.CALL_STATE_DIALING; - case RIL.CALL_STATE_ALERTING: - return nsITelephonyService.CALL_STATE_ALERTING; - case RIL.CALL_STATE_INCOMING: - case RIL.CALL_STATE_WAITING: - return nsITelephonyService.CALL_STATE_INCOMING; - default: - throw new Error("Unknown rilCallState: " + aState); - } - }, - - _convertRILSuppSvcNotification: function(aNotification) { - switch (aNotification) { - case RIL.GECKO_SUPP_SVC_NOTIFICATION_REMOTE_HELD: - return nsITelephonyService.NOTIFICATION_REMOTE_HELD; - case RIL.GECKO_SUPP_SVC_NOTIFICATION_REMOTE_RESUMED: - return nsITelephonyService.NOTIFICATION_REMOTE_RESUMED; - default: - if (DEBUG) { - debug("Unknown rilSuppSvcNotification: " + aNotification); - } - return; - } - }, - - _updateDebugFlag: function() { - try { - DEBUG = RIL.DEBUG_RIL || - Services.prefs.getBoolPref(kPrefRilDebuggingEnabled); - } catch (e) {} - }, - - _getDefaultServiceId: function() { - let id = Services.prefs.getIntPref(kPrefDefaultServiceId); - let numRil = Services.prefs.getIntPref(kPrefRilNumRadioInterfaces); - - if (id >= numRil || id < 0) { - id = 0; - } - - return id; - }, - - _currentCalls: null, - _enumerateCallsForClient: function(aClientId) { - if (DEBUG) debug("Enumeration of calls for client " + aClientId); - - this._sendToRilWorker(aClientId, "getCurrentCalls", null, response => { - if (response.errorMsg) { - return; - } - - // Clear all. - this._currentCalls[aClientId] = {}; - - for (let i in response.calls) { - let call = this._currentCalls[aClientId][i] = new Call(aClientId, i); - this._updateCallFromRil(call, response.calls[i]); - } - }); - }, - - /** - * Checks whether to temporarily suppress caller id for the call. - * - * @param aMmi - * MMI full object. - */ - _isTemporaryCLIR: function(aMmi) { - return (aMmi && aMmi.serviceCode === MMI_SC_CLIR) && aMmi.dialNumber; - }, - - /** - * Map MMI procedure to CLIR MODE. - * - * @param aProcedure - * MMI procedure - */ - _procedureToCLIRMode: function(aProcedure) { - // In temporary mode, MMI_PROCEDURE_ACTIVATION means allowing CLI - // presentation, i.e. CLIR_SUPPRESSION. See TS 22.030, Annex B. - switch (aProcedure) { - case MMI_PROCEDURE_ACTIVATION: - return Ci.nsIMobileConnection.CLIR_SUPPRESSION; - case MMI_PROCEDURE_DEACTIVATION: - return Ci.nsIMobileConnection.CLIR_INVOCATION; - default: - return Ci.nsIMobileConnection.CLIR_DEFAULT; - } - }, - - /** - * nsITelephonyService interface. - */ - - defaultServiceId: 0, - - registerListener: function(aListener) { - if (this._listeners.indexOf(aListener) >= 0) { - throw Cr.NS_ERROR_UNEXPECTED; - } - - this._listeners.push(aListener); - }, - - unregisterListener: function(aListener) { - let index = this._listeners.indexOf(aListener); - if (index < 0) { - throw Cr.NS_ERROR_UNEXPECTED; - } - - this._listeners.splice(index, 1); - }, - - enumerateCalls: function(aListener) { - if (DEBUG) debug("Requesting enumeration of calls for callback"); - - for (let cid = 0; cid < this._numClients; ++cid) { - let calls = this._currentCalls[cid]; - if (!calls) { - continue; - } - for (let i = 0, indexes = Object.keys(calls); i < indexes.length; ++i) { - let call = calls[indexes[i]]; - let callInfo = new TelephonyCallInfo(call); - aListener.enumerateCallState(callInfo); - } - } - aListener.enumerateCallStateComplete(); - }, - - _hasCalls: function(aClientId) { - return Object.keys(this._currentCalls[aClientId]).length !== 0; - }, - - _hasCallsOnOtherClient: function(aClientId) { - for (let cid = 0; cid < this._numClients; ++cid) { - if (cid !== aClientId && this._hasCalls(cid)) { - return true; - } - } - return false; - }, - - // All calls in the conference is regarded as one conference call. - _numCallsOnLine: function(aClientId) { - let numCalls = 0; - let hasConference = false; - - for (let cid in this._currentCalls[aClientId]) { - let call = this._currentCalls[aClientId][cid]; - if (call.isConference) { - hasConference = true; - } else { - numCalls++; - } - } - - return hasConference ? numCalls + 1 : numCalls; - }, - - /** - * Is there an active call? - */ - _isActive: function(aClientId) { - for (let index in this._currentCalls[aClientId]) { - let call = this._currentCalls[aClientId][index]; - if (call.state === nsITelephonyService.CALL_STATE_CONNECTED) { - return true; - } - } - return false; - }, - - /** - * Select a proper client for dialing emergency call. - * - * @return clientId - */ - _getClientIdForEmergencyCall: function() { - // Select the client with sim card first. - for (let cid = 0; cid < this._numClients; ++cid) { - let icc = gIccService.getIccByServiceId(cid); - let cardState = icc ? icc.cardState : Ci.nsIIcc.CARD_STATE_UNKONWN; - if (cardState !== Ci.nsIIcc.CARD_STATE_UNDETECTED && - cardState !== Ci.nsIIcc.CARD_STATE_UNKNOWN) { - return cid; - } - } - - // Use the defualt client if no card presents. - return EMERGENCY_CALL_DEFAULT_CLIENT_ID; - }, - - /** - * Dial number. Perform call setup or SS procedure accordingly. - * - * @see 3GPP TS 22.030 Figure 3.5.3.2 - */ - dial: function(aClientId, aNumber, aIsDialEmergency, aCallback) { - if (DEBUG) debug("Dialing " + (aIsDialEmergency ? "emergency " : "") - + aNumber + ", clientId: " + aClientId); - - // We don't try to be too clever here, as the phone is probably in the - // locked state. Let's just check if it's a number without normalizing - if (!aIsDialEmergency) { - aNumber = PhoneNumberUtils.normalize(aNumber); - } - - // Validate the number. - // Note: isPlainPhoneNumber also accepts USSD and SS numbers - if (!PhoneNumberUtils.isPlainPhoneNumber(aNumber)) { - if (DEBUG) debug("Error: Number '" + aNumber + "' is not viable. Drop."); - aCallback.notifyError(DIAL_ERROR_BAD_NUMBER); - return; - } - - let isEmergencyNumber = DialNumberUtils.isEmergency(aNumber); - - // DialEmergency accepts only emergency number. - if (aIsDialEmergency && !isEmergencyNumber) { - if (!this._isRadioOn(aClientId)) { - if (DEBUG) debug("Error: Radio is off. Drop."); - aCallback.notifyError(DIAL_ERROR_RADIO_NOT_AVAILABLE); - return; - } - - if (DEBUG) debug("Error: Dial a non-emergency by dialEmergency. Drop."); - aCallback.notifyError(DIAL_ERROR_BAD_NUMBER); - return; - } - - if (isEmergencyNumber) { - this._dialCall(aClientId, aNumber, undefined, aCallback); - return; - } - - // In cdma, we should always handle the request as a call. - if (this._isCdmaClient(aClientId)) { - this._dialCall(aClientId, aNumber, undefined, aCallback); - return; - } - - let mmi = DialNumberUtils.parseMMI(aNumber); - if (mmi) { - if (this._isTemporaryCLIR(mmi)) { - this._dialCall(aClientId, mmi.dialNumber, - this._procedureToCLIRMode(mmi.procedure), aCallback); - } else { - this._dialMMI(aClientId, mmi, aCallback); - } - } else { - if (aNumber[aNumber.length - 1] === "#") { // # string - this._dialMMI(aClientId, {fullMMI: aNumber}, aCallback); - } else if (aNumber.length <= 2) { // short string - if (this._hasCalls(aClientId)) { - this._dialInCallMMI(aClientId, aNumber, aCallback); - } else if (aNumber.length === 2 && aNumber[0] === "1") { - this._dialCall(aClientId, aNumber, undefined, aCallback); - } else { - this._dialMMI(aClientId, {fullMMI: aNumber}, aCallback); - } - } else { - this._dialCall(aClientId, aNumber, undefined, aCallback); - } - } - }, - - // Handling of supplementary services within a call as 3GPP TS 22.030 6.5.5 - _dialInCallMMI: function(aClientId, aNumber, aCallback) { - let mmiCallback = { - notifyError: () => aCallback.notifyDialMMIError(MMI_ERROR_KS_ERROR), - notifySuccess: () => aCallback.notifyDialMMISuccess(MMI_SM_KS_CALL_CONTROL) - }; - - if (aNumber === "0") { - aCallback.notifyDialMMI(MMI_KS_SC_CALL); - this._hangUpBackground(aClientId, mmiCallback); - } else if (aNumber === "1") { - aCallback.notifyDialMMI(MMI_KS_SC_CALL); - this._hangUpForeground(aClientId, mmiCallback); - } else if (aNumber[0] === "1" && aNumber.length === 2) { - aCallback.notifyDialMMI(MMI_KS_SC_CALL); - this.hangUpCall(aClientId, parseInt(aNumber[1]), mmiCallback); - } else if (aNumber === "2") { - aCallback.notifyDialMMI(MMI_KS_SC_CALL); - this._switchActiveCall(aClientId, mmiCallback); - } else if (aNumber[0] === "2" && aNumber.length === 2) { - aCallback.notifyDialMMI(MMI_KS_SC_CALL); - this._separateCallGsm(aClientId, parseInt(aNumber[1]), mmiCallback); - } else if (aNumber === "3") { - aCallback.notifyDialMMI(MMI_KS_SC_CALL); - this._conferenceCallGsm(aClientId, mmiCallback); - } else { - this._dialCall(aClientId, aNumber, undefined, aCallback); - } - }, - - _dialCall: function(aClientId, aNumber, aClirMode = RIL.CLIR_DEFAULT, - aCallback) { - if (this._isDialing) { - if (DEBUG) debug("Error: Already has a dialing call."); - aCallback.notifyError(DIAL_ERROR_INVALID_STATE_ERROR); - return; - } - - // We can only have at most two calls on the same line (client). - if (this._numCallsOnLine(aClientId) >= 2) { - if (DEBUG) debug("Error: Already has more than 2 calls on line."); - aCallback.notifyError(DIAL_ERROR_INVALID_STATE_ERROR); - return; - } - - // For DSDS, if there is aleady a call on SIM 'aClientId', we cannot place - // any new call on other SIM. - if (this._hasCallsOnOtherClient(aClientId)) { - if (DEBUG) debug("Error: Already has a call on other sim."); - aCallback.notifyError(DIAL_ERROR_OTHER_CONNECTION_IN_USE); - return; - } - - let isEmergency = DialNumberUtils.isEmergency(aNumber); - - if (!isEmergency) { - if (!this._isRadioOn(aClientId)) { - if (DEBUG) debug("Error: Dial a normal call when radio off. Drop"); - aCallback.notifyError(DIAL_ERROR_RADIO_NOT_AVAILABLE); - return; - } - - if (this._isEmergencyOnly(aClientId)) { - if (DEBUG) debug("Error: Dial a normal call when emergencyCallsOnly. Drop"); - aCallback.notifyError(DIAL_ERROR_BAD_NUMBER); - return; - } - } - - if (isEmergency) { - // Automatically select a proper clientId for emergency call. - aClientId = this._getClientIdForEmergencyCall() ; - if (aClientId === -1) { - if (DEBUG) debug("Error: No client is avaialble for emergency call."); - aCallback.notifyError(DIAL_ERROR_INVALID_STATE_ERROR); - return; - } - - // Radio is off. Turn it on first. - if (!this._isRadioOn(aClientId)) { - let connection = gGonkMobileConnectionService.getItemByServiceId(aClientId); - let listener = new MobileConnectionListener(); - - listener.notifyRadioStateChanged = () => { - if (this._isRadioOn(aClientId)) { - this._dialCall(aClientId, aNumber, undefined, aCallback); - connection.unregisterListener(listener); - } - }; - connection.registerListener(listener); - - // Turn on radio. - connection.setRadioEnabled(true, { - QueryInterface: XPCOMUtils.generateQI([Ci.nsIMobileConnectionCallback]), - notifySuccess: () => {}, - notifyError: aErrorMsg => { - connection.unregisterListener(listener); - aCallback.notifyError(DIAL_ERROR_RADIO_NOT_AVAILABLE); - } - }); - - return; - } - } - - let options = { - isEmergency: isEmergency, - number: aNumber, - clirMode: aClirMode - }; - - // No active call. Dial it out directly. - if (!this._isActive(aClientId)) { - this._sendDialCallRequest(aClientId, options, aCallback); - return; - } - - // CDMA 3-way calling. - if (this._isCdmaClient(aClientId)) { - this._dialCdmaThreeWayCall(aClientId, aNumber, aCallback); - return; - } - - // GSM. Hold the active call before dialing. - if (DEBUG) debug("There is an active call. Hold it first before dial."); - - if (this._cachedDialRequest) { - if (DEBUG) debug("Error: There already is a pending dial request."); - aCallback.notifyError(DIAL_ERROR_INVALID_STATE_ERROR); - return; - } - - this._switchActiveCall(aClientId, { - QueryInterface: XPCOMUtils.generateQI([Ci.nsITelephonyCallback]), - - notifySuccess: () => { - this._cachedDialRequest = { - clientId: aClientId, - options: options, - callback: aCallback - }; - }, - - notifyError: (aErrorMsg) => { - if (DEBUG) debug("Error: Fail to automatically hold the active call."); - aCallback.notifyError(aErrorMsg); - } - }); - }, - - _dialCdmaThreeWayCall: function(aClientId, aNumber, aCallback) { - this._sendToRilWorker(aClientId, "cdmaFlash", { featureStr: aNumber }, - response => { - if (response.errorMsg) { - aCallback.notifyError(response.errorMsg); - return; - } - - // RIL doesn't hold the 2nd call. We create one by ourselves. - aCallback.notifyDialCallSuccess(aClientId, CDMA_SECOND_CALL_INDEX, - aNumber); - - let childCall = this._currentCalls[aClientId][CDMA_SECOND_CALL_INDEX] = - new Call(aClientId, CDMA_SECOND_CALL_INDEX); - - childCall.parentId = CDMA_FIRST_CALL_INDEX; - childCall.state = nsITelephonyService.CALL_STATE_DIALING; - childCall.number = aNumber; - childCall.isOutgoing = true; - childCall.isEmergency = DialNumberUtils.isEmergency(aNumber); - childCall.isConference = false; - childCall.isSwitchable = false; - childCall.isMergeable = true; - - // Manual update call state according to the request response. - this._handleCallStateChanged(aClientId, [childCall]); - - childCall.state = nsITelephonyService.CALL_STATE_CONNECTED; - - let parentCall = this._currentCalls[aClientId][childCall.parentId]; - parentCall.childId = CDMA_SECOND_CALL_INDEX; - parentCall.state = nsITelephonyService.CALL_STATE_HELD; - parentCall.isSwitchable = false; - parentCall.isMergeable = true; - this._handleCallStateChanged(aClientId, [childCall, parentCall]); - }); - }, - - _sendDialCallRequest: function(aClientId, aOptions, aCallback) { - this._isDialing = true; - - this._sendToRilWorker(aClientId, "dial", aOptions, response => { - this._isDialing = false; - - if (response.errorMsg) { - this._sendToRilWorker(aClientId, "getFailCause", null, response => { - aCallback.notifyError(response.failCause); - }); - } else { - this._ongoingDial = { - clientId: aClientId, - callback: aCallback - }; - } - }); - }, - - /** - * @param aClientId - * Client id. - * @param aMmi - * Parsed MMI structure. - * @param aCallback - * A nsITelephonyDialCallback object. - */ - _dialMMI: function(aClientId, aMmi, aCallback) { - let mmiServiceCode = aMmi ? - this._serviceCodeToKeyString(aMmi.serviceCode) : MMI_KS_SC_USSD; - - aCallback.notifyDialMMI(mmiServiceCode); - - if (mmiServiceCode !== MMI_KS_SC_IMEI && !this._isRadioOn(aClientId)) { - aCallback.notifyDialMMIError(DIAL_ERROR_RADIO_NOT_AVAILABLE); - return; - } - - // We check if the MMI service code is supported and in that case we - // trigger the appropriate RIL request if possible. - switch (mmiServiceCode) { - // Call Forwarding - case MMI_KS_SC_CALL_FORWARDING: - this._callForwardingMMI(aClientId, aMmi, aCallback); - break; - - // Change the current ICC PIN number. - case MMI_KS_SC_PIN: - // Change the current ICC PIN2 number. - case MMI_KS_SC_PIN2: - this._iccChangeLockMMI(aClientId, aMmi, aCallback); - break; - - // Unblock ICC PUK. - case MMI_KS_SC_PUK: - // Unblock ICC PUN2. - case MMI_KS_SC_PUK2: - this._iccUnlockMMI(aClientId, aMmi, aCallback); - break; - - // IMEI - case MMI_KS_SC_IMEI: - this._getImeiMMI(aClientId, aMmi, aCallback); - break; - - // CLIP - case MMI_KS_SC_CLIP: - this._clipMMI(aClientId, aMmi, aCallback); - break; - - // CLIR (non-temporary ones) - case MMI_KS_SC_CLIR: - this._clirMMI(aClientId, aMmi, aCallback); - break; - - // Change call barring password - case MMI_KS_SC_CHANGE_PASSWORD: - this._callBarringPasswordMMI(aClientId, aMmi, aCallback); - break; - - // Call barring - case MMI_KS_SC_CALL_BARRING: - this._callBarringMMI(aClientId, aMmi, aCallback); - break; - - // Call waiting - case MMI_KS_SC_CALL_WAITING: - this._callWaitingMMI(aClientId, aMmi, aCallback); - break; - - // Handle unknown MMI code as USSD. - default: - if (this._ussdSessions[aClientId] == USSD_SESSION_ONGOING) { - // Cancel the previous ussd session first. - this._cancelUSSDInternal(aClientId, aResponse => { - // Fail to cancel ussd session, report error instead of sending ussd - // request. - if (aResponse.errorMsg) { - aCallback.notifyDialMMIError(aResponse.errorMsg); - return; - } - this._sendUSSDInternal(aClientId, aMmi.fullMMI, - this._defaultMMICallbackHandler.bind(this, aCallback)); - }); - return; - } - this._sendUSSDInternal(aClientId, aMmi.fullMMI, - this._defaultMMICallbackHandler.bind(this, aCallback)); - break; - } - }, - - /** - * Handle call forwarding MMI code. - * - * @param aClientId - * Client id. - * @param aMmi - * Parsed MMI structure. - * @param aCallback - * A nsITelephonyDialCallback object. - */ - _callForwardingMMI: function(aClientId, aMmi, aCallback) { - let connection = gGonkMobileConnectionService.getItemByServiceId(aClientId); - let action = MMI_PROC_TO_CF_ACTION[aMmi.procedure]; - let reason = MMI_SC_TO_CF_REASON[aMmi.serviceCode]; - - if (action === Ci.nsIMobileConnection.CALL_FORWARD_ACTION_QUERY_STATUS) { - connection.getCallForwarding(reason, { - QueryInterface: XPCOMUtils.generateQI([Ci.nsIMobileConnectionCallback]), - notifyGetCallForwardingSuccess: function(aCount, aResults) { - aCallback.notifyDialMMISuccessWithCallForwardingOptions( - MMI_SM_KS_SERVICE_INTERROGATED, aCount, aResults); - }, - notifyError: function(aErrorMsg) { - aCallback.notifyDialMMIError(aErrorMsg); - }, - }); - } else { - let number = aMmi.sia; - let serviceClass = this._siToServiceClass(aMmi.sib); - let timeSeconds = aMmi.sic; - connection.setCallForwarding(action, reason, number, timeSeconds, - serviceClass, { - QueryInterface: XPCOMUtils.generateQI([Ci.nsIMobileConnectionCallback]), - notifySuccess: function() { - aCallback.notifyDialMMISuccess(CF_ACTION_TO_STATUS_MESSAGE[action]); - }, - notifyError: function(aErrorMsg) { - aCallback.notifyDialMMIError(aErrorMsg); - }, - }); - } - }, - - /** - * Handle icc change lock MMI code. - * - * @param aClientId - * Client id. - * @param aMmi - * Parsed MMI structure. - * @param aCallback - * A nsITelephonyDialCallback object. - */ - _iccChangeLockMMI: function(aClientId, aMmi, aCallback) { - let errorMsg = this._getIccLockMMIError(aMmi); - if (errorMsg) { - aCallback.notifyDialMMIError(errorMsg); - return; - } - - let icc = gIccService.getIccByServiceId(aClientId); - let lockType = MMI_SC_TO_LOCK_TYPE[aMmi.serviceCode]; - - icc.changeCardLockPassword(lockType, aMmi.sia, aMmi.sib, { - QueryInterface: XPCOMUtils.generateQI([Ci.nsIIccCallback]), - notifySuccess: function() { - aCallback.notifyDialMMISuccess(LOCK_TYPE_TO_STATUS_MESSAGE[lockType]); - }, - notifyCardLockError: function(aErrorMsg, aRetryCount) { - if (aRetryCount <= 0) { - if (lockType === Ci.nsIIcc.CARD_LOCK_TYPE_PIN) { - aErrorMsg = MMI_ERROR_KS_NEEDS_PUK; - } - - aCallback.notifyDialMMIError(aErrorMsg); - return; - } - - aCallback.notifyDialMMIErrorWithInfo(MMI_ERROR_KS_BAD_PIN, - aRetryCount); - }, - }); - }, - - /** - * Handle icc unlock lock MMI code. - * - * @param aClientId - * Client id. - * @param aMmi - * Parsed MMI structure. - * @param aCallback - * A nsITelephonyDialCallback object. - */ - _iccUnlockMMI: function(aClientId, aMmi, aCallback) { - let errorMsg = this._getIccLockMMIError(aMmi); - if (errorMsg) { - aCallback.notifyDialMMIError(errorMsg); - return; - } - - let icc = gIccService.getIccByServiceId(aClientId); - let lockType = MMI_SC_TO_LOCK_TYPE[aMmi.serviceCode]; - - icc.unlockCardLock(lockType, aMmi.sia, aMmi.sib, { - QueryInterface: XPCOMUtils.generateQI([Ci.nsIIccCallback]), - notifySuccess: function() { - aCallback.notifyDialMMISuccess(LOCK_TYPE_TO_STATUS_MESSAGE[lockType]); - }, - notifyCardLockError: function(aErrorMsg, aRetryCount) { - if (aRetryCount <= 0) { - if (lockType === Ci.nsIIcc.CARD_LOCK_TYPE_PUK) { - aErrorMsg = MMI_ERROR_KS_SIM_BLOCKED; - } - - aCallback.notifyDialMMIError(aErrorMsg); - return; - } - - aCallback.notifyDialMMIErrorWithInfo(MMI_ERROR_KS_BAD_PUK, - aRetryCount); - }, - }); - }, - - /** - * Handle IMEI MMI code. - * - * @param aClientId - * Client id. - * @param aMmi - * Parsed MMI structure. - * @param aCallback - * A nsITelephonyDialCallback object. - */ - _getImeiMMI: function(aClientId, aMmi, aCallback) { - let connection = gGonkMobileConnectionService.getItemByServiceId(aClientId); - if (!connection.deviceIdentities || !connection.deviceIdentities.imei) { - aCallback.notifyDialMMIError(RIL.GECKO_ERROR_GENERIC_FAILURE); - return; - } - - aCallback.notifyDialMMISuccess(connection.deviceIdentities.imei); - }, - - /** - * Handle CLIP MMI code. - * - * @param aClientId - * Client id. - * @param aMmi - * Parsed MMI structure. - * @param aCallback - * A nsITelephonyDialCallback object. - */ - _clipMMI: function(aClientId, aMmi, aCallback) { - if (aMmi.procedure !== MMI_PROCEDURE_INTERROGATION) { - aCallback.notifyDialMMIError(MMI_ERROR_KS_NOT_SUPPORTED); - return; - } - - this._sendToRilWorker(aClientId, "queryCLIP", {}, aResponse => { - if (aResponse.errorMsg) { - aCallback.notifyDialMMIError(aResponse.errorMsg); - return; - } - - // aResponse.provisioned informs about the called party receives the - // calling party's address information: - // 0 for CLIP not provisioned - // 1 for CLIP provisioned - // 2 for unknown - switch (aResponse.provisioned) { - case 0: - aCallback.notifyDialMMISuccess(MMI_SM_KS_SERVICE_DISABLED); - break; - case 1: - aCallback.notifyDialMMISuccess(MMI_SM_KS_SERVICE_ENABLED); - break; - default: - aCallback.notifyDialMMIError(MMI_ERROR_KS_ERROR); - break; - } - }); - }, - - /** - * Handle CLIR MMI code. - * - * @param aClientId - * Client id. - * @param aMmi - * Parsed MMI structure. - * @param aCallback - * A nsITelephonyDialCallback object. - */ - _clirMMI: function(aClientId, aMmi, aCallback) { - let connection = gGonkMobileConnectionService.getItemByServiceId(aClientId); - switch (aMmi.procedure) { - case MMI_PROCEDURE_INTERROGATION: - connection.getCallingLineIdRestriction({ - QueryInterface: XPCOMUtils.generateQI([Ci.nsIMobileConnectionCallback]), - notifyGetClirStatusSuccess: function(aN, aM) { - let errorMsg; - let statusMessage; - // TS 27.007 +CLIR parameter 'm'. - switch (aM) { - // CLIR not provisioned. - case 0: - statusMessage = MMI_SM_KS_SERVICE_NOT_PROVISIONED; - break; - // CLIR provisioned in permanent mode. - case 1: - statusMessage = MMI_SM_KS_CLIR_PERMANENT; - break; - // Unknown (e.g. no network, etc.). - case 2: - errorMsg = MMI_ERROR_KS_ERROR; - break; - // CLIR temporary mode presentation restricted. - case 3: - // TS 27.007 +CLIR parameter 'n'. - switch (aN) { - // Default. - case 0: - // CLIR invocation. - case 1: - statusMessage = MMI_SM_KS_CLIR_DEFAULT_ON_NEXT_CALL_ON; - break; - // CLIR suppression. - case 2: - statusMessage = MMI_SM_KS_CLIR_DEFAULT_ON_NEXT_CALL_OFF; - break; - default: - errorMsg = RIL.GECKO_ERROR_GENERIC_FAILURE; - break; - } - break; - // CLIR temporary mode presentation allowed. - case 4: - // TS 27.007 +CLIR parameter 'n'. - switch (aN) { - // Default. - case 0: - // CLIR suppression. - case 2: - statusMessage = MMI_SM_KS_CLIR_DEFAULT_OFF_NEXT_CALL_OFF; - break; - // CLIR invocation. - case 1: - statusMessage = MMI_SM_KS_CLIR_DEFAULT_OFF_NEXT_CALL_ON; - break; - default: - errorMsg = RIL.GECKO_ERROR_GENERIC_FAILURE; - break; - } - break; - default: - errorMsg = RIL.GECKO_ERROR_GENERIC_FAILURE; - break; - } - - if (errorMsg) { - aCallback.notifyDialMMIError(errorMsg); - return; - } - - aCallback.notifyDialMMISuccess(statusMessage); - }, - notifyError: function(aErrorMsg) { - aCallback.notifyDialMMIError(aErrorMsg); - }, - }); - break; - case MMI_PROCEDURE_ACTIVATION: - case MMI_PROCEDURE_DEACTIVATION: { - let clirMode = MMI_PROC_TO_CLIR_ACTION[aMmi.procedure]; - connection.setCallingLineIdRestriction(clirMode, { - QueryInterface: XPCOMUtils.generateQI([Ci.nsIMobileConnectionCallback]), - notifySuccess: function() { - aCallback.notifyDialMMISuccess(CLIR_ACTION_TO_STATUS_MESSAGE[clirMode]); - }, - notifyError: function(aErrorMsg) { - aCallback.notifyDialMMIError(aErrorMsg); - }, - }); - break; - } - default: - aCallback.notifyDialMMIError(MMI_ERROR_KS_NOT_SUPPORTED); - break; - } - }, - - /** - * Handle change call barring password MMI code. - * - * @param aClientId - * Client id. - * @param aMmi - * Parsed MMI structure. - * @param aCallback - * A nsITelephonyDialCallback object. - */ - _callBarringPasswordMMI: function(aClientId, aMmi, aCallback) { - if (aMmi.procedure !== MMI_PROCEDURE_REGISTRATION && - aMmi.procedure !== MMI_PROCEDURE_ACTIVATION) { - aCallback.notifyDialMMIError(MMI_ERROR_KS_INVALID_ACTION); - return; - } - - if (aMmi.sia !== "" && aMmi.sia !== MMI_ZZ_BARRING_SERVICE) { - aCallback.notifyDialMMIError(MMI_ERROR_KS_NOT_SUPPORTED); - return; - } - - let validPassword = aSi => /^[0-9]{4}$/.test(aSi); - if (!validPassword(aMmi.sib) || !validPassword(aMmi.sic) || - !validPassword(aMmi.pwd)) { - aCallback.notifyDialMMIError(MMI_ERROR_KS_INVALID_PASSWORD); - return; - } - - if (aMmi.sic !== aMmi.pwd) { - aCallback.notifyDialMMIError(MMI_ERROR_KS_MISMATCH_PASSWORD); - return; - } - - let connection = gGonkMobileConnectionService.getItemByServiceId(aClientId); - connection.changeCallBarringPassword(aMmi.sib, aMmi.sic, { - QueryInterface: XPCOMUtils.generateQI([Ci.nsIMobileConnectionCallback]), - notifySuccess: function() { - aCallback.notifyDialMMISuccess(MMI_SM_KS_PASSWORD_CHANGED); - }, - notifyError: function(aErrorMsg) { - aCallback.notifyDialMMIError(aErrorMsg); - }, - }); - }, - - /** - * Handle call barring MMI code. - * - * @param aClientId - * Client id. - * @param aMmi - * Parsed MMI structure. - * @param aCallback - * A nsITelephonyDialCallback object. - */ - _callBarringMMI: function(aClientId, aMmi, aCallback) { - let connection = gGonkMobileConnectionService.getItemByServiceId(aClientId); - let program = MMI_SC_TO_CB_PROGRAM[aMmi.serviceCode]; - let password = aMmi.sia || ""; - let serviceClass = this._siToServiceClass(aMmi.sib); - - switch (aMmi.procedure) { - case MMI_PROCEDURE_INTERROGATION: - connection.getCallBarring(program, password, serviceClass, { - QueryInterface: XPCOMUtils.generateQI([Ci.nsIMobileConnectionCallback]), - notifyGetCallBarringSuccess: function(aProgram, aEnabled, aServiceClass) { - if (!aEnabled) { - aCallback.notifyDialMMISuccess(MMI_SM_KS_SERVICE_DISABLED); - return; - } - - let services = this._serviceClassToStringArray(aServiceClass); - aCallback.notifyDialMMISuccessWithStrings(MMI_SM_KS_SERVICE_ENABLED_FOR, - services.length, services); - }.bind(this), - notifyError: function(aErrorMsg) { - aCallback.notifyDialMMIError(aErrorMsg); - }, - }); - break; - case MMI_PROCEDURE_ACTIVATION: - case MMI_PROCEDURE_DEACTIVATION: { - let enabled = (aMmi.procedure === MMI_PROCEDURE_ACTIVATION); - connection.setCallBarring(program, enabled, password, serviceClass, { - QueryInterface: XPCOMUtils.generateQI([Ci.nsIMobileConnectionCallback]), - notifySuccess: function() { - aCallback.notifyDialMMISuccess( - enabled ? MMI_SM_KS_SERVICE_ENABLED - : MMI_SM_KS_SERVICE_DISABLED - ); - }, - notifyError: function(aErrorMsg) { - aCallback.notifyDialMMIError(aErrorMsg); - }, - }); - break; - } - default: - aCallback.notifyDialMMIError(MMI_ERROR_KS_NOT_SUPPORTED); - break; - } - }, - - /** - * Handle call waiting MMI code. - * - * @param aClientId - * Client id. - * @param aMmi - * Parsed MMI structure. - * @param aCallback - * A nsITelephonyDialCallback object. - */ - _callWaitingMMI: function(aClientId, aMmi, aCallback) { - let connection = gGonkMobileConnectionService.getItemByServiceId(aClientId); - - switch (aMmi.procedure) { - case MMI_PROCEDURE_INTERROGATION: - connection.getCallWaiting({ - QueryInterface: XPCOMUtils.generateQI([Ci.nsIMobileConnectionCallback]), - notifyGetCallWaitingSuccess: function(aServiceClass) { - if (aServiceClass === Ci.nsIMobileConnection.ICC_SERVICE_CLASS_NONE) { - aCallback.notifyDialMMISuccess(MMI_SM_KS_SERVICE_DISABLED); - return; - } - - let services = this._serviceClassToStringArray(aServiceClass); - aCallback.notifyDialMMISuccessWithStrings(MMI_SM_KS_SERVICE_ENABLED_FOR, - services.length, services); - }.bind(this), - notifyError: function(aErrorMsg) { - aCallback.notifyDialMMIError(aErrorMsg); - }, - }); - break; - case MMI_PROCEDURE_ACTIVATION: - case MMI_PROCEDURE_DEACTIVATION: { - let enabled = (aMmi.procedure === MMI_PROCEDURE_ACTIVATION); - let serviceClass = this._siToServiceClass(aMmi.sia); - connection.setCallWaiting(enabled, serviceClass, { - QueryInterface: XPCOMUtils.generateQI([Ci.nsIMobileConnectionCallback]), - notifySuccess: function() { - aCallback.notifyDialMMISuccess( - enabled ? MMI_SM_KS_SERVICE_ENABLED - : MMI_SM_KS_SERVICE_DISABLED - ); - }, - notifyError: function(aErrorMsg) { - aCallback.notifyDialMMIError(aErrorMsg); - }, - }); - break; - } - default: - aCallback.notifyDialMMIError(MMI_ERROR_KS_NOT_SUPPORTED); - break; - } - }, - - _serviceCodeToKeyString: function(aServiceCode) { - switch (aServiceCode) { - case MMI_SC_CFU: - case MMI_SC_CF_BUSY: - case MMI_SC_CF_NO_REPLY: - case MMI_SC_CF_NOT_REACHABLE: - case MMI_SC_CF_ALL: - case MMI_SC_CF_ALL_CONDITIONAL: - return MMI_KS_SC_CALL_FORWARDING; - case MMI_SC_PIN: - return MMI_KS_SC_PIN; - case MMI_SC_PIN2: - return MMI_KS_SC_PIN2; - case MMI_SC_PUK: - return MMI_KS_SC_PUK; - case MMI_SC_PUK2: - return MMI_KS_SC_PUK2; - case MMI_SC_IMEI: - return MMI_KS_SC_IMEI; - case MMI_SC_CLIP: - return MMI_KS_SC_CLIP; - case MMI_SC_CLIR: - return MMI_KS_SC_CLIR; - case MMI_SC_BAOC: - case MMI_SC_BAOIC: - case MMI_SC_BAOICxH: - case MMI_SC_BAIC: - case MMI_SC_BAICr: - case MMI_SC_BA_ALL: - case MMI_SC_BA_MO: - case MMI_SC_BA_MT: - return MMI_KS_SC_CALL_BARRING; - case MMI_SC_CALL_WAITING: - return MMI_KS_SC_CALL_WAITING; - case MMI_SC_CHANGE_PASSWORD: - return MMI_KS_SC_CHANGE_PASSWORD; - default: - return MMI_KS_SC_USSD; - } - }, - - /** - * Helper for translating basic service group to service class parameter. - */ - _siToServiceClass: function(aSi) { - if (!aSi) { - return Ci.nsIMobileConnection.ICC_SERVICE_CLASS_NONE; - } - - let serviceCode = parseInt(aSi, 10); - switch (serviceCode) { - case 10: - return Ci.nsIMobileConnection.ICC_SERVICE_CLASS_SMS + - Ci.nsIMobileConnection.ICC_SERVICE_CLASS_FAX + - Ci.nsIMobileConnection.ICC_SERVICE_CLASS_VOICE; - case 11: - return Ci.nsIMobileConnection.ICC_SERVICE_CLASS_VOICE; - case 12: - return Ci.nsIMobileConnection.ICC_SERVICE_CLASS_SMS + - Ci.nsIMobileConnection.ICC_SERVICE_CLASS_FAX; - case 13: - return Ci.nsIMobileConnection.ICC_SERVICE_CLASS_FAX; - case 16: - return Ci.nsIMobileConnection.ICC_SERVICE_CLASS_SMS; - case 19: - return Ci.nsIMobileConnection.ICC_SERVICE_CLASS_FAX + - Ci.nsIMobileConnection.ICC_SERVICE_CLASS_VOICE; - case 21: - return Ci.nsIMobileConnection.ICC_SERVICE_CLASS_PAD + - Ci.nsIMobileConnection.ICC_SERVICE_CLASS_DATA_ASYNC; - case 22: - return Ci.nsIMobileConnection.ICC_SERVICE_CLASS_PACKET + - Ci.nsIMobileConnection.ICC_SERVICE_CLASS_DATA_SYNC; - case 25: - return Ci.nsIMobileConnection.ICC_SERVICE_CLASS_DATA_ASYNC; - case 26: - return Ci.nsIMobileConnection.ICC_SERVICE_CLASS_DATA_SYNC + - Ci.nsIMobileConnection.ICC_SERVICE_CLASS_VOICE; - case 99: - return Ci.nsIMobileConnection.ICC_SERVICE_CLASS_PACKET; - default: - return Ci.nsIMobileConnection.ICC_SERVICE_CLASS_NONE; - } - }, - - _serviceClassToStringArray: function(aServiceClass) { - let services = []; - for (let mask = Ci.nsIMobileConnection.ICC_SERVICE_CLASS_VOICE; - mask <= Ci.nsIMobileConnection.ICC_SERVICE_CLASS_MAX; - mask <<= 1) { - if (mask & aServiceClass) { - services.push(MMI_KS_SERVICE_CLASS_MAPPING[mask]); - } - } - return services; - }, - - _getIccLockMMIError: function(aMmi) { - // As defined in TS.122.030 6.6.2 to change the ICC PIN we should expect - // an MMI code of the form **04*OLD_PIN*NEW_PIN*NEW_PIN#, where old PIN - // should be entered as the SIA parameter and the new PIN as SIB and - // SIC. - if (aMmi.procedure !== MMI_PROCEDURE_REGISTRATION) { - return MMI_ERROR_KS_INVALID_ACTION; - } - - if (!aMmi.sia || !aMmi.sib || !aMmi.sic) { - return MMI_ERROR_KS_ERROR; - } - - if (aMmi.sia.length < 4 || aMmi.sia.length > 8 || - aMmi.sib.length < 4 || aMmi.sib.length > 8 || - aMmi.sic.length < 4 || aMmi.sic.length > 8) { - return MMI_ERROR_KS_INVALID_PIN; - } - - if (aMmi.sib != aMmi.sic) { - return MMI_ERROR_KS_MISMATCH_PIN; - } - - return null; - }, - - /** - * The default callback handler for call operations. - * - * @param aCallback - * An callback object including notifySuccess() and notifyError(aMsg) - * @param aResponse - * The response from ril_worker. - */ - _defaultCallbackHandler: function(aCallback, aResponse) { - if (aResponse.errorMsg) { - aCallback.notifyError(aResponse.errorMsg); - } else { - aCallback.notifySuccess(); - } - }, - - _defaultMMICallbackHandler: function(aCallback, aResponse) { - if (aResponse.errorMsg) { - aCallback.notifyDialMMIError(aResponse.errorMsg); - } else { - aCallback.notifyDialMMISuccess(""); - } - }, - - _getCallsWithState: function(aClientId, aState) { - let calls = []; - for (let i in this._currentCalls[aClientId]) { - let call = this._currentCalls[aClientId][i]; - if (call.state === aState) { - calls.push(call); - } - } - return calls; - }, - - /** - * Update call information from RIL. - * - * @return Boolean to indicate whether the data is changed. - */ - _updateCallFromRil: function(aCall, aRilCall) { - aRilCall.state = this._convertRILCallState(aRilCall.state); - aRilCall.number = this._formatInternationalNumber(aRilCall.number, - aRilCall.toa); - - let change = false; - const key = ["state", "number", "numberPresentation", "name", - "namePresentation"]; - - for (let k of key) { - if (aCall[k] != aRilCall[k]) { - aCall[k] = aRilCall[k]; - change = true; - } - } - - aCall.isOutgoing = !aRilCall.isMT; - aCall.isEmergency = DialNumberUtils.isEmergency(aCall.number); - - if (!aCall.started && - aCall.state == nsITelephonyService.CALL_STATE_CONNECTED) { - aCall.started = new Date().getTime(); - } - - return change; - }, - - /** - * Identify the conference group. - * @return [conference state, array of calls in group] - * - * TODO: handle multi-sim case. - */ - _detectConference: function(aClientId) { - // There are some difficuties to identify the conference by |.isMpty| from RIL - // so we don't rely on this flag. - // - |.isMpty| becomes false when the conference call is put on hold. - // - |.isMpty| may remain true when other participants left the conference. - - // All the calls in the conference should have the same state and it is - // either CONNECTED or HELD. That means, if we find a group of call with - // the same state and its size is larger than 2, it must be a conference. - let connectedCalls = this._getCallsWithState(aClientId, nsITelephonyService.CALL_STATE_CONNECTED); - let heldCalls = this._getCallsWithState(aClientId, nsITelephonyService.CALL_STATE_HELD); - - if (connectedCalls.length >= 2) { - return [nsITelephonyService.CALL_STATE_CONNECTED, connectedCalls]; - } else if (heldCalls.length >= 2) { - return [nsITelephonyService.CALL_STATE_HELD, heldCalls]; - } - - return [nsITelephonyService.CALL_STATE_UNKNOWN, null]; - }, - - /** - * Update the isConference flag of all Calls. - * - * @return [conference state, array of calls being updated] - */ - _updateConference: function(aClientId) { - let [newConferenceState, conferenceCalls] = this._detectConference(aClientId); - if (DEBUG) debug("Conference state: " + newConferenceState); - - let changedCalls = []; - let conference = new Set(conferenceCalls); - - for (let i in this._currentCalls[aClientId]) { - let call = this._currentCalls[aClientId][i]; - let isConference = conference.has(call); - if (call.isConference != isConference) { - call.isConference = isConference; - changedCalls.push(call); - } - } - - return [newConferenceState, changedCalls]; - }, - - sendTones: function(aClientId, aDtmfChars, aPauseDuration, aToneDuration, - aCallback) { - let timer = Cc["@mozilla.org/timer;1"].createInstance(Ci.nsITimer); - let tones = aDtmfChars; - let playTone = (tone) => { - this._sendToRilWorker(aClientId, "startTone", { dtmfChar: tone }, response => { - if (response.errorMsg) { - aCallback.notifyError(response.errorMsg); - return; - } - - timer.initWithCallback(() => { - this.stopTone(); - timer.initWithCallback(() => { - if (tones.length === 1) { - aCallback.notifySuccess(); - } else { - tones = tones.substr(1); - playTone(tones[0]); - } - }, TONES_GAP_DURATION, Ci.nsITimer.TYPE_ONE_SHOT); - }, aToneDuration, Ci.nsITimer.TYPE_ONE_SHOT); - }); - }; - - timer.initWithCallback(() => { - playTone(tones[0]); - }, aPauseDuration, Ci.nsITimer.TYPE_ONE_SHOT); - }, - - startTone: function(aClientId, aDtmfChar) { - this._sendToRilWorker(aClientId, "startTone", { dtmfChar: aDtmfChar }); - }, - - stopTone: function(aClientId) { - this._sendToRilWorker(aClientId, "stopTone"); - }, - - answerCall: function(aClientId, aCallIndex, aCallback) { - let call = this._currentCalls[aClientId][aCallIndex]; - if (!call || call.state != nsITelephonyService.CALL_STATE_INCOMING) { - aCallback.notifyError(RIL.GECKO_ERROR_GENERIC_FAILURE); - return; - } - - let callNum = Object.keys(this._currentCalls[aClientId]).length; - if (callNum !== 1) { - this._switchActiveCall(aClientId, aCallback); - } else { - this._sendToRilWorker(aClientId, "answerCall", null, - this._defaultCallbackHandler.bind(this, aCallback)); - } - }, - - rejectCall: function(aClientId, aCallIndex, aCallback) { - if (this._isCdmaClient(aClientId)) { - this._hangUpBackground(aClientId, aCallback); - return; - } - - let call = this._currentCalls[aClientId][aCallIndex]; - if (!call || call.state != nsITelephonyService.CALL_STATE_INCOMING) { - aCallback.notifyError(RIL.GECKO_ERROR_GENERIC_FAILURE); - return; - } - - let callNum = Object.keys(this._currentCalls[aClientId]).length; - if (callNum !== 1) { - this._hangUpBackground(aClientId, aCallback); - } else { - call.hangUpLocal = true; - this._sendToRilWorker(aClientId, "udub", null, - this._defaultCallbackHandler.bind(this, aCallback)); - } - }, - - _hangUpForeground: function(aClientId, aCallback) { - let calls = this._getCallsWithState(aClientId, nsITelephonyService.CALL_STATE_CONNECTED); - calls.forEach(call => call.hangUpLocal = true); - - this._sendToRilWorker(aClientId, "hangUpForeground", null, - this._defaultCallbackHandler.bind(this, aCallback)); - }, - - _hangUpBackground: function(aClientId, aCallback) { - // When both a held and a waiting call exist, the request shall apply to - // the waiting call. - let waitingCalls = this._getCallsWithState(aClientId, nsITelephonyService.CALL_STATE_INCOMING); - let heldCalls = this._getCallsWithState(aClientId, nsITelephonyService.CALL_STATE_HELD); - - if (waitingCalls.length) { - waitingCalls.forEach(call => call.hangUpLocal = true); - } else { - heldCalls.forEach(call => call.hangUpLocal = true); - } - - this._sendToRilWorker(aClientId, "hangUpBackground", null, - this._defaultCallbackHandler.bind(this, aCallback)); - }, - - hangUpCall: function(aClientId, aCallIndex, aCallback) { - // Should release both, child and parent, together. Since RIL holds only - // the parent call, we send 'parentId' to RIL. - aCallIndex = this._currentCalls[aClientId][aCallIndex].parentId || aCallIndex; - - let call = this._currentCalls[aClientId][aCallIndex]; - if (call.state === nsITelephonyService.CALL_STATE_HELD) { - this._hangUpBackground(aClientId, aCallback); - return; - } - - // After hangup a single call, gecko has to resume the held call or conference. - if (!call.isConference) { - let heldCalls = this._getCallsWithState(aClientId, nsITelephonyService.CALL_STATE_HELD); - - if (heldCalls.length) { - if (call.state === nsITelephonyService.CALL_STATE_CONNECTED) { - // For a foreground call, ril has a request to do two actions together. - this._hangUpForeground(aClientId, aCallback); - } else { - // Otherwise, gecko should send out two consecutive requests by itself. - this._sendToRilWorker(aClientId, "hangUpCall", { callIndex: aCallIndex }, response => { - if (response.errorMsg) { - aCallback.notifyError(response.errorMsg); - } else { - aCallback.notifySuccess(); - - let emptyCallback = { - QueryInterface: XPCOMUtils.generateQI([Ci.nsITelephonyCallback]), - notifySuccess: () => {}, - notifyError: () => {} - }; - - if (heldCalls.length === 1) { - this.resumeCall(aClientId, heldCalls[0].callIndex, emptyCallback); - } else { - this.resumeConference(aClientId, emptyCallback); - } - } - }); - } - - return; - } - } - - call.hangUpLocal = true; - this._sendToRilWorker(aClientId, "hangUpCall", { callIndex: aCallIndex }, - this._defaultCallbackHandler.bind(this, aCallback)); - }, - - _switchCall: function(aClientId, aCallIndex, aCallback, aRequiredState) { - let call = this._currentCalls[aClientId][aCallIndex]; - if (!call) { - aCallback.notifyError(RIL.GECKO_ERROR_GENERIC_FAILURE); - return; - } - - if (this._isCdmaClient(aClientId)) { - this._switchCallCdma(aClientId, aCallIndex, aCallback); - } else { - this._switchCallGsm(aClientId, aCallIndex, aCallback, aRequiredState); - } - }, - - _switchCallGsm: function(aClientId, aCallIndex, aCallback, aRequiredState) { - let call = this._currentCalls[aClientId][aCallIndex]; - if (call.state != aRequiredState) { - aCallback.notifyError(RIL.GECKO_ERROR_GENERIC_FAILURE); - return; - } - - this._switchActiveCall(aClientId, aCallback); - }, - - _switchActiveCall: function(aClientId, aCallback) { - this._sendToRilWorker(aClientId, "switchActiveCall", null, - this._defaultCallbackHandler.bind(this, aCallback)); - }, - - _switchCallCdma: function(aClientId, aCallIndex, aCallback) { - let call = this._currentCalls[aClientId][aCallIndex]; - if (!call.isSwitchable) { - aCallback.notifyError(RIL.GECKO_ERROR_GENERIC_FAILURE); - return; - } - - this._sendToRilWorker(aClientId, "cdmaFlash", null, - this._defaultCallbackHandler.bind(this, aCallback)); - }, - - holdCall: function(aClientId, aCallIndex, aCallback) { - this._switchCall(aClientId, aCallIndex, aCallback, - nsITelephonyService.CALL_STATE_CONNECTED); - }, - - resumeCall: function(aClientId, aCallIndex, aCallback) { - this._switchCall(aClientId, aCallIndex, aCallback, - nsITelephonyService.CALL_STATE_HELD); - }, - - _conferenceCallGsm: function(aClientId, aCallback) { - this._sendToRilWorker(aClientId, "conferenceCall", null, response => { - if (response.errorMsg) { - aCallback.notifyError(RIL.GECKO_ERROR_GENERIC_FAILURE); - // TODO: Bug 1124993. Deprecate it. Use callback response is enough. - this._notifyAllListeners("notifyConferenceError", - ["addError", response.errorMsg]); - return; - } - - aCallback.notifySuccess(); - }); - }, - - _conferenceCallCdma: function(aClientId, aCallback) { - for (let index in this._currentCalls[aClientId]) { - let call = this._currentCalls[aClientId][index]; - if (!call.isMergeable) { - aCallback.notifyError(RIL.GECKO_ERROR_GENERIC_FAILURE); - return; - } - } - - this._sendToRilWorker(aClientId, "cdmaFlash", null, response => { - if (response.errorMsg) { - aCallback.notifyError(RIL.GECKO_ERROR_GENERIC_FAILURE); - // TODO: Bug 1124993. Deprecate it. Use callback response is enough. - this._notifyAllListeners("notifyConferenceError", - ["addError", response.errorMsg]); - return; - } - - let calls = []; - for (let index in this._currentCalls[aClientId]) { - let call = this._currentCalls[aClientId][index]; - call.state = nsITelephonyService.CALL_STATE_CONNECTED; - call.isConference = true; - calls.push(call); - } - this._handleCallStateChanged(aClientId, calls); - - aCallback.notifySuccess(); - }); - }, - - conferenceCall: function(aClientId, aCallback) { - if (Object.keys(this._currentCalls[aClientId]).length < 2) { - aCallback.notifyError(RIL.GECKO_ERROR_GENERIC_FAILURE); - return; - } - - if (this._isCdmaClient(aClientId)) { - this._conferenceCallCdma(aClientId, aCallback); - } else { - this._conferenceCallGsm(aClientId, aCallback); - } - }, - - _separateCallGsm: function(aClientId, aCallIndex, aCallback) { - this._sendToRilWorker(aClientId, "separateCall", { callIndex: aCallIndex }, - response => { - if (response.errorMsg) { - aCallback.notifyError(RIL.GECKO_ERROR_GENERIC_FAILURE); - // TODO: Bug 1124993. Deprecate it. Use callback response is enough. - this._notifyAllListeners("notifyConferenceError", - ["removeError", response.errorMsg]); - return; - } - - aCallback.notifySuccess(); - }); - }, - - _removeCdmaSecondCall: function(aClientId) { - let childCall = this._currentCalls[aClientId][CDMA_SECOND_CALL_INDEX]; - let parentCall = this._currentCalls[aClientId][CDMA_FIRST_CALL_INDEX]; - - this._disconnectCalls(aClientId, [childCall]); - - parentCall.isConference = false; - parentCall.isSwitchable = true; - parentCall.isMergeable = true; - this._handleCallStateChanged(aClientId, [childCall, parentCall]); - }, - - // See 3gpp2, S.R0006-522-A v1.0. Table 4, XID 6S. - // Release the third party. Optionally apply a warning tone. Connect the - // controlling subscriber and the second party. Go to the 2-way state. - _separateCallCdma: function(aClientId, aCallIndex, aCallback) { - this._sendToRilWorker(aClientId, "cdmaFlash", null, response => { - if (response.errorMsg) { - aCallback.notifyError(RIL.GECKO_ERROR_GENERIC_FAILURE); - // TODO: Bug 1124993. Deprecate it. Use callback response is enough. - this._notifyAllListeners("notifyConferenceError", - ["removeError", response.errorMsg]); - return; - } - - this._removeCdmaSecondCall(aClientId); - aCallback.notifySuccess(); - }); - }, - - separateCall: function(aClientId, aCallIndex, aCallback) { - let call = this._currentCalls[aClientId][aCallIndex]; - if (!call || !call.isConference) { - aCallback.notifyError(RIL.GECKO_ERROR_GENERIC_FAILURE); - return; - } - - if (this._isCdmaClient(aClientId)) { - this._separateCallCdma(aClientId, aCallIndex, aCallback); - } else { - this._separateCallGsm(aClientId, aCallIndex, aCallback); - } - }, - - hangUpConference: function(aClientId, aCallback) { - // In cdma, ril only maintains one call index. - if (this._isCdmaClient(aClientId)) { - this._sendToRilWorker(aClientId, "hangUpCall", - { callIndex: CDMA_FIRST_CALL_INDEX }, - this._defaultCallbackHandler.bind(this, aCallback)); - return; - } - - // Find a conference call, and send the corresponding request to RIL worker. - for (let index in this._currentCalls[aClientId]) { - let call = this._currentCalls[aClientId][index]; - if (!call.isConference) { - continue; - } - - let command = call.state === nsITelephonyService.CALL_STATE_CONNECTED ? - "hangUpForeground" : "hangUpBackground"; - this._sendToRilWorker(aClientId, command, null, - this._defaultCallbackHandler.bind(this, aCallback)); - return; - } - - // There is no conference call. - if (DEBUG) debug("hangUpConference: " + - "No conference call in modem[" + aClientId + "]."); - aCallback.notifyError(RIL.GECKO_ERROR_GENERIC_FAILURE); - }, - - _switchConference: function(aClientId, aCallback) { - // Cannot hold/resume a conference in cdma. - if (this._isCdmaClient(aClientId)) { - aCallback.notifyError(RIL.GECKO_ERROR_GENERIC_FAILURE); - return; - } - - this._switchActiveCall(aClientId, aCallback); - }, - - holdConference: function(aClientId, aCallback) { - this._switchConference(aClientId, aCallback); - }, - - resumeConference: function(aClientId, aCallback) { - this._switchConference(aClientId, aCallback); - }, - - sendUSSD: function(aClientId, aUssd, aCallback) { - this._sendUSSDInternal(aClientId, aUssd, - this._defaultCallbackHandler.bind(this, aCallback)); - }, - - _sendUSSDInternal: function(aClientId, aUssd, aCallback) { - this._ussdSessions[aClientId] = USSD_SESSION_ONGOING; - this._sendToRilWorker(aClientId, "sendUSSD", { ussd: aUssd }, aResponse => { - if (aResponse.errorMsg) { - this._ussdSessions[aClientId] = USSD_SESSION_DONE; - } - aCallback(aResponse); - }); - }, - - cancelUSSD: function(aClientId, aCallback) { - this._cancelUSSDInternal(aClientId, - this._defaultCallbackHandler.bind(this, aCallback)); - }, - - _cancelUSSDInternal: function(aClientId, aCallback) { - this._ussdSessions[aClientId] = USSD_SESSION_CANCELLING; - this._sendToRilWorker(aClientId, "cancelUSSD", {}, aResponse => { - if (aResponse.errorMsg) { - this._ussdSessions[aClientId] = USSD_SESSION_ONGOING; - } - aCallback(aResponse); - }); - }, - - get microphoneMuted() { - return gAudioService.microphoneMuted; - }, - - set microphoneMuted(aMuted) { - gAudioService.microphoneMuted = aMuted; - }, - - get speakerEnabled() { - return gAudioService.speakerEnabled; - }, - - set speakerEnabled(aEnabled) { - gAudioService.speakerEnabled = aEnabled; - }, - - /** - * nsIGonkTelephonyService interface. - */ - - _notifyCallEnded: function(aCall) { - let duration = ("started" in aCall && typeof aCall.started == "number") ? - new Date().getTime() - aCall.started : 0; - - gTelephonyMessenger.notifyCallEnded(aCall.clientId, - aCall.number, - this._cdmaCallWaitingNumber, - aCall.isEmergency, - duration, - aCall.isOutgoing, - aCall.hangUpLocal); - - // Clear cache of this._cdmaCallWaitingNumber after call disconnected. - this._cdmaCallWaitingNumber = null; - }, - - /** - * Disconnect calls by updating their states. Sometimes, it may cause other - * calls being disconnected as well. - * - * @return Array a list of calls we need to fire callStateChange - */ - _disconnectCalls: function(aClientId, aCalls, - aFailCause = RIL.GECKO_CALL_ERROR_NORMAL_CALL_CLEARING) { - if (DEBUG) debug("_disconnectCalls: " + JSON.stringify(aCalls)); - - // In addition to the disconnected call itself, its decedent calls should be - // treated as disconnected calls as well. - let disconnectedCalls = aCalls.slice(); - for (let call in aCalls) { - while (call.childId) { - call = this._currentCalls[aClientId][call.childId]; - disconnectedCalls.push(call); - } - } - - // Store unique value in the list. - disconnectedCalls = [...new Set(disconnectedCalls)]; - - let callsForStateChanged = []; - - disconnectedCalls.forEach(call => { - call.state = nsITelephonyService.CALL_STATE_DISCONNECTED; - call.disconnectedReason = aFailCause; - - let parentCall = this._currentCalls[aClientId][call.parentId]; - if (parentCall) { - delete parentCall.childId; - } - - this._notifyCallEnded(call); - - callsForStateChanged.push(call); - - delete this._currentCalls[aClientId][call.callIndex]; - }); - - return callsForStateChanged; - }, - - /** - * Handle an incoming call. - * - * Not much is known about this call at this point, but it's enough - * to start bringing up the Phone app already. - */ - notifyCallRing: function() { - // We need to acquire a CPU wake lock to avoid the system falling into - // the sleep mode when the RIL handles the incoming call. - this._acquireCallRingWakeLock(); - - gTelephonyMessenger.notifyNewCall(); - }, - - /** - * Handle current calls reported from RIL. - * - * @param aCalls call from RIL, which contains: - * state, callIndex, toa, isMT, number, numberPresentation, name, - * namePresentation. - */ - notifyCurrentCalls: function(aClientId, aCalls) { - // Check whether there is a removed call. - let hasRemovedCalls = () => { - let newIndexes = new Set(Object.keys(aCalls)); - for (let i in this._currentCalls[aClientId]) { - if (!newIndexes.has(i)) { - return true; - } - } - return false; - }; - - // If there are removedCalls, we should fetch the failCause first. - if (!hasRemovedCalls()) { - this._handleCurrentCalls(aClientId, aCalls); - } else { - this._sendToRilWorker(aClientId, "getFailCause", null, response => { - this._handleCurrentCalls(aClientId, aCalls, response.failCause); - }); - } - }, - - _handleCurrentCalls: function(aClientId, aCalls, - aFailCause = RIL.GECKO_CALL_ERROR_NORMAL_CALL_CLEARING) { - if (DEBUG) debug("handleCurrentCalls: " + JSON.stringify(aCalls) + - ", failCause: " + aFailCause); - - let changedCalls = new Set(); - let removedCalls = new Set(); - - let allIndexes = new Set([...Object.keys(this._currentCalls[aClientId]), - ...Object.keys(aCalls)]); - - for (let i of allIndexes) { - let call = this._currentCalls[aClientId][i]; - let rilCall = aCalls[i]; - - // Determine the change of call. - if (call && !rilCall) { // removed. - removedCalls.add(call); - } else if (call && rilCall) { // changed. - if (this._updateCallFromRil(call, rilCall)) { - changedCalls.add(call); - } - } else { // !call && rilCall. added. - this._currentCalls[aClientId][i] = call = new Call(aClientId, i); - this._updateCallFromRil(call, rilCall); - changedCalls.add(call); - - // Handle ongoingDial. - if (this._ongoingDial && this._ongoingDial.clientId === aClientId && - call.state !== nsITelephonyService.CALL_STATE_INCOMING) { - this._ongoingDial.callback.notifyDialCallSuccess(aClientId, i, - call.number); - this._ongoingDial = null; - } - } - } - - // For correct conference detection, we should mark removedCalls as - // DISCONNECTED first. - let disconnectedCalls = this._disconnectCalls(aClientId, [...removedCalls], aFailCause); - disconnectedCalls.forEach(call => changedCalls.add(call)); - - // Detect conference and update isConference flag. - let [newConferenceState, conferenceChangedCalls] = this._updateConference(aClientId); - conferenceChangedCalls.forEach(call => changedCalls.add(call)); - - this._handleCallStateChanged(aClientId, [...changedCalls]); - - this._updateAudioState(aClientId); - - // Handle cached dial request. - if (this._cachedDialRequest && !this._isActive(aClientId)) { - if (DEBUG) debug("All calls held. Perform the cached dial request."); - - let request = this._cachedDialRequest; - this._sendDialCallRequest(request.clientId, request.options, - request.callback); - this._cachedDialRequest = null; - } - }, - - /** - * Handle call state changes. - */ - _handleCallStateChanged: function(aClientId, aCalls) { - if (DEBUG) debug("handleCallStateChanged: " + JSON.stringify(aCalls)); - - if (aCalls.length === 0) { - return; - } - - if (aCalls.some(call => call.state == nsITelephonyService.CALL_STATE_DIALING)) { - gTelephonyMessenger.notifyNewCall(); - } - - let allInfo = aCalls.map(call => new TelephonyCallInfo(call)); - this._notifyAllListeners("callStateChanged", [allInfo.length, allInfo]); - }, - - notifyCdmaCallWaiting: function(aClientId, aCall) { - // We need to acquire a CPU wake lock to avoid the system falling into - // the sleep mode when the RIL handles the incoming call. - this._acquireCallRingWakeLock(); - - let call = this._currentCalls[aClientId][CDMA_SECOND_CALL_INDEX]; - if (call) { - // TODO: Bug 977503 - B2G RIL: [CDMA] update callNumber when a waiting - // call comes after a 3way call. - this._removeCdmaSecondCall(aClientId); - } - - this._cdmaCallWaitingNumber = aCall.number; - - this._notifyAllListeners("notifyCdmaCallWaiting", [aClientId, - aCall.number, - aCall.numberPresentation, - aCall.name, - aCall.namePresentation]); - }, - - notifySupplementaryService: function(aClientId, aNumber, aNotification) { - let notification = this._convertRILSuppSvcNotification(aNotification); - - // Get the target call object for this notification. - let callIndex = -1; - - let indexes = Object.keys(this.currentCalls); - if (indexes.length === 1) { - // Only one call exists. This should be the target. - callIndex = indexes[0]; - } else { - // Find the call in |currentCalls| by the given number. - if (aNumber) { - for (let i in this._currentCalls) { - let call = this._currentCalls[aClientId][i]; - if (call.number === aNumber) { - callIndex = i; - break; - } - } - } - } - - this._notifyAllListeners("supplementaryServiceNotification", - [aClientId, callIndex, notification]); - }, - - notifyUssdReceived: function(aClientId, aMessage, aSessionEnded) { - if (DEBUG) { - debug("notifyUssdReceived for " + aClientId + ": " + - aMessage + " (sessionEnded : " + aSessionEnded + ")"); - } - - let oldSession = this._ussdSessions[aClientId]; - this._ussdSessions[aClientId] = - aSessionEnded ? USSD_SESSION_DONE : USSD_SESSION_ONGOING; - - // We suppress the empty message only when the session is not changed and - // is not alive. See Bug 1057455, 1198676. - // Moreover, we should allow a notification initiated by network - // in which further response is not required. - // See |5.2.2 Actions at the UE| in 3GPP TS 22.090: - // " - // The network may explicitly indicate to the UE that a response - // from the user is required. ... - // If the network does not indicate that a response is required, - // then the normal MMI procedures on the UE continue to apply. - // " - if (oldSession != USSD_SESSION_ONGOING && - this._ussdSessions[aClientId] != USSD_SESSION_ONGOING && - !aMessage) { - return; - } - - gTelephonyMessenger.notifyUssdReceived(aClientId, aMessage, aSessionEnded); - }, - - /** - * nsIObserver interface. - */ - - observe: function(aSubject, aTopic, aData) { - switch (aTopic) { - case NS_PREFBRANCH_PREFCHANGE_TOPIC_ID: - if (aData === kPrefRilDebuggingEnabled) { - this._updateDebugFlag(); - } else if (aData === kPrefDefaultServiceId) { - this.defaultServiceId = this._getDefaultServiceId(); - } - break; - - case NS_XPCOM_SHUTDOWN_OBSERVER_ID: - // Release the CPU wake lock for handling the incoming call. - this._releaseCallRingWakeLock(); - - Services.obs.removeObserver(this, NS_XPCOM_SHUTDOWN_OBSERVER_ID); - break; - } - } -}; - -this.NSGetFactory = XPCOMUtils.generateNSGetFactory([TelephonyService]); diff --git a/dom/telephony/gonk/TelephonyService.manifest b/dom/telephony/gonk/TelephonyService.manifest deleted file mode 100644 index 8a15cdf8dc4c..000000000000 --- a/dom/telephony/gonk/TelephonyService.manifest +++ /dev/null @@ -1,3 +0,0 @@ -component {67d26434-d063-4d28-9f48-5b3189788155} TelephonyService.js -contract @mozilla.org/telephony/gonktelephonyservice;1 {67d26434-d063-4d28-9f48-5b3189788155} - diff --git a/dom/telephony/gonk/TelephonyUtils.jsm b/dom/telephony/gonk/TelephonyUtils.jsm deleted file mode 100644 index 4406656ba4f8..000000000000 --- a/dom/telephony/gonk/TelephonyUtils.jsm +++ /dev/null @@ -1,109 +0,0 @@ -/* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this file, - * You can obtain one at http://mozilla.org/MPL/2.0/. */ - -"use strict"; - -this.EXPORTED_SYMBOLS = ["TelephonyUtils"]; - -const {classes: Cc, interfaces: Ci, utils: Cu, results: Cr} = Components; - -Cu.import("resource://gre/modules/XPCOMUtils.jsm"); -Cu.import("resource://gre/modules/Promise.jsm"); - -/* global TelephonyService */ -XPCOMUtils.defineLazyServiceGetter(this, - "TelephonyService", - "@mozilla.org/telephony/telephonyservice;1", - "nsITelephonyService"); - -function getCurrentCalls(aFilter) { - if (aFilter === undefined) { - aFilter = call => true; - } - - let calls = []; - - // nsITelephonyService.enumerateCalls is synchronous. - TelephonyService.enumerateCalls({ - QueryInterface: XPCOMUtils.generateQI([Ci.nsITelephonyListener]), - enumerateCallStateComplete: function() {}, - enumerateCallState: function(call) { - if (aFilter(call)) { - calls.push(call); - } - }, - }); - - return calls; -} - -this.TelephonyUtils = { - /** - * Check whether there are any calls. - * - * @param aClientId [optional] If provided, only check on aClientId - * @return boolean - */ - hasAnyCalls: function(aClientId) { - let calls = getCurrentCalls(call => { - if (aClientId !== undefined && call.clientId !== aClientId) { - return false; - } - return true; - }); - - return calls.length !== 0; - }, - - /** - * Check whether there are any connected calls. - * - * @param aClientId [optional] If provided, only check on aClientId - * @return boolean - */ - hasConnectedCalls: function(aClientId) { - let calls = getCurrentCalls(call => { - if (aClientId !== undefined && call.clientId !== aClientId) { - return false; - } - return call.callState === Ci.nsITelephonyService.CALL_STATE_CONNECTED; - }); - - return calls.length !== 0; - }, - - /** - * Return a promise which will be resolved when there are no calls. - * - * @param aClientId [optional] only check on aClientId if provided - * @return Promise - */ - waitForNoCalls: function(aClientId) { - if (!this.hasAnyCalls(aClientId)) { - return Promise.resolve(); - } - - let self = this; - return new Promise(resolve => { - let listener = { - QueryInterface: XPCOMUtils.generateQI([Ci.nsITelephonyListener]), - - enumerateCallStateComplete: function() {}, - enumerateCallState: function() {}, - callStateChanged: function() { - if (!self.hasAnyCalls(aClientId)) { - TelephonyService.unregisterListener(this); - resolve(); - } - }, - supplementaryServiceNotification: function() {}, - notifyError: function() {}, - notifyCdmaCallWaiting: function() {}, - notifyConferenceError: function() {} - }; - - TelephonyService.registerListener(listener); - }); - } -}; diff --git a/dom/telephony/gonk/USSDReceivedWrapper.js b/dom/telephony/gonk/USSDReceivedWrapper.js deleted file mode 100644 index 4d78932a2a40..000000000000 --- a/dom/telephony/gonk/USSDReceivedWrapper.js +++ /dev/null @@ -1,82 +0,0 @@ -/* -*- indent-tabs-mode: nil; js-indent-level: 2 -*- */ -/* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this file, - * You can obtain one at http://mozilla.org/MPL/2.0/. */ - -"use strict"; - -const {classes: Cc, interfaces: Ci, utils: Cu, results: Cr} = Components; - -Cu.import("resource://gre/modules/Services.jsm"); -Cu.import("resource://gre/modules/XPCOMUtils.jsm"); - -const NS_PREFBRANCH_PREFCHANGE_TOPIC_ID = "nsPref:changed"; -const kPrefRilDebuggingEnabled = "ril.debugging.enabled"; - -var DEBUG; -function debug(s) { - dump("USSDReceivedWrapper: " + s + "\n"); -} - -XPCOMUtils.defineLazyGetter(this, "RIL", function () { - let obj = {}; - Cu.import("resource://gre/modules/ril_consts.js", obj); - return obj; -}); - -/** - * This implements nsISystemMessagesWrapper.wrapMessage(), which provides a - * plugable way to wrap a "ussd-received" type system message. - * - * Please see SystemMessageManager.js to know how it customizes the wrapper. - */ -function USSDReceivedWrapper() { - this._updateDebugFlag(); - Services.prefs.addObserver(kPrefRilDebuggingEnabled, this, false); - if (DEBUG) debug("USSDReceivedWrapper()"); -} -USSDReceivedWrapper.prototype = { - _updateDebugFlag: function() { - try { - DEBUG = RIL.DEBUG_RIL || - Services.prefs.getBoolPref(kPrefRilDebuggingEnabled); - } catch (e) {} - }, - - /** - * nsIObserver interface. - */ - observe: function(aSubject, aTopic, aData) { - switch (aTopic) { - case NS_PREFBRANCH_PREFCHANGE_TOPIC_ID: - if (aData === kPrefRilDebuggingEnabled) { - this._updateDebugFlag(); - } - break; - } - }, - - // nsISystemMessagesWrapper implementation. - wrapMessage: function(aMessage, aWindow) { - if (DEBUG) debug("wrapMessage: " + JSON.stringify(aMessage)); - - let session = aMessage.sessionEnded ? null : - new aWindow.USSDSession(aMessage.serviceId); - - let event = new aWindow.USSDReceivedEvent("ussdreceived", { - serviceId: aMessage.serviceId, - message: aMessage.message, - session: session - }); - - return event; - }, - - classDescription: "USSDReceivedWrapper", - classID: Components.ID("{d03684ed-ede4-4210-8206-f4f32772d9f5}"), - contractID: "@mozilla.org/dom/system-messages/wrapper/ussd-received;1", - QueryInterface: XPCOMUtils.generateQI([Ci.nsIObserver, - Ci.nsISystemMessagesWrapper]) -}; - -this.NSGetFactory = XPCOMUtils.generateNSGetFactory([USSDReceivedWrapper]); diff --git a/dom/telephony/gonk/USSDReceivedWrapper.manifest b/dom/telephony/gonk/USSDReceivedWrapper.manifest deleted file mode 100644 index 039498828c57..000000000000 --- a/dom/telephony/gonk/USSDReceivedWrapper.manifest +++ /dev/null @@ -1,2 +0,0 @@ -component {d03684ed-ede4-4210-8206-f4f32772d9f5} USSDReceivedWrapper.js -contract @mozilla.org/dom/system-messages/wrapper/ussd-received;1 {d03684ed-ede4-4210-8206-f4f32772d9f5} diff --git a/dom/telephony/ipc/PTelephony.ipdl b/dom/telephony/ipc/PTelephony.ipdl deleted file mode 100644 index 9660d1dd1b98..000000000000 --- a/dom/telephony/ipc/PTelephony.ipdl +++ /dev/null @@ -1,169 +0,0 @@ -/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ -/* vim: set sw=2 ts=8 et ft=cpp : */ -/* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this file, - * You can obtain one at http://mozilla.org/MPL/2.0/. */ - -include protocol PContent; -include protocol PTelephonyRequest; -include TelephonyTypes; - -using nsTelephonyCallInfo from "mozilla/dom/telephony/TelephonyIPCSerializer.h"; - -namespace mozilla { -namespace dom { -namespace telephony { - -struct EnumerateCallsRequest -{ - // empty. -}; - -struct DialRequest -{ - uint32_t clientId; - nsString number; - bool isEmergency; -}; - -struct SendUSSDRequest -{ - uint32_t clientId; - nsString ussd; -}; - -struct CancelUSSDRequest -{ - uint32_t clientId; -}; - -struct ConferenceCallRequest -{ - uint32_t clientId; -}; - -struct SeparateCallRequest -{ - uint32_t clientId; - uint32_t callIndex; -}; - -struct HangUpConferenceRequest -{ - uint32_t clientId; -}; - -struct HoldConferenceRequest -{ - uint32_t clientId; -}; - -struct ResumeConferenceRequest -{ - uint32_t clientId; -}; - -struct AnswerCallRequest -{ - uint32_t clientId; - uint32_t callIndex; -}; - -struct HangUpCallRequest -{ - uint32_t clientId; - uint32_t callIndex; -}; - -struct RejectCallRequest -{ - uint32_t clientId; - uint32_t callIndex; -}; - -struct HoldCallRequest -{ - uint32_t clientId; - uint32_t callIndex; -}; - -struct ResumeCallRequest -{ - uint32_t clientId; - uint32_t callIndex; -}; - -struct SendTonesRequest -{ - uint32_t clientId; - nsString dtmfChars; - uint32_t pauseDuration; - uint32_t toneDuration; -}; - -union IPCTelephonyRequest -{ - EnumerateCallsRequest; - DialRequest; - SendUSSDRequest; - CancelUSSDRequest; - ConferenceCallRequest; - SeparateCallRequest; - HangUpConferenceRequest; - HoldConferenceRequest; - ResumeConferenceRequest; - AnswerCallRequest; - HangUpCallRequest; - RejectCallRequest; - HoldCallRequest; - ResumeCallRequest; - SendTonesRequest; -}; - -sync protocol PTelephony { - manager PContent; - manages PTelephonyRequest; - -child: - async NotifyCallStateChanged(nsTelephonyCallInfo[] aAllInfo); - - async NotifyCdmaCallWaiting(uint32_t aClientId, IPCCdmaWaitingCallData aData); - - async NotifyConferenceError(nsString aName, nsString aMessage); - - async NotifySupplementaryService(uint32_t aClientId, int32_t aCallIndex, - uint16_t aNotification); - -parent: - /** - * Sent when the child no longer needs to use PTelephony. - */ - async __delete__(); - - /** - * Sent when the child makes an asynchronous request to the parent. - */ - async PTelephonyRequest(IPCTelephonyRequest request); - - async RegisterListener(); - - async UnregisterListener(); - - async StartTone(uint32_t aClientId, nsString aTone); - - async StopTone(uint32_t aClientId); - - sync GetMicrophoneMuted() - returns (bool aMuted); - - async SetMicrophoneMuted(bool aMuted); - - sync GetSpeakerEnabled() - returns (bool aEnabled); - - async SetSpeakerEnabled(bool aEnabled); -}; - -} /* namespace telephony */ -} /* namespace dom */ -} /* namespace mozilla */ diff --git a/dom/telephony/ipc/PTelephonyRequest.ipdl b/dom/telephony/ipc/PTelephonyRequest.ipdl deleted file mode 100644 index 7a9755851ee4..000000000000 --- a/dom/telephony/ipc/PTelephonyRequest.ipdl +++ /dev/null @@ -1,81 +0,0 @@ -/* -*- Mode: c++; c-basic-offset: 2; indent-tabs-mode: nil; tab-width: 40 -*- */ -/* vim: set ts=2 et sw=2 tw=80: */ -/* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this file, - * You can obtain one at http://mozilla.org/MPL/2.0/. */ - -include protocol PTelephony; -include TelephonyTypes; - -using nsTelephonyCallInfo from "mozilla/dom/telephony/TelephonyIPCSerializer.h"; - -namespace mozilla { -namespace dom { -namespace telephony { - -struct EnumerateCallsResponse -{ - // empty. -}; - -struct SuccessResponse -{ - // empty. -}; - -struct ErrorResponse -{ - nsString name; -}; - -struct DialResponseCallSuccess -{ - uint32_t clientId; - uint32_t callIndex; - nsString number; -}; - -struct DialResponseMMISuccess -{ - nsString statusMessage; - AdditionalInformation additionalInformation; -}; - -struct DialResponseMMIError -{ - nsString name; - AdditionalInformation additionalInformation; -}; - -union IPCTelephonyResponse -{ - EnumerateCallsResponse; - - // General. - SuccessResponse; - ErrorResponse; - - // dial - DialResponseCallSuccess; - DialResponseMMISuccess; - DialResponseMMIError; -}; - -protocol PTelephonyRequest -{ - manager PTelephony; - -child: - async NotifyEnumerateCallState(nsTelephonyCallInfo aInfo); - - async NotifyDialMMI(nsString aServiceCode); - - /** - * Sent when the asynchronous request has completed. - */ - async __delete__(IPCTelephonyResponse aResponse); -}; - -} /* namespace telephony */ -} /* namespace dom */ -} /* namespace mozilla */ diff --git a/dom/telephony/ipc/TelephonyChild.cpp b/dom/telephony/ipc/TelephonyChild.cpp deleted file mode 100644 index 2355e036c120..000000000000 --- a/dom/telephony/ipc/TelephonyChild.cpp +++ /dev/null @@ -1,271 +0,0 @@ -/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ -/* vim: set ts=8 sts=2 et sw=2 tw=80: */ -/* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this file, - * You can obtain one at http://mozilla.org/MPL/2.0/. */ - -#include "TelephonyChild.h" - -#include "mozilla/dom/telephony/TelephonyDialCallback.h" -#include "mozilla/UniquePtr.h" -#include "TelephonyIPCService.h" - -USING_TELEPHONY_NAMESPACE - -/******************************************************************************* - * TelephonyChild - ******************************************************************************/ - -TelephonyChild::TelephonyChild(TelephonyIPCService* aService) - : mService(aService) -{ - MOZ_ASSERT(aService); -} - -TelephonyChild::~TelephonyChild() -{ -} - -void -TelephonyChild::ActorDestroy(ActorDestroyReason aWhy) -{ - if (mService) { - mService->NoteActorDestroyed(); - mService = nullptr; - } -} - -PTelephonyRequestChild* -TelephonyChild::AllocPTelephonyRequestChild(const IPCTelephonyRequest& aRequest) -{ - MOZ_CRASH("Caller is supposed to manually construct a request!"); -} - -bool -TelephonyChild::DeallocPTelephonyRequestChild(PTelephonyRequestChild* aActor) -{ - delete aActor; - return true; -} - -bool -TelephonyChild::RecvNotifyCallStateChanged(nsTArray&& aAllInfo) -{ - uint32_t length = aAllInfo.Length(); - nsTArray> results; - for (uint32_t i = 0; i < length; ++i) { - // Use dont_AddRef here because this instance has already been AddRef-ed in - // TelephonyIPCSerializer.h - nsCOMPtr info = dont_AddRef(aAllInfo[i]); - results.AppendElement(info); - } - - MOZ_ASSERT(mService); - - mService->CallStateChanged(length, const_cast(aAllInfo.Elements())); - - return true; -} - -bool -TelephonyChild::RecvNotifyCdmaCallWaiting(const uint32_t& aClientId, - const IPCCdmaWaitingCallData& aData) -{ - MOZ_ASSERT(mService); - - mService->NotifyCdmaCallWaiting(aClientId, - aData.number(), - aData.numberPresentation(), - aData.name(), - aData.namePresentation()); - return true; -} - -bool -TelephonyChild::RecvNotifyConferenceError(const nsString& aName, - const nsString& aMessage) -{ - MOZ_ASSERT(mService); - - mService->NotifyConferenceError(aName, aMessage); - return true; -} - -bool -TelephonyChild::RecvNotifySupplementaryService(const uint32_t& aClientId, - const int32_t& aCallIndex, - const uint16_t& aNotification) -{ - MOZ_ASSERT(mService); - - mService->SupplementaryServiceNotification(aClientId, aCallIndex, - aNotification); - return true; -} - -/******************************************************************************* - * TelephonyRequestChild - ******************************************************************************/ - -TelephonyRequestChild::TelephonyRequestChild(nsITelephonyListener* aListener, - nsITelephonyCallback* aCallback) - : mListener(aListener), mCallback(aCallback) -{ -} - -void -TelephonyRequestChild::ActorDestroy(ActorDestroyReason aWhy) -{ - mListener = nullptr; - mCallback = nullptr; -} - -bool -TelephonyRequestChild::Recv__delete__(const IPCTelephonyResponse& aResponse) -{ - switch (aResponse.type()) { - case IPCTelephonyResponse::TEnumerateCallsResponse: - mListener->EnumerateCallStateComplete(); - break; - case IPCTelephonyResponse::TSuccessResponse: - return DoResponse(aResponse.get_SuccessResponse()); - case IPCTelephonyResponse::TErrorResponse: - return DoResponse(aResponse.get_ErrorResponse()); - case IPCTelephonyResponse::TDialResponseCallSuccess: - return DoResponse(aResponse.get_DialResponseCallSuccess()); - case IPCTelephonyResponse::TDialResponseMMISuccess: - return DoResponse(aResponse.get_DialResponseMMISuccess()); - case IPCTelephonyResponse::TDialResponseMMIError: - return DoResponse(aResponse.get_DialResponseMMIError()); - default: - MOZ_CRASH("Unknown type!"); - } - - return true; -} - -bool -TelephonyRequestChild::RecvNotifyEnumerateCallState(nsITelephonyCallInfo* const& aInfo) -{ - // Use dont_AddRef here because this instances has already been AddRef-ed in - // TelephonyIPCSerializer.h - nsCOMPtr info = dont_AddRef(aInfo); - - MOZ_ASSERT(mListener); - - mListener->EnumerateCallState(aInfo); - - return true; -} - -bool -TelephonyRequestChild::RecvNotifyDialMMI(const nsString& aServiceCode) -{ - MOZ_ASSERT(mCallback); - nsCOMPtr callback = do_QueryInterface(mCallback); - callback->NotifyDialMMI(aServiceCode); - return true; -} - -bool -TelephonyRequestChild::DoResponse(const SuccessResponse& aResponse) -{ - MOZ_ASSERT(mCallback); - mCallback->NotifySuccess(); - return true; -} - -bool -TelephonyRequestChild::DoResponse(const ErrorResponse& aResponse) -{ - MOZ_ASSERT(mCallback); - mCallback->NotifyError(aResponse.name()); - return true; -} - -bool -TelephonyRequestChild::DoResponse(const DialResponseCallSuccess& aResponse) -{ - MOZ_ASSERT(mCallback); - nsCOMPtr callback = do_QueryInterface(mCallback); - callback->NotifyDialCallSuccess(aResponse.clientId(), aResponse.callIndex(), - aResponse.number()); - return true; -} - -bool -TelephonyRequestChild::DoResponse(const DialResponseMMISuccess& aResponse) -{ - MOZ_ASSERT(mCallback); - nsCOMPtr callback = do_QueryInterface(mCallback); - - nsAutoString statusMessage(aResponse.statusMessage()); - AdditionalInformation info(aResponse.additionalInformation()); - - switch (info.type()) { - case AdditionalInformation::Tvoid_t: - callback->NotifyDialMMISuccess(statusMessage); - break; - case AdditionalInformation::Tuint16_t: - callback->NotifyDialMMISuccessWithInteger(statusMessage, info.get_uint16_t()); - break; - case AdditionalInformation::TArrayOfnsString: { - uint32_t count = info.get_ArrayOfnsString().Length(); - const nsTArray& additionalInformation = info.get_ArrayOfnsString(); - - auto additionalInfoPtrs = MakeUnique(count); - for (size_t i = 0; i < count; ++i) { - additionalInfoPtrs[i] = additionalInformation[i].get(); - } - - callback->NotifyDialMMISuccessWithStrings(statusMessage, count, - additionalInfoPtrs.get()); - break; - } - case AdditionalInformation::TArrayOfnsMobileCallForwardingOptions: { - uint32_t count = info.get_ArrayOfnsMobileCallForwardingOptions().Length(); - - nsTArray> results; - for (uint32_t i = 0; i < count; i++) { - // Use dont_AddRef here because these instances are already AddRef-ed in - // MobileConnectionIPCSerializer.h - nsCOMPtr item = dont_AddRef( - info.get_ArrayOfnsMobileCallForwardingOptions()[i]); - results.AppendElement(item); - } - - callback->NotifyDialMMISuccessWithCallForwardingOptions(statusMessage, count, - const_cast(info.get_ArrayOfnsMobileCallForwardingOptions().Elements())); - break; - } - default: - MOZ_CRASH("Received invalid type!"); - break; - } - - return true; -} - -bool -TelephonyRequestChild::DoResponse(const DialResponseMMIError& aResponse) -{ - MOZ_ASSERT(mCallback); - nsCOMPtr callback = do_QueryInterface(mCallback); - - nsAutoString name(aResponse.name()); - AdditionalInformation info(aResponse.additionalInformation()); - - switch (info.type()) { - case AdditionalInformation::Tvoid_t: - callback->NotifyDialMMIError(name); - break; - case AdditionalInformation::Tuint16_t: - callback->NotifyDialMMIErrorWithInfo(name, info.get_uint16_t()); - break; - default: - MOZ_CRASH("Received invalid type!"); - break; - } - - return true; -} diff --git a/dom/telephony/ipc/TelephonyChild.h b/dom/telephony/ipc/TelephonyChild.h deleted file mode 100644 index e26bb310de6d..000000000000 --- a/dom/telephony/ipc/TelephonyChild.h +++ /dev/null @@ -1,100 +0,0 @@ -/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ -/* vim: set ts=8 sts=2 et sw=2 tw=80: */ -/* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this file, - * You can obtain one at http://mozilla.org/MPL/2.0/. */ - -#ifndef mozilla_dom_telephony_TelephonyChild_h -#define mozilla_dom_telephony_TelephonyChild_h - -#include "mozilla/dom/telephony/PTelephonyChild.h" -#include "mozilla/dom/telephony/PTelephonyRequestChild.h" -#include "mozilla/dom/telephony/TelephonyCommon.h" -#include "nsITelephonyCallInfo.h" -#include "nsITelephonyService.h" - -BEGIN_TELEPHONY_NAMESPACE - -class TelephonyIPCService; - -class TelephonyChild : public PTelephonyChild -{ -public: - explicit TelephonyChild(TelephonyIPCService* aService); - -protected: - virtual ~TelephonyChild(); - - virtual void - ActorDestroy(ActorDestroyReason aWhy) override; - - virtual PTelephonyRequestChild* - AllocPTelephonyRequestChild(const IPCTelephonyRequest& aRequest) override; - - virtual bool - DeallocPTelephonyRequestChild(PTelephonyRequestChild* aActor) override; - - virtual bool - RecvNotifyCallStateChanged(nsTArray&& aAllInfo) override; - - virtual bool - RecvNotifyCdmaCallWaiting(const uint32_t& aClientId, - const IPCCdmaWaitingCallData& aData) override; - - virtual bool - RecvNotifyConferenceError(const nsString& aName, - const nsString& aMessage) override; - - virtual bool - RecvNotifySupplementaryService(const uint32_t& aClientId, - const int32_t& aCallIndex, - const uint16_t& aNotification) override; - -private: - RefPtr mService; -}; - -class TelephonyRequestChild : public PTelephonyRequestChild -{ -public: - TelephonyRequestChild(nsITelephonyListener* aListener, - nsITelephonyCallback* aCallback); - -protected: - virtual ~TelephonyRequestChild() {} - - virtual void - ActorDestroy(ActorDestroyReason aWhy) override; - - virtual bool - Recv__delete__(const IPCTelephonyResponse& aResponse) override; - - virtual bool - RecvNotifyEnumerateCallState(nsITelephonyCallInfo* const& aInfo) override; - - virtual bool - RecvNotifyDialMMI(const nsString& aServiceCode) override; - -private: - bool - DoResponse(const SuccessResponse& aResponse); - - bool - DoResponse(const ErrorResponse& aResponse); - - bool - DoResponse(const DialResponseCallSuccess& aResponse); - - bool - DoResponse(const DialResponseMMISuccess& aResponse); - - bool - DoResponse(const DialResponseMMIError& aResponse); - - nsCOMPtr mListener; - nsCOMPtr mCallback; -}; - -END_TELEPHONY_NAMESPACE - -#endif // mozilla_dom_telephony_TelephonyChild_h diff --git a/dom/telephony/ipc/TelephonyIPCSerializer.h b/dom/telephony/ipc/TelephonyIPCSerializer.h deleted file mode 100644 index 7461adabc4a2..000000000000 --- a/dom/telephony/ipc/TelephonyIPCSerializer.h +++ /dev/null @@ -1,160 +0,0 @@ -/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ -/* vim: set ts=8 sts=2 et sw=2 tw=80: */ -/* This Source Code Form is subject to the terms of the Mozilla Public -* License, v. 2.0. If a copy of the MPL was not distributed with this -* file, You can obtain one at http://mozilla.org/MPL/2.0/. */ - -#ifndef mozilla_dom_telephony_TelephonyIPCSerializer_h -#define mozilla_dom_telephony_TelephonyIPCSerializer_h - -#include "ipc/IPCMessageUtils.h" -#include "mozilla/dom/telephony/TelephonyCallInfo.h" -#include "nsITelephonyCallInfo.h" - -using mozilla::AutoJSContext; -using mozilla::dom::telephony::TelephonyCallInfo; - -typedef nsITelephonyCallInfo* nsTelephonyCallInfo; - -namespace IPC { - -/** - * nsITelephonyCallInfo Serialize/De-serialize. - */ -template <> -struct ParamTraits -{ - typedef nsITelephonyCallInfo* paramType; - - static void Write(Message* aMsg, const paramType& aParam) { - bool isNull = !aParam; - WriteParam(aMsg, isNull); - // If it is a null object, then we are done. - if (isNull) { - return; - } - - uint32_t clientId; - uint32_t callIndex; - uint16_t callState; - nsString disconnectedReason; - - nsString number; - uint16_t numberPresentation; - nsString name; - uint16_t namePresentation; - - bool isOutgoing; - bool isEmergency; - bool isConference; - bool isSwitchable; - bool isMergeable; - - aParam->GetClientId(&clientId); - aParam->GetCallIndex(&callIndex); - aParam->GetCallState(&callState); - aParam->GetDisconnectedReason(disconnectedReason); - - aParam->GetNumber(number); - aParam->GetNumberPresentation(&numberPresentation); - aParam->GetName(name); - aParam->GetNamePresentation(&namePresentation); - - aParam->GetIsOutgoing(&isOutgoing); - aParam->GetIsEmergency(&isEmergency); - aParam->GetIsConference(&isConference); - aParam->GetIsSwitchable(&isSwitchable); - aParam->GetIsMergeable(&isMergeable); - - WriteParam(aMsg, clientId); - WriteParam(aMsg, callIndex); - WriteParam(aMsg, callState); - WriteParam(aMsg, disconnectedReason); - - WriteParam(aMsg, number); - WriteParam(aMsg, numberPresentation); - WriteParam(aMsg, name); - WriteParam(aMsg, namePresentation); - - WriteParam(aMsg, isOutgoing); - WriteParam(aMsg, isEmergency); - WriteParam(aMsg, isConference); - WriteParam(aMsg, isSwitchable); - WriteParam(aMsg, isMergeable); - } - - static bool Read(const Message* aMsg, PickleIterator* aIter, paramType* aResult) - { - // Check if is the null pointer we have transfered. - bool isNull; - if (!ReadParam(aMsg, aIter, &isNull)) { - return false; - } - - if (isNull) { - *aResult = nullptr; - return true; - } - - uint32_t clientId; - uint32_t callIndex; - uint16_t callState; - nsString disconnectedReason; - - nsString number; - uint16_t numberPresentation; - nsString name; - uint16_t namePresentation; - - bool isOutgoing; - bool isEmergency; - bool isConference; - bool isSwitchable; - bool isMergeable; - - // It's not important to us where it fails, but rather if it fails - if (!(ReadParam(aMsg, aIter, &clientId) && - ReadParam(aMsg, aIter, &callIndex) && - ReadParam(aMsg, aIter, &callState) && - ReadParam(aMsg, aIter, &disconnectedReason) && - - ReadParam(aMsg, aIter, &number) && - ReadParam(aMsg, aIter, &numberPresentation) && - ReadParam(aMsg, aIter, &name) && - ReadParam(aMsg, aIter, &namePresentation) && - - ReadParam(aMsg, aIter, &isOutgoing) && - ReadParam(aMsg, aIter, &isEmergency) && - ReadParam(aMsg, aIter, &isConference) && - ReadParam(aMsg, aIter, &isSwitchable) && - ReadParam(aMsg, aIter, &isMergeable))) { - return false; - } - - nsCOMPtr info = - new TelephonyCallInfo(clientId, - callIndex, - callState, - disconnectedReason, - - number, - numberPresentation, - name, - namePresentation, - - isOutgoing, - isEmergency, - isConference, - isSwitchable, - isMergeable); - - info.forget(aResult); - - return true; - } -}; - - -} // namespace IPC - -#endif // mozilla_dom_telephony_TelephonyIPCSerializer_h diff --git a/dom/telephony/ipc/TelephonyIPCService.cpp b/dom/telephony/ipc/TelephonyIPCService.cpp deleted file mode 100644 index 862fa6b7a474..000000000000 --- a/dom/telephony/ipc/TelephonyIPCService.cpp +++ /dev/null @@ -1,425 +0,0 @@ -/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ -/* vim: set ts=8 sts=2 et sw=2 tw=80: */ -/* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this file, - * You can obtain one at http://mozilla.org/MPL/2.0/. */ - -#include "TelephonyIPCService.h" - -#include "mozilla/dom/ContentChild.h" -#include "mozilla/dom/telephony/TelephonyChild.h" -#include "mozilla/Preferences.h" - -#include "nsITelephonyCallInfo.h" - -USING_TELEPHONY_NAMESPACE -using namespace mozilla::dom; - -namespace { - -const char* kPrefRilNumRadioInterfaces = "ril.numRadioInterfaces"; -#define kPrefDefaultServiceId "dom.telephony.defaultServiceId" -const char* kObservedPrefs[] = { - kPrefDefaultServiceId, - nullptr -}; - -uint32_t -getDefaultServiceId() -{ - int32_t id = mozilla::Preferences::GetInt(kPrefDefaultServiceId, 0); - int32_t numRil = mozilla::Preferences::GetInt(kPrefRilNumRadioInterfaces, 1); - - if (id >= numRil || id < 0) { - id = 0; - } - - return id; -} - -} // namespace - -NS_IMPL_ISUPPORTS(TelephonyIPCService, - nsITelephonyService, - nsITelephonyListener, - nsIObserver) - -TelephonyIPCService::TelephonyIPCService() -{ - // Deallocated in ContentChild::DeallocPTelephonyChild(). - mPTelephonyChild = new TelephonyChild(this); - ContentChild::GetSingleton()->SendPTelephonyConstructor(mPTelephonyChild); - - Preferences::AddStrongObservers(this, kObservedPrefs); - mDefaultServiceId = getDefaultServiceId(); -} - -TelephonyIPCService::~TelephonyIPCService() -{ - if (mPTelephonyChild) { - mPTelephonyChild->Send__delete__(mPTelephonyChild); - mPTelephonyChild = nullptr; - } -} - -void -TelephonyIPCService::NoteActorDestroyed() -{ - MOZ_ASSERT(mPTelephonyChild); - - mPTelephonyChild = nullptr; -} - -/* - * Implementation of nsIObserver. - */ - -NS_IMETHODIMP -TelephonyIPCService::Observe(nsISupports* aSubject, - const char* aTopic, - const char16_t* aData) -{ - if (!strcmp(aTopic, NS_PREFBRANCH_PREFCHANGE_TOPIC_ID)) { - nsDependentString data(aData); - if (data.EqualsLiteral(kPrefDefaultServiceId)) { - mDefaultServiceId = getDefaultServiceId(); - } - return NS_OK; - } - - MOZ_ASSERT(false, "TelephonyIPCService got unexpected topic!"); - return NS_ERROR_UNEXPECTED; -} - -/* - * Implementation of nsITelephonyService. - */ - -NS_IMETHODIMP -TelephonyIPCService::GetDefaultServiceId(uint32_t* aServiceId) -{ - *aServiceId = mDefaultServiceId; - return NS_OK; -} - -NS_IMETHODIMP -TelephonyIPCService::RegisterListener(nsITelephonyListener *aListener) -{ - MOZ_ASSERT(!mListeners.Contains(aListener)); - - if (!mPTelephonyChild) { - NS_WARNING("TelephonyService used after shutdown has begun!"); - return NS_ERROR_FAILURE; - } - - // nsTArray doesn't fail. - mListeners.AppendElement(aListener); - - if (mListeners.Length() == 1) { - mPTelephonyChild->SendRegisterListener(); - } - return NS_OK; -} - -NS_IMETHODIMP -TelephonyIPCService::UnregisterListener(nsITelephonyListener *aListener) -{ - MOZ_ASSERT(mListeners.Contains(aListener)); - - if (!mPTelephonyChild) { - NS_WARNING("TelephonyService used after shutdown has begun!"); - return NS_ERROR_FAILURE; - } - - // We always have the element here, so it can't fail. - mListeners.RemoveElement(aListener); - - if (!mListeners.Length()) { - mPTelephonyChild->SendUnregisterListener(); - } - return NS_OK; -} - -nsresult -TelephonyIPCService::SendRequest(nsITelephonyListener *aListener, - nsITelephonyCallback *aCallback, - const IPCTelephonyRequest& aRequest) -{ - if (!mPTelephonyChild) { - NS_WARNING("TelephonyService used after shutdown has begun!"); - return NS_ERROR_FAILURE; - } - - // Life time of newly allocated TelephonyRequestChild instance is managed by - // IPDL itself. - TelephonyRequestChild* actor = new TelephonyRequestChild(aListener, aCallback); - mPTelephonyChild->SendPTelephonyRequestConstructor(actor, aRequest); - return NS_OK; -} - -NS_IMETHODIMP -TelephonyIPCService::EnumerateCalls(nsITelephonyListener *aListener) -{ - return SendRequest(aListener, nullptr, EnumerateCallsRequest()); -} - -NS_IMETHODIMP -TelephonyIPCService::Dial(uint32_t aClientId, const nsAString& aNumber, - bool aIsEmergency, - nsITelephonyDialCallback *aCallback) -{ - nsCOMPtr callback = do_QueryInterface(aCallback); - return SendRequest(nullptr, callback, - DialRequest(aClientId, nsString(aNumber), aIsEmergency)); -} - -NS_IMETHODIMP -TelephonyIPCService::AnswerCall(uint32_t aClientId, uint32_t aCallIndex, - nsITelephonyCallback *aCallback) -{ - if (!mPTelephonyChild) { - NS_WARNING("TelephonyService used after shutdown has begun!"); - return NS_ERROR_FAILURE; - } - - return SendRequest(nullptr, aCallback, AnswerCallRequest(aClientId, aCallIndex)); -} - -NS_IMETHODIMP -TelephonyIPCService::HangUpCall(uint32_t aClientId, uint32_t aCallIndex, - nsITelephonyCallback *aCallback) -{ - if (!mPTelephonyChild) { - NS_WARNING("TelephonyService used after shutdown has begun!"); - return NS_ERROR_FAILURE; - } - - return SendRequest(nullptr, aCallback, HangUpCallRequest(aClientId, aCallIndex)); -} - -NS_IMETHODIMP -TelephonyIPCService::RejectCall(uint32_t aClientId, uint32_t aCallIndex, - nsITelephonyCallback *aCallback) -{ - if (!mPTelephonyChild) { - NS_WARNING("TelephonyService used after shutdown has begun!"); - return NS_ERROR_FAILURE; - } - - return SendRequest(nullptr, aCallback, RejectCallRequest(aClientId, aCallIndex)); -} - -NS_IMETHODIMP -TelephonyIPCService::HoldCall(uint32_t aClientId, uint32_t aCallIndex, - nsITelephonyCallback *aCallback) -{ - if (!mPTelephonyChild) { - NS_WARNING("TelephonyService used after shutdown has begun!"); - return NS_ERROR_FAILURE; - } - - return SendRequest(nullptr, aCallback, HoldCallRequest(aClientId, aCallIndex)); -} - -NS_IMETHODIMP -TelephonyIPCService::ResumeCall(uint32_t aClientId, uint32_t aCallIndex, - nsITelephonyCallback *aCallback) -{ - if (!mPTelephonyChild) { - NS_WARNING("TelephonyService used after shutdown has begun!"); - return NS_ERROR_FAILURE; - } - - return SendRequest(nullptr, aCallback, ResumeCallRequest(aClientId, aCallIndex)); -} - -NS_IMETHODIMP -TelephonyIPCService::ConferenceCall(uint32_t aClientId, - nsITelephonyCallback *aCallback) -{ - return SendRequest(nullptr, aCallback, ConferenceCallRequest(aClientId)); -} - -NS_IMETHODIMP -TelephonyIPCService::SeparateCall(uint32_t aClientId, uint32_t aCallIndex, - nsITelephonyCallback *aCallback) -{ - return SendRequest(nullptr, aCallback, SeparateCallRequest(aClientId, - aCallIndex)); -} - -NS_IMETHODIMP -TelephonyIPCService::HangUpConference(uint32_t aClientId, - nsITelephonyCallback *aCallback) -{ - return SendRequest(nullptr, aCallback, HangUpConferenceRequest(aClientId)); -} - -NS_IMETHODIMP -TelephonyIPCService::HoldConference(uint32_t aClientId, - nsITelephonyCallback *aCallback) -{ - return SendRequest(nullptr, aCallback, HoldConferenceRequest(aClientId)); -} - -NS_IMETHODIMP -TelephonyIPCService::ResumeConference(uint32_t aClientId, - nsITelephonyCallback *aCallback) -{ - return SendRequest(nullptr, aCallback, ResumeConferenceRequest(aClientId)); -} - -NS_IMETHODIMP -TelephonyIPCService::SendTones(uint32_t aClientId, const nsAString& aDtmfChars, - uint32_t aPauseDuration, uint32_t aToneDuration, - nsITelephonyCallback *aCallback) -{ - return SendRequest(nullptr, aCallback, SendTonesRequest(aClientId, - nsString(aDtmfChars), aPauseDuration, aToneDuration)); -} - -NS_IMETHODIMP -TelephonyIPCService::StartTone(uint32_t aClientId, const nsAString& aDtmfChar) -{ - if (!mPTelephonyChild) { - NS_WARNING("TelephonyService used after shutdown has begun!"); - return NS_ERROR_FAILURE; - } - - mPTelephonyChild->SendStartTone(aClientId, nsString(aDtmfChar)); - return NS_OK; -} - -NS_IMETHODIMP -TelephonyIPCService::StopTone(uint32_t aClientId) -{ - if (!mPTelephonyChild) { - NS_WARNING("TelephonyService used after shutdown has begun!"); - return NS_ERROR_FAILURE; - } - - mPTelephonyChild->SendStopTone(aClientId); - return NS_OK; -} - -NS_IMETHODIMP -TelephonyIPCService::SendUSSD(uint32_t aClientId, const nsAString& aUssd, - nsITelephonyCallback *aCallback) -{ - return SendRequest(nullptr, aCallback, - SendUSSDRequest(aClientId, nsString(aUssd))); -} - -NS_IMETHODIMP -TelephonyIPCService::CancelUSSD(uint32_t aClientId, - nsITelephonyCallback *aCallback) -{ - return SendRequest(nullptr, aCallback, CancelUSSDRequest(aClientId)); -} - -NS_IMETHODIMP -TelephonyIPCService::GetMicrophoneMuted(bool* aMuted) -{ - if (!mPTelephonyChild) { - NS_WARNING("TelephonyService used after shutdown has begun!"); - return NS_ERROR_FAILURE; - } - - mPTelephonyChild->SendGetMicrophoneMuted(aMuted); - return NS_OK; -} - -NS_IMETHODIMP -TelephonyIPCService::SetMicrophoneMuted(bool aMuted) -{ - if (!mPTelephonyChild) { - NS_WARNING("TelephonyService used after shutdown has begun!"); - return NS_ERROR_FAILURE; - } - - mPTelephonyChild->SendSetMicrophoneMuted(aMuted); - return NS_OK; -} - -NS_IMETHODIMP -TelephonyIPCService::GetSpeakerEnabled(bool* aEnabled) -{ - if (!mPTelephonyChild) { - NS_WARNING("TelephonyService used after shutdown has begun!"); - return NS_ERROR_FAILURE; - } - - mPTelephonyChild->SendGetSpeakerEnabled(aEnabled); - return NS_OK; -} - -NS_IMETHODIMP -TelephonyIPCService::SetSpeakerEnabled(bool aEnabled) -{ - if (!mPTelephonyChild) { - NS_WARNING("TelephonyService used after shutdown has begun!"); - return NS_ERROR_FAILURE; - } - - mPTelephonyChild->SendSetSpeakerEnabled(aEnabled); - return NS_OK; -} - -// nsITelephonyListener - -NS_IMETHODIMP -TelephonyIPCService::CallStateChanged(uint32_t aLength, nsITelephonyCallInfo** aAllInfo) -{ - for (uint32_t i = 0; i < mListeners.Length(); i++) { - mListeners[i]->CallStateChanged(aLength, aAllInfo); - } - return NS_OK; -} - -NS_IMETHODIMP -TelephonyIPCService::EnumerateCallStateComplete() -{ - MOZ_CRASH("Not a EnumerateCalls request!"); -} - -NS_IMETHODIMP -TelephonyIPCService::EnumerateCallState(nsITelephonyCallInfo* aInfo) -{ - MOZ_CRASH("Not a EnumerateCalls request!"); -} - -NS_IMETHODIMP -TelephonyIPCService::NotifyCdmaCallWaiting(uint32_t aClientId, - const nsAString& aNumber, - uint16_t aNumberPresentation, - const nsAString& aName, - uint16_t aNamePresentation) -{ - for (uint32_t i = 0; i < mListeners.Length(); i++) { - mListeners[i]->NotifyCdmaCallWaiting(aClientId, aNumber, aNumberPresentation, - aName, aNamePresentation); - } - return NS_OK; -} - -NS_IMETHODIMP -TelephonyIPCService::NotifyConferenceError(const nsAString& aName, - const nsAString& aMessage) -{ - for (uint32_t i = 0; i < mListeners.Length(); i++) { - mListeners[i]->NotifyConferenceError(aName, aMessage); - } - return NS_OK; -} - -NS_IMETHODIMP -TelephonyIPCService::SupplementaryServiceNotification(uint32_t aClientId, - int32_t aCallIndex, - uint16_t aNotification) -{ - for (uint32_t i = 0; i < mListeners.Length(); i++) { - mListeners[i]->SupplementaryServiceNotification(aClientId, aCallIndex, - aNotification); - } - return NS_OK; -} diff --git a/dom/telephony/ipc/TelephonyIPCService.h b/dom/telephony/ipc/TelephonyIPCService.h deleted file mode 100644 index 6f409b0c1b19..000000000000 --- a/dom/telephony/ipc/TelephonyIPCService.h +++ /dev/null @@ -1,48 +0,0 @@ -/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ -/* vim: set ts=8 sts=2 et sw=2 tw=80: */ -/* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ - -#ifndef mozilla_dom_telephony_TelephonyIPCService_h -#define mozilla_dom_telephony_TelephonyIPCService_h - -#include "mozilla/dom/telephony/TelephonyCommon.h" -#include "mozilla/Attributes.h" -#include "nsIObserver.h" -#include "nsITelephonyService.h" - -BEGIN_TELEPHONY_NAMESPACE - -class IPCTelephonyRequest; -class PTelephonyChild; - -class TelephonyIPCService final : public nsITelephonyService - , public nsITelephonyListener - , public nsIObserver -{ -public: - NS_DECL_ISUPPORTS - NS_DECL_NSITELEPHONYSERVICE - NS_DECL_NSITELEPHONYLISTENER - NS_DECL_NSIOBSERVER - - TelephonyIPCService(); - - void NoteActorDestroyed(); - -private: - ~TelephonyIPCService(); - - nsTArray > mListeners; - PTelephonyChild* mPTelephonyChild; - uint32_t mDefaultServiceId; - - nsresult SendRequest(nsITelephonyListener *aListener, - nsITelephonyCallback *aCallback, - const IPCTelephonyRequest& aRequest); -}; - -END_TELEPHONY_NAMESPACE - -#endif // mozilla_dom_telephony_TelephonyIPCService_h diff --git a/dom/telephony/ipc/TelephonyParent.cpp b/dom/telephony/ipc/TelephonyParent.cpp deleted file mode 100644 index 3ed8b0cdf4c1..000000000000 --- a/dom/telephony/ipc/TelephonyParent.cpp +++ /dev/null @@ -1,523 +0,0 @@ -/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ -/* vim: set ts=8 sts=2 et sw=2 tw=80: */ -/* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this file, - * You can obtain one at http://mozilla.org/MPL/2.0/. */ - -#include "mozilla/dom/telephony/TelephonyParent.h" -#include "nsServiceManagerUtils.h" - -USING_TELEPHONY_NAMESPACE - -/******************************************************************************* - * TelephonyParent - ******************************************************************************/ - -NS_IMPL_ISUPPORTS(TelephonyParent, nsITelephonyListener) - -TelephonyParent::TelephonyParent() - : mActorDestroyed(false) - , mRegistered(false) -{ -} - -void -TelephonyParent::ActorDestroy(ActorDestroyReason why) -{ - // The child process could die before this asynchronous notification, in which - // case ActorDestroy() was called and mActorDestroyed is set to true. Return - // an error here to avoid sending a message to the dead process. - mActorDestroyed = true; - - // Try to unregister listener if we're still registered. - RecvUnregisterListener(); -} - -bool -TelephonyParent::RecvPTelephonyRequestConstructor(PTelephonyRequestParent* aActor, - const IPCTelephonyRequest& aRequest) -{ - TelephonyRequestParent* actor = static_cast(aActor); - nsCOMPtr service = do_GetService(TELEPHONY_SERVICE_CONTRACTID); - - if (!service) { - return NS_SUCCEEDED(actor->GetCallback()->NotifyError(NS_LITERAL_STRING("InvalidStateError"))); - } - - switch (aRequest.type()) { - case IPCTelephonyRequest::TEnumerateCallsRequest: { - nsresult rv = service->EnumerateCalls(actor); - if (NS_FAILED(rv)) { - return NS_SUCCEEDED(EnumerateCallStateComplete()); - } else { - return true; - } - } - - case IPCTelephonyRequest::TDialRequest: { - const DialRequest& request = aRequest.get_DialRequest(); - service->Dial(request.clientId(), request.number(), - request.isEmergency(), actor->GetDialCallback()); - return true; - } - - case IPCTelephonyRequest::TSendUSSDRequest: { - const SendUSSDRequest& request = aRequest.get_SendUSSDRequest(); - service->SendUSSD(request.clientId(), request.ussd(), actor->GetCallback()); - return true; - } - - case IPCTelephonyRequest::TCancelUSSDRequest: { - const CancelUSSDRequest& request = aRequest.get_CancelUSSDRequest(); - service->CancelUSSD(request.clientId(), actor->GetCallback()); - return true; - } - - case IPCTelephonyRequest::TConferenceCallRequest: { - const ConferenceCallRequest& request = aRequest.get_ConferenceCallRequest(); - service->ConferenceCall(request.clientId(), actor->GetCallback()); - return true; - } - - case IPCTelephonyRequest::TSeparateCallRequest: { - const SeparateCallRequest& request = aRequest.get_SeparateCallRequest(); - service->SeparateCall(request.clientId(), request.callIndex(), actor->GetCallback()); - return true; - } - - case IPCTelephonyRequest::THangUpConferenceRequest: { - const HangUpConferenceRequest& request = aRequest.get_HangUpConferenceRequest(); - service->HangUpConference(request.clientId(), actor->GetCallback()); - return true; - } - - case IPCTelephonyRequest::THoldConferenceRequest: { - const HoldConferenceRequest& request = aRequest.get_HoldConferenceRequest(); - service->HoldConference(request.clientId(), actor->GetCallback()); - return true; - } - - case IPCTelephonyRequest::TResumeConferenceRequest: { - const ResumeConferenceRequest& request = aRequest.get_ResumeConferenceRequest(); - service->ResumeConference(request.clientId(), actor->GetCallback()); - return true; - } - - case IPCTelephonyRequest::TAnswerCallRequest: { - const AnswerCallRequest& request = aRequest.get_AnswerCallRequest(); - service->AnswerCall(request.clientId(), request.callIndex(), actor->GetCallback()); - return true; - } - - case IPCTelephonyRequest::THangUpCallRequest: { - const HangUpCallRequest& request = aRequest.get_HangUpCallRequest(); - service->HangUpCall(request.clientId(), request.callIndex(), actor->GetCallback()); - return true; - } - - case IPCTelephonyRequest::TRejectCallRequest: { - const RejectCallRequest& request = aRequest.get_RejectCallRequest(); - service->RejectCall(request.clientId(), request.callIndex(), actor->GetCallback()); - return true; - } - - case IPCTelephonyRequest::THoldCallRequest: { - const HoldCallRequest& request = aRequest.get_HoldCallRequest(); - service->HoldCall(request.clientId(), request.callIndex(), actor->GetCallback()); - return true; - } - - case IPCTelephonyRequest::TResumeCallRequest: { - const ResumeCallRequest& request = aRequest.get_ResumeCallRequest(); - service->ResumeCall(request.clientId(), request.callIndex(), actor->GetCallback()); - return true; - } - - case IPCTelephonyRequest::TSendTonesRequest: { - const SendTonesRequest& request = aRequest.get_SendTonesRequest(); - service->SendTones(request.clientId(), - request.dtmfChars(), - request.pauseDuration(), - request.toneDuration(), - actor->GetCallback()); - return true; - } - - default: - MOZ_CRASH("Unknown type!"); - } - - return false; -} - -PTelephonyRequestParent* -TelephonyParent::AllocPTelephonyRequestParent(const IPCTelephonyRequest& aRequest) -{ - TelephonyRequestParent* actor = new TelephonyRequestParent(); - // Add an extra ref for IPDL. Will be released in - // TelephonyParent::DeallocPTelephonyRequestParent(). - NS_ADDREF(actor); - - return actor; -} - -bool -TelephonyParent::DeallocPTelephonyRequestParent(PTelephonyRequestParent* aActor) -{ - // TelephonyRequestParent is refcounted, must not be freed manually. - static_cast(aActor)->Release(); - return true; -} - -bool -TelephonyParent::Recv__delete__() -{ - return true; // Unregister listener in TelephonyParent::ActorDestroy(). -} - -bool -TelephonyParent::RecvRegisterListener() -{ - NS_ENSURE_TRUE(!mRegistered, true); - - nsCOMPtr service = - do_GetService(TELEPHONY_SERVICE_CONTRACTID); - NS_ENSURE_TRUE(service, true); - - mRegistered = NS_SUCCEEDED(service->RegisterListener(this)); - return true; -} - -bool -TelephonyParent::RecvUnregisterListener() -{ - NS_ENSURE_TRUE(mRegistered, true); - - nsCOMPtr service = - do_GetService(TELEPHONY_SERVICE_CONTRACTID); - NS_ENSURE_TRUE(service, true); - - mRegistered = !NS_SUCCEEDED(service->UnregisterListener(this)); - return true; -} - -bool -TelephonyParent::RecvStartTone(const uint32_t& aClientId, const nsString& aTone) -{ - nsCOMPtr service = - do_GetService(TELEPHONY_SERVICE_CONTRACTID); - NS_ENSURE_TRUE(service, true); - - service->StartTone(aClientId, aTone); - return true; -} - -bool -TelephonyParent::RecvStopTone(const uint32_t& aClientId) -{ - nsCOMPtr service = - do_GetService(TELEPHONY_SERVICE_CONTRACTID); - NS_ENSURE_TRUE(service, true); - - service->StopTone(aClientId); - return true; -} - -bool -TelephonyParent::RecvGetMicrophoneMuted(bool* aMuted) -{ - *aMuted = false; - - nsCOMPtr service = - do_GetService(TELEPHONY_SERVICE_CONTRACTID); - NS_ENSURE_TRUE(service, true); - - service->GetMicrophoneMuted(aMuted); - return true; -} - -bool -TelephonyParent::RecvSetMicrophoneMuted(const bool& aMuted) -{ - nsCOMPtr service = - do_GetService(TELEPHONY_SERVICE_CONTRACTID); - NS_ENSURE_TRUE(service, true); - - service->SetMicrophoneMuted(aMuted); - return true; -} - -bool -TelephonyParent::RecvGetSpeakerEnabled(bool* aEnabled) -{ - *aEnabled = false; - - nsCOMPtr service = - do_GetService(TELEPHONY_SERVICE_CONTRACTID); - NS_ENSURE_TRUE(service, true); - - service->GetSpeakerEnabled(aEnabled); - return true; -} - -bool -TelephonyParent::RecvSetSpeakerEnabled(const bool& aEnabled) -{ - nsCOMPtr service = - do_GetService(TELEPHONY_SERVICE_CONTRACTID); - NS_ENSURE_TRUE(service, true); - - service->SetSpeakerEnabled(aEnabled); - return true; -} - -// nsITelephonyListener - -NS_IMETHODIMP -TelephonyParent::CallStateChanged(uint32_t aLength, nsITelephonyCallInfo** aAllInfo) -{ - NS_ENSURE_TRUE(!mActorDestroyed, NS_ERROR_FAILURE); - - nsTArray allInfo; - for (uint32_t i = 0; i < aLength; i++) { - allInfo.AppendElement(aAllInfo[i]); - } - - return SendNotifyCallStateChanged(allInfo) ? NS_OK : NS_ERROR_FAILURE; -} - -NS_IMETHODIMP -TelephonyParent::EnumerateCallStateComplete() -{ - MOZ_CRASH("Not a EnumerateCalls request!"); -} - -NS_IMETHODIMP -TelephonyParent::EnumerateCallState(nsITelephonyCallInfo* aInfo) -{ - MOZ_CRASH("Not a EnumerateCalls request!"); -} - -NS_IMETHODIMP -TelephonyParent::NotifyCdmaCallWaiting(uint32_t aClientId, - const nsAString& aNumber, - uint16_t aNumberPresentation, - const nsAString& aName, - uint16_t aNamePresentation) -{ - NS_ENSURE_TRUE(!mActorDestroyed, NS_ERROR_FAILURE); - - IPCCdmaWaitingCallData data(nsString(aNumber), aNumberPresentation, - nsString(aName), aNamePresentation); - return SendNotifyCdmaCallWaiting(aClientId, data) ? NS_OK : NS_ERROR_FAILURE; -} - -NS_IMETHODIMP -TelephonyParent::NotifyConferenceError(const nsAString& aName, - const nsAString& aMessage) -{ - NS_ENSURE_TRUE(!mActorDestroyed, NS_ERROR_FAILURE); - - return SendNotifyConferenceError(nsString(aName), nsString(aMessage)) ? NS_OK - : NS_ERROR_FAILURE; -} - -NS_IMETHODIMP -TelephonyParent::SupplementaryServiceNotification(uint32_t aClientId, - int32_t aCallIndex, - uint16_t aNotification) -{ - NS_ENSURE_TRUE(!mActorDestroyed, NS_ERROR_FAILURE); - - return SendNotifySupplementaryService(aClientId, aCallIndex, aNotification) - ? NS_OK : NS_ERROR_FAILURE; -} - -/******************************************************************************* - * TelephonyRequestParent - ******************************************************************************/ - -NS_IMPL_ISUPPORTS(TelephonyRequestParent, - nsITelephonyListener) - -TelephonyRequestParent::TelephonyRequestParent() - : mActorDestroyed(false), - mCallback(new Callback(*this)), - mDialCallback(new DialCallback(*this)) -{ -} - -void -TelephonyRequestParent::ActorDestroy(ActorDestroyReason why) -{ - // The child process could die before this asynchronous notification, in which - // case ActorDestroy() was called and mActorDestroyed is set to true. Return - // an error here to avoid sending a message to the dead process. - mActorDestroyed = true; -} - -nsresult -TelephonyRequestParent::SendResponse(const IPCTelephonyResponse& aResponse) -{ - NS_ENSURE_TRUE(!mActorDestroyed, NS_ERROR_FAILURE); - - return Send__delete__(this, aResponse) ? NS_OK : NS_ERROR_FAILURE; -} - -// nsITelephonyListener - -NS_IMETHODIMP -TelephonyRequestParent::CallStateChanged(uint32_t aLength, nsITelephonyCallInfo** aAllInfo) -{ - MOZ_CRASH("Not a TelephonyParent!"); -} - -NS_IMETHODIMP -TelephonyRequestParent::EnumerateCallStateComplete() -{ - NS_ENSURE_TRUE(!mActorDestroyed, NS_ERROR_FAILURE); - - return Send__delete__(this, EnumerateCallsResponse()) ? NS_OK : NS_ERROR_FAILURE; -} - -NS_IMETHODIMP -TelephonyRequestParent::EnumerateCallState(nsITelephonyCallInfo* aInfo) -{ - NS_ENSURE_TRUE(!mActorDestroyed, NS_ERROR_FAILURE); - - return SendNotifyEnumerateCallState(aInfo) ? NS_OK : NS_ERROR_FAILURE; -} - -NS_IMETHODIMP -TelephonyRequestParent::NotifyCdmaCallWaiting(uint32_t aClientId, - const nsAString& aNumber, - uint16_t aNumberPresentation, - const nsAString& aName, - uint16_t aNamePresentation) -{ - MOZ_CRASH("Not a TelephonyParent!"); -} - -NS_IMETHODIMP -TelephonyRequestParent::NotifyConferenceError(const nsAString& aName, - const nsAString& aMessage) -{ - MOZ_CRASH("Not a TelephonyParent!"); -} - -NS_IMETHODIMP -TelephonyRequestParent::SupplementaryServiceNotification(uint32_t aClientId, - int32_t aCallIndex, - uint16_t aNotification) -{ - MOZ_CRASH("Not a TelephonyParent!"); -} - -/******************************************************************************* - * TelephonyRequestParent::Callback - ******************************************************************************/ - -NS_IMPL_ISUPPORTS(TelephonyRequestParent::Callback, - nsITelephonyCallback) - -nsresult TelephonyRequestParent::Callback::SendResponse(const IPCTelephonyResponse& aResponse) -{ - return mParent.SendResponse(aResponse); -} - -NS_IMETHODIMP -TelephonyRequestParent::Callback::NotifySuccess() -{ - return SendResponse(SuccessResponse()); -} - -NS_IMETHODIMP -TelephonyRequestParent::Callback::NotifyError(const nsAString& aError) -{ - return SendResponse(ErrorResponse(nsAutoString(aError))); -} - -/******************************************************************************* - * TelephonyRequestParent::DialCallback - ******************************************************************************/ - -NS_IMPL_ISUPPORTS_INHERITED(TelephonyRequestParent::DialCallback, - TelephonyRequestParent::Callback, - nsITelephonyDialCallback) - -NS_IMETHODIMP -TelephonyRequestParent::DialCallback::NotifyDialMMI(const nsAString& aServiceCode) -{ - NS_ENSURE_TRUE(!mParent.mActorDestroyed, NS_ERROR_FAILURE); - - return mParent.SendNotifyDialMMI(nsAutoString(aServiceCode)) ? NS_OK : NS_ERROR_FAILURE; -} - -NS_IMETHODIMP -TelephonyRequestParent::DialCallback::NotifyDialCallSuccess(uint32_t aClientId, - uint32_t aCallIndex, - const nsAString& aNumber) -{ - return SendResponse(DialResponseCallSuccess(aClientId, aCallIndex, - nsAutoString(aNumber))); -} - -NS_IMETHODIMP -TelephonyRequestParent::DialCallback::NotifyDialMMISuccess(const nsAString& aStatusMessage) -{ - return SendResponse(DialResponseMMISuccess(nsAutoString(aStatusMessage), - AdditionalInformation(mozilla::void_t()))); -} - -NS_IMETHODIMP -TelephonyRequestParent::DialCallback::NotifyDialMMISuccessWithInteger(const nsAString& aStatusMessage, - uint16_t aAdditionalInformation) -{ - return SendResponse(DialResponseMMISuccess(nsAutoString(aStatusMessage), - AdditionalInformation(aAdditionalInformation))); -} - -NS_IMETHODIMP -TelephonyRequestParent::DialCallback::NotifyDialMMISuccessWithStrings(const nsAString& aStatusMessage, - uint32_t aCount, - const char16_t** aAdditionalInformation) -{ - nsTArray additionalInformation; - nsString* infos = additionalInformation.AppendElements(aCount); - for (uint32_t i = 0; i < aCount; i++) { - infos[i].Rebind(aAdditionalInformation[i], - nsCharTraits::length(aAdditionalInformation[i])); - } - - return SendResponse(DialResponseMMISuccess(nsAutoString(aStatusMessage), - AdditionalInformation(additionalInformation))); -} - -NS_IMETHODIMP -TelephonyRequestParent::DialCallback::NotifyDialMMISuccessWithCallForwardingOptions(const nsAString& aStatusMessage, - uint32_t aCount, - nsIMobileCallForwardingOptions** aAdditionalInformation) -{ - nsTArray additionalInformation; - for (uint32_t i = 0; i < aCount; i++) { - additionalInformation.AppendElement(aAdditionalInformation[i]); - } - - return SendResponse(DialResponseMMISuccess(nsAutoString(aStatusMessage), - AdditionalInformation(additionalInformation))); -} - -NS_IMETHODIMP -TelephonyRequestParent::DialCallback::NotifyDialMMIError(const nsAString& aError) -{ - return SendResponse(DialResponseMMIError(nsAutoString(aError), - AdditionalInformation(mozilla::void_t()))); -} - -NS_IMETHODIMP -TelephonyRequestParent::DialCallback::NotifyDialMMIErrorWithInfo(const nsAString& aError, - uint16_t aInfo) -{ - return SendResponse(DialResponseMMIError(nsAutoString(aError), - AdditionalInformation(aInfo))); -} diff --git a/dom/telephony/ipc/TelephonyParent.h b/dom/telephony/ipc/TelephonyParent.h deleted file mode 100644 index d56ea9c5112c..000000000000 --- a/dom/telephony/ipc/TelephonyParent.h +++ /dev/null @@ -1,140 +0,0 @@ -/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ -/* vim: set ts=8 sts=2 et sw=2 tw=80: */ -/* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this file, - * You can obtain one at http://mozilla.org/MPL/2.0/. */ - -#ifndef mozilla_dom_telephony_TelephonyParent_h -#define mozilla_dom_telephony_TelephonyParent_h - -#include "mozilla/dom/telephony/TelephonyCommon.h" -#include "mozilla/dom/telephony/PTelephonyParent.h" -#include "mozilla/dom/telephony/PTelephonyRequestParent.h" -#include "nsITelephonyService.h" - -BEGIN_TELEPHONY_NAMESPACE - -class TelephonyParent : public PTelephonyParent - , public nsITelephonyListener -{ -public: - NS_DECL_ISUPPORTS - NS_DECL_NSITELEPHONYLISTENER - - TelephonyParent(); - -protected: - virtual ~TelephonyParent() {} - - virtual void - ActorDestroy(ActorDestroyReason aWhy) override; - - virtual bool - RecvPTelephonyRequestConstructor(PTelephonyRequestParent* aActor, const IPCTelephonyRequest& aRequest) override; - - virtual PTelephonyRequestParent* - AllocPTelephonyRequestParent(const IPCTelephonyRequest& aRequest) override; - - virtual bool - DeallocPTelephonyRequestParent(PTelephonyRequestParent* aActor) override; - - virtual bool - Recv__delete__() override; - - virtual bool - RecvRegisterListener() override; - - virtual bool - RecvUnregisterListener() override; - - virtual bool - RecvStartTone(const uint32_t& aClientId, const nsString& aTone) override; - - virtual bool - RecvStopTone(const uint32_t& aClientId) override; - - virtual bool - RecvGetMicrophoneMuted(bool* aMuted) override; - - virtual bool - RecvSetMicrophoneMuted(const bool& aMuted) override; - - virtual bool - RecvGetSpeakerEnabled(bool* aEnabled) override; - - virtual bool - RecvSetSpeakerEnabled(const bool& aEnabled) override; - -private: - bool mActorDestroyed; - bool mRegistered; -}; - -class TelephonyRequestParent : public PTelephonyRequestParent - , public nsITelephonyListener -{ - friend class TelephonyParent; - -public: - NS_DECL_ISUPPORTS - NS_DECL_NSITELEPHONYLISTENER - - class Callback : public nsITelephonyCallback { - friend class TelephonyRequestParent; - - public: - NS_DECL_ISUPPORTS - NS_DECL_NSITELEPHONYCALLBACK - - protected: - explicit Callback(TelephonyRequestParent& aParent): mParent(aParent) {} - virtual ~Callback() {} - - private: - nsresult SendResponse(const IPCTelephonyResponse& aResponse); - TelephonyRequestParent& mParent; - }; - - class DialCallback final : public Callback - , public nsITelephonyDialCallback { - friend class TelephonyRequestParent; - - public: - NS_DECL_ISUPPORTS_INHERITED - NS_DECL_NSITELEPHONYDIALCALLBACK - NS_FORWARD_NSITELEPHONYCALLBACK(Callback::) - - private: - explicit DialCallback(TelephonyRequestParent& aParent): Callback(aParent) {} - ~DialCallback() {} - }; - -protected: - TelephonyRequestParent(); - virtual ~TelephonyRequestParent() {} - - virtual void - ActorDestroy(ActorDestroyReason aWhy) override; - - nsresult - SendResponse(const IPCTelephonyResponse& aResponse); - - Callback* - GetCallback() { - return mCallback; - } - - DialCallback* - GetDialCallback() { - return mDialCallback; - } - -private: - bool mActorDestroyed; - RefPtr mCallback; - RefPtr mDialCallback; -}; - -END_TELEPHONY_NAMESPACE - -#endif /* mozilla_dom_telephony_TelephonyParent_h */ diff --git a/dom/telephony/ipc/TelephonyTypes.ipdlh b/dom/telephony/ipc/TelephonyTypes.ipdlh deleted file mode 100644 index 34194f427cfc..000000000000 --- a/dom/telephony/ipc/TelephonyTypes.ipdlh +++ /dev/null @@ -1,31 +0,0 @@ -/* -*- Mode: c++; c-basic-offset: 2; indent-tabs-mode: nil; tab-width: 40 -*- */ -/* vim: set ts=2 et sw=2 tw=80: */ -/* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this file, - * You can obtain one at http://mozilla.org/MPL/2.0/. */ - -using struct mozilla::void_t from "ipc/IPCMessageUtils.h"; -using nsMobileCallForwardingOptions from "mozilla/dom/mobileconnection/MobileConnectionIPCSerializer.h"; - -namespace mozilla { -namespace dom { -namespace telephony { - -struct IPCCdmaWaitingCallData -{ - nsString number; - uint16_t numberPresentation; - nsString name; - uint16_t namePresentation; -}; - -union AdditionalInformation { - void_t; - uint16_t; - nsString[]; - nsMobileCallForwardingOptions[]; -}; - -} /* namespace telephony */ -} /* namespace dom */ -} /* namespace mozilla */ diff --git a/dom/telephony/moz.build b/dom/telephony/moz.build deleted file mode 100644 index bc1803cbf97f..000000000000 --- a/dom/telephony/moz.build +++ /dev/null @@ -1,81 +0,0 @@ -# -*- Mode: python; indent-tabs-mode: nil; tab-width: 40 -*- -# vim: set filetype=python: -# This Source Code Form is subject to the terms of the Mozilla Public -# License, v. 2.0. If a copy of the MPL was not distributed with this -# file, You can obtain one at http://mozilla.org/MPL/2.0/. - -XPIDL_SOURCES += [ - 'nsITelephonyCallInfo.idl', - 'nsITelephonyService.idl', -] - -XPIDL_MODULE = 'dom_telephony' - -EXPORTS.mozilla.dom += [ - 'CallsList.h', - 'MMICall.h', - 'Telephony.h', - 'TelephonyCall.h', - 'TelephonyCallGroup.h', - 'TelephonyCallId.h', - 'USSDSession.h' -] - -EXPORTS.mozilla.dom.telephony += [ - 'ipc/TelephonyChild.h', - 'ipc/TelephonyIPCSerializer.h', - 'ipc/TelephonyParent.h', - 'TelephonyCallback.h', - 'TelephonyCallInfo.h', - 'TelephonyCommon.h', - 'TelephonyDialCallback.h', -] - -UNIFIED_SOURCES += [ - 'CallsList.cpp', - 'ipc/TelephonyChild.cpp', - 'ipc/TelephonyIPCService.cpp', - 'ipc/TelephonyParent.cpp', - 'MMICall.cpp', - 'Telephony.cpp', - 'TelephonyCall.cpp', - 'TelephonyCallback.cpp', - 'TelephonyCallGroup.cpp', - 'TelephonyCallId.cpp', - 'TelephonyCallInfo.cpp', - 'TelephonyDialCallback.cpp', - 'USSDSession.cpp', -] - -IPDL_SOURCES += [ - 'ipc/PTelephony.ipdl', - 'ipc/PTelephonyRequest.ipdl', - 'ipc/TelephonyTypes.ipdlh' -] - -if CONFIG['MOZ_WIDGET_TOOLKIT'] == 'gonk' and CONFIG['MOZ_B2G_RIL']: - XPCSHELL_TESTS_MANIFESTS += ['test/xpcshell/xpcshell.ini'] - XPIDL_SOURCES += [ - 'nsIGonkTelephonyService.idl', - 'nsITelephonyAudioService.idl', - 'nsITelephonyMessenger.idl', - ] - EXTRA_COMPONENTS += [ - 'gonk/TelephonyAudioService.js', - 'gonk/TelephonyAudioService.manifest', - 'gonk/USSDReceivedWrapper.js', - 'gonk/USSDReceivedWrapper.manifest', - ] - if not CONFIG['DISABLE_MOZ_RIL_GEOLOC']: - EXTRA_COMPONENTS += [ - 'gonk/TelephonyService.js', - 'gonk/TelephonyService.manifest', - ] - EXTRA_JS_MODULES += [ - 'gonk/DialNumberUtils.jsm', - 'gonk/TelephonyUtils.jsm', - ] - -include('/ipc/chromium/chromium-config.mozbuild') - -FINAL_LIBRARY = 'xul' diff --git a/dom/telephony/nsIGonkTelephonyService.idl b/dom/telephony/nsIGonkTelephonyService.idl deleted file mode 100644 index 764fd99a35e0..000000000000 --- a/dom/telephony/nsIGonkTelephonyService.idl +++ /dev/null @@ -1,27 +0,0 @@ -/* -*- Mode: idl; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ -/* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this file, - * You can obtain one at http://mozilla.org/MPL/2.0/. */ - -#include "nsITelephonyService.idl" - -%{C++ -#define GONK_TELEPHONY_SERVICE_CONTRACTID \ - "@mozilla.org/telephony/gonktelephonyservice;1" -%} - -[scriptable, uuid(8653d76b-6805-41d2-8ea5-3b14fb4e682d)] -interface nsIGonkTelephonyService : nsITelephonyService -{ - void notifyCallRing(); - - void notifyCurrentCalls(in unsigned long clientId, in jsval calls); - - void notifyCdmaCallWaiting(in unsigned long clientId, in jsval waitingCall); - - void notifySupplementaryService(in unsigned long clientId, in AString number, - in AString notification); - - void notifyUssdReceived(in unsigned long clientId, in DOMString message, - in boolean sessionEnded); -}; diff --git a/dom/telephony/nsITelephonyAudioService.idl b/dom/telephony/nsITelephonyAudioService.idl deleted file mode 100644 index 61880c065827..000000000000 --- a/dom/telephony/nsITelephonyAudioService.idl +++ /dev/null @@ -1,31 +0,0 @@ -/* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this file, - * You can obtain one at http://mozilla.org/MPL/2.0/. */ - -#include "nsISupports.idl" - -[scriptable, uuid(a452c565-fbac-4056-a8f4-feee9b33aa6e)] -interface nsITelephonyAudioService : nsISupports -{ - const long PHONE_STATE_NORMAL = 0; - const long PHONE_STATE_RINGTONE = 1; - const long PHONE_STATE_IN_CALL = 2; - - /** - * Microphone muted? - */ - attribute boolean microphoneMuted; - - /** - * Speaker enabled? - */ - attribute boolean speakerEnabled; - - /** - * Set the phone's audio mode. - * - * @param state - * One of the nsITelephonyAudioService::PHONE_STATE_* values. - */ - void setPhoneState(in long state); -}; diff --git a/dom/telephony/nsITelephonyCallInfo.idl b/dom/telephony/nsITelephonyCallInfo.idl deleted file mode 100644 index e179b7006049..000000000000 --- a/dom/telephony/nsITelephonyCallInfo.idl +++ /dev/null @@ -1,81 +0,0 @@ -/* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this file, - * You can obtain one at http://mozilla.org/MPL/2.0/. */ - -#include "nsISupports.idl" - -[scriptable, uuid(e5e1be26-a3d4-49b3-8d9f-c1df5192b364)] -interface nsITelephonyCallInfo : nsISupports -{ - /** - * Indicate the RIL client, 0 ~ (number of client - 1). - */ - readonly attribute unsigned long clientId; - - /** - * Call identifier assigned by the RIL. - */ - readonly attribute unsigned long callIndex; - - /** - * One of the nsITelephonyService::CALL_STATE_* values. - */ - readonly attribute unsigned short callState; - - /** - * The disconnectedReason of a call is defualt to an empty string when the - * call is "not disconnected", but once the call becomes "disconnected" the - * disconnectedReason should be a non-empty string no matter the call is - * disconnected for a noraml reason or an error. - */ - readonly attribute DOMString disconnectedReason; - - /** - * Number of the other party. - */ - readonly attribute DOMString number; - - /** - * Presentation of the call number. - * One of the nsITelephonyService::CALL_PRESENTATION_* values. - */ - readonly attribute unsigned short numberPresentation; - - /** - * Name of the other party. - */ - readonly attribute DOMString name; - - /** - * Presentation of the call name. - * One of the nsITelephonyService::CALL_PRESENTATION_* values. - */ - readonly attribute unsigned short namePresentation; - - /** - * Indicates whether this call is outgoing or incoming. - */ - readonly attribute boolean isOutgoing; - - /** - * Indicates whether this call is an emergency call. - */ - readonly attribute boolean isEmergency; - - /** - * Indicates whether this call is a conference call. - */ - readonly attribute boolean isConference; - - /** - * Indicates whether this call can be switched between states of - * nsITelephonyService::CALL_STATE_CONNECTED and - * nsITelephonyService::CALL_STATE_HELD. - */ - readonly attribute boolean isSwitchable; - - /** - * Indicates whether this call be be added into a conference. - */ - readonly attribute boolean isMergeable; -}; diff --git a/dom/telephony/nsITelephonyMessenger.idl b/dom/telephony/nsITelephonyMessenger.idl deleted file mode 100644 index a7b269af4402..000000000000 --- a/dom/telephony/nsITelephonyMessenger.idl +++ /dev/null @@ -1,54 +0,0 @@ -/* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ - -#include "nsISupports.idl" - -[scriptable, uuid(84045b7e-84fb-11e4-a94c-5ba58d0d5932)] -interface nsITelephonyMessenger : nsISupports -{ - /** - * To broadcast 'telephony-new-call' system message - */ - void notifyNewCall(); - - /** - * To broadcast 'telephony-call-ended' system message - * - * @param aServiceId - * The ID of Service where this info is notified from. - * @param aNumber - * The phone number of the call to be ended. - * @param aCdmaWaitingNumber - * The CDMA call waiting number to be ended if available. - * @param aEmergency - * true if it's a emergency number. - * @param aDuration - * The duration of this call. - * @param aOutgoing - * true if it's an outgoing call. - * @param aHangUpLocal - * true if this call was hung up by the user. - */ - void notifyCallEnded(in unsigned long aServiceId, - in DOMString aNumber, - in DOMString aCdmaWaitingNumber, - in boolean aEmergency, - in unsigned long aDuration, - in boolean aOutgoing, - in boolean aHangUpLocal); - - /** - * 'ussd-received' system message - * - * @param aServiceId - * The ID of Service where this info is notified from. - * @param aMessage - * USSD Message to be displayed. - * @param aSessionEnded - * True if USSD session is ended. - */ - void notifyUssdReceived(in unsigned long aServiceId, - in DOMString aMessage, - in boolean aSessionEnded); -}; \ No newline at end of file diff --git a/dom/telephony/nsITelephonyService.idl b/dom/telephony/nsITelephonyService.idl deleted file mode 100644 index f4fe40a13562..000000000000 --- a/dom/telephony/nsITelephonyService.idl +++ /dev/null @@ -1,255 +0,0 @@ -/* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this file, - * You can obtain one at http://mozilla.org/MPL/2.0/. */ - -#include "nsISupports.idl" - -interface nsIMobileCallForwardingOptions; -interface nsITelephonyCallInfo; - -[scriptable, uuid(baa9f5f3-5cab-40e0-81e9-ae0abd917907)] -interface nsITelephonyListener : nsISupports -{ - /** - * Called when enumeration asked by nsITelephonyService::enumerateCalls - * is completed. - */ - void enumerateCallStateComplete(); - - /** - * Called when nsITelephonyService is asked to enumerate the current - * telephony call state (nsITelephonyService::enumerateCalls). This is - * called once per call that is currently managed by the RIL. - */ - void enumerateCallState(in nsITelephonyCallInfo info); - - /** - * Notified when a telephony call changes state. - */ - void callStateChanged(in unsigned long length, - [array, size_is(length)] in nsITelephonyCallInfo allInfo); - - /** - * Notify when RIL receives supplementary service notification. - * - * @param clientId - Indicate the RIL client, 0 ~ (number of client - 1). - * @param callIndex - * Call identifier assigned by the RIL. -1 if not specified - * @param notification - * One of the nsITelephonyService::NOTIFICATION_* values. - */ - void supplementaryServiceNotification(in unsigned long clientId, - in long callIndex, - in unsigned short notification); - - /** - * Called when a waiting call comes in CDMA networks. - * - * @param clientId - Indicate the RIL client, 0 ~ (number of client - 1). - * @param number - * Number of the other party. - * @param numberPresentation - * Presentation of the call number. - * One of the nsITelephonyProvider::CALL_PRESENTATION_* values. - * @param name - * Name of the other party. - * @param namePresentation - * Presentation of the call name. - * One of the nsITelephonyProvider::CALL_PRESENTATION_* values. - */ - void notifyCdmaCallWaiting(in unsigned long clientId, - in AString number, - in unsigned short numberPresentation, - in AString name, - in unsigned short namePresentation); - - /** - * Called when RIL error occurs to creating or separating a conference call. - * - * @param name - * Error name. Possible values are addError and removeError. - * @param message - * Detailed error message from RIL. - */ - void notifyConferenceError(in AString name, - in AString message); -}; - -/** - * A callback interface for handling asynchronous response. - */ -[scriptable, uuid(cffc3f9d-2c88-4a14-8ebc-f216caf0cc1d)] -interface nsITelephonyCallback : nsISupports -{ - void notifySuccess(); - void notifyError(in AString error); -}; - -/** - * A callback interface for handling asynchronous response for telephony.dial. - */ -[scriptable, uuid(e16c6e6f-93c6-4e1e-99bf-592b98f67e15)] -interface nsITelephonyDialCallback : nsITelephonyCallback -{ - /** - * Called when a dial request is treated as an MMI code and it is about to - * process the request. - * - * @param serviceCode - * MMI service code key string that defined in MMI_KS_SC_* - */ - void notifyDialMMI(in AString serviceCode); - - /** - * Called when a dial request is treated as a call setup and the result - * succeeds. - * - * @param clientId - Indicate the RIL client, 0 ~ (number of client - 1). - * @param callIndex - * Call index from RIL. - * @param number - * Dialed out phone number (ex: Temporary CLIR prefix will be removed) - */ - void notifyDialCallSuccess(in unsigned long cliendId, - in unsigned long callIndex, - in AString number); - - /** - * Called when a MMI code request succeeds. - * The function should only be called after notifyDialMMI. - */ - void notifyDialMMISuccess(in AString statusMessage); - void notifyDialMMISuccessWithInteger(in AString statusMessage, - in unsigned short aAdditionalInformation); - void notifyDialMMISuccessWithStrings(in AString statusMessage, - in unsigned long aLength, - [array, size_is(aLength)] in wstring aAdditionalInformation); - void notifyDialMMISuccessWithCallForwardingOptions(in AString statusMessage, - in unsigned long aLength, - [array, size_is(aLength)] in nsIMobileCallForwardingOptions aAdditionalInformation); - - /** - * Called when a MMI code request fails. - * The function should only be called after notifyDialMMI. - */ - void notifyDialMMIError(in AString error); - void notifyDialMMIErrorWithInfo(in AString error, in unsigned short info); -}; - -%{C++ -#define TELEPHONY_SERVICE_CID \ - { 0x9cf8aa52, 0x7c1c, 0x4cde, { 0x97, 0x4e, 0xed, 0x2a, 0xa0, 0xe7, 0x35, 0xfa } } -#define TELEPHONY_SERVICE_CONTRACTID \ - "@mozilla.org/telephony/telephonyservice;1" -%} - -/** - * XPCOM component (in the content process) that provides the telephony - * information. - */ -[scriptable, uuid(75e4b5e3-6710-4156-bdaa-ba1081f390f4)] -interface nsITelephonyService : nsISupports -{ - const unsigned short CALL_STATE_UNKNOWN = 0; - const unsigned short CALL_STATE_DIALING = 1; - const unsigned short CALL_STATE_ALERTING = 2; - const unsigned short CALL_STATE_CONNECTED = 3; - const unsigned short CALL_STATE_HELD = 4; - const unsigned short CALL_STATE_DISCONNECTED = 5; - const unsigned short CALL_STATE_INCOMING = 6; - - const unsigned short NOTIFICATION_REMOTE_HELD = 0; - const unsigned short NOTIFICATION_REMOTE_RESUMED = 1; - - const unsigned short CALL_PRESENTATION_ALLOWED = 0; - const unsigned short CALL_PRESENTATION_RESTRICTED = 1; - const unsigned short CALL_PRESENTATION_UNKNOWN = 2; - const unsigned short CALL_PRESENTATION_PAYPHONE = 3; - - readonly attribute unsigned long defaultServiceId; - - /** - * Called when a content process registers receiving unsolicited messages from - * RadioInterfaceLayer in the chrome process. Only a content process that has - * the 'telephony' permission is allowed to register. - */ - void registerListener(in nsITelephonyListener listener); - void unregisterListener(in nsITelephonyListener listener); - - /** - * Will continue calling listener.enumerateCallState until the listener - * returns false. - */ - void enumerateCalls(in nsITelephonyListener listener); - - /** - * Functionality for making and managing phone calls. - */ - void dial(in unsigned long clientId, in DOMString number, - in boolean isEmergency, in nsITelephonyDialCallback callback); - - void sendTones(in unsigned long clientId, in DOMString dtmfChars, - in unsigned long pauseDuration, in unsigned long toneDuration, - in nsITelephonyCallback callback); - - void startTone(in unsigned long clientId, in DOMString dtmfChar); - void stopTone(in unsigned long clientId); - - void answerCall(in unsigned long clientId, - in unsigned long callIndex, - in nsITelephonyCallback callback); - void rejectCall(in unsigned long clientId, - in unsigned long callIndex, - in nsITelephonyCallback callback); - void hangUpCall(in unsigned long clientId, - in unsigned long callIndex, - in nsITelephonyCallback callback); - void holdCall(in unsigned long clientId, - in unsigned long callIndex, - in nsITelephonyCallback callback); - void resumeCall(in unsigned long clientId, - in unsigned long callIndex, - in nsITelephonyCallback callback); - - void conferenceCall(in unsigned long clientId, - in nsITelephonyCallback callback); - void separateCall(in unsigned long clientId, in unsigned long callIndex, - in nsITelephonyCallback callback); - void hangUpConference(in unsigned long clientId, - in nsITelephonyCallback callback); - void holdConference(in unsigned long clientId, - in nsITelephonyCallback callback); - void resumeConference(in unsigned long clientId, - in nsITelephonyCallback callback); - - /** - * Send an USSD on existing session. It results in error if the session is - * not existed. - * - * If successful, callback.notifySuccess() will be called. - * Otherwise, callback.notifyError() will be called. - */ - void sendUSSD(in unsigned long clientId, in DOMString ussd, - in nsITelephonyCallback callback); - - /** - * Cancel an existing USSD session. - * - * If successful, callback.notifySuccess() will be called. - * Otherwise, callback.notifyError() will be called. - */ - void cancelUSSD(in unsigned long cliendId, in nsITelephonyCallback callback); - - attribute bool microphoneMuted; - attribute bool speakerEnabled; -}; - -%{C++ -template struct already_AddRefed; - -already_AddRefed -NS_CreateTelephonyService(); -%} diff --git a/dom/telephony/test/marionette/head.js b/dom/telephony/test/marionette/head.js deleted file mode 100644 index eb5729a4a5e9..000000000000 --- a/dom/telephony/test/marionette/head.js +++ /dev/null @@ -1,1677 +0,0 @@ -/* Any copyright is dedicated to the Public Domain. - * http://creativecommons.org/publicdomain/zero/1.0/ */ - -// Emulate Promise.jsm semantics. -Promise.defer = function() { return new Deferred(); }; -function Deferred() { - this.promise = new Promise(function(resolve, reject) { - this.resolve = resolve; - this.reject = reject; - }.bind(this)); - Object.freeze(this); -} - -var telephony; -var conference; - -const kPrefRilDebuggingEnabled = "ril.debugging.enabled"; - -/** - * Emulator helper. - */ -var emulator = (function() { - let pendingCmdCount = 0; - let originalRunEmulatorCmd = runEmulatorCmd; - - let pendingShellCount = 0; - let originalRunEmulatorShell = runEmulatorShell; - - // Overwritten it so people could not call this function directly. - runEmulatorCmd = function() { - throw "Use emulator.runCmdWithCallback(cmd, callback) instead of runEmulatorCmd"; - }; - - // Overwritten it so people could not call this function directly. - runEmulatorShell = function() { - throw "Use emulator.runShellCmd(cmd) instead of runEmulatorShell"; - }; - - /** - * @return Promise - */ - function runCmd(cmd) { - return new Promise(function(resolve, reject) { - pendingCmdCount++; - originalRunEmulatorCmd(cmd, function(result) { - pendingCmdCount--; - if (result[result.length - 1] === "OK") { - resolve(result); - } else { - is(result[result.length - 1], "OK", "emulator command result."); - reject(); - } - }); - }); - } - - /** - * @return Promise - */ - function runCmdWithCallback(cmd, callback) { - return runCmd(cmd).then(result => { - if (callback && typeof callback === "function") { - callback(result); - } - }); - } - - /** - * @return Promise - */ - function runShellCmd(aCommands) { - return new Promise(function(resolve, reject) { - ++pendingShellCount; - originalRunEmulatorShell(aCommands, function(aResult) { - --pendingShellCount; - resolve(aResult); - }); - }); - } - - /** - * @return Promise - */ - function waitFinish() { - return new Promise(function(resolve, reject) { - waitFor(function() { - resolve(); - }, function() { - return pendingCmdCount === 0 && pendingShellCount === 0; - }); - }); - } - - return { - runCmd: runCmd, - runCmdWithCallback: runCmdWithCallback, - runShellCmd: runShellCmd, - waitFinish: waitFinish - }; -}()); - -/** - * Modem Helper - * - * TODO: Should select which modem here to support multi-SIM - */ - -function modemHelperGenerator() { - function Modem(aClientID) { - this.clientID = aClientID; - } - Modem.prototype = { - clientID: 0, - - voiceTypeToTech: function(aVoiceType) { - switch(aVoiceType) { - case "gsm": - case "gprs": - case "edge": - return "gsm"; - - case "umts": - case "hsdpa": - case "hsupa": - case "hspa": - case "hspa+": - return "wcdma"; - - case "is95a": - case "is95b": - case "1xrtt": - return "cdma"; - - case "evdo0": - case "evdoa": - case "evdob": - return "evdo"; - - case "ehrpd": - return "ehrpd"; - - case "lte": - return "lte"; - - default: - return null; - } - }, - - isCDMA: function() { - var mobileConn = navigator.mozMobileConnections[this.clientID]; - var tech = mobileConn && this.voiceTypeToTech(mobileConn.voice.type); - return tech === "cdma" || tech === "evdo" || tech == "ehrpd"; - }, - - isGSM: function() { - var mobileConn = navigator.mozMobileConnections[this.clientID]; - var tech = mobileConn && this.voiceTypeToTech(mobileConn.voice.type); - return tech === "gsm" || tech === "wcdma" || tech === "lte"; - }, - - /** - * @return Promise: - */ - changeTech: function(aTech, aMask) { - let target = navigator.mozMobileConnections[this.clientID]; - - let mask = aMask || { - gsm: "gsm", - wcdma: "gsm/wcdma", - cdma: "cdma", - evdo: "evdo0", - ehrpd: "ehrpd", - lte: "lte" - }[aTech]; - - let waitForExpectedTech = () => { - return new Promise((aResolve, aReject) => { - let listener = aEvent => { - log("MobileConnection[" + this.clientID + "] " + - "received event 'voicechange'"); - if (aTech === this.voiceTypeToTech(target.voice.type)) { - target.removeEventListener("voicechange", listener); - aResolve(); - } - }; - - target.addEventListener("voicechange", listener); - }); - }; - - // TODO: Should select a modem here to support multi-SIM - let changeToExpectedTech = () => { - return Promise.resolve() - .then(() => emulator.runCmd("modem tech " + aTech + " " + mask)) - .then(() => emulator.runCmd("modem tech")) - .then(result => is(result[0], aTech + " " + mask, - "Check modem 'tech/preferred mask'")); - } - - return aTech === this.voiceTypeToTech(target.voice.type) - ? Promise.resolve() - : Promise.all([waitForExpectedTech(), changeToExpectedTech()]); - } - }; - - let modems = []; - for (let i = 0; i < navigator.mozMobileConnections.length; ++i) { - modems.push(new Modem(i)); - } - return modems; -} - -var Modems = modemHelperGenerator(); -var Modem = Modems[0]; - -/** - * Telephony related helper functions. - */ -(function() { - /** - * @return Promise - */ - function delay(ms) { - return new Promise(function(resolve, reject) { - let startTime = Date.now(); - waitFor(function() { - resolve(); - },function() { - let duration = Date.now() - startTime; - return (duration >= ms); - }); - }); - } - - /** - * Wait for one named system message. - * - * Resolve if that named message is received. Never reject. - * - * Fulfill params: the message passed. - * - * @param aEventName - * A string message name. - * @param aMatchFun [optional] - * A matching function returns true or false to filter the message. If no - * matching function passed the promise is resolved after receiving the - * first message. - * - * @return Promise - */ - function waitForSystemMessage(aMessageName, aMatchFun = null) { - // Current page may not register to receiving the message. We should - // register it first. - let systemMessenger = SpecialPowers.Cc["@mozilla.org/system-message-internal;1"] - .getService(SpecialPowers.Ci.nsISystemMessagesInternal); - - // TODO: Find a better way to get current pageURI and manifestURI. - systemMessenger.registerPage(aMessageName, - SpecialPowers.Services.io.newURI("app://system.gaiamobile.org/index.html", null, null), - SpecialPowers.Services.io.newURI("app://system.gaiamobile.org/manifest.webapp", null, null)); - - return new Promise(function(aResolve, aReject) { - window.navigator.mozSetMessageHandler(aMessageName, function(aMessage) { - if (!aMatchFun || aMatchFun(aMessage)) { - log("System message '" + aMessageName + "' got."); - window.navigator.mozSetMessageHandler(aMessageName, null); - aResolve(aMessage); - } - }); - }); - } - - /** - * Wait for one named event. - * - * @param aTarget - * A event target. - * @param aEventName - * A string event name. - * @param aPredicate [optional] - * A predicate function, resolve the promise if aPredicate(event) - * return true - * @return Promise - */ - function waitForEvent(aTarget, aEventName, aPredicate) { - return new Promise(function(resolve, reject) { - aTarget.addEventListener(aEventName, function onevent(aEvent) { - if (aPredicate === undefined || aPredicate(aEvent)) { - aTarget.removeEventListener(aEventName, onevent); - - let label = "X"; - if (aTarget instanceof TelephonyCall) { - label = "Call (" + aTarget.id.number + ")"; - } else if (aTarget instanceof TelephonyCallGroup) { - label = "Conference"; - } else if (aTarget instanceof Telephony) { - label = "Telephony"; - } - - log(label + " received event '" + aEventName + "'"); - resolve(aEvent); - } - }); - }); - } - - /** - * Wait for callschanged event with event.call == aExpectedCall - * - * @param aTarget - * A event target. - * @param aExpectedCall [optional] - * Expected call for event.call - * @return Promise - */ - function waitForCallsChangedEvent(aTarget, aExpectedCall) { - if (aExpectedCall === undefined) { - return waitForEvent(aTarget, "callschanged").then(event => event.call); - } else { - return waitForEvent(aTarget, "callschanged", - event => event.call == aExpectedCall) - .then(event => event.call); - } - } - - /** - * Wait for call state event, e.g., "connected", "disconnected", ... - * - * @param aTarget - * A event target. - * @param aState - * State name - * @return Promise - */ - function waitForNamedStateEvent(aTarget, aState) { - return waitForEvent(aTarget, aState) - .then(event => { - if (aTarget instanceof TelephonyCall) { - is(aTarget, event.call, "event.call"); - } - is(aTarget.state, aState, "check state"); - return aTarget; - }); - } - - /** - * Wait for groupchange event. - * - * @param aCall - * A TelephonyCall object. - * @param aGroup - * The new group - * @return Promise - */ - function waitForGroupChangeEvent(aCall, aGroup) { - return waitForEvent(aCall, "groupchange") - .then(() => { - is(aCall.group, aGroup, "call group"); - return aCall; - }); - } - - /** - * Wait for statechange event. - * - * @param aTarget - * A event target. - * @param aState - * The desired new state. Check it. - * @return Promise - */ - function waitForStateChangeEvent(aTarget, aState) { - return waitForEvent(aTarget, "statechange") - .then(() => { - is(aTarget.state, aState); - return aTarget; - }); - } - - /** - * @return Promise - */ - function waitForNoCall() { - return new Promise(function(resolve, reject) { - waitFor(function() { - resolve(); - }, function() { - return telephony.calls.length === 0; - }); - }); - } - - /** - * @return Promise - */ - function clearCalls() { - log("Clear existing calls."); - - // Hang up all calls. - let hangUpPromises = []; - - for (let call of telephony.calls) { - log(".. hangUp " + call.id.number); - hangUpPromises.push(hangUp(call)); - } - - for (let call of conference.calls) { - log(".. hangUp " + call.id.number); - hangUpPromises.push(hangUp(call)); - } - - return Promise.all(hangUpPromises) - .then(() => { - return emulator.runCmd("telephony clear").then(waitForNoCall); - }) - .then(waitForNoCall); - } - - /** - * Provide a string with format of the emulator call list result. - * - * @param prefix - * Possible values are "outbound" and "inbound". - * @param number - * Call number. - * @return A string with format of the emulator call list result. - */ - function callStrPool(prefix, number) { - let padding = " : "; - let numberInfo = prefix + number + padding.substr(number.length); - - let info = {}; - let states = ["ringing", "incoming", "waiting", "active", "held"]; - for (let state of states) { - info[state] = numberInfo + state; - } - - return info; - } - - /** - * Provide a corresponding string of an outgoing call. The string is with - * format of the emulator call list result. - * - * @param number - * Number of an outgoing call. - * @return A string with format of the emulator call list result. - */ - function outCallStrPool(number) { - return callStrPool("outbound to ", number); - } - - /** - * Provide a corresponding string of an incoming call. The string is with - * format of the emulator call list result. - * - * @param number - * Number of an incoming call. - * @return A string with format of the emulator call list result. - */ - function inCallStrPool(number) { - return callStrPool("inbound from ", number); - } - - /** - * Check utility functions. - */ - - function checkInitialState() { - log("Verify initial state."); - ok(telephony.calls, 'telephony.call'); - ok(conference.calls, 'conference.calls'); - checkState(null, [], "", []); - } - - - /**************************************************************************** - **** Check Functions **** - ****************************************************************************/ - - /** - * Convenient helper to compare two call lists (order is not important). - */ - function checkCalls(actualCalls, expectedCalls) { - if (actualCalls.length != expectedCalls.length) { - ok(false, "check calls.length"); - return; - } - - let expectedSet = new Set(expectedCalls); - for (let i = 0; i < actualCalls.length; ++i) { - ok(expectedSet.has(actualCalls[i]), "should contain the call"); - } - } - - /** - * Convenient helper to check the expected call number and name. - * - * @param number - * A string sent to modem. - * @param numberPresentation - * An unsigned short integer sent to modem. - * @param name - * A string sent to modem. - * @param namePresentation - * An unsigned short integer sent to modem. - * @param receivedNumber - * A string exposed by Telephony API. - * @param receivedName - * A string exposed by Telephony API. - */ - function checkCallId(number, numberPresentation, name, namePresentation, - receivedNumber, receivedName) { - let expectedNum = !numberPresentation ? number : ""; - is(receivedNumber, expectedNum, "check number per numberPresentation"); - - let expectedName; - if (numberPresentation) { - expectedName = ""; - } else if (!namePresentation) { - expectedName = name ? name : ""; - } else { - expectedName = ""; - } - is(receivedName, expectedName, "check name per number/namePresentation"); - } - - /** - * Convenient helper to check the call list existing in the emulator. - * - * @param expectedCallList - * An array of call info with the format of "callStrPool()[state]". - * @return Promise - */ - function checkEmulatorCallList(expectedCallList) { - return emulator.runCmd("telephony list").then(result => { - log("Call list is now: " + result); - // The last element of the result is "OK" - is(result.length - 1, - expectedCallList.length, - "Emulator call list length"); - - for (let i = 0; i < expectedCallList.length; ++i) { - is(result[i], expectedCallList[i], "emulator calllist"); - } - }); - } - - /** - * Super convenient helper to check calls and state of mozTelephony and - * mozTelephony.conferenceGroup. - * - * @param active - * A TelephonyCall object. Should be the expected active call. - * @param calls - * An array of TelephonyCall objects. Should be the expected list of - * mozTelephony.calls. - * @param conferenceState - * A string. Should be the expected conference state. - * @param conferenceCalls - * An array of TelephonyCall objects. Should be the expected list of - * mozTelephony.conferenceGroup.calls. - */ - function checkState(active, calls, conferenceState, conferenceCalls) { - is(telephony.active, active, "telephony.active"); - checkCalls(telephony.calls, calls); - is(conference.state, conferenceState, "conference.state"); - checkCalls(conference.calls, conferenceCalls); - } - - /** - * Super convenient helper to check calls and state of mozTelephony and - * mozTelephony.conferenceGroup as well as the calls existing in the emulator. - * - * @param active - * A TelephonyCall object. Should be the expected active call. - * @param calls - * An array of TelephonyCall objects. Should be the expected list of - * mozTelephony.calls. - * @param conferenceState - * A string. Should be the expected conference state. - * @param conferenceCalls - * An array of TelephonyCall objects. Should be the expected list of - * mozTelephony.conferenceGroup.calls. - * @param callList - * An array of call info with the format of "callStrPool()[state]". - * @return Promise - */ - function checkAll(active, calls, conferenceState, conferenceCalls, callList) { - checkState(active, calls, conferenceState, conferenceCalls); - return checkEmulatorCallList(callList); - } - - /** - * The factory function for creating an expected call. - * - * @param aReference - * The reference of the telephonyCall object. - * @param aNumber - * The call number. - * @param aConference - * Shows whether the call belongs to the conference. - * @param aDirection - * The direction of the call, "in" for inbound, and "out" for outbound. - * @param aState - * The expected state of the call. - * @param aEmulatorState - * The state logged in emulator now, may be different from aState. - * @param aDisconnectedReason - * The disconnected reason if the call becomed disconnected. - */ - function createExptectedCall(aReference, aNumber, aConference, aDirection, - aState, aEmulatorState, aDisconnectedReason) { - return { - reference: aReference, - number: aNumber, - conference: aConference, - direction: aDirection, - state: aState, - emulatorState: aEmulatorState, - disconnectedReason: aDisconnectedReason - }; - } - - /** - * Check telephony.active - * - * @param aExpectedCalls - * An array of expected calls. - * @param aExpectedCallsInConference - * An array of expected calls in the conference. - */ - function checkActive(aExpectedCalls, aExpectedCallsInConference) { - // Get the active call - let activeCalls = aExpectedCalls && aExpectedCalls.map(aExpectedCall => { - let isActive = aExpectedCall.state === "connected" || - aExpectedCall.state === "alerting" || - aExpectedCall.state === "dialing"; - return isActive ? aExpectedCall.reference : null; - }); - - // Since a CDMA active call and a CDMA waiting call refer to the same - // telephony call object, we remove duplicated elememts in activeCalls - activeCalls = new Set(activeCalls); - activeCalls.delete(null); - activeCalls = [...activeCalls]; - - ok(activeCalls.length < 2, "Too many active calls in telephony.calls"); - let activeCall = activeCalls.length ? activeCalls[0] : null; - - // Get the active conference - let callsInConference = aExpectedCallsInConference || []; - let activeConference = callsInConference.length && - callsInConference[0].state === "connected" - ? navigator.mozTelephony.conferenceGroup - : null; - - // Check telephony.active - ok(!(activeCall && activeConference), - "An active call cannot coexist with an active conference call."); - is(telephony.active, activeCall || activeConference, "check Active"); - } - - /** - * Check whether the data in telephony and emulator meets our expectation. - * - * NOTE: Conference call is not supported in this function yet, so related - * checks are skipped. - * - * Fulfill params: - * { - * reference, -- the reference of the call object instance. - * number, -- the call number. - * conference, -- shows whether it belongs to the conference. - * direction, -- "in" for inbound, and "out" for outbound. - * state, -- the call state. - * emulatorState, -- the call state logged in emulator now. - * disconnectedReason, -- the disconnected reason of a disconnected call. - * } - * - * @param aExpectedCalls - * An array of call records. - * @return Promise - */ - function equals(aExpectedCalls) { - // Classify calls - let callsInTelephony = []; - let CallsInConference = []; - - aExpectedCalls.forEach(function(aCall) { - if (aCall.state === "disconnected") { - is(aCall.disconnectedReason, - aCall.reference.disconnectedReason, - "Check disconnectedReason"); - return; - } - - if (aCall.conference) { - CallsInConference.push(aCall); - return; - } - - callsInTelephony.push(aCall); - }); - - // Check the active connection - checkActive(callsInTelephony, CallsInConference); - - // Check telephony.calls - let references = callsInTelephony.map(aCall => aCall.reference); - references = new Set(references); - is(telephony.calls.length, references.size, "Check telephony.calls.length"); - - callsInTelephony.forEach(aExpectedCall => { - let number = aExpectedCall.number; - let call = telephony.calls.find(aCall => { - return (aCall.id.number === number) || - (Modem.isCDMA() ? (aCall.secondId && aCall.secondId.number === number) : false); - }); - if (!call) { - ok(false, "telephony.calls lost the call(number: " + number + ")"); - return; - } - - is(call, aExpectedCall.reference, - "Check the object reference of number:" + number); - - is(call.state, aExpectedCall.state, - "Check call.state of number:" + number); - }); - - // Check conference.calls - // NOTE: This function doesn't support conference call now, so the length of - // |CallsInConference| should be 0, and the conference state shoul be "". - is(conference.state, "", "Conference call is not supported yet."); - is(CallsInConference.length, 0, "Conference call is not supported yet."); - - // Check the emulator call list - // NOTE: Conference is not supported yet, so |CallsInConference| is ignored. - let strings = callsInTelephony.map(aCall => { - // The emulator doesn't have records for disconnected calls. - if (aCall.emulatorState === "disconnected") { - return null; - } - - let state = { - alerting: "ringing", - connected: "active", - held: "held", - incoming: "incoming" - }[aCall.state]; - - state = aCall.emulatorState || state; - let prefix = (aCall.direction === "in") ? "inbound from " - : "outbound to "; - - return state ? (prefix + aCall.number + " : " + state) : null; - }); - - return checkEmulatorCallList(strings.filter(aString => aString)); - } - - /**************************************************************************** - **** Request utility functions **** - ****************************************************************************/ - - /** - * Make an outgoing call. - * - * @param number - * A string. - * @param serviceId [optional] - * Identification of a service. 0 is set as default. - * @return Promise - */ - function dial(number, serviceId) { - serviceId = typeof serviceId !== "undefined" ? serviceId : 0; - log("Make an outgoing call: " + number + ", serviceId: " + serviceId); - - let outCall; - - return telephony.dial(number, serviceId) - .then(call => outCall = call) - .then(() => { - ok(outCall instanceof TelephonyCall, "check instance"); - is(outCall.id.number, number); - is(outCall.serviceId, serviceId); - - // A CDMA call goes to connected state directly when the operator find - // its callee, which makes the "connected" state in CDMA calls behaves - // like the "alerting" state in GSM calls. - let state = Modems[serviceId].isGSM() ? "alerting" : "connected"; - - // Sometimes the dialing state is missing, see Bug 1220548. - if (outCall.state === state) { - log("got " + state + " state, dialing is missing"); - return; - } - - is(outCall.state, "dialing", "check state"); - - return waitForNamedStateEvent(outCall, state); - }); - } - - /** - * Make an outgoing emergency call. - * - * @param number - * A string. - * @return Promise - */ - function dialEmergency(number) { - log("Make an outgoing emergency call: " + number); - - let outCall; - - return telephony.dialEmergency(number) - .then(call => outCall = call) - .then(() => { - ok(outCall instanceof TelephonyCall, "check instance"); - ok(outCall); - is(outCall.id.number, number); - - // Similar to function |dial|, a CDMA call directly goes to connected - // state when the operator find its callee. - let state = Modems[outCall.serviceId].isGSM() ? "alerting" - : "connected"; - - // Sometimes the dialing state is missing, see Bug 1220548. - if (outCall.state === state) { - log("got " + state + " state, dialing is missing"); - return; - } - - is(outCall.state, "dialing", "check state"); - - return waitForNamedStateEvent(outCall, state); - }) - .then(() => { - is(outCall.emergency, true, "check emergency"); - return outCall; - }); - } - - /** - * Simulate a call dialed out by STK directly. - * - * @param number - * A string. - * @return Promise - */ - function dialSTK(number) { - log("STK makes an outgoing call: " + number); - - let p1 = waitForCallsChangedEvent(telephony); - let p2 = emulator.runCmd("stk setupcall " + number); - - return Promise.all([p1, p2]) - .then(result => { - let call = result[0]; - - ok(call instanceof TelephonyCall, "check instance"); - is(call.id.number, number, "check number"); - - // Sometimes the dialing state is missing, see Bug 1220548. - if (call.state === "alerting") { - log("got alerting state, dialing is missing"); - return; - } - - is(call.state, "dialing", "check call state"); - - return waitForNamedStateEvent(call, "alerting"); - }); - } - - /** - * Answer an incoming call. - * - * @param call - * An incoming TelephonyCall object. - * @param conferenceStateChangeCallback [optional] - * A callback function which is called if answering an incoming call - * triggers conference state change. - * @return Promise - */ - function answer(call, conferenceStateChangeCallback) { - log("Answering the incoming call."); - - let promises = []; - - // incoming call triggers conference state change. We should wait for - // |conference.onstatechange| before checking the state of the conference - // call. - if (conference.state === "connected") { - let promise = waitForStateChangeEvent(conference, "held") - .then(() => { - if (typeof conferenceStateChangeCallback === "function") { - conferenceStateChangeCallback(); - } - }); - - promises.push(promise); - } - - promises.push(waitForNamedStateEvent(call, "connected")); - promises.push(call.answer()); - - return Promise.all(promises).then(() => call); - } - - /** - * Hold a call. - * - * @param aCall - * A TelephonyCall object. - * @param aWaitForEvent - * Decide whether to wait for the state event. - * @return Promise - */ - function hold(aCall, aWaitForEvent = true) { - log("Putting the call on hold."); - - let promises = []; - - if (aWaitForEvent) { - promises.push(waitForNamedStateEvent(aCall, "held")); - } - promises.push(aCall.hold()); - - return Promise.all(promises).then(() => aCall); - } - - /** - * Resume a call. - * - * @param call - * A TelephonyCall object. - * @return Promise - */ - function resume(call, aWaitForEvent = true) { - log("Resuming the held call."); - - let promises = []; - - promises.push(waitForNamedStateEvent(call, "connected")); - promises.push(call.resume()); - - return Promise.all(promises).then(() => call); - } - - /** - * Locally hang up a call. - * - * @param call - * A TelephonyCall object. - * @return Promise - */ - function hangUp(call) { - log("Local hanging up the call: " + call.id.number); - - let promises = []; - - promises.push(waitForNamedStateEvent(call, "disconnected")); - promises.push(call.hangUp()); - - return Promise.all(promises).then(() => call); - } - - /** - * Simulate an incoming call. - * - * @param number - * A string. - * @param numberPresentation [optional] - * An unsigned short integer. - * @param name [optional] - * A string. - * @param namePresentation [optional] - * An unsigned short integer. - * @return Promise - */ - function remoteDial(number, numberPresentation, name, namePresentation) { - log("Simulating an incoming call."); - - // Register listeners - let promises = [waitForEvent(telephony, "callschanged")]; - if (Modem.isGSM() || - Modem.isCDMA() && telephony.calls.length == 0) { - promises.push(waitForEvent(telephony, "incoming")); - } - - // Make an incoming call - numberPresentation = numberPresentation || ""; - name = name || ""; - namePresentation = namePresentation || ""; - promises.push(emulator.runCmd("telephony call " + number + - "," + numberPresentation + - "," + name + - "," + namePresentation)); - - // Return the promise and check - return Promise.all(promises) - .then(aResult => { - let call = aResult[0].call; - ok(call); - - let isCdmaSecondCall = Modem.isCDMA() && - navigator.mozTelephony.calls[0].secondId; - - is(call.state, isCdmaSecondCall ? "connected" : "incoming"); - checkCallId(number, numberPresentation, - name, namePresentation, - isCdmaSecondCall ? call.secondId.number : call.id.number, - isCdmaSecondCall ? call.secondId.name : call.id.name); - - return call; - }); - } - - /** - * Remote party answers the call. - * - * @param call - * A TelephonyCall object. - * @return Promise - */ - function remoteAnswer(call) { - log("Remote answering the call: " + call.id.number); - - emulator.runCmd("telephony accept " + call.id.number); - - // A CDMA call goes to connected state directly when the operator find its - // callee, which makes the "connected" state in CDMA calls behaves like the - // "alerting" state in GSM calls, so we don't have to wait for the call to - // change to "connected" state here for CDMA calls. - return Modem.isCDMA() ? Promise.resolve() - : waitForNamedStateEvent(call, "connected"); - } - - /** - * Remote party hangs up the call. - * - * @param aIdentifier - * - * @return Promise - */ - function remoteHangUp(aIdentifier, aWaitForEvent = true) { - let call; - let number; - if (typeof aIdentifier === "string") { // A number is passed in. - number = aIdentifier; - call = navigator.mozTelephony.calls.find(aCall => { - return aCall.id.number === number || - aCall.secondId && aCall.secondId.number === number; - }); - } else { // A Telephony call object is passed in. - call = aIdentifier; - number = aIdentifier.id.number; - } - - log("Remote hanging up the call: " + number); - - let promises = []; - if (aWaitForEvent) { - promises.push(waitForNamedStateEvent(call, "disconnected")); - } - - promises.push(emulator.runCmd("telephony cancel " + number)); - return Promise.all(promises); - } - - /** - * Remote party hangs up all the calls. - * - * @param calls - * An array of TelephonyCall objects. - * @return Promise - */ - function remoteHangUpCalls(calls) { - let promises = calls.map(remoteHangUp); - return Promise.all(promises); - } - - /** - * Add calls to conference. - * - * @param callsToAdd - * An array of TelephonyCall objects to be added into conference. The - * length of the array should be 1 or 2. - * @param connectedCallback [optional] - * A callback function which is called when conference state becomes - * connected. - * @return Promise<[TelephonyCall ...]> - */ - function addCallsToConference(callsToAdd, connectedCallback) { - log("Add " + callsToAdd.length + " calls into conference."); - - let promises = []; - - for (let call of callsToAdd) { - promises.push(waitForCallsChangedEvent(conference, call)); - promises.push(waitForGroupChangeEvent(call, conference)); - promises.push(waitForNamedStateEvent(call, "connected")); - promises.push(waitForStateChangeEvent(call, "connected")); - } - - let promise = waitForNamedStateEvent(conference, "connected") - .then(() => { - if (typeof connectedCallback === "function") { - connectedCallback(); - } - }); - promises.push(promise); - - // Cannot use apply() through webidl, so just separate the cases to handle. - if (callsToAdd.length == 2) { - promise = conference.add(callsToAdd[0], callsToAdd[1]); - promises.push(promise); - } else { - promise = conference.add(callsToAdd[0]); - promises.push(promise); - } - - return Promise.all(promises).then(() => conference.calls); - } - - /** - * Hold the conference. - * - * @param callsInConference - * An array of TelephonyCall objects existing in conference. - * @param heldCallback [optional] - * A callback function which is called when conference state becomes - * held. - * @return Promise<[TelephonyCall ...]> - */ - function holdConference(callsInConference, heldCallback) { - log("Holding the conference call."); - - let promises = []; - - for (let call of callsInConference) { - promises.push(waitForNamedStateEvent(call, "held")); - } - - let promise = waitForNamedStateEvent(conference, "held") - .then(() => { - if (typeof heldCallback === "function") { - heldCallback(); - } - }); - promises.push(promise); - - promises.push(conference.hold()); - - return Promise.all(promises).then(() => conference.calls); - } - - /** - * Resume the conference. - * - * @param callsInConference - * An array of TelephonyCall objects existing in conference. - * @param connectedCallback [optional] - * A callback function which is called when conference state becomes - * connected. - * @return Promise<[TelephonyCall ...]> - */ - function resumeConference(callsInConference, connectedCallback) { - log("Resuming the held conference call."); - - let promises = []; - - for (let call of callsInConference) { - promises.push(waitForNamedStateEvent(call, "connected")); - } - - let promise = waitForNamedStateEvent(conference, "connected") - .then(() => { - if (typeof connectedCallback === "function") { - connectedCallback(); - } - }); - promises.push(promise); - - promises.push(conference.resume()); - - return Promise.all(promises).then(() => conference.calls); - } - - /** - * Remove a call out of conference. - * - * @param callToRemove - * A TelephonyCall object existing in conference. - * @param autoRemovedCalls - * An array of TelephonyCall objects which is going to be automatically - * removed. The length of the array should be 0 or 1. - * @param remainedCalls - * An array of TelephonyCall objects which remain in conference. - * @param stateChangeCallback [optional] - * A callback function which is called when conference state changes. - * @return Promise<[TelephonyCall ...]> - */ - function removeCallInConference(callToRemove, autoRemovedCalls, remainedCalls, - statechangeCallback) { - log("Removing a participant from the conference call."); - - is(conference.state, 'connected'); - - let promises = []; - - // callToRemove. - promises.push(waitForCallsChangedEvent(telephony, callToRemove)); - promises.push(waitForCallsChangedEvent(conference, callToRemove)); - promises.push(waitForGroupChangeEvent(callToRemove, null).then(() => { - is(callToRemove.state, 'connected'); - })); - - // When a call is removed from conference with 2 calls, another one will be - // automatically removed from group and be put on hold. - for (let call of autoRemovedCalls) { - promises.push(waitForCallsChangedEvent(telephony, call)); - promises.push(waitForCallsChangedEvent(conference, call)); - promises.push(waitForGroupChangeEvent(call, null)); - promises.push(waitForStateChangeEvent(call, "held")); - } - - // Remained call in conference will be held. - for (let call of remainedCalls) { - promises.push(waitForStateChangeEvent(call, "held")); - } - - let finalConferenceState = remainedCalls.length ? "held" : ""; - let promise = waitForStateChangeEvent(conference, finalConferenceState) - .then(() => { - if (typeof statechangeCallback === 'function') { - statechangeCallback(); - } - }); - promises.push(promise); - - promises.push(conference.remove(callToRemove)); - - return Promise.all(promises) - .then(() => checkCalls(conference.calls, remainedCalls)) - .then(() => conference.calls); - } - - /** - * Hangup a call in conference. - * - * @param callToHangUp - * A TelephonyCall object existing in conference. - * @param autoRemovedCalls - * An array of TelephonyCall objects which is going to be automatically - * removed. The length of the array should be 0 or 1. - * @param remainedCalls - * An array of TelephonyCall objects which remain in conference. - * @param stateChangeCallback [optional] - * A callback function which is called when conference state changes. - * @return Promise<[TelephonyCall ...]> - */ - function hangUpCallInConference(callToHangUp, autoRemovedCalls, remainedCalls, - statechangeCallback) { - log("Release one call in conference."); - - let promises = []; - - // callToHangUp. - promises.push(waitForCallsChangedEvent(conference, callToHangUp)); - - // When a call is removed from conference with 2 calls, another one will be - // automatically removed from group. - for (let call of autoRemovedCalls) { - promises.push(waitForCallsChangedEvent(telephony, call)); - promises.push(waitForCallsChangedEvent(conference, call)); - promises.push(waitForGroupChangeEvent(call, null)); - } - - if (remainedCalls.length === 0) { - let promise = waitForStateChangeEvent(conference, "") - .then(() => { - if (typeof statechangeCallback === 'function') { - statechangeCallback(); - } - }); - promises.push(promise); - } - - promises.push(remoteHangUp(callToHangUp)); - - return Promise.all(promises) - .then(() => checkCalls(conference.calls, remainedCalls)) - .then(() => conference.calls); - } - - /** - * Hangup conference. - * - * @return Promise - */ - function hangUpConference() { - log("Hangup conference."); - - let promises = []; - - promises.push(waitForStateChangeEvent(conference, "")); - - for (let call of conference.calls) { - promises.push(waitForNamedStateEvent(call, "disconnected")); - } - - return conference.hangUp().then(() => { - return Promise.all(promises); - }); - } - - /** - * Create a conference with an outgoing call and an incoming call. - * - * @param outNumber - * Number of an outgoing call. - * @param inNumber - * Number of an incoming call. - * @return Promise<[outCall, inCall]> - */ - function createConferenceWithTwoCalls(outNumber, inNumber) { - let outCall; - let inCall; - let outInfo = outCallStrPool(outNumber); - let inInfo = inCallStrPool(inNumber); - - return Promise.resolve() - .then(checkInitialState) - .then(() => dial(outNumber)) - .then(call => { outCall = call; }) - .then(() => checkAll(outCall, [outCall], '', [], [outInfo.ringing])) - .then(() => remoteAnswer(outCall)) - .then(() => checkAll(outCall, [outCall], '', [], [outInfo.active])) - .then(() => remoteDial(inNumber)) - .then(call => { inCall = call; }) - .then(() => checkAll(outCall, [outCall, inCall], '', [], - [outInfo.active, inInfo.waiting])) - .then(() => answer(inCall)) - .then(() => checkAll(inCall, [outCall, inCall], '', [], - [outInfo.held, inInfo.active])) - .then(() => addCallsToConference([outCall, inCall], function() { - checkState(conference, [], 'connected', [outCall, inCall]); - })) - .then(() => checkAll(conference, [], 'connected', [outCall, inCall], - [outInfo.active, inInfo.active])) - .then(() => { - return [outCall, inCall]; - }); - } - - /** - * Create a new incoming call and add it into the conference. - * - * @param inNumber - * Number of an incoming call. - * @param conferenceCalls - * Calls already in conference. - * @return Promise<[calls in the conference]> - */ - function createCallAndAddToConference(inNumber, conferenceCalls) { - // Create an info array. allInfo = [info1, info2, ...]. - let allInfo = conferenceCalls.map(function(call, i) { - return (i === 0) ? outCallStrPool(call.id.number) - : inCallStrPool(call.id.number); - }); - - // Define state property of the info array. - // Ex: allInfo.active = [info1.active, info2.active, ...]. - function addInfoState(allInfo, state) { - Object.defineProperty(allInfo, state, { - get: function() { - return allInfo.map(function(info) { return info[state]; }); - } - }); - } - - for (let state of ["ringing", "incoming", "waiting", "active", "held"]) { - addInfoState(allInfo, state); - } - - let newCall; - let newInfo = inCallStrPool(inNumber); - - return remoteDial(inNumber) - .then(call => { newCall = call; }) - .then(() => checkAll(conference, [newCall], 'connected', conferenceCalls, - allInfo.active.concat(newInfo.waiting))) - .then(() => answer(newCall, function() { - checkState(newCall, [newCall], 'held', conferenceCalls); - })) - .then(() => checkAll(newCall, [newCall], 'held', conferenceCalls, - allInfo.held.concat(newInfo.active))) - .then(() => { - // We are going to add the new call into the conference. - conferenceCalls.push(newCall); - allInfo.push(newInfo); - }) - .then(() => addCallsToConference([newCall], function() { - checkState(conference, [], 'connected', conferenceCalls); - })) - .then(() => checkAll(conference, [], 'connected', conferenceCalls, - allInfo.active)) - .then(() => { - return conferenceCalls; - }); - } - - /** - * Setup a conference with an outgoing call and N incoming calls. - * - * @param callNumbers - * Array of numbers, the first number is for outgoing call and the - * remaining numbers are for incoming calls. - * @return Promise<[calls in the conference]> - */ - function setupConference(callNumbers) { - log("Create a conference with " + callNumbers.length + " calls."); - - let promise = createConferenceWithTwoCalls(callNumbers[0], callNumbers[1]); - - callNumbers.shift(); - callNumbers.shift(); - for (let number of callNumbers) { - promise = promise.then(createCallAndAddToConference.bind(null, number)); - } - - return promise; - } - - /** - * Send out the MMI code. - * - * @param mmi - * String of MMI code - * @return Promise - */ - function sendMMI(mmi) { - return telephony.dial(mmi).then(mmiCall => { - ok(mmiCall instanceof MMICall, "mmiCall is instance of MMICall"); - ok(mmiCall.result instanceof Promise, "result is Promise"); - return mmiCall.result; - }); - } - - function sendTone(tone, pause, serviceId) { - log("Send DTMF " + tone + " serviceId " + serviceId); - return telephony.sendTones(tone, pause, null, serviceId); - } - - /** - * Config radio. - * - * @param connection - * MobileConnection object. - * @param enabled - * True to enable the radio. - * @return Promise - */ - function setRadioEnabled(connection, enabled) { - let desiredRadioState = enabled ? 'enabled' : 'disabled'; - log("Set radio: " + desiredRadioState); - - if (connection.radioState === desiredRadioState) { - return Promise.resolve(); - } - - let promises = []; - - promises.push(gWaitForEvent(connection, "radiostatechange", event => { - let state = connection.radioState; - log("current radioState: " + state); - return state == desiredRadioState; - })); - - // Wait for icc status to finish updating. Please see bug 1169504 for the - // reason why we need this. - promises.push(gWaitForEvent(connection, "iccchange", event => { - let iccId = connection.iccId; - log("current iccId: " + iccId); - return !!iccId === enabled; - })); - - promises.push(connection.setRadioEnabled(enabled)); - - return Promise.all(promises); - } - - function setRadioEnabledAll(enabled) { - let promises = []; - let numOfSim = navigator.mozMobileConnections.length; - - for (let i = 0; i < numOfSim; i++) { - let connection = navigator.mozMobileConnections[i]; - ok(connection instanceof MozMobileConnection, - "connection[" + i + "] is instanceof " + connection.constructor); - - promises.push(setRadioEnabled(connection, enabled)); - } - - return Promise.all(promises); - } - - /** - * Public members. - */ - - this.gDelay = delay; - this.gWaitForSystemMessage = waitForSystemMessage; - this.gWaitForEvent = waitForEvent; - this.gWaitForCallsChangedEvent = waitForCallsChangedEvent; - this.gWaitForNamedStateEvent = waitForNamedStateEvent; - this.gWaitForStateChangeEvent = waitForStateChangeEvent; - this.gCheckInitialState = checkInitialState; - this.gClearCalls = clearCalls; - this.gOutCallStrPool = outCallStrPool; - this.gInCallStrPool = inCallStrPool; - this.gCheckState = checkState; - this.gCheckAll = checkAll; - this.gSendMMI = sendMMI; - this.gDial = dial; - this.gDialEmergency = dialEmergency; - this.gDialSTK = dialSTK; - this.gAnswer = answer; - this.gHangUp = hangUp; - this.gHold = hold; - this.gResume = resume; - this.gRemoteDial = remoteDial; - this.gRemoteAnswer = remoteAnswer; - this.gRemoteHangUp = remoteHangUp; - this.gRemoteHangUpCalls = remoteHangUpCalls; - this.gAddCallsToConference = addCallsToConference; - this.gHoldConference = holdConference; - this.gResumeConference = resumeConference; - this.gRemoveCallInConference = removeCallInConference; - this.gHangUpCallInConference = hangUpCallInConference; - this.gHangUpConference = hangUpConference; - this.gSendTone = sendTone; - this.gSetupConference = setupConference; - this.gSetRadioEnabled = setRadioEnabled; - this.gSetRadioEnabledAll = setRadioEnabledAll; - - // Telephony helper - this.TelephonyHelper = { - dial: dial, - answer: answer, - hangUp: hangUp, - hold: hold, - resume: resume, - equals: equals, - createExptectedCall: createExptectedCall - }; - - // Remote Utils, TODO: This should be an array for multi-SIM scenarios - this.Remotes = [{ - dial: remoteDial, - answer: remoteAnswer, - hangUp: remoteHangUp - }]; - this.Remote = this.Remotes[0]; -}()); - -function _startTest(permissions, test) { - function typesToPermissions(types) { - return types.map(type => { - return { - "type": type, - "allow": 1, - "context": document - }; - }); - } - - function ensureRadio() { - log("== Ensure Radio =="); - return new Promise(function(resolve, reject) { - SpecialPowers.pushPermissions(typesToPermissions(["mobileconnection"]), () => { - gSetRadioEnabledAll(true).then(() => { - SpecialPowers.popPermissions(() => { - resolve(); - }); - }); - }); - }); - } - - function permissionSetUp() { - log("== Permission SetUp =="); - return new Promise(function(resolve, reject) { - SpecialPowers.pushPermissions(typesToPermissions(permissions), resolve); - }); - } - - let debugPref; - - function setUp() { - log("== Test SetUp =="); - - // Turn on debugging pref. - debugPref = SpecialPowers.getBoolPref(kPrefRilDebuggingEnabled); - SpecialPowers.setBoolPref(kPrefRilDebuggingEnabled, true); - log("Set debugging pref: " + debugPref + " => true"); - - return Promise.resolve() - .then(ensureRadio) - .then(permissionSetUp) - .then(() => { - // Make sure that we get the telephony after adding permission. - telephony = window.navigator.mozTelephony; - ok(telephony); - conference = telephony.conferenceGroup; - ok(conference); - }) - .then(gClearCalls) - .then(gCheckInitialState); - } - - // Extend finish() with tear down. - finish = (function() { - let originalFinish = finish; - - function tearDown() { - log("== Test TearDown =="); - emulator.waitFinish() - .then(() => { - // Restore debugging pref. - SpecialPowers.setBoolPref(kPrefRilDebuggingEnabled, debugPref); - log("Set debugging pref: true => " + debugPref); - }) - .then(function() { - originalFinish.apply(this, arguments); - }); - } - - return tearDown.bind(this); - }()); - - setUp().then(() => { - log("== Test Start =="); - test(); - }) - .catch(error => ok(false, error)); -} - -function startTest(test) { - _startTest(["telephony"], test); -} - -function startTestWithPermissions(permissions, test) { - _startTest(permissions.concat("telephony"), test); -} - -function startDSDSTest(test) { - let numRIL; - try { - numRIL = SpecialPowers.getIntPref("ril.numRadioInterfaces"); - } catch (ex) { - numRIL = 1; // Pref not set. - } - - if (numRIL > 1) { - startTest(test); - } else { - log("Not a DSDS environment. Test is skipped."); - ok(true); // We should run at least one test. - finish(); - } -} diff --git a/dom/telephony/test/marionette/manifest.ini b/dom/telephony/test/marionette/manifest.ini deleted file mode 100644 index 98feb66042b6..000000000000 --- a/dom/telephony/test/marionette/manifest.ini +++ /dev/null @@ -1,69 +0,0 @@ -[DEFAULT] -run-if = buildapp == 'b2g' - -[test_audiomanager_phonestate.js] -[test_call_mute.js] -[test_call_presentation.js] -[test_cdma_call_waiting.js] -[test_conference_add_error.js] -[test_conference_add_twice_error.js] -[test_conference_remove_error.js] -[test_conference_three_hangup_one.js] -[test_conference_three_remove_one.js] -[test_conference_two_calls.js] -[test_conference_two_hangup_all.js] -[test_conference_two_hangup_one.js] -[test_conference_two_hold_resume.js] -[test_conference_two_remove_one.js] -[test_consecutive_hold.js] -[test_crash_emulator.js] -[test_dsds_connection_conflict.js] -[test_dsds_normal_call.js] -[test_dtmf.js] -[test_emergency.js] -[test_emergency_label.js] -[test_gsm_cdma_incoming_basic_operations.js] -skip-if = true # Bug 1214537 -[test_gsm_cdma_outgoing_basic_operations.js] -skip-if = true # Bug 1214537 -[test_incall_mmi_call_hold.js] -[test_incall_mmi_call_waiting.js] -[test_incall_mmi_conference.js] -[test_incall_mmi_imei.js] -[test_incoming_already_connected.js] -[test_incoming_already_held.js] -[test_incoming_answer_hangup_oncallschanged.js] -[test_incoming_onstatechange.js] -[test_mmi_call_barring.js] -[test_mmi_call_forwarding.js] -[test_mmi_call_waiting.js] -[test_mmi_change_barring_password.js] -[test_mmi_change_pin2.js] -[test_mmi_change_pin.js] -[test_mmi_clip.js] -[test_mmi_clir.js] -[test_mmi_imei.js] -[test_mmi_unlock_puk2.js] -[test_mmi_unlock_puk.js] -[test_mmi_ussd.js] -skip-if = android_version < '19' -[test_modem_switch_tech.js] -[test_multiple_hold.js] -[test_outgoing_already_held.js] -[test_outgoing_answer_hangup_oncallschanged.js] -[test_outgoing_answer_radio_off.js] -[test_outgoing_auto_hold.js] -[test_outgoing_badNumber.js] -[test_outgoing_busy.js] -[test_outgoing_from_stk.js] -[test_outgoing_onstatechange.js] -[test_outgoing_radio_off.js] -[test_outgoing_when_two_calls_on_line.js] -[test_ready.js] -[test_redundant_operations.js] -[test_swap_held_and_active.js] -[test_system_message_telephony_call_ended.js] -[test_telephony_dsds_default_service_id.js] -[test_TelephonyUtils.js] -[test_temporary_clir.js] - diff --git a/dom/telephony/test/marionette/test_TelephonyUtils.js b/dom/telephony/test/marionette/test_TelephonyUtils.js deleted file mode 100644 index 987e2459638e..000000000000 --- a/dom/telephony/test/marionette/test_TelephonyUtils.js +++ /dev/null @@ -1,100 +0,0 @@ -/* Any copyright is dedicated to the Public Domain. - * http://creativecommons.org/publicdomain/zero/1.0/ */ - -MARIONETTE_TIMEOUT = 60000; -MARIONETTE_CONTEXT = "chrome"; -MARIONETTE_HEAD_JS = 'head.js'; - -Cu.import("resource://gre/modules/XPCOMUtils.jsm"); -Cu.import("resource://gre/modules/Promise.jsm"); - -XPCOMUtils.defineLazyServiceGetter(this, - "TelephonyService", - "@mozilla.org/telephony/telephonyservice;1", - "nsIGonkTelephonyService"); - -XPCOMUtils.defineLazyModuleGetter(this, "TelephonyUtils", - "resource://gre/modules/TelephonyUtils.jsm"); - -XPCOMUtils.defineLazyGetter(this, "RIL", function () { - let ns = {}; - Cu.import("resource://gre/modules/ril_consts.js", ns); - return ns; -}); - -const number = "0912345678"; - -function dial() { - return new Promise(resolve => { - TelephonyService.dial(0, number, false, { - QueryInterface: XPCOMUtils.generateQI([Ci.nsITelephonyDialCallback]), - notifyDialCallSuccess: function() { resolve(); } - }); - }); -} - -function waitForStateChanged(aPredicate) { - return new Promise(resolve => { - let listener = { - QueryInterface: XPCOMUtils.generateQI([Ci.nsITelephonyListener]), - - callStateChanged: function(length, allInfo) { - if (aPredicate(allInfo)) { - resolve(allInfo); - TelephonyService.unregisterListener(listener); - } - }, - - supplementaryServiceNotification: function() {}, - notifyError: function() {}, - notifyCdmaCallWaiting: function() {}, - notifyConferenceError: function() {} - }; - - TelephonyService.registerListener(listener); - }); -} - -function test_noCall() { - log("== test_noCall =="); - is(TelephonyUtils.hasAnyCalls(), false, "hasAnyCalls"); - is(TelephonyUtils.hasConnectedCalls(), false, "hasConnectedCalls"); - return TelephonyUtils.waitForNoCalls(); -} - -function test_oneCall() { - log("== test_oneCall =="); - - return dial() - .then(() => { - is(TelephonyUtils.hasAnyCalls(), true, "hasAnyCalls"); - is(TelephonyUtils.hasConnectedCalls(), false, "hasConnectedCalls"); - }) - .then(() => waitForStateChanged(aAllInfo => { - return aAllInfo[0].callState === Ci.nsITelephonyService.CALL_STATE_ALERTING; - })) - .then(() => { - let p = waitForStateChanged(aAllInfo => { - return aAllInfo[0].callState === Ci.nsITelephonyService.CALL_STATE_CONNECTED; - }); - emulator.runCmd("telephony accept " + number); - return p; - }) - .then(() => { - is(TelephonyUtils.hasAnyCalls(), true, "hasAnyCalls"); - is(TelephonyUtils.hasConnectedCalls(), true, "hasConnectedCalls"); - }) - .then(() => { - let p = TelephonyUtils.waitForNoCalls(); - emulator.runCmd("telephony cancel " + number); - return p; - }); -} - -startTest(function() { - return Promise.resolve() - .then(test_noCall) - .then(test_oneCall) - .catch(error => ok(false, "Promise reject: " + error)) - .then(finish); -}); diff --git a/dom/telephony/test/marionette/test_audiomanager_phonestate.js b/dom/telephony/test/marionette/test_audiomanager_phonestate.js deleted file mode 100644 index e83dd6733e09..000000000000 --- a/dom/telephony/test/marionette/test_audiomanager_phonestate.js +++ /dev/null @@ -1,94 +0,0 @@ -/* Any copyright is dedicated to the Public Domain. - * http://creativecommons.org/publicdomain/zero/1.0/ */ - -MARIONETTE_TIMEOUT = 60000; -MARIONETTE_HEAD_JS = 'head.js'; - -const AUDIO_MANAGER_CONTRACT_ID = "@mozilla.org/telephony/audiomanager;1"; - -// See nsIAudioManager -const PHONE_STATE_INVALID = -2; -const PHONE_STATE_CURRENT = -1; -const PHONE_STATE_NORMAL = 0; -const PHONE_STATE_RINGTONE = 1; -const PHONE_STATE_IN_CALL = 2; -const PHONE_STATE_IN_COMMUNICATION = 3; - -var audioManager = SpecialPowers.Cc[AUDIO_MANAGER_CONTRACT_ID] - .getService(SpecialPowers.Ci.nsIAudioManager); - -ok(audioManager, "nsIAudioManager instance"); - -function check(phoneState) { - return new Promise(function(resolve, reject) { - waitFor(function() { - resolve(); - }, function() { - let currentPhoneState = audioManager.phoneState; - log("waiting.. audioState should change to " + phoneState + - ", current is" + currentPhoneState); - - return (phoneState == currentPhoneState || - (phoneState == PHONE_STATE_CURRENT && - currentPhoneState == PHONE_STATE_NORMAL)); - }); - }); -} - -// Start the test -startTest(function() { - let outNumber = "5555550101"; - let inNumber = "5555550201"; - let outCall; - let inCall; - - Promise.resolve() - .then(() => check(PHONE_STATE_CURRENT)) - - // Dial in - .then(() => gRemoteDial(inNumber)) - .then(call => { inCall = call; }) - .then(() => check(PHONE_STATE_RINGTONE)) - .then(() => gAnswer(inCall)) - .then(() => check(PHONE_STATE_IN_CALL)) - // Hang up all - .then(() => gRemoteHangUp(inCall)) - .then(() => check(PHONE_STATE_NORMAL)) - - // Dial out - .then(() => gDial(outNumber)) - .then(call => { outCall = call; }) - .then(() => check(PHONE_STATE_IN_CALL)) - .then(() => gRemoteAnswer(outCall)) - .then(() => check(PHONE_STATE_IN_CALL)) - // Hang up all - .then(() => gRemoteHangUp(outCall)) - .then(() => check(PHONE_STATE_NORMAL)) - - // Dial out - .then(() => gDial(outNumber)) - .then(call => { outCall = call; }) - .then(() => check(PHONE_STATE_IN_CALL)) - .then(() => gRemoteAnswer(outCall)) - .then(() => check(PHONE_STATE_IN_CALL)) - .then(() => gHold(outCall)) - .then(() => check(PHONE_STATE_IN_CALL)) - .then(() => gResume(outCall)) - .then(() => check(PHONE_STATE_IN_CALL)) - // Dial out and dial in - .then(() => gRemoteDial(inNumber)) - .then(call => { inCall = call; }) - .then(() => check(PHONE_STATE_IN_CALL)) - .then(() => gAnswer(inCall)) - .then(() => check(PHONE_STATE_IN_CALL)) - // Conference - .then(() => gAddCallsToConference([outCall, inCall])) - .then(() => check(PHONE_STATE_IN_CALL)) - // Hang up all - .then(() => gRemoteHangUpCalls([outCall, inCall])) - .then(() => check(PHONE_STATE_NORMAL)) - - // End - .catch(error => ok(false, "Promise reject: " + error)) - .then(finish); -}); diff --git a/dom/telephony/test/marionette/test_call_mute.js b/dom/telephony/test/marionette/test_call_mute.js deleted file mode 100644 index d97f73a126da..000000000000 --- a/dom/telephony/test/marionette/test_call_mute.js +++ /dev/null @@ -1,21 +0,0 @@ -/* Any copyright is dedicated to the Public Domain. - * http://creativecommons.org/publicdomain/zero/1.0/ */ - -MARIONETTE_TIMEOUT = 60000; -MARIONETTE_HEAD_JS = 'head.js'; - -function test_call_mute() { - telephony.muted = true; - is(telephony.muted, true); - telephony.muted = false; - is(telephony.muted, false); - cleanUp(); -} - -function cleanUp() { - finish(); -} - -startTest(function() { - test_call_mute(); -}); diff --git a/dom/telephony/test/marionette/test_call_presentation.js b/dom/telephony/test/marionette/test_call_presentation.js deleted file mode 100644 index 67b5c330fa8f..000000000000 --- a/dom/telephony/test/marionette/test_call_presentation.js +++ /dev/null @@ -1,71 +0,0 @@ -/* Any copyright is dedicated to the Public Domain. - * http://creativecommons.org/publicdomain/zero/1.0/ */ - -MARIONETTE_TIMEOUT = 60000; -MARIONETTE_HEAD_JS = 'head.js'; - -const ALLOWED = 0; -const RESTRICTED = 1; -const UNKNOWN = 2; -const PAYPHONE =3; - -function getPresentationStr(presentation) { - let str; - switch (presentation) { - case ALLOWED: - str = "allowed"; - break; - case RESTRICTED: - str = "restricted"; - break; - case UNKNOWN: - str = "unknown"; - break; - case PAYPHONE: - str = "payphone"; - break; - } - return str; -} - -function getNamePresentation(numberPresentation, namePresentation) { - // See TS 23.096 Figure 3a and Annex A Note 1. - if (!numberPresentation) { - if (namePresentation == undefined) { - namePresentation = ALLOWED; - } - } else { - namePresentation = ALLOWED; - } - return getPresentationStr(namePresentation); -} - -function test(number, numberPresentation, name, namePresentation) { - return gRemoteDial(number, numberPresentation, name, namePresentation) - .then(call => { - is(call.id.numberPresentation, getPresentationStr(numberPresentation), - "check numberPresentation"); - is(call.id.namePresentation, - getNamePresentation(numberPresentation, namePresentation), - "check namePresentation"); - return call; - }) - .then(gHangUp); -} - -startTest(function() { - let inNumber = "5555550201"; - Promise.resolve() - .then(() => test(inNumber, ALLOWED)) - .then(() => test(inNumber, RESTRICTED)) - .then(() => test(inNumber, UNKNOWN)) - .then(() => test(inNumber, PAYPHONE)) - .then(() => test(inNumber, ALLOWED, "TestName")) - .then(() => test(inNumber, ALLOWED, "TestName", ALLOWED)) - .then(() => test(inNumber, ALLOWED, "TestName", RESTRICTED)) - .then(() => test(inNumber, ALLOWED, "TestName", UNKNOWN)) - .then(() => test(inNumber, RESTRICTED, "TestName", ALLOWED)) - .then(() => test(inNumber, RESTRICTED, "TestName", RESTRICTED)) - .then(() => test(inNumber, RESTRICTED, "TestName", UNKNOWN)) - .then(finish); -}); diff --git a/dom/telephony/test/marionette/test_cdma_call_waiting.js b/dom/telephony/test/marionette/test_cdma_call_waiting.js deleted file mode 100644 index 60b3bcc883b3..000000000000 --- a/dom/telephony/test/marionette/test_cdma_call_waiting.js +++ /dev/null @@ -1,288 +0,0 @@ -/* Any copyright is dedicated to the Public Domain. - * http://creativecommons.org/publicdomain/zero/1.0/ */ - -MARIONETTE_TIMEOUT = 180000; -MARIONETTE_HEAD_JS = 'head.js'; - -/****************************************************************************** - **** Basic Operations **** - ******************************************************************************/ - -// In a CDMA network, a modem can connected with at most 2 remote parties at a -// time. To align to the spec defined in 3gpp2-Call Waiting, in this testcase, A -// refers to local party, while B and C refer to the first and the second remote -// party respectively. - -let Numbers = ["0911111111", - "0922222222"]; - -function exptectedCall(aCall, aNumberIndex, aState, aEmulatorState = null) { - let disconnectedReason = (aState === "disconnected") ? "NormalCallClearing" - : null; - - return TelephonyHelper.createExptectedCall(aCall, Numbers[aNumberIndex], - false, "in", aState, - aEmulatorState, - disconnectedReason); -} - -function empty(aCalls) { - return [exptectedCall(aCalls[0], 0, "disconnected"), - exptectedCall(aCalls[1], 1, "disconnected")]; -} - -function flash(aCall) { - return TelephonyHelper.hold(aCall, false); -} - -/****************************************************************************** - **** Plots **** - ******************************************************************************/ - -/* State defined by 3GPP2 | Abbreviation | Remote call state - --------------------------------+----------------+------------------------ - 2-Way | N/A | [connected] - --------------------------------+----------------+------------------------ - 2-Way Call Waiting Notification | CWN | [connected, waiting] - --------------------------------+----------------+------------------------ - 2-Way Call Waiting | CW | [connected, held], - | | [held, connected] */ - -let Opening = (function() { - - function CWN() { - let call; - return Promise.resolve() - .then(() => Remote.dial(Numbers[0])).then(aCall => call = aCall) - .then(() => TelephonyHelper.equals([exptectedCall(call, 0, "incoming")])) - - .then(() => TelephonyHelper.answer(call)) - .then(() => TelephonyHelper.equals([exptectedCall(call, 0, "connected")])) - - .then(() => Remote.dial(Numbers[1])) - .then(() => { - let calls = [exptectedCall(call, 0, "connected", "active"), - exptectedCall(call, 1, "connected", "waiting")]; - return TelephonyHelper.equals(calls); - }) - - // Return the call - .then(() => call); - } - - function CW() { - let call; - return CWN() - .then(aCall => call = aCall) - .then(() => flash(call)) - .then(() => { - // After A-C connection is constructed, A-C becomes the active connection. - let calls = [exptectedCall(call, 0, "connected", "held"), - exptectedCall(call, 1, "connected", "active")]; - return TelephonyHelper.equals(calls); - }) - - // Return the call - .then(() => call); - } - - function CW_1Flash() { - let call; - return CW() - .then(aCall => call = aCall) - .then(() => flash(call)) - .then(() => { - let calls = [exptectedCall(call, 0, "connected", "active"), - exptectedCall(call, 1, "connected", "held")]; - return TelephonyHelper.equals(calls); - }) - - // Return the call - .then(() => call); - } - - function CW_2Flash() { - let call; - return CW_1Flash() - .then(aCall => call = aCall) - .then(() => flash(call)) - .then(() => { - let calls = [exptectedCall(call, 0, "connected", "held"), - exptectedCall(call, 1, "connected", "active")]; - return TelephonyHelper.equals(calls); - }) - - // Return the call - .then(() => call); - } - - function CW_3Flash() { - let call; - return CW_2Flash() - .then(aCall => call = aCall) - .then(() => flash(call)) - .then(() => { - let calls = [exptectedCall(call, 0, "connected", "active"), - exptectedCall(call, 1, "connected", "held")]; - return TelephonyHelper.equals(calls); - }) - - // Return the call - .then(() => call); - } - - return { - CWN: CWN, - CW: CW, - CW_1Flash: CW_1Flash, - CW_2Flash: CW_2Flash, - CW_3Flash: CW_3Flash - }; -})(); - -let Ending = (function() { - // No matter how many remote parties are connected, locally hanging up the - // call will disconnect every remote party. - function AHangUp(aCall) { - return Promise.resolve() - .then(() => TelephonyHelper.hangUp(aCall)) - .then(() => TelephonyHelper.equals(empty([aCall, aCall]))); - } - - // B is the only remote party now, and B is going to hang up. - function BHangUp(aCall) { - return Promise.resolve() - .then(() => Remote.hangUp(Numbers[0], true)) - .then(() => TelephonyHelper.equals(empty([aCall, aCall]))); - } - - // C is the only remote party now, and C is going to hang up. - function CHangUp(aCall) { - return Promise.resolve() - .then(() => Remote.hangUp(Numbers[1], true)) - .then(() => TelephonyHelper.equals(empty([aCall, aCall]))); - } - - // Both B and C are connected now, and B is going to hang up. - function intermediate_BHangUp(aCall) { - // After B hang up, A-C connection will become active. On the other hand, - // since there is no notification for the disconnection of B, we still think - // B is connected. - let calls = [exptectedCall(aCall, 0, "connected", "disconnected"), - exptectedCall(aCall, 1, "connected", "active")]; - - return Promise.resolve() - .then(() => Remote.hangUp(Numbers[0], false)) - .then(() => TelephonyHelper.equals(calls)) - .then(() => aCall); - } - - // Both B and C are connected now, and C is going to hang up. - function intermediate_CHangUp(aCall) { - // After C hang up, A-C connection will become active. On the other hand, - // since there is no notification for the disconnection of C, we still think - // C is connected. - let calls = [exptectedCall(aCall, 0, "connected", "active"), - exptectedCall(aCall, 1, "connected", "disconnected")]; - - return Promise.resolve() - .then(() => Remote.hangUp(Numbers[1], false)) - .then(() => TelephonyHelper.equals(calls)) - .then(() => aCall); - } - - function BHangUp_AHangUp(aCall) { - return intermediate_BHangUp(aCall).then(aCall => AHangUp(aCall)); - } - - function BHangUp_CHangUp(aCall) { - return intermediate_BHangUp(aCall).then(aCall => CHangUp(aCall)); - } - - function CHangUp_AHangUp(aCall) { - return intermediate_CHangUp(aCall).then(aCall => AHangUp(aCall)); - } - - function CHangUp_BHangUp(aCall) { - return intermediate_CHangUp(aCall).then(aCall => BHangUp(aCall)); - } - - return { - AHangUp: AHangUp, - BHangUp: BHangUp, - CHangUp: CHangUp, - - BHangUp_AHangUp: BHangUp_AHangUp, - BHangUp_CHangUp: BHangUp_CHangUp, - CHangUp_AHangUp: CHangUp_AHangUp, - CHangUp_BHangUp: CHangUp_BHangUp - }; -})(); - -/****************************************************************************** - **** Testcases **** - ******************************************************************************/ - -// Tests for call waiting nofication state. [active, waiting] -function runTestSuiteForCallWaitingNotification() { - let endings = [Ending.AHangUp, - Ending.BHangUp, - Ending.CHangUp_AHangUp, - Ending.CHangUp_BHangUp]; - - let promise = Promise.resolve(); - endings.forEach(ending => { - promise = promise - .then(() => log("= Test: " + Opening.CWN.name + "_" + ending.name + " =")) - .then(() => Opening.CWN()) - .then(aCall => ending(aCall)); - }); - - return promise; -} - -// Tests for call waiting state. [active, held] or [held, active] -function runTestSuiteForCallWaiting() { - let openings = [Opening.CW, - Opening.CW_1Flash, - Opening.CW_2Flash, - Opening.CW_3Flash]; - - let endings = [Ending.AHangUp, - Ending.BHangUp_AHangUp, - Ending.BHangUp_CHangUp, - Ending.CHangUp_AHangUp, - Ending.CHangUp_BHangUp]; - - let promise = Promise.resolve(); - openings.forEach(opening => { - endings.forEach(ending => { - promise = promise - .then(() => log("= Test: " + opening.name + "_" + ending.name + " =")) - .then(() => opening()) - .then(aCall => ending(aCall)); - }); - }); - - return promise; -} - -/****************************************************************************** - **** Test Launcher **** - ******************************************************************************/ - -startTest(function() { - return Promise.resolve() - // Setup Environment - .then(() => Modem.changeTech("cdma")) - - .then(() => runTestSuiteForCallWaitingNotification()) - .then(() => runTestSuiteForCallWaiting()) - - // Restore Environment - .then(() => Modem.changeTech("wcdma")) - - // Finalize - .catch(error => ok(false, "Promise reject: " + error)) - .then(finish); -}); diff --git a/dom/telephony/test/marionette/test_conference_add_error.js b/dom/telephony/test/marionette/test_conference_add_error.js deleted file mode 100644 index 447b8b621f63..000000000000 --- a/dom/telephony/test/marionette/test_conference_add_error.js +++ /dev/null @@ -1,71 +0,0 @@ -/* Any copyright is dedicated to the Public Domain. - * http://creativecommons.org/publicdomain/zero/1.0/ */ - -MARIONETTE_TIMEOUT = 60000; -MARIONETTE_HEAD_JS = 'head.js'; - -function handleConferenceAddError(callToAdd) { - log('Handle conference add error.'); - - let deferred = Promise.defer(); - - conference.onerror = function(evt) { - log('Receiving a conference error event.'); - conference.onerror = null; - - is(evt.name, 'addError', 'conference addError'); - - deferred.resolve(); - }; - - return conference.add(callToAdd) - .then(() => ok(false, "|conference.add| should be rejected"), - () => log("|conference.add| is rejected as expected")) - .then(() => deferred.promise); -} - -function testConferenceAddError() { - log('= testConferenceAddError ='); - - let outCall, inCall, inCall2, inCall3, inCall4, inCall5; - let outNumber = "5555550101"; - let inNumber = "5555550201"; - let inNumber2 = "5555550202"; - let inNumber3 = "5555550203"; - let inNumber4 = "5555550204"; - let inNumber5 = "5555550205"; - let outInfo = gOutCallStrPool(outNumber); - let inInfo = gInCallStrPool(inNumber); - let inInfo2 = gInCallStrPool(inNumber2); - let inInfo3 = gInCallStrPool(inNumber3); - let inInfo4 = gInCallStrPool(inNumber4); - let inInfo5 = gInCallStrPool(inNumber5); - - return Promise.resolve() - .then(() => gSetupConference([outNumber, inNumber, inNumber2, inNumber3, - inNumber4])) - .then(calls => { - [outCall, inCall, inCall2, inCall3, inCall4] = calls; - }) - .then(() => gRemoteDial(inNumber5)) - .then(call => {inCall5 = call;}) - .then(() => gAnswer(inCall5, function() { - gCheckState(inCall5, [inCall5], 'held', - [outCall, inCall, inCall2, inCall3, inCall4]); - })) - .then(() => gCheckAll(inCall5, [inCall5], 'held', - [outCall, inCall, inCall2, inCall3, inCall4], - [outInfo.held, inInfo.held, inInfo2.held, - inInfo3.held, inInfo4.held, inInfo5.active])) - // Maximum number of conference participants is 5. - .then(() => handleConferenceAddError(inCall5)) - .then(() => gRemoteHangUpCalls([outCall, inCall, inCall2, inCall3, inCall4, - inCall5])); -} - -// Start the test -startTest(function() { - testConferenceAddError() - .catch(error => ok(false, "Promise reject: " + error)) - .then(finish); -}); diff --git a/dom/telephony/test/marionette/test_conference_add_twice_error.js b/dom/telephony/test/marionette/test_conference_add_twice_error.js deleted file mode 100644 index 28dbb23dc52b..000000000000 --- a/dom/telephony/test/marionette/test_conference_add_twice_error.js +++ /dev/null @@ -1,48 +0,0 @@ -/* Any copyright is dedicated to the Public Domain. - * http://creativecommons.org/publicdomain/zero/1.0/ */ - -MARIONETTE_TIMEOUT = 60000; -MARIONETTE_HEAD_JS = 'head.js'; - -function testConferenceTwoCallsTwice() { - log('= testConferenceTwoCallsTwice ='); - - let outCall; - let inCall; - let outNumber = "5555550101"; - let inNumber = "5555550201"; - let outInfo = gOutCallStrPool(outNumber); - let inInfo = gInCallStrPool(inNumber); - - return Promise.resolve() - .then(gCheckInitialState) - .then(() => gDial(outNumber)) - .then(call => { outCall = call; }) - .then(() => gCheckAll(outCall, [outCall], '', [], [outInfo.ringing])) - .then(() => gRemoteAnswer(outCall)) - .then(() => gCheckAll(outCall, [outCall], '', [], [outInfo.active])) - .then(() => gRemoteDial(inNumber)) - .then(call => { inCall = call; }) - .then(() => gCheckAll(outCall, [outCall, inCall], '', [], - [outInfo.active, inInfo.waiting])) - .then(() => gAnswer(inCall)) - .then(() => gCheckAll(inCall, [outCall, inCall], '', [], - [outInfo.held, inInfo.active])) - .then(() => gAddCallsToConference([outCall, inCall], function() { - gCheckState(conference, - [], 'connected', - [outCall, inCall]); })) - .then(() => conference.add(outCall, inCall)) - .then(() => ok(false, "The second |conference.add()| should be rejected"), - () => log("The second |conference.add()| is rejected as expected")) - .then(() => gCheckAll(conference, [], 'connected', [outCall, inCall], - [outInfo.active, inInfo.active])) - .then(() => gRemoteHangUpCalls([outCall, inCall])); -} - -// Start the test -startTest(function() { - testConferenceTwoCallsTwice() - .catch(error => ok(false, "Promise reject: " + error)) - .then(finish); -}); diff --git a/dom/telephony/test/marionette/test_conference_remove_error.js b/dom/telephony/test/marionette/test_conference_remove_error.js deleted file mode 100644 index cb53c30ef1e5..000000000000 --- a/dom/telephony/test/marionette/test_conference_remove_error.js +++ /dev/null @@ -1,68 +0,0 @@ -/* Any copyright is dedicated to the Public Domain. - * http://creativecommons.org/publicdomain/zero/1.0/ */ - -MARIONETTE_TIMEOUT = 60000; -MARIONETTE_HEAD_JS = 'head.js'; - -function handleConferenceRemoveError(callToRemove) { - log('Handle conference remove error.'); - - let deferred = Promise.defer(); - - conference.onerror = function(evt) { - log('Receiving a conference error event.'); - conference.onerror = null; - - is(evt.name, 'removeError', 'conference removeError'); - - deferred.resolve(); - }; - - return conference.remove(callToRemove) - .then(() => ok(false, "|conference.remove()| should be rejected"), - () => log("|conference.remove()| is rejected as expected")) - .then(() => deferred.promise); -} - -function testConferenceRemoveError() { - log('= testConferenceRemoveError ='); - - let outCall; - let inCall; - let inCall2; - let outNumber = "5555550101"; - let inNumber = "5555550201"; - let inNumber2 = "5555550202"; - let outInfo = gOutCallStrPool(outNumber); - let inInfo = gInCallStrPool(inNumber); - let inInfo2 = gInCallStrPool(inNumber2); - - return Promise.resolve() - .then(() => gSetupConference([outNumber, inNumber])) - .then(calls => { - [outCall, inCall] = calls; - }) - .then(() => gRemoteDial(inNumber2)) - .then(call => {inCall2 = call;}) - .then(() => gCheckAll(conference, [inCall2], 'connected', [outCall, inCall], - [outInfo.active, inInfo.active, inInfo2.waiting])) - .then(() => gAnswer(inCall2, function() { - gCheckState(inCall2, [inCall2], 'held', [outCall, inCall]); - })) - .then(() => gCheckAll(inCall2, [inCall2], 'held', [outCall, inCall], - [outInfo.held, inInfo.held, inInfo2.active])) - .then(() => gResumeConference([outCall, inCall], function() { - gCheckState(conference, [inCall2], 'connected', [outCall, inCall]); - })) - // Not allowed to remove a call when there are one connected and one held - // calls. - .then(() => handleConferenceRemoveError(outCall)) - .then(() => gRemoteHangUpCalls([outCall, inCall, inCall2])); -} - -// Start the test -startTest(function() { - testConferenceRemoveError() - .catch(error => ok(false, "Promise reject: " + error)) - .then(finish); -}); diff --git a/dom/telephony/test/marionette/test_conference_three_hangup_one.js b/dom/telephony/test/marionette/test_conference_three_hangup_one.js deleted file mode 100644 index b262d7ff3c42..000000000000 --- a/dom/telephony/test/marionette/test_conference_three_hangup_one.js +++ /dev/null @@ -1,35 +0,0 @@ -/* Any copyright is dedicated to the Public Domain. - * http://creativecommons.org/publicdomain/zero/1.0/ */ - -MARIONETTE_TIMEOUT = 60000; -MARIONETTE_HEAD_JS = 'head.js'; - -function testConferenceThreeAndHangupOne() { - log('= testConferenceThreeAndHangupOne ='); - - let outCall; - let inCall; - let inCall2; - let outNumber = "5555550101"; - let inNumber = "5555550201"; - let inNumber2 = "5555550202"; - let inInfo = gInCallStrPool(inNumber); - let inInfo2 = gInCallStrPool(inNumber2); - - return Promise.resolve() - .then(() => gSetupConference([outNumber, inNumber, inNumber2])) - .then(calls => { - [outCall, inCall, inCall2] = calls; - }) - .then(() => gHangUpCallInConference(outCall, [], [inCall, inCall2])) - .then(() => gCheckAll(conference, [], 'connected', [inCall, inCall2], - [inInfo.active, inInfo2.active])) - .then(() => gRemoteHangUpCalls([inCall, inCall2])); -} - -// Start the test -startTest(function() { - testConferenceThreeAndHangupOne() - .catch(error => ok(false, "Promise reject: " + error)) - .then(finish); -}); diff --git a/dom/telephony/test/marionette/test_conference_three_remove_one.js b/dom/telephony/test/marionette/test_conference_three_remove_one.js deleted file mode 100644 index 0f365c58730b..000000000000 --- a/dom/telephony/test/marionette/test_conference_three_remove_one.js +++ /dev/null @@ -1,39 +0,0 @@ -/* Any copyright is dedicated to the Public Domain. - * http://creativecommons.org/publicdomain/zero/1.0/ */ - -MARIONETTE_TIMEOUT = 60000; -MARIONETTE_HEAD_JS = 'head.js'; - -function testConferenceThreeAndRemoveOne() { - log('= testConferenceThreeAndRemoveOne ='); - - let outCall; - let inCall; - let inCall2; - let outNumber = "5555550101"; - let inNumber = "5555550201"; - let inNumber2 = "5555550202"; - let outInfo = gOutCallStrPool(outNumber); - let inInfo = gInCallStrPool(inNumber); - let inInfo2 = gInCallStrPool(inNumber2); - - return Promise.resolve() - .then(() => gSetupConference([outNumber, inNumber, inNumber2])) - .then(calls => { - [outCall, inCall, inCall2] = calls; - }) - .then(() => gRemoveCallInConference(outCall, [], [inCall, inCall2], - function() { - gCheckState(outCall, [outCall], 'held', [inCall, inCall2]); - })) - .then(() => gCheckAll(outCall, [outCall], 'held', [inCall, inCall2], - [outInfo.active, inInfo.held, inInfo2.held])) - .then(() => gRemoteHangUpCalls([outCall, inCall, inCall2])); -} - -// Start the test -startTest(function() { - testConferenceThreeAndRemoveOne() - .catch(error => ok(false, "Promise reject: " + error)) - .then(finish); -}); diff --git a/dom/telephony/test/marionette/test_conference_two_calls.js b/dom/telephony/test/marionette/test_conference_two_calls.js deleted file mode 100644 index 1143624ed260..000000000000 --- a/dom/telephony/test/marionette/test_conference_two_calls.js +++ /dev/null @@ -1,28 +0,0 @@ -/* Any copyright is dedicated to the Public Domain. - * http://creativecommons.org/publicdomain/zero/1.0/ */ - -MARIONETTE_TIMEOUT = 60000; -MARIONETTE_HEAD_JS = 'head.js'; - -function testConferenceTwoCalls() { - log('= testConferenceTwoCalls ='); - - let outCall; - let inCall; - let outNumber = "5555550101"; - let inNumber = "5555550201"; - - return Promise.resolve() - .then(() => gSetupConference([outNumber, inNumber])) - .then(calls => { - [outCall, inCall] = calls; - }) - .then(() => gRemoteHangUpCalls([outCall, inCall])); -} - -// Start the test -startTest(function() { - testConferenceTwoCalls() - .catch(error => ok(false, "Promise reject: " + error)) - .then(finish); -}); diff --git a/dom/telephony/test/marionette/test_conference_two_hangup_all.js b/dom/telephony/test/marionette/test_conference_two_hangup_all.js deleted file mode 100644 index d957f1968e1a..000000000000 --- a/dom/telephony/test/marionette/test_conference_two_hangup_all.js +++ /dev/null @@ -1,54 +0,0 @@ -/* Any copyright is dedicated to the Public Domain. - * http://creativecommons.org/publicdomain/zero/1.0/ */ - -MARIONETTE_TIMEOUT = 60000; -MARIONETTE_HEAD_JS = 'head.js'; - -function testConferenceHangUpForeground() { - log('= testConferenceHangUpForeground ='); - - let outCall; - let inCall; - let outNumber = "5555550101"; - let inNumber = "5555550201"; - - return Promise.resolve() - .then(() => gSetupConference([outNumber, inNumber])) - .then(calls => { - [outCall, inCall] = calls; - }) - .then(() => gHangUpConference()) - .then(() => gCheckAll(null, [], '', [], [])); -} - -function testConferenceHangUpBackground() { - log('= testConferenceHangUpBackground ='); - - let outCall; - let inCall; - let outNumber = "5555550101"; - let inNumber = "5555550201"; - let outInfo = gOutCallStrPool(outNumber); - let inInfo = gInCallStrPool(inNumber); - - return Promise.resolve() - .then(() => gSetupConference([outNumber, inNumber])) - .then(calls => { - [outCall, inCall] = calls; - }) - .then(() => gHoldConference([outCall, inCall], function() { - gCheckState(null, [], 'held', [outCall, inCall]); - })) - .then(() => gCheckAll(null, [], 'held', [outCall, inCall], - [outInfo.held, inInfo.held])) - .then(() => gHangUpConference()) - .then(() => gCheckAll(null, [], '', [], [])); -} - -// Start the test -startTest(function() { - testConferenceHangUpForeground() - .then(() => testConferenceHangUpBackground()) - .catch(error => ok(false, "Promise reject: " + error)) - .then(finish); -}); diff --git a/dom/telephony/test/marionette/test_conference_two_hangup_one.js b/dom/telephony/test/marionette/test_conference_two_hangup_one.js deleted file mode 100644 index 1f1d5b505aca..000000000000 --- a/dom/telephony/test/marionette/test_conference_two_hangup_one.js +++ /dev/null @@ -1,33 +0,0 @@ -/* Any copyright is dedicated to the Public Domain. - * http://creativecommons.org/publicdomain/zero/1.0/ */ - -MARIONETTE_TIMEOUT = 60000; -MARIONETTE_HEAD_JS = 'head.js'; - -function testConferenceTwoAndHangupOne() { - log('= testConferenceTwoAndHangupOne ='); - - let outCall; - let inCall; - let outNumber = "5555550101"; - let inNumber = "5555550201"; - let inInfo = gInCallStrPool(inNumber); - - return Promise.resolve() - .then(() => gSetupConference([outNumber, inNumber])) - .then(calls => { - [outCall, inCall] = calls; - }) - .then(() => gHangUpCallInConference(outCall, [inCall], [], function() { - gCheckState(inCall, [inCall], '', []); - })) - .then(() => gCheckAll(inCall, [inCall], '', [], [inInfo.active])) - .then(() => gRemoteHangUpCalls([inCall])); -} - -// Start the test -startTest(function() { - testConferenceTwoAndHangupOne() - .catch(error => ok(false, "Promise reject: " + error)) - .then(finish); -}); diff --git a/dom/telephony/test/marionette/test_conference_two_hold_resume.js b/dom/telephony/test/marionette/test_conference_two_hold_resume.js deleted file mode 100644 index 614506df88f2..000000000000 --- a/dom/telephony/test/marionette/test_conference_two_hold_resume.js +++ /dev/null @@ -1,40 +0,0 @@ -/* Any copyright is dedicated to the Public Domain. - * http://creativecommons.org/publicdomain/zero/1.0/ */ - -MARIONETTE_TIMEOUT = 60000; -MARIONETTE_HEAD_JS = 'head.js'; - -function testConferenceHoldAndResume() { - log('= testConferenceHoldAndResume ='); - - let outCall; - let inCall; - let outNumber = "5555550101"; - let inNumber = "5555550201"; - let outInfo = gOutCallStrPool(outNumber); - let inInfo = gInCallStrPool(inNumber); - - return Promise.resolve() - .then(() => gSetupConference([outNumber, inNumber])) - .then(calls => { - [outCall, inCall] = calls; - }) - .then(() => gHoldConference([outCall, inCall], function() { - gCheckState(null, [], 'held', [outCall, inCall]); - })) - .then(() => gCheckAll(null, [], 'held', [outCall, inCall], - [outInfo.held, inInfo.held])) - .then(() => gResumeConference([outCall, inCall], function() { - gCheckState(conference, [], 'connected', [outCall, inCall]); - })) - .then(() => gCheckAll(conference, [], 'connected', [outCall, inCall], - [outInfo.active, inInfo.active])) - .then(() => gRemoteHangUpCalls([outCall, inCall])); -} - -// Start the test -startTest(function() { - testConferenceHoldAndResume() - .catch(error => ok(false, "Promise reject: " + error)) - .then(finish); -}); diff --git a/dom/telephony/test/marionette/test_conference_two_remove_one.js b/dom/telephony/test/marionette/test_conference_two_remove_one.js deleted file mode 100644 index 8bbb3d565f3a..000000000000 --- a/dom/telephony/test/marionette/test_conference_two_remove_one.js +++ /dev/null @@ -1,35 +0,0 @@ -/* Any copyright is dedicated to the Public Domain. - * http://creativecommons.org/publicdomain/zero/1.0/ */ - -MARIONETTE_TIMEOUT = 60000; -MARIONETTE_HEAD_JS = 'head.js'; - -function testConferenceTwoAndRemoveOne() { - log('= testConferenceTwoAndRemoveOne ='); - - let outCall; - let inCall; - let outNumber = "5555550101"; - let inNumber = "5555550201"; - let outInfo = gOutCallStrPool(outNumber); - let inInfo = gInCallStrPool(inNumber); - - return Promise.resolve() - .then(() => gSetupConference([outNumber, inNumber])) - .then(calls => { - [outCall, inCall] = calls; - }) - .then(() => gRemoveCallInConference(outCall, [inCall], [], function() { - gCheckState(outCall, [outCall, inCall], '', []); - })) - .then(() => gCheckAll(outCall, [outCall, inCall], '', [], - [outInfo.active, inInfo.held])) - .then(() => gRemoteHangUpCalls([outCall, inCall])); -} - -// Start the test -startTest(function() { - testConferenceTwoAndRemoveOne() - .catch(error => ok(false, "Promise reject: " + error)) - .then(finish); -}); diff --git a/dom/telephony/test/marionette/test_consecutive_hold.js b/dom/telephony/test/marionette/test_consecutive_hold.js deleted file mode 100644 index c09c179fd1b8..000000000000 --- a/dom/telephony/test/marionette/test_consecutive_hold.js +++ /dev/null @@ -1,52 +0,0 @@ -/* Any copyright is dedicated to the Public Domain. - * http://creativecommons.org/publicdomain/zero/1.0/ */ - -MARIONETTE_TIMEOUT = 90000; -MARIONETTE_HEAD_JS = 'head.js'; - -const inNumber = "5555552222"; -const inInfo = gInCallStrPool(inNumber); -var inCall; - -startTest(function() { - Promise.resolve() - - // Incoming - .then(() => gRemoteDial(inNumber)) - .then(call => inCall = call) - .then(() => gCheckAll(null, [inCall], "", [], [inInfo.incoming])) - .then(() => is(inCall.disconnectedReason, null)) - - // Answer - .then(() => gAnswer(inCall)) - .then(() => gCheckAll(inCall, [inCall], "", [], [inInfo.active])) - .then(() => is(inCall.disconnectedReason, null)) - - // Disable the Hold function of the emulator, then hold the active call, - // where the hold request will fail and the call will remain active. - .then(() => emulator.runCmd("telephony disable hold")) - .then(() => gHold(inCall)) - .then(() => ok(false, "This hold request should be rejected."), - () => log("This hold request is rejected as expected.")) - .then(() => gCheckAll(inCall, [inCall], "", [], [inInfo.active])) - .then(() => is(inCall.disconnectedReason, null)) - - // Enable the Hold function of the emulator, then hold the active call, - // where the hold request should succeed and the call should become held. - .then(() => emulator.runCmd("telephony enable hold")) - .then(() => gHold(inCall)) - .then(() => log("This hold request is resolved as expected."), - () => ok(false, "This hold request should be resolved.")) - .then(() => gCheckAll(null, [inCall], "", [], [inInfo.held])) - .then(() => is(inCall.disconnectedReason, null)) - - // Hang up the call - .then(() => gHangUp(inCall)) - .then(() => gCheckAll(null, [], "", [], [])) - .then(() => is(inCall.disconnectedReason, "NormalCallClearing")) - - // Clean Up - .catch(error => ok(false, "Promise reject: " + error)) - .then(() => emulator.runCmd("telephony enable hold")) - .then(finish); -}); diff --git a/dom/telephony/test/marionette/test_crash_emulator.js b/dom/telephony/test/marionette/test_crash_emulator.js deleted file mode 100644 index 99b44c1e3abe..000000000000 --- a/dom/telephony/test/marionette/test_crash_emulator.js +++ /dev/null @@ -1,26 +0,0 @@ -/* Any copyright is dedicated to the Public Domain. - * http://creativecommons.org/publicdomain/zero/1.0/ */ - -MARIONETTE_TIMEOUT = 60000; -MARIONETTE_HEAD_JS = 'head.js'; - -startTest(function() { - let outCall; - - gDial("5555551111") - .then(call => outCall = call) - .then(() => gRemoteAnswer(outCall)) - .then(() => { - return new Promise(function(resolve, reject) { - callStartTime = Date.now(); - waitFor(resolve,function() { - callDuration = Date.now() - callStartTime; - log("Waiting while call is active, call duration (ms): " + callDuration); - return(callDuration >= 2000); - }); - }); - }) - .then(() => gHangUp(outCall)) - .catch(error => ok(false, "Promise reject: " + error)) - .then(finish); -}); diff --git a/dom/telephony/test/marionette/test_dsds_connection_conflict.js b/dom/telephony/test/marionette/test_dsds_connection_conflict.js deleted file mode 100644 index ac0d087fb880..000000000000 --- a/dom/telephony/test/marionette/test_dsds_connection_conflict.js +++ /dev/null @@ -1,51 +0,0 @@ -/* Any copyright is dedicated to the Public Domain. - * http://creativecommons.org/publicdomain/zero/1.0/ */ - -MARIONETTE_TIMEOUT = 60000; -MARIONETTE_HEAD_JS = 'head.js'; - -function muxModem(id) { - let deferred = Promise.defer(); - - emulator.runCmdWithCallback("mux modem " + id, function() { - deferred.resolve(); - }); - - return deferred.promise; -} - -function testNewCallWhenOtherConnectionInUse(firstServiceId, secondServiceId) { - log("= testNewCallWhenOtherConnectionInUse ="); - log("1st call on " + firstServiceId + ", 2nd call on " + secondServiceId); - - let outCall; - - return Promise.resolve() - .then(() => muxModem(firstServiceId)) - .then(() => { - return telephony.dial("0912345000", firstServiceId); - }) - .then(call => { - outCall = call; - is(outCall.serviceId, firstServiceId); - }) - .then(() => gRemoteAnswer(outCall)) - .then(() => { - return telephony.dial("0912345001", secondServiceId); - }) - .then(() => { - log("The promise should not be resolved"); - ok(false); - }, cause => { - is(cause, "OtherConnectionInUse"); - }) - .then(() => gRemoteHangUp(outCall)); -} - -startDSDSTest(function() { - testNewCallWhenOtherConnectionInUse(0, 1) - .then(() => testNewCallWhenOtherConnectionInUse(1, 0)) - .then(() => muxModem(0)) - .catch(error => ok(false, "Promise reject: " + error)) - .then(finish); -}); diff --git a/dom/telephony/test/marionette/test_dsds_normal_call.js b/dom/telephony/test/marionette/test_dsds_normal_call.js deleted file mode 100644 index ea03ef4576a0..000000000000 --- a/dom/telephony/test/marionette/test_dsds_normal_call.js +++ /dev/null @@ -1,78 +0,0 @@ -/* Any copyright is dedicated to the Public Domain. - * http://creativecommons.org/publicdomain/zero/1.0/ */ - -MARIONETTE_TIMEOUT = 60000; -MARIONETTE_HEAD_JS = 'head.js'; - -function muxModem(id) { - let deferred = Promise.defer(); - - emulator.runCmdWithCallback("mux modem " + id, function() { - deferred.resolve(); - }); - - return deferred.promise; -} - -function testOutgoingCallForServiceId(number, serviceId) { - let outCall; - let outInfo = gOutCallStrPool(number); - - return Promise.resolve() - .then(() => gDial(number, serviceId)) - .then(call => { - outCall = call; - is(outCall.serviceId, serviceId); - }) - .then(() => gCheckAll(outCall, [outCall], '', [], [outInfo.ringing])) - .then(() => gRemoteAnswer(outCall)) - .then(() => gCheckAll(outCall, [outCall], '', [], [outInfo.active])) - .then(() => gRemoteHangUp(outCall)) - .then(() => gCheckAll(null, [], '', [], [])); -} - -function testIncomingCallForServiceId(number, serviceId) { - let inCall; - let inInfo = gInCallStrPool(number); - - return Promise.resolve() - .then(() => gRemoteDial(number)) - .then(call => { - inCall = call; - is(inCall.serviceId, serviceId); - }) - .then(() => gCheckAll(null, [inCall], '', [], [inInfo.incoming])) - .then(() => gAnswer(inCall)) - .then(() => gCheckAll(inCall, [inCall], '', [], [inInfo.active])) - .then(() => gRemoteHangUp(inCall)) - .then(() => gCheckAll(null, [], '', [], [])); -} - -function testOutgoingCall() { - log("= testOutgoingCall ="); - - return Promise.resolve() - .then(() => muxModem(0)) - .then(() => testOutgoingCallForServiceId("0912345000", 0)) - .then(() => muxModem(1)) - .then(() => testOutgoingCallForServiceId("0912345001", 1)) - .then(() => muxModem(0)); -} - -function testIncomingCall() { - log("= testIncomingCall ="); - - return Promise.resolve() - .then(() => muxModem(0)) - .then(() => testIncomingCallForServiceId("0912345000", 0)) - .then(() => muxModem(1)) - .then(() => testIncomingCallForServiceId("0912345001", 1)) - .then(() => muxModem(0)); -} - -startDSDSTest(function() { - testOutgoingCall() - .then(testIncomingCall) - .catch(error => ok(false, "Promise reject: " + error)) - .then(finish); -}); diff --git a/dom/telephony/test/marionette/test_dtmf.js b/dom/telephony/test/marionette/test_dtmf.js deleted file mode 100644 index 644609440577..000000000000 --- a/dom/telephony/test/marionette/test_dtmf.js +++ /dev/null @@ -1,69 +0,0 @@ -/* Any copyright is dedicated to the Public Domain. - * http://creativecommons.org/publicdomain/zero/1.0/ */ - -MARIONETTE_TIMEOUT = 60000; -MARIONETTE_HEAD_JS = 'head.js'; - -function muxModem(id) { - return new Promise((resolve, reject) => { - emulator.runCmdWithCallback("mux modem " + id, resolve); - }); -} - -function testDtmfNoActiveCall() { - log("= testDtmfNoActiveCall ="); - return new Promise((resolve, reject) => { - gSendTone('1', 5, 0).then(() => { - log("Unexpected success. We cannot send a DTMF without an active call"); - reject(); - }, resolve); - }); -} - -function testDtmfDsds() { - log("= testDtmfDsds ="); - - let outCall; - let number = "0912345000"; - let serviceId = 0; - let otherServiceId = 1; - - return Promise.resolve() - .then(() => muxModem(serviceId)) - .then(() => gDial(number, serviceId)) - .then(call => { - outCall = call; - is(outCall.serviceId, serviceId); - }) - .then(() => gRemoteAnswer(outCall)) - // Send tone with correct serviceId. - .then(() => gSendTone('1', 5, serviceId)) - .then(() => emulator.runCmd("modem dtmf")) - .then(tone => { - is(tone, '1,OK', 'Sent tone is 1'); - }) - // Send tone without serviceId. - .then(() => gSendTone('2', 5)) - .then(() => emulator.runCmd("modem dtmf")) - .then(tone => { - is(tone, '2,OK', 'Sent tone is 2'); - }) - // Send tone with incorrect serviceId. - .then(gSendTone('1', 5, otherServiceId).catch((e) => { - log('Expected Error ' + e); - gRemoteHangUp(outCall); - }) - ) - .catch((e) => { - log('Unexpected Error ' + e); - ok(false); - }); -} - -startDSDSTest(function() { - testDtmfNoActiveCall() - .then(testDtmfDsds) - .then(emulator.runCmd("modem dtmf reset")) - .catch(error => ok(false, "Promise reject: " + error)) - .then(finish); -}); diff --git a/dom/telephony/test/marionette/test_emergency.js b/dom/telephony/test/marionette/test_emergency.js deleted file mode 100644 index 810e56a193c4..000000000000 --- a/dom/telephony/test/marionette/test_emergency.js +++ /dev/null @@ -1,39 +0,0 @@ -/* Any copyright is dedicated to the Public Domain. - * http://creativecommons.org/publicdomain/zero/1.0/ */ - -MARIONETTE_TIMEOUT = 60000; -MARIONETTE_HEAD_JS = 'head.js'; - -var outCall; - -function testEmergencyNumber() { - return gDialEmergency("911") - .then(call => outCall = call) - .then(() => gRemoteAnswer(outCall)) - .then(() => gHangUp(outCall)); -} - -function testNormalNumber() { - return gDialEmergency("0912345678") - .catch(cause => { - is(cause, "BadNumberError"); - return gCheckAll(null, [], "", [], []); - }); -} - -function testBadNumber() { - return gDialEmergency("not a valid emergency number") - .catch(cause => { - is(cause, "BadNumberError"); - return gCheckAll(null, [], "", [], []); - }); -} - -startTest(function() { - Promise.resolve() - .then(() => testEmergencyNumber()) - .then(() => testNormalNumber()) - .then(() => testBadNumber()) - .catch(error => ok(false, "Promise reject: " + error)) - .then(finish); -}); diff --git a/dom/telephony/test/marionette/test_emergency_label.js b/dom/telephony/test/marionette/test_emergency_label.js deleted file mode 100644 index 1cb4f3fd40b0..000000000000 --- a/dom/telephony/test/marionette/test_emergency_label.js +++ /dev/null @@ -1,72 +0,0 @@ -/* Any copyright is dedicated to the Public Domain. - * http://creativecommons.org/publicdomain/zero/1.0/ */ - -MARIONETTE_TIMEOUT = 60000; -MARIONETTE_HEAD_JS = 'head.js'; - -const DEFAULT_ECC_LIST = "112,911"; - -function setEccListProperty(list) { - log("Set property ril.ecclist: " + list); - - // We should wrap empty |list| by ''. Otherwise, the entire command will be - // "setprop ril.ecclist" which causus the command error. - if (!list) { - list = "''"; - } - - return emulator.runShellCmd(["setprop","ril.ecclist", list]) - .then(list => list); -} - -function getEccListProperty() { - log("Get property ril.ecclist."); - - return emulator.runShellCmd(["getprop","ril.ecclist"]) - .then(aResult => { - return !aResult.length ? "" : aResult[0]; - }); -} - -function testEmergencyLabel(number, list) { - if (!list) { - list = DEFAULT_ECC_LIST; - } - let index = list.split(",").indexOf(number); - let emergency = index != -1; - log("= testEmergencyLabel = " + number + " should be " + - (emergency ? "emergency" : "normal") + " call"); - - let outCall; - - return gDial(number) - .then(call => outCall = call) - .then(() => is(outCall.emergency, emergency, "check emergency")) - .then(() => gRemoteAnswer(outCall)) - .then(() => is(outCall.emergency, emergency, "check emergency")) - .then(() => gRemoteHangUp(outCall)); -} - -startTest(function() { - let origEccList; - let eccList; - - getEccListProperty() - .then(list => { - origEccList = eccList = list; - }) - .then(() => testEmergencyLabel("112", eccList)) - .then(() => testEmergencyLabel("911", eccList)) - .then(() => testEmergencyLabel("0912345678", eccList)) - .then(() => testEmergencyLabel("777", eccList)) - .then(() => { - eccList = "777,119"; - return setEccListProperty(eccList); - }) - .then(() => testEmergencyLabel("777", eccList)) - .then(() => testEmergencyLabel("119", eccList)) - .then(() => testEmergencyLabel("112", eccList)) - .then(() => setEccListProperty(origEccList)) - .catch(error => ok(false, "Promise reject: " + error)) - .then(finish); -}); diff --git a/dom/telephony/test/marionette/test_gsm_cdma_incoming_basic_operations.js b/dom/telephony/test/marionette/test_gsm_cdma_incoming_basic_operations.js deleted file mode 100644 index cf4fe6f60c9f..000000000000 --- a/dom/telephony/test/marionette/test_gsm_cdma_incoming_basic_operations.js +++ /dev/null @@ -1,170 +0,0 @@ -/* Any copyright is dedicated to the Public Domain. - * http://creativecommons.org/publicdomain/zero/1.0/ */ - -MARIONETTE_TIMEOUT = 90000; -MARIONETTE_HEAD_JS = 'head.js'; - -/****************************************************************************** - **** Basic Operations **** - ******************************************************************************/ - -const IncomingNumber = "1111110000"; - -function exptectedCall(aCall, aState, aEmulatorState = null) { - let disconnectedReason = aState === "disconnected" ? "NormalCallClearing" - : null; - - return TelephonyHelper.createExptectedCall(aCall, IncomingNumber, false, - "in", aState, aEmulatorState, - disconnectedReason); -} - -function incoming(aNumber) { - let ret; - return Remote.dial(aNumber) - .then(call => ret = call) - .then(() => TelephonyHelper.equals([exptectedCall(ret, "incoming")])) - .then(() => ret); -} - -function answer(aCall) { - let call = exptectedCall(aCall, "connected"); - return TelephonyHelper.answer(aCall) - .then(() => TelephonyHelper.equals([call])) - .then(() => aCall); -} - -function hold(aCall) { - // Since a CDMA call doesn't have any notification for its state changing to - // "held" state, a telephonyCall is still remains in "connected" state when - // the call actually goes to "held" state, and we shouldn't wait for the state - // change event here. - let state = Modem.isGSM() ? "held" : "connected"; - let call = exptectedCall(aCall, state,"held"); - return TelephonyHelper.hold(aCall, Modem.isGSM()) - .then(() => TelephonyHelper.equals([call])) - .then(() => aCall); -} - -function resume(aCall) { - // Similar to the hold case, there is no notification for a CDMA call's state - // change. Besides, a CDMA call still remains in "connected" state here, so we - // have to use |hold()| function here to resume the call. Otherwise, if we use - // |resume()| function, we'll get an invalid state error. - let call = exptectedCall(aCall, "connected"); - return Modem.isGSM() ? TelephonyHelper.resume(aCall) - : TelephonyHelper.hold(aCall, false) - .then(() => TelephonyHelper.equals([call])) - .then(() => aCall); -} - -function hangUp(aCall) { - let call = exptectedCall(aCall, "disconnected"); - return TelephonyHelper.hangUp(aCall) - .then(() => TelephonyHelper.equals([call])) - .then(() => aCall); -} - -function remoteHangUp(aCall) { - let call = exptectedCall(aCall, "disconnected"); - return Remote.hangUp(aCall) - .then(() => TelephonyHelper.equals([call])) - .then(() => aCall); -} - -/****************************************************************************** - **** Testcases **** - ******************************************************************************/ - -function testIncomingReject() { - log("= testIncomingReject ="); - return incoming(IncomingNumber) - .then(call => hangUp(call)); -} - -function testIncomingCancel() { - log("= testIncomingCancel ="); - return incoming(IncomingNumber) - .then(call => remoteHangUp(call)); -} - -function testIncomingAnswerHangUp() { - log("= testIncomingAnswerHangUp ="); - return incoming(IncomingNumber) - .then(call => answer(call)) - .then(call => hangUp(call)); -} - -function testIncomingAnswerRemoteHangUp() { - log("= testIncomingAnswerRemoteHangUp ="); - return incoming(IncomingNumber) - .then(call => answer(call)) - .then(call => remoteHangUp(call)); -} - -function testIncomingAnswerHoldHangUp() { - log("= testIncomingAnswerHoldHangUp ="); - return incoming(IncomingNumber) - .then(call => answer(call)) - .then(call => hold(call)) - .then(call => hangUp(call)); -} - -function testIncomingAnswerHoldRemoteHangUp() { - log("= testIncomingAnswerHoldRemoteHangUp ="); - return incoming(IncomingNumber) - .then(call => answer(call)) - .then(call => hold(call)) - .then(call => remoteHangUp(call)); -} - -function testIncomingAnswerHoldResumeHangUp() { - log("= testIncomingAnswerHoldResumeHangUp ="); - return incoming(IncomingNumber) - .then(call => answer(call)) - .then(call => hold(call)) - .then(call => resume(call)) - .then(call => hangUp(call)); -} - -function testIncomingAnswerHoldResumeRemoteHangUp() { - log("= testIncomingAnswerHoldResumeRemoteHangUp ="); - return incoming(IncomingNumber) - .then(call => answer(call)) - .then(call => hold(call)) - .then(call => resume(call)) - .then(call => remoteHangUp(call)); -} - -/****************************************************************************** - **** Test Launcher **** - ******************************************************************************/ - -function runTestSuite(aTech, aTechMask) { - return Promise.resolve() - // Setup Environment - .then(() => Modem.changeTech(aTech, aTechMask)) - - // Tests - .then(() => testIncomingReject()) - .then(() => testIncomingCancel()) - .then(() => testIncomingAnswerHangUp()) - .then(() => testIncomingAnswerRemoteHangUp()) - .then(() => testIncomingAnswerHoldHangUp()) - .then(() => testIncomingAnswerHoldRemoteHangUp()) - .then(() => testIncomingAnswerHoldResumeHangUp()) - .then(() => testIncomingAnswerHoldResumeRemoteHangUp()) - - // Restore Environment - .then(() => Modem.changeTech("wcdma")); -} - -startTest(function() { - return Promise.resolve() - .then(() => runTestSuite("cdma")) - .then(() => runTestSuite("wcdma")) - - .catch(error => ok(false, "Promise reject: " + error)) - .then(finish); -}); - diff --git a/dom/telephony/test/marionette/test_gsm_cdma_outgoing_basic_operations.js b/dom/telephony/test/marionette/test_gsm_cdma_outgoing_basic_operations.js deleted file mode 100644 index b53f4478c4f9..000000000000 --- a/dom/telephony/test/marionette/test_gsm_cdma_outgoing_basic_operations.js +++ /dev/null @@ -1,174 +0,0 @@ -/* Any copyright is dedicated to the Public Domain. - * http://creativecommons.org/publicdomain/zero/1.0/ */ - -MARIONETTE_TIMEOUT = 90000; -MARIONETTE_HEAD_JS = 'head.js'; - -/****************************************************************************** - **** Basic Operations **** - ******************************************************************************/ - -const OutgoingNumber = "5555551111"; - -function exptectedCall(aCall, aState, aEmulatorState = null) { - let disconnectedReason = aState === "disconnected" ? "NormalCallClearing" - : null; - - return TelephonyHelper.createExptectedCall(aCall, OutgoingNumber, false, - "out", aState, aEmulatorState, - disconnectedReason); -} - -function outgoing(aNumber) { - let ret; - - // Since a CDMA call doesn't have "alerting" state, it directly goes to - // "connected" state instead. - let state = Modem.isCDMA() ? "connected" : "alerting"; - return TelephonyHelper.dial(aNumber) - .then(call => ret = call) - .then(() => TelephonyHelper.equals([exptectedCall(ret, state)])) - .then(() => ret); -} - -function remoteAnswer(aCall) { - let call = exptectedCall(aCall, "connected"); - return Remote.answer(aCall) - .then(() => TelephonyHelper.equals([call])) - .then(() => aCall); -} - -function hold(aCall) { - // Since a CDMA call doesn't have any notification for its state changing to - // "held" state, a telephonyCall is still remains in "connected" state when - // the call actually goes to "held" state, and we shouldn't wait for the state - // change event here. - let state = Modem.isGSM() ? "held" : "connected"; - let call = exptectedCall(aCall, state, "held"); - return TelephonyHelper.hold(aCall, Modem.isGSM()) - .then(() => TelephonyHelper.equals([call])) - .then(() => aCall); -} - -function resume(aCall) { - // Similar to the hold case, there is no notification for a CDMA call's state - // change. Besides, a CDMA call still remains in "connected" state here, so we - // have to use |hold()| function here to resume the call. Otherwise, if we use - // |resume()| function, we'll get an invalid state error. - let call = exptectedCall(aCall, "connected"); - return Modem.isGSM() ? TelephonyHelper.resume(aCall) - : TelephonyHelper.hold(aCall, false) - .then(() => TelephonyHelper.equals([call])) - .then(() => aCall); -} - -function hangUp(aCall) { - let call = exptectedCall(aCall, "disconnected"); - return TelephonyHelper.hangUp(aCall) - .then(() => TelephonyHelper.equals([call])) - .then(() => aCall); -} - -function remoteHangUp(aCall) { - let call = exptectedCall(aCall, "disconnected"); - return Remote.hangUp(aCall) - .then(() => TelephonyHelper.equals([call])) - .then(() => aCall); -} - -/****************************************************************************** - **** Testcases **** - ******************************************************************************/ - -function testOutgoingReject() { - log("= testOutgoingReject ="); - return outgoing(OutgoingNumber) - .then(call => remoteHangUp(call)); -} - -function testOutgoingCancel() { - log("= testOutgoingCancel ="); - return outgoing(OutgoingNumber) - .then(call => hangUp(call)); -} - -function testOutgoingAnswerHangUp() { - log("= testOutgoingAnswerHangUp ="); - return outgoing(OutgoingNumber) - .then(call => remoteAnswer(call)) - .then(call => hangUp(call)); -} - -function testOutgoingAnswerRemoteHangUp() { - log("= testOutgoingAnswerRemoteHangUp ="); - return outgoing(OutgoingNumber) - .then(call => remoteAnswer(call)) - .then(call => remoteHangUp(call)); -} - -function testOutgoingAnswerHoldHangUp() { - log("= testOutgoingAnswerHoldHangUp ="); - return outgoing(OutgoingNumber) - .then(call => remoteAnswer(call)) - .then(call => hold(call)) - .then(call => hangUp(call)); -} - -function testOutgoingAnswerHoldRemoteHangUp() { - log("= testOutgoingAnswerHoldRemoteHangUp ="); - return outgoing(OutgoingNumber) - .then(call => remoteAnswer(call)) - .then(call => hold(call)) - .then(call => remoteHangUp(call)); -} - -function testOutgoingAnswerHoldResumeHangUp() { - log("= testOutgoingAnswerHoldResumeHangUp ="); - return outgoing(OutgoingNumber) - .then(call => remoteAnswer(call)) - .then(call => hold(call)) - .then(call => resume(call)) - .then(call => hangUp(call)); -} - -function testOutgoingAnswerHoldResumeRemoteHangUp() { - log("= testOutgoingAnswerHoldResumeRemoteHangUp ="); - return outgoing(OutgoingNumber) - .then(call => remoteAnswer(call)) - .then(call => hold(call)) - .then(call => resume(call)) - .then(call => remoteHangUp(call)); -} - -/******************************************************************************/ -/*** Test Launcher ***/ -/******************************************************************************/ - -function runTestSuite(aTech, aTechMask) { - return Promise.resolve() - // Setup Environment - .then(() => Modem.changeTech(aTech, aTechMask)) - - // Tests - .then(() => testOutgoingReject()) - .then(() => testOutgoingCancel()) - .then(() => testOutgoingAnswerHangUp()) - .then(() => testOutgoingAnswerRemoteHangUp()) - .then(() => testOutgoingAnswerHoldHangUp()) - .then(() => testOutgoingAnswerHoldRemoteHangUp()) - .then(() => testOutgoingAnswerHoldResumeHangUp()) - .then(() => testOutgoingAnswerHoldResumeRemoteHangUp()) - - // Restore Environment - .then(() => Modem.changeTech("wcdma")); -} - -startTest(function() { - return Promise.resolve() - .then(() => runTestSuite("cdma")) - .then(() => runTestSuite("wcdma")) - - .catch(error => ok(false, "Promise reject: " + error)) - .then(finish); -}); - diff --git a/dom/telephony/test/marionette/test_incall_mmi_call_hold.js b/dom/telephony/test/marionette/test_incall_mmi_call_hold.js deleted file mode 100644 index 48d7cf082f9d..000000000000 --- a/dom/telephony/test/marionette/test_incall_mmi_call_hold.js +++ /dev/null @@ -1,88 +0,0 @@ -/* Any copyright is dedicated to the Public Domain. - * http://creativecommons.org/publicdomain/zero/1.0/ */ - -MARIONETTE_TIMEOUT = 60000; -MARIONETTE_HEAD_JS = 'head.js'; - -const call1Number = "0900000001"; -const call2Number = "0900000002"; -const call1Info = gOutCallStrPool(call1Number); -const call2Info = gOutCallStrPool(call2Number); - -// call1 is held, call2 is active -function setupTwoCalls() { - let call1; - let call2; - - return gDial(call1Number) - .then(call => call1 = call) - .then(() => gRemoteAnswer(call1)) - .then(() => gDial(call2Number)) - .then(call => call2 = call) - .then(() => gRemoteAnswer(call2)) - .then(() => gCheckAll(call2, [call1, call2], "", [], - [call1Info.held, call2Info.active])) - .then(() => [call1, call2]); -} - -function testInCallMMI_0() { - log('= testInCallMMI_0 ='); - - return setupTwoCalls() - .then(calls => [call1, call2] = calls) - // Hangup held call. - .then(() => gSendMMI("0")) - .then(() => gWaitForNamedStateEvent(call1, "disconnected")) - .then(() => gCheckAll(call2, [call2], "", [], [call2Info.active])) - .then(() => gRemoteHangUpCalls([call2])); -} - -function testInCallMMI_1() { - log('= testInCallMMI_1 ='); - - return setupTwoCalls() - .then(calls => [call1, call2] = calls) - // Hangup current call, resume held call. - .then(() => gSendMMI("1")) - .then(() => { - let p1 = gWaitForNamedStateEvent(call1, "connected"); - let p2 = gWaitForNamedStateEvent(call2, "disconnected"); - return Promise.all([p1, p2]); - }) - .then(() => gCheckAll(call1, [call1], "", [], [call1Info.active])) - .then(() => gRemoteHangUpCalls([call1])); -} - -function testInCallMMI_2() { - log('= testInCallMMI_2 ='); - - return setupTwoCalls() - .then(calls => [call1, call2] = calls) - // Hold current call, resume held call. - .then(() => gSendMMI("2")) - .then(() => { - let p1 = gWaitForNamedStateEvent(call1, "connected"); - let p2 = gWaitForNamedStateEvent(call2, "held"); - return Promise.all([p1, p2]); - }) - .then(() => gCheckAll(call1, [call1, call2], "", [], - [call1Info.active, call2Info.held])) - // Hold current call, resume held call. - .then(() => gSendMMI("2")) - .then(() => { - let p1 = gWaitForNamedStateEvent(call1, "held"); - let p2 = gWaitForNamedStateEvent(call2, "connected"); - return Promise.all([p1, p2]); - }) - .then(() => gCheckAll(call2, [call1, call2], "", [], - [call1Info.held, call2Info.active])) - .then(() => gRemoteHangUpCalls([call1, call2])); -} - -startTest(function() { - testInCallMMI_0() - .then(() => testInCallMMI_1()) - .then(() => testInCallMMI_2()) - .catch(error => ok(false, "Promise reject: " + error)) - .then(finish); -}); diff --git a/dom/telephony/test/marionette/test_incall_mmi_call_waiting.js b/dom/telephony/test/marionette/test_incall_mmi_call_waiting.js deleted file mode 100644 index ea94ef9d8eee..000000000000 --- a/dom/telephony/test/marionette/test_incall_mmi_call_waiting.js +++ /dev/null @@ -1,77 +0,0 @@ -/* Any copyright is dedicated to the Public Domain. - * http://creativecommons.org/publicdomain/zero/1.0/ */ - -MARIONETTE_TIMEOUT = 60000; -MARIONETTE_HEAD_JS = 'head.js'; - -const outNumber = "0900000001"; -const inNumber = "0900000002"; -const outInfo = gOutCallStrPool(outNumber); -const inInfo = gInCallStrPool(inNumber); - -function setupTwoCalls() { - let outCall; - let inCall; - - return gDial(outNumber) - .then(call => outCall = call) - .then(() => gRemoteAnswer(outCall)) - .then(() => gRemoteDial(inNumber)) - .then(call => inCall = call) - .then(() => gCheckAll(outCall, [outCall, inCall], "", [], - [outInfo.active, inInfo.waiting])) - .then(() => [outCall, inCall]); -} - -function testInCallMMI_0() { - log('= testInCallMMI_0 ='); - - return setupTwoCalls() - .then(calls => [outCall, inCall] = calls) - // Hangup waiting call. - .then(() => gSendMMI("0")) - .then(() => gWaitForNamedStateEvent(inCall, "disconnected")) - .then(() => gCheckAll(outCall, [outCall], "", [], [outInfo.active])) - .then(() => gRemoteHangUpCalls([outCall])); -} - -function testInCallMMI_1() { - log('= testInCallMMI_1 ='); - - return setupTwoCalls() - .then(calls => [outCall, inCall] = calls) - // Hangup current call, accept waiting call. - .then(() => gSendMMI("1")) - .then(() => { - let p1 = gWaitForNamedStateEvent(outCall, "disconnected"); - let p2 = gWaitForNamedStateEvent(inCall, "connected"); - return Promise.all([p1, p2]); - }) - .then(() => gCheckAll(inCall, [inCall], "", [], [inInfo.active])) - .then(() => gRemoteHangUpCalls([inCall])); -} - -function testInCallMMI_2() { - log('= testInCallMMI_2 ='); - - return setupTwoCalls() - .then(calls => [outCall, inCall] = calls) - // Hold current call, accept waiting call. - .then(() => gSendMMI("2")) - .then(() => { - let p1 = gWaitForNamedStateEvent(outCall, "held"); - let p2 = gWaitForNamedStateEvent(inCall, "connected"); - return Promise.all([p1, p2]); - }) - .then(() => gCheckAll(inCall, [outCall, inCall], "", [], - [outInfo.held, inInfo.active])) - .then(() => gRemoteHangUpCalls([outCall, inCall])); -} - -startTest(function() { - testInCallMMI_0() - .then(() => testInCallMMI_1()) - .then(() => testInCallMMI_2()) - .catch(error => ok(false, "Promise reject: " + error)) - .then(finish); -}); diff --git a/dom/telephony/test/marionette/test_incall_mmi_conference.js b/dom/telephony/test/marionette/test_incall_mmi_conference.js deleted file mode 100644 index aff749d0e81a..000000000000 --- a/dom/telephony/test/marionette/test_incall_mmi_conference.js +++ /dev/null @@ -1,90 +0,0 @@ -/* Any copyright is dedicated to the Public Domain. - * http://creativecommons.org/publicdomain/zero/1.0/ */ - -MARIONETTE_TIMEOUT = 60000; -MARIONETTE_HEAD_JS = 'head.js'; - -const call1Number = "0900000001"; -const call2Number = "0900000002"; -const call3Number = "0900000003"; -const call1Info = gOutCallStrPool(call1Number); -const call2Info = gOutCallStrPool(call2Number); -const call3Info = gOutCallStrPool(call3Number); - -function setupTwoCalls() { - let call1; - let call2; - - return gDial(call1Number) - .then(call => call1 = call) - .then(() => gRemoteAnswer(call1)) - .then(() => gDial(call2Number)) - .then(call => call2 = call) - .then(() => gRemoteAnswer(call2)) - .then(() => gCheckAll(call2, [call1, call2], "", [], - [call1Info.held, call2Info.active])) - .then(() => [call1, call2]); -} - -function testInCallMMI() { - log('= testInCallMMI ='); - - return setupTwoCalls() - .then(calls => [call1, call2] = calls) - // Conference two calls. - .then(() => log("- Conference two calls.")) - .then(() => gSendMMI("3")) - .then(() => gWaitForNamedStateEvent(conference, "connected")) - .then(() => gCheckAll(conference, [], "connected", [call1, call2], - [call1Info.active, call2Info.active])) - - // Make third call. - .then(() => log("- Make third call.")) - .then(() => gDial(call3Number)) - .then(call => call3 = call) - .then(() => gRemoteAnswer(call3)) - .then(() => gCheckAll(call3, [call3], "held", [call1, call2], - [call1Info.held, call2Info.held, call3Info.active])) - - // Enlarge the conference. - .then(() => log("- Enlarge the conference.")) - .then(() => gSendMMI("3")) - .then(() => gWaitForNamedStateEvent(conference, "connected")) - .then(() => gCheckAll(conference, [], "connected", [call1, call2, call3], - [call1Info.active, call2Info.active, call3Info.active])) - - // Separate call 2. - .then(() => log("- Separate call 2.")) - .then(() => gSendMMI("22")) - .then(() => gWaitForNamedStateEvent(conference, "held")) - .then(() => gCheckAll(call2, [call2], "held", [call1, call3], - [call1Info.held, call2Info.active, call3Info.held])) - - // Switch active. - .then(() => log("- Switch active.")) - .then(() => gSendMMI("2")) - .then(() => gWaitForNamedStateEvent(conference, "connected")) - .then(() => gCheckAll(conference, [call2], "connected", [call1, call3], - [call1Info.active, call2Info.held, call3Info.active])) - - // Release call 2. - .then(() => log("- Release call 2.")) - .then(() => gSendMMI("12")) - .then(() => gWaitForNamedStateEvent(call2, "disconnected")) - .then(() => gCheckAll(conference, [], "connected", [call1, call3], - [call1Info.active, call3Info.active])) - - // Release call 1. - .then(() => log("- Release call 1.")) - .then(() => gSendMMI("11")) - .then(() => gWaitForStateChangeEvent(conference, "")) - .then(() => gCheckAll(call3, [call3], "", [], [call3Info.active])) - - .then(() => gRemoteHangUpCalls([call3])); -} - -startTest(function() { - testInCallMMI() - .catch(error => ok(false, "Promise reject: " + error)) - .then(finish); -}); diff --git a/dom/telephony/test/marionette/test_incall_mmi_imei.js b/dom/telephony/test/marionette/test_incall_mmi_imei.js deleted file mode 100644 index 8c0506c80aee..000000000000 --- a/dom/telephony/test/marionette/test_incall_mmi_imei.js +++ /dev/null @@ -1,38 +0,0 @@ -/* Any copyright is dedicated to the Public Domain. - * http://creativecommons.org/publicdomain/zero/1.0/ */ - -MARIONETTE_TIMEOUT = 60000; -MARIONETTE_HEAD_JS = 'head.js'; - -const number = "0900000001"; -var outCall; - -function getIMEI() { - log("Test *#06# ..."); - - return gSendMMI("*#06#").then(aResult => { - ok(aResult.success, "success"); - is(aResult.serviceCode, "scImei", "Service code IMEI"); - // IMEI is hardcoded as "000000000000000". - // See it here {B2G_HOME}/external/qemu/telephony/android_modem.c - // (The aResult of +CGSN). - is(aResult.statusMessage, "000000000000000", "Emulator IMEI"); - is(aResult.additionalInformation, undefined, "No additional information"); - }); -} - -function testInCallMMI_IMEI() { - log('= testInCallMMI_IMEI ='); - - return gDial(number) - .then(call => outCall = call) - .then(() => gRemoteAnswer(outCall)) - .then(() => getIMEI()) - .then(() => gRemoteHangUpCalls([outCall])); -} - -startTest(function() { - testInCallMMI_IMEI() - .catch(error => ok(false, "Promise reject: " + error)) - .then(finish); -}); diff --git a/dom/telephony/test/marionette/test_incoming_already_connected.js b/dom/telephony/test/marionette/test_incoming_already_connected.js deleted file mode 100644 index 21c3f95ddb08..000000000000 --- a/dom/telephony/test/marionette/test_incoming_already_connected.js +++ /dev/null @@ -1,47 +0,0 @@ -/* Any copyright is dedicated to the Public Domain. - * http://creativecommons.org/publicdomain/zero/1.0/ */ - -MARIONETTE_TIMEOUT = 60000; -MARIONETTE_HEAD_JS = 'head.js'; - -const outNumber = "5555551111"; -const outInfo = gOutCallStrPool(outNumber); -var outCall; - -const inNumber = "5555552222"; -const inInfo = gInCallStrPool(inNumber); -var inCall; - -startTest(function() { - gDial(outNumber) - .then(call => outCall = call) - .then(() => gCheckAll(outCall, [outCall], "", [], [outInfo.ringing])) - .then(() => gRemoteAnswer(outCall)) - .then(() => gCheckAll(outCall, [outCall], "", [], [outInfo.active])) - - // With one connected call already, simulate an incoming call - .then(() => gRemoteDial(inNumber)) - .then(call => inCall = call) - .then(() => gCheckAll(outCall, [outCall, inCall], "", [], - [outInfo.active, inInfo.waiting])) - - // Answer incoming call; original outgoing call should be held - .then(() => { - let p1 = gWaitForNamedStateEvent(outCall, "held"); - let p2 = gAnswer(inCall); - return Promise.all([p1, p2]); - }) - .then(() => gCheckAll(inCall, [outCall, inCall], "", [], - [outInfo.held, inInfo.active])) - - // Hang-up original outgoing (now held) call - .then(() => gHangUp(outCall)) - .then(() => gCheckAll(inCall, [inCall], "", [], [inInfo.active])) - - // Hang-up remaining (incoming) call - .then(() => gHangUp(inCall)) - .then(() => gCheckAll(null, [], "", [], [])) - - .catch(error => ok(false, "Promise reject: " + error)) - .then(finish); -}); diff --git a/dom/telephony/test/marionette/test_incoming_already_held.js b/dom/telephony/test/marionette/test_incoming_already_held.js deleted file mode 100644 index 6b40c7238e06..000000000000 --- a/dom/telephony/test/marionette/test_incoming_already_held.js +++ /dev/null @@ -1,45 +0,0 @@ -/* Any copyright is dedicated to the Public Domain. - * http://creativecommons.org/publicdomain/zero/1.0/ */ - -MARIONETTE_TIMEOUT = 60000; -MARIONETTE_HEAD_JS = 'head.js'; - -const outNumber = "5555551111"; -const outInfo = gOutCallStrPool(outNumber); -var outCall; - -const inNumber = "5555552222"; -const inInfo = gInCallStrPool(inNumber); -var inCall; - -startTest(function() { - gDial(outNumber) - .then(call => outCall = call) - .then(() => gCheckAll(outCall, [outCall], "", [], [outInfo.ringing])) - .then(() => gRemoteAnswer(outCall)) - .then(() => gCheckAll(outCall, [outCall], "", [], [outInfo.active])) - .then(() => gHold(outCall)) - .then(() => gCheckAll(null, [outCall], "", [], [outInfo.held])) - - // With one call on hold, simulate an incoming call - .then(() => gRemoteDial(inNumber)) - .then(call => inCall = call) - .then(() => gCheckAll(null, [outCall, inCall], "", [], - [outInfo.held, inInfo.waiting])) - - // Answer incoming call; original outgoing call should be held - .then(() => gAnswer(inCall)) - .then(() => gCheckAll(inCall, [outCall, inCall], "", [], - [outInfo.held, inInfo.active])) - - // Hang-up original outgoing (now held) call - .then(() => gHangUp(outCall)) - .then(() => gCheckAll(inCall, [inCall], "", [], [inInfo.active])) - - // Hang-up remaining (incoming) call - .then(() => gHangUp(inCall)) - .then(() => gCheckAll(null, [], "", [], [])) - - .catch(error => ok(false, "Promise reject: " + error)) - .then(finish); -}); diff --git a/dom/telephony/test/marionette/test_incoming_answer_hangup_oncallschanged.js b/dom/telephony/test/marionette/test_incoming_answer_hangup_oncallschanged.js deleted file mode 100644 index d27acf190c62..000000000000 --- a/dom/telephony/test/marionette/test_incoming_answer_hangup_oncallschanged.js +++ /dev/null @@ -1,30 +0,0 @@ -/* Any copyright is dedicated to the Public Domain. - * http://creativecommons.org/publicdomain/zero/1.0/ */ - -MARIONETTE_TIMEOUT = 60000; -MARIONETTE_HEAD_JS = 'head.js'; - -const inNumber = "5555552222"; -const inInfo = gInCallStrPool(inNumber); -var inCall; - -startTest(function() { - gRemoteDial(inNumber) - .then(call => inCall = call) - .then(() => gCheckAll(null, [inCall], "", [], [inInfo.incoming])) - - // Answer incoming call - .then(() => gAnswer(inCall)) - .then(() => gCheckAll(inCall, [inCall], "", [], [inInfo.active])) - - // Hang-up call - .then(() => { - let p1 = gHangUp(inCall); - let p2 = gWaitForCallsChangedEvent(telephony, inCall); - return Promise.all([p1, p2]); - }) - .then(() => gCheckAll(null, [], "", [], [])) - - .catch(error => ok(false, "Promise reject: " + error)) - .then(finish); -}); diff --git a/dom/telephony/test/marionette/test_incoming_onstatechange.js b/dom/telephony/test/marionette/test_incoming_onstatechange.js deleted file mode 100644 index ffd26547625e..000000000000 --- a/dom/telephony/test/marionette/test_incoming_onstatechange.js +++ /dev/null @@ -1,34 +0,0 @@ -/* Any copyright is dedicated to the Public Domain. - * http://creativecommons.org/publicdomain/zero/1.0/ */ - -MARIONETTE_HEAD_JS = 'head.js'; -MARIONETTE_TIMEOUT = 60000; - -const inNumber = "5555552222"; -const inInfo = gInCallStrPool(inNumber); -var inCall; - -startTest(function() { - gRemoteDial(inNumber) - .then(call => inCall = call) - .then(() => gCheckAll(null, [inCall], "", [], [inInfo.incoming])) - - // Answer incoming call - .then(() => gAnswer(inCall)) - .then(() => gCheckAll(inCall, [inCall], "", [], [inInfo.active])) - - // Hold the call. - .then(() => gHold(inCall)) - .then(() => gCheckAll(null, [inCall], "", [], [inInfo.held])) - - // Resume the call. - .then(() => gResume(inCall)) - .then(() => gCheckAll(inCall, [inCall], "", [], [inInfo.active])) - - // Hang-up call - .then(() => gHangUp(inCall)) - .then(() => gCheckAll(null, [], "", [], [])) - - .catch(error => ok(false, "Promise reject: " + error)) - .then(finish); -}); diff --git a/dom/telephony/test/marionette/test_mmi_call_barring.js b/dom/telephony/test/marionette/test_mmi_call_barring.js deleted file mode 100644 index 742204cfe69f..000000000000 --- a/dom/telephony/test/marionette/test_mmi_call_barring.js +++ /dev/null @@ -1,98 +0,0 @@ -/* Any copyright is dedicated to the Public Domain. - * http://creativecommons.org/publicdomain/zero/1.0/ */ - -MARIONETTE_TIMEOUT = 60000; -MARIONETTE_HEAD_JS = "head.js"; - -// Password is hardcoded as "0000" by default in emulator. -const PASSWORD = "0000"; -// Emulator doesn't support BA_ALL(330), BA_MO(333), BA_MT(353). -const CB_TYPES = ["33", "331", "332", "35", "351"]; -const CB_TYPES_UNSUPPORTED = ["330", "333", "353"]; -// Basic Service - 10: Voice + Fax + SMS. -const BS = "10"; -const MMI_SERVICE_CLASS = ["serviceClassVoice", "serviceClassFax", - "serviceClassSms"]; -// Call barring doesn't support Registration (**) and Erasure (##) operation. -const OPERATION_UNSUPPORTED = ["**", "##"]; - -function sendCbMMI(aOperation, aType, aExpectedSuccess, aExpectedStatusMessage) { - let mmi = aOperation + aType + "*" + PASSWORD + "*" + BS + "#"; - log("Test " + mmi + " ..."); - - return gSendMMI(mmi) - .then((aResult) => { - is(aResult.success, aExpectedSuccess, "Check success"); - is(aResult.serviceCode, "scCallBarring", "Check serviceCode"); - is(aResult.statusMessage, aExpectedStatusMessage, "Check statusMessage"); - return aResult; - }); -} - -function testCallBarring(aEnabled) { - let promise = Promise.resolve(); - - CB_TYPES.forEach(function(aType) { - promise = promise - // Test setting call barring. - .then(() => sendCbMMI(aEnabled ? "*" : "#", aType, true, - aEnabled ? "smServiceEnabled" : "smServiceDisabled")) - // Test getting call barring. - .then(() => sendCbMMI("*#", aType, true, - aEnabled ? "smServiceEnabledFor": "smServiceDisabled")) - .then(aResult => { - if (aEnabled) { - is(aResult.additionalInformation.length, MMI_SERVICE_CLASS.length, - "Check additionalInformation.length"); - for (let i = 0; i < MMI_SERVICE_CLASS.length; i++) { - is(aResult.additionalInformation[i], MMI_SERVICE_CLASS[i], - "Check additionalInformation[" + i + "]"); - } - } - }); - }); - - return promise; -} - -function testUnsupportType() { - let promise = Promise.resolve(); - - CB_TYPES_UNSUPPORTED.forEach(function(aType) { - promise = promise - // Test setting call barring. - .then(() => sendCbMMI("*", aType, false, "RequestNotSupported")) - // Test getting call barring. - .then(() => sendCbMMI("*#", aType, false, "RequestNotSupported")); - }); - - return promise; -} - -function testUnsupportedOperation() { - let promise = Promise.resolve(); - - let types = CB_TYPES.concat(CB_TYPES_UNSUPPORTED); - types.forEach(function(aType) { - OPERATION_UNSUPPORTED.forEach(function(aOperation) { - promise = promise - .then(() => sendCbMMI(aOperation, aType, false, - "emMmiErrorNotSupported")); - }); - }); - - return promise; -} - -// Start test. -startTest(function() { - // Activate call barring service. - return testCallBarring(true) - // Deactivate call barring service. - .then(() => testCallBarring(false)) - .then(() => testUnsupportType()) - .then(() => testUnsupportedOperation()) - - .catch(error => ok(false, "Promise reject: " + error)) - .then(finish);; -}); diff --git a/dom/telephony/test/marionette/test_mmi_call_forwarding.js b/dom/telephony/test/marionette/test_mmi_call_forwarding.js deleted file mode 100644 index bc3e924982a7..000000000000 --- a/dom/telephony/test/marionette/test_mmi_call_forwarding.js +++ /dev/null @@ -1,190 +0,0 @@ -/* Any copyright is dedicated to the Public Domain. - http://creativecommons.org/publicdomain/zero/1.0/ */ - -MARIONETTE_TIMEOUT = 60000; -MARIONETTE_HEAD_JS = "head.js"; - -var connection; - -/** - * Wait for one named MobileConnection event. - * - * Resolve if that named event occurs. Never reject. - * - * Fulfill params: the DOMEvent passed. - * - * @param aEventName - * A string event name. - * - * @return A deferred promise. - */ -function waitForManagerEvent(aEventName) { - let deferred = Promise.defer(); - - connection.addEventListener(aEventName, function onevent(aEvent) { - connection.removeEventListener(aEventName, onevent); - - ok(true, "MobileConnection event '" + aEventName + "' got."); - deferred.resolve(aEvent); - }); - - return deferred.promise; -} - -/** - * Configures call forward options. - * - * Fulfill params: (none) - * Reject params: - * 'RadioNotAvailable', 'RequestNotSupported', 'InvalidParameter', or - * 'GenericFailure'. - * - * @param aOptions - * A MozCallForwardingOptions. - * - * @return A deferred promise. - */ -function setCallForwardingOption(aOptions) { - let request = connection.setCallForwardingOption(aOptions); - return request.then(null, () => { throw request.error; }); -} - -const TEST_DATA = [ - { - reason: MozMobileConnection.CALL_FORWARD_REASON_UNCONDITIONAL, - number: "+886912345678", - serviceClass: MozMobileConnection.ICC_SERVICE_CLASS_VOICE, - timeSeconds: 5 - }, { - reason: MozMobileConnection.CALL_FORWARD_REASON_MOBILE_BUSY, - number: "0912345678", - serviceClass: MozMobileConnection.ICC_SERVICE_CLASS_VOICE, - timeSeconds: 10 - }, { - reason: MozMobileConnection.CALL_FORWARD_REASON_NO_REPLY, - number: "+886987654321", - serviceClass: MozMobileConnection.ICC_SERVICE_CLASS_VOICE, - timeSeconds: 15 - }, { - reason: MozMobileConnection.CALL_FORWARD_REASON_NOT_REACHABLE, - number: "+0987654321", - serviceClass: MozMobileConnection.ICC_SERVICE_CLASS_VOICE, - timeSeconds: 20 - } -]; - -// Please see TS 22.030 Annex B -const CF_REASON_TO_MMI = { - /* CALL_FORWARD_REASON_UNCONDITIONAL */ - 0: "21", - /* CALL_FORWARD_REASON_MOBILE_BUSY */ - 1: "67", - /* CALL_FORWARD_REASON_NO_REPLY */ - 2: "61", - /* CALL_FORWARD_REASON_NOT_REACHABLE */ - 3: "62", - /* CALL_FORWARD_REASON_ALL_CALL_FORWARDING */ - 4: "002", - /* CALL_FORWARD_REASON_ALL_CONDITIONAL_CALL_FORWARDING */ - 5: "004" -}; - -// Please see TS 22.030 Annex C -const SERVICE_CLASS_TO_MMI = { - /* ICC_SERVICE_CLASS_VOICE */ - 1: "11" -}; - -function testSetCallForwarding(aData) { - // Registration: **SC*SIA*SIB*SIC# - let MMI_CODE = "**" + CF_REASON_TO_MMI[aData.reason] + "*" + aData.number + - "*" + SERVICE_CLASS_TO_MMI[aData.serviceClass] + - "*" + aData.timeSeconds + "#"; - log("Test " + MMI_CODE); - - let promises = []; - // Check cfstatechange event. - promises.push(waitForManagerEvent("cfstatechange").then(function(aEvent) { - is(aEvent.action, MozMobileConnection.CALL_FORWARD_ACTION_REGISTRATION, - "check action"); - is(aEvent.reason, aData.reason, "check reason"); - is(aEvent.number, aData.number, "check number"); - is(aEvent.timeSeconds, aData.timeSeconds, "check timeSeconds"); - is(aEvent.serviceClass, aData.serviceClass, "check serviceClass"); - })); - - // Check MMI result. - promises.push(gSendMMI(MMI_CODE).then(aResult => { - ok(aResult.success, "success"); - is(aResult.serviceCode, "scCallForwarding", "Check service code"); - is(aResult.statusMessage, "smServiceRegistered", "Check status message"); - is(aResult.additionalInformation, undefined, "Check additional information"); - })); - - return Promise.all(promises); -} - -function testGetCallForwarding(aExpectedData) { - // Interrogation: *#SC# - let MMI_CODE = "*#" + CF_REASON_TO_MMI[aExpectedData.reason] + "#"; - log("Test " + MMI_CODE); - - return gSendMMI(MMI_CODE).then(aResult => { - ok(aResult.success, "success"); - is(aResult.serviceCode, "scCallForwarding", "Check service code"); - is(aResult.statusMessage, "smServiceInterrogated", "Check status message"); - ok(Array.isArray(aResult.additionalInformation), - "additionalInformation should be an array"); - - for (let i = 0; i < aResult.additionalInformation.length; i++) { - let result = aResult.additionalInformation[i]; - - // Only need to check the result containing the serviceClass that we are - // interested in. - if (!(result.serviceClass & aExpectedData.serviceClass)) { - continue; - } - - is(result.active, true, "check active"); - is(result.reason, aExpectedData.reason, "check reason"); - is(result.number, aExpectedData.number, "check number"); - is(result.timeSeconds, aExpectedData.timeSeconds, "check timeSeconds"); - } - }); -} - -function clearAllCallForwardingSettings() { - log("Clear all call forwarding settings"); - - let promise = Promise.resolve(); - for (let reason = MozMobileConnection.CALL_FORWARD_REASON_UNCONDITIONAL; - reason <= MozMobileConnection.CALL_FORWARD_REASON_ALL_CONDITIONAL_CALL_FORWARDING; - reason++) { - let options = { - reason: reason, - action: MozMobileConnection.CALL_FORWARD_ACTION_ERASURE - }; - // Emulator doesn't support CALL_FORWARD_REASON_ALL_* yet, we catch the - // reject here in order to avoid impact the test result. - promise = - promise.then(() => setCallForwardingOption(options).then(null, () => {})); - } - return promise; -} - -// Start tests -startTestWithPermissions(['mobileconnection'], function() { - connection = navigator.mozMobileConnections[0]; - - let promise = Promise.resolve(); - for (let i = 0; i < TEST_DATA.length; i++) { - let data = TEST_DATA[i]; - promise = promise.then(() => testSetCallForwarding(data)) - .then(() => testGetCallForwarding(data)); - } - - // reset call forwarding settings. - return promise.then(() => clearAllCallForwardingSettings()) - .catch(error => ok(false, "Promise reject: " + error)) - .then(finish); -}); diff --git a/dom/telephony/test/marionette/test_mmi_call_waiting.js b/dom/telephony/test/marionette/test_mmi_call_waiting.js deleted file mode 100644 index e26eb291aa39..000000000000 --- a/dom/telephony/test/marionette/test_mmi_call_waiting.js +++ /dev/null @@ -1,44 +0,0 @@ -/* Any copyright is dedicated to the Public Domain. - * http://creativecommons.org/publicdomain/zero/1.0/ */ - -MARIONETTE_TIMEOUT = 60000; -MARIONETTE_HEAD_JS = "head.js"; - -const TEST_DATA = [ - // [mmi, expectedError] - // Currently emulator doesn't support REQUEST_QUERY_CALL_WAITING, so we expect - // to get a 'RequestNotSupported' error here. - ["*#43*10#", "RequestNotSupported"], - // Currently emulator doesn't support REQUEST_SET_CALL_WAITING, so we expect - // to get a 'RequestNotSupported' error here. - ["*43*10#", "RequestNotSupported"], - ["#43*10#", "RequestNotSupported"], - // Unsupported Call Waiting MMI code. - ["**43*10#", "emMmiErrorNotSupported"], - ["##43*10#", "emMmiErrorNotSupported"], -]; - -function testCallWaiting(aMmi, aExpectedError) { - log("Test " + aMmi + " ..."); - - return gSendMMI(aMmi).then(aResult => { - // Since emulator doesn't support call waiting, so we expect the result is - // always failed. - ok(!aResult.success, "Check success"); - is(aResult.serviceCode, "scCallWaiting", "Check serviceCode"); - is(aResult.statusMessage, aExpectedError, "Check statusMessage"); - }); -} - -// Start test -startTest(function() { - let promise = Promise.resolve(); - - TEST_DATA.forEach(function(aData) { - promise = promise.then(() => testCallWaiting(aData[0], aData[1])); - }); - - return promise - .catch(aError => ok(false, "Promise reject: " + aError)) - .then(finish); -}); diff --git a/dom/telephony/test/marionette/test_mmi_change_barring_password.js b/dom/telephony/test/marionette/test_mmi_change_barring_password.js deleted file mode 100644 index df35e3d34386..000000000000 --- a/dom/telephony/test/marionette/test_mmi_change_barring_password.js +++ /dev/null @@ -1,100 +0,0 @@ -/* Any copyright is dedicated to the Public Domain. - http://creativecommons.org/publicdomain/zero/1.0/ */ - -MARIONETTE_TIMEOUT = 60000; -MARIONETTE_HEAD_JS = "head.js"; - -const TEST_DATA = [ - // Test passing no password. - { - password: "", - newPassword: "0000", - newPasswordAgain: "1111", - expectedError: { - name: "emMmiErrorInvalidPassword" - } - }, - // Test passing no newPassword. - { - password: "0000", - newPassword: "", - newPasswordAgain: "", - expectedError: { - name: "emMmiErrorInvalidPassword" - } - }, - // Test passing mismatched newPassword. - { - password: "0000", - newPassword: "0000", - newPasswordAgain: "1111", - expectedError: { - name: "emMmiErrorMismatchPassword" - } - }, - // Test passing invalid password (not 4 digits). - { - password: "000", - newPassword: "0000", - newPasswordAgain: "0000", - expectedError: { - name: "emMmiErrorInvalidPassword" - } - }, - // Expect to succeed. - { - password: "0000", // 0000 is the default password for call barring - newPassword: "1234", - newPasswordAgain: "1234" - }, - // Restore to the default password - { - password: "1234", - newPassword: "0000", - newPasswordAgain: "0000" - } -]; - -var MMI_PREFIX = [ - "*03*330*", - "**03*330*", - "*03**", - "**03**", -]; - -function testChangeCallBarringPassword(aMMIPrefix, aPassword, aNewPassword, - aNewPasswordAgain, aExpectedError) { - let MMI_CODE = aMMIPrefix + aPassword + "*" + aNewPassword + "*" + aNewPasswordAgain + "#"; - log("Test " + MMI_CODE); - - return gSendMMI(MMI_CODE).then(aResult => { - is(aResult.success, !aExpectedError, "check success"); - is(aResult.serviceCode, "scChangePassword", "Check service code"); - - if (aResult.success) { - is(aResult.statusMessage, "smPasswordChanged", "Check status message"); - } else { - is(aResult.statusMessage, aExpectedError.name, "Check name"); - } - }); -} - -// Start test -startTest(function() { - let promise = Promise.resolve(); - - for (let prefix of MMI_PREFIX) { - for (let i = 0; i < TEST_DATA.length; i++) { - let data = TEST_DATA[i]; - promise = promise.then(() => testChangeCallBarringPassword(prefix, - data.password, - data.newPassword, - data.newPasswordAgain, - data.expectedError)); - } - } - - return promise - .catch(error => ok(false, "Promise reject: " + error)) - .then(finish); -}); diff --git a/dom/telephony/test/marionette/test_mmi_change_pin.js b/dom/telephony/test/marionette/test_mmi_change_pin.js deleted file mode 100644 index 81ad3f9dfef1..000000000000 --- a/dom/telephony/test/marionette/test_mmi_change_pin.js +++ /dev/null @@ -1,113 +0,0 @@ -/* Any copyright is dedicated to the Public Domain. - * http://creativecommons.org/publicdomain/zero/1.0/ */ - -MARIONETTE_TIMEOUT = 60000; -MARIONETTE_HEAD_JS = "head.js"; - -// PIN is hardcoded as "0000" by default. -// See it here {B2G_HOME}/external/qemu/telephony/sim_card.c, -// in asimcard_create(). -const TEST_DATA = [ - // Test passing no pin. - { - pin: "", - newPin: "0000", - newPinAgain: "1111", - expectedError: { - name: "emMmiError", - additionalInformation: null - } - }, - // Test passing no newPin. - { - pin: "0000", - newPin: "", - newPinAgain: "", - expectedError: { - name: "emMmiError", - additionalInformation: null - } - }, - // Test passing mismatched newPin. - { - pin: "0000", - newPin: "0000", - newPinAgain: "1111", - expectedError: { - name: "emMmiErrorMismatchPin", - additionalInformation: null - } - }, - // Test passing invalid pin (< 4 digit). - { - pin: "000", - newPin: "0000", - newPinAgain: "0000", - expectedError: { - name: "emMmiErrorInvalidPin", - additionalInformation: null - } - }, - // Test passing invalid newPin (> 8 digit). - { - pin: "0000", - newPin: "000000000", - newPinAgain: "000000000", - expectedError: { - name: "emMmiErrorInvalidPin", - additionalInformation: null - } - }, - // Test passing incorrect pin. - { - pin: "1234", - newPin: "0000", - newPinAgain: "0000", - expectedError: { - name: "emMmiErrorBadPin", - // The default pin retries is 3, failed once becomes to 2 - additionalInformation: 2 - } - }, - // Test changing pin successfully (Reset the retries). - { - pin: "0000", - newPin: "0000", - newPinAgain: "0000" - } -]; - -function testChangePin(aPin, aNewPin, aNewPinAgain, aExpectedError) { - let MMI_CODE = "**04*" + aPin + "*" + aNewPin + "*" + aNewPinAgain + "#"; - log("Test " + MMI_CODE); - - return gSendMMI(MMI_CODE).then(aResult => { - is(aResult.success, !aExpectedError, "check success"); - is(aResult.serviceCode, "scPin", "Check service code"); - - if (aResult.success) { - is(aResult.statusMessage, "smPinChanged", "Check status message"); - is(aResult.additionalInformation, undefined, "Check additional information"); - } else { - is(aResult.statusMessage, aExpectedError.name, "Check name"); - is(aResult.additionalInformation, aExpectedError.additionalInformation, - "Check additional information"); - } - }); -} - -// Start test -startTest(function() { - let promise = Promise.resolve(); - for (let i = 0; i < TEST_DATA.length; i++) { - let data = TEST_DATA[i]; - promise = promise.then(() => testChangePin(data.pin, - data.newPin, - data.newPinAgain, - data.expectedError)); - } - - return promise - .catch(error => ok(false, "Promise reject: " + error)) - .then(finish); -}); diff --git a/dom/telephony/test/marionette/test_mmi_change_pin2.js b/dom/telephony/test/marionette/test_mmi_change_pin2.js deleted file mode 100644 index c073b98310eb..000000000000 --- a/dom/telephony/test/marionette/test_mmi_change_pin2.js +++ /dev/null @@ -1,105 +0,0 @@ -/* Any copyright is dedicated to the Public Domain. - * http://creativecommons.org/publicdomain/zero/1.0/ */ - -MARIONETTE_TIMEOUT = 60000; -MARIONETTE_HEAD_JS = "head.js"; - -const TEST_DATA = [ - // Test passing no pin2. - { - pin2: "", - newPin2: "0000", - newPin2Again: "1111", - expectedError: { - name: "emMmiError", - additionalInformation: null - } - }, - // Test passing no newPin2. - { - pin2: "0000", - newPin2: "", - newPin2Again: "", - expectedError: { - name: "emMmiError", - additionalInformation: null - } - }, - // Test passing mismatched newPin2. - { - pin2: "0000", - newPin2: "0000", - newPin2Again: "1111", - expectedError: { - name: "emMmiErrorMismatchPin", - additionalInformation: null - } - }, - // Test passing invalid pin2 (< 4 digit). - { - pin2: "123", - newPin2: "0000", - newPin2Again: "0000", - expectedError: { - name: "emMmiErrorInvalidPin", - additionalInformation: null - } - }, - // Test passing invalid newPin2 (> 8 digit). - { - pin2: "0000", - newPin2: "123456789", - newPin2Again: "123456789", - expectedError: { - name: "emMmiErrorInvalidPin", - additionalInformation: null - } - }, - // Test passing valid pin2 and newPin2. But currently emulator doesn't support - // REQUEST_CHANGE_SIM_PIN2, so we expect to get a 'RequestNotSupported' error - // here. - { - pin2: "0000", - newPin2: "0000", - newPin2Again: "0000", - expectedError: { - name: "RequestNotSupported", - additionalInformation: null - } - }, -]; - -function testChangePin2(aPin2, aNewPin2, aNewPin2Again, aExpectedError) { - let MMI_CODE = "**042*" + aPin2 + "*" + aNewPin2 + "*" + aNewPin2Again + "#"; - log("Test " + MMI_CODE); - - return gSendMMI(MMI_CODE).then(aResult => { - is(aResult.success, !aExpectedError, "check success"); - is(aResult.serviceCode, "scPin2", "Check service code"); - - if (aResult.success) { - is(aResult.statusMessage, "smPin2Changed", "Check status message"); - is(aResult.additionalInformation, undefined, "Check additional information"); - } else { - is(aResult.statusMessage, aExpectedError.name, "Check name"); - is(aResult.additionalInformation, aExpectedError.additionalInformation, - "Check additional information"); - } - }); -} - -// Start test -startTest(function() { - let promise = Promise.resolve(); - for (let i = 0; i < TEST_DATA.length; i++) { - let data = TEST_DATA[i]; - promise = promise.then(() => testChangePin2(data.pin2, - data.newPin2, - data.newPin2Again, - data.expectedError)); - } - - return promise - .catch(error => ok(false, "Promise reject: " + error)) - .then(finish); -}); diff --git a/dom/telephony/test/marionette/test_mmi_clip.js b/dom/telephony/test/marionette/test_mmi_clip.js deleted file mode 100644 index c878c3eb765d..000000000000 --- a/dom/telephony/test/marionette/test_mmi_clip.js +++ /dev/null @@ -1,42 +0,0 @@ -/* Any copyright is dedicated to the Public Domain. - * http://creativecommons.org/publicdomain/zero/1.0/ */ - -MARIONETTE_TIMEOUT = 60000; -MARIONETTE_HEAD_JS = "head.js"; - -const TEST_DATA = [ - // [mmi, expectedError] - // Currently emulator doesn't support REQUEST_QUERY_CLIP, so we expect to - // get a 'RequestNotSupported' error here. - ["*#30#", "RequestNotSupported"], - // Unsupported CLIP MMI code. - ["*30#", "emMmiErrorNotSupported"], - ["#30#", "emMmiErrorNotSupported"], - ["**30#", "emMmiErrorNotSupported"], - ["##30#", "emMmiErrorNotSupported"], -]; - -function testCLIP(aMmi, aExpectedError) { - log("Test " + aMmi + " ..."); - - return gSendMMI(aMmi).then(aResult => { - // Since emulator doesn't support clip, so we expect the result is always - // failed. - ok(!aResult.success, "Check success"); - is(aResult.serviceCode, "scClip", "Check serviceCode"); - is(aResult.statusMessage, aExpectedError, "Check statusMessage"); - }); -} - -// Start test -startTest(function() { - let promise = Promise.resolve(); - - TEST_DATA.forEach(function(aData) { - promise = promise.then(() => testCLIP(aData[0], aData[1])); - }); - - return promise - .catch(aError => ok(false, "Promise reject: " + aError)) - .then(finish); -}); diff --git a/dom/telephony/test/marionette/test_mmi_clir.js b/dom/telephony/test/marionette/test_mmi_clir.js deleted file mode 100644 index ff384276de33..000000000000 --- a/dom/telephony/test/marionette/test_mmi_clir.js +++ /dev/null @@ -1,44 +0,0 @@ -/* Any copyright is dedicated to the Public Domain. - * http://creativecommons.org/publicdomain/zero/1.0/ */ - -MARIONETTE_TIMEOUT = 60000; -MARIONETTE_HEAD_JS = "head.js"; - -const TEST_DATA = [ - // [mmi, expectedError] - // Currently emulator doesn't support REQUEST_GET_CLIR, so we expect to get a - // 'RequestNotSupported' error here. - ["*#31#", "RequestNotSupported"], - // Currently emulator doesn't support REQUEST_SET_CLIR, so we expect to get a - // 'RequestNotSupported' error here. - ["*31#", "RequestNotSupported"], - ["#31#", "RequestNotSupported"], - // Unsupported CLIR MMI code. - ["**31#", "emMmiErrorNotSupported"], - ["##31#", "emMmiErrorNotSupported"], -]; - -function testCLIR(aMmi, aExpectedError) { - log("Test " + aMmi + " ..."); - - return gSendMMI(aMmi).then(aResult => { - // Since emulator doesn't support clip, so we expect the result is always - // failed. - ok(!aResult.success, "Check success"); - is(aResult.serviceCode, "scClir", "Check serviceCode"); - is(aResult.statusMessage, aExpectedError, "Check statusMessage"); - }); -} - -// Start test -startTest(function() { - let promise = Promise.resolve(); - - TEST_DATA.forEach(function(aData) { - promise = promise.then(() => testCLIR(aData[0], aData[1])); - }); - - return promise - .catch(aError => ok(false, "Promise reject: " + aError)) - .then(finish); -}); diff --git a/dom/telephony/test/marionette/test_mmi_imei.js b/dom/telephony/test/marionette/test_mmi_imei.js deleted file mode 100644 index a9e1f01723e9..000000000000 --- a/dom/telephony/test/marionette/test_mmi_imei.js +++ /dev/null @@ -1,30 +0,0 @@ -/* Any copyright is dedicated to the Public Domain. - * http://creativecommons.org/publicdomain/zero/1.0/ */ - -MARIONETTE_TIMEOUT = 60000; -MARIONETTE_HEAD_JS = "head.js"; - -function testGettingIMEI() { - log("Test *#06# ..."); - - return gSendMMI("*#06#").then(aResult => { - ok(aResult.success, "success"); - is(aResult.serviceCode, "scImei", "Service code IMEI"); - // IMEI is hardcoded as "000000000000000". - // See it here {B2G_HOME}/external/qemu/telephony/android_modem.c - // (The aResult of +CGSN). - is(aResult.statusMessage, "000000000000000", "Emulator IMEI"); - is(aResult.additionalInformation, undefined, "No additional information"); - }); -} - -// Start test -startTestWithPermissions(['mobileconnection'], function() { - Promise.resolve() - .then(() => gSetRadioEnabledAll(false)) - .then(() => testGettingIMEI()) - .then(() => gSetRadioEnabledAll(true)) - .then(() => testGettingIMEI()) - .catch(error => ok(false, "Promise reject: " + error)) - .then(finish); -}); diff --git a/dom/telephony/test/marionette/test_mmi_unlock_puk.js b/dom/telephony/test/marionette/test_mmi_unlock_puk.js deleted file mode 100644 index b91c306f52ab..000000000000 --- a/dom/telephony/test/marionette/test_mmi_unlock_puk.js +++ /dev/null @@ -1,157 +0,0 @@ -/* Any copyright is dedicated to the Public Domain. - * http://creativecommons.org/publicdomain/zero/1.0/ */ - -MARIONETTE_TIMEOUT = 60000; -MARIONETTE_HEAD_JS = "head.js"; - -const DEFAULT_PIN = "0000"; -const DEFAULT_PUK = "12345678"; - -function getMozIcc() { - let iccId = navigator.mozMobileConnections[0].iccId; - return navigator.mozIccManager.getIccById(iccId); -} - -function waitForTargetEvent(aEventTarget, aEventName, aMatchFun) { - let deferred = Promise.defer(); - - aEventTarget.addEventListener(aEventName, function onevent(aEvent) { - if (!aMatchFun || aMatchFun(aEvent)) { - aEventTarget.removeEventListener(aEventName, onevent); - ok(true, "Event '" + aEventName + "' got."); - deferred.resolve(aEvent); - } - }); - - return deferred.promise; -} - -function setRadioEnabledAndWait(aEnabled) { - let promises = []; - let connection = navigator.mozMobileConnections[0]; - - promises.push(waitForTargetEvent(connection, "radiostatechange", function() { - return connection.radioState === aEnabled ? "enabled" : "disabled"; - })); - promises.push(connection.setRadioEnabled(aEnabled)); - - return Promise.all(promises); -} - -function restartRadioAndWait(aCardState) { - let iccManager = navigator.mozIccManager; - - return setRadioEnabledAndWait(false).then(() => { - let promises = []; - - promises.push(waitForTargetEvent(iccManager, "iccdetected") - .then((aEvent) => { - let icc = iccManager.getIccById(aEvent.iccId); - if (icc.cardState !== aCardState) { - return waitForTargetEvent(icc, "cardstatechange", function() { - return icc.cardState === aCardState; - }); - } - })); - promises.push(setRadioEnabledAndWait(true)); - - return Promise.all(promises); - }); -} - -function passingWrongPinAndWait(aIcc) { - return aIcc.getCardLockRetryCount("pin").then((aResult) => { - let promises = []; - let retryCount = aResult.retryCount; - - ok(true, "pin retryCount is " + retryCount); - - promises.push(waitForTargetEvent(aIcc, "cardstatechange", function() { - return aIcc.cardState === "pukRequired"; - })); - - for (let i = 0; i < retryCount; i++) { - promises.push(aIcc.unlockCardLock({ lockType: "pin", pin: "1111" }) - .then(() => { - ok(false, "unlocking pin should not success"); - }, (aError) => { - ok(true, "pin retryCount = " + aError.retryCount); - })); - } - - return Promise.all(promises); - }); -} - -function sendUnlockPukMmi(aPuk, aNewPin, aNewPinAgain) { - let MMI_CODE = "**05*" + aPuk + "*" + aNewPin + "*" + aNewPinAgain + "#"; - log("Test " + MMI_CODE); - - return gSendMMI(MMI_CODE); -} - -function testUnlockPukMmiError(aPuk, aNewPin, aNewPinAgain, aErrorName, - aRetryCount = null) { - return sendUnlockPukMmi(aPuk, aNewPin, aNewPinAgain) - .then((aResult) => { - ok(!aResult.success, "check success"); - is(aResult.serviceCode, "scPuk", "Check service code"); - is(aResult.statusMessage, aErrorName, "Check statusMessage"); - is(aResult.additionalInformation, aRetryCount, - "Check additional information"); - }); -} - -function testUnlockPukAndWait(aIcc, aCardState) { - let promises = []; - - promises.push(waitForTargetEvent(aIcc, "cardstatechange", function() { - return aIcc.cardState === aCardState; - })); - promises.push(sendUnlockPukMmi(DEFAULT_PUK, DEFAULT_PIN, DEFAULT_PIN)); - - return Promise.all(promises); -} - -// Start tests -startTestWithPermissions(['mobileconnection'], function() { - let icc = getMozIcc(); - let retryCount; - - // Enable PIN-lock. - return icc.setCardLock({lockType: "pin", enabled: true, pin: DEFAULT_PIN}) - // Reset card state to "pinRequired" by restarting radio. - .then(() => restartRadioAndWait("pinRequired")) - .then(() => { icc = getMozIcc(); }) - // Switch card state to "pukRequired" by entering wrong pin. - .then(() => passingWrongPinAndWait(icc)) - - // Get current PUK-lock retry count. - .then(() => icc.getCardLockRetryCount("puk")) - .then((aResult) => { - retryCount = aResult.retryCount; - ok(true, "puk retryCount is " + retryCount); - }) - - // Test passing no puk. - .then(() => testUnlockPukMmiError("", "1111", "2222", "emMmiError")) - // Test passing no newPin. - .then(() => testUnlockPukMmiError("11111111", "", "", "emMmiError")) - // Test passing mismatched newPin. - .then(() => testUnlockPukMmiError("11111111", "1111", "2222", - "emMmiErrorMismatchPin")) - // Test passing invalid puk (> 8 digit). - .then(() => testUnlockPukMmiError("123456789", DEFAULT_PIN, DEFAULT_PIN, - "emMmiErrorInvalidPin")) - // Test passing incorrect puk. - .then(() => testUnlockPukMmiError("11111111", DEFAULT_PIN, DEFAULT_PIN, - "emMmiErrorBadPuk", retryCount - 1)) - - // Test unlock PUK-lock success. - .then(() => testUnlockPukAndWait(icc, "ready")) - - // Restore pin state. - .then(() => icc.setCardLock({lockType: "pin", enabled: false, pin: DEFAULT_PIN})) - .catch((aError) => ok(false, "Promise reject " + aError)) - .then(finish); -}); diff --git a/dom/telephony/test/marionette/test_mmi_unlock_puk2.js b/dom/telephony/test/marionette/test_mmi_unlock_puk2.js deleted file mode 100644 index fe52939e7f61..000000000000 --- a/dom/telephony/test/marionette/test_mmi_unlock_puk2.js +++ /dev/null @@ -1,44 +0,0 @@ -/* Any copyright is dedicated to the Public Domain. - * http://creativecommons.org/publicdomain/zero/1.0/ */ - -MARIONETTE_TIMEOUT = 60000; -MARIONETTE_HEAD_JS = "head.js"; - -function sendUnlockPuk2Mmi(aPuk2, aNewPin2, aNewPin2Again) { - let MMI_CODE = "**052*" + aPuk2 + "*" + aNewPin2 + "*" + aNewPin2Again + "#"; - log("Test " + MMI_CODE); - - return gSendMMI(MMI_CODE); -} - -function testUnlockPuk2MmiError(aPuk2, aNewPin2, aNewPin2Again, aErrorName) { - return sendUnlockPuk2Mmi(aPuk2, aNewPin2, aNewPin2Again) - .then((aResult) => { - ok(!aResult.success, "Check success"); - is(aResult.serviceCode, "scPuk2", "Check service code"); - is(aResult.statusMessage, aErrorName, "Check statusMessage"); - is(aResult.additionalInformation, null, "Check additional information"); - }); -} - -// Start test -startTest(function() { - return Promise.resolve() - // Test passing no puk2. - .then(() => testUnlockPuk2MmiError("", "1111", "2222", "emMmiError")) - // Test passing no newPin2. - .then(() => testUnlockPuk2MmiError("11111111", "", "", "emMmiError")) - // Test passing mismatched newPin2. - .then(() => testUnlockPuk2MmiError("11111111", "1111", "2222", - "emMmiErrorMismatchPin")) - // Test passing invalid puk2 (> 8 digit). - .then(() => testUnlockPuk2MmiError("123456789", "0000", "0000", - "emMmiErrorInvalidPin")) - // Test passing valid puk2 and newPin2. But currently emulator doesn't - // support RIL_REQUEST_ENTER_SIM_PUK2, so we expect to get a - // 'RequestNotSupported' error here. - .then(() => testUnlockPuk2MmiError("11111111", "0000", "0000", - "RequestNotSupported")) - .catch(error => ok(false, "Promise reject: " + error)) - .then(finish); -}); diff --git a/dom/telephony/test/marionette/test_mmi_ussd.js b/dom/telephony/test/marionette/test_mmi_ussd.js deleted file mode 100644 index d78b7d17e610..000000000000 --- a/dom/telephony/test/marionette/test_mmi_ussd.js +++ /dev/null @@ -1,23 +0,0 @@ -/* Any copyright is dedicated to the Public Domain. - * http://creativecommons.org/publicdomain/zero/1.0/ */ - -MARIONETTE_TIMEOUT = 60000; -MARIONETTE_HEAD_JS = "head.js"; - -function testUSSD() { - log("Test *#1234# ..."); - - return gSendMMI("*#1234#").then(aResult => { - ok(aResult.success, "Check success"); - is(aResult.serviceCode, "scUssd", "Check serviceCode"); - is(aResult.statusMessage, "", "Check statusMessage"); - is(aResult.additionalInformation, undefined, "No additional information"); - }); -} - -// Start test -startTest(function() { - return testUSSD() - .catch(error => ok(false, "Promise reject: " + error)) - .then(finish); -}); diff --git a/dom/telephony/test/marionette/test_modem_switch_tech.js b/dom/telephony/test/marionette/test_modem_switch_tech.js deleted file mode 100644 index 7af228cdae4d..000000000000 --- a/dom/telephony/test/marionette/test_modem_switch_tech.js +++ /dev/null @@ -1,54 +0,0 @@ -/* Any copyright is dedicated to the Public Domain. - http://creativecommons.org/publicdomain/zero/1.0/ */ - -MARIONETTE_TIMEOUT = 60000; -MARIONETTE_HEAD_JS = "head.js"; - -var settings = [ - // "gsm/wcdma" - {tech: "gsm", mask: "gsm/wcdma"}, - {tech: "wcdma", mask: "gsm/wcdma"}, - - // "gsm" - {tech: "gsm", mask: "gsm"}, - - // "wcdma" - {tech: "wcdma", mask: "wcdma"}, - - // "gsm/wcdma-auto" - {tech: "gsm", mask: "gsm/wcdma-auto"}, - {tech: "wcdma", mask: "gsm/wcdma-auto"}, - - // "cdma/evdo" - {tech: "cdma", mask: "cdma/evdo"}, - {tech: "evdo", mask: "cdma/evdo"}, - - // "cdma" - {tech: "cdma", mask: "cdma"}, - - // "evdo" - {tech: "evdo", mask: "evdo"}, - - // "gsm/wcdma/cdma/evdo" - {tech: "gsm", mask: "gsm/wcdma/cdma/evdo"}, - {tech: "wcdma", mask: "gsm/wcdma/cdma/evdo"}, - {tech: "cdma", mask: "gsm/wcdma/cdma/evdo"}, - {tech: "evdo", mask: "gsm/wcdma/cdma/evdo"} -]; - -startTest(function() { - - let promise = settings.reduce((aPromise, aSetting) => { - return aPromise.then(() => Modem.changeTech(aSetting.tech, aSetting.mask)); - }, Promise.resolve()); - - return promise - // Exception Catching - .catch(error => ok(false, "Promise reject: " + error)) - - // Switch to the default modem tech - .then(() => Modem.changeTech("wcdma", "gsm/wcdma")) - .catch(error => ok(false, "Fetal Error: Promise reject: " + error)) - - .then(finish); -}); diff --git a/dom/telephony/test/marionette/test_multiple_hold.js b/dom/telephony/test/marionette/test_multiple_hold.js deleted file mode 100644 index d6e6f2e37999..000000000000 --- a/dom/telephony/test/marionette/test_multiple_hold.js +++ /dev/null @@ -1,61 +0,0 @@ -/* Any copyright is dedicated to the Public Domain. - * http://creativecommons.org/publicdomain/zero/1.0/ */ - -MARIONETTE_TIMEOUT = 60000; -MARIONETTE_HEAD_JS = 'head.js'; - -const outNumber = "5555551111"; -const outInfo = gOutCallStrPool(outNumber); -var outCall; - -const inNumber = "5555552222"; -const inInfo = gInCallStrPool(inNumber); -var inCall; - -startTest(function() { - gRemoteDial(inNumber) - .then(call => inCall = call) - .then(() => gCheckAll(null, [inCall], "", [], [inInfo.incoming])) - - // Answer incoming call - .then(() => gAnswer(inCall)) - .then(() => gCheckAll(inCall, [inCall], "", [], [inInfo.active])) - - // Hold the call - .then(() => gHold(inCall)) - .then(() => gCheckAll(null, [inCall], "", [], [inInfo.held])) - - // Dial out. - .then(() => gDial(outNumber)) - .then(call => outCall = call) - .then(() => gCheckAll(outCall, [inCall, outCall], "", [], - [inInfo.held, outInfo.ringing])) - - // Remote answer the call - .then(() => gRemoteAnswer(outCall)) - .then(() => gCheckAll(outCall, [inCall, outCall], "", [], - [inInfo.held, outInfo.active])) - - // With one held call and one active, hold the active one; expect the first - // (held) call to automatically become active, and the 2nd call to be held - .then(() => { - let p1 = gWaitForNamedStateEvent(inCall, "connected"); - let p2 = gHold(outCall); - return Promise.all([p1, p2]); - }) - .then(() => gCheckAll(inCall, [inCall, outCall], "", [], - [inInfo.active, outInfo.held])) - - // Hangup the active call will automatically resume the held call. - .then(() => { - let p1 = gWaitForNamedStateEvent(outCall, "connected"); - let p2 = gHangUp(inCall); - return Promise.all([p1, p2]); - }) - .then(() => gCheckAll(outCall, [outCall], "", [], [outInfo.active])) - .then(() => gHangUp(outCall)) - .then(() => gCheckAll(null, [], "", [], [])) - - .catch(error => ok(false, "Promise reject: " + error)) - .then(finish); -}); diff --git a/dom/telephony/test/marionette/test_outgoing_already_held.js b/dom/telephony/test/marionette/test_outgoing_already_held.js deleted file mode 100644 index 657d9af08d0b..000000000000 --- a/dom/telephony/test/marionette/test_outgoing_already_held.js +++ /dev/null @@ -1,41 +0,0 @@ -/* Any copyright is dedicated to the Public Domain. - * http://creativecommons.org/publicdomain/zero/1.0/ */ - -MARIONETTE_TIMEOUT = 60000; -MARIONETTE_HEAD_JS = 'head.js'; - -const outNumber = "5555551111"; -const outInfo = gOutCallStrPool(outNumber); -var outCall; - -const inNumber = "5555552222"; -const inInfo = gInCallStrPool(inNumber); -var inCall; - -startTest(function() { - gRemoteDial(inNumber) - .then(call => inCall = call) - .then(() => gCheckAll(null, [inCall], "", [], [inInfo.incoming])) - .then(() => gAnswer(inCall)) - .then(() => gCheckAll(inCall, [inCall], "", [], [inInfo.active])) - .then(() => gHold(inCall)) - .then(() => gCheckAll(null, [inCall], "", [], [inInfo.held])) - - // With one call on hold, make outgoing call - .then(() => gDial(outNumber)) - .then(call => outCall = call) - .then(() => gCheckAll(outCall, [inCall, outCall], "", [], - [inInfo.held, outInfo.ringing])) - .then(() => gRemoteAnswer(outCall)) - .then(() => gCheckAll(outCall, [inCall, outCall], "", [], - [inInfo.held, outInfo.active])) - - // Hang-up - .then(() => gHangUp(inCall)) - .then(() => gCheckAll(outCall, [outCall], "", [], [outInfo.active])) - .then(() => gHangUp(outCall)) - .then(() => gCheckAll(null, [], "", [], [])) - - .catch(error => ok(false, "Promise reject: " + error)) - .then(finish); -}); diff --git a/dom/telephony/test/marionette/test_outgoing_answer_hangup_oncallschanged.js b/dom/telephony/test/marionette/test_outgoing_answer_hangup_oncallschanged.js deleted file mode 100644 index 276202e80719..000000000000 --- a/dom/telephony/test/marionette/test_outgoing_answer_hangup_oncallschanged.js +++ /dev/null @@ -1,40 +0,0 @@ -/* Any copyright is dedicated to the Public Domain. - * http://creativecommons.org/publicdomain/zero/1.0/ */ - -MARIONETTE_TIMEOUT = 60000; -MARIONETTE_HEAD_JS = 'head.js'; - -const outNumber = "5555551111"; -const outInfo = gOutCallStrPool(outNumber); -var outCall; - -startTest(function() { - Promise.resolve() - // Dial. - .then(() => { - let tmpCall; - - let p1 = gWaitForCallsChangedEvent(telephony) - .then(call => tmpCall = call); - - let p2 = gDial(outNumber) - .then(call => outCall = call); - - return Promise.all([p1, p2]).then(() => is(outCall, tmpCall)); - }) - .then(() => gCheckAll(outCall, [outCall], "", [], [outInfo.ringing])) - - .then(() => gRemoteAnswer(outCall)) - .then(() => gCheckAll(outCall, [outCall], "", [], [outInfo.active])) - - // Hang-up. - .then(() => { - let p1 = gWaitForCallsChangedEvent(telephony, outCall); - let p2 = gRemoteHangUp(outCall); - return Promise.all([p1, p2]); - }) - .then(() => gCheckAll(null, [], "", [], [])) - - .catch(error => ok(false, "Promise reject: " + error)) - .then(finish); -}); diff --git a/dom/telephony/test/marionette/test_outgoing_answer_radio_off.js b/dom/telephony/test/marionette/test_outgoing_answer_radio_off.js deleted file mode 100644 index 48b80106da04..000000000000 --- a/dom/telephony/test/marionette/test_outgoing_answer_radio_off.js +++ /dev/null @@ -1,26 +0,0 @@ -/* Any copyright is dedicated to the Public Domain. - * http://creativecommons.org/publicdomain/zero/1.0/ */ - -MARIONETTE_TIMEOUT = 60000; -MARIONETTE_HEAD_JS = 'head.js'; - -// Make an outgoing call then power off radio. -startTestWithPermissions(['mobileconnection'], function() { - let connection = navigator.mozMobileConnections[0]; - ok(connection instanceof MozMobileConnection, - "connection is instanceof " + connection.constructor); - - let outCall; - - gDial("0912345000") - .then(call => outCall = call) - .then(() => gRemoteAnswer(outCall)) - .then(() => { - let p1 = gWaitForNamedStateEvent(outCall, "disconnected"); - let p2 = gSetRadioEnabled(connection, false); - return Promise.all([p1, p2]); - }) - .then(() => gSetRadioEnabled(connection, true)) - .catch(error => ok(false, "Promise reject: " + error)) - .then(finish); -}); diff --git a/dom/telephony/test/marionette/test_outgoing_auto_hold.js b/dom/telephony/test/marionette/test_outgoing_auto_hold.js deleted file mode 100644 index 7dca375920bd..000000000000 --- a/dom/telephony/test/marionette/test_outgoing_auto_hold.js +++ /dev/null @@ -1,93 +0,0 @@ -/* Any copyright is dedicated to the Public Domain. - * http://creativecommons.org/publicdomain/zero/1.0/ */ - -MARIONETTE_TIMEOUT = 60000; -MARIONETTE_HEAD_JS = 'head.js'; - -function testAutoHoldCall() { - log('= testAutoHoldCall ='); - - let outCall1; - let outCall2; - const callNumber1 = "0900000001"; - const callNumber2 = "0900000002"; - - return Promise.resolve() - .then(() => gDial(callNumber1)) - .then(call => { outCall1 = call; }) - .then(() => gRemoteAnswer(outCall1)) - .then(() => { - is(outCall1.state, "connected"); - }) - .then(() => gDial(callNumber2)) - .then(call => { outCall2 = call; }) - .then(() => { - is(outCall1.state, "held"); - }) - .then(() => gRemoteHangUpCalls([outCall1, outCall2])); -} - - -function testAutoHoldCallFailed() { - log('= testAutoHoldCallFailed ='); - - let outCall1; - let outCall2; - const callNumber1 = "0900000011"; - const callNumber2 = "0900000012"; - - return Promise.resolve() - .then(() => emulator.runCmd("telephony disable hold")) - .then(() => gDial(callNumber1)) - .then(call => { outCall1 = call; }) - .then(() => gRemoteAnswer(outCall1)) - .then(() => { - is(outCall1.state, "connected"); - }) - .then(() => gDial(callNumber2)) - .then(call => { - ok(false, "The second |dial()| should be rejected."); - outCall2 = call; - return gRemoteHangUpCalls([outCall2]); - }, () => log("The second |dial()| is rejected as expected.")) - .then(() => gRemoteHangUpCalls([outCall1])) - .then(() => emulator.runCmd("telephony enable hold")); -} - -function testAutoHoldConferenceCall() { - log('= testAutoHoldConferenceCall ='); - - let subCall1; - let subCall2; - let outCall; - const subNumber1 = "0900000021"; - const subNumber2 = "0900000022"; - const outNumber = "0900000023"; - - return Promise.resolve() - .then(() => gSetupConference([subNumber1, subNumber2])) - .then(calls => { - [subCall1, subCall2] = calls; - is(conference.state, "connected"); - }) - .then(() => gDial(outNumber)) - .then(call => { outCall = call; }) - .then(() => { - is(subCall1.state, "held"); - is(subCall2.state, "held"); - is(conference.state, "held"); - }) - .then(() => gRemoteHangUpCalls([subCall1, subCall2, outCall])); -} - -startTest(function() { - Promise.resolve() - .then(() => testAutoHoldCall()) - .then(() => testAutoHoldCallFailed()) - .then(() => testAutoHoldConferenceCall()) - .catch(error => { - ok(false, "Promise reject: " + error); - emulator.runCmd("telephony enable hold"); - }) - .then(finish); -}); diff --git a/dom/telephony/test/marionette/test_outgoing_badNumber.js b/dom/telephony/test/marionette/test_outgoing_badNumber.js deleted file mode 100644 index e575f29fc339..000000000000 --- a/dom/telephony/test/marionette/test_outgoing_badNumber.js +++ /dev/null @@ -1,40 +0,0 @@ -/* Any copyright is dedicated to the Public Domain. - * http://creativecommons.org/publicdomain/zero/1.0/ */ - -MARIONETTE_TIMEOUT = 60000; -MARIONETTE_HEAD_JS = 'head.js'; - -const number = "****5555552368****"; -var outCall; - -function testDialOutInvalidNumber() { - log("Make an outCall call to an invalid number."); - - // Note: The number is valid from the view of phone and the call could be - // dialed out successfully. However, it will later receive the BadNumberError - // from network side. - return telephony.dial(number).then(call => { - outCall = call; - ok(outCall); - is(outCall.id.number, ""); // Emulator returns empty number for this call. - is(outCall.state, "dialing"); - - is(outCall, telephony.active); - is(telephony.calls.length, 1); - is(telephony.calls[0], outCall); - - return gWaitForEvent(outCall, "error").then(event => { - is(event.call, outCall); - ok(event.call.error); - is(event.call.error.name, "BadNumberError"); - is(event.call.disconnectedReason, "BadNumber"); - }) - .then(() => gCheckAll(null, [], "", [], [])); - }); -} - -startTest(function() { - testDialOutInvalidNumber() - .catch(error => ok(false, "Promise reject: " + error)) - .then(finish); -}); diff --git a/dom/telephony/test/marionette/test_outgoing_busy.js b/dom/telephony/test/marionette/test_outgoing_busy.js deleted file mode 100644 index 1a77316db233..000000000000 --- a/dom/telephony/test/marionette/test_outgoing_busy.js +++ /dev/null @@ -1,28 +0,0 @@ -/* Any copyright is dedicated to the Public Domain. - * http://creativecommons.org/publicdomain/zero/1.0/ */ - -MARIONETTE_TIMEOUT = 60000; -MARIONETTE_HEAD_JS = 'head.js'; - -const outNumber = "5555551111"; -const outInfo = gOutCallStrPool(outNumber); -var outCall; - -startTest(function() { - gDial(outNumber) - .then(call => outCall = call) - .then(() => gCheckAll(outCall, [outCall], "", [], [outInfo.ringing])) - .then(() => { - let p1 = gWaitForEvent(outCall, "error") - .then(event => { - is(event.call, outCall); - is(event.call.error.name, "BusyError"); - is(event.call.disconnectedReason, "Busy"); - }); - let p2 = emulator.runCmd("telephony busy " + outNumber); - return Promise.all([p1, p2]); - }) - .then(() => gCheckAll(null, [], "", [], [])) - .catch(error => ok(false, "Promise reject: " + error)) - .then(finish); -}); diff --git a/dom/telephony/test/marionette/test_outgoing_from_stk.js b/dom/telephony/test/marionette/test_outgoing_from_stk.js deleted file mode 100644 index 61b14f35dd14..000000000000 --- a/dom/telephony/test/marionette/test_outgoing_from_stk.js +++ /dev/null @@ -1,65 +0,0 @@ -/* Any copyright is dedicated to the Public Domain. - * http://creativecommons.org/publicdomain/zero/1.0/ */ - -MARIONETTE_TIMEOUT = 90000; -MARIONETTE_HEAD_JS = 'head.js'; - -const outNumber = "5555552222"; -const outInfo = gOutCallStrPool(outNumber); -var outCall; - -// Basic functions - -function outgoing() { - return gDialSTK(outNumber) - .then(call => outCall = call) - .then(() => gCheckAll(outCall, [outCall], "", [], [outInfo.ringing])); -} - -function localHangUp() { - return gHangUp(outCall) - .then(() => gCheckAll(null, [], "", [], [])); -} - -function remoteAnswer() { - return gRemoteAnswer(outCall) - .then(() => gCheckAll(outCall, [outCall], "", [], [outInfo.active])); -} - -function remoteHangUp() { - return gRemoteHangUp(outCall) - .then(() => gCheckAll(null, [], "", [], [])); -} - -// Sub tests - -function testOutgoingLocalHangUp(){ - log("= testOutgoingLocalHangUp ="); - return outgoing() - .then(() => localHangUp()); -} - -function testOutgoingRemoteHangUp() { - log("= testOutgoingRemoteHangUp ="); - return outgoing() - .then(() => remoteHangUp()); -} - -function testOutgoingRemoteAnswerRemoteHangUp() { - log("= testOutgoingRemoreAnswerRemoteHangUp ="); - return outgoing() - .then(() => remoteAnswer()) - .then(() => remoteHangUp()); -} - -// Main test - -startTest(function() { - Promise.resolve() - .then(() => testOutgoingLocalHangUp()) - .then(() => testOutgoingRemoteHangUp()) - .then(() => testOutgoingRemoteAnswerRemoteHangUp()) - - .catch(error => ok(false, "Promise reject: " + error)) - .then(finish); -}); diff --git a/dom/telephony/test/marionette/test_outgoing_onstatechange.js b/dom/telephony/test/marionette/test_outgoing_onstatechange.js deleted file mode 100644 index 191b0b64bc74..000000000000 --- a/dom/telephony/test/marionette/test_outgoing_onstatechange.js +++ /dev/null @@ -1,38 +0,0 @@ -/* Any copyright is dedicated to the Public Domain. - * http://creativecommons.org/publicdomain/zero/1.0/ */ - -MARIONETTE_TIMEOUT = 60000; -MARIONETTE_HEAD_JS = 'head.js'; - -const outNumber = "5555551111"; -const outInfo = gOutCallStrPool(outNumber); -var outCall; - -startTest(function() { - gDial(outNumber) - .then(call => outCall = call) - .then(() => gCheckAll(outCall, [outCall], "", [], [outInfo.ringing])) - - // Remote answer. - .then(() => { - let p1 = gWaitForStateChangeEvent(outCall, "connected"); - let p2 = gRemoteAnswer(outCall); - return Promise.all([p1, p2]); - }) - .then(() => gCheckAll(outCall, [outCall], "", [], [outInfo.active])) - - // Hold the call. - .then(() => gHold(outCall)) - .then(() => gCheckAll(null, [outCall], "", [], [outInfo.held])) - - // Resume the call. - .then(() => gResume(outCall)) - .then(() => gCheckAll(outCall, [outCall], "", [], [outInfo.active])) - - // Hang-up call - .then(() => gHangUp(outCall)) - .then(() => gCheckAll(null, [], "", [], [])) - - .catch(error => ok(false, "Promise reject: " + error)) - .then(finish); -}); diff --git a/dom/telephony/test/marionette/test_outgoing_radio_off.js b/dom/telephony/test/marionette/test_outgoing_radio_off.js deleted file mode 100644 index b200d2268e8d..000000000000 --- a/dom/telephony/test/marionette/test_outgoing_radio_off.js +++ /dev/null @@ -1,57 +0,0 @@ -/* Any copyright is dedicated to the Public Domain. - http://creativecommons.org/publicdomain/zero/1.0/ */ - -MARIONETTE_TIMEOUT = 60000; -MARIONETTE_HEAD_JS = 'head.js'; - -const normalNumber = "0912345678"; -const emergencyNumber = "112"; -var outCall; - -function testDial_NormalNumber() { - return gSetRadioEnabledAll(false) - .then(() => gDial(normalNumber)) - .catch(cause => { - is(cause, "RadioNotAvailable"); - return gCheckAll(null, [], "", [], []); - }); -} - -function testDial_EmergencyNumber() { - return gSetRadioEnabledAll(false) - .then(() => gDial(emergencyNumber)) - .then(call => { outCall = call; }) - .then(() => gRemoteAnswer(outCall)) - .then(() => gDelay(1000)) // See Bug 1018051 for the purpose of the delay. - .then(() => gRemoteHangUp(outCall)); -} - -function testDialEmergency_NormalNumber() { - return gSetRadioEnabledAll(false) - .then(() => gDialEmergency(normalNumber)) - .catch(cause => { - is(cause, "RadioNotAvailable"); - return gCheckAll(null, [], "", [], []); - }); -} - -function testDialEmergency_EmergencyNumber() { - return gSetRadioEnabledAll(false) - .then(() => gDialEmergency(emergencyNumber)) - .then(call => { outCall = call; }) - .then(() => gRemoteAnswer(outCall)) - .then(() => gDelay(1000)) // See Bug 1018051 for the purpose of the delay. - .then(() => gRemoteHangUp(outCall)); -} - -startTestWithPermissions(['mobileconnection'], function() { - Promise.resolve() - .then(() => testDial_NormalNumber()) - .then(() => testDial_EmergencyNumber()) - .then(() => testDialEmergency_NormalNumber()) - .then(() => testDialEmergency_EmergencyNumber()) - .catch(error => ok(false, "Promise reject: " + error)) - .then(() => gSetRadioEnabledAll(true)) - .catch(error => ok(false, "Promise reject: " + error)) - .then(finish); -}); diff --git a/dom/telephony/test/marionette/test_outgoing_when_two_calls_on_line.js b/dom/telephony/test/marionette/test_outgoing_when_two_calls_on_line.js deleted file mode 100644 index ffce822307b5..000000000000 --- a/dom/telephony/test/marionette/test_outgoing_when_two_calls_on_line.js +++ /dev/null @@ -1,32 +0,0 @@ -/* Any copyright is dedicated to the Public Domain. - * http://creativecommons.org/publicdomain/zero/1.0/ */ - -MARIONETTE_TIMEOUT = 60000; -MARIONETTE_HEAD_JS = 'head.js'; - -function testReject3rdCall() { - let outCall1; - let outCall2; - - return gDial("0912345001") - .then(call => { outCall1 = call; }) - .then(() => gRemoteAnswer(outCall1)) - .then(() => gHold(outCall1)) - .then(() => gDial("0912345002")) - .then(call => { outCall2 = call; }) - .then(() => gRemoteAnswer(outCall2)) - .then(() => gDial("0912345003")) - .then(call => { - ok(false, "The dial request should be rejected"); - }, cause => { - log("Reject 3rd call, cuase: " + cause); - is(cause, "InvalidStateError"); - }) - .then(() => gRemoteHangUpCalls([outCall1, outCall2])); -} - -startTest(function() { - testReject3rdCall() - .catch(error => ok(false, "Promise reject: " + error)) - .then(finish); -}); diff --git a/dom/telephony/test/marionette/test_ready.js b/dom/telephony/test/marionette/test_ready.js deleted file mode 100644 index f7390bd0e6c6..000000000000 --- a/dom/telephony/test/marionette/test_ready.js +++ /dev/null @@ -1,35 +0,0 @@ -/* Any copyright is dedicated to the Public Domain. - * http://creativecommons.org/publicdomain/zero/1.0/ */ - -MARIONETTE_TIMEOUT = 60000; - -SpecialPowers.addPermission("telephony", true, document); - -function cleanUp() { - SpecialPowers.removePermission("telephony", document); - finish(); -} - -var telephony = window.navigator.mozTelephony; -ok(telephony); - -telephony.ready.then(function() { - log("Telephony got ready"); - - // Test telephony.ready in another window. - let iframe = document.createElement("iframe"); - iframe.addEventListener("load", function load() { - iframe.removeEventListener("load", load); - - let iframeTelephony = iframe.contentWindow.navigator.mozTelephony; - ok(iframeTelephony); - - iframeTelephony.ready.then(function() { - log("Telephony in iframe got ready"); - - cleanUp(); - }); - }); - - document.body.appendChild(iframe); -}); diff --git a/dom/telephony/test/marionette/test_redundant_operations.js b/dom/telephony/test/marionette/test_redundant_operations.js deleted file mode 100644 index df7a2e94a351..000000000000 --- a/dom/telephony/test/marionette/test_redundant_operations.js +++ /dev/null @@ -1,49 +0,0 @@ -/* Any copyright is dedicated to the Public Domain. - * http://creativecommons.org/publicdomain/zero/1.0/ */ - -MARIONETTE_TIMEOUT = 60000; -MARIONETTE_HEAD_JS = 'head.js'; - -const inNumber = "5555552222"; -const inInfo = gInCallStrPool(inNumber); -var inCall; - -function error(aEvent, aAction) { - ok(false, "Received '" + aEvent + "' event when " + aAction); -} - -function checkUnexpected(aMsg, aCall, aEvent, aActionCallback) { - let handler = error.bind(this, aEvent, aMsg); - aCall.addEventListener(aEvent, handler); - - return aActionCallback().then( - () => ok(false, msg + "should be rejected."), - () => gDelay(2000).then(() => aCall.removeEventListener(aEvent, handler))); -} - -startTest(function() { - gRemoteDial(inNumber) - .then(call => inCall = call) - .then(() => gAnswer(inCall)) - .then(() => checkUnexpected("answered an active call", inCall, - "connected", () => inCall.answer())) - .then(() => gHold(inCall)) - .then(() => checkUnexpected("held a held call", inCall, - "held", () => inCall.hold())) - .then(() => checkUnexpected("answered a held call", inCall, - "connected", () => inCall.answer())) - .then(() => gResume(inCall)) - .then(() => checkUnexpected("resumed non-held call", inCall, - "connected", () => inCall.resume())) - .then(() => gHangUp(inCall)) - .then(() => checkUnexpected("answered a disconnected call", inCall, - "connected", () => inCall.answer())) - .then(() => checkUnexpected("held a disconnected call", inCall, - "held", () => inCall.hold())) - .then(() => checkUnexpected("resumed a disconnected call", inCall, - "connected", () => inCall.resume())) - .then(() => checkUnexpected("hang-up a disconnected call", inCall, - "disconnected", () => inCall.hangUp())) - .catch(error => ok(false, "Promise reject: " + error)) - .then(finish); -}); diff --git a/dom/telephony/test/marionette/test_swap_held_and_active.js b/dom/telephony/test/marionette/test_swap_held_and_active.js deleted file mode 100644 index c5c2e7b85618..000000000000 --- a/dom/telephony/test/marionette/test_swap_held_and_active.js +++ /dev/null @@ -1,42 +0,0 @@ -/* Any copyright is dedicated to the Public Domain. - * http://creativecommons.org/publicdomain/zero/1.0/ */ - -MARIONETTE_TIMEOUT = 60000; -MARIONETTE_HEAD_JS = 'head.js'; - -const outNumber = "5555551111"; -const outInfo = gOutCallStrPool(outNumber); -var outCall; - -const inNumber = "5555552222"; -const inInfo = gInCallStrPool(inNumber); -var inCall; - -startTest(function() { - gDial(outNumber) - .then(call => outCall = call) - .then(() => gRemoteAnswer(outCall)) - .then(() => gHold(outCall)) - - .then(() => gRemoteDial(inNumber)) - .then(call => inCall = call) - .then(() => gAnswer(inCall)) - .then(() => gCheckAll(inCall, [outCall, inCall], "", [], - [outInfo.held, inInfo.active])) - - // Swap calls by resuming the held (outgoing) call. Will force active - // (incoming) call to hold. - .then(() => { - let p1 = gWaitForNamedStateEvent(inCall, "held"); - let p2 = gResume(outCall); - return Promise.all([p1, p2]); - }) - .then(() => gCheckAll(outCall, [outCall, inCall], "", [], - [outInfo.active, inInfo.held])) - - .then(() => gHangUp(outCall)) - .then(() => gHangUp(inCall)) - - .catch(error => ok(false, "Promise reject: " + error)) - .then(finish); -}); diff --git a/dom/telephony/test/marionette/test_system_message_telephony_call_ended.js b/dom/telephony/test/marionette/test_system_message_telephony_call_ended.js deleted file mode 100644 index ffd08440a89b..000000000000 --- a/dom/telephony/test/marionette/test_system_message_telephony_call_ended.js +++ /dev/null @@ -1,104 +0,0 @@ -/* Any copyright is dedicated to the Public Domain. - * http://creativecommons.org/publicdomain/zero/1.0/ */ - -MARIONETTE_TIMEOUT = 90000; -MARIONETTE_HEAD_JS = 'head.js'; - -const inNumber = "5555552222"; -const inInfo = gInCallStrPool(inNumber); -var inCall; - -/** - * telephony-call-ended message contains the following fields: - * - serviceId - * - number - * - emergency - * - duration - * - direction - * - hangUpLocal - */ - -function testIncomingReject() { - log("= testIncomingReject ="); - - let p1 = gWaitForSystemMessage("telephony-call-ended") - .then(message => { - is(message.number, inNumber); - is(message.duration, 0); - is(message.direction, "incoming"); - is(message.hangUpLocal, true); - }); - - let p2 = gRemoteDial(inNumber) - .then(call => inCall = call) - .then(() => gHangUp(inCall)); - - return Promise.all([p1, p2]); -} - -function testIncomingCancel() { - log("= testIncomingCancel ="); - - let p1 = gWaitForSystemMessage("telephony-call-ended") - .then(message => { - is(message.number, inNumber); - is(message.duration, 0); - is(message.direction, "incoming"); - is(message.hangUpLocal, false); - }); - - let p2 = gRemoteDial(inNumber) - .then(call => inCall = call) - .then(() => gRemoteHangUp(inCall)); - - return Promise.all([p1, p2]); -} - -function testIncomingAnswerHangUp() { - log("= testIncomingAnswerHangUp ="); - - p1 = gWaitForSystemMessage("telephony-call-ended") - .then(message => { - is(message.number, inNumber); - ok(message.duration > 0); - is(message.direction, "incoming"); - is(message.hangUpLocal, true); - }); - - p2 = gRemoteDial(inNumber) - .then(call => inCall = call) - .then(() => gAnswer(inCall)) - .then(() => gHangUp(inCall)); - - return Promise.all([p1, p2]); -} - -function testIncomingAnswerRemoteHangUp() { - log("= testIncomingAnswerRemoteHangUp ="); - - p1 = gWaitForSystemMessage("telephony-call-ended") - .then(message => { - is(message.number, inNumber); - ok(message.duration > 0); - is(message.direction, "incoming"); - is(message.hangUpLocal, false); - }); - - p2 = gRemoteDial(inNumber) - .then(call => inCall = call) - .then(() => gAnswer(inCall)) - .then(() => gRemoteHangUp(inCall)); - - return Promise.all([p1, p2]); -} - -startTest(function() { - Promise.resolve() - .then(() => testIncomingReject()) - .then(() => testIncomingCancel()) - .then(() => testIncomingAnswerHangUp()) - .then(() => testIncomingAnswerRemoteHangUp()) - - .catch(error => ok(false, "Promise reject: " + error)) - .then(finish); -}); diff --git a/dom/telephony/test/marionette/test_telephony_dsds_default_service_id.js b/dom/telephony/test/marionette/test_telephony_dsds_default_service_id.js deleted file mode 100644 index 1399cbee7cf7..000000000000 --- a/dom/telephony/test/marionette/test_telephony_dsds_default_service_id.js +++ /dev/null @@ -1,127 +0,0 @@ -/* Any copyright is dedicated to the Public Domain. - * http://creativecommons.org/publicdomain/zero/1.0/ */ - -MARIONETTE_TIMEOUT = 60000; -MARIONETTE_CONTEXT = "chrome"; - -Cu.import("resource://gre/modules/Promise.jsm"); - -const TELEPHONY_SERVICE_CONTRACTID = - "@mozilla.org/telephony/telephonyservice;1"; - -const PREF_RIL_NUM_RADIO_INTERFACES = "ril.numRadioInterfaces"; -const PREF_DEFAULT_SERVICE_ID = "dom.telephony.defaultServiceId"; - -function setPrefAndVerify(prefKey, setVal, service, attrName, expectedVal, deferred) { - log(" Set '" + prefKey + "' to " + setVal); - Services.prefs.setIntPref(prefKey, setVal); - let prefVal = Services.prefs.getIntPref(prefKey); - is(prefVal, setVal, "'" + prefKey + "' set to " + setVal); - - window.setTimeout(function() { - let defaultVal = service[attrName]; - is(defaultVal, expectedVal, attrName); - - deferred.resolve(service); - }, 0); -} - -function getNumRadioInterfaces() { - let deferred = Promise.defer(); - - window.setTimeout(function() { - let numRil = Services.prefs.getIntPref(PREF_RIL_NUM_RADIO_INTERFACES); - log("numRil = " + numRil); - - deferred.resolve(numRil); - }, 0); - - return deferred.promise; -} - -function getService(contractId, ifaceName) { - let deferred = Promise.defer(); - - window.setTimeout(function() { - log("Getting service for " + ifaceName); - let service = Cc[contractId].getService(Ci[ifaceName]); - ok(service, "service.constructor is " + service.constructor); - - deferred.resolve(service); - }, 0); - - return deferred.promise; -} - -function checkInitialEquality(attrName, prefKey, service) { - let deferred = Promise.defer(); - - log(" Checking initial value for '" + prefKey + "'"); - let origPrefVal = Services.prefs.getIntPref(prefKey); - ok(isFinite(origPrefVal), "default '" + prefKey + "' value"); - - window.setTimeout(function() { - let defaultVal = service[attrName]; - is(defaultVal, origPrefVal, attrName); - - deferred.resolve(service); - }, 0); - - return deferred.promise; -} - -function checkSetToNegtiveValue(attrName, prefKey, service) { - let deferred = Promise.defer(); - - // Set to -1 and verify defaultVal == 0. - setPrefAndVerify(prefKey, -1, service, attrName, 0, deferred); - - return deferred.promise; -} - -function checkSetToOverflowedValue(attrName, prefKey, numRil, service) { - let deferred = Promise.defer(); - - // Set to larger-equal than numRil and verify defaultVal == 0. - setPrefAndVerify(prefKey, numRil, service, attrName, 0, deferred); - - return deferred.promise; -} - -function checkValueChange(attrName, prefKey, numRil, service) { - let deferred = Promise.defer(); - - if (numRil > 1) { - // Set to (numRil - 1) and verify defaultVal equals. - setPrefAndVerify(prefKey, numRil - 1, service, attrName, numRil - 1, deferred); - } else { - window.setTimeout(function() { - deferred.resolve(service); - }, 0); - } - - return deferred.promise; -} - -function verify(contractId, ifaceName, attrName, prefKey, numRil) { - let deferred = Promise.defer(); - - getService(contractId, ifaceName) - .then(checkInitialEquality.bind(null, attrName, prefKey)) - .then(checkSetToNegtiveValue.bind(null, attrName, prefKey)) - .then(checkSetToOverflowedValue.bind(null, attrName, prefKey, numRil)) - .then(checkValueChange.bind(null, attrName, prefKey, numRil)) - .then(function() { - // Reset. - Services.prefs.clearUserPref(prefKey); - - deferred.resolve(numRil); - }); - - return deferred.promise; -} - -getNumRadioInterfaces() - .then(verify.bind(null, TELEPHONY_SERVICE_CONTRACTID, "nsITelephonyService", - "defaultServiceId", PREF_DEFAULT_SERVICE_ID)) - .then(finish); diff --git a/dom/telephony/test/marionette/test_temporary_clir.js b/dom/telephony/test/marionette/test_temporary_clir.js deleted file mode 100644 index 30342fda39c9..000000000000 --- a/dom/telephony/test/marionette/test_temporary_clir.js +++ /dev/null @@ -1,22 +0,0 @@ -/* Any copyright is dedicated to the Public Domain. - * http://creativecommons.org/publicdomain/zero/1.0/ */ - -MARIONETTE_TIMEOUT = 60000; -MARIONETTE_HEAD_JS = 'head.js'; - -const clirPrefix = "*31#"; -const number = "0912345678"; - -startTest(function() { - let outCall; - - telephony.dial(clirPrefix + number).then(call => { - outCall = call; - - ok(call); - is(call.id.number, number); // Should display the number w/o clir prefix. - }) - .then(() => gRemoteHangUp(outCall)) - .catch(error => ok(false, "Promise reject: " + error)) - .then(finish); -}); diff --git a/dom/telephony/test/xpcshell/header_helpers.js b/dom/telephony/test/xpcshell/header_helpers.js deleted file mode 100644 index fee6392e012c..000000000000 --- a/dom/telephony/test/xpcshell/header_helpers.js +++ /dev/null @@ -1,9 +0,0 @@ -/* Any copyright is dedicated to the Public Domain. - * http://creativecommons.org/publicdomain/zero/1.0/ */ - -"use strict"; - -const {classes: Cc, interfaces: Ci, utils: Cu, results: Cr} = Components; - -var subscriptLoader = Cc["@mozilla.org/moz/jssubscript-loader;1"] - .getService(Ci.mozIJSSubScriptLoader); diff --git a/dom/telephony/test/xpcshell/test_parseMMI.js b/dom/telephony/test/xpcshell/test_parseMMI.js deleted file mode 100644 index 444eb12a87e9..000000000000 --- a/dom/telephony/test/xpcshell/test_parseMMI.js +++ /dev/null @@ -1,271 +0,0 @@ -/* Any copyright is dedicated to the Public Domain. - * http://creativecommons.org/publicdomain/zero/1.0/ */ - -var TS = {}; -subscriptLoader.loadSubScript("resource://gre/components/TelephonyService.js", TS); - -var NS = {}; -subscriptLoader.loadSubScript("resource://gre/modules/DialNumberUtils.jsm", NS); - -function run_test() { - run_next_test(); -} - -function parseMMI(mmiString) { - return NS.DialNumberUtils.parseMMI(mmiString); -} - -add_test(function test_parseMMI_empty() { - let mmi = parseMMI(""); - - equal(mmi, null); - - run_next_test(); -}); - -add_test(function test_parseMMI_undefined() { - let mmi = parseMMI(); - - equal(mmi, null); - - run_next_test(); -}); - -add_test(function test_parseMMI_dial_string() { - let mmi = parseMMI("12345"); - - equal(mmi, null); - - run_next_test(); -}); - -add_test(function test_parseMMI_USSD_without_asterisk_prefix() { - let mmi = parseMMI("123#"); - - equal(mmi, null); - - run_next_test(); -}); - -add_test(function test_parseMMI_USSD() { - let mmi = parseMMI("*123#"); - - equal(mmi.fullMMI, "*123#"); - equal(mmi.procedure, TS.MMI_PROCEDURE_ACTIVATION); - equal(mmi.serviceCode, "123"); - equal(mmi.sia, undefined); - equal(mmi.sib, undefined); - equal(mmi.sic, undefined); - equal(mmi.pwd, undefined); - equal(mmi.dialNumber, undefined); - - run_next_test(); -}); - -add_test(function test_parseMMI_USSD_with_two_sharps() { - let mmi = parseMMI("*225#4384903113430962#"); - - equal(mmi, null); - - run_next_test(); -}); - -add_test(function test_parseMMI_sia() { - let mmi = parseMMI("*123*1#"); - - equal(mmi.fullMMI, "*123*1#"); - equal(mmi.procedure, TS.MMI_PROCEDURE_ACTIVATION); - equal(mmi.serviceCode, "123"); - equal(mmi.sia, "1"); - equal(mmi.sib, undefined); - equal(mmi.sic, undefined); - equal(mmi.pwd, undefined); - equal(mmi.dialNumber, undefined); - - run_next_test(); -}); - -add_test(function test_parseMMI_sib() { - let mmi = parseMMI("*123**1#"); - - equal(mmi.fullMMI, "*123**1#"); - equal(mmi.procedure, TS.MMI_PROCEDURE_ACTIVATION); - equal(mmi.serviceCode, "123"); - equal(mmi.sia, ""); - equal(mmi.sib, "1"); - equal(mmi.sic, undefined); - equal(mmi.pwd, undefined); - equal(mmi.dialNumber, undefined); - - run_next_test(); -}); - -add_test(function test_parseMMI_sic() { - let mmi = parseMMI("*123***1#"); - - equal(mmi.fullMMI, "*123***1#"); - equal(mmi.procedure, TS.MMI_PROCEDURE_ACTIVATION); - equal(mmi.serviceCode, "123"); - equal(mmi.sia, ""); - equal(mmi.sib, ""); - equal(mmi.sic, "1"); - equal(mmi.pwd, undefined); - equal(mmi.dialNumber, undefined); - - run_next_test(); -}); - -add_test(function test_parseMMI_sia_sib() { - let mmi = parseMMI("*123*1*1#"); - - equal(mmi.fullMMI, "*123*1*1#"); - equal(mmi.procedure, TS.MMI_PROCEDURE_ACTIVATION); - equal(mmi.serviceCode, "123"); - equal(mmi.sia, "1"); - equal(mmi.sib, "1"); - equal(mmi.sic, undefined); - equal(mmi.pwd, undefined); - equal(mmi.dialNumber, undefined); - - run_next_test(); -}); - -add_test(function test_parseMMI_sia_sic() { - let mmi = parseMMI("*123*1**1#"); - - equal(mmi.fullMMI, "*123*1**1#"); - equal(mmi.procedure, TS.MMI_PROCEDURE_ACTIVATION); - equal(mmi.serviceCode, "123"); - equal(mmi.sia, "1"); - equal(mmi.sib, ""); - equal(mmi.sic, "1"); - equal(mmi.pwd, undefined); - equal(mmi.dialNumber, undefined); - - run_next_test(); -}); - -add_test(function test_parseMMI_sib_sic() { - let mmi = parseMMI("*123**1*1#"); - - equal(mmi.fullMMI, "*123**1*1#"); - equal(mmi.procedure, TS.MMI_PROCEDURE_ACTIVATION); - equal(mmi.serviceCode, "123"); - equal(mmi.sia, ""); - equal(mmi.sib, "1"); - equal(mmi.sic, "1"); - equal(mmi.pwd, undefined); - equal(mmi.dialNumber, undefined); - - run_next_test(); -}); - -add_test(function test_parseMMI_pwd() { - let mmi = parseMMI("*123****1#"); - - equal(mmi.fullMMI, "*123****1#"); - equal(mmi.procedure, TS.MMI_PROCEDURE_ACTIVATION); - equal(mmi.serviceCode, "123"); - equal(mmi.sia, ""); - equal(mmi.sib, ""); - equal(mmi.sic, ""); - equal(mmi.pwd, "1"); - equal(mmi.dialNumber, undefined); - - run_next_test(); -}); - -add_test(function test_parseMMI_dial_number() { - let mmi = parseMMI("*123#345"); - - equal(mmi.fullMMI, "*123#"); - equal(mmi.procedure, TS.MMI_PROCEDURE_ACTIVATION); - equal(mmi.serviceCode, "123"); - equal(mmi.sia, undefined); - equal(mmi.sib, undefined); - equal(mmi.sic, undefined); - equal(mmi.pwd, undefined); - equal(mmi.dialNumber, "345"); - - run_next_test(); -}); - - -/** - * MMI procedures tests - */ - -add_test(function test_parseMMI_activation() { - let mmi = parseMMI("*00*12*34*56#"); - - equal(mmi.fullMMI, "*00*12*34*56#"); - equal(mmi.procedure, TS.MMI_PROCEDURE_ACTIVATION); - equal(mmi.serviceCode, "00"); - equal(mmi.sia, "12"); - equal(mmi.sib, "34"); - equal(mmi.sic, "56"); - equal(mmi.pwd, undefined); - equal(mmi.dialNumber, undefined); - - run_next_test(); -}); - -add_test(function test_parseMMI_deactivation() { - let mmi = parseMMI("#00*12*34*56#"); - - equal(mmi.fullMMI, "#00*12*34*56#"); - equal(mmi.procedure, TS.MMI_PROCEDURE_DEACTIVATION); - equal(mmi.serviceCode, "00"); - equal(mmi.sia, "12"); - equal(mmi.sib, "34"); - equal(mmi.sic, "56"); - equal(mmi.pwd, undefined); - equal(mmi.dialNumber, undefined); - - run_next_test(); -}); - -add_test(function test_parseMMI_interrogation() { - let mmi = parseMMI("*#00*12*34*56#"); - - equal(mmi.fullMMI, "*#00*12*34*56#"); - equal(mmi.procedure, TS.MMI_PROCEDURE_INTERROGATION); - equal(mmi.serviceCode, "00"); - equal(mmi.sia, "12"); - equal(mmi.sib, "34"); - equal(mmi.sic, "56"); - equal(mmi.pwd, undefined); - equal(mmi.dialNumber, undefined); - - run_next_test(); -}); - -add_test(function test_parseMMI_registration() { - let mmi = parseMMI("**00*12*34*56#"); - - equal(mmi.fullMMI, "**00*12*34*56#"); - equal(mmi.procedure, TS.MMI_PROCEDURE_REGISTRATION); - equal(mmi.serviceCode, "00"); - equal(mmi.sia, "12"); - equal(mmi.sib, "34"); - equal(mmi.sic, "56"); - equal(mmi.pwd, undefined); - equal(mmi.dialNumber, undefined); - - run_next_test(); -}); - -add_test(function test_parseMMI_erasure() { - let mmi = parseMMI("##00*12*34*56#"); - - equal(mmi.fullMMI, "##00*12*34*56#"); - equal(mmi.procedure, TS.MMI_PROCEDURE_ERASURE); - equal(mmi.serviceCode, "00"); - equal(mmi.sia, "12"); - equal(mmi.sib, "34"); - equal(mmi.sic, "56"); - equal(mmi.pwd, undefined); - equal(mmi.dialNumber, undefined); - - run_next_test(); -}); diff --git a/dom/telephony/test/xpcshell/xpcshell.ini b/dom/telephony/test/xpcshell/xpcshell.ini deleted file mode 100644 index 0867ebc50c20..000000000000 --- a/dom/telephony/test/xpcshell/xpcshell.ini +++ /dev/null @@ -1,5 +0,0 @@ -[DEFAULT] -head = header_helpers.js -tail = - -[test_parseMMI.js] diff --git a/dom/webidl/CallEvent.webidl b/dom/webidl/CallEvent.webidl deleted file mode 100644 index 5add9254d757..000000000000 --- a/dom/webidl/CallEvent.webidl +++ /dev/null @@ -1,16 +0,0 @@ -/* -*- Mode: IDL; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ -/* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this file, - * You can obtain one at http://mozilla.org/MPL/2.0/. - */ - -[Constructor(DOMString type, optional CallEventInit eventInitDict), Pref="dom.telephony.enabled"] -interface CallEvent : Event -{ - readonly attribute TelephonyCall? call; -}; - -dictionary CallEventInit : EventInit -{ - TelephonyCall? call = null; -}; diff --git a/dom/webidl/CallGroupErrorEvent.webidl b/dom/webidl/CallGroupErrorEvent.webidl deleted file mode 100644 index ee46245188c2..000000000000 --- a/dom/webidl/CallGroupErrorEvent.webidl +++ /dev/null @@ -1,20 +0,0 @@ -/* -*- Mode: IDL; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ -/* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this file, - * You can obtain one at http://mozilla.org/MPL/2.0/. - */ - -[Pref="dom.telephony.enabled", - Constructor(DOMString type, - optional CallGroupErrorEventInit eventInitDict)] -interface CallGroupErrorEvent : Event -{ - readonly attribute DOMString? name; - readonly attribute DOMString? message; -}; - -dictionary CallGroupErrorEventInit : EventInit -{ - DOMString name = ""; - DOMString message = ""; -}; diff --git a/dom/webidl/CallsList.webidl b/dom/webidl/CallsList.webidl deleted file mode 100644 index 251a0b91d5f4..000000000000 --- a/dom/webidl/CallsList.webidl +++ /dev/null @@ -1,11 +0,0 @@ -/* -*- Mode: IDL; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ -/* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this file, - * You can obtain one at http://mozilla.org/MPL/2.0/. - */ - -[ArrayClass, NoInterfaceObject] -interface CallsList { - getter TelephonyCall item(unsigned long index); - readonly attribute unsigned long length; -}; diff --git a/dom/webidl/MMICall.webidl b/dom/webidl/MMICall.webidl deleted file mode 100644 index ec066b3bae1b..000000000000 --- a/dom/webidl/MMICall.webidl +++ /dev/null @@ -1,12 +0,0 @@ -/* -*- Mode: IDL; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ -/* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. - */ - -[Pref="dom.telephony.enabled", - ChromeOnly] -interface MMICall { - [Throws] - readonly attribute Promise result; -}; diff --git a/dom/webidl/Navigator.webidl b/dom/webidl/Navigator.webidl index 71e6bfd76891..fb4f035a85c3 100644 --- a/dom/webidl/Navigator.webidl +++ b/dom/webidl/Navigator.webidl @@ -280,11 +280,6 @@ partial interface Navigator { UnsafeInPrerendering] readonly attribute MozIccManager? mozIccManager; }; - -partial interface Navigator { - [Throws, Pref="dom.telephony.enabled", ChromeOnly, UnsafeInPrerendering] - readonly attribute Telephony? mozTelephony; -}; #endif // MOZ_B2G_RIL #ifdef MOZ_GAMEPAD diff --git a/dom/webidl/Telephony.webidl b/dom/webidl/Telephony.webidl deleted file mode 100644 index 9440efc52900..000000000000 --- a/dom/webidl/Telephony.webidl +++ /dev/null @@ -1,77 +0,0 @@ -/* -*- Mode: IDL; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ -/* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. - */ - -[Pref="dom.telephony.enabled"] -interface Telephony : EventTarget { - /** - * There are multiple telephony services in multi-sim architecture. We use - * |serviceId| to indicate the target telephony service. If not specified, - * the implementation MUST use the default service. - * - * Possible values of |serviceId| are 0 ~ (number of services - 1), which is - * simply the index of a service. Get number of services by acquiring - * |navigator.mozMobileConnections.length|. - */ - - /** - * Make a phone call or send the mmi code depending on the number provided. - * - * TelephonyCall - for call setup - * MMICall - for MMI code - */ - [Throws] - Promise<(TelephonyCall or MMICall)> dial(DOMString number, optional unsigned long serviceId); - - [Throws] - Promise dialEmergency(DOMString number, optional unsigned long serviceId); - -/** - * Send a series of DTMF tones. - * - * @param tones - * DTMF chars. - * @param pauseDuraton (ms) [optional] - * Time to wait before sending tones. Default value is 3000 ms. - * @param toneDuration (ms) [optional] - * Duration of each tone. Default value is 70 ms. - * @param serviceId [optional] - * Default value is as user setting dom.telephony.defaultServiceId. - */ - [Throws] - Promise sendTones(DOMString tones, optional unsigned long pauseDuration = 3000, optional unsigned long toneDuration = 70, optional unsigned long serviceId); - - [Throws] - void startTone(DOMString tone, optional unsigned long serviceId); - - [Throws] - void stopTone(optional unsigned long serviceId); - - // Calling this method, the app will be treated as owner of the telephony - // calls from the AudioChannel policy. - [Throws] - void ownAudioChannel(); - - [Throws] - attribute boolean muted; - - [Throws] - attribute boolean speakerEnabled; - - readonly attribute (TelephonyCall or TelephonyCallGroup)? active; - - // A call is contained either in Telephony or in TelephonyCallGroup. - readonly attribute CallsList calls; - readonly attribute TelephonyCallGroup conferenceGroup; - - // Async notification that object initialization is done. - [Throws] - readonly attribute Promise ready; - - attribute EventHandler onincoming; - attribute EventHandler oncallschanged; - attribute EventHandler onremoteheld; - attribute EventHandler onremoteresumed; -}; diff --git a/dom/webidl/TelephonyCall.webidl b/dom/webidl/TelephonyCall.webidl deleted file mode 100644 index 7a44866ed513..000000000000 --- a/dom/webidl/TelephonyCall.webidl +++ /dev/null @@ -1,133 +0,0 @@ -/* -*- Mode: IDL; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ -/* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. - */ - -[Pref="dom.telephony.enabled"] -interface TelephonyCall : EventTarget { - // Indicate which service the call comes from. - readonly attribute unsigned long serviceId; - - readonly attribute TelephonyCallId id; - - // In CDMA networks, the 2nd waiting call shares the connection with the 1st - // call. We need an additional attribute for the CDMA waiting call. - readonly attribute TelephonyCallId? secondId; - - readonly attribute TelephonyCallState state; - - // The property "emergency" indicates whether the call number is an emergency - // number. Only the outgoing call could have a value with true and it is - // available after dialing state. - readonly attribute boolean emergency; - - // Indicate whether the call state can be switched between "connected" and - // "held". - readonly attribute boolean switchable; - - // Indicate whether the call can be added into TelephonyCallGroup. - readonly attribute boolean mergeable; - - readonly attribute DOMError? error; - - readonly attribute TelephonyCallDisconnectedReason? disconnectedReason; - - readonly attribute TelephonyCallGroup? group; - - [NewObject] - Promise answer(); - [NewObject] - Promise hangUp(); - [NewObject] - Promise hold(); - [NewObject] - Promise resume(); - - attribute EventHandler onstatechange; - attribute EventHandler ondialing; - attribute EventHandler onalerting; - attribute EventHandler onconnected; - attribute EventHandler ondisconnected; - attribute EventHandler onheld; - attribute EventHandler onerror; - - // Fired whenever the group attribute changes. - attribute EventHandler ongroupchange; -}; - -enum TelephonyCallState { - "dialing", - "alerting", - "connected", - "held", - "disconnected", - "incoming", -}; - -enum TelephonyCallDisconnectedReason { - "BadNumber", - "NoRouteToDestination", - "ChannelUnacceptable", - "OperatorDeterminedBarring", - "NormalCallClearing", - "Busy", - "NoUserResponding", - "UserAlertingNoAnswer", - "CallRejected", - "NumberChanged", - "CallRejectedDestinationFeature", - "PreEmption", - "DestinationOutOfOrder", - "InvalidNumberFormat", - "FacilityRejected", - "ResponseToStatusEnquiry", - "Congestion", - "NetworkOutOfOrder", - "NetworkTempFailure", - "SwitchingEquipCongestion", - "AccessInfoDiscarded", - "RequestedChannelNotAvailable", - "ResourceUnavailable", - "QosUnavailable", - "RequestedFacilityNotSubscribed", - "IncomingCallsBarredWithinCug", - "BearerCapabilityNotAuthorized", - "BearerCapabilityNotAvailable", - "BearerNotImplemented", - "ServiceNotAvailable", - "IncomingCallExceeded", - "RequestedFacilityNotImplemented", - "UnrestrictedBearerNotAvailable", - "ServiceNotImplemented", - "InvalidTransactionId", - "NotCugMember", - "IncompatibleDestination", - "InvalidTransitNetworkSelection", - "SemanticallyIncorrectMessage", - "InvalidMandatoryInfo", - "MessageTypeNotImplemented", - "MessageTypeIncompatibleProtocolState", - "InfoElementNotImplemented", - "ConditionalIe", - "MessageIncompatibleProtocolState", - "RecoveryOnTimerExpiry", - "Protocol", - "Interworking", - "Barred", - "FDNBlocked", - "SubscriberUnknown", - "DeviceNotAccepted", - "ModifiedDial", - "CdmaLockedUntilPowerCycle", - "CdmaDrop", - "CdmaIntercept", - "CdmaReorder", - "CdmaSoReject", - "CdmaRetryOrder", - "CdmaAcess", - "CdmaPreempted", - "CdmaNotEmergency", - "CdmaAccessBlocked", - "Unspecified", -}; diff --git a/dom/webidl/TelephonyCallGroup.webidl b/dom/webidl/TelephonyCallGroup.webidl deleted file mode 100644 index e5af4083094c..000000000000 --- a/dom/webidl/TelephonyCallGroup.webidl +++ /dev/null @@ -1,42 +0,0 @@ -/* -*- Mode: c++; c-basic-offset: 2; indent-tabs-mode: nil; tab-width: 40 -*- */ -/* vim: set ts=2 et sw=2 tw=40: */ -/* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ - -[Pref="dom.telephony.enabled"] -interface TelephonyCallGroup : EventTarget { - readonly attribute CallsList calls; - - [NewObject, Throws] - Promise add(TelephonyCall call); - - [NewObject, Throws] - Promise add(TelephonyCall call, TelephonyCall secondCall); - - [NewObject, Throws] - Promise remove(TelephonyCall call); - - [NewObject] - Promise hangUp(); - - [NewObject, Throws] - Promise hold(); - - [NewObject, Throws] - Promise resume(); - - readonly attribute TelephonyCallGroupState state; - - attribute EventHandler onstatechange; - attribute EventHandler onconnected; - attribute EventHandler onheld; - attribute EventHandler oncallschanged; - attribute EventHandler onerror; -}; - -enum TelephonyCallGroupState { - "", - "connected", - "held", -}; diff --git a/dom/webidl/TelephonyCallId.webidl b/dom/webidl/TelephonyCallId.webidl deleted file mode 100644 index 1cc8201d3a57..000000000000 --- a/dom/webidl/TelephonyCallId.webidl +++ /dev/null @@ -1,35 +0,0 @@ -/* -*- Mode: IDL; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ -/* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this file, - * You can obtain one at http://mozilla.org/MPL/2.0/. - */ - -enum CallIdPresentation { - "allowed", - // Call number/name has been withheld by the calling party. - "restricted", - // Call number is not available due to calling party being of type payphone. - "payphone", - // Call number/name is not available due to networking problems or other reason. - "unknown" -}; - -[Pref="dom.telephony.enabled"] -interface TelephonyCallId { - // It is an empty string when "numberPresentation" is not "allowed." - readonly attribute DOMString number; - - // This attribute is not relevant for outgoing calls. Default value is - // "allowed." - readonly attribute CallIdPresentation numberPresentation; - - // This attribute is not relevant for outgoing calls. It is an empty string - // 1) when the call is outgoing, or 2) when the call is incoming and - // "namePresentation" is not "allowed." However, it could still be empty - // even the call is incoming and "namePresentation" is "allowed." - readonly attribute DOMString name; - - // This attribute is not relevant for outgoing calls. Default value is - // "allowed." - readonly attribute CallIdPresentation namePresentation; -}; diff --git a/dom/webidl/USSDReceivedEvent.webidl b/dom/webidl/USSDReceivedEvent.webidl deleted file mode 100644 index 5d11ad5a014e..000000000000 --- a/dom/webidl/USSDReceivedEvent.webidl +++ /dev/null @@ -1,22 +0,0 @@ -/* -*- Mode: IDL; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ -/* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this file, - * You can obtain one at http://mozilla.org/MPL/2.0/. - */ - -[Pref="dom.telephony.enabled", - ChromeOnly, - Constructor(DOMString type, optional USSDReceivedEventInit eventInitDict)] -interface USSDReceivedEvent : Event -{ - readonly attribute unsigned long serviceId; - readonly attribute DOMString? message; - readonly attribute USSDSession? session; // null if session is ended. -}; - -dictionary USSDReceivedEventInit : EventInit -{ - unsigned long serviceId = 0; - DOMString? message = null; - USSDSession? session = null; -}; diff --git a/dom/webidl/USSDSession.webidl b/dom/webidl/USSDSession.webidl deleted file mode 100644 index 3e86c3ba297d..000000000000 --- a/dom/webidl/USSDSession.webidl +++ /dev/null @@ -1,16 +0,0 @@ -/* -*- Mode: IDL; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ -/* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. - */ - -[Pref="dom.telephony.enabled", - ChromeOnly, - Constructor(unsigned long serviceId)] -interface USSDSession { - [NewObject] - Promise send(DOMString ussd); - - [NewObject] - Promise cancel(); -}; diff --git a/dom/webidl/moz.build b/dom/webidl/moz.build index 57738359141c..a3806aadeb87 100644 --- a/dom/webidl/moz.build +++ b/dom/webidl/moz.build @@ -63,7 +63,6 @@ WEBIDL_FILES = [ 'BrowserElementProxy.webidl', 'Cache.webidl', 'CacheStorage.webidl', - 'CallsList.webidl', 'CanvasCaptureMediaStream.webidl', 'CanvasRenderingContext2D.webidl', 'CaretPosition.webidl', @@ -323,7 +322,6 @@ WEBIDL_FILES = [ 'MessagePort.webidl', 'MimeType.webidl', 'MimeTypeArray.webidl', - 'MMICall.webidl', 'MouseEvent.webidl', 'MouseScrollEvent.webidl', 'MozIcc.webidl', @@ -545,10 +543,6 @@ WEBIDL_FILES = [ 'TCPSocket.webidl', 'TCPSocketErrorEvent.webidl', 'TCPSocketEvent.webidl', - 'Telephony.webidl', - 'TelephonyCall.webidl', - 'TelephonyCallGroup.webidl', - 'TelephonyCallId.webidl', 'Text.webidl', 'TextClause.webidl', 'TextDecoder.webidl', @@ -574,7 +568,6 @@ WEBIDL_FILES = [ 'UIEvent.webidl', 'URL.webidl', 'URLSearchParams.webidl', - 'USSDSession.webidl', 'ValidityState.webidl', 'VideoPlaybackQuality.webidl', 'VideoStreamTrack.webidl', @@ -743,8 +736,6 @@ GENERATED_EVENTS_WEBIDL_FILES = [ 'AnimationPlaybackEvent.webidl', 'AutocompleteErrorEvent.webidl', 'BlobEvent.webidl', - 'CallEvent.webidl', - 'CallGroupErrorEvent.webidl', 'CaretStateChangedEvent.webidl', 'CFStateChangeEvent.webidl', 'CloseEvent.webidl', @@ -789,7 +780,6 @@ GENERATED_EVENTS_WEBIDL_FILES = [ 'TrackEvent.webidl', 'UDPMessageEvent.webidl', 'UserProximityEvent.webidl', - 'USSDReceivedEvent.webidl', 'WebGLContextEvent.webidl', ] diff --git a/layout/build/moz.build b/layout/build/moz.build index 9f62b1907fc5..6fd3589813d1 100644 --- a/layout/build/moz.build +++ b/layout/build/moz.build @@ -42,7 +42,6 @@ LOCAL_INCLUDES += [ '/dom/speakermanager', '/dom/storage', '/dom/svg', - '/dom/telephony', '/dom/xbl', '/dom/xslt/base', '/dom/xslt/xml', diff --git a/layout/build/nsLayoutModule.cpp b/layout/build/nsLayoutModule.cpp index a4e28dca484a..552ccc378ca4 100644 --- a/layout/build/nsLayoutModule.cpp +++ b/layout/build/nsLayoutModule.cpp @@ -105,8 +105,6 @@ using mozilla::dom::gonk::SystemWorkerManager; #define SYSTEMWORKERMANAGER_CID \ {0xd53b6524, 0x6ac3, 0x42b0, {0xae, 0xca, 0x62, 0xb3, 0xc4, 0xe5, 0x2b, 0x04}} -#define SYSTEMWORKERMANAGER_CONTRACTID \ - "@mozilla.org/telephony/system-worker-manager;1" #endif #ifdef MOZ_B2G_BT @@ -213,7 +211,6 @@ static void Shutdown(); #include "StreamingProtocolService.h" #include "nsIPresentationService.h" -#include "nsITelephonyService.h" #include "FakeInputPortService.h" #include "InputPortData.h" @@ -359,8 +356,6 @@ NS_GENERIC_FACTORY_SINGLETON_CONSTRUCTOR(nsIMediaManagerService, MediaManager::GetInstance) NS_GENERIC_FACTORY_SINGLETON_CONSTRUCTOR(nsIMobileConnectionService, NS_CreateMobileConnectionService) -NS_GENERIC_FACTORY_SINGLETON_CONSTRUCTOR(nsITelephonyService, - NS_CreateTelephonyService) NS_GENERIC_FACTORY_CONSTRUCTOR(PresentationDeviceManager) NS_GENERIC_FACTORY_CONSTRUCTOR(TextInputProcessor) NS_GENERIC_FACTORY_SINGLETON_CONSTRUCTOR(FakeInputPortService, @@ -794,7 +789,6 @@ NS_DEFINE_NAMED_CID(NS_HAPTICFEEDBACK_CID); NS_DEFINE_NAMED_CID(GONK_GPS_GEOLOCATION_PROVIDER_CID); #endif #endif -NS_DEFINE_NAMED_CID(TELEPHONY_SERVICE_CID); NS_DEFINE_NAMED_CID(NS_MOBILE_CONNECTION_SERVICE_CID); NS_DEFINE_NAMED_CID(ICC_SERVICE_CID); NS_DEFINE_NAMED_CID(NS_POWERMANAGERSERVICE_CID); @@ -1103,7 +1097,6 @@ static const mozilla::Module::CIDEntry kLayoutCIDs[] = { #ifdef ACCESSIBILITY { &kNS_ACCESSIBILITY_SERVICE_CID, false, nullptr, CreateA11yService }, #endif - { &kTELEPHONY_SERVICE_CID, false, nullptr, nsITelephonyServiceConstructor }, { &kNS_MOBILE_CONNECTION_SERVICE_CID, false, NULL, nsIMobileConnectionServiceConstructor }, { &kPRESENTATION_SERVICE_CID, false, nullptr, nsIPresentationServiceConstructor }, { &kPRESENTATION_DEVICE_MANAGER_CID, false, nullptr, PresentationDeviceManagerConstructor }, @@ -1257,7 +1250,6 @@ static const mozilla::Module::ContractIDEntry kLayoutContracts[] = { { "@mozilla.org/accessibilityService;1", &kNS_ACCESSIBILITY_SERVICE_CID }, { "@mozilla.org/accessibleRetrieval;1", &kNS_ACCESSIBILITY_SERVICE_CID }, #endif - { TELEPHONY_SERVICE_CONTRACTID, &kTELEPHONY_SERVICE_CID }, { "@mozilla.org/gecko-media-plugin-service;1", &kGECKO_MEDIA_PLUGIN_SERVICE_CID }, { NS_MOBILE_CONNECTION_SERVICE_CONTRACTID, &kNS_MOBILE_CONNECTION_SERVICE_CID }, { PRESENTATION_SERVICE_CONTRACTID, &kPRESENTATION_SERVICE_CID }, diff --git a/modules/libpref/init/all.js b/modules/libpref/init/all.js index 56ea694de04b..cd0018737de3 100644 --- a/modules/libpref/init/all.js +++ b/modules/libpref/init/all.js @@ -5003,16 +5003,6 @@ pref("dom.mozInputMethod.enabled", false); pref("dom.flyweb.enabled", false); -// Telephony API -#ifdef MOZ_B2G_RIL -pref("dom.telephony.enabled", true); -#else -pref("dom.telephony.enabled", false); -#endif -// Numeric default service id for WebTelephony API calls with |serviceId| -// parameter omitted. -pref("dom.telephony.defaultServiceId", 0); - // ICC API #ifdef MOZ_B2G_RIL pref("dom.icc.enabled", true); diff --git a/testing/marionette/harness/marionette/tests/webapi-tests.ini b/testing/marionette/harness/marionette/tests/webapi-tests.ini index 3a6915e36b47..4dd6b66d37d3 100644 --- a/testing/marionette/harness/marionette/tests/webapi-tests.ini +++ b/testing/marionette/harness/marionette/tests/webapi-tests.ini @@ -1,5 +1,4 @@ [include:../../../../../dom/bluetooth/tests/marionette/manifest.ini] -[include:../../../../../dom/telephony/test/marionette/manifest.ini] [include:../../../../../dom/battery/test/marionette/manifest.ini] [include:../../../../../dom/mobileconnection/tests/marionette/manifest.ini] [include:../../../../../dom/system/gonk/tests/marionette/manifest.ini] From 1fa27577d0e08b17ec6aa28933213bdbe9079e6c Mon Sep 17 00:00:00 2001 From: Xidorn Quan Date: Tue, 25 Oct 2016 17:25:10 +1100 Subject: [PATCH 20/60] Bug 1310123 - Move values of static constants in nsStyleStruct to the header. r=mats MozReview-Commit-ID: J5Fp0iAEnkg --HG-- extra : rebase_source : b8366ff6b14493f53c0aa8880850adcad7495983 --- layout/style/nsStyleStruct.cpp | 8 +++----- layout/style/nsStyleStruct.h | 8 +++++--- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/layout/style/nsStyleStruct.cpp b/layout/style/nsStyleStruct.cpp index 9d76b0832a36..16d9e80d9a5e 100644 --- a/layout/style/nsStyleStruct.cpp +++ b/layout/style/nsStyleStruct.cpp @@ -45,10 +45,8 @@ static_assert((((1 << nsStyleStructID_Length) - 1) & ~(NS_STYLE_INHERIT_MASK)) == 0, "Not enough bits in NS_STYLE_INHERIT_MASK"); -// These are the limits that we choose to clamp grid line numbers to. -// http://dev.w3.org/csswg/css-grid/#overlarge-grids -const int32_t nsStyleGridLine::kMinLine = -10000; -const int32_t nsStyleGridLine::kMaxLine = 10000; +/* static */ const int32_t nsStyleGridLine::kMinLine; +/* static */ const int32_t nsStyleGridLine::kMaxLine; static bool EqualURIs(nsIURI *aURI1, nsIURI *aURI2) @@ -822,7 +820,7 @@ nsStyleXUL::CalcDifference(const nsStyleXUL& aNewData) const // -------------------- // nsStyleColumn // -/* static */ const uint32_t nsStyleColumn::kMaxColumnCount = 1000; +/* static */ const uint32_t nsStyleColumn::kMaxColumnCount; nsStyleColumn::nsStyleColumn(StyleStructContext aContext) : mColumnCount(NS_STYLE_COLUMN_COUNT_AUTO) diff --git a/layout/style/nsStyleStruct.h b/layout/style/nsStyleStruct.h index b9ac3ff32771..5a7e85197a30 100644 --- a/layout/style/nsStyleStruct.h +++ b/layout/style/nsStyleStruct.h @@ -1593,9 +1593,11 @@ struct nsStyleGridLine int32_t mInteger; // 0 means not provided nsString mLineName; // Empty string means not provided. + // These are the limits that we choose to clamp grid line numbers to. + // http://dev.w3.org/csswg/css-grid/#overlarge-grids // mInteger is clamped to this range: - static const int32_t kMinLine; - static const int32_t kMaxLine; + static const int32_t kMinLine = -10000; + static const int32_t kMaxLine = 10000; nsStyleGridLine() : mHasSpan(false) @@ -3467,7 +3469,7 @@ struct MOZ_NEEDS_MEMMOVABLE_MEMBERS nsStyleColumn * This is the maximum number of columns we can process. It's used in both * nsColumnSetFrame and nsRuleNode. */ - static const uint32_t kMaxColumnCount; + static const uint32_t kMaxColumnCount = 1000; uint32_t mColumnCount; // [reset] see nsStyleConsts.h nsStyleCoord mColumnWidth; // [reset] coord, auto From 47aa3f8372859eb0f8158694b123720cdaaa3de6 Mon Sep 17 00:00:00 2001 From: Tomislav Jovanovic Date: Wed, 12 Oct 2016 05:48:04 +0200 Subject: [PATCH 21/60] bug 1272890 - implement match_about_blank for content scripts r=kmag MozReview-Commit-ID: 3iZLpUw5LF4 --HG-- extra : rebase_source : d520a13211584af096f68cd0a2cfec022a72e413 --- .../extensions/ExtensionContent.jsm | 36 ++++-- .../test/mochitest/file_with_about_blank.html | 10 ++ .../extensions/test/mochitest/mochitest.ini | 3 + .../test_ext_contentscript_about_blank.html | 117 ++++++++++++++++++ 4 files changed, 159 insertions(+), 7 deletions(-) create mode 100644 toolkit/components/extensions/test/mochitest/file_with_about_blank.html create mode 100644 toolkit/components/extensions/test/mochitest/test_ext_contentscript_about_blank.html diff --git a/toolkit/components/extensions/ExtensionContent.jsm b/toolkit/components/extensions/ExtensionContent.jsm index ceaf889eb35b..4415d57a944b 100644 --- a/toolkit/components/extensions/ExtensionContent.jsm +++ b/toolkit/components/extensions/ExtensionContent.jsm @@ -101,6 +101,7 @@ function Script(extension, options, deferred = PromiseUtils.defer()) { this.js = this.options.js || []; this.css = this.options.css || []; this.remove_css = this.options.remove_css; + this.match_about_blank = this.options.match_about_blank; this.deferred = deferred; @@ -140,6 +141,12 @@ Script.prototype = { return false; } + if (this.match_about_blank && ["about:blank", "about:srcdoc"].includes(uri.spec)) { + // When matching about:blank/srcdoc documents, the checks below + // need to be performed against the "owner" document's URI. + uri = window.document.nodePrincipal.URI; + } + if (!(this.matches_.matches(uri) || this.matches_host_.matchesIgnoringPath(uri))) { return false; } @@ -166,8 +173,6 @@ Script.prototype = { return false; } - // TODO: match_about_blank. - return true; }, @@ -426,11 +431,13 @@ DocumentManager = { extensionPageWindows: new Map(), init() { + Services.obs.addObserver(this, "content-document-global-created", false); Services.obs.addObserver(this, "document-element-inserted", false); Services.obs.addObserver(this, "inner-window-destroyed", false); }, uninit() { + Services.obs.removeObserver(this, "content-document-global-created"); Services.obs.removeObserver(this, "document-element-inserted"); Services.obs.removeObserver(this, "inner-window-destroyed"); }, @@ -447,13 +454,27 @@ DocumentManager = { }, observe: function(subject, topic, data) { - if (topic == "document-element-inserted") { + // For some types of documents (about:blank), we only see the first + // notification, for others (data: URIs) we only observe the second. + if (topic == "content-document-global-created" || topic == "document-element-inserted") { let document = subject; let window = document && document.defaultView; + + if (topic == "content-document-global-created") { + window = subject; + document = window && window.document; + } + if (!document || !document.location || !window) { return; } + // Make sure we always load exactly once (notice != used as logical XOR), + // usually on document-element-inserted, except for about:blank documents. + if ((topic == "content-document-global-created") != (window.location.href == "about:blank")) { + return; + } + // Make sure we only load into frames that ExtensionContent.init // was called on (i.e., not frames for social or sidebars). let mm = getWindowMessageManager(window); @@ -482,7 +503,8 @@ DocumentManager = { } } - this.trigger("document_start", window); + this.trigger(window); + /* eslint-disable mozilla/balanced-listeners */ window.addEventListener("DOMContentLoaded", this, true); window.addEventListener("load", this, true); @@ -526,9 +548,9 @@ DocumentManager = { // Need to check if we're still on the right page? Greasemonkey does this. if (event.type == "DOMContentLoaded") { - this.trigger("document_end", window); + this.trigger(window); } else if (event.type == "load") { - this.trigger("document_idle", window); + this.trigger(window); } }, @@ -666,7 +688,7 @@ DocumentManager = { } }, - trigger(when, window) { + trigger(window) { let state = this.getWindowState(window); if (state == "document_start") { diff --git a/toolkit/components/extensions/test/mochitest/file_with_about_blank.html b/toolkit/components/extensions/test/mochitest/file_with_about_blank.html new file mode 100644 index 000000000000..af51c2e52a11 --- /dev/null +++ b/toolkit/components/extensions/test/mochitest/file_with_about_blank.html @@ -0,0 +1,10 @@ + + + + + + + + + + diff --git a/toolkit/components/extensions/test/mochitest/mochitest.ini b/toolkit/components/extensions/test/mochitest/mochitest.ini index c8e7eb7a6184..338661545e7b 100644 --- a/toolkit/components/extensions/test/mochitest/mochitest.ini +++ b/toolkit/components/extensions/test/mochitest/mochitest.ini @@ -18,6 +18,7 @@ support-files = file_WebNavigation_page1.html file_WebNavigation_page2.html file_WebNavigation_page3.html + file_with_about_blank.html file_image_good.png file_image_bad.png file_image_redirect.png @@ -50,6 +51,8 @@ skip-if = os == 'android' # Android does not currently support windows. [test_ext_contentscript_devtools_metadata.html] [test_ext_contentscript_exporthelpers.html] [test_ext_contentscript_css.html] +[test_ext_contentscript_about_blank.html] +skip-if = (os == 'android') # bug 1312357 [test_ext_contentscript_teardown.html] skip-if = (os == 'android') # Android does not support tabs API. Bug 1260250 [test_ext_exclude_include_globs.html] diff --git a/toolkit/components/extensions/test/mochitest/test_ext_contentscript_about_blank.html b/toolkit/components/extensions/test/mochitest/test_ext_contentscript_about_blank.html new file mode 100644 index 000000000000..3766678e718d --- /dev/null +++ b/toolkit/components/extensions/test/mochitest/test_ext_contentscript_about_blank.html @@ -0,0 +1,117 @@ + + + + Test content script match_about_blank option + + + + + + + + + + + From 489763535cd2ec855aa4f0b734c0a1658e43d16e Mon Sep 17 00:00:00 2001 From: Chia-hung Tai Date: Wed, 19 Oct 2016 17:55:18 +0800 Subject: [PATCH 22/60] Bug 1311231 - Fix test_mixed_principals.html in XP. r=jwwang Can not play mp4 on XP. So add the canPlayType checking for the test failure. MozReview-Commit-ID: KH70XsQkYYF --HG-- extra : rebase_source : fc08ea1aad6094757dcc7f72662d0d214b4bdeb7 --- dom/media/test/mochitest.ini | 1 - dom/media/test/test_mixed_principals.html | 8 ++++---- 2 files changed, 4 insertions(+), 5 deletions(-) diff --git a/dom/media/test/mochitest.ini b/dom/media/test/mochitest.ini index 621b7068f868..f6eef504adb3 100644 --- a/dom/media/test/mochitest.ini +++ b/dom/media/test/mochitest.ini @@ -797,7 +797,6 @@ skip-if = toolkit == 'gonk' && debug # bug 1065924 [test_mediatrack_replay_from_end.html] [test_metadata.html] [test_mixed_principals.html] -skip-if = os == 'win' && os_version == '5.1' # Skip XP. See bug Bug 1311231 [test_mozHasAudio.html] [test_multiple_mediastreamtracks.html] [test_networkState.html] diff --git a/dom/media/test/test_mixed_principals.html b/dom/media/test/test_mixed_principals.html index ec7244b74c35..d3f7ec257b6e 100644 --- a/dom/media/test/test_mixed_principals.html +++ b/dom/media/test/test_mixed_principals.html @@ -22,7 +22,6 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=489415 SimpleTest.waitForExplicitFinish(); var pushPrefs = (...p) => new Promise(r => SpecialPowers.pushPrefEnv({set: p}, r)); -var throwOutside = e => setTimeout(() => { throw e; }); var v1 = document.getElementById("v1"); var v2 = document.getElementById("v2"); @@ -45,8 +44,10 @@ function onendedcb(id) { } function testMixedPrincipals(resource) { - if (!resource) { + // In some OS(XP) can not play mp4. Add this checking for the test failure. + if (!resource || !v1.canPlayType(resource.type)) { todo(false, "No types supported"); + SimpleTest.finish(); return; } // Make sure the media cache size(50MB) is large enough that the data could @@ -84,8 +85,7 @@ function testMixedPrincipals(resource) { }); } -testMixedPrincipals({ name:"pixel_aspect_ratio.mp4", type:"video/mp4", duration:28}) -.catch(e => throwOutside(e)); +testMixedPrincipals({ name:"pixel_aspect_ratio.mp4", type:"video/mp4", duration:28}); From d9621bf2ed47af1681e76006bdf8c044b82f0369 Mon Sep 17 00:00:00 2001 From: Fred Lin Date: Mon, 24 Oct 2016 13:55:05 +0800 Subject: [PATCH 23/60] Bug 1311591 - Implement clear button for Net Panel Toolbar;r=jsnajdr MozReview-Commit-ID: LI2ObmV5BV3 --HG-- extra : rebase_source : a6d73690208531fb61c5c86d47867d4ade700e06 --- devtools/client/netmonitor/netmonitor.xul | 5 ++--- .../client/netmonitor/requests-menu-view.js | 5 ----- devtools/client/netmonitor/toolbar-view.js | 19 ++++++++++++++++++- devtools/client/themes/netmonitor.css | 4 ++++ 4 files changed, 24 insertions(+), 9 deletions(-) diff --git a/devtools/client/netmonitor/netmonitor.xul b/devtools/client/netmonitor/netmonitor.xul index 0aa9d51cf38b..9421cbba67f7 100644 --- a/devtools/client/netmonitor/netmonitor.xul +++ b/devtools/client/netmonitor/netmonitor.xul @@ -22,9 +22,8 @@ - + { + NetMonitorView.RequestsMenu.clear(); + } + }), this._clearContainerNode); + + // filter button ReactDOM.render(Provider( { store }, FilterButtons() @@ -40,6 +56,7 @@ ToolbarView.prototype = { destroy: function () { dumpn("Destroying the ToolbarView"); + ReactDOM.unmountComponentAtNode(this._clearContainerNode); ReactDOM.unmountComponentAtNode(this._filterContainerNode); this._detailsPaneToggleButton.removeEventListener("mousedown", diff --git a/devtools/client/themes/netmonitor.css b/devtools/client/themes/netmonitor.css index 4b2ca670761a..b053ffa6dc4a 100644 --- a/devtools/client/themes/netmonitor.css +++ b/devtools/client/themes/netmonitor.css @@ -7,6 +7,10 @@ overflow: hidden; } +#react-clear-button-hook { + display: flex; +} + /** * Collapsed details pane needs to be truly hidden to prevent both accessibility * tools and keyboard from accessing its contents. From 8e3719b7e2c87758a06c6f254d491b4785e248a5 Mon Sep 17 00:00:00 2001 From: Sergei Chernov Date: Wed, 28 Sep 2016 20:19:56 +0300 Subject: [PATCH 24/60] Bug 1305289 - Certificate Transparency - basic UI indicator; r=Dolske,keeler MozReview-Commit-ID: b0SUW2WNJT --HG-- extra : rebase_source : 2bfa8895246f862f3e49c0c9674a8e862137f8a6 --- browser/base/content/pageinfo/pageInfo.xul | 1 + browser/base/content/pageinfo/security.js | 37 ++++++- .../en-US/chrome/pippki/pippki.properties | 4 + .../manager/ssl/SSLServerCertVerification.cpp | 2 + security/manager/ssl/nsISSLStatus.idl | 7 ++ security/manager/ssl/nsSSLStatus.cpp | 98 ++++++++++++++++++- security/manager/ssl/nsSSLStatus.h | 5 + 7 files changed, 150 insertions(+), 4 deletions(-) diff --git a/browser/base/content/pageinfo/pageInfo.xul b/browser/base/content/pageinfo/pageInfo.xul index 318805ef2c23..12d4f526f341 100644 --- a/browser/base/content/pageinfo/pageInfo.xul +++ b/browser/base/content/pageinfo/pageInfo.xul @@ -417,6 +417,7 @@ diff --git a/browser/base/content/pageinfo/security.js b/browser/base/content/pageinfo/security.js index 70a876ddbe0e..42e3f7127f0e 100644 --- a/browser/base/content/pageinfo/security.js +++ b/browser/base/content/pageinfo/security.js @@ -65,7 +65,8 @@ var security = { isBroken : isBroken, isMixed : isMixed, isEV : isEV, - cert : cert + cert : cert, + certificateTransparency : undefined }; var version; @@ -95,6 +96,27 @@ var security = { break; } + // Select status text to display for Certificate Transparency. + switch (status.certificateTransparencyStatus) { + case nsISSLStatus.CERTIFICATE_TRANSPARENCY_NOT_APPLICABLE: + // CT compliance checks were not performed, + // do not display any status text. + retval.certificateTransparency = null; + break; + case nsISSLStatus.CERTIFICATE_TRANSPARENCY_NONE: + retval.certificateTransparency = "None"; + break; + case nsISSLStatus.CERTIFICATE_TRANSPARENCY_OK: + retval.certificateTransparency = "OK"; + break; + case nsISSLStatus.CERTIFICATE_TRANSPARENCY_UNKNOWN_LOG: + retval.certificateTransparency = "UnknownLog"; + break; + case nsISSLStatus.CERTIFICATE_TRANSPARENCY_INVALID: + retval.certificateTransparency = "Invalid"; + break; + } + return retval; } return { @@ -106,7 +128,8 @@ var security = { isBroken : isBroken, isMixed : isMixed, isEV : isEV, - cert : null + cert : null, + certificateTransparency : null }; }, @@ -283,6 +306,16 @@ function securityOnLoad(uri, windowInfo) { setText("security-technical-shortform", hdr); setText("security-technical-longform1", msg1); setText("security-technical-longform2", msg2); + + const ctStatus = + document.getElementById("security-technical-certificate-transparency"); + if (info.certificateTransparency) { + ctStatus.hidden = false; + ctStatus.value = pkiBundle.getString( + "pageInfo_CertificateTransparency_" + info.certificateTransparency); + } else { + ctStatus.hidden = true; + } } function setText(id, value) diff --git a/security/manager/locales/en-US/chrome/pippki/pippki.properties b/security/manager/locales/en-US/chrome/pippki/pippki.properties index 056f609af1fd..f841d0798f86 100644 --- a/security/manager/locales/en-US/chrome/pippki/pippki.properties +++ b/security/manager/locales/en-US/chrome/pippki/pippki.properties @@ -109,6 +109,10 @@ pageInfo_Privacy_Encrypted2=Encryption makes it difficult for unauthorized peopl pageInfo_MixedContent=Connection Partially Encrypted pageInfo_MixedContent2=Parts of the page you are viewing were not encrypted before being transmitted over the Internet. pageInfo_WeakCipher=Your connection to this website uses weak encryption and is not private. Other people can view your information or modify the website’s behavior. +pageInfo_CertificateTransparency_None=This website does not supply Certificate Transparency audit records. +pageInfo_CertificateTransparency_OK=This website supplies publicly auditable Certificate Transparency records. +pageInfo_CertificateTransparency_UnknownLog=This website claims to have Certificate Transparency audit records, but the records were issued by an unknown party and cannot be verified. +pageInfo_CertificateTransparency_Invalid=This website supplies Certificate Transparency audit records, but the records failed verification. # Cert Viewer # LOCALIZATION NOTE(certViewerTitle): Title used for the Certificate Viewer. diff --git a/security/manager/ssl/SSLServerCertVerification.cpp b/security/manager/ssl/SSLServerCertVerification.cpp index 33ce23df77b0..d89f8117122b 100644 --- a/security/manager/ssl/SSLServerCertVerification.cpp +++ b/security/manager/ssl/SSLServerCertVerification.cpp @@ -1417,6 +1417,8 @@ AuthCertificate(CertVerifier& certVerifier, MOZ_LOG(gPIPNSSLog, LogLevel::Debug, ("AuthCertificate setting NEW cert %p\n", nsc.get())); } + + status->SetCertificateTransparencyInfo(certificateTransparencyInfo); } if (rv != Success) { diff --git a/security/manager/ssl/nsISSLStatus.idl b/security/manager/ssl/nsISSLStatus.idl index da1fbcfac1f0..f5c56a8cf8d5 100644 --- a/security/manager/ssl/nsISSLStatus.idl +++ b/security/manager/ssl/nsISSLStatus.idl @@ -23,6 +23,13 @@ interface nsISSLStatus : nsISupports { const short TLS_VERSION_1_3 = 4; readonly attribute unsigned short protocolVersion; + const short CERTIFICATE_TRANSPARENCY_NOT_APPLICABLE = 0; + const short CERTIFICATE_TRANSPARENCY_NONE = 1; + const short CERTIFICATE_TRANSPARENCY_OK = 2; + const short CERTIFICATE_TRANSPARENCY_UNKNOWN_LOG = 3; + const short CERTIFICATE_TRANSPARENCY_INVALID = 4; + readonly attribute unsigned short certificateTransparencyStatus; + readonly attribute boolean isDomainMismatch; readonly attribute boolean isNotValidAtThisTime; diff --git a/security/manager/ssl/nsSSLStatus.cpp b/security/manager/ssl/nsSSLStatus.cpp index 084697cfe63e..69391159024b 100644 --- a/security/manager/ssl/nsSSLStatus.cpp +++ b/security/manager/ssl/nsSSLStatus.cpp @@ -4,11 +4,13 @@ * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ +#include "mozilla/Casting.h" #include "nsSSLStatus.h" #include "plstr.h" #include "nsIClassInfoImpl.h" #include "nsIObjectOutputStream.h" #include "nsIObjectInputStream.h" +#include "SignedCertificateTimestamp.h" #include "ssl.h" NS_IMETHODIMP @@ -86,6 +88,16 @@ nsSSLStatus::GetProtocolVersion(uint16_t* aProtocolVersion) return NS_OK; } +NS_IMETHODIMP +nsSSLStatus::GetCertificateTransparencyStatus( + uint16_t* aCertificateTransparencyStatus) +{ + NS_ENSURE_ARG_POINTER(aCertificateTransparencyStatus); + + *aCertificateTransparencyStatus = mCertificateTransparencyStatus; + return NS_OK; +} + NS_IMETHODIMP nsSSLStatus::GetIsDomainMismatch(bool* aIsDomainMismatch) { @@ -146,8 +158,19 @@ nsSSLStatus::Read(nsIObjectInputStream* aStream) rv = aStream->Read16(&mCipherSuite); NS_ENSURE_SUCCESS(rv, rv); - rv = aStream->Read16(&mProtocolVersion); + + // The code below is a workaround to allow serializing new fields + // while preserving binary compatibility with older streams. For more details + // on the binary compatibility requirement, refer to bug 1248628. + // Here, we take advantage of the fact that mProtocolVersion was originally + // stored as a 16 bits integer, but the highest 8 bits were never used. + // These bits are now used for stream versioning. + uint16_t protocolVersionAndStreamFormatVersion; + rv = aStream->Read16(&protocolVersionAndStreamFormatVersion); NS_ENSURE_SUCCESS(rv, rv); + mProtocolVersion = protocolVersionAndStreamFormatVersion & 0xFF; + const uint8_t streamFormatVersion = + (protocolVersionAndStreamFormatVersion >> 8) & 0xFF; rv = aStream->ReadBoolean(&mIsDomainMismatch); NS_ENSURE_SUCCESS(rv, rv); @@ -165,12 +188,21 @@ nsSSLStatus::Read(nsIObjectInputStream* aStream) rv = aStream->ReadBoolean(&mHaveCertErrorBits); NS_ENSURE_SUCCESS(rv, rv); + // Added in version 1 (see bug 1305289). + if (streamFormatVersion >= 1) { + rv = aStream->Read16(&mCertificateTransparencyStatus); + NS_ENSURE_SUCCESS(rv, rv); + } + return NS_OK; } NS_IMETHODIMP nsSSLStatus::Write(nsIObjectOutputStream* aStream) { + // The current version of the binary stream format. + const uint8_t STREAM_FORMAT_VERSION = 1; + nsresult rv = aStream->WriteCompoundObject(mServerCert, NS_GET_IID(nsIX509Cert), true); @@ -178,7 +210,11 @@ nsSSLStatus::Write(nsIObjectOutputStream* aStream) rv = aStream->Write16(mCipherSuite); NS_ENSURE_SUCCESS(rv, rv); - rv = aStream->Write16(mProtocolVersion); + + uint16_t protocolVersionAndStreamFormatVersion = + mozilla::AssertedCast(mProtocolVersion) | + (STREAM_FORMAT_VERSION << 8); + rv = aStream->Write16(protocolVersionAndStreamFormatVersion); NS_ENSURE_SUCCESS(rv, rv); rv = aStream->WriteBoolean(mIsDomainMismatch); @@ -197,6 +233,10 @@ nsSSLStatus::Write(nsIObjectOutputStream* aStream) rv = aStream->WriteBoolean(mHaveCertErrorBits); NS_ENSURE_SUCCESS(rv, rv); + // Added in version 1. + rv = aStream->Write16(mCertificateTransparencyStatus); + NS_ENSURE_SUCCESS(rv, rv); + return NS_OK; } @@ -258,6 +298,8 @@ nsSSLStatus::GetClassIDNoAlloc(nsCID* aClassIDNoAlloc) nsSSLStatus::nsSSLStatus() : mCipherSuite(0) , mProtocolVersion(0) +, mCertificateTransparencyStatus(nsISSLStatus:: + CERTIFICATE_TRANSPARENCY_NOT_APPLICABLE) , mIsDomainMismatch(false) , mIsNotValidAtThisTime(false) , mIsUntrusted(false) @@ -294,3 +336,55 @@ nsSSLStatus::SetServerCert(nsNSSCertificate* aServerCert, mHasIsEVStatus = true; } } + +void +nsSSLStatus::SetCertificateTransparencyInfo( + const mozilla::psm::CertificateTransparencyInfo& info) +{ + using mozilla::ct::SignedCertificateTimestamp; + + if (!info.enabled) { + // CT disabled. + mCertificateTransparencyStatus = + nsISSLStatus::CERTIFICATE_TRANSPARENCY_NOT_APPLICABLE; + return; + } + + if (!info.processedSCTs) { + // No SCTs processed on the connection. + mCertificateTransparencyStatus = + nsISSLStatus::CERTIFICATE_TRANSPARENCY_NONE; + return; + } + + bool hasOKSCTs = false; + bool hasUnknownLogSCTs = false; + bool hasInvalidSCTs = false; + for (const SignedCertificateTimestamp& sct : info.verifyResult.scts) { + switch (sct.verificationStatus) { + case SignedCertificateTimestamp::VerificationStatus::OK: + hasOKSCTs = true; + break; + case SignedCertificateTimestamp::VerificationStatus::UnknownLog: + hasUnknownLogSCTs = true; + break; + case SignedCertificateTimestamp::VerificationStatus::InvalidSignature: + case SignedCertificateTimestamp::VerificationStatus::InvalidTimestamp: + hasInvalidSCTs = true; + break; + default: + MOZ_ASSERT_UNREACHABLE("Unexpected SCT::VerificationStatus type"); + } + } + + if (hasOKSCTs) { + mCertificateTransparencyStatus = + nsISSLStatus::CERTIFICATE_TRANSPARENCY_OK; + } else if (hasUnknownLogSCTs) { + mCertificateTransparencyStatus = + nsISSLStatus::CERTIFICATE_TRANSPARENCY_UNKNOWN_LOG; + } else if (hasInvalidSCTs) { + mCertificateTransparencyStatus = + nsISSLStatus::CERTIFICATE_TRANSPARENCY_INVALID; + } +} diff --git a/security/manager/ssl/nsSSLStatus.h b/security/manager/ssl/nsSSLStatus.h index c79019c63f48..0984f7f9f5d0 100644 --- a/security/manager/ssl/nsSSLStatus.h +++ b/security/manager/ssl/nsSSLStatus.h @@ -7,6 +7,7 @@ #ifndef _NSSSLSTATUS_H #define _NSSSLSTATUS_H +#include "CertVerifier.h" // For CertificateTransparencyInfo #include "nsISSLStatus.h" #include "nsCOMPtr.h" #include "nsXPIDLString.h" @@ -37,9 +38,13 @@ public: return mServerCert != nullptr; } + void SetCertificateTransparencyInfo( + const mozilla::psm::CertificateTransparencyInfo& info); + /* public for initilization in this file */ uint16_t mCipherSuite; uint16_t mProtocolVersion; + uint16_t mCertificateTransparencyStatus; bool mIsDomainMismatch; bool mIsNotValidAtThisTime; From 3b68400cf38ec3886f3c2440cc3c3b8b66022159 Mon Sep 17 00:00:00 2001 From: Henrik Skupin Date: Wed, 26 Oct 2016 13:30:20 +0200 Subject: [PATCH 25/60] Bug 1280878 - Update safebrowing_notification test for changed Google URL. r=francois MozReview-Commit-ID: 7jkbKM9FLXg --HG-- extra : rebase_source : 4243b2dfedce63a26fa51e129cbb5e2c21499354 --- .../test_safe_browsing_notification.py | 21 +++++++++++++------ 1 file changed, 15 insertions(+), 6 deletions(-) diff --git a/testing/firefox-ui/tests/functional/security/test_safe_browsing_notification.py b/testing/firefox-ui/tests/functional/security/test_safe_browsing_notification.py index 3465ede78222..7b06a7b10c5f 100644 --- a/testing/firefox-ui/tests/functional/security/test_safe_browsing_notification.py +++ b/testing/firefox-ui/tests/functional/security/test_safe_browsing_notification.py @@ -26,13 +26,13 @@ class TestSafeBrowsingNotificationBar(FirefoxTestCase): # Phishing URL info { 'button_property': 'safebrowsing.notADeceptiveSiteButton.label', - 'report_page': 'www.google.com/safebrowsing/report_error', + 'report_page': 'google.com/safebrowsing/report_error', 'unsafe_page': 'https://www.itisatrap.org/firefox/its-a-trap.html' }, # Malware URL object { 'button_property': 'safebrowsing.notAnAttackButton.label', - 'report_page': 'www.stopbadware.org', + 'report_page': 'stopbadware.org', 'unsafe_page': 'https://www.itisatrap.org/firefox/its-an-attack.html' } ] @@ -93,7 +93,9 @@ class TestSafeBrowsingNotificationBar(FirefoxTestCase): button.click() Wait(self.marionette, timeout=self.browser.timeout_page_load).until( - expected.element_present(By.ID, 'main-feature')) + expected.element_present(By.ID, 'main-feature'), + message='Expected target element "#main-feature" has not been found', + ) self.assertEquals(self.marionette.get_url(), self.browser.get_final_url(unsafe_page)) # Clean up here since the permission gets set in this function @@ -110,7 +112,10 @@ class TestSafeBrowsingNotificationBar(FirefoxTestCase): self.browser.tabbar.open_tab(lambda _: button.click()) Wait(self.marionette, timeout=self.browser.timeout_page_load).until( - lambda mn: report_page in mn.get_url()) + lambda mn: report_page in mn.get_url(), + message='The expected safe-browsing report page has not been opened', + ) + with self.marionette.using_context('chrome'): self.browser.tabbar.close_tab() @@ -123,7 +128,9 @@ class TestSafeBrowsingNotificationBar(FirefoxTestCase): button.click() Wait(self.marionette, timeout=self.browser.timeout_page_load).until( - lambda mn: self.browser.default_homepage in mn.get_url()) + lambda mn: self.browser.default_homepage in mn.get_url(), + message='The default home page has not been loaded', + ) def check_x_button(self): with self.marionette.using_context('chrome'): @@ -135,4 +142,6 @@ class TestSafeBrowsingNotificationBar(FirefoxTestCase): button.click() Wait(self.marionette, timeout=self.browser.timeout_page_load).until( - expected.element_stale(button)) + expected.element_stale(button), + message='The notification bar has not been closed', + ) From 204e68059640cf4c0dd2813185888ae60bdab700 Mon Sep 17 00:00:00 2001 From: Tomislav Jovanovic Date: Sat, 22 Oct 2016 12:06:22 +0200 Subject: [PATCH 26/60] bug 1247793 - Implement download() options: method, headers and body, r=aswan MozReview-Commit-ID: 2muhcweY8Fo --HG-- extra : rebase_source : 30f0aabce48717caa963610c2fcf831a0b890702 --- .../components/extensions/ext-downloads.js | 64 ++++++++++-- .../extensions/schemas/downloads.json | 3 - .../xpcshell/test_ext_downloads_download.js | 98 +++++++++++++++++++ 3 files changed, 155 insertions(+), 10 deletions(-) diff --git a/toolkit/components/extensions/ext-downloads.js b/toolkit/components/extensions/ext-downloads.js index 60e01f54f449..132814ae4b23 100644 --- a/toolkit/components/extensions/ext-downloads.js +++ b/toolkit/components/extensions/ext-downloads.js @@ -38,6 +38,14 @@ const DOWNLOAD_ITEM_FIELDS = ["id", "url", "referrer", "filename", "incognito", const DOWNLOAD_ITEM_CHANGE_FIELDS = ["endTime", "state", "paused", "canResume", "error", "exists"]; +// From https://fetch.spec.whatwg.org/#forbidden-header-name +const FORBIDDEN_HEADERS = ["ACCEPT-CHARSET", "ACCEPT-ENCODING", + "ACCESS-CONTROL-REQUEST-HEADERS", "ACCESS-CONTROL-REQUEST-METHOD", + "CONNECTION", "CONTENT-LENGTH", "COOKIE", "COOKIE2", "DATE", "DNT", + "EXPECT", "HOST", "KEEP-ALIVE", "ORIGIN", "REFERER", "TE", "TRAILER", + "TRANSFER-ENCODING", "UPGRADE", "VIA"]; + +const FORBIDDEN_PREFIXES = /^PROXY-|^SEC-/i; class DownloadItem { constructor(id, download, extension) { @@ -418,6 +426,38 @@ extensions.registerSchemaAPI("downloads", "addon_parent", context => { return Promise.reject({message: "conflictAction prompt not yet implemented"}); } + if (options.headers) { + for (let {name} of options.headers) { + if (FORBIDDEN_HEADERS.includes(name.toUpperCase()) || name.match(FORBIDDEN_PREFIXES)) { + return Promise.reject({message: "Forbidden request header name"}); + } + } + } + + // Handle method, headers and body options. + function adjustChannel(channel) { + if (channel instanceof Ci.nsIHttpChannel) { + const method = options.method || "GET"; + channel.requestMethod = method; + + if (options.headers) { + for (let {name, value} of options.headers) { + channel.setRequestHeader(name, value, false); + } + } + + if (options.body != null) { + const stream = Cc["@mozilla.org/io/string-input-stream;1"] + .createInstance(Ci.nsIStringInputStream); + stream.setData(options.body, options.body.length); + + channel.QueryInterface(Ci.nsIUploadChannel2); + channel.explicitSetUploadStream(stream, null, -1, method, false); + } + } + return Promise.resolve(); + } + function createTarget(downloadsDir) { let target; if (filename) { @@ -481,13 +521,23 @@ extensions.registerSchemaAPI("downloads", "addon_parent", context => { let download; return Downloads.getPreferredDownloadsDirectory() .then(downloadsDir => createTarget(downloadsDir)) - .then(target => Downloads.createDownload({ - source: options.url, - target: { - path: target, - partFilePath: target + ".part", - }, - })).then(dl => { + .then(target => { + const source = { + url: options.url, + }; + + if (options.method || options.headers || options.body) { + source.adjustChannel = adjustChannel; + } + + return Downloads.createDownload({ + source, + target: { + path: target, + partFilePath: target + ".part", + }, + }); + }).then(dl => { download = dl; return DownloadMap.getDownloadList(); }).then(list => { diff --git a/toolkit/components/extensions/schemas/downloads.json b/toolkit/components/extensions/schemas/downloads.json index 81c6452540ad..dcd43e4e153d 100644 --- a/toolkit/components/extensions/schemas/downloads.json +++ b/toolkit/components/extensions/schemas/downloads.json @@ -386,7 +386,6 @@ "type": "boolean" }, "method": { - "unsupported": true, "description": "The HTTP method to use if the URL uses the HTTP[S] protocol.", "enum": [ "GET", @@ -396,7 +395,6 @@ "type": "string" }, "headers": { - "unsupported": true, "optional": true, "type": "array", "description": "Extra HTTP headers to send with the request if the URL uses the HTTP[s] protocol. Each header is represented as a dictionary containing the keys name and either value or binaryValue, restricted to those allowed by XMLHttpRequest.", @@ -415,7 +413,6 @@ } }, "body": { - "unsupported": true, "description": "Post body.", "optional": true, "type": "string" diff --git a/toolkit/components/extensions/test/xpcshell/test_ext_downloads_download.js b/toolkit/components/extensions/test/xpcshell/test_ext_downloads_download.js index 8654c9a92df7..33fb3909c8d2 100644 --- a/toolkit/components/extensions/test/xpcshell/test_ext_downloads_download.js +++ b/toolkit/components/extensions/test/xpcshell/test_ext_downloads_download.js @@ -255,3 +255,101 @@ add_task(function* test_downloads() { yield extension.unload(); }); + +add_task(function* test_download_post() { + const server = createHttpServer(); + const url = `http://localhost:${server.identity.primaryPort}/post-log`; + + let received; + server.registerPathHandler("/post-log", request => { + received = request; + }); + + // Confirm received vs. expected values. + function confirm(method, headers = {}, body) { + equal(received.method, method, "method is correct"); + + for (let name in headers) { + ok(received.hasHeader(name), `header ${name} received`); + equal(received.getHeader(name), headers[name], `header ${name} is correct`); + } + + if (body) { + const str = NetUtil.readInputStreamToString(received.bodyInputStream, + received.bodyInputStream.available()); + equal(str, body, "body is correct"); + } + } + + function background() { + browser.test.onMessage.addListener(options => { + Promise.resolve() + .then(() => browser.downloads.download(options)) + .catch(err => browser.test.sendMessage("done", {err: err.message})); + }); + browser.downloads.onChanged.addListener(({state}) => { + if (state && state.current === "complete") { + browser.test.sendMessage("done", {ok: true}); + } + }); + } + + const manifest = {permissions: ["downloads"]}; + const extension = ExtensionTestUtils.loadExtension({background, manifest}); + yield extension.startup(); + + function download(options) { + options.url = url; + options.conflictAction = "overwrite"; + + extension.sendMessage(options); + return extension.awaitMessage("done"); + } + + // Test method option. + let result = yield download({}); + ok(result.ok, "download works without the method option, defaults to GET"); + confirm("GET"); + + result = yield download({method: "PUT"}); + ok(!result.ok, "download rejected with PUT method"); + ok(/method: Invalid enumeration/.test(result.err), "descriptive error message"); + + result = yield download({method: "POST"}); + ok(result.ok, "download works with POST method"); + confirm("POST"); + + // Test body option values. + result = yield download({body: []}); + ok(!result.ok, "download rejected because of non-string body"); + ok(/body: Expected string/.test(result.err), "descriptive error message"); + + result = yield download({method: "POST", body: "of work"}); + ok(result.ok, "download works with POST method and body"); + confirm("POST", {"Content-Length": 7}, "of work"); + + // Test custom headers. + result = yield download({headers: [{name: "X-Custom"}]}); + ok(!result.ok, "download rejected because of missing header value"); + ok(/"value" is required/.test(result.err), "descriptive error message"); + + result = yield download({headers: [{name: "X-Custom", value: "13"}]}); + ok(result.ok, "download works with a custom header"); + confirm("GET", {"X-Custom": "13"}); + + // Test forbidden headers. + result = yield download({headers: [{name: "DNT", value: "1"}]}); + ok(!result.ok, "download rejected because of forbidden header name DNT"); + ok(/Forbidden request header/.test(result.err), "descriptive error message"); + + result = yield download({headers: [{name: "Proxy-Connection", value: "keep"}]}); + ok(!result.ok, "download rejected because of forbidden header name prefix Proxy-"); + ok(/Forbidden request header/.test(result.err), "descriptive error message"); + + result = yield download({headers: [{name: "Sec-ret", value: "13"}]}); + ok(!result.ok, "download rejected because of forbidden header name prefix Sec-"); + ok(/Forbidden request header/.test(result.err), "descriptive error message"); + + remove("post-log"); + yield extension.unload(); +}); From c0890a4a2c93202828a7c733d4243915f20a9a4c Mon Sep 17 00:00:00 2001 From: Ralph Giles Date: Tue, 25 Oct 2016 19:25:18 -0700 Subject: [PATCH 27/60] Bug 1303888 - Update rust mp4parse. r=kinetik Update to the latest upstream master, including skipping padding at the end of some boxes, esds parsing and flac support. MozReview-Commit-ID: GdHEQIrtyLB --HG-- extra : rebase_source : 97e1d09725d813e0f2b31bed6ce80e16b0701fbe --- .../libstagefright/binding/include/mp4parse.h | 2 + .../binding/mp4parse/Cargo.toml | 2 +- .../binding/mp4parse/src/boxes.rs | 3 + .../binding/mp4parse/src/lib.rs | 346 +++++++++++++++--- .../binding/mp4parse/src/tests.rs | 205 ++++++++++- .../binding/mp4parse/tests/public.rs | 12 +- .../binding/mp4parse_capi/build.rs | 1 + .../binding/mp4parse_capi/src/lib.rs | 49 ++- 8 files changed, 561 insertions(+), 59 deletions(-) diff --git a/media/libstagefright/binding/include/mp4parse.h b/media/libstagefright/binding/include/mp4parse.h index 802e904499a7..6650661cb13c 100644 --- a/media/libstagefright/binding/include/mp4parse.h +++ b/media/libstagefright/binding/include/mp4parse.h @@ -33,9 +33,11 @@ typedef enum mp4parse_track_type { typedef enum mp4parse_codec { MP4PARSE_CODEC_UNKNOWN, MP4PARSE_CODEC_AAC, + MP4PARSE_CODEC_FLAC, MP4PARSE_CODEC_OPUS, MP4PARSE_CODEC_AVC, MP4PARSE_CODEC_VP9, + MP4PARSE_CODEC_MP3, } mp4parse_codec; typedef struct mp4parse_track_info { diff --git a/media/libstagefright/binding/mp4parse/Cargo.toml b/media/libstagefright/binding/mp4parse/Cargo.toml index 1e9ed2fbd012..0c3c5f019272 100644 --- a/media/libstagefright/binding/mp4parse/Cargo.toml +++ b/media/libstagefright/binding/mp4parse/Cargo.toml @@ -18,7 +18,7 @@ exclude = [ ] [dependencies] -byteorder = { version = "0.5.0" } +byteorder = "0.5.0" [dev-dependencies] test-assembler = "0.1.2" diff --git a/media/libstagefright/binding/mp4parse/src/boxes.rs b/media/libstagefright/binding/mp4parse/src/boxes.rs index 25eef40c008b..689439ade2be 100644 --- a/media/libstagefright/binding/mp4parse/src/boxes.rs +++ b/media/libstagefright/binding/mp4parse/src/boxes.rs @@ -50,10 +50,13 @@ box_database!( VP8SampleEntry 0x76703038, // "vp08" VP9SampleEntry 0x76703039, // "vp09" VPCodecConfigurationBox 0x76706343, // "vpcC" + FLACSampleEntry 0x664c6143, // "fLaC" + FLACSpecificBox 0x64664c61, // "dfLa" OpusSampleEntry 0x4f707573, // "Opus" OpusSpecificBox 0x644f7073, // "dOps" ProtectedVisualSampleEntry 0x656e6376, // "encv" - Need to check official name in spec. ProtectedAudioSampleEntry 0x656e6361, // "enca" - Need to check official name in spec. MovieExtendsBox 0x6d766578, // "mvex" MovieExtendsHeaderBox 0x6d656864, // "mehd" + QTWaveAtom 0x77617665, // "wave" - quicktime atom ); diff --git a/media/libstagefright/binding/mp4parse/src/lib.rs b/media/libstagefright/binding/mp4parse/src/lib.rs index 9e78d9520b12..cae9f545228e 100644 --- a/media/libstagefright/binding/mp4parse/src/lib.rs +++ b/media/libstagefright/binding/mp4parse/src/lib.rs @@ -11,6 +11,7 @@ extern crate afl; extern crate byteorder; use byteorder::ReadBytesExt; use std::io::{Read, Take}; +use std::io::Cursor; use std::cmp; mod boxes; @@ -203,10 +204,19 @@ pub enum SampleEntry { Unknown, } +#[allow(non_camel_case_types)] +#[derive(Debug, Clone)] +pub struct ES_Descriptor { + pub audio_codec: CodecType, + pub audio_sample_rate: Option, + pub codec_specific_config: Vec, +} + #[allow(non_camel_case_types)] #[derive(Debug, Clone)] pub enum AudioCodecSpecific { - ES_Descriptor(Vec), + ES_Descriptor(ES_Descriptor), + FLACSpecificBox(FLACSpecificBox), OpusSpecificBox(OpusSpecificBox), } @@ -246,6 +256,19 @@ pub struct VPxConfigBox { pub codec_init: Vec, // Empty for vp8/vp9. } +#[derive(Debug, Clone)] +pub struct FLACMetadataBlock { + pub block_type: u8, + pub data: Vec, +} + +/// Represet a FLACSpecificBox 'dfLa' +#[derive(Debug, Clone)] +pub struct FLACSpecificBox { + version: u8, + pub blocks: Vec, +} + #[derive(Debug, Clone)] struct ChannelMappingTable { stream_count: u8, @@ -285,7 +308,7 @@ impl MediaContext { } } -#[derive(Debug)] +#[derive(Debug, PartialEq)] pub enum TrackType { Audio, Video, @@ -296,10 +319,12 @@ impl Default for TrackType { fn default() -> Self { TrackType::Unknown } } -#[derive(Debug)] +#[derive(Debug, Clone, Copy, PartialEq)] pub enum CodecType { Unknown, + MP3, AAC, + FLAC, Opus, H264, VP9, @@ -469,6 +494,17 @@ fn skip_box_content(src: &mut BMFFBox) -> Result<()> { skip(src, to_skip) } +/// Skip over the remain data of a box. +fn skip_box_remain(src: &mut BMFFBox) -> Result<()> { + let remain = { + let header = src.get_header(); + let len = src.bytes_left(); + log!("remain {} (skipped) in {:?}", len, header); + len + }; + skip(src, remain) +} + macro_rules! check_parser_state { ( $src:expr ) => { if $src.limit() > 0 { @@ -921,6 +957,9 @@ fn read_stco(src: &mut BMFFBox) -> Result { offsets.push(try!(be_u32(src)) as u64); } + // Padding could be added in some contents. + try!(skip_box_remain(src)); + Ok(ChunkOffsetBox { offsets: offsets, }) @@ -935,6 +974,9 @@ fn read_co64(src: &mut BMFFBox) -> Result { offsets.push(try!(be_u64(src))); } + // Padding could be added in some contents. + try!(skip_box_remain(src)); + Ok(ChunkOffsetBox { offsets: offsets, }) @@ -949,6 +991,9 @@ fn read_stss(src: &mut BMFFBox) -> Result { samples.push(try!(be_u32(src))); } + // Padding could be added in some contents. + try!(skip_box_remain(src)); + Ok(SyncSampleBox { samples: samples, }) @@ -970,6 +1015,9 @@ fn read_stsc(src: &mut BMFFBox) -> Result { }); } + // Padding could be added in some contents. + try!(skip_box_remain(src)); + Ok(SampleToChunkBox { samples: samples, }) @@ -987,6 +1035,9 @@ fn read_stsz(src: &mut BMFFBox) -> Result { } } + // Padding could be added in some contents. + try!(skip_box_remain(src)); + Ok(SampleSizeBox { sample_size: sample_size, sample_sizes: sample_sizes, @@ -1007,6 +1058,9 @@ fn read_stts(src: &mut BMFFBox) -> Result { }); } + // Padding could be added in some contents. + try!(skip_box_remain(src)); + Ok(TimeToSampleBox { samples: samples, }) @@ -1046,11 +1100,177 @@ fn read_vpcc(src: &mut BMFFBox) -> Result { }) } +fn read_flac_metadata(src: &mut BMFFBox) -> Result { + let temp = try!(src.read_u8()); + let block_type = temp & 0x7f; + let length = try!(be_u24(src)); + if length as usize > src.bytes_left() { + return Err(Error::InvalidData( + "FLACMetadataBlock larger than parent box")); + } + let data = try!(read_buf(src, length as usize)); + Ok(FLACMetadataBlock { + block_type: block_type, + data: data, + }) +} + +fn read_esds(src: &mut BMFFBox) -> Result { + // Tags for elementary stream description + const ESDESCR_TAG: u8 = 0x03; + const DECODER_CONFIG_TAG: u8 = 0x04; + const DECODER_SPECIFIC_TAG: u8 = 0x05; + + let frequency_table = + vec![(0x1, 96000), (0x1, 88200), (0x2, 64000), (0x3, 48000), + (0x4, 44100), (0x5, 32000), (0x6, 24000), (0x7, 22050), + (0x8, 16000), (0x9, 12000), (0xa, 11025), (0xb, 8000), + (0xc, 7350)]; + + let (_, _) = try!(read_fullbox_extra(src)); + + let esds_size = src.head.size - src.head.offset - 4; + if esds_size > BUF_SIZE_LIMIT { + return Err(Error::InvalidData("esds box exceeds BUF_SIZE_LIMIT")); + } + let esds_array = try!(read_buf(src, esds_size as usize)); + + // Parsing DecoderConfig descriptor to get the object_profile_indicator + // for correct codec type and audio sample rate. + let (object_profile_indicator, sample_frequency) = { + let mut object_profile: u8 = 0; + let mut sample_frequency = None; + + // clone a esds cursor for parsing. + let esds = &mut Cursor::new(&esds_array); + let next_tag = try!(esds.read_u8()); + + if next_tag != ESDESCR_TAG { + return Err(Error::Unsupported("fail to parse ES descriptor")); + } + + let esds_extend = try!(esds.read_u8()); + // extension tag start from 0x80. + let esds_end = if esds_extend >= 0x80 { + // skip remaining extension. + try!(skip(esds, 2)); + esds.position() + try!(esds.read_u8()) as u64 + } else { + esds.position() + esds_extend as u64 + }; + try!(skip(esds, 2)); + + let esds_flags = try!(esds.read_u8()); + + // Stream dependency flag, first bit from left most. + if esds_flags & 0x80 > 0 { + // Skip uninteresting fields. + try!(skip(esds, 2)); + } + + // Url flag, second bit from left most. + if esds_flags & 0x40 > 0 { + // Skip uninteresting fields. + let skip_es_len: usize = try!(esds.read_u8()) as usize + 2; + try!(skip(esds, skip_es_len)); + } + + // find DecoderConfig descriptor (tag = DECODER_CONFIG_TAG) + if esds_end > esds.position() { + let next_tag = try!(esds.read_u8()); + if next_tag == DECODER_CONFIG_TAG { + let dcds_extend = try!(esds.read_u8()); + // extension tag start from 0x80. + if dcds_extend >= 0x80 { + // skip remains extension and length. + try!(skip(esds, 3)); + } + + object_profile = try!(esds.read_u8()); + + // Skip uninteresting fields. + try!(skip(esds, 12)); + } + } + + + // find DecoderSpecific descriptor (tag = DECODER_SPECIFIC_TAG) + if esds_end > esds.position() { + let next_tag = try!(esds.read_u8()); + if next_tag == DECODER_SPECIFIC_TAG { + let dsds_extend = try!(esds.read_u8()); + // extension tag start from 0x80. + if dsds_extend >= 0x80 { + // skip remains extension and length. + try!(skip(esds, 3)); + } + + let audio_specific_config = try!(be_u16(esds)); + + let sample_index = (audio_specific_config & 0x07FF) >> 7; + + sample_frequency = + frequency_table.iter().find(|item| item.0 == sample_index).map(|x| x.1); + } + } + + (object_profile, sample_frequency) + }; + + let codec = match object_profile_indicator { + 0x40 | 0x41 => CodecType::AAC, + 0x6B => CodecType::MP3, + _ => CodecType::Unknown, + }; + + if codec == CodecType::Unknown { + return Err(Error::Unsupported("unknown audio codec")); + } + + Ok(ES_Descriptor { + audio_codec: codec, + audio_sample_rate: sample_frequency, + codec_specific_config: esds_array, + }) +} + +/// Parse `FLACSpecificBox`. +fn read_dfla(src: &mut BMFFBox) -> Result { + let (version, flags) = try!(read_fullbox_extra(src)); + if version != 0 { + return Err(Error::Unsupported("unknown dfLa (FLAC) version")); + } + if flags != 0 { + return Err(Error::InvalidData("no-zero dfLa (FLAC) flags")); + } + let mut blocks = Vec::new(); + while src.bytes_left() > 0 { + let block = try!(read_flac_metadata(src)); + blocks.push(block); + } + // The box must have at least one meta block, and the first block + // must be the METADATA_BLOCK_STREAMINFO + if blocks.is_empty() { + return Err(Error::InvalidData("FLACSpecificBox missing metadata")); + } else if blocks[0].block_type != 0 { + println!("flac metadata block:\n {:?}", blocks[0]); + return Err(Error::InvalidData( + "FLACSpecificBox must have STREAMINFO metadata first")); + } else if blocks[0].data.len() != 34 { + return Err(Error::InvalidData( + "FLACSpecificBox STREAMINFO block is the wrong size")); + } + Ok(FLACSpecificBox { + version: version, + blocks: blocks, + }) +} + /// Parse `OpusSpecificBox`. fn read_dops(src: &mut BMFFBox) -> Result { let version = try!(src.read_u8()); if version != 0 { - return Err(Error::Unsupported("unknown dOps version")); + return Err(Error::Unsupported("unknown dOps (Opus) version")); } let output_channel_count = try!(src.read_u8()); @@ -1149,7 +1369,7 @@ fn read_hdlr(src: &mut BMFFBox) -> Result { } /// Parse an video description inside an stsd box. -fn read_video_desc(src: &mut BMFFBox, track: &mut Track) -> Result { +fn read_video_sample_entry(src: &mut BMFFBox, track: &mut Track) -> Result { let name = src.get_header().name; track.codec_type = match name { BoxType::AVCSampleEntry | BoxType::AVC3SampleEntry => CodecType::H264, @@ -1222,12 +1442,29 @@ fn read_video_desc(src: &mut BMFFBox, track: &mut Track) -> Result(src: &mut BMFFBox) -> Result { + let mut codec_specific = None; + let mut iter = src.box_iter(); + while let Some(mut b) = try!(iter.next_box()) { + match b.head.name { + BoxType::ESDBox => { + let esds = try!(read_esds(&mut b)); + codec_specific = Some(esds); + }, + _ => try!(skip_box_content(&mut b)), + } + } + + codec_specific.ok_or_else(|| Error::InvalidData("malformed audio sample entry")) +} + /// Parse an audio description inside an stsd box. -fn read_audio_desc(src: &mut BMFFBox, track: &mut Track) -> Result { +fn read_audio_sample_entry(src: &mut BMFFBox, track: &mut Track) -> Result { let name = src.get_header().name; track.codec_type = match name { // TODO(kinetik): stagefright inspects ESDS to detect MP3 (audio/mpeg). BoxType::MP4AudioSampleEntry => CodecType::AAC, + BoxType::FLACSampleEntry => CodecType::FLAC, BoxType::OpusSampleEntry => CodecType::Opus, BoxType::ProtectedAudioSampleEntry => CodecType::EncryptedAudio, _ => CodecType::Unknown, @@ -1257,6 +1494,11 @@ fn read_audio_desc(src: &mut BMFFBox, track: &mut Track) -> Result (), + 1 => { + // Quicktime sound sample description version 1. + // Skip uninteresting fields. + try!(skip(src, 16)); + }, _ => return Err(Error::Unsupported("unsupported non-isom audio sample entry")), } @@ -1270,24 +1512,35 @@ fn read_audio_desc(src: &mut BMFFBox, track: &mut Track) -> Result BUF_SIZE_LIMIT { - return Err(Error::InvalidData("esds box exceeds BUF_SIZE_LIMIT")); } - let esds = try!(read_buf(&mut b.content, esds_size as usize)); - // TODO(kinetik): Parse esds box? For now we just stash the data. + + let esds = try!(read_esds(&mut b)); + track.codec_type = esds.audio_codec; codec_specific = Some(AudioCodecSpecific::ES_Descriptor(esds)); } + BoxType::FLACSpecificBox => { + if name != BoxType::FLACSampleEntry || + codec_specific.is_some() { + return Err(Error::InvalidData("malformed audio sample entry")); + } + let dfla = try!(read_dfla(&mut b)); + track.codec_type = CodecType::FLAC; + codec_specific = Some(AudioCodecSpecific::FLACSpecificBox(dfla)); + } BoxType::OpusSpecificBox => { if name != BoxType::OpusSampleEntry || codec_specific.is_some() { return Err(Error::InvalidData("malformed audio sample entry")); } let dops = try!(read_dops(&mut b)); + track.codec_type = CodecType::Opus; codec_specific = Some(AudioCodecSpecific::OpusSpecificBox(dops)); } + BoxType::QTWaveAtom => { + let qt_esds = try!(read_qt_wave_atom(&mut b)); + track.codec_type = qt_esds.audio_codec; + codec_specific = Some(AudioCodecSpecific::ES_Descriptor(qt_esds)); + } _ => try!(skip_box_content(&mut b)), } check_parser_state!(b.content); @@ -1311,38 +1564,43 @@ fn read_stsd(src: &mut BMFFBox, track: &mut Track) -> Result read_video_desc(&mut b, track), - TrackType::Audio => read_audio_desc(&mut b, track), - TrackType::Unknown => Err(Error::Unsupported("unknown track type")), - }; - let description = match description { - Ok(desc) => desc, - Err(Error::Unsupported(_)) => { - // read_{audio,video}_desc may have returned Unsupported - // after partially reading the box content, so we can't - // simply use skip_box_content here. - let to_skip = b.bytes_left(); - try!(skip(&mut b, to_skip)); - SampleEntry::Unknown + { + // TODO(kinetik): check if/when more than one desc per track? do we need to support? + let mut iter = src.box_iter(); + while let Some(mut b) = try!(iter.next_box()) { + let description = match track.track_type { + TrackType::Video => read_video_sample_entry(&mut b, track), + TrackType::Audio => read_audio_sample_entry(&mut b, track), + TrackType::Unknown => Err(Error::Unsupported("unknown track type")), + }; + let description = match description { + Ok(desc) => desc, + Err(Error::Unsupported(_)) => { + // read_{audio,video}_desc may have returned Unsupported + // after partially reading the box content, so we can't + // simply use skip_box_content here. + let to_skip = b.bytes_left(); + try!(skip(&mut b, to_skip)); + SampleEntry::Unknown + } + Err(e) => return Err(e), + }; + if track.data.is_none() { + track.data = Some(description.clone()); + } else { + log!("** don't know how to handle multiple descriptions **"); + } + descriptions.push(description); + check_parser_state!(b.content); + if descriptions.len() == description_count as usize { + break; } - Err(e) => return Err(e), - }; - if track.data.is_none() { - track.data = Some(description.clone()); - } else { - log!("** don't know how to handle multiple descriptions **"); - } - descriptions.push(description); - check_parser_state!(b.content); - if descriptions.len() == description_count as usize { - break; } } + // Padding could be added in some contents. + try!(skip_box_remain(src)); + Ok(SampleDescriptionBox { descriptions: descriptions, }) @@ -1424,6 +1682,12 @@ fn be_u16(src: &mut T) -> Result { src.read_u16::().map_err(From::from) } +fn be_u24(src: &mut T) -> Result { + src.read_uint::(3) + .map(|v| v as u32) + .map_err(From::from) +} + fn be_u32(src: &mut T) -> Result { src.read_u32::().map_err(From::from) } diff --git a/media/libstagefright/binding/mp4parse/src/tests.rs b/media/libstagefright/binding/mp4parse/src/tests.rs index 56e8b0a2d181..7063b37906bc 100644 --- a/media/libstagefright/binding/mp4parse/src/tests.rs +++ b/media/libstagefright/binding/mp4parse/src/tests.rs @@ -442,6 +442,102 @@ fn read_hdlr_zero_length_name() { assert_eq!(parsed.handler_type, 0x76696465); // vide } +fn flac_streaminfo() -> Vec { + vec![ + 0x10, 0x00, 0x10, 0x00, 0x00, 0x0a, 0x11, 0x00, + 0x38, 0x32, 0x0a, 0xc4, 0x42, 0xf0, 0x00, 0xc9, + 0xdf, 0xae, 0xb5, 0x66, 0xfc, 0x02, 0x15, 0xa3, + 0xb1, 0x54, 0x61, 0x47, 0x0f, 0xfb, 0x05, 0x00, + 0x33, 0xad, + ] +} + +#[test] +fn read_flac() { + let mut stream = make_box(BoxSize::Auto, b"fLaC", |s| { + s.append_repeated(0, 6) // reserved + .B16(1) // data reference index + .B32(0) // reserved + .B32(0) // reserved + .B16(2) // channel count + .B16(16) // bits per sample + .B16(0) // pre_defined + .B16(0) // reserved + .B32(44100 << 16) // Sample rate + .append_bytes(&make_dfla(FlacBlockType::StreamInfo, true, + &flac_streaminfo(), FlacBlockLength::Correct) + .into_inner()) + }); + let mut iter = super::BoxIter::new(&mut stream); + let mut stream = iter.next_box().unwrap().unwrap(); + let mut track = super::Track::new(0); + let r = super::read_audio_sample_entry(&mut stream, &mut track); + r.unwrap(); +} + +#[derive(Clone, Copy)] +enum FlacBlockType { + StreamInfo = 0, + _Padding = 1, + _Application = 2, + _Seektable = 3, + _Comment = 4, + _Cuesheet = 5, + _Picture = 6, + _Reserved, + _Invalid = 127, +} + +enum FlacBlockLength { + Correct, + Incorrect(usize), +} + +fn make_dfla(block_type: FlacBlockType, last: bool, data: &Vec, + data_length: FlacBlockLength) -> Cursor> { + assert!(data.len() < 1<<24); + make_fullbox(BoxSize::Auto, b"dfLa", 0, |s| { + let flag = match last { + true => 1, + false => 0, + }; + let size = match data_length { + FlacBlockLength::Correct => (data.len() as u32) & 0xffffff, + FlacBlockLength::Incorrect(size) => { + assert!(size < 1<<24); + (size as u32) & 0xffffff + } + }; + let block_type = (block_type as u32) & 0x7f; + s.B32(flag << 31 | block_type << 24 | size) + .append_bytes(data) + }) +} + +#[test] +fn read_dfla() { + let mut stream = make_dfla(FlacBlockType::StreamInfo, true, + &flac_streaminfo(), FlacBlockLength::Correct); + let mut iter = super::BoxIter::new(&mut stream); + let mut stream = iter.next_box().unwrap().unwrap(); + assert_eq!(stream.head.name, BoxType::FLACSpecificBox); + let dfla = super::read_dfla(&mut stream).unwrap(); + assert_eq!(dfla.version, 0); +} + +#[test] +fn long_flac_metadata() { + let streaminfo = flac_streaminfo(); + let mut stream = make_dfla(FlacBlockType::StreamInfo, true, + &streaminfo, + FlacBlockLength::Incorrect(streaminfo.len() + 4)); + let mut iter = super::BoxIter::new(&mut stream); + let mut stream = iter.next_box().unwrap().unwrap(); + assert_eq!(stream.head.name, BoxType::FLACSpecificBox); + let r = super::read_dfla(&mut stream); + assert!(r.is_err()); +} + #[test] fn read_opus() { let mut stream = make_box(BoxSize::Auto, b"Opus", |s| { @@ -459,7 +555,7 @@ fn read_opus() { let mut iter = super::BoxIter::new(&mut stream); let mut stream = iter.next_box().unwrap().unwrap(); let mut track = super::Track::new(0); - let r = super::read_audio_desc(&mut stream, &mut track); + let r = super::read_audio_sample_entry(&mut stream, &mut track); assert!(r.is_ok()); } @@ -547,7 +643,7 @@ fn avcc_limit() { let mut iter = super::BoxIter::new(&mut stream); let mut stream = iter.next_box().unwrap().unwrap(); let mut track = super::Track::new(0); - match super::read_video_desc(&mut stream, &mut track) { + match super::read_video_sample_entry(&mut stream, &mut track) { Err(Error::InvalidData(s)) => assert_eq!(s, "avcC box exceeds BUF_SIZE_LIMIT"), Ok(_) => assert!(false, "expected an error result"), _ => assert!(false, "expected a different error result"), @@ -573,7 +669,7 @@ fn esds_limit() { let mut iter = super::BoxIter::new(&mut stream); let mut stream = iter.next_box().unwrap().unwrap(); let mut track = super::Track::new(0); - match super::read_audio_desc(&mut stream, &mut track) { + match super::read_audio_sample_entry(&mut stream, &mut track) { Err(Error::InvalidData(s)) => assert_eq!(s, "esds box exceeds BUF_SIZE_LIMIT"), Ok(_) => assert!(false, "expected an error result"), _ => assert!(false, "expected a different error result"), @@ -599,7 +695,7 @@ fn esds_limit_2() { let mut iter = super::BoxIter::new(&mut stream); let mut stream = iter.next_box().unwrap().unwrap(); let mut track = super::Track::new(0); - match super::read_audio_desc(&mut stream, &mut track) { + match super::read_audio_sample_entry(&mut stream, &mut track) { Err(Error::UnexpectedEOF) => (), Ok(_) => assert!(false, "expected an error result"), _ => assert!(false, "expected a different error result"), @@ -661,3 +757,104 @@ fn invalid_pascal_string() { let s = super::read_fixed_length_pascal_string(&mut stream, 32).unwrap(); assert_eq!(s.len(), 31); } + +#[test] +fn skip_padding_in_boxes() { + // Padding data could be added in the end of these boxes. Parser needs to skip + // them instead of returning error. + let box_names = vec![b"stts", b"stsc", b"stsz", b"stco", b"co64", b"stss"]; + + for name in box_names { + let mut stream = make_fullbox(BoxSize::Auto, name, 1, |s| { + s.append_repeated(0, 100) // add padding data + }); + let mut iter = super::BoxIter::new(&mut stream); + let mut stream = iter.next_box().unwrap().unwrap(); + match name { + b"stts" => { + super::read_stts(&mut stream).expect("fail to skip padding: stts"); + }, + b"stsc" => { + super::read_stsc(&mut stream).expect("fail to skip padding: stsc"); + }, + b"stsz" => { + super::read_stsz(&mut stream).expect("fail to skip padding: stsz"); + }, + b"stco" => { + super::read_stco(&mut stream).expect("fail to skip padding: stco"); + }, + b"co64" => { + super::read_co64(&mut stream).expect("fail to skip padding: co64"); + }, + b"stss" => { + super::read_stss(&mut stream).expect("fail to skip padding: stss"); + }, + _ => (), + } + } +} + +#[test] +fn skip_padding_in_stsd() { + // Padding data could be added in the end of stsd boxes. Parser needs to skip + // them instead of returning error. + let avc = make_box(BoxSize::Auto, b"avc1", |s| { + s.append_repeated(0, 6) + .B16(1) + .append_repeated(0, 16) + .B16(320) + .B16(240) + .append_repeated(0, 14) + .append_repeated(0, 32) + .append_repeated(0, 4) + .B32(0xffffffff) + .append_bytes(b"avcC") + .append_repeated(0, 100) + }).into_inner(); + let mut stream = make_fullbox(BoxSize::Auto, b"stsd", 0, |s| { + s.B32(1) + .append_bytes(avc.as_slice()) + .append_repeated(0, 100) // add padding data + }); + + let mut iter = super::BoxIter::new(&mut stream); + let mut stream = iter.next_box().unwrap().unwrap(); + super::read_stsd(&mut stream, &mut super::Track::new(0)) + .expect("fail to skip padding: stsd"); +} + +#[test] +fn read_qt_wave_atom() { + let esds = make_fullbox(BoxSize::Auto, b"esds", 0, |s| { + s.B8(0x03) // elementary stream descriptor tag + .B8(0x0b) // esds length + .append_repeated(0, 2) + .B8(0x00) // flags + .B8(0x04) // decoder config descriptor tag + .B8(0x0d) // dcds length + .B8(0x6b) // mp3 + .append_repeated(0, 12) + }).into_inner(); + let wave = make_box(BoxSize::Auto, b"wave", |s| { + s.append_bytes(esds.as_slice()) + }).into_inner(); + let mut stream = make_box(BoxSize::Auto, b"mp4a", |s| { + s.append_repeated(0, 6) + .B16(1) // data_reference_count + .B16(1) // verion: qt -> 1 + .append_repeated(0, 6) + .B16(2) + .B16(16) + .append_repeated(0, 4) + .B32(48000 << 16) + .append_repeated(0, 16) + .append_bytes(wave.as_slice()) + }); + + let mut iter = super::BoxIter::new(&mut stream); + let mut stream = iter.next_box().unwrap().unwrap(); + let mut track = super::Track::new(0); + super::read_audio_sample_entry(&mut stream, &mut track) + .expect("fail to read qt wave atom"); + assert_eq!(track.codec_type, super::CodecType::MP3); +} diff --git a/media/libstagefright/binding/mp4parse/tests/public.rs b/media/libstagefright/binding/mp4parse/tests/public.rs index cfcb63ef83f9..1d36f5f5ac87 100644 --- a/media/libstagefright/binding/mp4parse/tests/public.rs +++ b/media/libstagefright/binding/mp4parse/tests/public.rs @@ -70,10 +70,18 @@ fn public_api() { // track.data part assert_eq!(match a.codec_specific { - mp4::AudioCodecSpecific::ES_Descriptor(v) => { - assert!(v.len() > 0); + mp4::AudioCodecSpecific::ES_Descriptor(esds) => { + assert_eq!(esds.audio_codec, mp4::CodecType::AAC); + assert_eq!(esds.audio_sample_rate.unwrap(), 48000); "ES" } + mp4::AudioCodecSpecific::FLACSpecificBox(flac) => { + // STREAMINFO block must be present and first. + assert!(flac.blocks.len() > 0); + assert!(flac.blocks[0].block_type == 0); + assert!(flac.blocks[0].data.len() == 34); + "FLAC" + } mp4::AudioCodecSpecific::OpusSpecificBox(opus) => { // We don't enter in here, we just check if fields are public. assert!(opus.version > 0); diff --git a/media/libstagefright/binding/mp4parse_capi/build.rs b/media/libstagefright/binding/mp4parse_capi/build.rs index 66019bed52e5..29f2a85ced13 100644 --- a/media/libstagefright/binding/mp4parse_capi/build.rs +++ b/media/libstagefright/binding/mp4parse_capi/build.rs @@ -1,6 +1,7 @@ extern crate cheddar; fn main() { + println!("cargo:rerun-if-changed=src/lib.rs"); // Generate mp4parse.h. cheddar::Cheddar::new().expect("could not read manifest") .insert_code("// THIS FILE IS AUTOGENERATED BY mp4parse-rust/build.rs - DO NOT EDIT\n\n") diff --git a/media/libstagefright/binding/mp4parse_capi/src/lib.rs b/media/libstagefright/binding/mp4parse_capi/src/lib.rs index 0d27ef95e383..e7f1d16c8800 100644 --- a/media/libstagefright/binding/mp4parse_capi/src/lib.rs +++ b/media/libstagefright/binding/mp4parse_capi/src/lib.rs @@ -52,6 +52,7 @@ use mp4parse::MediaScaledTime; use mp4parse::TrackTimeScale; use mp4parse::TrackScaledTime; use mp4parse::serialize_opus_header; +use mp4parse::CodecType; // rusty-cheddar's C enum generation doesn't namespace enum members by // prefixing them, so we're forced to do it in our member names until @@ -84,9 +85,11 @@ pub enum mp4parse_track_type { pub enum mp4parse_codec { MP4PARSE_CODEC_UNKNOWN, MP4PARSE_CODEC_AAC, + MP4PARSE_CODEC_FLAC, MP4PARSE_CODEC_OPUS, MP4PARSE_CODEC_AVC, MP4PARSE_CODEC_VP9, + MP4PARSE_CODEC_MP3, } #[repr(C)] @@ -342,8 +345,14 @@ pub unsafe extern fn mp4parse_get_track_info(parser: *mut mp4parse_parser, track Some(SampleEntry::Audio(ref audio)) => match audio.codec_specific { AudioCodecSpecific::OpusSpecificBox(_) => mp4parse_codec::MP4PARSE_CODEC_OPUS, - AudioCodecSpecific::ES_Descriptor(_) => + AudioCodecSpecific::FLACSpecificBox(_) => + mp4parse_codec::MP4PARSE_CODEC_FLAC, + AudioCodecSpecific::ES_Descriptor(ref esds) if esds.audio_codec == CodecType::AAC => mp4parse_codec::MP4PARSE_CODEC_AAC, + AudioCodecSpecific::ES_Descriptor(ref esds) if esds.audio_codec == CodecType::MP3 => + mp4parse_codec::MP4PARSE_CODEC_MP3, + AudioCodecSpecific::ES_Descriptor(_) => + mp4parse_codec::MP4PARSE_CODEC_UNKNOWN, }, Some(SampleEntry::Video(ref video)) => match video.codec_specific { VideoCodecSpecific::VPxConfig(_) => @@ -357,10 +366,8 @@ pub unsafe extern fn mp4parse_get_track_info(parser: *mut mp4parse_parser, track let track = &context.tracks[track_index]; if let (Some(track_timescale), - Some(context_timescale), - Some(track_duration)) = (track.timescale, - context.timescale, - track.duration) { + Some(context_timescale)) = (track.timescale, + context.timescale) { let media_time = match track.media_time.map_or(Some(0), |media_time| { track_time_to_us(media_time, track_timescale) }) { @@ -375,9 +382,14 @@ pub unsafe extern fn mp4parse_get_track_info(parser: *mut mp4parse_parser, track }; info.media_time = media_time - empty_duration; - match track_time_to_us(track_duration, track_timescale) { - Some(duration) => info.duration = duration, - None => return MP4PARSE_ERROR_INVALID, + if let Some(track_duration) = track.duration { + match track_time_to_us(track_duration, track_timescale) { + Some(duration) => info.duration = duration, + None => return MP4PARSE_ERROR_INVALID, + } + } else { + // Duration unknown; stagefright returns 0 for this. + info.duration = 0 } } else { return MP4PARSE_ERROR_INVALID @@ -427,11 +439,23 @@ pub unsafe extern fn mp4parse_get_track_audio_info(parser: *mut mp4parse_parser, match audio.codec_specific { AudioCodecSpecific::ES_Descriptor(ref v) => { - if v.len() > std::u32::MAX as usize { + if v.codec_specific_config.len() > std::u32::MAX as usize { return MP4PARSE_ERROR_INVALID; } - (*info).codec_specific_config.length = v.len() as u32; - (*info).codec_specific_config.data = v.as_ptr(); + (*info).codec_specific_config.length = v.codec_specific_config.len() as u32; + (*info).codec_specific_config.data = v.codec_specific_config.as_ptr(); + if let Some(rate) = v.audio_sample_rate { + (*info).sample_rate = rate; + } + } + AudioCodecSpecific::FLACSpecificBox(ref flac) => { + // Return the STREAMINFO metadata block in the codec_specific. + let streaminfo = &flac.blocks[0]; + if streaminfo.block_type != 0 || streaminfo.data.len() != 34 { + return MP4PARSE_ERROR_INVALID; + } + (*info).codec_specific_config.length = streaminfo.data.len() as u32; + (*info).codec_specific_config.data = streaminfo.data.as_ptr(); } AudioCodecSpecific::OpusSpecificBox(ref opus) => { let mut v = Vec::new(); @@ -445,6 +469,9 @@ pub unsafe extern fn mp4parse_get_track_audio_info(parser: *mut mp4parse_parser, match header.get(&track_index) { None => {} Some(v) => { + if v.len() > std::u32::MAX as usize { + return MP4PARSE_ERROR_INVALID; + } (*info).codec_specific_config.length = v.len() as u32; (*info).codec_specific_config.data = v.as_ptr(); } From a45686ff520827b7c0f51128a29ef05884cf9f52 Mon Sep 17 00:00:00 2001 From: Ralph Giles Date: Tue, 25 Oct 2016 16:42:12 -0700 Subject: [PATCH 28/60] Bug 1303888 - Accept flac from the rust mp4parse demuxer. r=kinetik Recognize FLAC as an audio mimetype in MP4Metadata and prefer the rust demuxer for it. Stagefright does not support this. MozReview-Commit-ID: 7T4tCSCCNBk --HG-- extra : rebase_source : b69c6e35d4e48c4d419856ee979eae893dbc72b1 --- media/libstagefright/binding/MP4Metadata.cpp | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/media/libstagefright/binding/MP4Metadata.cpp b/media/libstagefright/binding/MP4Metadata.cpp index a50730845247..5468dd46acbf 100644 --- a/media/libstagefright/binding/MP4Metadata.cpp +++ b/media/libstagefright/binding/MP4Metadata.cpp @@ -245,7 +245,8 @@ bool MP4Metadata::ShouldPreferRust() const { if (!info) { return false; } - if (info->mMimeType.EqualsASCII("audio/opus")) { + if (info->mMimeType.EqualsASCII("audio/opus") || + info->mMimeType.EqualsASCII("audio/flac")) { return true; } } @@ -741,6 +742,7 @@ MP4MetadataRust::GetTrackInfo(mozilla::TrackInfo::TrackType aType, case MP4PARSE_CODEC_UNKNOWN: codec_string = "unknown"; break; case MP4PARSE_CODEC_AAC: codec_string = "aac"; break; case MP4PARSE_CODEC_OPUS: codec_string = "opus"; break; + case MP4PARSE_CODEC_FLAC: codec_string = "flac"; break; case MP4PARSE_CODEC_AVC: codec_string = "h.264"; break; case MP4PARSE_CODEC_VP9: codec_string = "vp9"; break; } @@ -774,6 +776,8 @@ MP4MetadataRust::GetTrackInfo(mozilla::TrackInfo::TrackType aType, mozilla::FramesToUsecs(preskip, 48000).value()); } else if (info.codec == MP4PARSE_CODEC_AAC) { track->mMimeType = MEDIA_MIMETYPE_AUDIO_AAC; + } else if (info.codec == MP4PARSE_CODEC_FLAC) { + track->mMimeType = MEDIA_MIMETYPE_AUDIO_FLAC; } track->mCodecSpecificConfig->AppendElements( audio.codec_specific_config.data, From 1f1a694612593b63e96e8f0c88aee9e91f94f428 Mon Sep 17 00:00:00 2001 From: Ralph Giles Date: Tue, 25 Oct 2016 16:43:28 -0700 Subject: [PATCH 29/60] Bug 1303888 - Fix a logging typo. r=kinetik The error message refers to video, not audio tracks. Looks like a cut-and-paste error. MozReview-Commit-ID: J6ur36FMSRF --HG-- extra : rebase_source : 626e4b3287ce268d9daee26610a599c721116148 --- media/libstagefright/binding/MP4Metadata.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/media/libstagefright/binding/MP4Metadata.cpp b/media/libstagefright/binding/MP4Metadata.cpp index 5468dd46acbf..6c30b06a5040 100644 --- a/media/libstagefright/binding/MP4Metadata.cpp +++ b/media/libstagefright/binding/MP4Metadata.cpp @@ -795,7 +795,7 @@ MP4MetadataRust::GetTrackInfo(mozilla::TrackInfo::TrackType aType, mp4parse_track_video_info video; auto rv = mp4parse_get_track_video_info(mRustParser.get(), trackIndex.value(), &video); if (rv != MP4PARSE_OK) { - MOZ_LOG(sLog, LogLevel::Warning, ("mp4parse_get_track_audio_info returned error %d", rv)); + MOZ_LOG(sLog, LogLevel::Warning, ("mp4parse_get_track_video_info returned error %d", rv)); return nullptr; } auto track = mozilla::MakeUnique(); From b547239226e1de6bc41a02aabc31162df62e1fe7 Mon Sep 17 00:00:00 2001 From: Gregory Szorc Date: Mon, 24 Oct 2016 09:58:01 -0700 Subject: [PATCH 30/60] Bug 1312475 - Add a version parameter to checkouts cache; r=dustin ff5a4bab0813 (bug 1311791) and 332a08725ed0 (bug 1292071) changed behavior of the VCS caches. First, the store cache / path was merged into the checkouts cache. Then the path of the Mercurial shared store was moved within the cache to always be rooted at the cache root. Caches are shared across tasks. Tasks can execute on any revision configured to use a cache. So, when interacting with caches, it is important to consider how every revision configured to use that cache will interact with it. Take this scenario for example. A worker executes a task where the hg shared store is rooted at /home/worker/checkouts/src/hg-shared. Then the worker executes a task where the hg shared store is rooted at /home/worker/checkouts/hg-store. `hg robustcheckout` will see the checkout from the first task. But then it sees that the store it is pointing to is at an unexpected location (checkouts/src/hg-shared instead of checkouts/hg-store). `hg robustcheckout` aggressively normalizes state to ensure consistency. So when it sees this mismatch, it blows away the checkout and creates one from checkouts/hg-store to replace it. That's a lot of overhead. And this cycle can repeat itself if the right combination of revisions run on the worker! A solution to this problem is to create a clean break from caches when cache semantics change. In TaskCluster, that means using a different cache. This commit introduces a "version" component to the checkouts cache name. By doing so, we create a clean break from all previous caches, ensuring all revisions this point forward won't encounter an hg shared store at an unexpected location. This also paves the road for easily making additional clean breaks in the future. MozReview-Commit-ID: JT8yuULKpch --HG-- extra : rebase_source : 2e5d321e4314ff7543423d3c7837b770b7c8a3a3 --- taskcluster/docs/caches.rst | 5 ++++- taskcluster/taskgraph/transforms/job/common.py | 10 +++++++++- 2 files changed, 13 insertions(+), 2 deletions(-) diff --git a/taskcluster/docs/caches.rst b/taskcluster/docs/caches.rst index 8f35ff1cf03b..9f19035d722c 100644 --- a/taskcluster/docs/caches.rst +++ b/taskcluster/docs/caches.rst @@ -10,7 +10,7 @@ document them and their appropriate use. Version Control Caches ====================== -``level-{{level}}-checkouts`` +``level-{{level}}-checkouts-{{version}}`` This cache holds version control checkouts, each in a subdirectory named after the repo (e.g., ``gecko``). @@ -18,6 +18,9 @@ Version Control Caches content of a checkout, this content should be written in a separate directory/cache (like a workspace). + A ``version`` parameter appears in the cache name to allow + backwards-incompatible changes to the cache's behavior. + ``level-{{level}}-{{project}}-tc-vcs`` (deprecated) This cache is used internally by ``tc-vcs``. This tool is deprecated and should be replaced with ``hg robustcheckout``. diff --git a/taskcluster/taskgraph/transforms/job/common.py b/taskcluster/taskgraph/transforms/job/common.py index 6fac440d5ffa..59a51d75ad4a 100644 --- a/taskcluster/taskgraph/transforms/job/common.py +++ b/taskcluster/taskgraph/transforms/job/common.py @@ -67,7 +67,15 @@ def docker_worker_support_vcs_checkout(config, job, taskdesc): taskdesc['worker'].setdefault('caches', []).append({ 'type': 'persistent', - 'name': 'level-%s-checkouts' % level, + # History of versions: + # + # ``level-%s-checkouts`` was initially used and contained a number + # of backwards incompatible changes, such as moving HG_STORE_PATH + # from a separate cache to this cache. + # + # ``v1`` was introduced to provide a clean break from the unversioned + # cache. + 'name': 'level-%s-checkouts-v1' % level, 'mount-point': '/home/worker/checkouts', }) From 9e17d950d7cc1dd9d2d9ad7bdbe9226c295c0944 Mon Sep 17 00:00:00 2001 From: Henrik Skupin Date: Mon, 24 Oct 2016 17:38:30 +0200 Subject: [PATCH 31/60] Bug 1141483 - After a restart Marionette doesn't restore the previous context. r=automatedtester MozReview-Commit-ID: KCI7UZn0NeZ --HG-- extra : rebase_source : 1d743d69c1ab1e4ce3c2f90e474b5e27f9043814 --- .../client/marionette_driver/marionette.py | 57 ++++++++++-------- .../tests/unit/test_profile_management.py | 2 - .../tests/unit/test_quit_restart.py | 60 +++++++++++++++++++ .../firefox_puppeteer/testcases/base.py | 3 - 4 files changed, 93 insertions(+), 29 deletions(-) diff --git a/testing/marionette/client/marionette_driver/marionette.py b/testing/marionette/client/marionette_driver/marionette.py index 68dc9d5f68f5..1a70725ab751 100644 --- a/testing/marionette/client/marionette_driver/marionette.py +++ b/testing/marionette/client/marionette_driver/marionette.py @@ -1048,37 +1048,41 @@ class Marionette(object): raise errors.MarionetteException("enforce_gecko_prefs() can only be called " "on Gecko instances launched by Marionette") pref_exists = True - self.set_context(self.CONTEXT_CHROME) - for pref, value in prefs.iteritems(): - if type(value) is not str: - value = json.dumps(value) - pref_exists = self.execute_script(""" - let prefInterface = Components.classes["@mozilla.org/preferences-service;1"] - .getService(Components.interfaces.nsIPrefBranch); - let pref = '{0}'; - let value = '{1}'; - let type = prefInterface.getPrefType(pref); - switch(type) {{ - case prefInterface.PREF_STRING: - return value == prefInterface.getCharPref(pref).toString(); - case prefInterface.PREF_BOOL: - return value == prefInterface.getBoolPref(pref).toString(); - case prefInterface.PREF_INT: - return value == prefInterface.getIntPref(pref).toString(); - case prefInterface.PREF_INVALID: - return false; - }} - """.format(pref, value)) - if not pref_exists: - break - self.set_context(self.CONTEXT_CONTENT) + with self.using_context(self.CONTEXT_CHROME): + for pref, value in prefs.iteritems(): + if type(value) is not str: + value = json.dumps(value) + pref_exists = self.execute_script(""" + let prefInterface = Components.classes["@mozilla.org/preferences-service;1"] + .getService(Components.interfaces.nsIPrefBranch); + let pref = '{0}'; + let value = '{1}'; + let type = prefInterface.getPrefType(pref); + switch(type) {{ + case prefInterface.PREF_STRING: + return value == prefInterface.getCharPref(pref).toString(); + case prefInterface.PREF_BOOL: + return value == prefInterface.getBoolPref(pref).toString(); + case prefInterface.PREF_INT: + return value == prefInterface.getIntPref(pref).toString(); + case prefInterface.PREF_INVALID: + return false; + }} + """.format(pref, value)) + if not pref_exists: + break + if not pref_exists: + context = self._send_message("getContext", key="value") self.delete_session() self.instance.restart(prefs) self.raise_for_port() self.start_session() self.reset_timeouts() + # Restore the context as used before the restart + self.set_context(context) + def _request_in_app_shutdown(self, shutdown_flags=None): """Terminate the currently running instance from inside the application. @@ -1157,6 +1161,8 @@ class Marionette(object): if not self.instance: raise errors.MarionetteException("restart() can only be called " "on Gecko instances launched by Marionette") + + context = self._send_message("getContext", key="value") session_id = self.session_id if in_app: @@ -1186,6 +1192,9 @@ class Marionette(object): self.start_session(session_id=session_id) self.reset_timeouts() + # Restore the context as used before the restart + self.set_context(context) + if in_app and self.session.get("processId"): # In some cases Firefox restarts itself by spawning into a new process group. # As long as mozprocess cannot track that behavior (bug 1284864) we assist by diff --git a/testing/marionette/harness/marionette/tests/unit/test_profile_management.py b/testing/marionette/harness/marionette/tests/unit/test_profile_management.py index 884514c0889e..3d801ea2c1a5 100644 --- a/testing/marionette/harness/marionette/tests/unit/test_profile_management.py +++ b/testing/marionette/harness/marionette/tests/unit/test_profile_management.py @@ -25,12 +25,10 @@ class TestProfileManagement(MarionetteTestCase): self.assertTrue(self.marionette.get_pref("marionette.test.bool")) self.marionette.enforce_gecko_prefs({"marionette.test.bool": False}) - self.marionette.set_context('chrome') self.assertFalse(self.marionette.get_pref("marionette.test.bool")) def test_clean_profile(self): self.marionette.restart(clean=True) - self.marionette.set_context('chrome') self.assertEqual(self.marionette.get_pref("marionette.test.bool"), None) diff --git a/testing/marionette/harness/marionette/tests/unit/test_quit_restart.py b/testing/marionette/harness/marionette/tests/unit/test_quit_restart.py index 438df673db35..90f71c06a17b 100644 --- a/testing/marionette/harness/marionette/tests/unit/test_quit_restart.py +++ b/testing/marionette/harness/marionette/tests/unit/test_quit_restart.py @@ -100,6 +100,66 @@ class TestQuitRestart(MarionetteTestCase): self.assertNotEqual(self.marionette.session_id, self.session_id) self.assertNotEqual(self.marionette.get_pref("browser.startup.page"), 3) + def test_reset_context_after_quit_by_set_context(self): + # Check that we are in content context which is used by default in Marionette + self.assertNotIn('chrome://', self.marionette.get_url(), + "Context doesn't default to content") + + self.marionette.set_context('chrome') + self.marionette.quit(in_app=True) + self.assertEqual(self.marionette.session, None) + self.marionette.start_session() + self.assertNotIn('chrome://', self.marionette.get_url(), + "Not in content context after quit with using_context") + + def test_reset_context_after_quit_by_using_context(self): + # Check that we are in content context which is used by default in Marionette + self.assertNotIn('chrome://', self.marionette.get_url(), + "Context doesn't default to content") + + with self.marionette.using_context('chrome'): + self.marionette.quit(in_app=True) + self.assertEqual(self.marionette.session, None) + self.marionette.start_session() + self.assertNotIn('chrome://', self.marionette.get_url(), + "Not in content context after quit with using_context") + + def test_keep_context_after_restart_by_set_context(self): + # Check that we are in content context which is used by default in Marionette + self.assertNotIn('chrome://', self.marionette.get_url(), + "Context doesn't default to content") + + # restart while we are in chrome context + self.marionette.set_context('chrome') + self.marionette.restart(in_app=True) + + # An in-app restart will keep the same process id only on Linux + if self.marionette.session_capabilities['platformName'] == 'linux': + self.assertEqual(self.marionette.session["processId"], self.pid) + else: + self.assertNotEqual(self.marionette.session["processId"], self.pid) + + self.assertIn('chrome://', self.marionette.get_url(), + "Not in chrome context after a restart with set_context") + + def test_keep_context_after_restart_by_using_context(self): + # Check that we are in content context which is used by default in Marionette + self.assertNotIn('chrome://', self.marionette.get_url(), + "Context doesn't default to content") + + # restart while we are in chrome context + with self.marionette.using_context('chrome'): + self.marionette.restart(in_app=True) + + # An in-app restart will keep the same process id only on Linux + if self.marionette.session_capabilities['platformName'] == 'linux': + self.assertEqual(self.marionette.session["processId"], self.pid) + else: + self.assertNotEqual(self.marionette.session["processId"], self.pid) + + self.assertIn('chrome://', self.marionette.get_url(), + "Not in chrome context after a restart with using_context") + def shutdown(self, restart=False): self.marionette.set_context("chrome") self.marionette.execute_script(""" diff --git a/testing/puppeteer/firefox/firefox_puppeteer/testcases/base.py b/testing/puppeteer/firefox/firefox_puppeteer/testcases/base.py index b7d47892186c..8dcda71df0b5 100644 --- a/testing/puppeteer/firefox/firefox_puppeteer/testcases/base.py +++ b/testing/puppeteer/firefox/firefox_puppeteer/testcases/base.py @@ -76,9 +76,6 @@ class BaseFirefoxTestCase(unittest.TestCase, Puppeteer): else: self.marionette.restart(in_app=True) - # Marionette doesn't keep the former context, so restore to chrome - self.marionette.set_context('chrome') - # Ensure that we always have a valid browser instance available self.browser = self.windows.switch_to(lambda win: type(win) is BrowserWindow) From 628bd1ae8782f24773a42b182679d7985f0a739a Mon Sep 17 00:00:00 2001 From: Thom Chiovoloni Date: Tue, 25 Oct 2016 12:13:34 -0400 Subject: [PATCH 32/60] Bug 1312015 - Ensure that TPS catches failures when generating sync telemetry r=markh MozReview-Commit-ID: HdXROi6Ctcj --HG-- extra : rebase_source : e5f980222f0323c8aaff5f934e606092691d80cb --- .../sync/tps/extensions/tps/resource/tps.jsm | 37 +++++++++++++++++++ 1 file changed, 37 insertions(+) diff --git a/services/sync/tps/extensions/tps/resource/tps.jsm b/services/sync/tps/extensions/tps/resource/tps.jsm index 8bf20e7ee746..4260e8f037e3 100644 --- a/services/sync/tps/extensions/tps/resource/tps.jsm +++ b/services/sync/tps/extensions/tps/resource/tps.jsm @@ -23,6 +23,7 @@ Cu.import("resource://services-common/async.js"); Cu.import("resource://services-sync/constants.js"); Cu.import("resource://services-sync/main.js"); Cu.import("resource://services-sync/util.js"); +Cu.import("resource://services-sync/telemetry.js"); Cu.import("resource://services-sync/bookmark_validator.js"); Cu.import("resource://services-sync/engines/passwords.js"); Cu.import("resource://services-sync/engines/forms.js"); @@ -106,6 +107,8 @@ var TPS = { _phaselist: {}, _setupComplete: false, _syncActive: false, + _syncCount: 0, + _syncsReportedViaTelemetry: 0, _syncErrors: 0, _syncWipeAction: null, _tabsAdded: 0, @@ -910,6 +913,8 @@ var TPS = { prefs.setCharPref('tps.account.passphrase', this.config.sync_account.passphrase); } + this._interceptSyncTelemetry(); + // start processing the test actions this._currentAction = 0; } @@ -919,6 +924,37 @@ var TPS = { } }, + /** + * Override sync telemetry functions so that we can detect errors generating + * the sync ping, and count how many pings we report. + */ + _interceptSyncTelemetry() { + let originalObserve = SyncTelemetry.observe; + let self = this; + SyncTelemetry.observe = function() { + try { + originalObserve.apply(this, arguments); + } catch (e) { + self.DumpError("Error when generating sync telemetry", e); + } + }; + SyncTelemetry.submit = record => { + Logger.logInfo("Intercepted sync telemetry submission: " + JSON.stringify(record)); + this._syncsReportedViaTelemetry += record.syncs.length + (record.discarded || 0); + if (record.discarded) { + Logger.AssertTrue(record.syncs.length == SyncTelemetry.maxPayloadCount, + "Syncs discarded from ping before maximum payload count reached"); + } + // If this is the shutdown ping, check and see that the telemetry saw all the syncs. + if (record.why === "shutdown") { + // If we happen to sync outside of tps manually causing it, its not an + // error in the telemetry, so we only complain if we didn't see all of them. + Logger.AssertTrue(this._syncsReportedViaTelemetry >= this._syncCount, + `Telemetry missed syncs: Saw ${this._syncsReportedViaTelemetry}, should have >= ${this._syncCount}.`); + } + }; + }, + /** * Register a single phase with the test harness. * @@ -1101,6 +1137,7 @@ var TPS = { } this.Login(false); + ++this._syncCount; this._triggeredSync = true; this.StartAsyncOperation(); From b041553ba86f4247bf2184d42249fdb14dac430c Mon Sep 17 00:00:00 2001 From: Thom Chiovoloni Date: Tue, 25 Oct 2016 11:15:19 -0400 Subject: [PATCH 33/60] Bug 1304534 - Enable "Send Tab to Device" on builds other than nightly r=markh MozReview-Commit-ID: BNKYhCQsZey --HG-- extra : rebase_source : 159b3d16e5cbbfde2fa71307a6fe270600daf5b5 --- browser/app/profile/firefox.js | 4 ---- 1 file changed, 4 deletions(-) diff --git a/browser/app/profile/firefox.js b/browser/app/profile/firefox.js index 92d00cab4c6f..2991eb6d36d1 100644 --- a/browser/app/profile/firefox.js +++ b/browser/app/profile/firefox.js @@ -1127,11 +1127,7 @@ pref("services.sync.prefs.sync.xpinstall.whitelist.required", true); // user's tabs and bookmarks. Note this pref is also synced. pref("services.sync.syncedTabs.showRemoteIcons", true); -#ifdef NIGHTLY_BUILD pref("services.sync.sendTabToDevice.enabled", true); -#else -pref("services.sync.sendTabToDevice.enabled", false); -#endif // Developer edition preferences #ifdef MOZ_DEV_EDITION From 463d8d9ba6e59027a63bceb47d74e7424dfc5ce1 Mon Sep 17 00:00:00 2001 From: Sebastian Kaspari Date: Tue, 25 Oct 2016 16:21:11 +0200 Subject: [PATCH 34/60] Bug 1311938 - Activity Stream: Use default base margin for "highlights" label. r=ahunt MozReview-Commit-ID: BjCchrU6PZt --HG-- extra : rebase_source : fa92fb3b160e099edaffd2523dc5605b57b9771c --- .../layout/activity_stream_main_toppanel.xml | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/mobile/android/base/resources/layout/activity_stream_main_toppanel.xml b/mobile/android/base/resources/layout/activity_stream_main_toppanel.xml index 3f8fdf85b491..b12c597a7eef 100644 --- a/mobile/android/base/resources/layout/activity_stream_main_toppanel.xml +++ b/mobile/android/base/resources/layout/activity_stream_main_toppanel.xml @@ -38,11 +38,12 @@ + android:layout_alignParentStart="true" /> \ No newline at end of file From 1eefd99be60324822abd7096cb09e7e509a0a6b9 Mon Sep 17 00:00:00 2001 From: Sebastian Kaspari Date: Tue, 25 Oct 2016 15:16:40 +0200 Subject: [PATCH 35/60] Bug 1312033 - Activity Stream Top Sites: Never add more sites than returned by the cursor. r=ahunt MozReview-Commit-ID: JONNSrRPNyW --HG-- extra : rebase_source : 8f4f6adacc6b95d497a98f693783be5dfe6db94b --- .../home/activitystream/topsites/TopSitesPageAdapter.java | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/mobile/android/base/java/org/mozilla/gecko/home/activitystream/topsites/TopSitesPageAdapter.java b/mobile/android/base/java/org/mozilla/gecko/home/activitystream/topsites/TopSitesPageAdapter.java index aaeccda7f639..74b2c0084873 100644 --- a/mobile/android/base/java/org/mozilla/gecko/home/activitystream/topsites/TopSitesPageAdapter.java +++ b/mobile/android/base/java/org/mozilla/gecko/home/activitystream/topsites/TopSitesPageAdapter.java @@ -6,12 +6,8 @@ package org.mozilla.gecko.home.activitystream.topsites; import android.content.Context; import android.database.Cursor; -import android.database.CursorWrapper; import android.support.annotation.UiThread; -import android.support.v7.widget.CardView; import android.support.v7.widget.RecyclerView; -import android.util.Log; -import android.util.TypedValue; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; @@ -63,7 +59,7 @@ public class TopSitesPageAdapter extends RecyclerView.Adapter { return; } - for (int i = 0; i < tiles; i++) { + for (int i = 0; i < tiles && startIndex + i < cursor.getCount(); i++) { cursor.moveToPosition(startIndex + i); // The Combined View only contains pages that have been visited at least once, i.e. any From 7e75e60f1ff22dca1e0ad3bebfb9816283bd7ef8 Mon Sep 17 00:00:00 2001 From: Sebastian Hengst Date: Wed, 26 Oct 2016 19:01:38 +0200 Subject: [PATCH 36/60] Backed out changeset 6a904e8a06a7 (bug 1272890) for timing out in test_ext_tab_teardown.html. r=backout --- .../extensions/ExtensionContent.jsm | 36 ++---- .../test/mochitest/file_with_about_blank.html | 10 -- .../extensions/test/mochitest/mochitest.ini | 3 - .../test_ext_contentscript_about_blank.html | 117 ------------------ 4 files changed, 7 insertions(+), 159 deletions(-) delete mode 100644 toolkit/components/extensions/test/mochitest/file_with_about_blank.html delete mode 100644 toolkit/components/extensions/test/mochitest/test_ext_contentscript_about_blank.html diff --git a/toolkit/components/extensions/ExtensionContent.jsm b/toolkit/components/extensions/ExtensionContent.jsm index 4415d57a944b..ceaf889eb35b 100644 --- a/toolkit/components/extensions/ExtensionContent.jsm +++ b/toolkit/components/extensions/ExtensionContent.jsm @@ -101,7 +101,6 @@ function Script(extension, options, deferred = PromiseUtils.defer()) { this.js = this.options.js || []; this.css = this.options.css || []; this.remove_css = this.options.remove_css; - this.match_about_blank = this.options.match_about_blank; this.deferred = deferred; @@ -141,12 +140,6 @@ Script.prototype = { return false; } - if (this.match_about_blank && ["about:blank", "about:srcdoc"].includes(uri.spec)) { - // When matching about:blank/srcdoc documents, the checks below - // need to be performed against the "owner" document's URI. - uri = window.document.nodePrincipal.URI; - } - if (!(this.matches_.matches(uri) || this.matches_host_.matchesIgnoringPath(uri))) { return false; } @@ -173,6 +166,8 @@ Script.prototype = { return false; } + // TODO: match_about_blank. + return true; }, @@ -431,13 +426,11 @@ DocumentManager = { extensionPageWindows: new Map(), init() { - Services.obs.addObserver(this, "content-document-global-created", false); Services.obs.addObserver(this, "document-element-inserted", false); Services.obs.addObserver(this, "inner-window-destroyed", false); }, uninit() { - Services.obs.removeObserver(this, "content-document-global-created"); Services.obs.removeObserver(this, "document-element-inserted"); Services.obs.removeObserver(this, "inner-window-destroyed"); }, @@ -454,27 +447,13 @@ DocumentManager = { }, observe: function(subject, topic, data) { - // For some types of documents (about:blank), we only see the first - // notification, for others (data: URIs) we only observe the second. - if (topic == "content-document-global-created" || topic == "document-element-inserted") { + if (topic == "document-element-inserted") { let document = subject; let window = document && document.defaultView; - - if (topic == "content-document-global-created") { - window = subject; - document = window && window.document; - } - if (!document || !document.location || !window) { return; } - // Make sure we always load exactly once (notice != used as logical XOR), - // usually on document-element-inserted, except for about:blank documents. - if ((topic == "content-document-global-created") != (window.location.href == "about:blank")) { - return; - } - // Make sure we only load into frames that ExtensionContent.init // was called on (i.e., not frames for social or sidebars). let mm = getWindowMessageManager(window); @@ -503,8 +482,7 @@ DocumentManager = { } } - this.trigger(window); - + this.trigger("document_start", window); /* eslint-disable mozilla/balanced-listeners */ window.addEventListener("DOMContentLoaded", this, true); window.addEventListener("load", this, true); @@ -548,9 +526,9 @@ DocumentManager = { // Need to check if we're still on the right page? Greasemonkey does this. if (event.type == "DOMContentLoaded") { - this.trigger(window); + this.trigger("document_end", window); } else if (event.type == "load") { - this.trigger(window); + this.trigger("document_idle", window); } }, @@ -688,7 +666,7 @@ DocumentManager = { } }, - trigger(window) { + trigger(when, window) { let state = this.getWindowState(window); if (state == "document_start") { diff --git a/toolkit/components/extensions/test/mochitest/file_with_about_blank.html b/toolkit/components/extensions/test/mochitest/file_with_about_blank.html deleted file mode 100644 index af51c2e52a11..000000000000 --- a/toolkit/components/extensions/test/mochitest/file_with_about_blank.html +++ /dev/null @@ -1,10 +0,0 @@ - - - - - - - - - - diff --git a/toolkit/components/extensions/test/mochitest/mochitest.ini b/toolkit/components/extensions/test/mochitest/mochitest.ini index 338661545e7b..c8e7eb7a6184 100644 --- a/toolkit/components/extensions/test/mochitest/mochitest.ini +++ b/toolkit/components/extensions/test/mochitest/mochitest.ini @@ -18,7 +18,6 @@ support-files = file_WebNavigation_page1.html file_WebNavigation_page2.html file_WebNavigation_page3.html - file_with_about_blank.html file_image_good.png file_image_bad.png file_image_redirect.png @@ -51,8 +50,6 @@ skip-if = os == 'android' # Android does not currently support windows. [test_ext_contentscript_devtools_metadata.html] [test_ext_contentscript_exporthelpers.html] [test_ext_contentscript_css.html] -[test_ext_contentscript_about_blank.html] -skip-if = (os == 'android') # bug 1312357 [test_ext_contentscript_teardown.html] skip-if = (os == 'android') # Android does not support tabs API. Bug 1260250 [test_ext_exclude_include_globs.html] diff --git a/toolkit/components/extensions/test/mochitest/test_ext_contentscript_about_blank.html b/toolkit/components/extensions/test/mochitest/test_ext_contentscript_about_blank.html deleted file mode 100644 index 3766678e718d..000000000000 --- a/toolkit/components/extensions/test/mochitest/test_ext_contentscript_about_blank.html +++ /dev/null @@ -1,117 +0,0 @@ - - - - Test content script match_about_blank option - - - - - - - - - - - From f8747ad476260da2372cd55bf1904e02e8b8807f Mon Sep 17 00:00:00 2001 From: Kit Cambridge Date: Tue, 25 Oct 2016 11:39:56 -0700 Subject: [PATCH 37/60] Bug 1312857 - Pass the correct change sources in `getOrCreateTagFolder` and `importJSONNode`. r=markh MozReview-Commit-ID: Gga9kiC3AxK --HG-- extra : rebase_source : 0b07551617c277aeaec619d0a4432874fc77e9ec --- .../sync/tests/unit/test_bookmark_engine.js | 102 ++++++++++++------ .../components/places/BookmarkJSONUtils.jsm | 6 +- toolkit/components/places/PlacesSyncUtils.jsm | 1 + 3 files changed, 72 insertions(+), 37 deletions(-) diff --git a/services/sync/tests/unit/test_bookmark_engine.js b/services/sync/tests/unit/test_bookmark_engine.js index a472f6b593d5..9de6c5c0dc09 100644 --- a/services/sync/tests/unit/test_bookmark_engine.js +++ b/services/sync/tests/unit/test_bookmark_engine.js @@ -17,6 +17,12 @@ initTestLogging("Trace"); Service.engineManager.register(BookmarksEngine); +function* assertChildGuids(folderGuid, expectedChildGuids, message) { + let tree = yield PlacesUtils.promiseBookmarksTree(folderGuid); + let childGuids = tree.children.map(child => child.guid); + deepEqual(childGuids, expectedChildGuids, message); +} + add_task(function* test_change_during_sync() { _("Ensure that we track changes made during a sync."); @@ -50,32 +56,41 @@ add_task(function* test_change_during_sync() { // Sync is synchronous, so, to simulate a bookmark change made during a // sync, we create a server record that adds a bookmark as a side effect. - let bmk2_guid = "get-firefox1"; - let bmk3_id = -1; + let bmk2_guid = "get-firefox1"; // New child of Folder 1, created remotely. + let bmk3_id = -1; // New child of Folder 1, created locally during sync. + let folder2_guid = "folder2-1111"; // New folder, created remotely. + let tagQuery_guid = "tag-query111"; // New tag query child of Folder 2, created remotely. + let bmk4_guid = "example-org1"; // New tagged child of Folder 2, created remotely. { // An existing record changed on the server that should not trigger // another sync when applied. - let changedRecord = new Bookmark("bookmarks", bz_guid); - changedRecord.bmkUri = "https://bugzilla.mozilla.org/"; - changedRecord.description = "New description"; - changedRecord.title = "Bugzilla"; - changedRecord.tags = ["new", "tags"]; - changedRecord.parentName = "Bookmarks Toolbar"; - changedRecord.parentid = PlacesUtils.bookmarks.toolbarGuid; - collection.insert(bz_guid, encryptPayload(changedRecord.cleartext)); + let bzBmk = new Bookmark("bookmarks", bz_guid); + bzBmk.bmkUri = "https://bugzilla.mozilla.org/"; + bzBmk.description = "New description"; + bzBmk.title = "Bugzilla"; + bzBmk.tags = ["new", "tags"]; + bzBmk.parentName = "Bookmarks Toolbar"; + bzBmk.parentid = "toolbar"; + collection.insert(bz_guid, encryptPayload(bzBmk.cleartext)); - let localRecord = new Bookmark("bookmarks", bmk2_guid); - localRecord.bmkUri = "http://getfirefox.com/"; - localRecord.description = "Firefox is awesome."; - localRecord.title = "Get Firefox!"; - localRecord.tags = ["firefox", "awesome", "browser"]; - localRecord.keyword = "awesome"; - localRecord.loadInSidebar = false; - localRecord.parentName = "Folder 1"; - localRecord.parentid = folder1_guid; + let remoteFolder = new BookmarkFolder("bookmarks", folder2_guid); + remoteFolder.title = "Folder 2"; + remoteFolder.children = [bmk4_guid, tagQuery_guid]; + remoteFolder.parentName = "Bookmarks Menu"; + remoteFolder.parentid = "menu"; + collection.insert(folder2_guid, encryptPayload(remoteFolder.cleartext)); - let remoteRecord = collection.insert(bmk2_guid, encryptPayload(localRecord.cleartext)); - remoteRecord.get = function get() { + let localFxBmk = new Bookmark("bookmarks", bmk2_guid); + localFxBmk.bmkUri = "http://getfirefox.com/"; + localFxBmk.description = "Firefox is awesome."; + localFxBmk.title = "Get Firefox!"; + localFxBmk.tags = ["firefox", "awesome", "browser"]; + localFxBmk.keyword = "awesome"; + localFxBmk.loadInSidebar = false; + localFxBmk.parentName = "Folder 1"; + localFxBmk.parentid = folder1_guid; + let remoteFxBmk = collection.insert(bmk2_guid, encryptPayload(localFxBmk.cleartext)); + remoteFxBmk.get = function get() { _("Inserting bookmark into local store"); bmk3_id = PlacesUtils.bookmarks.insertBookmark( folder1_id, Utils.makeURI("https://mozilla.org/"), @@ -83,13 +98,28 @@ add_task(function* test_change_during_sync() { return ServerWBO.prototype.get.apply(this, arguments); }; + + // A tag query referencing a nonexistent tag folder, which we should + // create locally when applying the record. + let localTagQuery = new BookmarkQuery("bookmarks", tagQuery_guid); + localTagQuery.bmkUri = "place:type=7&folder=999"; + localTagQuery.title = "Taggy tags"; + localTagQuery.folderName = "taggy"; + localTagQuery.parentName = "Folder 2"; + localTagQuery.parentid = folder2_guid; + collection.insert(tagQuery_guid, encryptPayload(localTagQuery.cleartext)); + + // A bookmark that should appear in the results for the tag query. + let localTaggedBmk = new Bookmark("bookmarks", bmk4_guid); + localTaggedBmk.bmkUri = "https://example.org"; + localTaggedBmk.title = "Tagged bookmark"; + localTaggedBmk.tags = ["taggy"]; + localTaggedBmk.parentName = "Folder 2"; + localTaggedBmk.parentid = folder2_guid; + collection.insert(bmk4_guid, encryptPayload(localTaggedBmk.cleartext)); } - { - let tree = yield PlacesUtils.promiseBookmarksTree(folder1_guid); - let childGuids = tree.children.map(child => child.guid); - deepEqual(childGuids, [bmk1_guid], "Folder should have 1 child before first sync"); - } + yield* assertChildGuids(folder1_guid, [bmk1_guid], "Folder should have 1 child before first sync"); _("Perform first sync"); { @@ -110,10 +140,14 @@ add_task(function* test_change_during_sync() { ok(!collection.wbo(bmk3_guid), "Bookmark created during first sync shouldn't be uploaded yet"); - let tree = yield PlacesUtils.promiseBookmarksTree(folder1_guid); - let childGuids = tree.children.map(child => child.guid); - deepEqual(childGuids, [bmk1_guid, bmk3_guid, bmk2_guid], - "Folder should have 3 children after first sync"); + yield* assertChildGuids(folder1_guid, [bmk1_guid, bmk3_guid, bmk2_guid], + "Folder 1 should have 3 children after first sync"); + yield* assertChildGuids(folder2_guid, [bmk4_guid, tagQuery_guid], + "Folder 2 should have 2 children after first sync"); + let taggedURIs = PlacesUtils.tagging.getURIsForTag("taggy"); + equal(taggedURIs.length, 1, "Should have 1 tagged URI"); + equal(taggedURIs[0].spec, "https://example.org/", + "Synced tagged bookmark should appear in tagged URI list"); } _("Perform second sync"); @@ -126,10 +160,10 @@ add_task(function* test_change_during_sync() { ok(collection.wbo(bmk3_guid), "Bookmark created during first sync should be uploaded during second sync"); - let tree = yield PlacesUtils.promiseBookmarksTree(folder1_guid); - let childGuids = tree.children.map(child => child.guid); - deepEqual(childGuids, [bmk1_guid, bmk3_guid, bmk2_guid], - "Folder should have same children after second sync"); + yield* assertChildGuids(folder1_guid, [bmk1_guid, bmk3_guid, bmk2_guid], + "Folder 1 should have same children after second sync"); + yield* assertChildGuids(folder2_guid, [bmk4_guid, tagQuery_guid], + "Folder 2 should have same children after second sync"); } } finally { store.wipe(); diff --git a/toolkit/components/places/BookmarkJSONUtils.jsm b/toolkit/components/places/BookmarkJSONUtils.jsm index 4d0e9ff1bd1d..7f8d3fd8f524 100644 --- a/toolkit/components/places/BookmarkJSONUtils.jsm +++ b/toolkit/components/places/BookmarkJSONUtils.jsm @@ -397,14 +397,14 @@ BookmarkImporter.prototype = { if (aContainer == PlacesUtils.tagsFolderId) { // Node is a tag if (aData.children) { - aData.children.forEach(function(aChild) { + for (let child of aData.children) { try { PlacesUtils.tagging.tagURI( - NetUtil.newURI(aChild.uri), [aData.title], this._source); + NetUtil.newURI(child.uri), [aData.title], this._source); } catch (ex) { // Invalid tag child, skip it } - }); + } return [folderIdMap, searchIds]; } } else if (aData.annos && diff --git a/toolkit/components/places/PlacesSyncUtils.jsm b/toolkit/components/places/PlacesSyncUtils.jsm index b80e3526cd2f..0a9e2a7c7a8e 100644 --- a/toolkit/components/places/PlacesSyncUtils.jsm +++ b/toolkit/components/places/PlacesSyncUtils.jsm @@ -933,6 +933,7 @@ var getOrCreateTagFolder = Task.async(function* (tag) { type: PlacesUtils.bookmarks.TYPE_FOLDER, parentGuid: PlacesUtils.bookmarks.tagsGuid, title: tag, + source: SOURCE_SYNC, }); return PlacesUtils.promiseItemId(item.guid); }); From 14a2b3bc99b6400052b18ef4130731d2a98b3e4b Mon Sep 17 00:00:00 2001 From: Eitan Isaacson Date: Fri, 14 Oct 2016 16:49:57 -0700 Subject: [PATCH 38/60] Bug 1308030 - Add telemetry probes to narrate. r=bsmedberg,Gijs, data-review=bsmedberg Added 2 probes: 1. Breakup by language of initilizations and available voice support for that language. 2. Speak time of narrate. MozReview-Commit-ID: AGD8nON2m7N --HG-- extra : rebase_source : 2bbd483bf48b92e290e726cea4f16c6ff5155b58 --- .../components/narrate/NarrateControls.jsm | 32 +++++++++++++++++-- toolkit/components/telemetry/Histograms.json | 20 ++++++++++++ 2 files changed, 50 insertions(+), 2 deletions(-) diff --git a/toolkit/components/narrate/NarrateControls.jsm b/toolkit/components/narrate/NarrateControls.jsm index cba360846c18..6bc6ab7f9a39 100644 --- a/toolkit/components/narrate/NarrateControls.jsm +++ b/toolkit/components/narrate/NarrateControls.jsm @@ -10,6 +10,7 @@ Cu.import("resource://gre/modules/narrate/VoiceSelect.jsm"); Cu.import("resource://gre/modules/narrate/Narrator.jsm"); Cu.import("resource://gre/modules/Services.jsm"); Cu.import("resource://gre/modules/AsyncPrefs.jsm"); +Cu.import("resource://gre/modules/TelemetryStopwatch.jsm"); this.EXPORTED_SYMBOLS = ["NarrateControls"]; @@ -19,6 +20,8 @@ function NarrateControls(mm, win) { this._mm = mm; this._winRef = Cu.getWeakReference(win); + win.addEventListener("unload", this); + // Append content style sheet in document head let style = win.document.createElement("link"); style.rel = "stylesheet"; @@ -148,6 +151,11 @@ NarrateControls.prototype = { case "voiceschanged": this._setupVoices(); break; + case "unload": + if (this.narrator.speaking) { + TelemetryStopwatch.finish("NARRATE_CONTENT_SPEAKTIME_MS", this); + } + break; } }, @@ -158,7 +166,6 @@ NarrateControls.prototype = { return this.narrator.languagePromise.then(language => { this.voiceSelect.clear(); let win = this._win; - let doc = win.document; let voicePrefs = this._getVoicePref(); let selectedVoice = voicePrefs[language || "default"]; let comparer = win.Intl ? @@ -183,8 +190,23 @@ NarrateControls.prototype = { this.voiceSelect.addOptions(options); } + let narrateToggle = win.document.getElementById("narrate-toggle"); + let histogram = + Services.telemetry.getKeyedHistogramById("NARRATE_CONTENT_BY_LANGUAGE"); + let initial = !!this._voicesInitialized; + this._voicesInitialized = true; + + if (initial) { + histogram.add(language, 0); + } + + if (options.length && narrateToggle.hidden) { + // About to show for the first time.. + histogram.add(language, 1); + } + // We disable this entire feature if there are no available voices. - doc.getElementById("narrate-toggle").hidden = !options.length; + narrateToggle.hidden = !options.length; }); }, @@ -250,6 +272,12 @@ NarrateControls.prototype = { this._doc.getElementById("narrate-skip-previous").disabled = !speaking; this._doc.getElementById("narrate-skip-next").disabled = !speaking; + + if (speaking) { + TelemetryStopwatch.start("NARRATE_CONTENT_SPEAKTIME_MS", this); + } else { + TelemetryStopwatch.finish("NARRATE_CONTENT_SPEAKTIME_MS", this); + } }, _createVoiceLabel: function(voice) { diff --git a/toolkit/components/telemetry/Histograms.json b/toolkit/components/telemetry/Histograms.json index 2fe261045c57..1712dcd2dcba 100644 --- a/toolkit/components/telemetry/Histograms.json +++ b/toolkit/components/telemetry/Histograms.json @@ -10347,5 +10347,25 @@ "high": 100, "n_buckets": 10, "description": "Percentage of time taken by phases in expensive content paints." + }, + "NARRATE_CONTENT_BY_LANGUAGE": { + "alert_emails": ["eisaacson@mozilla.com"], + "bug_numbers": [1308030], + "releaseChannelCollection": "opt-out", + "expires_in_version": "56", + "kind": "enumerated", + "keyed": true, + "n_values": 4, + "description": "Number of Narrate initialization attempts and successes broken up by content's language (ISO 639-1 code) (0 = initialization attempt, 1 = successfully initialized)" + }, + "NARRATE_CONTENT_SPEAKTIME_MS": { + "alert_emails": ["eisaacson@mozilla.com"], + "bug_numbers": [1308030], + "releaseChannelCollection": "opt-out", + "expires_in_version": "56", + "kind": "linear", + "high": 300000, + "n_buckets": 30, + "description": "Time in MS that content is narrated in 10 second increments up to 5 minutes" } } From b158ffd8b60887407a22e19e602d87611478beb1 Mon Sep 17 00:00:00 2001 From: "J. Ryan Stinnett" Date: Tue, 25 Oct 2016 12:54:26 -0500 Subject: [PATCH 39/60] Bug 1311605 - Support save page for RDM content. r=ochameau MozReview-Commit-ID: J8d9J2GRkf5 --HG-- extra : rebase_source : 4948d1dc518a85239cd86fbcd73cd1e4d55b76ca --- .../client/responsive.html/browser/tunnel.js | 82 ++++++++++--------- 1 file changed, 42 insertions(+), 40 deletions(-) diff --git a/devtools/client/responsive.html/browser/tunnel.js b/devtools/client/responsive.html/browser/tunnel.js index 34b893479ced..034b62ae8b18 100644 --- a/devtools/client/responsive.html/browser/tunnel.js +++ b/devtools/client/responsive.html/browser/tunnel.js @@ -9,6 +9,10 @@ const Services = require("Services"); const { Task } = require("devtools/shared/task"); const DevToolsUtils = require("devtools/shared/DevToolsUtils"); const { BrowserElementWebNavigation } = require("./web-navigation"); +const { getStack } = require("devtools/shared/platform/stack"); + +// A symbol used to hold onto the frame loader from the outer browser while tunneling. +const FRAME_LOADER = Symbol("devtools/responsive/frame-loader"); function debug(msg) { // console.log(msg); @@ -77,6 +81,34 @@ function tunnelToInnerBrowser(outer, inner) { throw new Error("The inner browser must be remote."); } + // Various browser methods access the `frameLoader` property, including: + // * `saveBrowser` from contentAreaUtils.js + // * `docShellIsActive` from remote-browser.xml + // * `hasContentOpener` from remote-browser.xml + // * `preserveLayers` from remote-browser.xml + // * `receiveMessage` from SessionStore.jsm + // In general, these methods are interested in the `frameLoader` for the content, + // so we redirect them to the inner browser's `frameLoader`. + outer[FRAME_LOADER] = outer.frameLoader; + Object.defineProperty(outer, "frameLoader", { + get() { + let stack = getStack(); + // One exception is `receiveMessage` from SessionStore.jsm. SessionStore + // expects data updates to come in as messages targeted to a . + // In addition, it verifies[1] correctness by checking that the received + // message's `targetFrameLoader` property matches the `frameLoader` of the + // . To keep SessionStore functioning as expected, we give it the + // outer `frameLoader` as if nothing has changed. + // [1]: https://dxr.mozilla.org/mozilla-central/rev/b1b18f25c0ea69d9ee57c4198d577dfcd0129ce1/browser/components/sessionstore/SessionStore.jsm#716 + if (stack.caller.filename.endsWith("SessionStore.jsm")) { + return outer[FRAME_LOADER]; + } + return inner.frameLoader; + }, + configurable: true, + enumerable: true, + }); + // The `permanentKey` property on a is used to index into various maps // held by the session store. When you swap content around with // `_swapBrowserDocShells`, these keys are also swapped so they follow the content. @@ -152,35 +184,6 @@ function tunnelToInnerBrowser(outer, inner) { outer[property] = inner[property]; } - // Wants to access the content's `frameLoader`, so we'll redirect it to - // inner browser. - Object.defineProperty(outer, "hasContentOpener", { - get() { - return inner.frameLoader.tabParent.hasContentOpener; - }, - configurable: true, - enumerable: true, - }); - - // Wants to access the content's `frameLoader`, so we'll redirect it to - // inner browser. - Object.defineProperty(outer, "docShellIsActive", { - get() { - return inner.frameLoader.tabParent.docShellIsActive; - }, - set(value) { - inner.frameLoader.tabParent.docShellIsActive = value; - }, - configurable: true, - enumerable: true, - }); - - // Wants to access the content's `frameLoader`, so we'll redirect it to - // inner browser. - outer.preserveLayers = value => { - inner.frameLoader.tabParent.preserveLayers(value); - }; - // Expose `PopupNotifications` on the content's owner global. // This is used by PermissionUI.jsm for permission doorhangers. // Note: This pollutes the responsive.html tool UI's global. @@ -253,13 +256,6 @@ function tunnelToInnerBrowser(outer, inner) { outer.destroy(); outer.style.MozBinding = ""; - // Reset overridden XBL properties and methods. Deleting the override - // means it will fallback to the original XBL binding definitions which - // are on the prototype. - delete outer.hasContentOpener; - delete outer.docShellIsActive; - delete outer.preserveLayers; - // Reset @remote since this is now back to a regular, non-remote browser outer.setAttribute("remote", "false"); @@ -273,6 +269,12 @@ function tunnelToInnerBrowser(outer, inner) { mmTunnel.destroy(); mmTunnel = null; + // Reset overridden XBL properties and methods. Deleting the override + // means it will fallback to the original XBL binding definitions which + // are on the prototype. + delete outer.frameLoader; + delete outer[FRAME_LOADER]; + // Invalidate outer's permanentKey so that SessionStore stops associating // things that happen to the outer browser with the content inside in the // inner browser. @@ -296,7 +298,7 @@ function copyPermanentKey(outer, inner) { // no direct mechanism to do so. As a workaround, we wait until the one errant message // has gone by, and then we copy the permanentKey after that, since the permanentKey is // what SessionStore uses to identify each browser. - let outerMM = outer.frameLoader.messageManager; + let outerMM = outer[FRAME_LOADER].messageManager; let onHistoryEntry = message => { let history = message.data.data.history; if (!history || !history.entries) { @@ -427,17 +429,17 @@ MessageManagerTunnel.prototype = { ], get outerParentMM() { - if (!this.outer.frameLoader) { + if (!this.outer[FRAME_LOADER]) { return null; } - return this.outer.frameLoader.messageManager; + return this.outer[FRAME_LOADER].messageManager; }, get outerChildMM() { // This is only possible because we require the outer browser to be // non-remote, so we're able to reach into its window and use the child // side message manager there. - let docShell = this.outer.frameLoader.docShell; + let docShell = this.outer[FRAME_LOADER].docShell; return docShell.QueryInterface(Ci.nsIInterfaceRequestor) .getInterface(Ci.nsIContentFrameMessageManager); }, From bbf6fceee06b3a2bb1a8e8c312bfab5cbff3fb08 Mon Sep 17 00:00:00 2001 From: Brian Stack Date: Tue, 25 Oct 2016 11:47:50 -0700 Subject: [PATCH 40/60] Bug 1304180 - Set taskcluster artifact expiration to 28 days on try r=dustin MozReview-Commit-ID: ECXCs9EkOYI --HG-- extra : rebase_source : e1c52eaa1c3324b44851f9d3c88d69d0174b0f21 --- taskcluster/taskgraph/transforms/task.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/taskcluster/taskgraph/transforms/task.py b/taskcluster/taskgraph/transforms/task.py index 76b62fae7a41..2fb542a8bcad 100644 --- a/taskcluster/taskgraph/transforms/task.py +++ b/taskcluster/taskgraph/transforms/task.py @@ -518,7 +518,7 @@ def build_task(config, tasks): ]) if 'expires-after' not in task: - task['expires-after'] = '14 days' if config.params['project'] == 'try' else '1 year' + task['expires-after'] = '28 days' if config.params['project'] == 'try' else '1 year' if 'deadline-after' not in task: task['deadline-after'] = '1 day' From 84abd2cc9a1875211354bacf5d2e2392869a03cd Mon Sep 17 00:00:00 2001 From: Alexandre Poirot Date: Tue, 25 Oct 2016 03:18:28 -0700 Subject: [PATCH 41/60] Bug 1311789: Fix the missing "Themes" legend in devtools options panel. r=jryans MozReview-Commit-ID: 6ZpXntxvk3w --HG-- extra : rebase_source : d129842a1dc81cce318e8e4e9e78ad5455bca8e4 --- devtools/client/framework/toolbox-options.js | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/devtools/client/framework/toolbox-options.js b/devtools/client/framework/toolbox-options.js index 92d7218d7af6..c480825f1cb0 100644 --- a/devtools/client/framework/toolbox-options.js +++ b/devtools/client/framework/toolbox-options.js @@ -256,7 +256,10 @@ OptionsPanel.prototype = { setupThemeList: function () { let themeBox = this.panelDoc.getElementById("devtools-theme-box"); - themeBox.innerHTML = ""; + let themeLabels = themeBox.querySelectorAll("label"); + for (let label of themeLabels) { + label.remove(); + } let createThemeOption = theme => { let inputLabel = this.panelDoc.createElement("label"); From f1049dae1049dac89b250a302d737f662235b40a Mon Sep 17 00:00:00 2001 From: Jean-Yves Avenard Date: Wed, 26 Oct 2016 20:09:41 +1100 Subject: [PATCH 42/60] Bug 1312958: P1. Do not modify original Audio/Video info. r=gerald The issue is particularly problematic with the Apple audio decoder. The Apple decoder relies on the sampling rate to configure the CoreAudio transform. The actual output rate may be different (such as with HE-AAC). Should the decoder ever need to be reset again, future initialization would have failed as the initial rate was now incorrect. MozReview-Commit-ID: 7kTiaUYuOgf --HG-- extra : rebase_source : 00119a13205c610542a2f690ce6c3b9caeb1b69c --- dom/media/MediaFormatReader.cpp | 10 ++++++++-- dom/media/MediaFormatReader.h | 2 ++ 2 files changed, 10 insertions(+), 2 deletions(-) diff --git a/dom/media/MediaFormatReader.cpp b/dom/media/MediaFormatReader.cpp index d48983992473..f3ffdd90f180 100644 --- a/dom/media/MediaFormatReader.cpp +++ b/dom/media/MediaFormatReader.cpp @@ -288,6 +288,7 @@ MediaFormatReader::OnDemuxerInitDone(nsresult) for (const MetadataTag& tag : videoInfo->mTags) { tags->Put(tag.mKey, tag.mValue); } + mVideo.mOriginalInfo = Move(videoInfo); mVideo.mCallback = new DecoderCallback(this, TrackInfo::kVideoTrack); mVideo.mTimeRanges = mVideo.mTrackDemuxer->GetBuffered(); mTrackDemuxersMayBlock |= mVideo.mTrackDemuxer->GetSamplesMayBlock(); @@ -316,6 +317,7 @@ MediaFormatReader::OnDemuxerInitDone(nsresult) for (const MetadataTag& tag : audioInfo->mTags) { tags->Put(tag.mKey, tag.mValue); } + mAudio.mOriginalInfo = Move(audioInfo); mAudio.mCallback = new DecoderCallback(this, TrackInfo::kAudioTrack); mAudio.mTimeRanges = mAudio.mTrackDemuxer->GetBuffered(); mTrackDemuxersMayBlock |= mAudio.mTrackDemuxer->GetSamplesMayBlock(); @@ -403,7 +405,9 @@ MediaFormatReader::EnsureDecoderCreated(TrackType aTrack) switch (aTrack) { case TrackType::kAudioTrack: { decoder.mDecoder = mPlatform->CreateDecoder({ - decoder.mInfo ? *decoder.mInfo->GetAsAudioInfo() : mInfo.mAudio, + decoder.mInfo + ? *decoder.mInfo->GetAsAudioInfo() + : *decoder.mOriginalInfo->GetAsAudioInfo(), decoder.mTaskQueue, decoder.mCallback.get(), mCrashHelper, @@ -417,7 +421,9 @@ MediaFormatReader::EnsureDecoderCreated(TrackType aTrack) // Decoders use the layers backend to decide if they can use hardware decoding, // so specify LAYERS_NONE if we want to forcibly disable it. decoder.mDecoder = mPlatform->CreateDecoder({ - mVideo.mInfo ? *mVideo.mInfo->GetAsVideoInfo() : mInfo.mVideo, + decoder.mInfo + ? *decoder.mInfo->GetAsVideoInfo() + : *decoder.mOriginalInfo->GetAsVideoInfo(), decoder.mTaskQueue, decoder.mCallback.get(), mKnowsCompositor, diff --git a/dom/media/MediaFormatReader.h b/dom/media/MediaFormatReader.h index e42b8bc11528..32fc826969f2 100644 --- a/dom/media/MediaFormatReader.h +++ b/dom/media/MediaFormatReader.h @@ -425,6 +425,8 @@ private: Maybe mNextStreamSourceID; media::TimeIntervals mTimeRanges; Maybe mLastTimeRangesEnd; + // TrackInfo as first discovered during ReadMetadata. + UniquePtr mOriginalInfo; RefPtr mInfo; Maybe mFirstDemuxedSampleTime; // Use BlankDecoderModule or not. From 94530fa5a6528987d71676e42e4fb4e52da545a6 Mon Sep 17 00:00:00 2001 From: Jean-Yves Avenard Date: Wed, 26 Oct 2016 20:13:44 +1100 Subject: [PATCH 43/60] Bug 1312958: P2. Only delete the trackinfo object once the decoder has been shutdown. r=gerald While it's unlikely to have been a problem as the decoder would have been idled at this stage. During the time the TrackInfo was reset and the decoder actually be shut down, the reference to the object would have been invalid causing a potential UAF. MozReview-Commit-ID: 7pGJtYRy2Yr --HG-- extra : rebase_source : d32b8ff393f55685ef182b00f286aea1d1d75464 --- dom/media/MediaFormatReader.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dom/media/MediaFormatReader.cpp b/dom/media/MediaFormatReader.cpp index f3ffdd90f180..0df8c978d3a7 100644 --- a/dom/media/MediaFormatReader.cpp +++ b/dom/media/MediaFormatReader.cpp @@ -977,13 +977,13 @@ MediaFormatReader::HandleDemuxedSamples(TrackType aTrack, LOG("%s stream id has changed from:%d to:%d, recreating decoder.", TrackTypeToStr(aTrack), decoder.mLastStreamSourceID, info->GetID()); - decoder.mInfo = info; decoder.mLastStreamSourceID = info->GetID(); decoder.mNextStreamSourceID.reset(); // Reset will clear our array of queued samples. So make a copy now. nsTArray> samples{decoder.mQueuedSamples}; Reset(aTrack); decoder.ShutdownDecoder(); + decoder.mInfo = info; if (sample->mKeyframe) { decoder.mQueuedSamples.AppendElements(Move(samples)); ScheduleUpdate(aTrack); From f0515f7a99e632166ad103b7a50e89471539faf0 Mon Sep 17 00:00:00 2001 From: Jean-Yves Avenard Date: Wed, 26 Oct 2016 08:48:47 +1100 Subject: [PATCH 44/60] Bug 1311876: P1. Flush audio decoder when error occurs. r=gerald MozReview-Commit-ID: JaFfXj3xMat --HG-- extra : rebase_source : b0929ead47ec912731a867b17ce17d59934f85c2 --- dom/media/MediaFormatReader.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/dom/media/MediaFormatReader.cpp b/dom/media/MediaFormatReader.cpp index 0df8c978d3a7..f153b9bc8e70 100644 --- a/dom/media/MediaFormatReader.cpp +++ b/dom/media/MediaFormatReader.cpp @@ -1261,6 +1261,8 @@ MediaFormatReader::Update(TrackType aTrack) NS_SUCCEEDED(decoder.mTrackDemuxer->GetNextRandomAccessPoint(&nextKeyframe))) { SkipVideoDemuxToNextKeyFrame(decoder.mLastSampleTime.refOr(TimeInterval()).Length()); return; + } else if (aTrack == TrackType::kAudioTrack) { + decoder.Flush(); } } From 83df18207fb136df5242e77ed36bdf8aa1b3dfd9 Mon Sep 17 00:00:00 2001 From: Jean-Yves Avenard Date: Wed, 26 Oct 2016 09:06:14 +1100 Subject: [PATCH 45/60] Bug 1311876: P2. Recreate audio decoder when an error occurs. r=gerald MozReview-Commit-ID: CwQMZwSNndO --HG-- extra : rebase_source : d76bd3c15f4d4fc54fcb6f4659ad3d501433f8be --- dom/media/platforms/apple/AppleATDecoder.cpp | 44 ++++++++++++++------ dom/media/platforms/apple/AppleATDecoder.h | 2 + 2 files changed, 33 insertions(+), 13 deletions(-) diff --git a/dom/media/platforms/apple/AppleATDecoder.cpp b/dom/media/platforms/apple/AppleATDecoder.cpp index 56244d830b22..a8ee183dd8f2 100644 --- a/dom/media/platforms/apple/AppleATDecoder.cpp +++ b/dom/media/platforms/apple/AppleATDecoder.cpp @@ -29,6 +29,7 @@ AppleATDecoder::AppleATDecoder(const AudioInfo& aConfig, , mStream(nullptr) , mIsFlushing(false) , mParsedFramesForAACMagicCookie(0) + , mErrored(false) { MOZ_COUNT_CTOR(AppleATDecoder); LOG("Creating Apple AudioToolbox decoder"); @@ -89,9 +90,17 @@ AppleATDecoder::ProcessFlush() { MOZ_ASSERT(mTaskQueue->IsCurrentThreadIn()); mQueuedSamples.Clear(); - OSStatus rv = AudioConverterReset(mConverter); - if (rv) { - LOG("Error %d resetting AudioConverter", rv); + if (mConverter) { + OSStatus rv = AudioConverterReset(mConverter); + if (rv) { + LOG("Error %d resetting AudioConverter", rv); + } + } + if (mErrored) { + mParsedFramesForAACMagicCookie = 0; + mMagicCookie.Clear(); + ProcessShutdown(); + mErrored = false; } } @@ -121,24 +130,33 @@ void AppleATDecoder::Shutdown() { MOZ_ASSERT(mCallback->OnReaderTaskQueue()); + nsCOMPtr runnable = + NewRunnableMethod(this, &AppleATDecoder::ProcessShutdown); + SyncRunnable::DispatchToThread(mTaskQueue, runnable); +} - LOG("Shutdown: Apple AudioToolbox AAC decoder"); - mQueuedSamples.Clear(); - OSStatus rv = AudioConverterDispose(mConverter); - if (rv) { - LOG("error %d disposing of AudioConverter", rv); - return; - } - mConverter = nullptr; +void +AppleATDecoder::ProcessShutdown() +{ + MOZ_ASSERT(mTaskQueue->IsCurrentThreadIn()); if (mStream) { - rv = AudioFileStreamClose(mStream); + OSStatus rv = AudioFileStreamClose(mStream); if (rv) { LOG("error %d disposing of AudioFileStream", rv); return; } mStream = nullptr; } + + if (mConverter) { + LOG("Shutdown: Apple AudioToolbox AAC decoder"); + OSStatus rv = AudioConverterDispose(mConverter); + if (rv) { + LOG("error %d disposing of AudioConverter", rv); + } + mConverter = nullptr; + } } struct PassthroughUserData { @@ -207,7 +225,7 @@ AppleATDecoder::SubmitSample(MediaRawData* aSample) for (size_t i = 0; i < mQueuedSamples.Length(); i++) { rv = DecodeSample(mQueuedSamples[i]); if (NS_FAILED(rv)) { - mQueuedSamples.Clear(); + mErrored = true; mCallback->Error(MediaResult( rv, RESULT_DETAIL("Unable to decode sample %lld", aSample->mTime))); return; diff --git a/dom/media/platforms/apple/AppleATDecoder.h b/dom/media/platforms/apple/AppleATDecoder.h index 4835e1331fc6..34b6ececcc23 100644 --- a/dom/media/platforms/apple/AppleATDecoder.h +++ b/dom/media/platforms/apple/AppleATDecoder.h @@ -59,6 +59,7 @@ private: Atomic mIsFlushing; void ProcessFlush(); + void ProcessShutdown(); void SubmitSample(MediaRawData* aSample); nsresult DecodeSample(MediaRawData* aSample); nsresult GetInputAudioDescription(AudioStreamBasicDescription& aDesc, @@ -69,6 +70,7 @@ private: nsresult GetImplicitAACMagicCookie(const MediaRawData* aSample); nsresult SetupChannelLayout(); uint32_t mParsedFramesForAACMagicCookie; + bool mErrored; }; } // namespace mozilla From a4f3312d228dbf3618c3f1cd6d271704caf199d4 Mon Sep 17 00:00:00 2001 From: Jean-Yves Avenard Date: Wed, 26 Oct 2016 11:34:46 +1100 Subject: [PATCH 46/60] Bug 1311876: P3. Provide more details when audio decoder errors. r=gerald MozReview-Commit-ID: Dbh2Cvyq1NH --HG-- extra : rebase_source : 6fa83589965db1f63c80c18bb6c94b896c1b894b --- dom/media/platforms/apple/AppleATDecoder.cpp | 39 ++++++++++++-------- dom/media/platforms/apple/AppleATDecoder.h | 8 ++-- 2 files changed, 28 insertions(+), 19 deletions(-) diff --git a/dom/media/platforms/apple/AppleATDecoder.cpp b/dom/media/platforms/apple/AppleATDecoder.cpp index a8ee183dd8f2..65794d82c80e 100644 --- a/dom/media/platforms/apple/AppleATDecoder.cpp +++ b/dom/media/platforms/apple/AppleATDecoder.cpp @@ -209,12 +209,11 @@ AppleATDecoder::SubmitSample(MediaRawData* aSample) return; } - nsresult rv = NS_OK; + MediaResult rv = NS_OK; if (!mConverter) { rv = SetupDecoder(aSample); if (rv != NS_OK && rv != NS_ERROR_NOT_INITIALIZED) { - mCallback->Error( - MediaResult(rv, RESULT_DETAIL("Unable to create decoder"))); + mCallback->Error(rv); return; } } @@ -226,8 +225,7 @@ AppleATDecoder::SubmitSample(MediaRawData* aSample) rv = DecodeSample(mQueuedSamples[i]); if (NS_FAILED(rv)) { mErrored = true; - mCallback->Error(MediaResult( - rv, RESULT_DETAIL("Unable to decode sample %lld", aSample->mTime))); + mCallback->Error(rv); return; } } @@ -236,7 +234,7 @@ AppleATDecoder::SubmitSample(MediaRawData* aSample) mCallback->InputExhausted(); } -nsresult +MediaResult AppleATDecoder::DecodeSample(MediaRawData* aSample) { MOZ_ASSERT(mTaskQueue->IsCurrentThreadIn()); @@ -283,8 +281,10 @@ AppleATDecoder::DecodeSample(MediaRawData* aSample) packets.get()); if (rv && rv != kNoMoreDataErr) { - LOG("Error decoding audio stream: %d\n", rv); - return NS_ERROR_DOM_MEDIA_DECODE_ERR; + LOG("Error decoding audio sample: %d\n", rv); + return MediaResult(NS_ERROR_DOM_MEDIA_DECODE_ERR, + RESULT_DETAIL("Error decoding audio sample: %d @ %lld", + rv, aSample->mTime)); } if (numFrames) { @@ -305,7 +305,11 @@ AppleATDecoder::DecodeSample(MediaRawData* aSample) media::TimeUnit duration = FramesToTimeUnit(numFrames, rate); if (!duration.IsValid()) { NS_WARNING("Invalid count of accumulated audio samples"); - return NS_ERROR_DOM_MEDIA_OVERFLOW_ERR; + return MediaResult( + NS_ERROR_DOM_MEDIA_OVERFLOW_ERR, + RESULT_DETAIL( + "Invalid count of accumulated audio samples: num:%llu rate:%d", + uint64_t(numFrames), rate)); } #ifdef LOG_SAMPLE_DECODE @@ -322,7 +326,8 @@ AppleATDecoder::DecodeSample(MediaRawData* aSample) AudioConfig in(*mChannelLayout.get(), rate); AudioConfig out(channels, rate); if (!in.IsValid() || !out.IsValid()) { - return NS_ERROR_DOM_MEDIA_DECODE_ERR; + return MediaResult(NS_ERROR_DOM_MEDIA_DECODE_ERR, + RESULT_DETAIL("Invalid audio config")); } mAudioConverter = MakeUnique(in, out); } @@ -342,7 +347,7 @@ AppleATDecoder::DecodeSample(MediaRawData* aSample) return NS_OK; } -nsresult +MediaResult AppleATDecoder::GetInputAudioDescription(AudioStreamBasicDescription& aDesc, const nsTArray& aExtraData) { @@ -373,7 +378,9 @@ AppleATDecoder::GetInputAudioDescription(AudioStreamBasicDescription& aDesc, &inputFormatSize, &aDesc); if (NS_WARN_IF(rv)) { - return NS_ERROR_FAILURE; + return MediaResult( + NS_ERROR_FAILURE, + RESULT_DETAIL("Unable to get format info:%lld", int64_t(rv))); } // If any of the methods below fail, we will return the default format as @@ -549,7 +556,7 @@ AppleATDecoder::SetupChannelLayout() return NS_OK; } -nsresult +MediaResult AppleATDecoder::SetupDecoder(MediaRawData* aSample) { MOZ_ASSERT(mTaskQueue->IsCurrentThreadIn()); @@ -574,7 +581,7 @@ AppleATDecoder::SetupDecoder(MediaRawData* aSample) AudioStreamBasicDescription inputFormat; PodZero(&inputFormat); - nsresult rv = + MediaResult rv = GetInputAudioDescription(inputFormat, mMagicCookie.Length() ? mMagicCookie : *mConfig.mExtraData); @@ -606,7 +613,9 @@ AppleATDecoder::SetupDecoder(MediaRawData* aSample) if (status) { LOG("Error %d constructing AudioConverter", status); mConverter = nullptr; - return NS_ERROR_FAILURE; + return MediaResult( + NS_ERROR_FAILURE, + RESULT_DETAIL("Error constructing AudioConverter:%lld", int64_t(status))); } if (NS_FAILED(SetupChannelLayout())) { diff --git a/dom/media/platforms/apple/AppleATDecoder.h b/dom/media/platforms/apple/AppleATDecoder.h index 34b6ececcc23..be232e07be0b 100644 --- a/dom/media/platforms/apple/AppleATDecoder.h +++ b/dom/media/platforms/apple/AppleATDecoder.h @@ -61,12 +61,12 @@ private: void ProcessFlush(); void ProcessShutdown(); void SubmitSample(MediaRawData* aSample); - nsresult DecodeSample(MediaRawData* aSample); - nsresult GetInputAudioDescription(AudioStreamBasicDescription& aDesc, - const nsTArray& aExtraData); + MediaResult DecodeSample(MediaRawData* aSample); + MediaResult GetInputAudioDescription(AudioStreamBasicDescription& aDesc, + const nsTArray& aExtraData); // Setup AudioConverter once all information required has been gathered. // Will return NS_ERROR_NOT_INITIALIZED if more data is required. - nsresult SetupDecoder(MediaRawData* aSample); + MediaResult SetupDecoder(MediaRawData* aSample); nsresult GetImplicitAACMagicCookie(const MediaRawData* aSample); nsresult SetupChannelLayout(); uint32_t mParsedFramesForAACMagicCookie; From ab630e99bee23ed8c9ca1f923cccc35b7017e933 Mon Sep 17 00:00:00 2001 From: Marco Bonardo Date: Wed, 28 Sep 2016 13:52:44 +0200 Subject: [PATCH 47/60] Bug 1251569 - It's not possible to hide the Blocked Popup menu by clicking its anchor button in urlbar. r=Dolske MozReview-Commit-ID: 7L6JwLNJt5x --HG-- extra : rebase_source : 97d9188694ecfeeb08fcea26797018cf5f38ccad --- browser/base/content/browser.js | 9 +++++++-- browser/base/content/browser.xul | 2 +- 2 files changed, 8 insertions(+), 3 deletions(-) diff --git a/browser/base/content/browser.js b/browser/base/content/browser.js index 98ab71687802..1e2aa26286b8 100755 --- a/browser/base/content/browser.js +++ b/browser/base/content/browser.js @@ -398,9 +398,11 @@ function findChildShell(aDocument, aDocShell, aSoughtURI) { var gPopupBlockerObserver = { _reportButton: null, - onReportButtonClick: function (aEvent) + onReportButtonMousedown: function (aEvent) { - if (aEvent.button != 0 || aEvent.target != this._reportButton) + // If this method is called on the same event tick as the popup gets + // hidden, do nothing to avoid re-opening the popup. + if (aEvent.button != 0 || aEvent.target != this._reportButton || this.isPopupHidingTick) return; document.getElementById("blockedPopupOptions") @@ -598,6 +600,9 @@ var gPopupBlockerObserver = { if (aEvent.target.anchorNode.id == "page-report-button") aEvent.target.anchorNode.removeAttribute("open"); + this.isPopupHidingTick = true; + setTimeout(() => this.isPopupHidingTick = false, 0); + let item = aEvent.target.lastChild; while (item && item.getAttribute("observes") != "blockedPopupsSeparator") { let next = item.previousSibling; diff --git a/browser/base/content/browser.xul b/browser/base/content/browser.xul index f7bcab8600e2..5c39f44599e7 100644 --- a/browser/base/content/browser.xul +++ b/browser/base/content/browser.xul @@ -766,7 +766,7 @@ class="urlbar-icon" hidden="true" tooltiptext="&pageReportIcon.tooltip;" - onclick="gPopupBlockerObserver.onReportButtonClick(event);"/> + onmousedown="gPopupBlockerObserver.onReportButtonMousedown(event);"/> Date: Wed, 19 Oct 2016 15:59:09 -0500 Subject: [PATCH 48/60] Bug 1311178 - Remove various duplicate DevTools files. r=ntim MozReview-Commit-ID: ABtuFPC85OQ --HG-- rename : devtools/client/themes/images/security-state-local.svg => devtools/client/themes/images/globe.svg rename : devtools/client/themes/images/itemArrow-dark-ltr.svg => devtools/client/themes/images/item-arrow-dark-ltr.svg rename : devtools/client/themes/images/itemArrow-ltr.svg => devtools/client/themes/images/item-arrow-ltr.svg rename : devtools/client/themes/images/itemArrow-rtl.svg => devtools/client/themes/images/item-arrow-rtl.svg rename : devtools/client/themes/images/debugger-blackbox.svg => devtools/client/themes/images/item-toggle.svg extra : rebase_source : fe6f4a532d83a25ddf4083506c945f2b57015b27 --- .../aboutdebugging/components/tabs/panel.js | 2 +- devtools/client/dom/dom.html | 1 - devtools/client/dom/moz.build | 2 -- devtools/client/inspector/moz.build | 1 - devtools/client/jar.mn | 21 ++++-------- devtools/client/jsonview/css/controls.png | Bin 1630 -> 0 bytes devtools/client/jsonview/css/controls@2x.png | Bin 2045 -> 0 bytes devtools/client/jsonview/css/moz.build | 4 --- .../client/jsonview/css/read-only-prop.svg | 32 ------------------ devtools/client/memory/moz.build | 1 - .../projecteditor/lib/helpers/moz.build | 1 - .../promisedebugger/promise-debugger.xhtml | 1 - devtools/client/shared/moz.build | 2 -- devtools/client/themes/debugger.css | 6 ++-- .../themes/images/command-scratchpad.svg | 7 ---- .../themes/images/debugger-prettyprint.svg | 6 ---- .../client/themes/images/filetypes/store.svg | 7 ---- .../{security-state-local.svg => globe.svg} | 0 ...w-dark-ltr.svg => item-arrow-dark-ltr.svg} | 0 ...w-dark-rtl.svg => item-arrow-dark-rtl.svg} | 14 ++++---- .../{itemArrow-ltr.svg => item-arrow-ltr.svg} | 0 .../{itemArrow-rtl.svg => item-arrow-rtl.svg} | 0 ...{debugger-blackbox.svg => item-toggle.svg} | 0 devtools/client/themes/images/itemToggle.svg | 7 ---- devtools/client/themes/images/tabs-icon.svg | 8 ----- devtools/client/themes/netmonitor.css | 2 +- devtools/client/themes/promisedebugger.css | 3 -- devtools/client/themes/shadereditor.css | 2 +- devtools/client/themes/splitview.css | 8 ++--- devtools/client/themes/storage.css | 2 +- devtools/client/themes/styleeditor.css | 2 +- devtools/client/themes/toolbox.css | 2 +- devtools/client/themes/widgets.css | 12 +++---- 33 files changed, 32 insertions(+), 124 deletions(-) delete mode 100644 devtools/client/jsonview/css/controls.png delete mode 100644 devtools/client/jsonview/css/controls@2x.png delete mode 100644 devtools/client/jsonview/css/read-only-prop.svg delete mode 100644 devtools/client/themes/images/command-scratchpad.svg delete mode 100644 devtools/client/themes/images/debugger-prettyprint.svg delete mode 100644 devtools/client/themes/images/filetypes/store.svg rename devtools/client/themes/images/{security-state-local.svg => globe.svg} (100%) rename devtools/client/themes/images/{itemArrow-dark-ltr.svg => item-arrow-dark-ltr.svg} (100%) rename devtools/client/themes/images/{itemArrow-dark-rtl.svg => item-arrow-dark-rtl.svg} (98%) rename devtools/client/themes/images/{itemArrow-ltr.svg => item-arrow-ltr.svg} (100%) rename devtools/client/themes/images/{itemArrow-rtl.svg => item-arrow-rtl.svg} (100%) rename devtools/client/themes/images/{debugger-blackbox.svg => item-toggle.svg} (100%) delete mode 100644 devtools/client/themes/images/itemToggle.svg delete mode 100644 devtools/client/themes/images/tabs-icon.svg delete mode 100644 devtools/client/themes/promisedebugger.css diff --git a/devtools/client/aboutdebugging/components/tabs/panel.js b/devtools/client/aboutdebugging/components/tabs/panel.js index dac51c4f3a4d..f12116dd0525 100644 --- a/devtools/client/aboutdebugging/components/tabs/panel.js +++ b/devtools/client/aboutdebugging/components/tabs/panel.js @@ -55,7 +55,7 @@ module.exports = createClass({ } tab.icon = prePath + "/favicon.ico"; } else { - tab.icon = "chrome://devtools/skin/images/tabs-icon.svg"; + tab.icon = "chrome://devtools/skin/images/globe.svg"; } }); this.setState({ tabs }); diff --git a/devtools/client/dom/dom.html b/devtools/client/dom/dom.html index 62172590d2a9..5fe473d0982b 100644 --- a/devtools/client/dom/dom.html +++ b/devtools/client/dom/dom.html @@ -10,7 +10,6 @@ - diff --git a/devtools/client/dom/moz.build b/devtools/client/dom/moz.build index f585527159b0..1e04a09dc2e7 100644 --- a/devtools/client/dom/moz.build +++ b/devtools/client/dom/moz.build @@ -11,6 +11,4 @@ DIRS += [ DevToolsModules( 'dom-panel.js', - 'dom.html', - 'main.js', ) diff --git a/devtools/client/inspector/moz.build b/devtools/client/inspector/moz.build index 04a5d4b3cbeb..bdf3e3887f6b 100644 --- a/devtools/client/inspector/moz.build +++ b/devtools/client/inspector/moz.build @@ -16,7 +16,6 @@ DevToolsModules( 'breadcrumbs.js', 'inspector-commands.js', 'inspector-search.js', - 'inspector.xhtml', 'panel.js', 'toolsidebar.js', ) diff --git a/devtools/client/jar.mn b/devtools/client/jar.mn index 6790aacbab96..9ee1f80939e6 100644 --- a/devtools/client/jar.mn +++ b/devtools/client/jar.mn @@ -25,7 +25,6 @@ devtools.jar: content/styleeditor/styleeditor.xul (styleeditor/styleeditor.xul) content/storage/storage.xul (storage/storage.xul) content/inspector/inspector.js (inspector/inspector.js) - content/inspector/fonts/fonts.js (inspector/fonts/fonts.js) content/inspector/markup/markup.xhtml (inspector/markup/markup.xhtml) content/animationinspector/animation-controller.js (animationinspector/animation-controller.js) content/animationinspector/animation-panel.js (animationinspector/animation-panel.js) @@ -110,7 +109,6 @@ devtools.jar: content/commandline/commandlinetooltip.xhtml (commandline/commandlinetooltip.xhtml) content/framework/toolbox-window.xul (framework/toolbox-window.xul) content/framework/toolbox-options.xhtml (framework/toolbox-options.xhtml) - content/framework/toolbox-options.js (framework/toolbox-options.js) content/framework/toolbox.xul (framework/toolbox.xul) content/framework/toolbox-init.js (framework/toolbox-init.js) content/framework/options-panel.css (framework/options-panel.css) @@ -134,7 +132,6 @@ devtools.jar: content/responsive.html/index.xhtml (responsive.html/index.xhtml) content/responsive.html/index.js (responsive.html/index.js) content/dom/dom.html (dom/dom.html) - content/dom/content/dom-view.css (dom/content/dom-view.css) content/dom/main.js (dom/main.js) % skin devtools classic/1.0 %skin/ skin/devtools-browser.css (themes/devtools-browser.css) @@ -161,7 +158,6 @@ devtools.jar: skin/images/filetypes/dir-close.svg (themes/images/filetypes/dir-close.svg) skin/images/filetypes/dir-open.svg (themes/images/filetypes/dir-open.svg) skin/images/filetypes/globe.svg (themes/images/filetypes/globe.svg) - skin/images/filetypes/store.svg (themes/images/filetypes/store.svg) skin/images/commandline-icon.svg (themes/images/commandline-icon.svg) skin/images/alerticon-warning.png (themes/images/alerticon-warning.png) skin/images/alerticon-warning@2x.png (themes/images/alerticon-warning@2x.png) @@ -170,7 +166,6 @@ devtools.jar: skin/images/command-paintflashing.svg (themes/images/command-paintflashing.svg) skin/images/command-screenshot.svg (themes/images/command-screenshot.svg) skin/images/command-responsivemode.svg (themes/images/command-responsivemode.svg) - skin/images/command-scratchpad.svg (themes/images/command-scratchpad.svg) skin/images/command-pick.svg (themes/images/command-pick.svg) skin/images/command-frames.svg (themes/images/command-frames.svg) skin/images/command-console.svg (themes/images/command-console.svg) @@ -193,7 +188,6 @@ devtools.jar: skin/dom.css (themes/dom.css) skin/performance.css (themes/performance.css) skin/memory.css (themes/memory.css) - skin/promisedebugger.css (themes/promisedebugger.css) skin/scratchpad.css (themes/scratchpad.css) skin/shadereditor.css (themes/shadereditor.css) skin/storage.css (themes/storage.css) @@ -205,11 +199,11 @@ devtools.jar: skin/jit-optimizations.css (themes/jit-optimizations.css) skin/images/filter.svg (themes/images/filter.svg) skin/images/search.svg (themes/images/search.svg) - skin/images/itemToggle.svg (themes/images/itemToggle.svg) - skin/images/itemArrow-dark-rtl.svg (themes/images/itemArrow-dark-rtl.svg) - skin/images/itemArrow-dark-ltr.svg (themes/images/itemArrow-dark-ltr.svg) - skin/images/itemArrow-rtl.svg (themes/images/itemArrow-rtl.svg) - skin/images/itemArrow-ltr.svg (themes/images/itemArrow-ltr.svg) + skin/images/item-toggle.svg (themes/images/item-toggle.svg) + skin/images/item-arrow-dark-rtl.svg (themes/images/item-arrow-dark-rtl.svg) + skin/images/item-arrow-dark-ltr.svg (themes/images/item-arrow-dark-ltr.svg) + skin/images/item-arrow-rtl.svg (themes/images/item-arrow-rtl.svg) + skin/images/item-arrow-ltr.svg (themes/images/item-arrow-ltr.svg) skin/images/noise.png (themes/images/noise.png) skin/images/dropmarker.svg (themes/images/dropmarker.svg) skin/boxmodel.css (themes/boxmodel.css) @@ -221,8 +215,6 @@ devtools.jar: skin/images/debugger-step-in.svg (themes/images/debugger-step-in.svg) skin/images/debugger-step-out.svg (themes/images/debugger-step-out.svg) skin/images/debugger-step-over.svg (themes/images/debugger-step-over.svg) - skin/images/debugger-blackbox.svg (themes/images/debugger-blackbox.svg) - skin/images/debugger-prettyprint.svg (themes/images/debugger-prettyprint.svg) skin/images/debugger-toggleBreakpoints.svg (themes/images/debugger-toggleBreakpoints.svg) skin/images/tracer-icon.png (themes/images/tracer-icon.png) skin/images/tracer-icon@2x.png (themes/images/tracer-icon@2x.png) @@ -266,7 +258,7 @@ devtools.jar: skin/images/debugging-devices.svg (themes/images/debugging-devices.svg) skin/images/debugging-tabs.svg (themes/images/debugging-tabs.svg) skin/images/debugging-workers.svg (themes/images/debugging-workers.svg) - skin/images/tabs-icon.svg (themes/images/tabs-icon.svg) + skin/images/globe.svg (themes/images/globe.svg) skin/images/tool-options.svg (themes/images/tool-options.svg) skin/images/tool-webconsole.svg (themes/images/tool-webconsole.svg) skin/images/tool-canvas.svg (themes/images/tool-canvas.svg) @@ -317,7 +309,6 @@ devtools.jar: skin/images/reload.svg (themes/images/reload.svg) skin/images/security-state-broken.svg (themes/images/security-state-broken.svg) skin/images/security-state-insecure.svg (themes/images/security-state-insecure.svg) - skin/images/security-state-local.svg (themes/images/security-state-local.svg) skin/images/security-state-secure.svg (themes/images/security-state-secure.svg) skin/images/security-state-weak.svg (themes/images/security-state-weak.svg) skin/images/diff.svg (themes/images/diff.svg) diff --git a/devtools/client/jsonview/css/controls.png b/devtools/client/jsonview/css/controls.png deleted file mode 100644 index 569c266e4e4c79a60c4b023728b1ee3e648fe551..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1630 zcmbVMeNYr-7+(%NkOUbpzr&sN3zfayJ@!8Kh67FxyhHi$xJDXBYwzwo*kEtZ+l9L$ zKaMPcY5W2;w1Nam!9hf`$+U5t2+)x+CNif{N|2hADWISz()N(E{&4)Go!Ncg=Y5~w z^ZcH#t<1?<7ZJWN9D<+-qd{*HSGD*q4wH&s^5XU+aakawCD=sHs6(u7SBt;PMupB26FapQq6iN^pQl%l3@brU- z-dr}j#-vZ5_9aSMq(Bgy8Vqy0-7#NFPOl;G@h!> zo4rnenE=lfyR2e8>`Mb+F?Y{)Z6<>?9#q z+DX)c6H1g+Dk+p!6AF~DSS(7MCKPt1Enw$qcwDVlQ+l511-_uytGqIXf7oY{sW#+h|Ko{f`a015{a85Wi6^_fKt&GDj zukzREamae$VoHE5-Nmu+RFXB!QwRXkM&l}#4OPk&6iUi1c9g;aj*=>?B0*`ls(}h1 z(|FteO&%ta!u*}`pUw#!iS6j$KA8hicrr=AA&!qroD=VFz7YtLlo|Cpv*%mO z@0l8tqEr&%cG5BL@Q*j@hENn$y!QLg#XHCDAD;h0VrOK#B4ub+d%bz=`=;Cz*E2FQ zN_Reb*c~484q;9280g#&Vxptxo@{EmQ-3!9y6=))3B)Ux$6jd}CtzwS>?{2Ft#rsm<-H*YG>ojEgkye#yDq%Ah8Tr%<^oE6f)E9G`b zd))ZOQwNX zaBxKR3b`j}FCi^5RyP~xNQ+o@c4tS2ti(kw=84qV9yY;e#wB7D@q_{@xHsd^z`(Nu>FIEMUBV1<3Ii4{TWeoD|;~Uem^rzRp^7=mrRaRmE diff --git a/devtools/client/jsonview/css/controls@2x.png b/devtools/client/jsonview/css/controls@2x.png deleted file mode 100644 index fb062516db8e49e90b5081f63bd7881ebfc5df65..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2045 zcmbVNdsGu=7Ej6}$g5}piB>y=qGHKoLLMZNN|G@OC4vyzv@2*PnLH%Pgk*q#h#F%d zwt}k#3RVO~k%w@wP@zaUt*mTaSa4CRa-^a{vC5Hp5T$Z#CkpQV;prbc=gfTfe&6r@ z?)~oLj3Z&=dLPdvo&*BHCuRebh_5F6jr4HGzoGYYWATNIt&?L(s2a;sm=S_dg~A9B zV^C<2L`0#=PX7^!A`o0GI++}kOXK)T)Id`>F*K{eNkt$;t+kpI$}|K6U__%c3Mdad zx+s87C7^u7mNKL!F{0IN$T1^HIU8lloHQj*MOphk5M|}#1O^0C09J$EXyIE0loz~w zTy}2LDZmQ|mL{OQ3`#Cd0K}*n0oXJ)Rmot20GCGt*(@Fih679n7(oXabS94qf_xU2 z4|0IHhk|=EtJM5NNHXUO*8~(ThMD+udRA5zEh~bCnl*Hg$K%l%OgfWE#Sv6Xwh>cU zsYXl4JOhMSlxCd?)1gMd$*6$Q3`{`5BYk-VgGnlVMQpUpB??a&-KsFrK^lW@FgWk^ z0&T$(k^hGATC_!$Z9?dYhy~3sEAe`$L*|X~-2Js9ClHT@A8*#-MN#M>RGDEwj93gL zpx`Gol}^P+)GUz6QM0Hp1LROy91f4Fhy>YG5Qbq6LjkhY9MwF}>+BhkP$UnEWbs50 z8wA%y@IY3i7-B#yp->2}<3-Hd#uzP_!l*>%ed}=FbG8wGY0DRz5e0^tWhknj?}7v^ zilG)QY68S!V3ky%)ES+6n6pMNuM8n(T_&QEm{9}pBFTK+YXX2lE|05(nN$vg$)&Pj zCY!2Ib3iJ{fg{vB1dfCe4rR_>_5UW1jt50|cFO;B&ioeMj!yB_9N@~UNkWYH_?YoI zSqym(5eTk83?!6UZ#+0G(E1Dgdo)E}j`eV~)IaInZ3?|V9J~Pzh5zoqZ?Eem$^I=w zukS_Rky;t#7DCzgPQiYW$EmFg0|pnwRN0;;YoTKYgC334{<5A&}`p{7O&9e06 zvtP%ZDQj>4x%coBwdTlXT2I5hG~IJ$%;SCXCC{Q}J`KGzd^wI&GR;g5Xg*sScySqG zZ2CF5u%q)k=GmW$q3vP!?cSy;VhFb`!~Rv+sIln-^Y$Gv-)J zT^uK1KQ!&s^{qMUdn5Kp{oY2hd(o4LpvNePU8^Qv^PcdRjOCuc)hg21pI<4vD_UB$ z!$z9%NU`UU-#~pZa$V)4547AblF3_rT1eX#v^6dN_0zFUGixy4@(NLiwqAU+Mc0+Flptk#>yvWL3xb&f@qGb>;np zjX}*+T72_S_3E>0TO{WORnj{Zw+jZkGE3hZO}iOT)!$Xy)t_(G1`JiX2i3>Lm(=wGUB?H`!>g02Z=Q2GZ42~hobnpo?$$vPTw#6t zU^ge)$F)eD8$Xl!eU5I~W%J4l|0*_S?!WzPNe$`H^2VtHlUd)nSG<{2wJ*DJs5nr6 zZPbRf3XkSR?JCSa9d`w)==cvRnhC%hw#9EX^G@vqclc~%PpCG;Ek9s@(n7 z`!(k={B8x7tR+s{N4X{YEmh=i8{NAlF2umXhpo-CI>PavqLYG|DZwR+y5$Asr+4T1 zm3_`$__*O8h^~9v$;zImQ6D?}%BtDvAuUnxvf1pBl<9~1+Amn5t8op764p!P^~r}F zJ_oPfD>vWW%>*7P$2Mtviw^VzWYoB%My#y<%_F;Evm;klaA#p~$(l}wXL>lLn>V=h z<2B&h@Csr<`shhR_>E`zCq&-8QiRwWYucj-E{sk$gufI6TbmCYbVWBLy2``5+eUtr z_xunYp7YVF&;=E}1d0c|X!63lSIMs6<&xA`&?@xH$Y1OVPUY!ih1NVj>F!@h&DDKV zEypIIf+G2Iw||E1x#jSi`HWWF&^>tlUiC;o`l(ony`B;kw$K=RsjSo - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/devtools/client/memory/moz.build b/devtools/client/memory/moz.build index 64a27ac20cb7..dccb579387b3 100644 --- a/devtools/client/memory/moz.build +++ b/devtools/client/memory/moz.build @@ -16,7 +16,6 @@ DevToolsModules( 'app.js', 'constants.js', 'dominator-tree-lazy-children.js', - 'initializer.js', 'models.js', 'panel.js', 'reducers.js', diff --git a/devtools/client/projecteditor/lib/helpers/moz.build b/devtools/client/projecteditor/lib/helpers/moz.build index e9cfb020c2de..c2e14fce65d2 100644 --- a/devtools/client/projecteditor/lib/helpers/moz.build +++ b/devtools/client/projecteditor/lib/helpers/moz.build @@ -9,5 +9,4 @@ DevToolsModules( 'file-picker.js', 'l10n.js', 'prompts.js', - 'readdir.js', ) diff --git a/devtools/client/promisedebugger/promise-debugger.xhtml b/devtools/client/promisedebugger/promise-debugger.xhtml index cca446f531e3..4394c877553f 100644 --- a/devtools/client/promisedebugger/promise-debugger.xhtml +++ b/devtools/client/promisedebugger/promise-debugger.xhtml @@ -12,7 +12,6 @@ &title; - - + + + + diff --git a/dom/animation/test/mozilla/test_transition_finish_on_compositor.html b/dom/animation/test/mozilla/test_transition_finish_on_compositor.html new file mode 100644 index 000000000000..357e5297e97e --- /dev/null +++ b/dom/animation/test/mozilla/test_transition_finish_on_compositor.html @@ -0,0 +1,14 @@ + + + + +
+ From 4999550c29de9493630bdb8ef75d54cc0ac249be Mon Sep 17 00:00:00 2001 From: Hiroyuki Ikezoe Date: Wed, 26 Oct 2016 17:19:38 +0900 Subject: [PATCH 52/60] Bug 1311196 - Part 3: Adjust fill mode to fill forwards for all animations on the compositor. r=birtles MozReview-Commit-ID: DsIrWoxci0X --HG-- extra : rebase_source : 559edb1756cf13b2677cabcc18321825c9fd8e4c --- gfx/layers/Layers.cpp | 22 ++++++++++++++++++---- layout/base/nsDisplayList.cpp | 2 +- 2 files changed, 19 insertions(+), 5 deletions(-) diff --git a/gfx/layers/Layers.cpp b/gfx/layers/Layers.cpp index ab6a88abc9d0..b0759a891b47 100644 --- a/gfx/layers/Layers.cpp +++ b/gfx/layers/Layers.cpp @@ -431,11 +431,25 @@ Layer::SetAnimations(const AnimationArray& aAnimations) mAnimations = aAnimations; mAnimationData.Clear(); for (uint32_t i = 0; i < mAnimations.Length(); i++) { + Animation& animation = mAnimations[i]; + // Adjust fill mode to fill forwards so that if the main thread is delayed + // in clearing this animation we don't introduce flicker by jumping back to + // the old underlying value + switch (static_cast(animation.fillMode())) { + case dom::FillMode::None: + animation.fillMode() = static_cast(dom::FillMode::Forwards); + break; + case dom::FillMode::Backwards: + animation.fillMode() = static_cast(dom::FillMode::Both); + break; + default: + break; + } + AnimData* data = mAnimationData.AppendElement(); InfallibleTArray>& functions = data->mFunctions; - const InfallibleTArray& segments = - mAnimations.ElementAt(i).segments(); + const InfallibleTArray& segments = animation.segments(); for (uint32_t j = 0; j < segments.Length(); j++) { TimingFunction tf = segments.ElementAt(j).sampleFn(); @@ -448,8 +462,8 @@ Layer::SetAnimations(const AnimationArray& aAnimations) // animation. InfallibleTArray& startValues = data->mStartValues; InfallibleTArray& endValues = data->mEndValues; - for (uint32_t j = 0; j < mAnimations[i].segments().Length(); j++) { - const AnimationSegment& segment = mAnimations[i].segments()[j]; + for (uint32_t j = 0; j < segments.Length(); j++) { + const AnimationSegment& segment = segments[j]; StyleAnimationValue* startValue = startValues.AppendElement(); StyleAnimationValue* endValue = endValues.AppendElement(); if (segment.endState().type() == Animatable::TArrayOfTransformFunction) { diff --git a/layout/base/nsDisplayList.cpp b/layout/base/nsDisplayList.cpp index 3d6b222ca187..f3462b76d23a 100644 --- a/layout/base/nsDisplayList.cpp +++ b/layout/base/nsDisplayList.cpp @@ -431,7 +431,7 @@ AddAnimationForProperty(nsIFrame* aFrame, const AnimationProperty& aProperty, animation->iterations() = computedTiming.mIterations; animation->iterationStart() = computedTiming.mIterationStart; animation->direction() = static_cast(timing.mDirection); - animation->fillMode() = static_cast(timing.mFill); + animation->fillMode() = static_cast(computedTiming.mFill); animation->property() = aProperty.mProperty; animation->playbackRate() = aAnimation->PlaybackRate(); animation->data() = aData; From 6b585714178baffdb72a6d588a4c065d1685aa70 Mon Sep 17 00:00:00 2001 From: Markus Stange Date: Wed, 26 Oct 2016 17:56:59 -0400 Subject: [PATCH 53/60] Bug 1310814 - Use public NSLocale API for getting the system country code. r=spohl This potentially changes behavior. On my machine, the old code returned NS_ERROR_FAILURE because the dictionary did not have a "countryCode" entry, but this new implementation correctly returns the string "CA". MozReview-Commit-ID: 17Vme0fcAIw --HG-- extra : rebase_source : 9ffc388ae98b11cb37c37957a8721e92284208c3 extra : source : e1a14b0c638571ec7f7aaec56f11d4b77dfb4dd5 --- xpcom/base/MacHelpers.mm | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/xpcom/base/MacHelpers.mm b/xpcom/base/MacHelpers.mm index 58e1ad490812..9ec468dd46b2 100644 --- a/xpcom/base/MacHelpers.mm +++ b/xpcom/base/MacHelpers.mm @@ -14,12 +14,15 @@ namespace mozilla { nsresult GetSelectedCityInfo(nsAString& aCountryCode) { - NSDictionary* selected_city = - [[NSUserDefaults standardUserDefaults] - objectForKey:@"com.apple.preferences.timezone.selected_city"]; - NSString *countryCode = (NSString *) - [selected_city objectForKey:@"CountryCode"]; - const char *countryCodeUTF8 = [countryCode UTF8String]; + // Can be replaced with [[NSLocale currentLocale] countryCode] once we build + // with the 10.12 SDK. + id countryCode = [[NSLocale currentLocale] objectForKey:NSLocaleCountryCode]; + + if (![countryCode isKindOfClass:[NSString class]]) { + return NS_ERROR_FAILURE; + } + + const char* countryCodeUTF8 = [(NSString*)countryCode UTF8String]; if (!countryCodeUTF8) { return NS_ERROR_FAILURE; From f92c8259d3b3da815ac719e4430b4b17abaa40bd Mon Sep 17 00:00:00 2001 From: Markus Stange Date: Tue, 18 Oct 2016 11:23:38 -0400 Subject: [PATCH 54/60] Bug 1310814 - Add ObjC exception guards. r=spohl With the added safety checks it's unlikely that anything in this function will fire ObjC exceptions, but our rule is to have guards around every Objective C function that can directly be called from C++ files. MozReview-Commit-ID: GQ0bN5638Sf --HG-- extra : rebase_source : 3919f4a2b8160f197e1690ba13b58319239848e1 extra : source : 3d233eddd929e0cb2cadf0b07f75d60aa3fba419 --- xpcom/base/MacHelpers.mm | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/xpcom/base/MacHelpers.mm b/xpcom/base/MacHelpers.mm index 9ec468dd46b2..19d0d8900700 100644 --- a/xpcom/base/MacHelpers.mm +++ b/xpcom/base/MacHelpers.mm @@ -6,6 +6,7 @@ #include "nsString.h" #include "MacHelpers.h" +#include "nsObjCExceptions.h" #import @@ -14,6 +15,8 @@ namespace mozilla { nsresult GetSelectedCityInfo(nsAString& aCountryCode) { + NS_OBJC_BEGIN_TRY_ABORT_BLOCK_NSRESULT; + // Can be replaced with [[NSLocale currentLocale] countryCode] once we build // with the 10.12 SDK. id countryCode = [[NSLocale currentLocale] objectForKey:NSLocaleCountryCode]; @@ -30,6 +33,8 @@ GetSelectedCityInfo(nsAString& aCountryCode) AppendUTF8toUTF16(countryCodeUTF8, aCountryCode); return NS_OK; + + NS_OBJC_END_TRY_ABORT_BLOCK_NSRESULT; } } // namespace Mozilla From 21f6342dd50bb0068bfa6b97ef36a4785bdd1d53 Mon Sep 17 00:00:00 2001 From: Alexandre Poirot Date: Thu, 25 Aug 2016 05:51:11 -0700 Subject: [PATCH 55/60] Bug 1266134 - Pull host management out of toolbox.xul. r=jryans MozReview-Commit-ID: 71GNAFuVFgl --HG-- extra : rebase_source : 44e7a3e98a7a4888c9673e531be05498e9133dc7 --- .../browser_dbg_breakpoints-other-tabs.js | 1 - .../test/mochitest/browser_dbg_host-layout.js | 4 +- .../mochitest/browser_dbg_worker-window.js | 13 +- .../client/debugger/test/mochitest/head.js | 3 + devtools/client/framework/devtools.js | 48 ++-- devtools/client/framework/moz.build | 1 + .../framework/test/browser_devtools_api.js | 4 +- .../test/browser_toolbox_custom_host.js | 3 + .../framework/test/browser_toolbox_raise.js | 8 +- .../framework/test/browser_toolbox_toggle.js | 2 +- .../browser_toolbox_window_title_changes.js | 29 ++- ...owser_toolbox_window_title_frame_select.js | 9 + devtools/client/framework/test/shared-head.js | 14 + .../client/framework/toolbox-host-manager.js | 244 ++++++++++++++++++ devtools/client/framework/toolbox.js | 229 ++++++++-------- ...rowser_inspector_breadcrumbs_visibility.js | 2 +- .../test/browser_inspector_portrait_mode.js | 4 +- .../test/browser_styleeditor_sv_resize.js | 2 +- .../browser_webconsole_closure_inspection.js | 2 +- 19 files changed, 446 insertions(+), 176 deletions(-) create mode 100644 devtools/client/framework/toolbox-host-manager.js diff --git a/devtools/client/debugger/test/mochitest/browser_dbg_breakpoints-other-tabs.js b/devtools/client/debugger/test/mochitest/browser_dbg_breakpoints-other-tabs.js index 11cde294f2f5..2763eee95dff 100644 --- a/devtools/client/debugger/test/mochitest/browser_dbg_breakpoints-other-tabs.js +++ b/devtools/client/debugger/test/mochitest/browser_dbg_breakpoints-other-tabs.js @@ -37,6 +37,5 @@ var test = Task.async(function* () { is(packet.frame.where.line, 3, "Should have stopped at line 3 (debugger statement), not line 2 (other tab's breakpoint)"); - yield teardown(panel1); yield resumeDebuggerThenCloseAndFinish(panel2); }); diff --git a/devtools/client/debugger/test/mochitest/browser_dbg_host-layout.js b/devtools/client/debugger/test/mochitest/browser_dbg_host-layout.js index eae6a1f7acec..dc86d8649370 100644 --- a/devtools/client/debugger/test/mochitest/browser_dbg_host-layout.js +++ b/devtools/client/debugger/test/mochitest/browser_dbg_host-layout.js @@ -84,7 +84,7 @@ function getHost(host) { function resizeToolboxWindow(panel, host) { let sizeOption = host.split(":")[1]; - let win = panel._toolbox._host._window; + let win = panel._toolbox.win.parent; // should be the same value as BREAKPOINT_SMALL_WINDOW_WIDTH in debugger-view.js let breakpoint = 850; @@ -101,7 +101,7 @@ function resizeToolboxWindow(panel, host) { function resizeAndWaitForLayoutChange(panel, width) { info("Updating toolbox window width to " + width); - let win = panel._toolbox._host._window; + let win = panel._toolbox.win.parent; let gDebugger = panel.panelWin; win.resizeTo(width, window.screen.availHeight); diff --git a/devtools/client/debugger/test/mochitest/browser_dbg_worker-window.js b/devtools/client/debugger/test/mochitest/browser_dbg_worker-window.js index 7cc7cfb5af7e..46198d31cd7f 100644 --- a/devtools/client/debugger/test/mochitest/browser_dbg_worker-window.js +++ b/devtools/client/debugger/test/mochitest/browser_dbg_worker-window.js @@ -34,8 +34,17 @@ add_task(function* () { "jsdebugger", Toolbox.HostType.WINDOW); - is(toolbox._host.type, "window", "correct host"); - ok(toolbox._host._window.document.title.includes(WORKER_URL), + is(toolbox.hostType, "window", "correct host"); + + yield new Promise(done => { + toolbox.win.parent.addEventListener("message", function onmessage(event) { + if (event.data.name == "set-host-title") { + toolbox.win.parent.removeEventListener("message", onmessage); + done(); + } + }); + }); + ok(toolbox.win.parent.document.title.includes(WORKER_URL), "worker URL in host title"); let toolTabs = toolbox.doc.querySelectorAll(".devtools-tab"); diff --git a/devtools/client/debugger/test/mochitest/head.js b/devtools/client/debugger/test/mochitest/head.js index 9ca0e0c8698c..1f9d38b82d15 100644 --- a/devtools/client/debugger/test/mochitest/head.js +++ b/devtools/client/debugger/test/mochitest/head.js @@ -751,6 +751,9 @@ AddonDebugger.prototype = { }), _onMessage: function (event) { + if (typeof(event.data) !== "string") { + return; + } let json = JSON.parse(event.data); switch (json.name) { case "toolbox-title": diff --git a/devtools/client/framework/devtools.js b/devtools/client/framework/devtools.js index 9753ddaef429..58002e01a8a2 100644 --- a/devtools/client/framework/devtools.js +++ b/devtools/client/framework/devtools.js @@ -10,6 +10,7 @@ const defer = require("devtools/shared/defer"); // Load gDevToolsBrowser toolbox lazily as they need gDevTools to be fully initialized loader.lazyRequireGetter(this, "Toolbox", "devtools/client/framework/toolbox", true); +loader.lazyRequireGetter(this, "ToolboxHostManager", "devtools/client/framework/toolbox-host-manager", true); loader.lazyRequireGetter(this, "gDevToolsBrowser", "devtools/client/framework/devtools-browser", true); const {defaultTools: DefaultTools, defaultThemes: DefaultThemes} = @@ -18,6 +19,7 @@ const EventEmitter = require("devtools/shared/event-emitter"); const {JsonView} = require("devtools/client/jsonview/main"); const AboutDevTools = require("devtools/client/framework/about-devtools-toolbox"); const {when: unload} = require("sdk/system/unload"); +const {Task} = require("devtools/shared/task"); const FORBIDDEN_IDS = new Set(["toolbox", ""]); const MAX_ORDINAL = 99; @@ -397,35 +399,27 @@ DevTools.prototype = { * @return {Toolbox} toolbox * The toolbox that was opened */ - showToolbox: function (target, toolId, hostType, hostOptions) { - let deferred = defer(); - + showToolbox: Task.async(function* (target, toolId, hostType, hostOptions) { let toolbox = this._toolboxes.get(target); if (toolbox) { - let hostPromise = (hostType != null && toolbox.hostType != hostType) ? - toolbox.switchHost(hostType) : - promise.resolve(null); - - if (toolId != null && toolbox.currentToolId != toolId) { - hostPromise = hostPromise.then(function () { - return toolbox.selectTool(toolId); - }); + if (hostType != null && toolbox.hostType != hostType) { + yield toolbox.switchHost(hostType); } - return hostPromise.then(function () { - toolbox.raise(); - return toolbox; - }); - } - else { - // No toolbox for target, create one - toolbox = new Toolbox(target, toolId, hostType, hostOptions); + if (toolId != null && toolbox.currentToolId != toolId) { + yield toolbox.selectTool(toolId); + } + + toolbox.raise(); + } else { + let manager = new ToolboxHostManager(target, hostType, hostOptions); + + toolbox = yield manager.create(toolId); + this._toolboxes.set(target, toolbox); this.emit("toolbox-created", toolbox); - this._toolboxes.set(target, toolbox); - toolbox.once("destroy", () => { this.emit("toolbox-destroy", target); }); @@ -435,16 +429,12 @@ DevTools.prototype = { this.emit("toolbox-destroyed", target); }); - // If toolId was passed in, it will already be selected before the - // open promise resolves. - toolbox.open().then(() => { - deferred.resolve(toolbox); - this.emit("toolbox-ready", toolbox); - }); + yield toolbox.open(); + this.emit("toolbox-ready", toolbox); } - return deferred.promise; - }, + return toolbox; + }), /** * Return the toolbox for a given target. diff --git a/devtools/client/framework/moz.build b/devtools/client/framework/moz.build index 13c7d27de317..7b28b4b9e749 100644 --- a/devtools/client/framework/moz.build +++ b/devtools/client/framework/moz.build @@ -25,6 +25,7 @@ DevToolsModules( 'target-from-url.js', 'target.js', 'toolbox-highlighter-utils.js', + 'toolbox-host-manager.js', 'toolbox-hosts.js', 'toolbox-options.js', 'toolbox.js', diff --git a/devtools/client/framework/test/browser_devtools_api.js b/devtools/client/framework/test/browser_devtools_api.js index f389df690e73..dc5a202e58cc 100644 --- a/devtools/client/framework/test/browser_devtools_api.js +++ b/devtools/client/framework/test/browser_devtools_api.js @@ -71,7 +71,7 @@ function runTests1(aTab) { gDevTools.showToolbox(target, toolId1).then(function (toolbox) { is(toolbox.target, target, "toolbox target is correct"); - is(toolbox._host.hostTab, gBrowser.selectedTab, "toolbox host is correct"); + is(toolbox.target.tab, gBrowser.selectedTab, "targeted tab is correct"); ok(events["init"], "init event fired"); ok(events["ready"], "ready event fired"); @@ -139,7 +139,7 @@ function runTests2() { gDevTools.showToolbox(target, toolId2).then(function (toolbox) { is(toolbox.target, target, "toolbox target is correct"); - is(toolbox._host.hostTab, gBrowser.selectedTab, "toolbox host is correct"); + is(toolbox.target.tab, gBrowser.selectedTab, "targeted tab is correct"); ok(events["init"], "init event fired"); ok(events["build"], "build event fired"); diff --git a/devtools/client/framework/test/browser_toolbox_custom_host.js b/devtools/client/framework/test/browser_toolbox_custom_host.js index 8d5f2215d2b1..5d3aeed54ce0 100644 --- a/devtools/client/framework/test/browser_toolbox_custom_host.js +++ b/devtools/client/framework/test/browser_toolbox_custom_host.js @@ -24,6 +24,9 @@ function test() { }); function onMessage(event) { + if (typeof(event.data) !== "string") { + return; + } info("onMessage: " + event.data); let json = JSON.parse(event.data); if (json.name == "toolbox-close") { diff --git a/devtools/client/framework/test/browser_toolbox_raise.js b/devtools/client/framework/test/browser_toolbox_raise.js index c1f26659fec0..0af1a457192c 100644 --- a/devtools/client/framework/test/browser_toolbox_raise.js +++ b/devtools/client/framework/test/browser_toolbox_raise.js @@ -42,12 +42,12 @@ function testWindowHost() { // Need to wait for focus as otherwise window.focus() is overridden by // toolbox window getting focused first on Linux and Mac. let onToolboxFocus = () => { - toolbox._host._window.removeEventListener("focus", onToolboxFocus, true); + toolbox.win.parent.removeEventListener("focus", onToolboxFocus, true); info("focusing main window."); window.focus(); }; // Need to wait for toolbox window to get focus. - toolbox._host._window.addEventListener("focus", onToolboxFocus, true); + toolbox.win.parent.addEventListener("focus", onToolboxFocus, true); } function onFocus() { @@ -56,11 +56,11 @@ function onFocus() { // Check if toolbox window got focus. let onToolboxFocusAgain = () => { - toolbox._host._window.removeEventListener("focus", onToolboxFocusAgain, false); + toolbox.win.parent.removeEventListener("focus", onToolboxFocusAgain, false); ok(true, "Toolbox window is the focused window after calling toolbox.raise()"); cleanup(); }; - toolbox._host._window.addEventListener("focus", onToolboxFocusAgain, false); + toolbox.win.parent.addEventListener("focus", onToolboxFocusAgain, false); // Now raise toolbox. toolbox.raise(); diff --git a/devtools/client/framework/test/browser_toolbox_toggle.js b/devtools/client/framework/test/browser_toolbox_toggle.js index c66aa002a3c7..d5b6d0e961d1 100644 --- a/devtools/client/framework/test/browser_toolbox_toggle.js +++ b/devtools/client/framework/test/browser_toolbox_toggle.js @@ -82,7 +82,7 @@ function* testToggleDetachedToolbox(tab, key, modifiers) { info("Verify windowed toolbox is focused instead of closed when using " + "toggle key from the main window"); - let toolboxWindow = toolbox._host._window; + let toolboxWindow = toolbox.win.top; let onToolboxWindowFocus = once(toolboxWindow, "focus", true); EventUtils.synthesizeKey(key, modifiers); yield onToolboxWindowFocus; diff --git a/devtools/client/framework/test/browser_toolbox_window_title_changes.js b/devtools/client/framework/test/browser_toolbox_window_title_changes.js index 0ea14209d90b..558c2094fa1e 100644 --- a/devtools/client/framework/test/browser_toolbox_window_title_changes.js +++ b/devtools/client/framework/test/browser_toolbox_window_title_changes.js @@ -28,28 +28,35 @@ function test() { .then(() => toolbox.selectTool(TOOL_ID_1)) // undock toolbox and check title - .then(() => toolbox.switchHost(Toolbox.HostType.WINDOW)) + .then(() => { + // We have to first switch the host in order to spawn the new top level window + // on which we are going to listen from title change event + return toolbox.switchHost(Toolbox.HostType.WINDOW) + .then(() => waitForTitleChange(toolbox)); + }) .then(checkTitle.bind(null, NAME_1, URL_1, "toolbox undocked")) // switch to different tool and check title - .then(() => toolbox.selectTool(TOOL_ID_2)) + .then(() => { + let onTitleChanged = waitForTitleChange(toolbox); + toolbox.selectTool(TOOL_ID_2); + return onTitleChanged; + }) .then(checkTitle.bind(null, NAME_1, URL_1, "tool changed")) // navigate to different local url and check title .then(function () { - let deferred = defer(); - target.once("navigate", () => deferred.resolve()); + let onTitleChanged = waitForTitleChange(toolbox); gBrowser.loadURI(URL_2); - return deferred.promise; + return onTitleChanged; }) .then(checkTitle.bind(null, NAME_2, URL_2, "url changed")) // navigate to a real url and check title .then(() => { - let deferred = defer(); - target.once("navigate", () => deferred.resolve()); + let onTitleChanged = waitForTitleChange(toolbox); gBrowser.loadURI(URL_3); - return deferred.promise; + return onTitleChanged; }) .then(checkTitle.bind(null, NAME_3, URL_3, "url changed")) @@ -66,7 +73,11 @@ function test() { return gDevTools.showToolbox(target, null, Toolbox.HostType.WINDOW); }) .then(function (aToolbox) { toolbox = aToolbox; }) - .then(() => toolbox.selectTool(TOOL_ID_1)) + .then(() => { + let onTitleChanged = waitForTitleChange(toolbox); + toolbox.selectTool(TOOL_ID_1); + return onTitleChanged; + }) .then(checkTitle.bind(null, NAME_3, URL_3, "toolbox destroyed and recreated")) diff --git a/devtools/client/framework/test/browser_toolbox_window_title_frame_select.js b/devtools/client/framework/test/browser_toolbox_window_title_frame_select.js index a674e0b44f4b..1e3d6664684b 100644 --- a/devtools/client/framework/test/browser_toolbox_window_title_frame_select.js +++ b/devtools/client/framework/test/browser_toolbox_window_title_frame_select.js @@ -25,8 +25,14 @@ add_task(function* () { let toolbox = yield gDevTools.showToolbox(target, null, Toolbox.HostType.BOTTOM); + let onTitleChanged = waitForTitleChange(toolbox); yield toolbox.selectTool("inspector"); + yield onTitleChanged; + yield toolbox.switchHost(Toolbox.HostType.WINDOW); + // Wait for title change event *after* switch host, in order to listen + // for the event on the WINDOW host window, which only exists after switchHost + yield waitForTitleChange(toolbox); is(getTitle(), `Developer Tools - Page title - ${URL}`, "Devtools title correct after switching to detached window host"); @@ -56,6 +62,8 @@ add_task(function* () { // Listen to will-navigate to check if the view is empty let willNavigate = toolbox.target.once("will-navigate"); + onTitleChanged = waitForTitleChange(toolbox); + // Only select the iframe after we are able to select an element from the top // level document. let newRoot = toolbox.getPanel("inspector").once("new-root"); @@ -64,6 +72,7 @@ add_task(function* () { yield willNavigate; yield newRoot; + yield onTitleChanged; info("Navigation to the iframe is done, the inspector should be back up"); is(getTitle(), `Developer Tools - Page title - ${URL}`, diff --git a/devtools/client/framework/test/shared-head.js b/devtools/client/framework/test/shared-head.js index eb69b40068dc..a89c6d7525ec 100644 --- a/devtools/client/framework/test/shared-head.js +++ b/devtools/client/framework/test/shared-head.js @@ -580,3 +580,17 @@ function emptyClipboard() { function isWindows() { return Services.appinfo.OS === "WINNT"; } + +/** + * Wait for a given toolbox to get its title updated. + */ +function waitForTitleChange(toolbox) { + let deferred = defer(); + toolbox.win.parent.addEventListener("message", function onmessage(event) { + if (event.data.name == "set-host-title") { + toolbox.win.parent.removeEventListener("message", onmessage); + deferred.resolve(); + } + }); + return deferred.promise; +} diff --git a/devtools/client/framework/toolbox-host-manager.js b/devtools/client/framework/toolbox-host-manager.js new file mode 100644 index 000000000000..a59251176299 --- /dev/null +++ b/devtools/client/framework/toolbox-host-manager.js @@ -0,0 +1,244 @@ +const Services = require("Services"); +const {Ci} = require("chrome"); +const {LocalizationHelper} = require("devtools/shared/l10n"); +const L10N = new LocalizationHelper("devtools/locale/toolbox.properties"); +const DevToolsUtils = require("devtools/shared/DevToolsUtils"); +const {Task} = require("devtools/shared/task"); + +loader.lazyRequireGetter(this, "Toolbox", "devtools/client/framework/toolbox", true); +loader.lazyRequireGetter(this, "Hosts", "devtools/client/framework/toolbox-hosts", true); + +/** + * Implement a wrapper on the chrome side to setup a Toolbox within Firefox UI. + * + * This component handles iframe creation within Firefox, in which we are loading + * the toolbox document. Then both the chrome and the toolbox document communicate + * via "message" events. + * + * Messages sent by the toolbox to the chrome: + * - switch-host: + * Order to display the toolbox in another host (side, bottom, window, or the + * previously used one) + * - toggle-minimize-mode: + * When using the bottom host, the toolbox can be miximized to only display + * the tool titles + * - maximize-host: + * When using the bottom host in minimized mode, revert back to regular mode + * in order to see tool titles and the tools + * - raise-host: + * Focus the tools + * - set-host-title: + * When using the window host, update the window title + * + * Messages sent by the chrome to the toolbox: + * - host-minimized: + * The bottom host is done minimizing (after animation end) + * - host-maximized: + * The bottom host is done switching back to regular mode (after animation + * end) + * - switched-host: + * The `switch-host` command sent by the toolbox is done + */ + +const LAST_HOST = "devtools.toolbox.host"; +const PREVIOUS_HOST = "devtools.toolbox.previousHost"; +let ID_COUNTER = 1; + +function ToolboxHostManager(target, hostType, hostOptions) { + this.target = target; + + this.frameId = ID_COUNTER++; + + if (!hostType) { + hostType = Services.prefs.getCharPref(LAST_HOST); + } + this.onHostMinimized = this.onHostMinimized.bind(this); + this.onHostMaximized = this.onHostMaximized.bind(this); + this.host = this.createHost(hostType, hostOptions); + this.hostType = hostType; +} + +ToolboxHostManager.prototype = { + create: Task.async(function* (toolId) { + yield this.host.create(); + + this.host.frame.setAttribute("aria-label", L10N.getStr("toolbox.label")); + this.host.frame.ownerDocument.defaultView.addEventListener("message", this); + // We have to listen on capture as no event fires on bubble + this.host.frame.addEventListener("unload", this, true); + + let toolbox = new Toolbox(this.target, toolId, this.host.type, this.host.frame.contentWindow, this.frameId); + + // Prevent reloading the toolbox when loading the tools in a tab (e.g. from about:debugging) + if (!this.host.frame.contentWindow.location.href.startsWith("about:devtools-toolbox")) { + this.host.frame.setAttribute("src", "about:devtools-toolbox"); + } + + return toolbox; + }), + + handleEvent(event) { + switch(event.type) { + case "message": + this.onMessage(event); + break; + case "unload": + // On unload, host iframe already lost its contentWindow attribute, so + // we can only compare against locations. Here we filter two very + // different cases: preliminary about:blank document as well as iframes + // like tool iframes. + if (!event.target.location.href.startsWith("about:devtools-toolbox")) { + break; + } + // Don't destroy the host during unload event (esp., don't remove the + // iframe from DOM!). Otherwise the unload event for the toolbox + // document doesn't fire within the toolbox *document*! This is + // the unload event that fires on the toolbox *iframe*. + DevToolsUtils.executeSoon(() => { + this.destroy(); + }); + break; + } + }, + + onMessage(event) { + if (!event.data) { + return; + } + // Toolbox document is still chrome and disallow identifying message + // origin via event.source as it is null. So use a custom id. + if (event.data.frameId != this.frameId) { + return; + } + switch (event.data.name) { + case "switch-host": + this.switchHost(event.data.hostType); + break; + case "maximize-host": + this.host.maximize(); + break; + case "raise-host": + this.host.raise(); + break; + case "toggle-minimize-mode": + this.host.toggleMinimizeMode(event.data.toolbarHeight); + break; + case "set-host-title": + this.host.setTitle(event.data.title); + break; + } + }, + + postMessage(data) { + let window = this.host.frame.contentWindow; + window.postMessage(data, "*"); + }, + + destroy() { + this.destroyHost(); + this.host = null; + this.hostType = null; + this.target = null; + }, + + /** + * Create a host object based on the given host type. + * + * Warning: bottom and sidebar hosts require that the toolbox target provides + * a reference to the attached tab. Not all Targets have a tab property - + * make sure you correctly mix and match hosts and targets. + * + * @param {string} hostType + * The host type of the new host object + * + * @return {Host} host + * The created host object + */ + createHost(hostType, options) { + if (!Hosts[hostType]) { + throw new Error("Unknown hostType: " + hostType); + } + + let newHost = new Hosts[hostType](this.target.tab, options); + // Update the label and icon when the state changes. + newHost.on("minimized", this.onHostMinimized); + newHost.on("maximized", this.onHostMaximized); + return newHost; + }, + + onHostMinimized() { + this.postMessage({ + name: "host-minimized" + }); + }, + + onHostMaximized() { + this.postMessage({ + name: "host-maximized" + }); + }, + + switchHost: Task.async(function* (hostType) { + if (hostType == "previous") { + // Switch to the last used host for the toolbox UI. + // This is determined by the devtools.toolbox.previousHost pref. + hostType = Services.prefs.getCharPref(PREVIOUS_HOST); + + // Handle the case where the previous host happens to match the current + // host. If so, switch to bottom if it's not already used, and side if not. + if (hostType === this.hostType) { + if (hostType === Toolbox.HostType.BOTTOM) { + hostType = Toolbox.HostType.SIDE; + } else { + hostType = Toolbox.HostType.BOTTOM; + } + } + } + let iframe = this.host.frame; + let newHost = this.createHost(hostType); + let newIframe = yield newHost.create(); + // change toolbox document's parent to the new host + newIframe.swapFrameLoaders(iframe); + + this.destroyHost(); + + if (this.hostType != Toolbox.HostType.CUSTOM) { + Services.prefs.setCharPref(PREVIOUS_HOST, this.hostType); + } + + this.host = newHost; + this.hostType = hostType; + this.host.setTitle(this.host.frame.contentWindow.document.title); + this.host.frame.ownerDocument.defaultView.addEventListener("message", this); + this.host.frame.addEventListener("unload", this, true); + + if (hostType != Toolbox.HostType.CUSTOM) { + Services.prefs.setCharPref(LAST_HOST, hostType); + } + + // Tell the toolbox the host changed + this.postMessage({ + name: "switched-host", + hostType + }); + }), + + /** + * Destroy the current host, and remove event listeners from its frame. + * + * @return {promise} to be resolved when the host is destroyed. + */ + destroyHost() { + // When Firefox toplevel is closed, the frame may already be detached and + // the top level document gone + if (this.host.frame.ownerDocument.defaultView) { + this.host.frame.ownerDocument.defaultView.removeEventListener("message", this); + } + this.host.frame.removeEventListener("unload", this, true); + + this.host.off("minimized", this.onHostMinimized); + this.host.off("maximized", this.onHostMaximized); + return this.host.destroy(); + } +}; +exports.ToolboxHostManager = ToolboxHostManager; diff --git a/devtools/client/framework/toolbox.js b/devtools/client/framework/toolbox.js index a45c03ccb279..fa148d45ccf8 100644 --- a/devtools/client/framework/toolbox.js +++ b/devtools/client/framework/toolbox.js @@ -40,8 +40,6 @@ loader.lazyRequireGetter(this, "CommandUtils", "devtools/client/shared/developer-toolbar", true); loader.lazyRequireGetter(this, "getHighlighterUtils", "devtools/client/framework/toolbox-highlighter-utils", true); -loader.lazyRequireGetter(this, "Hosts", - "devtools/client/framework/toolbox-hosts", true); loader.lazyRequireGetter(this, "Selection", "devtools/client/framework/selection", true); loader.lazyRequireGetter(this, "InspectorFront", @@ -80,12 +78,17 @@ loader.lazyGetter(this, "registerHarOverlay", () => { * Tool to select initially * @param {Toolbox.HostType} hostType * Type of host that will host the toolbox (e.g. sidebar, window) - * @param {object} hostOptions - * Options for host specifically + * @param {DOMWindow} contentWindow + * The window object of the toolbox document + * @param {string} frameId + * A unique identifier to differentiate toolbox documents from the + * chrome codebase when passing DOM messages */ -function Toolbox(target, selectedTool, hostType, hostOptions) { +function Toolbox(target, selectedTool, hostType, contentWindow, frameId) { this._target = target; - this._win = null; + this._win = contentWindow; + this.frameId = frameId; + this._toolPanels = new Map(); this._telemetry = new Telemetry(); if (Services.prefs.getBoolPref("devtools.sourcemap.locations.enabled")) { @@ -113,6 +116,7 @@ function Toolbox(target, selectedTool, hostType, hostOptions) { this._prefChanged = this._prefChanged.bind(this); this._saveSplitConsoleHeight = this._saveSplitConsoleHeight.bind(this); this._onFocus = this._onFocus.bind(this); + this._onBrowserMessage = this._onBrowserMessage.bind(this); this._showDevEditionPromo = this._showDevEditionPromo.bind(this); this._updateTextBoxMenuItems = this._updateTextBoxMenuItems.bind(this); this._onBottomHostMinimized = this._onBottomHostMinimized.bind(this); @@ -130,16 +134,12 @@ function Toolbox(target, selectedTool, hostType, hostOptions) { this._target.on("close", this.destroy); - if (!hostType) { - hostType = Services.prefs.getCharPref(this._prefs.LAST_HOST); - } if (!selectedTool) { selectedTool = Services.prefs.getCharPref(this._prefs.LAST_TOOL); } this._defaultToolId = selectedTool; - this._hostOptions = hostOptions; - this._host = this._createHost(hostType, hostOptions); + this._hostType = hostType; EventEmitter.decorate(this); @@ -174,10 +174,8 @@ Toolbox.prototype = { _URL: "about:devtools-toolbox", _prefs: { - LAST_HOST: "devtools.toolbox.host", LAST_TOOL: "devtools.toolbox.selectedTool", SIDE_ENABLED: "devtools.toolbox.sideEnabled", - PREVIOUS_HOST: "devtools.toolbox.previousHost" }, currentToolId: null, @@ -254,7 +252,7 @@ Toolbox.prototype = { * tab. See HostType for more details. */ get hostType() { - return this._host.type; + return this._hostType; }, /** @@ -337,27 +335,18 @@ Toolbox.prototype = { */ open: function () { return Task.spawn(function* () { - let iframe = yield this._host.create(); - this._win = iframe.contentWindow; - - let domReady = defer(); - - // Prevent reloading the document when the toolbox is opened in a tab - let location = iframe.contentWindow.location.href; - if (!location.startsWith(this._URL)) { - iframe.setAttribute("src", this._URL); - } else { - // Update the URL so that onceDOMReady watch for the right url. - this._URL = location; - } - this.browserRequire = BrowserLoader({ window: this.doc.defaultView, useOnlyShared: true }).require; - iframe.setAttribute("aria-label", L10N.getStr("toolbox.label")); - let domHelper = new DOMHelpers(iframe.contentWindow); + if (this.win.location.href.startsWith(this._URL)) { + // Update the URL so that onceDOMReady watch for the right url. + this._URL = this.win.location.href; + } + + let domReady = defer(); + let domHelper = new DOMHelpers(this.win); domHelper.onceDOMReady(() => { domReady.resolve(); }, this._URL); @@ -610,6 +599,7 @@ Toolbox.prototype = { this.doc.addEventListener("keypress", this._splitConsoleOnKeypress, false); this.doc.addEventListener("focus", this._onFocus, true); this.win.addEventListener("unload", this.destroy); + this.win.addEventListener("message", this._onBrowserMessage, true); }, _removeHostListeners: function () { @@ -618,6 +608,29 @@ Toolbox.prototype = { this.doc.removeEventListener("keypress", this._splitConsoleOnKeypress, false); this.doc.removeEventListener("focus", this._onFocus, true); this.win.removeEventListener("unload", this.destroy); + this.win.removeEventListener("message", this._onBrowserMessage, true); + } + }, + + // Called whenever the chrome send a message + _onBrowserMessage: function (event) { + if (!event.data) { + return; + } + switch (event.data.name) { + case "switched-host": + this._onSwitchedHost(event.data); + break; + case "host-minimized": + if (this.hostType == Toolbox.HostType.BOTTOM) { + this._onBottomHostMinimized(); + } + break; + case "host-maximized": + if (this.hostType == Toolbox.HostType.BOTTOM) { + this._onBottomHostMaximized(); + } + break; } }, @@ -781,9 +794,6 @@ Toolbox.prototype = { // Show the button in its maximized state. this._onBottomHostMaximized(); - // Update the label and icon when the state changes. - this._host.on("minimized", this._onBottomHostMinimized); - this._host.on("maximized", this._onBottomHostMaximized); // Maximize again when a tool gets selected. this.on("before-select", this._onToolSelectWhileMinimized); // Maximize and stop listening before the host type changes. @@ -842,14 +852,27 @@ Toolbox.prototype = { }, _onToolSelectWhileMinimized: function () { - this._host.maximize(); + this.postMessage({ + name: "maximize-host" + }); + }, + + postMessage: function (msg) { + // We sometime try to send messages in middle of destroy(), where the + // toolbox iframe may already be detached and no longer have a parent. + if (this.win.parent) { + // Toolbox document is still chrome and disallow identifying message + // origin via event.source as it is null. So use a custom id. + msg.frameId = this.frameId; + this.win.parent.postMessage(msg, "*"); + } }, _onBottomHostWillChange: function () { - this._host.maximize(); + this.postMessage({ + name: "maximize-host" + }); - this._host.off("minimized", this._onBottomHostMinimized); - this._host.off("maximized", this._onBottomHostMaximized); this.off("before-select", this._onToolSelectWhileMinimized); }, @@ -862,7 +885,10 @@ Toolbox.prototype = { // tabbar is still visible. let toolbarHeight = this.tabbar.getBoxQuads({box: "content"})[0].bounds .height; - this._host.toggleMinimizeMode(toolbarHeight); + this.postMessage({ + name: "toggle-minimize-mode", + toolbarHeight + }); }, /** @@ -1625,7 +1651,9 @@ Toolbox.prototype = { * Raise the toolbox host. */ raise: function () { - this._host.raise(); + this.postMessage({ + name: "raise-host" + }); }, /** @@ -1639,7 +1667,10 @@ Toolbox.prototype = { } else { title = L10N.getFormatStr("toolbox.titleTemplate1", this.target.url); } - this._host.setTitle(title); + this.postMessage({ + name: "set-host-title", + title + }); }, // Returns an instance of the preference actor @@ -1817,48 +1848,11 @@ Toolbox.prototype = { } }, - /** - * Create a host object based on the given host type. - * - * Warning: some hosts require that the toolbox target provides a reference to - * the attached tab. Not all Targets have a tab property - make sure you - * correctly mix and match hosts and targets. - * - * @param {string} hostType - * The host type of the new host object - * - * @return {Host} host - * The created host object - */ - _createHost: function (hostType, options) { - if (!Hosts[hostType]) { - throw new Error("Unknown hostType: " + hostType); - } - - // clean up the toolbox if its window is closed - let newHost = new Hosts[hostType](this.target.tab, options); - newHost.on("window-closed", this.destroy); - return newHost; - }, - /** * Switch to the last used host for the toolbox UI. - * This is determined by the devtools.toolbox.previousHost pref. */ switchToPreviousHost: function () { - let hostType = Services.prefs.getCharPref(this._prefs.PREVIOUS_HOST); - - // Handle the case where the previous host happens to match the current - // host. If so, switch to bottom if it's not already used, and side if not. - if (hostType === this.hostType) { - if (hostType === Toolbox.HostType.BOTTOM) { - hostType = Toolbox.HostType.SIDE; - } else { - hostType = Toolbox.HostType.BOTTOM; - } - } - - return this.switchHost(hostType); + return this.switchHost("previous"); }, /** @@ -1875,39 +1869,33 @@ Toolbox.prototype = { this.emit("host-will-change", hostType); - // If we call swapFrameLoaders() when a tool if focused it leaves the - // browser in a state where it thinks that the tool is focused but in - // reality the content area is focused. Blurring the tool before calling - // swapFrameLoaders() works around this issue. + // ToolboxHostManager is going to call swapFrameLoaders which mess up with + // focus. We have to blur before calling it in order to be able to restore + // the focus after, in _onSwitchedHost. this.focusTool(this.currentToolId, false); - let newHost = this._createHost(hostType); - return newHost.create().then(iframe => { - // change toolbox document's parent to the new host - iframe.QueryInterface(Ci.nsIFrameLoaderOwner); - iframe.swapFrameLoaders(this._host.frame); - - this._host.off("window-closed", this.destroy); - this.destroyHost(); - - let prevHostType = this._host.type; - this._host = newHost; - - if (this.hostType != Toolbox.HostType.CUSTOM) { - Services.prefs.setCharPref(this._prefs.LAST_HOST, this._host.type); - Services.prefs.setCharPref(this._prefs.PREVIOUS_HOST, prevHostType); - } - - this._buildDockButtons(); - this._addKeysToWindow(); - - // Focus the tool to make sure keyboard shortcuts work straight away. - this.focusTool(this.currentToolId, true); - - this.emit("host-changed"); - - this._telemetry.log(HOST_HISTOGRAM, this._getTelemetryHostId()); + // Host code on the chrome side will send back a message once the host + // switched + this.postMessage({ + name: "switch-host", + hostType }); + + return this.once("host-changed"); + }, + + _onSwitchedHost: function ({ hostType }) { + this._hostType = hostType; + + this._buildDockButtons(); + this._addKeysToWindow(); + + // We blurred the tools at start of switchHost, but also when clicking on + // host switching button. We now have to restore the focus. + this.focusTool(this.currentToolId, true); + + this.emit("host-changed"); + this._telemetry.log(HOST_HISTOGRAM, this._getTelemetryHostId()); }, /** @@ -2079,16 +2067,6 @@ Toolbox.prototype = { return this.notificationBox; }, - /** - * Destroy the current host, and remove event listeners from its frame. - * - * @return {promise} to be resolved when the host is destroyed. - */ - destroyHost: function () { - this._removeHostListeners(); - return this._host.destroy(); - }, - /** * Remove all UI elements, detach from target and clear up */ @@ -2196,11 +2174,19 @@ Toolbox.prototype = { // then destroying the host, successfully or not) before destroying the // target. deferred.resolve(settleAll(outstanding) - .catch(console.error) - .then(() => this.destroyHost()) .catch(console.error) .then(() => { - this._win = null; + this._removeHostListeners(); + + // `location` may already be null if the toolbox document is already + // in process of destruction. Otherwise if it is still around, ensure + // releasing toolbox document and triggering cleanup thanks to unload + // event. We do that precisely here, before nullifying the target as + // various cleanup code depends on the target attribute to be still + // defined. + if (win.location) { + win.location.replace("about:blank"); + } // Targets need to be notified that the toolbox is being torn down. // This is done after other destruction tasks since it may tear down @@ -2220,6 +2206,7 @@ Toolbox.prototype = { // Free _host after the call to destroyed in order to let a chance // to destroyed listeners to still query toolbox attributes this._host = null; + this._win = null; this._toolPanels.clear(); // Force GC to prevent long GC pauses when running tests and to free up diff --git a/devtools/client/inspector/test/browser_inspector_breadcrumbs_visibility.js b/devtools/client/inspector/test/browser_inspector_breadcrumbs_visibility.js index 5bfba98d317a..caee745c9b37 100644 --- a/devtools/client/inspector/test/browser_inspector_breadcrumbs_visibility.js +++ b/devtools/client/inspector/test/browser_inspector_breadcrumbs_visibility.js @@ -43,7 +43,7 @@ add_task(function* () { inspector.breadcrumbs.arrowScrollBox.scrollBehavior = "instant"; yield toolbox.switchHost(Toolbox.HostType.WINDOW); - let hostWindow = toolbox._host._window; + let hostWindow = toolbox.win.parent; let originalWidth = hostWindow.outerWidth; let originalHeight = hostWindow.outerHeight; hostWindow.resizeTo(640, 300); diff --git a/devtools/client/inspector/test/browser_inspector_portrait_mode.js b/devtools/client/inspector/test/browser_inspector_portrait_mode.js index e24134275cf7..04fcc2b56bc4 100644 --- a/devtools/client/inspector/test/browser_inspector_portrait_mode.js +++ b/devtools/client/inspector/test/browser_inspector_portrait_mode.js @@ -11,7 +11,7 @@ add_task(function* () { let { inspector, toolbox } = yield openInspectorForURL( "data:text/html;charset=utf-8,

foo

bar", "window"); - let hostWindow = toolbox._host._window; + let hostWindow = toolbox.win.parent; let originalWidth = hostWindow.outerWidth; let originalHeight = hostWindow.outerHeight; @@ -45,7 +45,7 @@ add_task(function* () { ok(splitter.classList.contains("horz"), "Splitter is in horizontal mode"); info("Restore original window size"); - toolbox._host._window.resizeTo(originalWidth, originalHeight); + toolbox.win.parent.resizeTo(originalWidth, originalHeight); }); /** diff --git a/devtools/client/styleeditor/test/browser_styleeditor_sv_resize.js b/devtools/client/styleeditor/test/browser_styleeditor_sv_resize.js index ff94bca1b713..d684905fc707 100644 --- a/devtools/client/styleeditor/test/browser_styleeditor_sv_resize.js +++ b/devtools/client/styleeditor/test/browser_styleeditor_sv_resize.js @@ -21,7 +21,7 @@ add_task(function* () { let editor = yield ui.editors[0].getSourceEditor(); let originalSourceEditor = editor.sourceEditor; - let hostWindow = toolbox._host._window; + let hostWindow = toolbox.win.parent; let originalWidth = hostWindow.outerWidth; let originalHeight = hostWindow.outerHeight; diff --git a/devtools/client/webconsole/test/browser_webconsole_closure_inspection.js b/devtools/client/webconsole/test/browser_webconsole_closure_inspection.js index 007b1d3184dd..6a29d61aab6c 100644 --- a/devtools/client/webconsole/test/browser_webconsole_closure_inspection.js +++ b/devtools/client/webconsole/test/browser_webconsole_closure_inspection.js @@ -96,5 +96,5 @@ function onExpandClosure(results) { gVariablesView.window.focus(); gJSTerm.once("sidebar-closed", finishTest); - EventUtils.synthesizeKey("VK_ESCAPE", {}); + EventUtils.synthesizeKey("VK_ESCAPE", {}, gVariablesView.window); } From f4cc00b7b08c9bfb921806c7e5da7b949df17473 Mon Sep 17 00:00:00 2001 From: Alexandre Poirot Date: Thu, 15 Sep 2016 09:57:46 -0700 Subject: [PATCH 56/60] Bug 1266134 - Fix responsive design possible leak on shutdown. r=jryans MozReview-Commit-ID: 3DteAYhBDNi --HG-- extra : rebase_source : 29b903505b0693c8dd7261a110b0ccecf65de388 --- devtools/client/responsivedesign/resize-commands.js | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/devtools/client/responsivedesign/resize-commands.js b/devtools/client/responsivedesign/resize-commands.js index 3569be711d08..b2f884df871b 100644 --- a/devtools/client/responsivedesign/resize-commands.js +++ b/devtools/client/responsivedesign/resize-commands.js @@ -59,10 +59,9 @@ exports.items = [ } }, offChange: function (aTarget, aChangeHandler) { - if (aTarget.tab) { - ResponsiveUIManager.off("on", aChangeHandler); - ResponsiveUIManager.off("off", aChangeHandler); - } + // Do not check for target.tab as it may already be null during destroy + ResponsiveUIManager.off("on", aChangeHandler); + ResponsiveUIManager.off("off", aChangeHandler); }, }, exec: gcli_cmd_resize From eb9db5ddc0e4454f3a3247658fd4fbb8f35c4eed Mon Sep 17 00:00:00 2001 From: Alexandre Poirot Date: Thu, 25 Aug 2016 05:48:27 -0700 Subject: [PATCH 57/60] Bug 1266134 - Convert browser_dbg_on-pause-raise.js to Task and wait for TabSelect before asserting the newly selected tab. r=jryans MozReview-Commit-ID: 7vu2fFdiE4g --HG-- extra : rebase_source : ea3ef7fa0e04fffb5e26704624b495c78d66627a --- .../mochitest/browser_dbg_on-pause-raise.js | 197 ++++++++---------- 1 file changed, 86 insertions(+), 111 deletions(-) diff --git a/devtools/client/debugger/test/mochitest/browser_dbg_on-pause-raise.js b/devtools/client/debugger/test/mochitest/browser_dbg_on-pause-raise.js index 488a11a6c8a2..6f6f152477b7 100644 --- a/devtools/client/debugger/test/mochitest/browser_dbg_on-pause-raise.js +++ b/devtools/client/debugger/test/mochitest/browser_dbg_on-pause-raise.js @@ -9,137 +9,112 @@ const TAB_URL = EXAMPLE_URL + "doc_recursion-stack.html"; -var gTab, gPanel, gDebugger; -var gFocusedWindow, gToolbox, gToolboxTab; - -function test() { +add_task(function *() { let options = { source: TAB_URL, line: 1 }; - initDebugger(TAB_URL, options).then(([aTab,, aPanel]) => { - gTab = aTab; - gPanel = aPanel; - gDebugger = gPanel.panelWin; - gToolbox = gPanel._toolbox; - gToolboxTab = gToolbox.doc.getElementById("toolbox-tab-jsdebugger"); + let [tab,, panel] = yield initDebugger(TAB_URL, options); + let panelWin = panel.panelWin; + let toolbox = panel._toolbox; + let toolboxTab = toolbox.doc.getElementById("toolbox-tab-jsdebugger"); - performTest(); - }); -} + let newTab = yield addTab(TAB_URL); + isnot(newTab, tab, + "The newly added tab is different from the debugger's tab."); + is(gBrowser.selectedTab, newTab, + "Debugger's tab is not the selected tab."); -function performTest() { - addTab(TAB_URL).then(aTab => { - isnot(aTab, gTab, - "The newly added tab is different from the debugger's tab."); - is(gBrowser.selectedTab, aTab, - "Debugger's tab is not the selected tab."); + info("Run tests against bottom host."); + yield testPause(); + yield testResume(); - gFocusedWindow = window; - testPause(); - }); -} + // testResume selected the console, select back the debugger. + yield toolbox.selectTool("jsdebugger"); -function focusMainWindow() { - // Make sure toolbox is not focused. - window.addEventListener("focus", onFocus, true); - info("Focusing main window."); + info("Switching to a toolbox window host."); + yield toolbox.switchHost(Toolbox.HostType.WINDOW); - // Execute soon to avoid any race conditions between toolbox and main window - // getting focused. - executeSoon(() => { - window.focus(); - }); -} + info("Run tests against window host."); + yield testPause(); + yield testResume(); -function onFocus() { - window.removeEventListener("focus", onFocus, true); - info("Main window focused."); + info("Cleanup after the test."); + yield toolbox.switchHost(Toolbox.HostType.BOTTOM); + yield closeDebuggerAndFinish(panel); - gFocusedWindow = window; - testPause(); -} + function* testPause() { + is(panelWin.gThreadClient.paused, false, + "Should be running after starting the test."); -function testPause() { - is(gDebugger.gThreadClient.paused, false, - "Should be running after starting the test."); - - is(gFocusedWindow, window, - "Main window is the top level window before pause."); - - if (gToolbox.hostType == Toolbox.HostType.WINDOW) { - gToolbox._host._window.addEventListener("focus", function onFocus() { - gToolbox._host._window.removeEventListener("focus", onFocus, true); - gFocusedWindow = gToolbox._host._window; - }, true); - } - - gDebugger.gThreadClient.addOneTimeListener("paused", () => { - if (gToolbox.hostType == Toolbox.HostType.WINDOW) { - is(gFocusedWindow, gToolbox._host._window, - "Toolbox window is the top level window on pause."); + let onFocus, onTabSelect; + if (toolbox.hostType == Toolbox.HostType.WINDOW) { + onFocus = new Promise(done => { + toolbox.win.parent.addEventListener("focus", function onFocus() { + toolbox.win.parent.removeEventListener("focus", onFocus, true); + done(); + }, true); + }); } else { - is(gBrowser.selectedTab, gTab, + onTabSelect = new Promise(done => { + tab.parentNode.addEventListener("TabSelect", function listener({type}) { + tab.parentNode.removeEventListener(type, listener); + done(); + }); + }); + } + + let onPaused = waitForPause(panelWin.gThreadClient); + + // Evaluate a script to fully pause the debugger + evalInTab(tab, "debugger;"); + + yield onPaused; + yield onFocus; + yield onTabSelect; + + if (toolbox.hostType != Toolbox.HostType.WINDOW) { + is(gBrowser.selectedTab, tab, "Debugger's tab got selected."); } - gToolbox.selectTool("webconsole").then(() => { - ok(gToolboxTab.hasAttribute("highlighted") && - gToolboxTab.getAttribute("highlighted") == "true", - "The highlighted class is present"); - ok(!gToolboxTab.hasAttribute("selected") || - gToolboxTab.getAttribute("selected") != "true", - "The tab is not selected"); - }).then(() => gToolbox.selectTool("jsdebugger")).then(() => { - ok(gToolboxTab.hasAttribute("highlighted") && - gToolboxTab.getAttribute("highlighted") == "true", - "The highlighted class is present"); - ok(gToolboxTab.hasAttribute("selected") && - gToolboxTab.getAttribute("selected") == "true", - "...and the tab is selected, so the glow will not be present."); - }).then(testResume); - }); - // Evaluate a script to fully pause the debugger - evalInTab(gTab, "debugger;"); -} - -function testResume() { - gDebugger.gThreadClient.addOneTimeListener("resumed", () => { - gToolbox.selectTool("webconsole").then(() => { - ok(!gToolboxTab.hasAttribute("highlighted") || - gToolboxTab.getAttribute("highlighted") != "true", - "The highlighted class is not present now after the resume"); - ok(!gToolboxTab.hasAttribute("selected") || - gToolboxTab.getAttribute("selected") != "true", - "The tab is not selected"); - }).then(maybeEndTest); - }); - - EventUtils.sendMouseEvent({ type: "mousedown" }, - gDebugger.document.getElementById("resume"), - gDebugger); -} - -function maybeEndTest() { - if (gToolbox.hostType == Toolbox.HostType.BOTTOM) { - info("Switching to a toolbox window host."); - gToolbox.switchHost(Toolbox.HostType.WINDOW).then(focusMainWindow); - } else { - info("Switching to main window host."); - gToolbox.switchHost(Toolbox.HostType.BOTTOM).then(() => closeDebuggerAndFinish(gPanel)); + yield toolbox.selectTool("webconsole"); + ok(toolboxTab.hasAttribute("highlighted") && + toolboxTab.getAttribute("highlighted") == "true", + "The highlighted class is present"); + ok(!toolboxTab.hasAttribute("selected") || + toolboxTab.getAttribute("selected") != "true", + "The tab is not selected"); + yield toolbox.selectTool("jsdebugger"); + ok(toolboxTab.hasAttribute("highlighted") && + toolboxTab.getAttribute("highlighted") == "true", + "The highlighted class is present"); + ok(toolboxTab.hasAttribute("selected") && + toolboxTab.getAttribute("selected") == "true", + "...and the tab is selected, so the glow will not be present."); } -} + + function* testResume() { + let onPaused = waitForEvent(panelWin.gThreadClient, "resumed"); + + EventUtils.sendMouseEvent({ type: "mousedown" }, + panelWin.document.getElementById("resume"), + panelWin); + + yield onPaused; + + yield toolbox.selectTool("webconsole"); + ok(!toolboxTab.hasAttribute("highlighted") || + toolboxTab.getAttribute("highlighted") != "true", + "The highlighted class is not present now after the resume"); + ok(!toolboxTab.hasAttribute("selected") || + toolboxTab.getAttribute("selected") != "true", + "The tab is not selected"); + } +}); registerCleanupFunction(function () { // Revert to the default toolbox host, so that the following tests proceed // normally and not inside a non-default host. Services.prefs.setCharPref("devtools.toolbox.host", Toolbox.HostType.BOTTOM); - - gTab = null; - gPanel = null; - gDebugger = null; - - gFocusedWindow = null; - gToolbox = null; - gToolboxTab = null; }); From 7c35371232c1afa7b1519ba98735a36d223dc4d4 Mon Sep 17 00:00:00 2001 From: Alexandre Poirot Date: Mon, 12 Sep 2016 03:20:52 -0700 Subject: [PATCH 58/60] Bug 1266134 - Wait for window close before ending test in browser_styleeditor_private_perwindowpb.js. r=jryans MozReview-Commit-ID: 65WEA8goOP5 --HG-- extra : rebase_source : 2db41fb4bb9d86f8064739453354c55a09b76cd8 --- .../browser_styleeditor_private_perwindowpb.js | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/devtools/client/styleeditor/test/browser_styleeditor_private_perwindowpb.js b/devtools/client/styleeditor/test/browser_styleeditor_private_perwindowpb.js index 144467fa16f4..4381704e97f7 100644 --- a/devtools/client/styleeditor/test/browser_styleeditor_private_perwindowpb.js +++ b/devtools/client/styleeditor/test/browser_styleeditor_private_perwindowpb.js @@ -22,14 +22,26 @@ add_task(function* () { info("Clearing the browser cache"); cache.clear(); - let { ui } = yield openStyleEditorForURL(TEST_URL, win); + let { toolbox, ui } = yield openStyleEditorForURL(TEST_URL, win); is(ui.editors.length, 1, "The style editor contains one sheet."); let editor = ui.editors[0]; yield editor.getSourceEditor(); yield checkDiskCacheFor(TEST_HOST); + + yield toolbox.destroy(); + + let onUnload = new Promise(done => { + win.addEventListener("unload", function listener(event) { + if (event.target == win.document) { + win.removeEventListener("unload", listener); + done(); + } + }); + }); win.close(); + yield onUnload; }); function checkDiskCacheFor(host) { From 55a228567fc579c64c1bdac0415ca51c76f95005 Mon Sep 17 00:00:00 2001 From: Alexandre Poirot Date: Thu, 15 Sep 2016 15:08:11 -0700 Subject: [PATCH 59/60] Bug 1266134 - Prevent browser_computed_keybindings_01.js from opening options panel. r=jryans MozReview-Commit-ID: LXCWjQwkwUN --HG-- extra : rebase_source : 97e106007719319a1214b16ae29be707fcf2e7e7 --- devtools/client/inspector/computed/computed.js | 5 +++-- .../computed/test/browser_computed_keybindings_01.js | 2 +- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/devtools/client/inspector/computed/computed.js b/devtools/client/inspector/computed/computed.js index 59ad37ce5d61..86268c2d2313 100644 --- a/devtools/client/inspector/computed/computed.js +++ b/devtools/client/inspector/computed/computed.js @@ -939,6 +939,9 @@ PropertyView.prototype = { }); this.shortcuts.on("F1", (name, event) => { this.mdnLinkClick(event); + // Prevent opening the options panel + event.preventDefault(); + event.stopPropagation(); }); this.shortcuts.on("Return", (name, event) => this.onMatchedToggle(event)); this.shortcuts.on("Space", (name, event) => this.onMatchedToggle(event)); @@ -1170,8 +1173,6 @@ PropertyView.prototype = { let browserWin = inspector.target.tab.ownerDocument.defaultView; browserWin.openUILinkIn(this.link, "tab"); } - event.preventDefault(); - event.stopPropagation(); }, /** diff --git a/devtools/client/inspector/computed/test/browser_computed_keybindings_01.js b/devtools/client/inspector/computed/test/browser_computed_keybindings_01.js index 7953af0bebab..199e125af1a1 100644 --- a/devtools/client/inspector/computed/test/browser_computed_keybindings_01.js +++ b/devtools/client/inspector/computed/test/browser_computed_keybindings_01.js @@ -73,7 +73,7 @@ function checkHelpLinkKeybinding(view) { let def = defer(); let propView = getFirstVisiblePropertyView(view); - propView.mdnLinkClick = function () { + propView.mdnLinkClick = function (event) { ok(true, "Pressing F1 opened the MDN link"); def.resolve(); }; From 871f020127cd62375fe3d4755398dee1faea8343 Mon Sep 17 00:00:00 2001 From: Sebastian Hengst Date: Thu, 27 Oct 2016 00:15:57 +0200 Subject: [PATCH 60/60] Bug 1311178 - Remove various duplicate DevTools files: touch clobber to fix bustage on OS X. r=clobber MozReview-Commit-ID: 6zN4xdtlB0N --- CLOBBER | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CLOBBER b/CLOBBER index fe88fbc7c2d5..6370307fe54a 100644 --- a/CLOBBER +++ b/CLOBBER @@ -22,4 +22,4 @@ # changes to stick? As of bug 928195, this shouldn't be necessary! Please # don't change CLOBBER for WebIDL changes any more. -Bug 1306438 and bug 1304815 - Rust update and related changes require clobber +Bug 1311178 - File removals in devtools on OS X