author | Ryan VanderMeulen <ryanvm@gmail.com> |
Wed, 17 Sep 2014 14:43:42 -0400 | |
changeset 205897 | 0c796a435ec069935cfb4ab980f4e83c7cbd264e |
parent 205896 | 3774cabb49f23b15d4be7f5649b4f6fb59955385 (current diff) |
parent 205836 | d2c01d77b9d0bf344d3a570dd224c4c543f47bba (diff) |
child 205898 | 57b5abc0d381d714a71597959df038ba3aee78cc |
push id | 27507 |
push user | ryanvm@gmail.com |
push date | Thu, 18 Sep 2014 02:16:54 +0000 |
treeherder | mozilla-central@488d490da742 [default view] [failures only] |
perfherder | [talos] [build metrics] [platform microbench] (compared to previous push) |
reviewers | merge |
milestone | 35.0a1 |
first release with | nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
|
last release without | nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
|
browser/base/content/test/general/browser_bug1047603.js | file | annotate | diff | comparison | revisions | |
dom/mobileconnection/gonk/MobileConnectionService.js | file | annotate | diff | comparison | revisions | |
dom/mobileconnection/gonk/MobileConnectionService.manifest | file | annotate | diff | comparison | revisions | |
dom/mobileconnection/gonk/nsIGonkMobileConnectionService.idl | file | annotate | diff | comparison | revisions |
--- a/b2g/components/AlertsHelper.jsm +++ b/b2g/components/AlertsHelper.jsm @@ -220,31 +220,33 @@ let AlertsHelper = { try { let data = Cu.cloneInto(dataObj, {}); } catch(e) { dataObj = null; } return dataObj; }, showNotification: function(imageURL, title, text, textClickable, cookie, - uid, bidi, lang, dataObj, manifestURL, timestamp) { + uid, bidi, lang, dataObj, manifestURL, timestamp, + behavior) { function send(appName, appIcon) { SystemAppProxy._sendCustomEvent(kMozChromeNotificationEvent, { type: kDesktopNotification, id: uid, icon: imageURL, title: title, text: text, bidi: bidi, lang: lang, appName: appName, appIcon: appIcon, manifestURL: manifestURL, timestamp: timestamp, - data: dataObj + data: dataObj, + mozbehavior: behavior }); } if (!manifestURL || !manifestURL.length) { send(null, null); return; } @@ -287,17 +289,17 @@ let AlertsHelper = { tag: details.tag || undefined, timestamp: details.timestamp || undefined, dataObj: dataObject || undefined }; this.registerAppListener(data.uid, listener); this.showNotification(data.imageURL, data.title, data.text, details.textClickable, null, data.uid, details.dir, details.lang, dataObject, details.manifestURL, - details.timestamp); + details.timestamp, details.mozbehavior); }, closeAlert: function(name) { SystemAppProxy._sendCustomEvent(kMozChromeNotificationEvent, { type: kDesktopNotificationClose, id: name }); },
--- a/b2g/config/dolphin/sources.xml +++ b/b2g/config/dolphin/sources.xml @@ -10,17 +10,17 @@ <!--original fetch url was git://codeaurora.org/--> <remote fetch="https://git.mozilla.org/external/caf" name="caf"/> <!--original fetch url was https://git.mozilla.org/releases--> <remote fetch="https://git.mozilla.org/releases" name="mozillaorg"/> <!-- B2G specific things. --> <project name="platform_build" path="build" remote="b2g" revision="fe92ddd450e03b38edb2d465de7897971d68ac68"> <copyfile dest="Makefile" src="core/root.mk"/> </project> - <project name="gaia" path="gaia" remote="mozillaorg" revision="50666fa8bbbf3d346faff24f92ad8140a44a49d0"/> + <project name="gaia" path="gaia" remote="mozillaorg" revision="72262d054ffa5d0d2b5a0033f713149281511aea"/> <project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/> <project name="gonk-misc" path="gonk-misc" remote="b2g" revision="f2f293787d4a86257c9e78a35bd3f73b31b706e2"/> <project name="librecovery" path="librecovery" remote="b2g" revision="891e5069c0ad330d8191bf8c7b879c814258c89f"/> <project name="moztt" path="external/moztt" remote="b2g" revision="562d357b72279a9e35d4af5aeecc8e1ffa2f44f1"/> <project name="rilproxy" path="rilproxy" remote="b2g" revision="827214fcf38d6569aeb5c6d6f31cb296d1f09272"/> <project name="valgrind" path="external/valgrind" remote="b2g" revision="daa61633c32b9606f58799a3186395fd2bbb8d8c"/> <project name="vex" path="external/VEX" remote="b2g" revision="47f031c320888fe9f3e656602588565b52d43010"/> <project name="apitrace" path="external/apitrace" remote="apitrace" revision="f3e998242fb9a857cf50f5bf3a02304a530ea617"/>
--- a/b2g/config/emulator-ics/sources.xml +++ b/b2g/config/emulator-ics/sources.xml @@ -14,17 +14,17 @@ <!--original fetch url was git://github.com/apitrace/--> <remote fetch="https://git.mozilla.org/external/apitrace" name="apitrace"/> <default remote="caf" revision="refs/tags/android-4.0.4_r2.1" sync-j="4"/> <!-- Gonk specific things and forks --> <project name="platform_build" path="build" remote="b2g" revision="4d1e85908d792d9468c4da7040acd191fbb51b40"> <copyfile dest="Makefile" src="core/root.mk"/> </project> <project name="fake-dalvik" path="dalvik" remote="b2g" revision="ca1f327d5acc198bb4be62fa51db2c039032c9ce"/> - <project name="gaia.git" path="gaia" remote="mozillaorg" revision="50666fa8bbbf3d346faff24f92ad8140a44a49d0"/> + <project name="gaia.git" path="gaia" remote="mozillaorg" revision="72262d054ffa5d0d2b5a0033f713149281511aea"/> <project name="gonk-misc" path="gonk-misc" remote="b2g" revision="f2f293787d4a86257c9e78a35bd3f73b31b706e2"/> <project name="rilproxy" path="rilproxy" remote="b2g" revision="827214fcf38d6569aeb5c6d6f31cb296d1f09272"/> <project name="platform_hardware_ril" path="hardware/ril" remote="b2g" revision="cd88d860656c31c7da7bb310d6a160d0011b0961"/> <project name="platform_external_qemu" path="external/qemu" remote="b2g" revision="c058843242068d0df7c107e09da31b53d2e08fa6"/> <project name="moztt" path="external/moztt" remote="b2g" revision="562d357b72279a9e35d4af5aeecc8e1ffa2f44f1"/> <project name="apitrace" path="external/apitrace" remote="apitrace" revision="f3e998242fb9a857cf50f5bf3a02304a530ea617"/> <!-- Stock Android things --> <project name="platform/abi/cpp" path="abi/cpp" revision="dd924f92906085b831bf1cbbc7484d3c043d613c"/>
--- a/b2g/config/emulator-jb/sources.xml +++ b/b2g/config/emulator-jb/sources.xml @@ -12,17 +12,17 @@ <!--original fetch url was https://git.mozilla.org/releases--> <remote fetch="https://git.mozilla.org/releases" name="mozillaorg"/> <!-- B2G specific things. --> <project name="platform_build" path="build" remote="b2g" revision="8986df0f82e15ac2798df0b6c2ee3435400677ac"> <copyfile dest="Makefile" src="core/root.mk"/> </project> <project name="rilproxy" path="rilproxy" remote="b2g" revision="827214fcf38d6569aeb5c6d6f31cb296d1f09272"/> <project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/> - <project name="gaia" path="gaia" remote="mozillaorg" revision="50666fa8bbbf3d346faff24f92ad8140a44a49d0"/> + <project name="gaia" path="gaia" remote="mozillaorg" revision="72262d054ffa5d0d2b5a0033f713149281511aea"/> <project name="gonk-misc" path="gonk-misc" remote="b2g" revision="f2f293787d4a86257c9e78a35bd3f73b31b706e2"/> <project name="moztt" path="external/moztt" remote="b2g" revision="562d357b72279a9e35d4af5aeecc8e1ffa2f44f1"/> <project name="apitrace" path="external/apitrace" remote="apitrace" revision="f3e998242fb9a857cf50f5bf3a02304a530ea617"/> <project name="valgrind" path="external/valgrind" remote="b2g" revision="daa61633c32b9606f58799a3186395fd2bbb8d8c"/> <project name="vex" path="external/VEX" remote="b2g" revision="47f031c320888fe9f3e656602588565b52d43010"/> <!-- Stock Android things --> <project groups="linux" name="platform/prebuilts/clang/linux-x86/3.1" path="prebuilts/clang/linux-x86/3.1" revision="5c45f43419d5582949284eee9cef0c43d866e03b"/> <project groups="linux" name="platform/prebuilts/clang/linux-x86/3.2" path="prebuilts/clang/linux-x86/3.2" revision="3748b4168e7bd8d46457d4b6786003bc6a5223ce"/>
--- a/b2g/config/emulator-kk/sources.xml +++ b/b2g/config/emulator-kk/sources.xml @@ -10,17 +10,17 @@ <!--original fetch url was git://codeaurora.org/--> <remote fetch="https://git.mozilla.org/external/caf" name="caf"/> <!--original fetch url was https://git.mozilla.org/releases--> <remote fetch="https://git.mozilla.org/releases" name="mozillaorg"/> <!-- B2G specific things. --> <project name="platform_build" path="build" remote="b2g" revision="fe92ddd450e03b38edb2d465de7897971d68ac68"> <copyfile dest="Makefile" src="core/root.mk"/> </project> - <project name="gaia" path="gaia" remote="mozillaorg" revision="50666fa8bbbf3d346faff24f92ad8140a44a49d0"/> + <project name="gaia" path="gaia" remote="mozillaorg" revision="72262d054ffa5d0d2b5a0033f713149281511aea"/> <project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/> <project name="gonk-misc" path="gonk-misc" remote="b2g" revision="f2f293787d4a86257c9e78a35bd3f73b31b706e2"/> <project name="librecovery" path="librecovery" remote="b2g" revision="891e5069c0ad330d8191bf8c7b879c814258c89f"/> <project name="moztt" path="external/moztt" remote="b2g" revision="562d357b72279a9e35d4af5aeecc8e1ffa2f44f1"/> <project name="rilproxy" path="rilproxy" remote="b2g" revision="827214fcf38d6569aeb5c6d6f31cb296d1f09272"/> <project name="valgrind" path="external/valgrind" remote="b2g" revision="daa61633c32b9606f58799a3186395fd2bbb8d8c"/> <project name="vex" path="external/VEX" remote="b2g" revision="47f031c320888fe9f3e656602588565b52d43010"/> <project name="apitrace" path="external/apitrace" remote="apitrace" revision="f3e998242fb9a857cf50f5bf3a02304a530ea617"/>
--- a/b2g/config/emulator/sources.xml +++ b/b2g/config/emulator/sources.xml @@ -14,17 +14,17 @@ <!--original fetch url was git://github.com/apitrace/--> <remote fetch="https://git.mozilla.org/external/apitrace" name="apitrace"/> <default remote="caf" revision="refs/tags/android-4.0.4_r2.1" sync-j="4"/> <!-- Gonk specific things and forks --> <project name="platform_build" path="build" remote="b2g" revision="4d1e85908d792d9468c4da7040acd191fbb51b40"> <copyfile dest="Makefile" src="core/root.mk"/> </project> <project name="fake-dalvik" path="dalvik" remote="b2g" revision="ca1f327d5acc198bb4be62fa51db2c039032c9ce"/> - <project name="gaia.git" path="gaia" remote="mozillaorg" revision="50666fa8bbbf3d346faff24f92ad8140a44a49d0"/> + <project name="gaia.git" path="gaia" remote="mozillaorg" revision="72262d054ffa5d0d2b5a0033f713149281511aea"/> <project name="gonk-misc" path="gonk-misc" remote="b2g" revision="f2f293787d4a86257c9e78a35bd3f73b31b706e2"/> <project name="rilproxy" path="rilproxy" remote="b2g" revision="827214fcf38d6569aeb5c6d6f31cb296d1f09272"/> <project name="platform_hardware_ril" path="hardware/ril" remote="b2g" revision="cd88d860656c31c7da7bb310d6a160d0011b0961"/> <project name="platform_external_qemu" path="external/qemu" remote="b2g" revision="c058843242068d0df7c107e09da31b53d2e08fa6"/> <project name="moztt" path="external/moztt" remote="b2g" revision="562d357b72279a9e35d4af5aeecc8e1ffa2f44f1"/> <project name="apitrace" path="external/apitrace" remote="apitrace" revision="f3e998242fb9a857cf50f5bf3a02304a530ea617"/> <!-- Stock Android things --> <project name="platform/abi/cpp" path="abi/cpp" revision="dd924f92906085b831bf1cbbc7484d3c043d613c"/>
--- a/b2g/config/flame-kk/sources.xml +++ b/b2g/config/flame-kk/sources.xml @@ -10,17 +10,17 @@ <!--original fetch url was git://codeaurora.org/--> <remote fetch="https://git.mozilla.org/external/caf" name="caf"/> <!--original fetch url was https://git.mozilla.org/releases--> <remote fetch="https://git.mozilla.org/releases" name="mozillaorg"/> <!-- B2G specific things. --> <project name="platform_build" path="build" remote="b2g" revision="fe92ddd450e03b38edb2d465de7897971d68ac68"> <copyfile dest="Makefile" src="core/root.mk"/> </project> - <project name="gaia" path="gaia" remote="mozillaorg" revision="50666fa8bbbf3d346faff24f92ad8140a44a49d0"/> + <project name="gaia" path="gaia" remote="mozillaorg" revision="72262d054ffa5d0d2b5a0033f713149281511aea"/> <project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/> <project name="gonk-misc" path="gonk-misc" remote="b2g" revision="f2f293787d4a86257c9e78a35bd3f73b31b706e2"/> <project name="librecovery" path="librecovery" remote="b2g" revision="891e5069c0ad330d8191bf8c7b879c814258c89f"/> <project name="moztt" path="external/moztt" remote="b2g" revision="562d357b72279a9e35d4af5aeecc8e1ffa2f44f1"/> <project name="rilproxy" path="rilproxy" remote="b2g" revision="827214fcf38d6569aeb5c6d6f31cb296d1f09272"/> <project name="valgrind" path="external/valgrind" remote="b2g" revision="daa61633c32b9606f58799a3186395fd2bbb8d8c"/> <project name="vex" path="external/VEX" remote="b2g" revision="47f031c320888fe9f3e656602588565b52d43010"/> <project name="apitrace" path="external/apitrace" remote="apitrace" revision="f3e998242fb9a857cf50f5bf3a02304a530ea617"/>
--- a/b2g/config/flame/sources.xml +++ b/b2g/config/flame/sources.xml @@ -12,17 +12,17 @@ <!--original fetch url was https://git.mozilla.org/releases--> <remote fetch="https://git.mozilla.org/releases" name="mozillaorg"/> <!-- B2G specific things. --> <project name="platform_build" path="build" remote="b2g" revision="8986df0f82e15ac2798df0b6c2ee3435400677ac"> <copyfile dest="Makefile" src="core/root.mk"/> </project> <project name="librecovery" path="librecovery" remote="b2g" revision="891e5069c0ad330d8191bf8c7b879c814258c89f"/> <project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/> - <project name="gaia" path="gaia" remote="mozillaorg" revision="50666fa8bbbf3d346faff24f92ad8140a44a49d0"/> + <project name="gaia" path="gaia" remote="mozillaorg" revision="72262d054ffa5d0d2b5a0033f713149281511aea"/> <project name="gonk-misc" path="gonk-misc" remote="b2g" revision="f2f293787d4a86257c9e78a35bd3f73b31b706e2"/> <project name="moztt" path="external/moztt" remote="b2g" revision="562d357b72279a9e35d4af5aeecc8e1ffa2f44f1"/> <project name="apitrace" path="external/apitrace" remote="apitrace" revision="f3e998242fb9a857cf50f5bf3a02304a530ea617"/> <project name="valgrind" path="external/valgrind" remote="b2g" revision="daa61633c32b9606f58799a3186395fd2bbb8d8c"/> <project name="vex" path="external/VEX" remote="b2g" revision="47f031c320888fe9f3e656602588565b52d43010"/> <!-- Stock Android things --> <project groups="linux" name="platform/prebuilts/clang/linux-x86/3.1" path="prebuilts/clang/linux-x86/3.1" revision="e95b4ce22c825da44d14299e1190ea39a5260bde"/> <project groups="linux" name="platform/prebuilts/clang/linux-x86/3.2" path="prebuilts/clang/linux-x86/3.2" revision="471afab478649078ad7c75ec6b252481a59e19b8"/>
--- a/b2g/config/gaia.json +++ b/b2g/config/gaia.json @@ -1,9 +1,9 @@ { "git": { "git_revision": "", "remote": "", "branch": "" }, - "revision": "9d4cf6d16100e4091fa14530e44ef2cdb5c0f832", + "revision": "9fffcfaa0e101a04a867ee3cbab0f59805e7cb45", "repo_path": "/integration/gaia-central" }
--- a/b2g/config/hamachi/sources.xml +++ b/b2g/config/hamachi/sources.xml @@ -12,17 +12,17 @@ <!--original fetch url was git://github.com/apitrace/--> <remote fetch="https://git.mozilla.org/external/apitrace" name="apitrace"/> <default remote="caf" revision="b2g/ics_strawberry" sync-j="4"/> <!-- Gonk specific things and forks --> <project name="platform_build" path="build" remote="b2g" revision="4d1e85908d792d9468c4da7040acd191fbb51b40"> <copyfile dest="Makefile" src="core/root.mk"/> </project> <project name="fake-dalvik" path="dalvik" remote="b2g" revision="ca1f327d5acc198bb4be62fa51db2c039032c9ce"/> - <project name="gaia.git" path="gaia" remote="mozillaorg" revision="50666fa8bbbf3d346faff24f92ad8140a44a49d0"/> + <project name="gaia.git" path="gaia" remote="mozillaorg" revision="72262d054ffa5d0d2b5a0033f713149281511aea"/> <project name="gonk-misc" path="gonk-misc" remote="b2g" revision="f2f293787d4a86257c9e78a35bd3f73b31b706e2"/> <project name="rilproxy" path="rilproxy" remote="b2g" revision="827214fcf38d6569aeb5c6d6f31cb296d1f09272"/> <project name="librecovery" path="librecovery" remote="b2g" revision="891e5069c0ad330d8191bf8c7b879c814258c89f"/> <project name="moztt" path="external/moztt" remote="b2g" revision="562d357b72279a9e35d4af5aeecc8e1ffa2f44f1"/> <project name="apitrace" path="external/apitrace" remote="apitrace" revision="f3e998242fb9a857cf50f5bf3a02304a530ea617"/> <!-- Stock Android things --> <project name="platform/abi/cpp" path="abi/cpp" revision="6426040f1be4a844082c9769171ce7f5341a5528"/> <project name="platform/bionic" path="bionic" revision="d2eb6c7b6e1bc7643c17df2d9d9bcb1704d0b9ab"/>
--- a/b2g/config/helix/sources.xml +++ b/b2g/config/helix/sources.xml @@ -10,17 +10,17 @@ <!--original fetch url was https://git.mozilla.org/releases--> <remote fetch="https://git.mozilla.org/releases" name="mozillaorg"/> <default remote="caf" revision="b2g/ics_strawberry" sync-j="4"/> <!-- Gonk specific things and forks --> <project name="platform_build" path="build" remote="b2g" revision="4d1e85908d792d9468c4da7040acd191fbb51b40"> <copyfile dest="Makefile" src="core/root.mk"/> </project> <project name="fake-dalvik" path="dalvik" remote="b2g" revision="ca1f327d5acc198bb4be62fa51db2c039032c9ce"/> - <project name="gaia.git" path="gaia" remote="mozillaorg" revision="50666fa8bbbf3d346faff24f92ad8140a44a49d0"/> + <project name="gaia.git" path="gaia" remote="mozillaorg" revision="72262d054ffa5d0d2b5a0033f713149281511aea"/> <project name="gonk-misc" path="gonk-misc" remote="b2g" revision="f2f293787d4a86257c9e78a35bd3f73b31b706e2"/> <project name="rilproxy" path="rilproxy" remote="b2g" revision="827214fcf38d6569aeb5c6d6f31cb296d1f09272"/> <project name="librecovery" path="librecovery" remote="b2g" revision="891e5069c0ad330d8191bf8c7b879c814258c89f"/> <project name="moztt" path="external/moztt" remote="b2g" revision="562d357b72279a9e35d4af5aeecc8e1ffa2f44f1"/> <project name="gonk-patches" path="patches" remote="b2g" revision="223a2421006e8f5da33f516f6891c87cae86b0f6"/> <!-- Stock Android things --> <project name="platform/abi/cpp" path="abi/cpp" revision="6426040f1be4a844082c9769171ce7f5341a5528"/> <project name="platform/bionic" path="bionic" revision="d2eb6c7b6e1bc7643c17df2d9d9bcb1704d0b9ab"/>
--- a/b2g/config/nexus-4/sources.xml +++ b/b2g/config/nexus-4/sources.xml @@ -12,17 +12,17 @@ <!--original fetch url was https://git.mozilla.org/releases--> <remote fetch="https://git.mozilla.org/releases" name="mozillaorg"/> <!-- B2G specific things. --> <project name="platform_build" path="build" remote="b2g" revision="8986df0f82e15ac2798df0b6c2ee3435400677ac"> <copyfile dest="Makefile" src="core/root.mk"/> </project> <project name="rilproxy" path="rilproxy" remote="b2g" revision="827214fcf38d6569aeb5c6d6f31cb296d1f09272"/> <project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/> - <project name="gaia" path="gaia" remote="mozillaorg" revision="50666fa8bbbf3d346faff24f92ad8140a44a49d0"/> + <project name="gaia" path="gaia" remote="mozillaorg" revision="72262d054ffa5d0d2b5a0033f713149281511aea"/> <project name="gonk-misc" path="gonk-misc" remote="b2g" revision="f2f293787d4a86257c9e78a35bd3f73b31b706e2"/> <project name="moztt" path="external/moztt" remote="b2g" revision="562d357b72279a9e35d4af5aeecc8e1ffa2f44f1"/> <project name="apitrace" path="external/apitrace" remote="apitrace" revision="f3e998242fb9a857cf50f5bf3a02304a530ea617"/> <project name="valgrind" path="external/valgrind" remote="b2g" revision="daa61633c32b9606f58799a3186395fd2bbb8d8c"/> <project name="vex" path="external/VEX" remote="b2g" revision="47f031c320888fe9f3e656602588565b52d43010"/> <!-- Stock Android things --> <project groups="linux" name="platform/prebuilts/clang/linux-x86/3.1" path="prebuilts/clang/linux-x86/3.1" revision="5c45f43419d5582949284eee9cef0c43d866e03b"/> <project groups="linux" name="platform/prebuilts/clang/linux-x86/3.2" path="prebuilts/clang/linux-x86/3.2" revision="3748b4168e7bd8d46457d4b6786003bc6a5223ce"/>
--- a/b2g/config/wasabi/sources.xml +++ b/b2g/config/wasabi/sources.xml @@ -12,17 +12,17 @@ <!--original fetch url was git://github.com/apitrace/--> <remote fetch="https://git.mozilla.org/external/apitrace" name="apitrace"/> <default remote="caf" revision="ics_chocolate_rb4.2" sync-j="4"/> <!-- Gonk specific things and forks --> <project name="platform_build" path="build" remote="b2g" revision="4d1e85908d792d9468c4da7040acd191fbb51b40"> <copyfile dest="Makefile" src="core/root.mk"/> </project> <project name="fake-dalvik" path="dalvik" remote="b2g" revision="ca1f327d5acc198bb4be62fa51db2c039032c9ce"/> - <project name="gaia.git" path="gaia" remote="mozillaorg" revision="50666fa8bbbf3d346faff24f92ad8140a44a49d0"/> + <project name="gaia.git" path="gaia" remote="mozillaorg" revision="72262d054ffa5d0d2b5a0033f713149281511aea"/> <project name="gonk-misc" path="gonk-misc" remote="b2g" revision="f2f293787d4a86257c9e78a35bd3f73b31b706e2"/> <project name="rilproxy" path="rilproxy" remote="b2g" revision="827214fcf38d6569aeb5c6d6f31cb296d1f09272"/> <project name="librecovery" path="librecovery" remote="b2g" revision="891e5069c0ad330d8191bf8c7b879c814258c89f"/> <project name="moztt" path="external/moztt" remote="b2g" revision="562d357b72279a9e35d4af5aeecc8e1ffa2f44f1"/> <project name="apitrace" path="external/apitrace" remote="apitrace" revision="f3e998242fb9a857cf50f5bf3a02304a530ea617"/> <project name="gonk-patches" path="patches" remote="b2g" revision="223a2421006e8f5da33f516f6891c87cae86b0f6"/> <!-- Stock Android things --> <project name="platform/abi/cpp" path="abi/cpp" revision="6426040f1be4a844082c9769171ce7f5341a5528"/>
--- a/b2g/installer/package-manifest.in +++ b/b2g/installer/package-manifest.in @@ -433,25 +433,25 @@ @BINPATH@/components/ResourceStatsManager.js @BINPATH@/components/ResourceStatsManager.manifest #endif // MOZ_WIDGET_GONK ; RIL #if defined(MOZ_WIDGET_GONK) && defined(MOZ_B2G_RIL) @BINPATH@/components/MmsService.js @BINPATH@/components/MmsService.manifest -@BINPATH@/components/MobileConnectionService.js -@BINPATH@/components/MobileConnectionService.manifest @BINPATH@/components/MobileMessageDatabaseService.js @BINPATH@/components/MobileMessageDatabaseService.manifest @BINPATH@/components/RadioInterfaceLayer.js @BINPATH@/components/RadioInterfaceLayer.manifest @BINPATH@/components/RILContentHelper.js @BINPATH@/components/TelephonyService.js @BINPATH@/components/TelephonyService.manifest +@BINPATH@/components/MobileConnectionGonkService.js +@BINPATH@/components/MobileConnectionGonkService.manifest #endif // MOZ_WIDGET_GONK && MOZ_B2G_RIL #ifndef MOZ_WIDGET_GONK @BINPATH@/components/extensions.manifest @BINPATH@/components/addonManager.js @BINPATH@/components/amContentHandler.js @BINPATH@/components/amInstallTrigger.js @BINPATH@/components/amWebInstallListener.js
--- a/browser/base/content/browser-tabPreviews.js +++ b/browser/base/content/browser-tabPreviews.js @@ -42,16 +42,20 @@ var tabPreviews = { img.src = PageThumbs.getThumbnailURL(uri); return img; } return this.capture(aTab, !aTab.hasAttribute("busy")); }, capture: function tabPreviews_capture(aTab, aShouldCache) { + // Bug 863512 - Make page thumbnails work in electrolysis + if (gMultiProcessBrowser) + return new Image(); + let browser = aTab.linkedBrowser; let uri = browser.currentURI.spec; // FIXME: The gBrowserThumbnails._shouldCapture determines whether // thumbnails should be written to disk. This should somehow be part // of the PageThumbs API. (bug 1062414) if (aShouldCache && gBrowserThumbnails._shouldCapture(browser)) {
--- a/browser/base/content/browser.css +++ b/browser/base/content/browser.css @@ -1210,8 +1210,18 @@ toolbarpaletteitem[place="palette"][hidd animation-duration: 2s; } /* Combined context-menu items */ #context-navigation > .menuitem-iconic > .menu-iconic-text, #context-navigation > .menuitem-iconic > .menu-accel-container { display: none; } + +/* Tracking protection doorhanger */ +.popup-notification-footer[popupid="bad-content"] { + display: none; +} + +.popup-notification-footer[popupid="bad-content"][mixedblockdisabled], +.popup-notification-footer[popupid="bad-content"][trackingblockdisabled] { + display: block; +}
--- a/browser/base/content/browser.js +++ b/browser/base/content/browser.js @@ -4129,17 +4129,17 @@ var TabsProgressListener = { } } function nsBrowserAccess() { } nsBrowserAccess.prototype = { QueryInterface: XPCOMUtils.generateQI([Ci.nsIBrowserDOMWindow, Ci.nsISupports]), - _openURIInNewTab: function(aURI, aOpener, aIsExternal, aEnsureNonRemote=false) { + _openURIInNewTab: function(aURI, aOpener, aIsExternal) { let win, needToFocusWin; // try the current window. if we're in a popup, fall back on the most recent browser window if (window.toolbar.visible) win = window; else { let isPrivate = PrivateBrowsingUtils.isWindowPrivate(aOpener || window); win = RecentWindow.getMostRecentBrowserWindow({private: isPrivate}); @@ -4161,40 +4161,23 @@ nsBrowserAccess.prototype = { let referrer = aOpener ? makeURI(aOpener.location.href) : null; let tab = win.gBrowser.loadOneTab(aURI ? aURI.spec : "about:blank", { referrerURI: referrer, fromExternal: aIsExternal, inBackground: loadInBackground}); let browser = win.gBrowser.getBrowserForTab(tab); - // It's possible that we've been asked to open a new non-remote - // browser in a window that defaults to having remote browsers - - // this can happen if we're opening the new tab due to a window.open - // or _blank anchor in a non-remote browser. If so, we have to force - // the newly opened browser to also not be remote. - if (win.gMultiProcessBrowser && aEnsureNonRemote) { - win.gBrowser.updateBrowserRemoteness(browser, false); - } - if (needToFocusWin || (!loadInBackground && aIsExternal)) win.focus(); return browser; }, openURI: function (aURI, aOpener, aWhere, aContext) { - // This function should only ever be called if we're opening a URI - // from a non-remote browser window (via nsContentTreeOwner). - if (aOpener && Cu.isCrossProcessWrapper(aOpener)) { - Cu.reportError("nsBrowserAccess.openURI was passed a CPOW for aOpener. " + - "openURI should only ever be called from non-remote browsers."); - throw Cr.NS_ERROR_FAILURE; - } - var newWindow = null; var isExternal = (aContext == Ci.nsIBrowserDOMWindow.OPEN_EXTERNAL); if (isExternal && aURI && aURI.schemeIs("chrome")) { dump("use -chrome command-line option to load external chrome urls\n"); return null; } @@ -4210,17 +4193,17 @@ nsBrowserAccess.prototype = { // FIXME: Bug 408379. So how come this doesn't send the // referrer like the other loads do? var url = aURI ? aURI.spec : "about:blank"; // Pass all params to openDialog to ensure that "url" isn't passed through // loadOneOrMoreURIs, which splits based on "|" newWindow = openDialog(getBrowserURL(), "_blank", "all,dialog=no", url, null, null, null); break; case Ci.nsIBrowserDOMWindow.OPEN_NEWTAB : - let browser = this._openURIInNewTab(aURI, aOpener, isExternal, true); + let browser = this._openURIInNewTab(aURI, aOpener, isExternal); if (browser) newWindow = browser.contentWindow; break; default : // OPEN_CURRENTWINDOW or an illegal value newWindow = content; if (aURI) { let referrer = aOpener ? makeURI(aOpener.location.href) : null; let loadflags = isExternal ?
--- a/browser/base/content/searchSuggestionUI.css +++ b/browser/base/content/searchSuggestionUI.css @@ -20,29 +20,25 @@ .searchSuggestionRow { cursor: default; margin: 0; max-width: inherit; padding: 0; } -.searchSuggestionRow.formHistory { - color: hsl(210,100%,40%); +.searchSuggestionRow.formHistory + .searchSuggestionRow.remote > td { + border-top: 1px solid GrayText; } .searchSuggestionRow.selected { background-color: hsl(210,100%,40%); color: hsl(0,0%,100%); } .searchSuggestionEntry { margin: 0; max-width: inherit; overflow: hidden; padding: 6px 8px; text-overflow: ellipsis; white-space: nowrap; } - -.searchSuggestionEntry > span.typed { - font-weight: bold; -}
--- a/browser/base/content/searchSuggestionUI.js +++ b/browser/base/content/searchSuggestionUI.js @@ -218,23 +218,16 @@ SearchSuggestionUIController.prototype = _onFocus: function () { this._speculativeConnect(); }, _onBlur: function () { this._hideSuggestions(); }, - _onMousemove: function (event) { - // It's important to listen for mousemove, not mouseover or mouseenter. The - // latter two are triggered when the user is typing and the mouse happens to - // be over the suggestions popup. - this.selectedIndex = this._indexOfTableRowOrDescendent(event.target); - }, - _onMousedown: function (event) { let idx = this._indexOfTableRowOrDescendent(event.target); let suggestion = this.suggestionAtIndex(idx); this._stickyInputValue = suggestion; this.input.value = suggestion; this.input.setAttribute("selection-index", idx); this.input.setAttribute("selection-kind", "mouse"); this._hideSuggestions(); @@ -302,17 +295,16 @@ SearchSuggestionUIController.prototype = } }, _makeTableRow: function (type, suggestionStr, currentRow, searchWords) { let row = document.createElementNS(HTML_NS, "tr"); row.classList.add("searchSuggestionRow"); row.classList.add(type); row.setAttribute("role", "presentation"); - row.addEventListener("mousemove", this); row.addEventListener("mousedown", this); let entry = document.createElementNS(HTML_NS, "td"); entry.classList.add("searchSuggestionEntry"); entry.setAttribute("role", "option"); entry.id = this._idPrefix + SUGGESTION_ID_PREFIX + currentRow; entry.setAttribute("aria-selected", "false");
--- a/browser/base/content/test/general/browser.ini +++ b/browser/base/content/test/general/browser.ini @@ -478,10 +478,8 @@ skip-if = e10s # Bug 516755 - SessionSto skip-if = e10s [browser_bug1024133-switchtab-override-keynav.js] skip-if = e10s [browser_bug1025195_switchToTabHavingURI_ignoreFragment.js] [browser_addCertException.js] skip-if = e10s # Bug ?????? - test directly manipulates content (content.document.getElementById) [browser_bug1045809.js] skip-if = e10s -[browser_bug1047603.js] -skip-if = os == "linux" # Bug 1066856 - waiting for OMTC to be enabled by default on Linux.
deleted file mode 100644 --- a/browser/base/content/test/general/browser_bug1047603.js +++ /dev/null @@ -1,139 +0,0 @@ -/* Any copyright is dedicated to the Public Domain. - * http://creativecommons.org/publicdomain/zero/1.0/ - */ - -const OPEN_LOCATION_PREF = "browser.link.open_newwindow"; -const NON_REMOTE_PAGE = "about:crashes"; - -const SIMPLE_PAGE_HTML = ` -<a href="about:home" target="_blank" id="testAnchor">Open a window</a> -`; - -function frame_script() { - addMessageListener("test:click", (message) => { - let element = content.document.getElementById("testAnchor"); - element.click(); - }); - sendAsyncMessage("test:ready"); -} - -/** - * Returns a Promise that resolves once the frame_script is loaded - * in the browser, and has seen the DOMContentLoaded event. - */ -function waitForFrameScriptReady(mm) { - return new Promise((resolve, reject) => { - mm.addMessageListener("test:ready", function onTestReady() { - mm.removeMessageListener("test:ready", onTestReady); - resolve(); - }); - }); -} - -/** - * Takes some browser in some window, and forces that browser - * to become non-remote, and then navigates it to a page that - * we're not supposed to be displaying remotely. Returns a - * Promise that resolves when the browser is no longer remote. - */ -function prepareNonRemoteBrowser(aWindow, browser) { - aWindow.gBrowser.updateBrowserRemoteness(browser, false); - browser.loadURI(NON_REMOTE_PAGE); - return new Promise((resolve, reject) => { - waitForCondition(() => !browser.isRemoteBrowser, () => { - resolve(); - }, "Waiting for browser to become non-remote"); - }) -} - -registerCleanupFunction(() => { - Services.prefs.clearUserPref(OPEN_LOCATION_PREF); -}); - -/** - * Test that if we open a new tab from a link in a non-remote - * browser in an e10s window, that the new tab's browser is also - * not remote. Also tests with a private browsing window. - */ -add_task(function* test_new_tab() { - let normalWindow = yield promiseOpenAndLoadWindow({ - remote: true - }, true); - let privateWindow = yield promiseOpenAndLoadWindow({ - remote: true, - private: true, - }, true); - - for (let testWindow of [normalWindow, privateWindow]) { - let testBrowser = testWindow.gBrowser.selectedBrowser; - yield prepareNonRemoteBrowser(testWindow, testBrowser); - - // Get our framescript ready - let mm = testBrowser.messageManager; - mm.loadFrameScript("data:,(" + frame_script.toString() + ")();", true); - let readyPromise = waitForFrameScriptReady(mm); - yield readyPromise; - - // Inject our test HTML into our non-remote tab. - testBrowser.contentDocument.body.innerHTML = SIMPLE_PAGE_HTML; - - // Click on the link in the browser, and wait for the new tab. - mm.sendAsyncMessage("test:click"); - let tabOpenEvent = yield waitForNewTab(testWindow.gBrowser); - let newTab = tabOpenEvent.target; - ok(!newTab.linkedBrowser.isRemoteBrowser, - "The opened browser should not be remote."); - - testWindow.gBrowser.removeTab(newTab); - } - - normalWindow.close(); - privateWindow.close(); -}); - -/** - * Test that if we open a new window from a link in a non-remote - * browser in an e10s window, that the new window is not an e10s - * window. Also tests with a private browsing window. - */ -add_task(function* test_new_window() { - let normalWindow = yield promiseOpenAndLoadWindow({ - remote: true - }, true); - let privateWindow = yield promiseOpenAndLoadWindow({ - remote: true, - private: true, - }, true); - - // Fiddle with the prefs so that we open target="_blank" links - // in new windows instead of new tabs. - Services.prefs.setIntPref(OPEN_LOCATION_PREF, - Ci.nsIBrowserDOMWindow.OPEN_NEWWINDOW); - - for (let testWindow of [normalWindow, privateWindow]) { - let testBrowser = testWindow.gBrowser.selectedBrowser; - yield prepareNonRemoteBrowser(testWindow, testBrowser); - - // Get our framescript ready - let mm = testBrowser.messageManager; - mm.loadFrameScript("data:,(" + frame_script.toString() + ")();", true); - let readyPromise = waitForFrameScriptReady(mm); - yield readyPromise; - - // Inject our test HTML into our non-remote window. - testBrowser.contentDocument.body.innerHTML = SIMPLE_PAGE_HTML; - - // Click on the link in the browser, and wait for the new window. - let windowOpenPromise = promiseTopicObserved("browser-delayed-startup-finished"); - mm.sendAsyncMessage("test:click"); - let [newWindow] = yield windowOpenPromise; - ok(!newWindow.gMultiProcessBrowser, - "The opened window should not be an e10s window."); - newWindow.close(); - } - - normalWindow.close(); - privateWindow.close(); - - Services.prefs.clearUserPref(OPEN_LOCATION_PREF); -});
--- a/browser/base/content/test/general/browser_searchSuggestionUI.js +++ b/browser/base/content/test/general/browser_searchSuggestionUI.js @@ -97,24 +97,16 @@ add_task(rightArrowOrReturn("VK_RIGHT")) add_task(rightArrowOrReturn("VK_RETURN")); add_task(function* mouse() { yield setUp(); let state = yield msg("key", { key: "x", waitForSuggestions: true }); checkState(state, "x", ["xfoo", "xbar"], -1); - // Mouse over the first suggestion. - state = yield msg("mousemove", 0); - checkState(state, "xfoo", ["xfoo", "xbar"], 0); - - // Mouse over the second suggestion. - state = yield msg("mousemove", 1); - checkState(state, "xbar", ["xfoo", "xbar"], 1); - // Click the second suggestion. This should make it sticky. To make sure it // sticks, trigger suggestions again and cycle through them by pressing Down // until nothing is selected again. state = yield msg("mousedown", 1); checkState(state, "xbar", [], -1); state = yield msg("key", { key: "VK_DOWN", waitForSuggestions: true }); checkState(state, "xbar", ["xbarfoo", "xbarbar"], -1);
--- a/browser/base/content/test/general/head.js +++ b/browser/base/content/test/general/head.js @@ -665,12 +665,8 @@ function assertWebRTCIndicatorStatus(exp } } } function makeActionURI(action, params) { let url = "moz-action:" + action + "," + JSON.stringify(params); return NetUtil.newURI(url); } - -function waitForNewTab(aTabBrowser) { - return promiseWaitForEvent(aTabBrowser.tabContainer, "TabOpen"); -}
--- a/browser/base/content/test/general/searchSuggestionUI.js +++ b/browser/base/content/test/general/searchSuggestionUI.js @@ -32,43 +32,16 @@ let messageHandlers = { ack(); }, blur: function () { gController.input.blur(); ack(); }, - mousemove: function (suggestionIdx) { - // Copied from widget/tests/test_panel_mouse_coords.xul and - // browser/base/content/test/newtab/head.js - let row = gController._table.children[suggestionIdx]; - let rect = row.getBoundingClientRect(); - let left = content.mozInnerScreenX + rect.left; - let x = left + rect.width / 2; - let y = content.mozInnerScreenY + rect.top + rect.height / 2; - - let utils = content.SpecialPowers.getDOMWindowUtils(content); - let scale = utils.screenPixelsPerCSSPixel; - - let widgetToolkit = content.SpecialPowers. - Cc["@mozilla.org/xre/app-info;1"]. - getService(content.SpecialPowers.Ci.nsIXULRuntime). - widgetToolkit; - let nativeMsg = widgetToolkit == "cocoa" ? 5 : // NSMouseMoved - widgetToolkit == "windows" ? 1 : // MOUSEEVENTF_MOVE - 3; // GDK_MOTION_NOTIFY - - row.addEventListener("mousemove", function onMove() { - row.removeEventListener("mousemove", onMove); - ack(); - }); - utils.sendNativeMouseEvent(x * scale, y * scale, nativeMsg, 0, null); - }, - mousedown: function (suggestionIdx) { gController.onClick = () => { gController.onClick = null; ack(); }; let row = gController._table.children[suggestionIdx]; content.sendMouseEvent({ type: "mousedown" }, row); },
--- a/browser/base/content/test/social/browser.ini +++ b/browser/base/content/test/social/browser.ini @@ -1,10 +1,10 @@ [DEFAULT] -skip-if = buildapp == "mulet" || e10s # Bug 915547 (social providers don't install) +skip-if = buildapp == "mulet" support-files = blocklist.xml checked.jpg head.js opengraph/og_invalid_url.html opengraph/opengraph.html opengraph/shortlink_linkrel.html opengraph/shorturl_link.html @@ -21,26 +21,36 @@ support-files = social_postActivation.html social_sidebar.html social_sidebar_empty.html social_window.html social_worker.js unchecked.jpg [browser_aboutHome_activation.js] +skip-if = e10s # Bug 915547 (social providers don't install) [browser_addons.js] +skip-if = e10s # Bug 915547 (social providers don't install) [browser_blocklist.js] +skip-if = e10s # Bug 915547 (social providers don't install) [browser_share.js] +skip-if = e10s # Bug 915547 (social providers don't install) [browser_social_activation.js] +skip-if = e10s # Bug 915547 (social providers don't install) [browser_social_chatwindow.js] +skip-if = e10s # Bug 915547 (social providers don't install) [browser_social_chatwindow_resize.js] +skip-if = e10s # Bug 915547 (social providers don't install) [browser_social_chatwindowfocus.js] +skip-if = e10s # Bug 915547 (social providers don't install) [browser_social_errorPage.js] [browser_social_flyout.js] [browser_social_isVisible.js] [browser_social_marks.js] +skip-if = e10s # Bug 915547 (social providers don't install) [browser_social_multiprovider.js] [browser_social_multiworker.js] [browser_social_perwindowPB.js] [browser_social_sidebar.js] [browser_social_status.js] +skip-if = e10s # Bug 915547 (social providers don't install) [browser_social_window.js] [browser_social_workercrash.js]
--- a/browser/base/content/test/social/browser_social_errorPage.js +++ b/browser/base/content/test/social/browser_social_errorPage.js @@ -31,17 +31,20 @@ function goOnline(callback) { BrowserOffline.toggleOfflineStatus(); if (callback) callback(); } function openPanel(url, panelCallback, loadCallback) { // open a flyout SocialFlyout.open(url, 0, panelCallback); - SocialFlyout.panel.firstChild.addEventListener("load", function panelLoad() { + SocialFlyout.panel.firstChild.addEventListener("load", function panelLoad(evt) { + if (evt.target != SocialFlyout.panel.firstChild.contentDocument) { + return; + } SocialFlyout.panel.firstChild.removeEventListener("load", panelLoad, true); loadCallback(); }, true); } function openChat(url, panelCallback, loadCallback) { // open a chat window let chatbar = getChatBar(); @@ -140,18 +143,20 @@ var tests = { function() { // the panel api callback panelCallbackCount++; }, function() { // the "load" callback. executeSoon(function() { todo_is(panelCallbackCount, 0, "Bug 833207 - should be no callback when error page loads."); ok(panel.firstChild.contentDocument.location.href.indexOf("about:socialerror?")==0, "is on social error page"); gc(); - SocialFlyout.unload(); - next(); + executeSoon(function() { + SocialFlyout.unload(); + next(); + }); }); } ); }); } ); },
--- a/browser/base/content/test/social/browser_social_marks.js +++ b/browser/base/content/test/social/browser_social_marks.js @@ -68,17 +68,17 @@ function test() { }); }); } var tests = { testButtonDisabledOnActivate: function(next) { // starting on about:blank page, share should be visible but disabled when // adding provider - is(gBrowser.contentDocument.location.href, "about:blank"); + is(gBrowser.selectedTab.linkedBrowser.currentURI.spec, "about:blank"); SocialService.addProvider(manifest2, function(provider) { is(provider.origin, manifest2.origin, "provider is installed"); let id = SocialMarks._toolbarHelper.idFromOrigin(manifest2.origin); let widget = CustomizableUI.getWidget(id).forWindow(window) ok(widget.node, "button added to widget set"); // bypass widget go directly to dom, check attribute states let button = document.getElementById(id);
--- a/browser/base/content/test/social/browser_social_multiprovider.js +++ b/browser/base/content/test/social/browser_social_multiprovider.js @@ -79,15 +79,18 @@ var tests = { function checkUIStateMatchesProvider(provider) { // Sidebar is(document.getElementById("social-sidebar-browser").getAttribute("src"), provider.sidebarURL, "side bar URL is set"); } function onSidebarLoad(callback) { let sbrowser = document.getElementById("social-sidebar-browser"); - sbrowser.addEventListener("load", function load() { + sbrowser.addEventListener("load", function load(evt) { + if (evt.target != sbrowser.contentDocument) { + return; + } sbrowser.removeEventListener("load", load, true); // give the load a chance to finish before pulling the rug (ie. calling // next) executeSoon(callback); }, true); }
--- a/browser/base/content/urlbarBindings.xml +++ b/browser/base/content/urlbarBindings.xml @@ -1645,17 +1645,17 @@ <xul:separator class="groove"/> <xul:hbox align="start"> <xul:vbox> <xul:description class="popup-notification-item-title" xbl:inherits="popupid"> &mixedContentBlocked2.message; </xul:description> <xul:description class="popup-notification-item-message" - xbl:inherits="popupid"> + xbl:inherits="popupid,mixedblockdisabled"> &mixedContentBlocked2.moreinfo; </xul:description> <xul:label anonid="mixedContent.helplink" class="text-link plain" href="" value="&mixedContentBlocked2.learnMore;"/> </xul:vbox> <xul:button type="menu" label="&mixedContentBlocked2.options;" @@ -1667,34 +1667,33 @@ oncommand="document.getBindingParent(this).disableMixedContentProtection();"/> <xul:menuitem anonid="mixedContentAction.block" hidden="true" label="&mixedContentBlocked2.block.label;" accesskey="&mixedContentBlocked2.block.accesskey;" oncommand="document.getBindingParent(this).enableMixedContentProtection();"/> </xul:menupopup> </xul:button> </xul:hbox> - <xul:hbox anonid="mixedContentProtectionDisabled" hidden="true" - class="popup-notification-footer" xbl:inherits="popupid"> + <xul:hbox class="popup-notification-footer" xbl:inherits="popupid,mixedblockdisabled"> <xul:description class="popup-notification-item-message popup-notification-item-message-critical" xbl:inherits="popupid"> &mixedContentBlocked2.disabled.message; </xul:description> </xul:hbox> </xul:vbox> <!-- tracking content --> <xul:vbox anonid="trackingContent" hidden="true"> <xul:separator class="groove"/> <xul:hbox align="start"> <xul:vbox> <xul:description class="popup-notification-item-title" xbl:inherits="popupid"> &trackingContentBlocked.message; </xul:description> <xul:description class="popup-notification-item-message" - xbl:inherits="popupid"> + xbl:inherits="popupid,trackingblockdisabled"> &trackingContentBlocked.moreinfo; </xul:description> <xul:label anonid="trackingContent.helplink" class="text-link plain" href="" value="&trackingContentBlocked.learnMore;"/> </xul:vbox> <xul:button type="menu" label="&trackingContentBlocked.options;" @@ -1706,18 +1705,17 @@ oncommand="document.getBindingParent(this).disableTrackingContentProtection();"/> <xul:menuitem anonid="trackingContentAction.block" hidden="true" label="&trackingContentBlocked.block.label;" accesskey="&trackingContentBlocked.block.accesskey;" oncommand="document.getBindingParent(this).enableTrackingContentProtection();"/> </xul:menupopup> </xul:button> </xul:hbox> - <xul:hbox anonid="trackingContentProtectionDisabled" hidden="true" - class="popup-notification-footer" xbl:inherits="popupid"> + <xul:hbox class="popup-notification-footer" xbl:inherits="popupid,trackingblockdisabled"> <xul:description class="popup-notification-item-message popup-notification-item-message-critical" xbl:inherits="popupid"> &trackingContentBlocked.disabled.message; </xul:description> </xul:hbox> </xul:vbox> </xul:vbox> <xul:vbox pack="start"> <xul:toolbarbutton anonid="closebutton" @@ -1745,20 +1743,16 @@ <field name="_mixedContentUnblock"> document.getAnonymousElementByAttribute(this, "anonid", "mixedContentAction.unblock") </field> <field name="_mixedContentBlock"> document.getAnonymousElementByAttribute(this, "anonid", "mixedContentAction.block"); </field> - <field name="_mixedContentProtectionDisabledWarning"> - document.getAnonymousElementByAttribute(this, "anonid", - "mixedContentProtectionDisabled") - </field> <field name="_mixedContentHelpLink"> document.getAnonymousElementByAttribute(this, "anonid", "mixedContent.helplink") </field> <property name="isMixedContentBlocked" readonly="true"> <getter><![CDATA[ return this.notification.options.state & Ci.nsIWebProgressListener.STATE_BLOCKED_MIXED_ACTIVE_CONTENT; @@ -1771,20 +1765,16 @@ <field name="_trackingContentUnblock"> document.getAnonymousElementByAttribute(this, "anonid", "trackingContentAction.unblock") </field> <field name="_trackingContentBlock"> document.getAnonymousElementByAttribute(this, "anonid", "trackingContentAction.block"); </field> - <field name="_trackingContentProtectionDisabledWarning"> - document.getAnonymousElementByAttribute(this, "anonid", - "trackingContentProtectionDisabled") - </field> <field name="_trackingContentHelpLink"> document.getAnonymousElementByAttribute(this, "anonid", "trackingContent.helplink") </field> <property name="isTrackingContentBlocked" readonly="true"> <getter><![CDATA[ return this.notification.options.state & Ci.nsIWebProgressListener.STATE_BLOCKED_TRACKING_CONTENT; @@ -1804,39 +1794,39 @@ _mixedContent.hidden = false; _mixedContentUnblock.hidden = false; _mixedContentHelpLink.href = Services.urlFormatter.formatURLPref("app.support.baseURL") + "mixed-content"; } if (this.notification.options.state & Ci.nsIWebProgressListener.STATE_LOADED_MIXED_ACTIVE_CONTENT) { + this.setAttribute("mixedblockdisabled", true); _mixedContent.hidden = false; _mixedContentBlock.hidden = false; - _mixedContentProtectionDisabledWarning.hidden = false; _mixedContentHelpLink.href = Services.urlFormatter.formatURLPref("app.support.baseURL") + "mixed-content"; } if (this.notification.options.state & Ci.nsIWebProgressListener.STATE_BLOCKED_TRACKING_CONTENT) { _doorhangerTitle.value = gNavigatorBundle.getFormattedString( "badContentBlocked.blocked.message", [this._brandShortName]); - _trackingContent.hidden = false + _trackingContent.hidden = false; _trackingContentUnblock.hidden = false; _trackingContentHelpLink.href = Services.urlFormatter.formatURLPref("app.support.baseURL") + "tracking-protection"; } if (this.notification.options.state & Ci.nsIWebProgressListener.STATE_LOADED_TRACKING_CONTENT) { - _trackingContent.hidden = false + this.setAttribute("trackingblockdisabled", true); + _trackingContent.hidden = false; _trackingContentBlock.hidden = false; - _trackingContentProtectionDisabledWarning.hidden = false; _trackingContentHelpLink.href = Services.urlFormatter.formatURLPref("app.support.baseURL") + "tracking-protection"; } ]]></constructor> <method name="disableMixedContentProtection"> <body><![CDATA[ // Use telemetry to measure how often unblocking happens
--- a/browser/components/loop/MozLoopAPI.jsm +++ b/browser/components/loop/MozLoopAPI.jsm @@ -104,16 +104,33 @@ const injectObjectAPI = function(api, ta function injectLoopAPI(targetWindow) { let ringer; let ringerStopper; let appVersionInfo; let contactsAPI; let api = { /** + * Gets an object with data that represents the currently + * authenticated user's identity. + */ + userProfile: { + enumerable: true, + get: function() { + if (!MozLoopService.userProfile) + return null; + let userProfile = Cu.cloneInto({ + email: MozLoopService.userProfile.email, + uid: MozLoopService.userProfile.uid + }, targetWindow); + return userProfile; + } + }, + + /** * Sets and gets the "do not disturb" mode activation flag. */ doNotDisturb: { enumerable: true, get: function() { return MozLoopService.doNotDisturb; }, set: function(aFlag) { @@ -435,20 +452,34 @@ function injectLoopAPI(targetWindow) { OS: appInfo.OS }, targetWindow); } return appVersionInfo; } }, }; + function onStatusChanged(aSubject, aTopic, aData) { + let event = new targetWindow.CustomEvent("LoopStatusChanged"); + targetWindow.dispatchEvent(event) + }; + + function onDOMWindowDestroyed(aSubject, aTopic, aData) { + if (targetWindow && aSubject != targetWindow) + return; + Services.obs.removeObserver(onDOMWindowDestroyed, "dom-window-destroyed"); + Services.obs.removeObserver(onStatusChanged, "loop-status-changed"); + }; + let contentObj = Cu.createObjectIn(targetWindow); Object.defineProperties(contentObj, api); Object.seal(contentObj); Cu.makeObjectPropsNormal(contentObj); + Services.obs.addObserver(onStatusChanged, "loop-status-changed", false); + Services.obs.addObserver(onDOMWindowDestroyed, "dom-window-destroyed", false); targetWindow.navigator.wrappedJSObject.__defineGetter__("mozLoop", function() { // We do this in a getter, so that we create these objects // only on demand (this is a potential concern, since // otherwise we might add one per iframe, and keep them // alive for as long as the window is alive). delete targetWindow.navigator.wrappedJSObject.mozLoop; return targetWindow.navigator.wrappedJSObject.mozLoop = contentObj;
--- a/browser/components/loop/MozLoopService.jsm +++ b/browser/components/loop/MozLoopService.jsm @@ -41,16 +41,19 @@ XPCOMUtils.defineLazyModuleGetter(this, XPCOMUtils.defineLazyModuleGetter(this, "Chat", "resource:///modules/Chat.jsm"); XPCOMUtils.defineLazyModuleGetter(this, "CommonUtils", "resource://services-common/utils.js"); XPCOMUtils.defineLazyModuleGetter(this, "CryptoUtils", "resource://services-crypto/utils.js"); +XPCOMUtils.defineLazyModuleGetter(this, "FxAccountsProfileClient", + "resource://gre/modules/FxAccountsProfileClient.jsm"); + XPCOMUtils.defineLazyModuleGetter(this, "HawkClient", "resource://services-common/hawkclient.js"); XPCOMUtils.defineLazyModuleGetter(this, "deriveHawkCredentials", "resource://services-common/hawkrequest.js"); XPCOMUtils.defineLazyModuleGetter(this, "MozLoopPushHandler", "resource:///modules/loop/MozLoopPushHandler.jsm"); @@ -71,16 +74,17 @@ let gRegisteredDeferred = null; let gPushHandler = null; let gHawkClient = null; let gRegisteredLoopServer = false; let gLocalizedStrings = null; let gInitializeTimer = null; let gFxAOAuthClientPromise = null; let gFxAOAuthClient = null; let gFxAOAuthTokenData = null; +let gFxAOAuthProfile = null; let gErrors = new Map(); /** * Internal helper methods and state * * The registration is a two-part process. First we need to connect to * and register with the push server. Then we need to take the result of that * and register with the Loop server. @@ -879,16 +883,20 @@ this.MozLoopService = { * Sets MozLoopService "do not disturb" value. * * @param {Boolean} aFlag */ set doNotDisturb(aFlag) { MozLoopServiceInternal.doNotDisturb = aFlag; }, + get userProfile() { + return gFxAOAuthProfile; + }, + get errors() { return MozLoopServiceInternal.errors; }, /** * Returns the current locale * * @return {String} The code of the current locale. @@ -999,19 +1007,33 @@ this.MozLoopService = { return gRegisteredDeferred.promise.then(Task.async(function*() { if (gPushHandler.pushUrl) { yield MozLoopServiceInternal.registerWithLoopServer(LOOP_SESSION_TYPE.FXA, gPushHandler.pushUrl); } else { throw new Error("No pushUrl for FxA registration"); } return gFxAOAuthTokenData; })); - }, - error => { + }).then(tokenData => { + let client = new FxAccountsProfileClient({ + serverURL: gFxAOAuthClient.parameters.profile_uri, + token: tokenData.access_token + }); + client.fetchProfile().then(result => { + gFxAOAuthProfile = result; + MozLoopServiceInternal.notifyStatusChanged(); + }, error => { + console.error("Failed to retrieve profile", error); + gFxAOAuthProfile = null; + MozLoopServiceInternal.notifyStatusChanged(); + }); + return tokenData; + }).catch(error => { gFxAOAuthTokenData = null; + gFxAOAuthProfile = null; throw error; }); }, /** * Performs a hawk based request to the loop server. * * @param {LOOP_SESSION_TYPE} sessionType The type of session to use for the request.
--- a/browser/components/loop/content/js/panel.js +++ b/browser/components/loop/content/js/panel.js @@ -224,18 +224,17 @@ loop.panel = (function(_, mozL10n) { // XXX to be implemented - bug 979845 navigator.mozLoop.logOutFromFxA(); } else { navigator.mozLoop.logInToFxA(); } }, _isSignedIn: function() { - // XXX to be implemented - bug 979845 - return !!navigator.mozLoop.loggedInToFxA; + return !!navigator.mozLoop.userProfile; }, render: function() { var cx = React.addons.classSet; return ( React.DOM.div({className: "settings-menu dropdown"}, React.DOM.a({className: "btn btn-settings", onClick: this.showDropdownMenu, title: __("settings_menu_button_tooltip")}), @@ -444,46 +443,82 @@ loop.panel = (function(_, mozL10n) { __("panel_footer_signin_or_signup_link") ) ) ); } }); /** + * FxA user identity (guest/authenticated) component. + */ + var UserIdentity = React.createClass({displayName: 'UserIdentity', + render: function() { + return ( + React.DOM.p({className: "user-identity"}, + this.props.displayName + ) + ); + } + }); + + /** * Panel view. */ var PanelView = React.createClass({displayName: 'PanelView', propTypes: { notifications: React.PropTypes.object.isRequired, client: React.PropTypes.object.isRequired, // Mostly used for UI components showcase and unit tests - callUrl: React.PropTypes.string + callUrl: React.PropTypes.string, + userProfile: React.PropTypes.object, + }, + + getInitialState: function() { + return { + userProfile: this.props.userProfile || navigator.mozLoop.userProfile, + }; + }, + + _onAuthStatusChange: function() { + this.setState({userProfile: navigator.mozLoop.userProfile}); + }, + + componentDidMount: function() { + window.addEventListener("LoopStatusChanged", this._onAuthStatusChange); + }, + + componentWillUnmount: function() { + window.removeEventListener("LoopStatusChanged", this._onAuthStatusChange); }, render: function() { var NotificationListView = sharedViews.NotificationListView; - + var displayName = this.state.userProfile && this.state.userProfile.email || + __("display_name_guest"); return ( React.DOM.div(null, NotificationListView({notifications: this.props.notifications, clearOnDocumentHidden: true}), TabView({onSelect: this.selectTab}, Tab({name: "call"}, CallUrlResult({client: this.props.client, notifications: this.props.notifications, callUrl: this.props.callUrl}), ToSView(null) ), Tab({name: "contacts"}, React.DOM.span(null, "contacts") ) ), React.DOM.div({className: "footer"}, - AvailabilityDropdown(null), + React.DOM.div({className: "user-details"}, + UserIdentity({displayName: displayName}), + AvailabilityDropdown(null) + ), AuthLink(null), SettingsDropdown(null) ) ) ); } }); @@ -538,16 +573,17 @@ loop.panel = (function(_, mozL10n) { // Notify the window that we've finished initalization and initial layout var evtObject = document.createEvent('Event'); evtObject.initEvent('loopPanelInitialized', true, false); window.dispatchEvent(evtObject); } return { init: init, + UserIdentity: UserIdentity, AvailabilityDropdown: AvailabilityDropdown, CallUrlResult: CallUrlResult, PanelView: PanelView, PanelRouter: PanelRouter, SettingsDropdown: SettingsDropdown, ToSView: ToSView }; })(_, document.mozL10n);
--- a/browser/components/loop/content/js/panel.jsx +++ b/browser/components/loop/content/js/panel.jsx @@ -224,18 +224,17 @@ loop.panel = (function(_, mozL10n) { // XXX to be implemented - bug 979845 navigator.mozLoop.logOutFromFxA(); } else { navigator.mozLoop.logInToFxA(); } }, _isSignedIn: function() { - // XXX to be implemented - bug 979845 - return !!navigator.mozLoop.loggedInToFxA; + return !!navigator.mozLoop.userProfile; }, render: function() { var cx = React.addons.classSet; return ( <div className="settings-menu dropdown"> <a className="btn btn-settings" onClick={this.showDropdownMenu} title={__("settings_menu_button_tooltip")} /> @@ -444,46 +443,82 @@ loop.panel = (function(_, mozL10n) { {__("panel_footer_signin_or_signup_link")} </a> </p> ); } }); /** + * FxA user identity (guest/authenticated) component. + */ + var UserIdentity = React.createClass({ + render: function() { + return ( + <p className="user-identity"> + {this.props.displayName} + </p> + ); + } + }); + + /** * Panel view. */ var PanelView = React.createClass({ propTypes: { notifications: React.PropTypes.object.isRequired, client: React.PropTypes.object.isRequired, // Mostly used for UI components showcase and unit tests - callUrl: React.PropTypes.string + callUrl: React.PropTypes.string, + userProfile: React.PropTypes.object, + }, + + getInitialState: function() { + return { + userProfile: this.props.userProfile || navigator.mozLoop.userProfile, + }; + }, + + _onAuthStatusChange: function() { + this.setState({userProfile: navigator.mozLoop.userProfile}); + }, + + componentDidMount: function() { + window.addEventListener("LoopStatusChanged", this._onAuthStatusChange); + }, + + componentWillUnmount: function() { + window.removeEventListener("LoopStatusChanged", this._onAuthStatusChange); }, render: function() { var NotificationListView = sharedViews.NotificationListView; - + var displayName = this.state.userProfile && this.state.userProfile.email || + __("display_name_guest"); return ( <div> <NotificationListView notifications={this.props.notifications} clearOnDocumentHidden={true} /> <TabView onSelect={this.selectTab}> <Tab name="call"> <CallUrlResult client={this.props.client} notifications={this.props.notifications} callUrl={this.props.callUrl} /> <ToSView /> </Tab> <Tab name="contacts"> <span>contacts</span> </Tab> </TabView> <div className="footer"> - <AvailabilityDropdown /> + <div className="user-details"> + <UserIdentity displayName={displayName} /> + <AvailabilityDropdown /> + </div> <AuthLink /> <SettingsDropdown /> </div> </div> ); } }); @@ -538,16 +573,17 @@ loop.panel = (function(_, mozL10n) { // Notify the window that we've finished initalization and initial layout var evtObject = document.createEvent('Event'); evtObject.initEvent('loopPanelInitialized', true, false); window.dispatchEvent(evtObject); } return { init: init, + UserIdentity: UserIdentity, AvailabilityDropdown: AvailabilityDropdown, CallUrlResult: CallUrlResult, PanelView: PanelView, PanelRouter: PanelRouter, SettingsDropdown: SettingsDropdown, ToSView: ToSView }; })(_, document.mozL10n);
--- a/browser/components/loop/standalone/.gitignore +++ b/browser/components/loop/standalone/.gitignore @@ -6,9 +6,9 @@ content/config.js content/VERSION.txt # XXX Once a grunt contrib-clean command has been added (bug 1066491), or # once legal has centralized their ToS and PP hosting infrastructure, # (expected Q4 2014) the legal doc build stuff for Loop can be removed, # including the following three lines: content/legal/styles/*.css content/legal/terms/*.html -content/legal/terms/!index.html +!content/legal/terms/index.html
--- a/browser/components/loop/test/desktop-local/panel_test.js +++ b/browser/components/loop/test/desktop-local/panel_test.js @@ -135,17 +135,17 @@ describe("loop.panel", function() { TestUtils.Simulate.click(availableMenuOption); expect(view.state.showMenu).eql(true); }); }); }); describe("loop.panel.PanelView", function() { - var fakeClient, callUrlData, view; + var fakeClient, callUrlData, view, callTab, contactsTab; beforeEach(function() { callUrlData = { callUrl: "http://call.invalid/", expiresAt: 1000 }; fakeClient = { @@ -153,16 +153,37 @@ describe("loop.panel", function() { cb(null, callUrlData); } }; view = TestUtils.renderIntoDocument(loop.panel.PanelView({ notifications: notifications, client: fakeClient })); + + [callTab, contactsTab] = + TestUtils.scryRenderedDOMComponentsWithClass(view, "tab"); + }); + + describe('TabView', function() { + it("should select contacts tab when clicking tab button", function() { + TestUtils.Simulate.click( + view.getDOMNode().querySelector('li[data-tab-name="contacts"]')); + + expect(contactsTab.getDOMNode().classList.contains("selected")) + .to.be.true; + }); + + it("should select call tab when clicking tab button", function() { + TestUtils.Simulate.click( + view.getDOMNode().querySelector('li[data-tab-name="call"]')); + + expect(callTab.getDOMNode().classList.contains("selected")) + .to.be.true; + }); }); describe("AuthLink", function() { it("should trigger the FxA sign in/up process when clicking the link", function() { navigator.mozLoop.loggedInToFxA = false; navigator.mozLoop.logInToFxA = sandbox.stub(); @@ -189,28 +210,28 @@ describe("loop.panel", function() { expect(view.getDOMNode().querySelectorAll(".icon-signout")) .to.have.length.of(0); expect(view.getDOMNode().querySelectorAll(".icon-signin")) .to.have.length.of(1); }); it("should show a signout entry when user is authenticated", function() { - navigator.mozLoop.loggedInToFxA = true; + navigator.mozLoop.userProfile = {email: "test@example.com"}; var view = TestUtils.renderIntoDocument(loop.panel.SettingsDropdown()); expect(view.getDOMNode().querySelectorAll(".icon-signout")) .to.have.length.of(1); expect(view.getDOMNode().querySelectorAll(".icon-signin")) .to.have.length.of(0); }); it("should show an account entry when user is authenticated", function() { - navigator.mozLoop.loggedInToFxA = true; + navigator.mozLoop.userProfile = {email: "test@example.com"}; var view = TestUtils.renderIntoDocument(loop.panel.SettingsDropdown()); expect(view.getDOMNode().querySelectorAll(".icon-account")) .to.have.length.of(1); }); it("should hide any account entry when user is not authenticated", @@ -229,17 +250,17 @@ describe("loop.panel", function() { TestUtils.Simulate.click( view.getDOMNode().querySelector(".icon-signin")); sinon.assert.calledOnce(navigator.mozLoop.logInToFxA); }); it("should sign out the user on click when authenticated", function() { - navigator.mozLoop.loggedInToFxA = true; + navigator.mozLoop.userProfile = {email: "test@example.com"}; var view = TestUtils.renderIntoDocument(loop.panel.SettingsDropdown()); TestUtils.Simulate.click( view.getDOMNode().querySelector(".icon-signout")); sinon.assert.calledOnce(navigator.mozLoop.logOutFromFxA); }); });
--- a/browser/components/loop/test/mochitest/browser_fxa_login.js +++ b/browser/components/loop/test/mochitest/browser_fxa_login.js @@ -4,16 +4,17 @@ /** * Test FxA logins with Loop. */ "use strict"; const { gFxAOAuthTokenData, + gFxAOAuthProfile, } = Cu.import("resource:///modules/loop/MozLoopService.jsm", {}); const BASE_URL = "http://mochi.test:8888/browser/browser/components/loop/test/mochitest/loop_fxa.sjs?"; add_task(function* setup() { Services.prefs.setCharPref("loop.server", BASE_URL); Services.prefs.setCharPref("services.push.serverURL", "ws://localhost/"); registerCleanupFunction(function* () { @@ -219,21 +220,32 @@ add_task(function* basicAuthorizationAnd info("registering"); mockPushHandler.pushUrl = "https://localhost/pushUrl/guest"; yield MozLoopService.register(mockPushHandler); // Normally the same pushUrl would be registered but we change it in the test // to be able to check for success on the second registration. mockPushHandler.pushUrl = "https://localhost/pushUrl/fxa"; + yield loadLoopPanel({loopURL: BASE_URL, stayOnline: true}); + let loopDoc = document.getElementById("loop").contentDocument; + let visibleEmail = loopDoc.getElementsByClassName("user-identity")[0]; + is(visibleEmail.textContent, "Guest", "Guest should be displayed on the panel when not logged in"); + is(MozLoopService.userProfile, null, "profile should be null before log-in"); + let tokenData = yield MozLoopService.logInToFxA(); + yield promiseObserverNotified("loop-status-changed"); ise(tokenData.access_token, "code1_access_token", "Check access_token"); ise(tokenData.scope, "profile", "Check scope"); ise(tokenData.token_type, "bearer", "Check token_type"); + is(MozLoopService.userProfile.email, "test@example.com", "email should exist in the profile data"); + is(MozLoopService.userProfile.uid, "1234abcd", "uid should exist in the profile data"); + is(visibleEmail.textContent, "test@example.com", "the email should be correct on the panel"); + let registrationResponse = yield promiseOAuthGetRegistration(BASE_URL); ise(registrationResponse.response.simplePushURL, "https://localhost/pushUrl/fxa", "Check registered push URL"); }); add_task(function* loginWithParams401() { resetFxA(); let params = { client_id: "client_id",
--- a/browser/components/loop/test/mochitest/head.js +++ b/browser/components/loop/test/mochitest/head.js @@ -53,27 +53,29 @@ function promiseGetMozLoopAPI() { } /** * Loads the loop panel by clicking the button and waits for its open to complete. * It also registers * * This assumes that the tests are running in a generatorTest. */ -function loadLoopPanel() { +function loadLoopPanel(aOverrideOptions = {}) { // Set prefs to ensure we don't access the network externally. - Services.prefs.setCharPref("services.push.serverURL", "ws://localhost/"); - Services.prefs.setCharPref("loop.server", "http://localhost/"); + Services.prefs.setCharPref("services.push.serverURL", aOverrideOptions.pushURL || "ws://localhost/"); + Services.prefs.setCharPref("loop.server", aOverrideOptions.loopURL || "http://localhost/"); // Turn off the network for loop tests, so that we don't // try to access the remote servers. If we want to turn this // back on in future, be careful to check for intermittent // failures. let wasOffline = Services.io.offline; - Services.io.offline = true; + if (!aOverrideOptions.stayOnline) { + Services.io.offline = true; + } registerCleanupFunction(function() { Services.prefs.clearUserPref("services.push.serverURL"); Services.prefs.clearUserPref("loop.server"); Services.io.offline = wasOffline; }); // Turn off animations to make tests quicker. @@ -98,32 +100,42 @@ function promiseOAuthParamsSetup(baseURL } function resetFxA() { let global = Cu.import("resource:///modules/loop/MozLoopService.jsm", {}); global.gHawkClient = null; global.gFxAOAuthClientPromise = null; global.gFxAOAuthClient = null; global.gFxAOAuthTokenData = null; + global.gFxAOAuthProfile = null; const fxASessionPref = MozLoopServiceInternal.getSessionTokenPrefName(LOOP_SESSION_TYPE.FXA); Services.prefs.clearUserPref(fxASessionPref); } function promiseDeletedOAuthParams(baseURL) { let deferred = Promise.defer(); let xhr = Cc["@mozilla.org/xmlextras/xmlhttprequest;1"]. createInstance(Ci.nsIXMLHttpRequest); xhr.open("DELETE", baseURL + "/setup_params", true); xhr.addEventListener("load", () => deferred.resolve(xhr)); xhr.addEventListener("error", deferred.reject); xhr.send(); return deferred.promise; } +function promiseObserverNotified(aTopic) { + let deferred = Promise.defer(); + Services.obs.addObserver(function onNotification(aSubject, aTopic, aData) { + Services.obs.removeObserver(onNotification, aTopic); + deferred.resolve({subject: aSubject, data: aData}); + }, aTopic, false); + return deferred.promise; +} + /** * Get the last registration on the test server. */ function promiseOAuthGetRegistration(baseURL) { let deferred = Promise.defer(); let xhr = Cc["@mozilla.org/xmlextras/xmlhttprequest;1"]. createInstance(Ci.nsIXMLHttpRequest); xhr.open("GET", baseURL + "/get_registration", true);
--- a/browser/components/loop/test/mochitest/loop_fxa.sjs +++ b/browser/components/loop/test/mochitest/loop_fxa.sjs @@ -32,29 +32,32 @@ function handleRequest(request, response token(request, response); return; case "/registration": registration(request, response); return; case "/get_registration": // Test-only get_registration(request, response); return; + case "/profile/profile": + profile(request, response); + return; } response.setStatusLine(request.httpVersion, 404, "Not Found"); } /** * POST /setup_params * DELETE /setup_params * * Test-only endpoint to setup the /fxa-oauth/params response. * * For a POST the X-Params header should contain a JSON object with keys to set for /fxa-oauth/params. * A DELETE request will delete the stored parameters and should be run in a cleanup function to - * avoid interfering with subsequen tests. + * avoid interfering with subsequent tests. */ function setup_params(request, response) { response.setHeader("Content-Type", "text/plain", false); if (request.method == "DELETE") { setSharedState("/fxa-oauth/params", ""); setSharedState("/registration", ""); response.write("Params deleted"); return; @@ -162,16 +165,29 @@ function token(request, response) { scope: "profile", token_type: "bearer", }; response.setHeader("Content-Type", "application/json; charset=utf-8", false); response.write(JSON.stringify(tokenData, null, 2)); } /** + * GET /profile + * + */ +function profile(request, response) { + response.setHeader("Content-Type", "application/json; charset=utf-8", false); + let profile = { + email: "test@example.com", + uid: "1234abcd", + }; + response.write(JSON.stringify(profile, null, 2)); +} + +/** * POST /registration * * Mock Loop registration endpoint. Hawk Authorization headers are expected only for FxA sessions. */ function registration(request, response) { let body = NetUtil.readInputStreamToString(request.bodyInputStream, request.bodyInputStream.available()); let payload = JSON.parse(body);
--- a/browser/components/loop/ui/ui-showcase.js +++ b/browser/components/loop/ui/ui-showcase.js @@ -121,21 +121,34 @@ Section({name: "PanelView"}, React.DOM.p({className: "note"}, React.DOM.strong(null, "Note:"), " 332px wide." ), Example({summary: "Call URL retrieved", dashed: "true", style: {width: "332px"}}, PanelView({client: mockClient, notifications: notifications, callUrl: "http://invalid.example.url/"}) ), + Example({summary: "Call URL retrieved - authenticated", dashed: "true", style: {width: "332px"}}, + PanelView({client: mockClient, notifications: notifications, + callUrl: "http://invalid.example.url/", + userProfile: {email: "test@example.com"}}) + ), Example({summary: "Pending call url retrieval", dashed: "true", style: {width: "332px"}}, PanelView({client: mockClient, notifications: notifications}) ), + Example({summary: "Pending call url retrieval - authenticated", dashed: "true", style: {width: "332px"}}, + PanelView({client: mockClient, notifications: notifications, + userProfile: {email: "test@example.com"}}) + ), Example({summary: "Error Notification", dashed: "true", style: {width: "332px"}}, PanelView({client: mockClient, notifications: errNotifications}) + ), + Example({summary: "Error Notification - authenticated", dashed: "true", style: {width: "332px"}}, + PanelView({client: mockClient, notifications: errNotifications, + userProfile: {email: "test@example.com"}}) ) ), Section({name: "IncomingCallView"}, Example({summary: "Default / incoming video call", dashed: "true", style: {width: "280px"}}, React.DOM.div({className: "fx-embedded"}, IncomingCallView({model: mockConversationModel, video: {enabled: true}})
--- a/browser/components/loop/ui/ui-showcase.jsx +++ b/browser/components/loop/ui/ui-showcase.jsx @@ -121,22 +121,35 @@ <Section name="PanelView"> <p className="note"> <strong>Note:</strong> 332px wide. </p> <Example summary="Call URL retrieved" dashed="true" style={{width: "332px"}}> <PanelView client={mockClient} notifications={notifications} callUrl="http://invalid.example.url/" /> </Example> + <Example summary="Call URL retrieved - authenticated" dashed="true" style={{width: "332px"}}> + <PanelView client={mockClient} notifications={notifications} + callUrl="http://invalid.example.url/" + userProfile={{email: "test@example.com"}} /> + </Example> <Example summary="Pending call url retrieval" dashed="true" style={{width: "332px"}}> <PanelView client={mockClient} notifications={notifications} /> </Example> + <Example summary="Pending call url retrieval - authenticated" dashed="true" style={{width: "332px"}}> + <PanelView client={mockClient} notifications={notifications} + userProfile={{email: "test@example.com"}} /> + </Example> <Example summary="Error Notification" dashed="true" style={{width: "332px"}}> <PanelView client={mockClient} notifications={errNotifications}/> </Example> + <Example summary="Error Notification - authenticated" dashed="true" style={{width: "332px"}}> + <PanelView client={mockClient} notifications={errNotifications} + userProfile={{email: "test@example.com"}} /> + </Example> </Section> <Section name="IncomingCallView"> <Example summary="Default / incoming video call" dashed="true" style={{width: "280px"}}> <div className="fx-embedded"> <IncomingCallView model={mockConversationModel} video={{enabled: true}} /> </div>
--- a/browser/components/places/content/editBookmarkOverlay.xul +++ b/browser/components/places/content/editBookmarkOverlay.xul @@ -144,17 +144,19 @@ type="autocomplete" class="padded" flex="1" autocompletesearch="places-tag-autocomplete" completedefaultindex="true" tabscrolling="true" showcommentcolumn="true" observes="paneElementsBroadcaster" - placeholder="&editBookmarkOverlay.tagsEmptyDesc.label;"/> + placeholder="&editBookmarkOverlay.tagsEmptyDesc.label;" + maxlength="1000" + /> <button id="editBMPanel_tagsSelectorExpander" class="expander-down" tooltiptext="&editBookmarkOverlay.tagsExpanderDown.tooltip;" tooltiptextdown="&editBookmarkOverlay.tagsExpanderDown.tooltip;" tooltiptextup="&editBookmarkOverlay.expanderUp.tooltip;" oncommand="gEditItemOverlay.toggleTagsSelector();" observes="paneElementsBroadcaster"/> </hbox>
--- a/browser/components/places/content/moveBookmarks.js +++ b/browser/components/places/content/moveBookmarks.js @@ -46,18 +46,18 @@ var gMoveBookmarksDialog = { } PlacesTransactions.transact(function* () { let newParentGUID = yield PlacesUtils.promiseItemGUID(selectedFolderId); for (let node of this._nodes) { // Nothing to do if the node is already under the selected folder. if (node.parent.itemId == selectedFolderId) continue; - yield PlacesTransactions.MoveItem({ GUID: node.bookmarkGuid - , newParentGUID: newParentGUID }); + yield PlacesTransactions.Move({ GUID: node.bookmarkGuid + , newParentGUID: newParentGUID }); } }.bind(this)).then(null, Components.utils.reportError); }, newFolder: function MBD_newFolder() { // The command is disabled when the tree is not focused this.foldersTree.focus(); goDoCommand("placesCmd_new:folder");
--- a/browser/themes/shared/badcontent-doorhanger.inc.css +++ b/browser/themes/shared/badcontent-doorhanger.inc.css @@ -1,16 +1,21 @@ .popup-notification-item-title[popupid="bad-content"] { font-weight: bold; } .popup-notification-item-message[popupid="bad-content"] { width: 17em; } +.popup-notification-item-message[popupid="bad-content"][mixedblockdisabled]:not(.popup-notification-item-message-critical), +.popup-notification-item-message[popupid="bad-content"][trackingblockdisabled]:not(.popup-notification-item-message-critical) { + color: GrayText; +} + .popup-notification-item-message-critical[popupid="bad-content"] { color: #d74345; font-style: italic; } .popup-notification-footer[popupid="bad-content"] { padding-top: 1em; }
--- a/browser/themes/shared/incontentprefs/preferences.css +++ b/browser/themes/shared/incontentprefs/preferences.css @@ -18,16 +18,26 @@ prefwindow, prefpane { max-width: 800px; padding: 0; font: message-box; font-size: 1.25rem; line-height: 22px; } +* { + -moz-user-select: text; +} + +button, +treecol { + /* override the * rule */ + -moz-user-select: none; +} + /* Category List */ .category-icon { list-style-image: url("chrome://browser/skin/preferences/in-content/icons.png"); } #category-general > .category-icon { -moz-image-region: rect(0, 24px, 24px, 0);
--- a/content/media/CubebUtils.cpp +++ b/content/media/CubebUtils.cpp @@ -1,50 +1,37 @@ /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ /* vim:set ts=2 sw=2 sts=2 et cindent: */ /* 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 <stdint.h> #include <algorithm> -#include "mozilla/Atomics.h" #include "mozilla/Preferences.h" -#include "mozilla/StaticMutex.h" #include "CubebUtils.h" -#include "nsAutoRef.h" #include "prdtoa.h" #define PREF_VOLUME_SCALE "media.volume_scale" #define PREF_CUBEB_LATENCY "media.cubeb_latency_ms" namespace mozilla { -namespace { - -// Prefered samplerate, in Hz (characteristic of the -// hardware/mixer/platform/API used). -Atomic<uint32_t> sPreferredSampleRate; - -// This mutex protects the variables below. -StaticMutex sMutex; -cubeb* sCubebContext; -double sVolumeScale; -uint32_t sCubebLatency; -bool sCubebLatencyPrefSet; - -} // anonymous namespace - extern PRLogModuleInfo* gAudioStreamLog; static const uint32_t CUBEB_NORMAL_LATENCY_MS = 100; -namespace CubebUtils { +StaticMutex CubebUtils::sMutex; +cubeb* CubebUtils::sCubebContext; +uint32_t CubebUtils::sPreferredSampleRate; +double CubebUtils::sVolumeScale; +uint32_t CubebUtils::sCubebLatency; +bool CubebUtils::sCubebLatencyPrefSet; -void PrefChanged(const char* aPref, void* aClosure) +/*static*/ void CubebUtils::PrefChanged(const char* aPref, void* aClosure) { if (strcmp(aPref, PREF_VOLUME_SCALE) == 0) { nsAdoptingString value = Preferences::GetString(aPref); StaticMutexAutoLock lock(sMutex); if (value.IsEmpty()) { sVolumeScale = 1.0; } else { NS_ConvertUTF16toUTF8 utf8(value); @@ -56,123 +43,116 @@ void PrefChanged(const char* aPref, void // audible. sCubebLatencyPrefSet = Preferences::HasUserValue(aPref); uint32_t value = Preferences::GetUint(aPref, CUBEB_NORMAL_LATENCY_MS); StaticMutexAutoLock lock(sMutex); sCubebLatency = std::min<uint32_t>(std::max<uint32_t>(value, 1), 1000); } } -bool GetFirstStream() +/*static*/ bool CubebUtils::GetFirstStream() { static bool sFirstStream = true; StaticMutexAutoLock lock(sMutex); bool result = sFirstStream; sFirstStream = false; return result; } -double GetVolumeScale() +/*static*/ double CubebUtils::GetVolumeScale() { StaticMutexAutoLock lock(sMutex); return sVolumeScale; } -cubeb* GetCubebContext() +/*static*/ cubeb* CubebUtils::GetCubebContext() { StaticMutexAutoLock lock(sMutex); return GetCubebContextUnlocked(); } -void InitPreferredSampleRate() +/*static*/ void CubebUtils::InitPreferredSampleRate() { - // The mutex is used here to prohibit concurrent initialization calls, but - // sPreferredSampleRate itself is safe to access without the mutex because - // it is using atomic storage. StaticMutexAutoLock lock(sMutex); - uint32_t preferredSampleRate = 0; if (sPreferredSampleRate == 0 && cubeb_get_preferred_sample_rate(GetCubebContextUnlocked(), - &preferredSampleRate) == CUBEB_OK) { - sPreferredSampleRate = preferredSampleRate; - } else { - // Query failed, use a sensible default. + &sPreferredSampleRate) != CUBEB_OK) { sPreferredSampleRate = 44100; } } -cubeb* GetCubebContextUnlocked() +/*static*/ cubeb* CubebUtils::GetCubebContextUnlocked() { sMutex.AssertCurrentThreadOwns(); if (sCubebContext || cubeb_init(&sCubebContext, "CubebUtils") == CUBEB_OK) { return sCubebContext; } NS_WARNING("cubeb_init failed"); return nullptr; } -uint32_t GetCubebLatency() +/*static*/ uint32_t CubebUtils::GetCubebLatency() { StaticMutexAutoLock lock(sMutex); return sCubebLatency; } -bool CubebLatencyPrefSet() +/*static*/ bool CubebUtils::CubebLatencyPrefSet() { StaticMutexAutoLock lock(sMutex); return sCubebLatencyPrefSet; } -void InitLibrary() +/*static*/ void CubebUtils::InitLibrary() { #ifdef PR_LOGGING gAudioStreamLog = PR_NewLogModule("AudioStream"); #endif PrefChanged(PREF_VOLUME_SCALE, nullptr); Preferences::RegisterCallback(PrefChanged, PREF_VOLUME_SCALE); PrefChanged(PREF_CUBEB_LATENCY, nullptr); Preferences::RegisterCallback(PrefChanged, PREF_CUBEB_LATENCY); } -void ShutdownLibrary() +/*static*/ void CubebUtils::ShutdownLibrary() { Preferences::UnregisterCallback(PrefChanged, PREF_VOLUME_SCALE); Preferences::UnregisterCallback(PrefChanged, PREF_CUBEB_LATENCY); StaticMutexAutoLock lock(sMutex); if (sCubebContext) { cubeb_destroy(sCubebContext); sCubebContext = nullptr; } } -uint32_t MaxNumberOfChannels() +/*static*/ int CubebUtils::MaxNumberOfChannels() { - cubeb* cubebContext = GetCubebContext(); + cubeb* cubebContext = CubebUtils::GetCubebContext(); uint32_t maxNumberOfChannels; if (cubebContext && cubeb_get_max_channel_count(cubebContext, &maxNumberOfChannels) == CUBEB_OK) { - return maxNumberOfChannels; + return static_cast<int>(maxNumberOfChannels); } return 0; } -uint32_t PreferredSampleRate() +/*static*/ int CubebUtils::PreferredSampleRate() { MOZ_ASSERT(sPreferredSampleRate, "sPreferredSampleRate has not been initialized!"); return sPreferredSampleRate; } #if defined(__ANDROID__) && defined(MOZ_B2G) -cubeb_stream_type ConvertChannelToCubebType(dom::AudioChannel aChannel) +/*static*/ cubeb_stream_type CubebUtils::ConvertChannelToCubebType(dom::AudioChannel aChannel) { switch(aChannel) { case dom::AudioChannel::Normal: return CUBEB_STREAM_TYPE_SYSTEM; case dom::AudioChannel::Content: return CUBEB_STREAM_TYPE_MUSIC; case dom::AudioChannel::Notification: return CUBEB_STREAM_TYPE_NOTIFICATION; @@ -186,10 +166,9 @@ cubeb_stream_type ConvertChannelToCubebT return CUBEB_STREAM_TYPE_SYSTEM_ENFORCED; default: NS_ERROR("The value of AudioChannel is invalid"); return CUBEB_STREAM_TYPE_MAX; } } #endif -} // namespace CubebUtils -} // namespace mozilla +}
--- a/content/media/CubebUtils.h +++ b/content/media/CubebUtils.h @@ -3,47 +3,70 @@ /* 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/. */ #if !defined(CubebUtils_h_) #define CubebUtils_h_ #include "cubeb/cubeb.h" +#include "nsAutoRef.h" +#include "mozilla/StaticMutex.h" #include "mozilla/dom/AudioChannelBinding.h" +template <> +class nsAutoRefTraits<cubeb_stream> : public nsPointerRefTraits<cubeb_stream> +{ +public: + static void Release(cubeb_stream* aStream) { cubeb_stream_destroy(aStream); } +}; + namespace mozilla { -namespace CubebUtils { -// Initialize Audio Library. Some Audio backends require initializing the -// library before using it. -void InitLibrary(); +class CubebUtils { +public: + // Initialize Audio Library. Some Audio backends require initializing the + // library before using it. + static void InitLibrary(); -// Shutdown Audio Library. Some Audio backends require shutting down the -// library after using it. -void ShutdownLibrary(); + // Shutdown Audio Library. Some Audio backends require shutting down the + // library after using it. + static void ShutdownLibrary(); -// Returns the maximum number of channels supported by the audio hardware. -uint32_t MaxNumberOfChannels(); + // Returns the maximum number of channels supported by the audio hardware. + static int MaxNumberOfChannels(); -// Queries the samplerate the hardware/mixer runs at, and stores it. -// Can be called on any thread. When this returns, it is safe to call -// PreferredSampleRate. -void InitPreferredSampleRate(); - -// Get the aforementioned sample rate. Thread safe. -uint32_t PreferredSampleRate(); + // Queries the samplerate the hardware/mixer runs at, and stores it. + // Can be called on any thread. When this returns, it is safe to call + // PreferredSampleRate without locking. + static void InitPreferredSampleRate(); + // Get the aformentionned sample rate. Does not lock. + static int PreferredSampleRate(); -void PrefChanged(const char* aPref, void* aClosure); -double GetVolumeScale(); -bool GetFirstStream(); -cubeb* GetCubebContext(); -cubeb* GetCubebContextUnlocked(); -uint32_t GetCubebLatency(); -bool CubebLatencyPrefSet(); + static void PrefChanged(const char* aPref, void* aClosure); + static double GetVolumeScale(); + static bool GetFirstStream(); + static cubeb* GetCubebContext(); + static cubeb* GetCubebContextUnlocked(); + static uint32_t GetCubebLatency(); + static bool CubebLatencyPrefSet(); #if defined(__ANDROID__) && defined(MOZ_B2G) -cubeb_stream_type ConvertChannelToCubebType(dom::AudioChannel aChannel); + static cubeb_stream_type ConvertChannelToCubebType(dom::AudioChannel aChannel); #endif -} // namespace CubebUtils -} // namespace mozilla +private: + // This mutex protects the static members below. + static StaticMutex sMutex; + static cubeb* sCubebContext; + + // Prefered samplerate, in Hz (characteristic of the + // hardware/mixer/platform/API used). + static uint32_t sPreferredSampleRate; + + static double sVolumeScale; + static uint32_t sCubebLatency; + static bool sCubebLatencyPrefSet; +}; +} + + #endif // CubebUtils_h_
--- a/content/media/GraphDriver.h +++ b/content/media/GraphDriver.h @@ -9,24 +9,18 @@ #include "nsAutoPtr.h" #include "nsAutoRef.h" #include "AudioBufferUtils.h" #include "AudioMixer.h" #include "AudioSegment.h" struct cubeb_stream; -template <> -class nsAutoRefTraits<cubeb_stream> : public nsPointerRefTraits<cubeb_stream> -{ -public: - static void Release(cubeb_stream* aStream) { cubeb_stream_destroy(aStream); } -}; +namespace mozilla { -namespace mozilla { /** * Assume we can run an iteration of the MediaStreamGraph loop in this much time * or less. * We try to run the control loop at this rate. */ static const int MEDIA_GRAPH_TARGET_PERIOD_MS = 10;
--- a/dom/bluetooth/BluetoothRilListener.cpp +++ b/dom/bluetooth/BluetoothRilListener.cpp @@ -2,21 +2,19 @@ /* 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 "BluetoothRilListener.h" #include "BluetoothHfpManager.h" -#include "nsIIccProvider.h" #include "nsIMobileConnectionInfo.h" -#include "nsIMobileConnectionService.h" -#include "nsITelephonyService.h" -#include "nsRadioInterfaceLayer.h" // For NS_RILCONTENTHELPER_CONTRACTID. +#include "nsIRadioInterfaceLayer.h" +#include "nsRadioInterfaceLayer.h" #include "nsServiceManagerUtils.h" #include "nsString.h" USING_BLUETOOTH_NAMESPACE /** * IccListener */ @@ -176,25 +174,21 @@ MobileConnectionListener::NotifyNetworkS bool MobileConnectionListener::Listen(bool aStart) { nsCOMPtr<nsIMobileConnectionService> service = do_GetService(NS_MOBILE_CONNECTION_SERVICE_CONTRACTID); NS_ENSURE_TRUE(service, false); - nsCOMPtr<nsIMobileConnection> connection; - service->GetItemByServiceId(mClientId, getter_AddRefs(connection)); - NS_ENSURE_TRUE(connection, false); - nsresult rv; if (aStart) { - rv = connection->RegisterListener(this); + rv = service->RegisterListener(mClientId, this); } else { - rv = connection->UnregisterListener(this); + rv = service->UnregisterListener(mClientId, this); } return NS_SUCCEEDED(rv); } /** * TelephonyListener Implementation */ @@ -330,27 +324,27 @@ TelephonyListener::Listen(bool aStart) return NS_SUCCEEDED(rv); } /** * BluetoothRilListener */ BluetoothRilListener::BluetoothRilListener() { - nsCOMPtr<nsIMobileConnectionService> service = - do_GetService(NS_MOBILE_CONNECTION_SERVICE_CONTRACTID); - NS_ENSURE_TRUE_VOID(service); + // Query number of total clients (sim slots) + uint32_t numOfClients; + nsCOMPtr<nsIRadioInterfaceLayer> radioInterfaceLayer = + do_GetService(NS_RADIOINTERFACELAYER_CONTRACTID); + NS_ENSURE_TRUE_VOID(radioInterfaceLayer); - // Query number of total clients (sim slots) - uint32_t numItems = 0; - if (NS_SUCCEEDED(service->GetNumItems(&numItems))) { - // Init MobileConnectionListener array and IccInfoListener - for (uint32_t i = 0; i < numItems; i++) { - mMobileConnListeners.AppendElement(new MobileConnectionListener(i)); - } + radioInterfaceLayer->GetNumRadioInterfaces(&numOfClients); + + // Init MobileConnectionListener array and IccInfoListener + for (uint32_t i = 0; i < numOfClients; i++) { + mMobileConnListeners.AppendElement(new MobileConnectionListener(i)); } mTelephonyListener = new TelephonyListener(); mIccListener = new IccListener(); mIccListener->SetOwner(this); // Probe for available client SelectClient(); @@ -376,25 +370,18 @@ BluetoothRilListener::SelectClient() // Reset mClientId mClientId = mMobileConnListeners.Length(); nsCOMPtr<nsIMobileConnectionService> service = do_GetService(NS_MOBILE_CONNECTION_SERVICE_CONTRACTID); NS_ENSURE_TRUE_VOID(service); for (uint32_t i = 0; i < mMobileConnListeners.Length(); i++) { - nsCOMPtr<nsIMobileConnection> connection; - service->GetItemByServiceId(i, getter_AddRefs(connection)); - if (!connection) { - BT_WARNING("%s: Failed to get mobile connection", __FUNCTION__); - continue; - } - nsCOMPtr<nsIMobileConnectionInfo> voiceInfo; - connection->GetVoice(getter_AddRefs(voiceInfo)); + service->GetVoiceConnectionInfo(i, getter_AddRefs(voiceInfo)); if (!voiceInfo) { BT_WARNING("%s: Failed to get voice connection info", __FUNCTION__); continue; } nsString regState; voiceInfo->GetState(regState); if (regState.EqualsLiteral("registered")) {
--- a/dom/bluetooth/bluedroid/hfp/BluetoothHfpManager.cpp +++ b/dom/bluetooth/bluedroid/hfp/BluetoothHfpManager.cpp @@ -607,26 +607,22 @@ BluetoothHfpManager::HandleVolumeChanged sBluetoothHfpInterface->VolumeControl(HFP_VOLUME_TYPE_SPEAKER, mCurrentVgs, new VolumeControlResultHandler()); } } void BluetoothHfpManager::HandleVoiceConnectionChanged(uint32_t aClientId) { - nsCOMPtr<nsIMobileConnectionService> mcService = + nsCOMPtr<nsIMobileConnectionService> connection = do_GetService(NS_MOBILE_CONNECTION_SERVICE_CONTRACTID); - NS_ENSURE_TRUE_VOID(mcService); - - nsCOMPtr<nsIMobileConnection> connection; - mcService->GetItemByServiceId(aClientId, getter_AddRefs(connection)); NS_ENSURE_TRUE_VOID(connection); nsCOMPtr<nsIMobileConnectionInfo> voiceInfo; - connection->GetVoice(getter_AddRefs(voiceInfo)); + connection->GetVoiceConnectionInfo(aClientId, getter_AddRefs(voiceInfo)); NS_ENSURE_TRUE_VOID(voiceInfo); nsString type; voiceInfo->GetType(type); mPhoneType = GetPhoneType(type); // Roam bool roaming;
--- a/dom/bluetooth/bluez/BluetoothHfpManager.cpp +++ b/dom/bluetooth/bluez/BluetoothHfpManager.cpp @@ -601,26 +601,22 @@ BluetoothHfpManager::HandleVolumeChanged SendCommand(RESPONSE_VGS, mCurrentVgs); } } #ifdef MOZ_B2G_RIL void BluetoothHfpManager::HandleVoiceConnectionChanged(uint32_t aClientId) { - nsCOMPtr<nsIMobileConnectionService> mcService = + nsCOMPtr<nsIMobileConnectionService> connection = do_GetService(NS_MOBILE_CONNECTION_SERVICE_CONTRACTID); - NS_ENSURE_TRUE_VOID(mcService); - - nsCOMPtr<nsIMobileConnection> connection; - mcService->GetItemByServiceId(aClientId, getter_AddRefs(connection)); NS_ENSURE_TRUE_VOID(connection); nsCOMPtr<nsIMobileConnectionInfo> voiceInfo; - connection->GetVoice(getter_AddRefs(voiceInfo)); + connection->GetVoiceConnectionInfo(aClientId, getter_AddRefs(voiceInfo)); NS_ENSURE_TRUE_VOID(voiceInfo); nsString type; voiceInfo->GetType(type); mPhoneType = GetPhoneType(type); bool roaming; voiceInfo->GetRoaming(&roaming); @@ -645,17 +641,17 @@ BluetoothHfpManager::HandleVoiceConnecti /** * Possible return values for mode are: * - null (unknown): set mNetworkSelectionMode to 0 (auto) * - automatic: set mNetworkSelectionMode to 0 (auto) * - manual: set mNetworkSelectionMode to 1 (manual) */ nsString mode; - connection->GetNetworkSelectionMode(mode); + connection->GetNetworkSelectionMode(aClientId, mode); if (mode.EqualsLiteral("manual")) { mNetworkSelectionMode = 1; } else { mNetworkSelectionMode = 0; } nsCOMPtr<nsIMobileNetworkInfo> network; voiceInfo->GetNetwork(getter_AddRefs(network));
--- a/dom/bluetooth2/BluetoothRilListener.cpp +++ b/dom/bluetooth2/BluetoothRilListener.cpp @@ -2,21 +2,19 @@ /* 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 "BluetoothRilListener.h" #include "BluetoothHfpManager.h" -#include "nsIIccProvider.h" #include "nsIMobileConnectionInfo.h" -#include "nsIMobileConnectionService.h" -#include "nsITelephonyService.h" -#include "nsRadioInterfaceLayer.h" // For NS_RILCONTENTHELPER_CONTRACTID. +#include "nsIRadioInterfaceLayer.h" +#include "nsRadioInterfaceLayer.h" #include "nsServiceManagerUtils.h" #include "nsString.h" USING_BLUETOOTH_NAMESPACE /** * IccListener */ @@ -176,25 +174,21 @@ MobileConnectionListener::NotifyNetworkS bool MobileConnectionListener::Listen(bool aStart) { nsCOMPtr<nsIMobileConnectionService> service = do_GetService(NS_MOBILE_CONNECTION_SERVICE_CONTRACTID); NS_ENSURE_TRUE(service, false); - nsCOMPtr<nsIMobileConnection> connection; - mcService->GetItemByServiceId(mClientId, getter_AddRefs(connection)); - NS_ENSURE_TRUE(connection, false); - nsresult rv; if (aStart) { - rv = connection->RegisterListener(this); + rv = service->RegisterListener(mClientId, this); } else { - rv = connection->UnregisterListener(this); + rv = service->UnregisterListener(mClientId, this); } return NS_SUCCEEDED(rv); } /** * TelephonyListener Implementation */ @@ -330,27 +324,27 @@ TelephonyListener::Listen(bool aStart) return NS_SUCCEEDED(rv); } /** * BluetoothRilListener */ BluetoothRilListener::BluetoothRilListener() { - nsCOMPtr<nsIMobileConnectionService> service = - do_GetService(NS_MOBILE_CONNECTION_SERVICE_CONTRACTID); - NS_ENSURE_TRUE_VOID(service); + // Query number of total clients (sim slots) + uint32_t numOfClients; + nsCOMPtr<nsIRadioInterfaceLayer> radioInterfaceLayer = + do_GetService(NS_RADIOINTERFACELAYER_CONTRACTID); + NS_ENSURE_TRUE_VOID(radioInterfaceLayer); - // Query number of total clients (sim slots) - uint32_t numItems = 0; - if (NS_SUCCEEDED(service->GetNumItems(&numItems))) { - // Init MobileConnectionListener array and IccInfoListener - for (uint32_t i = 0; i < numItems; i++) { - mMobileConnListeners.AppendElement(new MobileConnectionListener(i)); - } + radioInterfaceLayer->GetNumRadioInterfaces(&numOfClients); + + // Init MobileConnectionListener array and IccInfoListener + for (uint32_t i = 0; i < numOfClients; i++) { + mMobileConnListeners.AppendElement(new MobileConnectionListener(i)); } mTelephonyListener = new TelephonyListener(); mIccListener = new IccListener(); mIccListener->SetOwner(this); // Probe for available client SelectClient(); @@ -376,25 +370,18 @@ BluetoothRilListener::SelectClient() // Reset mClientId mClientId = mMobileConnListeners.Length(); nsCOMPtr<nsIMobileConnectionService> service = do_GetService(NS_MOBILE_CONNECTION_SERVICE_CONTRACTID); NS_ENSURE_TRUE_VOID(service); for (uint32_t i = 0; i < mMobileConnListeners.Length(); i++) { - nsCOMPtr<nsIMobileConnection> connection; - service->GetItemByServiceId(i, getter_AddRefs(connection)); - if (!connection) { - BT_WARNING("%s: Failed to get mobile connection", __FUNCTION__); - continue; - } - nsCOMPtr<nsIMobileConnectionInfo> voiceInfo; - connection->GetVoice(getter_AddRefs(voiceInfo)); + service->GetVoiceConnectionInfo(i, getter_AddRefs(voiceInfo)); if (!voiceInfo) { BT_WARNING("%s: Failed to get voice connection info", __FUNCTION__); continue; } nsString regState; voiceInfo->GetState(regState); if (regState.EqualsLiteral("registered")) {
--- a/dom/bluetooth2/bluedroid/hfp/BluetoothHfpManager.cpp +++ b/dom/bluetooth2/bluedroid/hfp/BluetoothHfpManager.cpp @@ -610,26 +610,22 @@ BluetoothHfpManager::HandleVolumeChanged sBluetoothHfpInterface->VolumeControl(HFP_VOLUME_TYPE_SPEAKER, mCurrentVgs, new VolumeControlResultHandler()); } } void BluetoothHfpManager::HandleVoiceConnectionChanged(uint32_t aClientId) { - nsCOMPtr<nsIMobileConnectionService> mcService = + nsCOMPtr<nsIMobileConnectionService> connection = do_GetService(NS_MOBILE_CONNECTION_SERVICE_CONTRACTID); - NS_ENSURE_TRUE_VOID(mcService); - - nsCOMPtr<nsIMobileConnection> connection; - mcService->GetItemByServiceId(aClientId, getter_AddRefs(connection)); NS_ENSURE_TRUE_VOID(connection); nsCOMPtr<nsIMobileConnectionInfo> voiceInfo; - connection->GetVoice(getter_AddRefs(voiceInfo)); + connection->GetVoiceConnectionInfo(aClientId, getter_AddRefs(voiceInfo)); NS_ENSURE_TRUE_VOID(voiceInfo); nsString type; voiceInfo->GetType(type); mPhoneType = GetPhoneType(type); // Roam bool roaming;
--- a/dom/bluetooth2/bluez/BluetoothHfpManager.cpp +++ b/dom/bluetooth2/bluez/BluetoothHfpManager.cpp @@ -601,26 +601,22 @@ BluetoothHfpManager::HandleVolumeChanged SendCommand(RESPONSE_VGS, mCurrentVgs); } } #ifdef MOZ_B2G_RIL void BluetoothHfpManager::HandleVoiceConnectionChanged(uint32_t aClientId) { - nsCOMPtr<nsIMobileConnectionService> mcService = + nsCOMPtr<nsIMobileConnectionService> connection = do_GetService(NS_MOBILE_CONNECTION_SERVICE_CONTRACTID); - NS_ENSURE_TRUE_VOID(mcService); - - nsCOMPtr<nsIMobileConnection> connection; - mcService->GetItemByServiceId(aClientId, getter_AddRefs(connection)); NS_ENSURE_TRUE_VOID(connection); nsCOMPtr<nsIMobileConnectionInfo> voiceInfo; - connection->GetVoice(getter_AddRefs(voiceInfo)); + connection->GetVoiceConnectionInfo(aClientId, getter_AddRefs(voiceInfo)); NS_ENSURE_TRUE_VOID(voiceInfo); nsString type; voiceInfo->GetType(type); mPhoneType = GetPhoneType(type); bool roaming; voiceInfo->GetRoaming(&roaming); @@ -645,17 +641,17 @@ BluetoothHfpManager::HandleVoiceConnecti /** * Possible return values for mode are: * - null (unknown): set mNetworkSelectionMode to 0 (auto) * - automatic: set mNetworkSelectionMode to 0 (auto) * - manual: set mNetworkSelectionMode to 1 (manual) */ nsString mode; - connection->GetNetworkSelectionMode(mode); + connection->GetNetworkSelectionMode(aClientId, mode); if (mode.EqualsLiteral("manual")) { mNetworkSelectionMode = 1; } else { mNetworkSelectionMode = 0; } nsCOMPtr<nsIMobileNetworkInfo> network; voiceInfo->GetNetwork(getter_AddRefs(network));
--- a/dom/interfaces/notification/nsINotificationStorage.idl +++ b/dom/interfaces/notification/nsINotificationStorage.idl @@ -1,15 +1,15 @@ /* 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 "domstubs.idl" -[scriptable, uuid(9b12f566-2c7f-48ef-990d-e5092a71d11e)] +[scriptable, uuid(9f1c43b9-f01b-4c87-ad3d-1a86520c2159)] interface nsINotificationStorageCallback : nsISupports { /** * Callback function used to pass single notification back * into C++ land for Notification.get return data. * * @param id: a uuid for this notification * @param title: the notification title @@ -22,30 +22,31 @@ interface nsINotificationStorageCallback [implicit_jscontext] void handle(in DOMString id, in DOMString title, in DOMString dir, in DOMString lang, in DOMString body, in DOMString tag, in DOMString icon, - in DOMString data); + in DOMString data, + in DOMString behavior); /** * Callback function used to notify C++ the we have returned * all notification objects for this Notification.get call. */ [implicit_jscontext] void done(); }; /** * Interface for notification persistence layer. */ -[scriptable, uuid(1be733d9-d614-43f2-9fd4-8f573a33b215)] +[scriptable, uuid(f5145be6-e34b-468b-84da-c8c4c1ad60fe)] interface nsINotificationStorage : nsISupports { /** * Add/replace a notification to the persistence layer. * * @param origin: the origin/app of this notification * @param id: a uuid for this notification @@ -65,17 +66,18 @@ interface nsINotificationStorage : nsISu in DOMString id, in DOMString title, in DOMString dir, in DOMString lang, in DOMString body, in DOMString tag, in DOMString icon, in DOMString alertName, - in DOMString data); + in DOMString data, + in DOMString behavior); /** * Retrieve a list of notifications. * * @param origin: the origin/app for which to fetch notifications from * @param tag: used to fetch only a specific tag * @param callback: nsINotificationStorageCallback, used for * returning notifications objects
--- a/dom/ipc/ContentChild.cpp +++ b/dom/ipc/ContentChild.cpp @@ -121,17 +121,16 @@ #include "nsIAccessibilityService.h" #endif #ifdef MOZ_NUWA_PROCESS #include <setjmp.h> #include "ipc/Nuwa.h" #endif -#include "mozilla/dom/mobileconnection/MobileConnectionChild.h" #include "mozilla/dom/mobilemessage/SmsChild.h" #include "mozilla/dom/devicestorage/DeviceStorageRequestChild.h" #include "mozilla/dom/PFileSystemRequestChild.h" #include "mozilla/dom/FileSystemTaskBase.h" #include "mozilla/dom/bluetooth/PBluetoothChild.h" #include "mozilla/dom/PFMRadioChild.h" #include "mozilla/ipc/InputStreamUtils.h" @@ -150,23 +149,27 @@ #include "AudioChannelService.h" #include "JavaScriptChild.h" #include "mozilla/dom/DataStoreService.h" #include "mozilla/dom/telephony/PTelephonyChild.h" #include "mozilla/dom/time/DateCacheCleaner.h" #include "mozilla/net/NeckoMessageUtils.h" #include "mozilla/RemoteSpellCheckEngineChild.h" +#ifdef MOZ_B2G_RIL +#include "mozilla/dom/mobileconnection/MobileConnectionChild.h" +using namespace mozilla::dom::mobileconnection; +#endif + using namespace base; using namespace mozilla; using namespace mozilla::docshell; using namespace mozilla::dom::bluetooth; using namespace mozilla::dom::devicestorage; using namespace mozilla::dom::ipc; -using namespace mozilla::dom::mobileconnection; using namespace mozilla::dom::mobilemessage; using namespace mozilla::dom::telephony; using namespace mozilla::hal_sandbox; using namespace mozilla::ipc; using namespace mozilla::layers; using namespace mozilla::net; using namespace mozilla::jsipc; #if defined(MOZ_WIDGET_GONK)
--- a/dom/ipc/ContentParent.cpp +++ b/dom/ipc/ContentParent.cpp @@ -39,21 +39,20 @@ #include "mozilla/dom/PMemoryReportRequestParent.h" #include "mozilla/dom/power/PowerManagerService.h" #include "mozilla/dom/DOMStorageIPC.h" #include "mozilla/dom/bluetooth/PBluetoothParent.h" #include "mozilla/dom/PFMRadioParent.h" #include "mozilla/dom/devicestorage/DeviceStorageRequestParent.h" #include "mozilla/dom/FileSystemRequestParent.h" #include "mozilla/dom/GeolocationBinding.h" -#include "mozilla/dom/mobileconnection/MobileConnectionParent.h" -#include "mozilla/dom/mobilemessage/SmsParent.h" #include "mozilla/dom/quota/QuotaManager.h" #include "mozilla/dom/telephony/TelephonyParent.h" #include "mozilla/dom/time/DateCacheCleaner.h" +#include "SmsParent.h" #include "mozilla/hal_sandbox/PHalParent.h" #include "mozilla/ipc/BackgroundChild.h" #include "mozilla/ipc/BackgroundParent.h" #include "mozilla/ipc/FileDescriptorSetParent.h" #include "mozilla/ipc/FileDescriptorUtils.h" #include "mozilla/ipc/PFileDescriptorSetParent.h" #include "mozilla/ipc/TestShellParent.h" #include "mozilla/ipc/InputStreamUtils.h" @@ -173,31 +172,34 @@ using namespace mozilla::system; #endif #ifdef ENABLE_TESTS #include "BackgroundChildImpl.h" #include "mozilla/ipc/PBackgroundChild.h" #include "nsIIPCBackgroundChildCreateCallback.h" #endif +#ifdef MOZ_B2G_RIL +#include "mozilla/dom/mobileconnection/MobileConnectionParent.h" +using namespace mozilla::dom::mobileconnection; +#endif #if defined(MOZ_CONTENT_SANDBOX) && defined(XP_LINUX) #include "mozilla/Sandbox.h" #endif static NS_DEFINE_CID(kCClipboardCID, NS_CLIPBOARD_CID); static const char* sClipboardTextFlavors[] = { kUnicodeMime }; using base::ChildPrivileges; using base::KillProcess; using namespace mozilla::dom::bluetooth; using namespace mozilla::dom::devicestorage; using namespace mozilla::dom::indexedDB; using namespace mozilla::dom::power; -using namespace mozilla::dom::mobileconnection; using namespace mozilla::dom::mobilemessage; using namespace mozilla::dom::telephony; using namespace mozilla::hal; using namespace mozilla::ipc; using namespace mozilla::layers; using namespace mozilla::net; using namespace mozilla::jsipc; using namespace mozilla::widget;
--- a/dom/mobileconnection/DOMMMIError.cpp +++ b/dom/mobileconnection/DOMMMIError.cpp @@ -1,15 +1,15 @@ /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ /* 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 "mozilla/dom/DOMMMIError.h" +#include "DOMMMIError.h" #include "mozilla/dom/DOMMMIErrorBinding.h" using namespace mozilla::dom; NS_IMPL_CYCLE_COLLECTION_CLASS(DOMMMIError) NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN_INHERITED(DOMMMIError, DOMError) NS_IMPL_CYCLE_COLLECTION_UNLINK_END
--- a/dom/mobileconnection/MobileCellInfo.cpp +++ b/dom/mobileconnection/MobileCellInfo.cpp @@ -1,15 +1,15 @@ /* -*- 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/MobileCellInfo.h" +#include "MobileCellInfo.h" #include "mozilla/dom/MozMobileCellInfoBinding.h" using namespace mozilla::dom; NS_IMPL_CYCLE_COLLECTION_WRAPPERCACHE(MobileCellInfo, mWindow) NS_IMPL_CYCLE_COLLECTING_ADDREF(MobileCellInfo) NS_IMPL_CYCLE_COLLECTING_RELEASE(MobileCellInfo)
--- a/dom/mobileconnection/MobileConnection.cpp +++ b/dom/mobileconnection/MobileConnection.cpp @@ -1,13 +1,13 @@ /* 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/MobileConnection.h" +#include "MobileConnection.h" #include "MobileConnectionCallback.h" #include "mozilla/dom/CFStateChangeEvent.h" #include "mozilla/dom/DataErrorEvent.h" #include "mozilla/dom/MozClirModeEvent.h" #include "mozilla/dom/MozEmergencyCbModeEvent.h" #include "mozilla/dom/MozOtaStatusEvent.h" #include "mozilla/dom/ToJSValue.h" @@ -37,17 +37,16 @@ { \ uint32_t index = uint32_t(_enum); \ _string.AssignASCII(_enumType##Values::strings[index].value, \ _enumType##Values::strings[index].length); \ } using mozilla::ErrorResult; using namespace mozilla::dom; -using namespace mozilla::dom::mobileconnection; class MobileConnection::Listener MOZ_FINAL : public nsIMobileConnectionListener { MobileConnection* mMobileConnection; public: NS_DECL_ISUPPORTS NS_FORWARD_SAFE_NSIMOBILECONNECTIONLISTENER(mMobileConnection) @@ -73,19 +72,18 @@ private: NS_IMPL_ISUPPORTS(MobileConnection::Listener, nsIMobileConnectionListener) NS_IMPL_CYCLE_COLLECTION_CLASS(MobileConnection) NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_INHERITED(MobileConnection, DOMEventTargetHelper) // Don't traverse mListener because it doesn't keep any reference to - // MobileConnection but a raw pointer instead. Neither does mMobileConnection - // because it's an xpcom service owned object and is only released at shutting - // down. + // MobileConnection but a raw pointer instead. Neither does mService because + // it's an xpcom service and is only released at shutting down. NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mVoice) NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mData) NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN_INHERITED(MobileConnection, DOMEventTargetHelper) tmp->Shutdown(); NS_IMPL_CYCLE_COLLECTION_UNLINK(mVoice) @@ -98,55 +96,48 @@ NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION_ // to us. NS_INTERFACE_MAP_END_INHERITING(DOMEventTargetHelper) NS_IMPL_ADDREF_INHERITED(MobileConnection, DOMEventTargetHelper) NS_IMPL_RELEASE_INHERITED(MobileConnection, DOMEventTargetHelper) MobileConnection::MobileConnection(nsPIDOMWindow* aWindow, uint32_t aClientId) : DOMEventTargetHelper(aWindow) + , mClientId(aClientId) { SetIsDOMBinding(); - nsCOMPtr<nsIMobileConnectionService> service = - do_GetService(NS_MOBILE_CONNECTION_SERVICE_CONTRACTID); + mService = do_GetService(NS_MOBILE_CONNECTION_SERVICE_CONTRACTID); // Not being able to acquire the service isn't fatal since we check // for it explicitly below. - if (!service) { + if (!mService) { NS_WARNING("Could not acquire nsIMobileConnectionService!"); return; } - nsresult rv = service->GetItemByServiceId(aClientId, - getter_AddRefs(mMobileConnection)); - if (NS_FAILED(rv) || !mMobileConnection) { - NS_WARNING("Could not acquire nsIMobileConnection!"); - return; - } - mListener = new Listener(this); mVoice = new MobileConnectionInfo(GetOwner()); mData = new MobileConnectionInfo(GetOwner()); if (CheckPermission("mobileconnection")) { - DebugOnly<nsresult> rv = mMobileConnection->RegisterListener(mListener); + DebugOnly<nsresult> rv = mService->RegisterListener(mClientId, mListener); NS_WARN_IF_FALSE(NS_SUCCEEDED(rv), "Failed registering mobile connection messages with service"); UpdateVoice(); UpdateData(); } } void MobileConnection::Shutdown() { if (mListener) { - if (mMobileConnection) { - mMobileConnection->UnregisterListener(mListener); + if (mService) { + mService->UnregisterListener(mClientId, mListener); } mListener->Disconnect(); mListener = nullptr; } } MobileConnection::~MobileConnection() @@ -179,61 +170,61 @@ MobileConnection::CheckPermission(const uint32_t permission = nsIPermissionManager::DENY_ACTION; permMgr->TestPermissionFromWindow(GetOwner(), aType, &permission); return permission == nsIPermissionManager::ALLOW_ACTION; } void MobileConnection::UpdateVoice() { - if (!mMobileConnection) { + if (!mService) { return; } nsCOMPtr<nsIMobileConnectionInfo> info; - mMobileConnection->GetVoice(getter_AddRefs(info)); + mService->GetVoiceConnectionInfo(mClientId, getter_AddRefs(info)); mVoice->Update(info); } void MobileConnection::UpdateData() { - if (!mMobileConnection) { + if (!mService) { return; } nsCOMPtr<nsIMobileConnectionInfo> info; - mMobileConnection->GetData(getter_AddRefs(info)); + mService->GetDataConnectionInfo(mClientId, getter_AddRefs(info)); mData->Update(info); } // WebIDL interface void MobileConnection::GetLastKnownNetwork(nsString& aRetVal) const { aRetVal.SetIsVoid(true); - if (!mMobileConnection) { + if (!mService) { return; } - mMobileConnection->GetLastKnownNetwork(aRetVal); + mService->GetLastKnownNetwork(mClientId, aRetVal); } void MobileConnection::GetLastKnownHomeNetwork(nsString& aRetVal) const { aRetVal.SetIsVoid(true); - if (!mMobileConnection) { + if (!mService) { return; } - mMobileConnection->GetLastKnownHomeNetwork(aRetVal); + mService->GetLastKnownHomeNetwork(mClientId, aRetVal); } // All fields below require the "mobileconnection" permission. MobileConnectionInfo* MobileConnection::Voice() const { return mVoice; @@ -245,350 +236,362 @@ MobileConnection::Data() const return mData; } void MobileConnection::GetIccId(nsString& aRetVal) const { aRetVal.SetIsVoid(true); - if (!mMobileConnection) { + if (!mService) { return; } - mMobileConnection->GetIccId(aRetVal); + mService->GetIccId(mClientId, aRetVal); } Nullable<MobileNetworkSelectionMode> MobileConnection::GetNetworkSelectionMode() const { Nullable<MobileNetworkSelectionMode> retVal = Nullable<MobileNetworkSelectionMode>(); - if (!mMobileConnection) { + if (!mService) { return retVal; } nsAutoString mode; - mMobileConnection->GetNetworkSelectionMode(mode); + mService->GetNetworkSelectionMode(mClientId, mode); CONVERT_STRING_TO_NULLABLE_ENUM(mode, MobileNetworkSelectionMode, retVal); return retVal; } Nullable<MobileRadioState> MobileConnection::GetRadioState() const { Nullable<MobileRadioState> retVal = Nullable<MobileRadioState>(); - if (!mMobileConnection) { + if (!mService) { return retVal; } nsAutoString state; - mMobileConnection->GetRadioState(state); + mService->GetRadioState(mClientId, state); CONVERT_STRING_TO_NULLABLE_ENUM(state, MobileRadioState, retVal); return retVal; } void MobileConnection::GetSupportedNetworkTypes(nsTArray<MobileNetworkType>& aTypes) const { - if (!mMobileConnection) { + if (!mService) { return; } - char16_t** types = nullptr; - uint32_t length = 0; + nsCOMPtr<nsIVariant> variant; + mService->GetSupportedNetworkTypes(mClientId, + getter_AddRefs(variant)); - nsresult rv = mMobileConnection->GetSupportedNetworkTypes(&types, &length); - NS_ENSURE_SUCCESS_VOID(rv); + uint16_t type; + nsIID iid; + uint32_t count; + void* data; - for (uint32_t i = 0; i < length; ++i) { - nsDependentString rawType(types[i]); - Nullable<MobileNetworkType> type = Nullable<MobileNetworkType>(); - CONVERT_STRING_TO_NULLABLE_ENUM(rawType, MobileNetworkType, type); + // Convert the nsIVariant to an array. We own the resulting buffer and its + // elements. + if (NS_FAILED(variant->GetAsArray(&type, &iid, &count, &data))) { + return; + } - if (!type.IsNull()) { - aTypes.AppendElement(type.Value()); + // We expect the element type is wstring. + if (type == nsIDataType::VTYPE_WCHAR_STR) { + char16_t** rawArray = reinterpret_cast<char16_t**>(data); + for (uint32_t i = 0; i < count; ++i) { + nsDependentString rawType(rawArray[i]); + Nullable<MobileNetworkType> type = Nullable<MobileNetworkType>(); + CONVERT_STRING_TO_NULLABLE_ENUM(rawType, MobileNetworkType, type); + + if (!type.IsNull()) { + aTypes.AppendElement(type.Value()); + } } } - - NS_FREE_XPCOM_ALLOCATED_POINTER_ARRAY(length, types); + NS_Free(data); } already_AddRefed<DOMRequest> MobileConnection::GetNetworks(ErrorResult& aRv) { - if (!mMobileConnection) { + if (!mService) { aRv.Throw(NS_ERROR_FAILURE); return nullptr; } nsRefPtr<DOMRequest> request = new DOMRequest(GetOwner()); nsRefPtr<MobileConnectionCallback> requestCallback = new MobileConnectionCallback(GetOwner(), request); - nsresult rv = mMobileConnection->GetNetworks(requestCallback); + nsresult rv = mService->GetNetworks(mClientId, requestCallback); if (NS_FAILED(rv)) { aRv.Throw(rv); return nullptr; } return request.forget(); } already_AddRefed<DOMRequest> MobileConnection::SelectNetwork(MobileNetworkInfo& aNetwork, ErrorResult& aRv) { - if (!mMobileConnection) { + if (!mService) { aRv.Throw(NS_ERROR_FAILURE); return nullptr; } nsRefPtr<DOMRequest> request = new DOMRequest(GetOwner()); nsRefPtr<MobileConnectionCallback> requestCallback = new MobileConnectionCallback(GetOwner(), request); - nsresult rv = mMobileConnection->SelectNetwork(&aNetwork, requestCallback); + nsresult rv = mService->SelectNetwork(mClientId, &aNetwork, requestCallback); if (NS_FAILED(rv)) { aRv.Throw(rv); return nullptr; } return request.forget(); } already_AddRefed<DOMRequest> MobileConnection::SelectNetworkAutomatically(ErrorResult& aRv) { - if (!mMobileConnection) { + if (!mService) { aRv.Throw(NS_ERROR_FAILURE); return nullptr; } nsRefPtr<DOMRequest> request = new DOMRequest(GetOwner()); nsRefPtr<MobileConnectionCallback> requestCallback = new MobileConnectionCallback(GetOwner(), request); - nsresult rv = - mMobileConnection->SelectNetworkAutomatically(requestCallback); + nsresult rv = mService->SelectNetworkAutomatically(mClientId, + requestCallback); if (NS_FAILED(rv)) { aRv.Throw(rv); return nullptr; } return request.forget(); } already_AddRefed<DOMRequest> MobileConnection::SetPreferredNetworkType(MobilePreferredNetworkType& aType, ErrorResult& aRv) { - if (!mMobileConnection) { + if (!mService) { aRv.Throw(NS_ERROR_FAILURE); return nullptr; } nsAutoString type; CONVERT_ENUM_TO_STRING(MobilePreferredNetworkType, aType, type); nsRefPtr<DOMRequest> request = new DOMRequest(GetOwner()); nsRefPtr<MobileConnectionCallback> requestCallback = new MobileConnectionCallback(GetOwner(), request); - nsresult rv = - mMobileConnection->SetPreferredNetworkType(type, requestCallback); + nsresult rv = mService->SetPreferredNetworkType(mClientId, type, + requestCallback); if (NS_FAILED(rv)) { aRv.Throw(rv); return nullptr; } return request.forget(); } already_AddRefed<DOMRequest> MobileConnection::GetPreferredNetworkType(ErrorResult& aRv) { - if (!mMobileConnection) { + if (!mService) { aRv.Throw(NS_ERROR_FAILURE); return nullptr; } nsRefPtr<DOMRequest> request = new DOMRequest(GetOwner()); nsRefPtr<MobileConnectionCallback> requestCallback = new MobileConnectionCallback(GetOwner(), request); - nsresult rv = mMobileConnection->GetPreferredNetworkType(requestCallback); + nsresult rv = mService->GetPreferredNetworkType(mClientId, requestCallback); if (NS_FAILED(rv)) { aRv.Throw(rv); return nullptr; } return request.forget(); } already_AddRefed<DOMRequest> MobileConnection::SetRoamingPreference(MobileRoamingMode& aMode, ErrorResult& aRv) { - if (!mMobileConnection) { + if (!mService) { aRv.Throw(NS_ERROR_FAILURE); return nullptr; } nsAutoString mode; CONVERT_ENUM_TO_STRING(MobileRoamingMode, aMode, mode); nsRefPtr<DOMRequest> request = new DOMRequest(GetOwner()); nsRefPtr<MobileConnectionCallback> requestCallback = new MobileConnectionCallback(GetOwner(), request); - nsresult rv = mMobileConnection->SetRoamingPreference(mode, requestCallback); + nsresult rv = mService->SetRoamingPreference(mClientId, mode, requestCallback); if (NS_FAILED(rv)) { aRv.Throw(rv); return nullptr; } return request.forget(); } already_AddRefed<DOMRequest> MobileConnection::GetRoamingPreference(ErrorResult& aRv) { - if (!mMobileConnection) { + if (!mService) { aRv.Throw(NS_ERROR_FAILURE); return nullptr; } nsRefPtr<DOMRequest> request = new DOMRequest(GetOwner()); nsRefPtr<MobileConnectionCallback> requestCallback = new MobileConnectionCallback(GetOwner(), request); - nsresult rv = mMobileConnection->GetRoamingPreference(requestCallback); + nsresult rv = mService->GetRoamingPreference(mClientId, requestCallback); if (NS_FAILED(rv)) { aRv.Throw(rv); return nullptr; } return request.forget(); } already_AddRefed<DOMRequest> MobileConnection::SetVoicePrivacyMode(bool aEnabled, ErrorResult& aRv) { - if (!mMobileConnection) { + if (!mService) { aRv.Throw(NS_ERROR_FAILURE); return nullptr; } nsRefPtr<DOMRequest> request = new DOMRequest(GetOwner()); nsRefPtr<MobileConnectionCallback> requestCallback = new MobileConnectionCallback(GetOwner(), request); - nsresult rv = - mMobileConnection->SetVoicePrivacyMode(aEnabled, requestCallback); + nsresult rv = mService->SetVoicePrivacyMode(mClientId, aEnabled, + requestCallback); if (NS_FAILED(rv)) { aRv.Throw(rv); return nullptr; } return request.forget(); } already_AddRefed<DOMRequest> MobileConnection::GetVoicePrivacyMode(ErrorResult& aRv) { - if (!mMobileConnection) { + if (!mService) { aRv.Throw(NS_ERROR_FAILURE); return nullptr; } nsRefPtr<DOMRequest> request = new DOMRequest(GetOwner()); nsRefPtr<MobileConnectionCallback> requestCallback = new MobileConnectionCallback(GetOwner(), request); - nsresult rv = mMobileConnection->GetVoicePrivacyMode(requestCallback); + nsresult rv = mService->GetVoicePrivacyMode(mClientId, requestCallback); if (NS_FAILED(rv)) { aRv.Throw(rv); return nullptr; } return request.forget(); } already_AddRefed<DOMRequest> MobileConnection::SendMMI(const nsAString& aMMIString, ErrorResult& aRv) { - if (!mMobileConnection) { + if (!mService) { aRv.Throw(NS_ERROR_FAILURE); return nullptr; } nsRefPtr<DOMRequest> request = new DOMRequest(GetOwner()); nsRefPtr<MobileConnectionCallback> requestCallback = new MobileConnectionCallback(GetOwner(), request); - nsresult rv = mMobileConnection->SendMMI(aMMIString, requestCallback); + nsresult rv = mService->SendMMI(mClientId, aMMIString, requestCallback); if (NS_FAILED(rv)) { aRv.Throw(rv); return nullptr; } return request.forget(); } already_AddRefed<DOMRequest> MobileConnection::CancelMMI(ErrorResult& aRv) { - if (!mMobileConnection) { + if (!mService) { aRv.Throw(NS_ERROR_FAILURE); return nullptr; } nsRefPtr<DOMRequest> request = new DOMRequest(GetOwner()); nsRefPtr<MobileConnectionCallback> requestCallback = new MobileConnectionCallback(GetOwner(), request); - nsresult rv = mMobileConnection->CancelMMI(requestCallback); + nsresult rv = mService->CancelMMI(mClientId, requestCallback); if (NS_FAILED(rv)) { aRv.Throw(rv); return nullptr; } return request.forget(); } already_AddRefed<DOMRequest> MobileConnection::GetCallForwardingOption(uint16_t aReason, ErrorResult& aRv) { - if (!mMobileConnection) { + if (!mService) { aRv.Throw(NS_ERROR_FAILURE); return nullptr; } nsRefPtr<DOMRequest> request = new DOMRequest(GetOwner()); nsRefPtr<MobileConnectionCallback> requestCallback = new MobileConnectionCallback(GetOwner(), request); - nsresult rv = mMobileConnection->GetCallForwarding(aReason, requestCallback); + nsresult rv = mService->GetCallForwarding(mClientId, aReason, requestCallback); if (NS_FAILED(rv)) { aRv.Throw(rv); return nullptr; } return request.forget(); } already_AddRefed<DOMRequest> MobileConnection::SetCallForwardingOption(const MozCallForwardingOptions& aOptions, ErrorResult& aRv) { - if (!mMobileConnection) { + if (!mService) { aRv.Throw(NS_ERROR_FAILURE); return nullptr; } AutoJSAPI jsapi; if (!NS_WARN_IF(jsapi.Init(GetOwner()))) { aRv.Throw(NS_ERROR_FAILURE); return nullptr; @@ -600,30 +603,30 @@ MobileConnection::SetCallForwardingOptio aRv.Throw(NS_ERROR_TYPE_ERR); return nullptr; } nsRefPtr<DOMRequest> request = new DOMRequest(GetOwner()); nsRefPtr<MobileConnectionCallback> requestCallback = new MobileConnectionCallback(GetOwner(), request); - nsresult rv = mMobileConnection->SetCallForwarding(options, requestCallback); + nsresult rv = mService->SetCallForwarding(mClientId, options, requestCallback); if (NS_FAILED(rv)) { aRv.Throw(rv); return nullptr; } return request.forget(); } already_AddRefed<DOMRequest> MobileConnection::GetCallBarringOption(const MozCallBarringOptions& aOptions, ErrorResult& aRv) { - if (!mMobileConnection) { + if (!mService) { aRv.Throw(NS_ERROR_FAILURE); return nullptr; } AutoJSAPI jsapi; if (!NS_WARN_IF(jsapi.Init(GetOwner()))) { aRv.Throw(NS_ERROR_FAILURE); return nullptr; @@ -635,30 +638,30 @@ MobileConnection::GetCallBarringOption(c aRv.Throw(NS_ERROR_TYPE_ERR); return nullptr; } nsRefPtr<DOMRequest> request = new DOMRequest(GetOwner()); nsRefPtr<MobileConnectionCallback> requestCallback = new MobileConnectionCallback(GetOwner(), request); - nsresult rv = mMobileConnection->GetCallBarring(options, requestCallback); + nsresult rv = mService->GetCallBarring(mClientId, options, requestCallback); if (NS_FAILED(rv)) { aRv.Throw(rv); return nullptr; } return request.forget(); } already_AddRefed<DOMRequest> MobileConnection::SetCallBarringOption(const MozCallBarringOptions& aOptions, ErrorResult& aRv) { - if (!mMobileConnection) { + if (!mService) { aRv.Throw(NS_ERROR_FAILURE); return nullptr; } AutoJSAPI jsapi; if (!NS_WARN_IF(jsapi.Init(GetOwner()))) { aRv.Throw(NS_ERROR_FAILURE); return nullptr; @@ -670,30 +673,30 @@ MobileConnection::SetCallBarringOption(c aRv.Throw(NS_ERROR_TYPE_ERR); return nullptr; } nsRefPtr<DOMRequest> request = new DOMRequest(GetOwner()); nsRefPtr<MobileConnectionCallback> requestCallback = new MobileConnectionCallback(GetOwner(), request); - nsresult rv = mMobileConnection->SetCallBarring(options, requestCallback); + nsresult rv = mService->SetCallBarring(mClientId, options, requestCallback); if (NS_FAILED(rv)) { aRv.Throw(rv); return nullptr; } return request.forget(); } already_AddRefed<DOMRequest> MobileConnection::ChangeCallBarringPassword(const MozCallBarringOptions& aOptions, ErrorResult& aRv) { - if (!mMobileConnection) { + if (!mService) { aRv.Throw(NS_ERROR_FAILURE); return nullptr; } AutoJSAPI jsapi; if (!NS_WARN_IF(jsapi.Init(GetOwner()))) { aRv.Throw(NS_ERROR_FAILURE); return nullptr; @@ -705,147 +708,147 @@ MobileConnection::ChangeCallBarringPassw aRv.Throw(NS_ERROR_TYPE_ERR); return nullptr; } nsRefPtr<DOMRequest> request = new DOMRequest(GetOwner()); nsRefPtr<MobileConnectionCallback> requestCallback = new MobileConnectionCallback(GetOwner(), request); - nsresult rv = - mMobileConnection->ChangeCallBarringPassword(options, requestCallback); + nsresult rv = mService->ChangeCallBarringPassword(mClientId, options, + requestCallback); if (NS_FAILED(rv)) { aRv.Throw(rv); return nullptr; } return request.forget(); } already_AddRefed<DOMRequest> MobileConnection::GetCallWaitingOption(ErrorResult& aRv) { - if (!mMobileConnection) { + if (!mService) { aRv.Throw(NS_ERROR_FAILURE); return nullptr; } nsRefPtr<DOMRequest> request = new DOMRequest(GetOwner()); nsRefPtr<MobileConnectionCallback> requestCallback = new MobileConnectionCallback(GetOwner(), request); - nsresult rv = mMobileConnection->GetCallWaiting(requestCallback); + nsresult rv = mService->GetCallWaiting(mClientId, requestCallback); if (NS_FAILED(rv)) { aRv.Throw(rv); return nullptr; } return request.forget(); } already_AddRefed<DOMRequest> MobileConnection::SetCallWaitingOption(bool aEnabled, ErrorResult& aRv) { - if (!mMobileConnection) { + if (!mService) { aRv.Throw(NS_ERROR_FAILURE); return nullptr; } nsRefPtr<DOMRequest> request = new DOMRequest(GetOwner()); nsRefPtr<MobileConnectionCallback> requestCallback = new MobileConnectionCallback(GetOwner(), request); - nsresult rv = mMobileConnection->SetCallWaiting(aEnabled, requestCallback); + nsresult rv = mService->SetCallWaiting(mClientId, aEnabled, requestCallback); if (NS_FAILED(rv)) { aRv.Throw(rv); return nullptr; } return request.forget(); } already_AddRefed<DOMRequest> MobileConnection::GetCallingLineIdRestriction(ErrorResult& aRv) { - if (!mMobileConnection) { + if (!mService) { aRv.Throw(NS_ERROR_FAILURE); return nullptr; } nsRefPtr<DOMRequest> request = new DOMRequest(GetOwner()); nsRefPtr<MobileConnectionCallback> requestCallback = new MobileConnectionCallback(GetOwner(), request); - nsresult rv = - mMobileConnection->GetCallingLineIdRestriction(requestCallback); + nsresult rv = mService->GetCallingLineIdRestriction(mClientId, + requestCallback); if (NS_FAILED(rv)) { aRv.Throw(rv); return nullptr; } return request.forget(); } already_AddRefed<DOMRequest> MobileConnection::SetCallingLineIdRestriction(uint16_t aMode, ErrorResult& aRv) { - if (!mMobileConnection) { + if (!mService) { aRv.Throw(NS_ERROR_FAILURE); return nullptr; } nsRefPtr<DOMRequest> request = new DOMRequest(GetOwner()); nsRefPtr<MobileConnectionCallback> requestCallback = new MobileConnectionCallback(GetOwner(), request); - nsresult rv = - mMobileConnection->SetCallingLineIdRestriction(aMode, requestCallback); + nsresult rv = mService->SetCallingLineIdRestriction(mClientId, aMode, + requestCallback); if (NS_FAILED(rv)) { aRv.Throw(rv); return nullptr; } return request.forget(); } already_AddRefed<DOMRequest> MobileConnection::ExitEmergencyCbMode(ErrorResult& aRv) { - if (!mMobileConnection) { + if (!mService) { aRv.Throw(NS_ERROR_FAILURE); return nullptr; } nsRefPtr<DOMRequest> request = new DOMRequest(GetOwner()); nsRefPtr<MobileConnectionCallback> requestCallback = new MobileConnectionCallback(GetOwner(), request); - nsresult rv = mMobileConnection->ExitEmergencyCbMode(requestCallback); + nsresult rv = mService->ExitEmergencyCbMode(mClientId, requestCallback); if (NS_FAILED(rv)) { aRv.Throw(rv); return nullptr; } return request.forget(); } already_AddRefed<DOMRequest> MobileConnection::SetRadioEnabled(bool aEnabled, ErrorResult& aRv) { - if (!mMobileConnection) { + if (!mService) { aRv.Throw(NS_ERROR_FAILURE); return nullptr; } nsRefPtr<DOMRequest> request = new DOMRequest(GetOwner()); nsRefPtr<MobileConnectionCallback> requestCallback = new MobileConnectionCallback(GetOwner(), request); - nsresult rv = mMobileConnection->SetRadioEnabled(aEnabled, requestCallback); + nsresult rv = mService->SetRadioEnabled(mClientId, aEnabled, requestCallback); if (NS_FAILED(rv)) { aRv.Throw(rv); return nullptr; } return request.forget(); }
--- a/dom/mobileconnection/MobileConnection.h +++ b/dom/mobileconnection/MobileConnection.h @@ -1,19 +1,19 @@ /* 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_MobileConnection_h #define mozilla_dom_MobileConnection_h +#include "MobileConnectionInfo.h" +#include "MobileNetworkInfo.h" #include "mozilla/DOMEventTargetHelper.h" #include "mozilla/dom/DOMRequest.h" -#include "mozilla/dom/MobileConnectionInfo.h" -#include "mozilla/dom/MobileNetworkInfo.h" #include "mozilla/dom/MozMobileConnectionBinding.h" #include "nsCycleCollectionParticipant.h" #include "nsIMobileConnectionService.h" #include "nsWeakPtr.h" namespace mozilla { namespace dom { @@ -158,17 +158,18 @@ public: IMPL_EVENT_HANDLER(iccchange) IMPL_EVENT_HANDLER(radiostatechange) IMPL_EVENT_HANDLER(clirmodechange) private: ~MobileConnection(); private: - nsCOMPtr<nsIMobileConnection> mMobileConnection; + uint32_t mClientId; + nsCOMPtr<nsIMobileConnectionService> mService; nsRefPtr<Listener> mListener; nsRefPtr<MobileConnectionInfo> mVoice; nsRefPtr<MobileConnectionInfo> mData; bool CheckPermission(const char* aType) const; void
--- a/dom/mobileconnection/MobileConnectionArray.cpp +++ b/dom/mobileconnection/MobileConnectionArray.cpp @@ -1,51 +1,59 @@ /* -*- 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/MobileConnectionArray.h" +#include "MobileConnectionArray.h" #include "mozilla/dom/MozMobileConnectionArrayBinding.h" #include "mozilla/Preferences.h" -#include "nsServiceManagerUtils.h" - -// Service instantiation -#include "ipc/MobileConnectionIPCService.h" -#if defined(MOZ_WIDGET_GONK) && defined(MOZ_B2G_RIL) -#include "nsIGonkMobileConnectionService.h" -#endif -#include "nsXULAppAPI.h" // For XRE_GetProcessType() using namespace mozilla::dom; NS_IMPL_CYCLE_COLLECTION_WRAPPERCACHE(MobileConnectionArray, mWindow, mMobileConnections) NS_IMPL_CYCLE_COLLECTING_ADDREF(MobileConnectionArray) NS_IMPL_CYCLE_COLLECTING_RELEASE(MobileConnectionArray) NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(MobileConnectionArray) NS_WRAPPERCACHE_INTERFACE_MAP_ENTRY NS_INTERFACE_MAP_ENTRY(nsISupports) NS_INTERFACE_MAP_END MobileConnectionArray::MobileConnectionArray(nsPIDOMWindow* aWindow) - : mLengthInitialized(false) + : mInitialized(false) , mWindow(aWindow) { + uint32_t numRil = mozilla::Preferences::GetUint("ril.numRadioInterfaces", 1); + MOZ_ASSERT(numRil > 0); + + mMobileConnections.SetLength(numRil); + SetIsDOMBinding(); } MobileConnectionArray::~MobileConnectionArray() { } +void +MobileConnectionArray::Init() +{ + mInitialized = true; + + for (uint32_t id = 0; id < mMobileConnections.Length(); id++) { + nsRefPtr<MobileConnection> mobileConnection = new MobileConnection(mWindow, id); + mMobileConnections[id] = mobileConnection; + } +} + nsPIDOMWindow* MobileConnectionArray::GetParentObject() const { MOZ_ASSERT(mWindow); return mWindow; } JSObject* @@ -57,58 +65,25 @@ MobileConnectionArray::WrapObject(JSCont MobileConnection* MobileConnectionArray::Item(uint32_t aIndex) { bool unused; return IndexedGetter(aIndex, unused); } uint32_t -MobileConnectionArray::Length() +MobileConnectionArray::Length() const { - if (!mLengthInitialized) { - mLengthInitialized = true; - - nsCOMPtr<nsIMobileConnectionService> service = - do_GetService(NS_MOBILE_CONNECTION_SERVICE_CONTRACTID); - NS_ENSURE_TRUE(service, 0); - - uint32_t length = 0; - nsresult rv = service->GetNumItems(&length); - NS_ENSURE_SUCCESS(rv, 0); - - mMobileConnections.SetLength(length); - } - return mMobileConnections.Length(); } MobileConnection* MobileConnectionArray::IndexedGetter(uint32_t aIndex, bool& aFound) { - - aFound = aIndex < Length(); - if (!aFound) { - return nullptr; - } - - if (!mMobileConnections[aIndex]) { - mMobileConnections[aIndex] = new MobileConnection(mWindow, aIndex); + if (!mInitialized) { + Init(); } - return mMobileConnections[aIndex]; -} - -already_AddRefed<nsIMobileConnectionService> -NS_CreateMobileConnectionService() -{ - nsCOMPtr<nsIMobileConnectionService> service; + aFound = false; + aFound = aIndex < mMobileConnections.Length(); - if (XRE_GetProcessType() == GeckoProcessType_Content) { - service = new mozilla::dom::mobileconnection::MobileConnectionIPCService(); - } else { -#if defined(MOZ_WIDGET_GONK) && defined(MOZ_B2G_RIL) - service = do_CreateInstance(GONK_MOBILECONNECTION_SERVICE_CONTRACTID); -#endif - } - - return service.forget(); + return aFound ? mMobileConnections[aIndex] : nullptr; }
--- a/dom/mobileconnection/MobileConnectionArray.h +++ b/dom/mobileconnection/MobileConnectionArray.h @@ -2,18 +2,18 @@ /* 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_network_MobileConnectionArray_h__ #define mozilla_dom_network_MobileConnectionArray_h__ -#include "mozilla/dom/MobileConnection.h" #include "nsWrapperCache.h" +#include "MobileConnection.h" namespace mozilla { namespace dom { class MobileConnectionArray MOZ_FINAL : public nsISupports , public nsWrapperCache { public: @@ -29,25 +29,28 @@ public: virtual JSObject* WrapObject(JSContext* aCx) MOZ_OVERRIDE; // WebIDL MobileConnection* Item(uint32_t aIndex); uint32_t - Length(); + Length() const; MobileConnection* IndexedGetter(uint32_t aIndex, bool& aFound); private: ~MobileConnectionArray(); - bool mLengthInitialized; + void + Init(); + + bool mInitialized; nsCOMPtr<nsPIDOMWindow> mWindow; nsTArray<nsRefPtr<MobileConnection>> mMobileConnections; }; } // namespace dom } // namespace mozilla
--- a/dom/mobileconnection/MobileConnectionCallback.cpp +++ b/dom/mobileconnection/MobileConnectionCallback.cpp @@ -1,24 +1,22 @@ /* 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 "MobileConnectionCallback.h" -#include "mozilla/dom/DOMMMIError.h" +#include "DOMMMIError.h" #include "mozilla/dom/MobileNetworkInfo.h" #include "mozilla/dom/MozMobileConnectionBinding.h" #include "mozilla/dom/ToJSValue.h" #include "nsJSUtils.h" #include "nsServiceManagerUtils.h" -namespace mozilla { -namespace dom { -namespace mobileconnection { +using namespace mozilla::dom; NS_IMPL_ISUPPORTS(MobileConnectionCallback, nsIMobileConnectionCallback) MobileConnectionCallback::MobileConnectionCallback(nsPIDOMWindow* aWindow, DOMRequest* aRequest) : mWindow(aWindow) , mRequest(aRequest) { @@ -314,12 +312,8 @@ MobileConnectionCallback::NotifyError(co case 3: error = new DOMMMIError(mWindow, aName, aMessage, aServiceCode, Nullable<int16_t>(int16_t(aInfo))); return rs->FireDetailedError(mRequest, error); } return NS_ERROR_FAILURE; } - -} // namespace mobileconnection -} // namespace dom -} // namespace mozilla
--- a/dom/mobileconnection/MobileConnectionCallback.h +++ b/dom/mobileconnection/MobileConnectionCallback.h @@ -1,32 +1,31 @@ /* 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_mobileconnection_MobileConnectionCallback_h -#define mozilla_dom_mobileconnection_MobileConnectionCallback_h +#ifndef mozilla_dom_MobileConnectionCallback_h +#define mozilla_dom_MobileConnectionCallback_h #include "mozilla/dom/DOMRequest.h" -#include "mozilla/dom/mobileconnection/MobileConnectionIPCSerializer.h" +#include "mozilla/dom/MobileConnectionIPCSerializer.h" #include "nsCOMPtr.h" #include "nsIMobileConnectionService.h" namespace mozilla { namespace dom { -namespace mobileconnection { /** * A callback object for handling asynchronous request/response. This object is * created when an asynchronous request is made and should be destroyed after * Notify*Success/Error is called. * The modules hold the reference of MobileConnectionCallback in OOP mode and * non-OOP mode are different. * - OOP mode: MobileConnectionRequestChild - * - non-OOP mode: MobileConnectionService + * - non-OOP mode: MobileConnectionGonkService * The reference should be released after Notify*Success/Error is called. */ class MobileConnectionCallback MOZ_FINAL : public nsIMobileConnectionCallback { public: NS_DECL_ISUPPORTS NS_DECL_NSIMOBILECONNECTIONCALLBACK @@ -68,13 +67,12 @@ private: nsresult NotifySuccess(JS::Handle<JS::Value> aResult); nsCOMPtr<nsPIDOMWindow> mWindow; nsRefPtr<DOMRequest> mRequest; }; -} // namespace mobileconnection -} // namespace dom -} // namespace mozilla +} // name space dom +} // name space mozilla -#endif // mozilla_dom_mobileconnection_MobileConnectionCallback_h +#endif // mozilla_dom_MobileConnectionCallback_h
--- a/dom/mobileconnection/MobileConnectionInfo.cpp +++ b/dom/mobileconnection/MobileConnectionInfo.cpp @@ -1,15 +1,15 @@ /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ /* vim:set ts=2 sw=2 sts=2 et cindent: */ /* 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/MobileConnectionInfo.h" +#include "MobileConnectionInfo.h" #include "mozilla/dom/ScriptSettings.h" #include "jsapi.h" #define CONVERT_STRING_TO_NULLABLE_ENUM(_string, _enumType, _enum) \ { \ _enum.SetNull(); \
--- a/dom/mobileconnection/MobileConnectionInfo.h +++ b/dom/mobileconnection/MobileConnectionInfo.h @@ -2,18 +2,18 @@ /* vim:set ts=2 sw=2 sts=2 et cindent: */ /* 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_MobileConnectionInfo_h #define mozilla_dom_MobileConnectionInfo_h -#include "mozilla/dom/MobileCellInfo.h" -#include "mozilla/dom/MobileNetworkInfo.h" +#include "MobileCellInfo.h" +#include "MobileNetworkInfo.h" #include "mozilla/dom/MozMobileConnectionInfoBinding.h" #include "nsIMobileConnectionInfo.h" #include "nsPIDOMWindow.h" #include "nsWrapperCache.h" namespace mozilla { namespace dom {
--- a/dom/mobileconnection/MobileNetworkInfo.cpp +++ b/dom/mobileconnection/MobileNetworkInfo.cpp @@ -1,15 +1,15 @@ /* -*- 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/MobileNetworkInfo.h" +#include "MobileNetworkInfo.h" using namespace mozilla::dom; NS_IMPL_CYCLE_COLLECTION_WRAPPERCACHE(MobileNetworkInfo, mWindow) NS_IMPL_CYCLE_COLLECTING_ADDREF(MobileNetworkInfo) NS_IMPL_CYCLE_COLLECTING_RELEASE(MobileNetworkInfo)
rename from dom/mobileconnection/gonk/MobileConnectionService.js rename to dom/mobileconnection/gonk/MobileConnectionGonkService.js --- a/dom/mobileconnection/gonk/MobileConnectionService.js +++ b/dom/mobileconnection/gonk/MobileConnectionGonkService.js @@ -9,23 +9,21 @@ const {classes: Cc, interfaces: Ci, util Cu.import("resource://gre/modules/Services.jsm"); Cu.import("resource://gre/modules/systemlibs.js"); Cu.import("resource://gre/modules/XPCOMUtils.jsm"); var RIL = {}; Cu.import("resource://gre/modules/ril_consts.js", RIL); -const GONK_MOBILECONNECTIONSERVICE_CONTRACTID = - "@mozilla.org/mobileconnection/gonkmobileconnectionservice;1"; +const MOBILECONNECTIONGONKSERVICE_CONTRACTID = + "@mozilla.org/mobileconnection/mobileconnectiongonkservice;1"; -const GONK_MOBILECONNECTIONSERVICE_CID = +const MOBILECONNECTIONGONKSERVICE_CID = Components.ID("{05e20430-fe65-4984-8df9-a6a504b24a91}"); -const MOBILECONNECTIONINFO_CID = - Components.ID("{8162b3c0-664b-45f6-96cd-f07b4e193b0e}"); const MOBILENETWORKINFO_CID = Components.ID("{a6c8416c-09b4-46d1-bf29-6520d677d085}"); const MOBILECELLINFO_CID = Components.ID("{0635d9ab-997e-4cdf-84e7-c1883752dff3}"); const NS_XPCOM_SHUTDOWN_OBSERVER_ID = "xpcom-shutdown"; const NS_PREFBRANCH_PREFCHANGE_TOPIC_ID = "nsPref:changed"; const NS_NETWORK_ACTIVE_CHANGED_TOPIC_ID = "network-active-changed"; @@ -41,17 +39,17 @@ XPCOMUtils.defineLazyServiceGetter(this, "nsINetworkManager"); XPCOMUtils.defineLazyServiceGetter(this, "gRadioInterfaceLayer", "@mozilla.org/ril;1", "nsIRadioInterfaceLayer"); let DEBUG = RIL.DEBUG_RIL; function debug(s) { - dump("MobileConnectionService: " + s + "\n"); + dump("MobileConnectionGonkService: " + s + "\n"); } function MobileNetworkInfo() { this.shortName = null; this.longName = null; this.mcc = null; this.mnc = null; this.stat = null; @@ -80,37 +78,16 @@ MobileCellInfo.prototype = { classID: MOBILECELLINFO_CID, classInfo: XPCOMUtils.generateCI({ classID: MOBILECELLINFO_CID, classDescription: "MobileCellInfo", interfaces: [Ci.nsIMobileCellInfo] }) }; -function MobileConnectionInfo() {} -MobileConnectionInfo.prototype = { - QueryInterface: XPCOMUtils.generateQI([Ci.nsIMobileConnectionInfo]), - classID: MOBILECONNECTIONINFO_CID, - classInfo: XPCOMUtils.generateCI({ - classID: MOBILECONNECTIONINFO_CID, - classDescription: "MobileConnectionInfo", - interfaces: [Ci.nsIMobileConnectionInfo] - }), - - state: null, - connected: false, - emergencyCallsOnly: false, - roaming: false, - network: null, - cell: null, - type: null, - signalStrength: null, - relSignalStrength: null -}; - function CallForwardingOptions(aOptions) { this.active = aOptions.active; this.action = aOptions.action; this.reason = aOptions.reason; this.number = aOptions.number; this.timeSeconds = aOptions.timeSeconds; this.serviceClass = aOptions.serviceClass; } @@ -137,37 +114,53 @@ MMIResult.prototype = { function MobileConnectionProvider(aClientId, aRadioInterface) { this._clientId = aClientId; this._radioInterface = aRadioInterface; this._operatorInfo = {}; // An array of nsIMobileConnectionListener instances. this._listeners = []; this.supportedNetworkTypes = this._getSupportedNetworkTypes(); - this.voice = new MobileConnectionInfo(); - this.data = new MobileConnectionInfo(); + // These objects implement the nsIMobileConnectionInfo interface, + // although the actual implementation lives in the content process. So are + // the child attributes `network` and `cell`, which implement + // nsIMobileNetworkInfo and nsIMobileCellInfo respectively. + this.voiceInfo = {connected: false, + emergencyCallsOnly: false, + roaming: false, + network: null, + cell: null, + type: null, + signalStrength: null, + relSignalStrength: null}; + this.dataInfo = {connected: false, + emergencyCallsOnly: false, + roaming: false, + network: null, + cell: null, + type: null, + signalStrength: null, + relSignalStrength: null}; } MobileConnectionProvider.prototype = { - QueryInterface: XPCOMUtils.generateQI([Ci.nsIMobileConnection]), - _clientId: null, _radioInterface: null, _operatorInfo: null, _listeners: null, /** * The networks that are currently trying to be selected (or "automatic"). * This helps ensure that only one network per client is selected at a time. */ _selectingNetwork: null, - voice: null, - data: null, + voiceInfo: null, + dataInfo: null, iccId: null, - networkSelectionMode: null, + networkSelectMode: null, radioState: null, lastKnownNetwork: null, lastKnownHomeNetwork: null, supportedNetworkTypes: null, /** * A utility function to dump debug message. */ @@ -214,53 +207,53 @@ MobileConnectionProvider.prototype = { return supportedNetworkTypes; }, /** * Helper for guarding us against invalid reason values for call forwarding. */ _isValidCallForwardingReason: function(aReason) { switch (aReason) { - case Ci.nsIMobileConnection.CALL_FORWARD_REASON_UNCONDITIONAL: - case Ci.nsIMobileConnection.CALL_FORWARD_REASON_MOBILE_BUSY: - case Ci.nsIMobileConnection.CALL_FORWARD_REASON_NO_REPLY: - case Ci.nsIMobileConnection.CALL_FORWARD_REASON_NOT_REACHABLE: - case Ci.nsIMobileConnection.CALL_FORWARD_REASON_ALL_CALL_FORWARDING: - case Ci.nsIMobileConnection.CALL_FORWARD_REASON_ALL_CONDITIONAL_CALL_FORWARDING: + case Ci.nsIMobileConnectionService.CALL_FORWARD_REASON_UNCONDITIONAL: + case Ci.nsIMobileConnectionService.CALL_FORWARD_REASON_MOBILE_BUSY: + case Ci.nsIMobileConnectionService.CALL_FORWARD_REASON_NO_REPLY: + case Ci.nsIMobileConnectionService.CALL_FORWARD_REASON_NOT_REACHABLE: + case Ci.nsIMobileConnectionService.CALL_FORWARD_REASON_ALL_CALL_FORWARDING: + case Ci.nsIMobileConnectionService.CALL_FORWARD_REASON_ALL_CONDITIONAL_CALL_FORWARDING: return true; default: return false; } }, /** * Helper for guarding us against invalid action values for call forwarding. */ _isValidCallForwardingAction: function(aAction) { switch (aAction) { - case Ci.nsIMobileConnection.CALL_FORWARD_ACTION_DISABLE: - case Ci.nsIMobileConnection.CALL_FORWARD_ACTION_ENABLE: - case Ci.nsIMobileConnection.CALL_FORWARD_ACTION_REGISTRATION: - case Ci.nsIMobileConnection.CALL_FORWARD_ACTION_ERASURE: + case Ci.nsIMobileConnectionService.CALL_FORWARD_ACTION_DISABLE: + case Ci.nsIMobileConnectionService.CALL_FORWARD_ACTION_ENABLE: + case Ci.nsIMobileConnectionService.CALL_FORWARD_ACTION_REGISTRATION: + case Ci.nsIMobileConnectionService.CALL_FORWARD_ACTION_ERASURE: return true; default: return false; } }, /** * Helper for guarding us against invalid program values for call barring. */ _isValidCallBarringProgram: function(aProgram) { switch (aProgram) { - case Ci.nsIMobileConnection.CALL_BARRING_PROGRAM_ALL_OUTGOING: - case Ci.nsIMobileConnection.CALL_BARRING_PROGRAM_OUTGOING_INTERNATIONAL: - case Ci.nsIMobileConnection.CALL_BARRING_PROGRAM_OUTGOING_INTERNATIONAL_EXCEPT_HOME: - case Ci.nsIMobileConnection.CALL_BARRING_PROGRAM_ALL_INCOMING: - case Ci.nsIMobileConnection.CALL_BARRING_PROGRAM_INCOMING_ROAMING: + case Ci.nsIMobileConnectionService.CALL_BARRING_PROGRAM_ALL_OUTGOING: + case Ci.nsIMobileConnectionService.CALL_BARRING_PROGRAM_OUTGOING_INTERNATIONAL: + case Ci.nsIMobileConnectionService.CALL_BARRING_PROGRAM_OUTGOING_INTERNATIONAL_EXCEPT_HOME: + case Ci.nsIMobileConnectionService.CALL_BARRING_PROGRAM_ALL_INCOMING: + case Ci.nsIMobileConnectionService.CALL_BARRING_PROGRAM_INCOMING_ROAMING: return true; default: return false; } }, /** * Helper for guarding us against invalid options for call barring. @@ -280,32 +273,32 @@ MobileConnectionProvider.prototype = { return true; }, /** * Helper for guarding us against invalid mode for clir. */ _isValidClirMode: function(aMode) { switch (aMode) { - case Ci.nsIMobileConnection.CLIR_DEFAULT: - case Ci.nsIMobileConnection.CLIR_INVOCATION: - case Ci.nsIMobileConnection.CLIR_SUPPRESSION: + case Ci.nsIMobileConnectionService.CLIR_DEFAULT: + case Ci.nsIMobileConnectionService.CLIR_INVOCATION: + case Ci.nsIMobileConnectionService.CLIR_SUPPRESSION: return true; default: return false; } }, /** * Fix the roaming. RIL can report roaming in some case it is not * really the case. See bug 787967 */ _checkRoamingBetweenOperators: function(aNetworkInfo) { // TODO: Bug 864489 - B2G RIL: use ipdl as IPC in MozIccManager - // Should get iccInfo from GonkIccProvider. + // Should get iccInfo from IccGonkProvider. let iccInfo = this._radioInterface.rilContext.iccInfo; let operator = aNetworkInfo.network; let state = aNetworkInfo.state; if (!iccInfo || !operator || state !== RIL.GECKO_MOBILE_CONNECTION_STATE_REGISTERED) { return false; } @@ -388,31 +381,31 @@ MobileConnectionProvider.prototype = { if (DEBUG) { this._debug("listener for " + aName + " threw an exception: " + e); } } } }, updateVoiceInfo: function(aNewInfo, aBatch = false) { - let isUpdated = this._updateInfo(this.voice, aNewInfo); + let isUpdated = this._updateInfo(this.voiceInfo, aNewInfo); // Make sure we also reset the operator and signal strength information // if we drop off the network. - if (this.voice.state !== RIL.GECKO_MOBILE_CONNECTION_STATE_REGISTERED) { - this.voice.cell = null; - this.voice.network = null; - this.voice.signalStrength = null; - this.voice.relSignalStrength = null; + if (this.voiceInfo.state !== RIL.GECKO_MOBILE_CONNECTION_STATE_REGISTERED) { + this.voiceInfo.cell = null; + this.voiceInfo.network = null; + this.voiceInfo.signalStrength = null; + this.voiceInfo.relSignalStrength = null; } else { - this.voice.network = this._operatorInfo; + this.voiceInfo.network = this._operatorInfo; } // Check roaming state - isUpdated = this._checkRoamingBetweenOperators(this.voice) || isUpdated; + isUpdated = this._checkRoamingBetweenOperators(this.voiceInfo) || isUpdated; if (isUpdated && !aBatch) { this.deliverListenerEvent("notifyVoiceChanged"); } }, updateDataInfo: function(aNewInfo, aBatch = false) { let isUpdated = false; @@ -422,31 +415,31 @@ MobileConnectionProvider.prototype = { let active = gNetworkManager.active; aNewInfo.connected = false; if (active && active.type === Ci.nsINetworkInterface.NETWORK_TYPE_MOBILE && active.serviceId === this._clientId) { aNewInfo.connected = true; } - isUpdated = this._updateInfo(this.data, aNewInfo); + isUpdated = this._updateInfo(this.dataInfo, aNewInfo); // Make sure we also reset the operator and signal strength information // if we drop off the network. - if (this.data.state !== RIL.GECKO_MOBILE_CONNECTION_STATE_REGISTERED) { - this.data.cell = null; - this.data.network = null; - this.data.signalStrength = null; - this.data.relSignalStrength = null; + if (this.dataInfo.state !== RIL.GECKO_MOBILE_CONNECTION_STATE_REGISTERED) { + this.dataInfo.cell = null; + this.dataInfo.network = null; + this.dataInfo.signalStrength = null; + this.dataInfo.relSignalStrength = null; } else { - this.data.network = this._operatorInfo; + this.dataInfo.network = this._operatorInfo; } // Check roaming state - isUpdated = this._checkRoamingBetweenOperators(this.data) || isUpdated; + isUpdated = this._checkRoamingBetweenOperators(this.dataInfo) || isUpdated; if (isUpdated && !aBatch) { this.deliverListenerEvent("notifyDataChanged"); } }, updateOperatorInfo: function(aNewInfo, aBatch = false) { let isUpdated = this._updateInfo(this._operatorInfo, aNewInfo); @@ -460,39 +453,39 @@ MobileConnectionProvider.prototype = { } this.lastKnownNetwork = network; this.deliverListenerEvent("notifyLastKnownNetworkChanged"); } } // If the voice is unregistered, no need to send notification. - if (this.voice.state !== RIL.GECKO_MOBILE_CONNECTION_STATE_REGISTERED && + if (this.voiceInfo.state !== RIL.GECKO_MOBILE_CONNECTION_STATE_REGISTERED && isUpdated && !aBatch) { this.deliverListenerEvent("notifyVoiceChanged"); } // If the data is unregistered, no need to send notification. - if (this.data.state !== RIL.GECKO_MOBILE_CONNECTION_STATE_REGISTERED && + if (this.dataInfo.state !== RIL.GECKO_MOBILE_CONNECTION_STATE_REGISTERED && isUpdated && !aBatch) { this.deliverListenerEvent("notifyDataChanged"); } }, updateSignalInfo: function(aNewInfo, aBatch = false) { // If the voice is not registered, no need to update signal information. - if (this.voice.state === RIL.GECKO_MOBILE_CONNECTION_STATE_REGISTERED) { - if (this._updateInfo(this.voice, aNewInfo.voice) && !aBatch) { + if (this.voiceInfo.state === RIL.GECKO_MOBILE_CONNECTION_STATE_REGISTERED) { + if (this._updateInfo(this.voiceInfo, aNewInfo.voice) && !aBatch) { this.deliverListenerEvent("notifyVoiceChanged"); } } // If the data is not registered, no need to update signal information. - if (this.data.state === RIL.GECKO_MOBILE_CONNECTION_STATE_REGISTERED) { - if (this._updateInfo(this.data, aNewInfo.data) && !aBatch) { + if (this.dataInfo.state === RIL.GECKO_MOBILE_CONNECTION_STATE_REGISTERED) { + if (this._updateInfo(this.dataInfo, aNewInfo.data) && !aBatch) { this.deliverListenerEvent("notifyDataChanged"); } } }, updateIccId: function(aIccId) { if (this.iccId === aIccId) { return; @@ -506,21 +499,16 @@ MobileConnectionProvider.prototype = { if (this.radioState === aRadioState) { return; } this.radioState = aRadioState; this.deliverListenerEvent("notifyRadioStateChanged"); }, - getSupportedNetworkTypes: function(aTypes) { - aTypes.value = this.supportedNetworkTypes.slice(); - return aTypes.value.length; - }, - getNetworks: function(aCallback) { this._radioInterface.sendWorkerMessage("getAvailableNetworks", null, (function(aResponse) { if (aResponse.errorMsg) { aCallback.notifyError(aResponse.errorMsg); return false; } @@ -957,41 +945,41 @@ MobileConnectionProvider.prototype = { } aCallback.notifySuccess(); return true; }).bind(this)); }, }; -function MobileConnectionService() { +function MobileConnectionGonkService() { this._providers = []; let numClients = gRadioInterfaceLayer.numRadioInterfaces; for (let i = 0; i < numClients; i++) { let radioInterface = gRadioInterfaceLayer.getRadioInterface(i); let provider = new MobileConnectionProvider(i, radioInterface); this._providers.push(provider); } Services.prefs.addObserver(kPrefRilDebuggingEnabled, this, false); Services.obs.addObserver(this, NS_NETWORK_ACTIVE_CHANGED_TOPIC_ID, false); Services.obs.addObserver(this, NS_XPCOM_SHUTDOWN_OBSERVER_ID, false); debug("init complete"); } -MobileConnectionService.prototype = { - classID: GONK_MOBILECONNECTIONSERVICE_CID, - classInfo: XPCOMUtils.generateCI({classID: GONK_MOBILECONNECTIONSERVICE_CID, - contractID: GONK_MOBILECONNECTIONSERVICE_CONTRACTID, - classDescription: "MobileConnectionService", - interfaces: [Ci.nsIGonkMobileConnectionService, +MobileConnectionGonkService.prototype = { + classID: MOBILECONNECTIONGONKSERVICE_CID, + classInfo: XPCOMUtils.generateCI({classID: MOBILECONNECTIONGONKSERVICE_CID, + contractID: MOBILECONNECTIONGONKSERVICE_CONTRACTID, + classDescription: "MobileConnectionGonkService", + interfaces: [Ci.nsIMobileConnectionGonkService, Ci.nsIMobileConnectionService], flags: Ci.nsIClassInfo.SINGLETON}), - QueryInterface: XPCOMUtils.generateQI([Ci.nsIGonkMobileConnectionService, + QueryInterface: XPCOMUtils.generateQI([Ci.nsIMobileConnectionGonkService, Ci.nsIMobileConnectionService, Ci.nsIObserver]), // An array of MobileConnectionProvider instances. _providers: null, _shutdown: function() { Services.prefs.removeObserver(kPrefRilDebuggingEnabled, this); @@ -1004,120 +992,435 @@ MobileConnectionService.prototype = { DEBUG = RIL.DEBUG_RIL || Services.prefs.getBoolPref(kPrefRilDebuggingEnabled); } catch (e) {} }, /** * nsIMobileConnectionService interface. */ - get numItems() { - return this._providers.length; + registerListener: function(aClientId, aListener) { + let provider = this._providers[aClientId]; + if (!provider) { + throw Cr.NS_ERROR_UNEXPECTED; + } + + provider.registerListener(aListener); + }, + + unregisterListener: function(aClientId, aListener) { + let provider = this._providers[aClientId]; + if (!provider) { + throw Cr.NS_ERROR_UNEXPECTED; + } + + provider.unregisterListener(aListener); + }, + + getVoiceConnectionInfo: function(aClientId) { + let provider = this._providers[aClientId]; + if (!provider) { + throw Cr.NS_ERROR_UNEXPECTED; + } + + return provider.voiceInfo; + }, + + getDataConnectionInfo: function(aClientId) { + let provider = this._providers[aClientId]; + if (!provider) { + throw Cr.NS_ERROR_UNEXPECTED; + } + + return provider.dataInfo; + }, + + getIccId: function(aClientId) { + let provider = this._providers[aClientId]; + if (!provider) { + throw Cr.NS_ERROR_UNEXPECTED; + } + + return provider.iccId; + }, + + getNetworkSelectionMode: function(aClientId) { + let provider = this._providers[aClientId]; + if (!provider) { + throw Cr.NS_ERROR_UNEXPECTED; + } + + return provider.networkSelectMode; + }, + + getRadioState: function(aClientId) { + let provider = this._providers[aClientId]; + if (!provider) { + throw Cr.NS_ERROR_UNEXPECTED; + } + + return provider.radioState; }, - getItemByServiceId: function(aServiceId) { - let provider = this._providers[aServiceId]; + getLastKnownNetwork: function(aClientId) { + let provider = this._providers[aClientId]; + if (!provider) { + throw Cr.NS_ERROR_UNEXPECTED; + } + + return provider.lastKnownNetwork; + }, + + getLastKnownHomeNetwork: function(aClientId) { + let provider = this._providers[aClientId]; + if (!provider) { + throw Cr.NS_ERROR_UNEXPECTED; + } + + return provider.lastKnownHomeNetwork; + }, + + getSupportedNetworkTypes: function(aClientId) { + let provider = this._providers[aClientId]; + if (!provider) { + throw Cr.NS_ERROR_UNEXPECTED; + } + + return provider.supportedNetworkTypes; + }, + + getNetworks: function(aClientId, aCallback) { + let provider = this._providers[aClientId]; + if (!provider) { + throw Cr.NS_ERROR_UNEXPECTED; + } + + provider.getNetworks(aCallback); + }, + + selectNetwork: function(aClientId, aNetwork, aCallback) { + let provider = this._providers[aClientId]; + if (!provider) { + throw Cr.NS_ERROR_UNEXPECTED; + } + + provider.selectNetwork(aNetwork, aCallback); + }, + + selectNetworkAutomatically: function(aClientId, aCallback) { + let provider = this._providers[aClientId]; + if (!provider) { + throw Cr.NS_ERROR_UNEXPECTED; + } + + provider.selectNetworkAutomatically(aCallback); + }, + + setPreferredNetworkType: function(aClientId, aType, aCallback) { + let provider = this._providers[aClientId]; + if (!provider) { + throw Cr.NS_ERROR_UNEXPECTED; + } + + provider.setPreferredNetworkType(aType, aCallback); + }, + + getPreferredNetworkType: function(aClientId, aCallback) { + let provider = this._providers[aClientId]; + if (!provider) { + throw Cr.NS_ERROR_UNEXPECTED; + } + + provider.getPreferredNetworkType(aCallback); + }, + + setRoamingPreference: function(aClientId, aMode, aCallback) { + let provider = this._providers[aClientId]; if (!provider) { throw Cr.NS_ERROR_UNEXPECTED; } - return provider; + provider.setRoamingPreference(aMode, aCallback); + }, + + getRoamingPreference: function(aClientId, aCallback) { + let provider = this._providers[aClientId]; + if (!provider) { + throw Cr.NS_ERROR_UNEXPECTED; + } + + provider.getRoamingPreference(aCallback); + }, + + setVoicePrivacyMode: function(aClientId, aEnabled, aCallback) { + let provider = this._providers[aClientId]; + if (!provider) { + throw Cr.NS_ERROR_UNEXPECTED; + } + + provider.setVoicePrivacyMode(aEnabled, aCallback); + }, + + getVoicePrivacyMode: function(aClientId, aCallback) { + let provider = this._providers[aClientId]; + if (!provider) { + throw Cr.NS_ERROR_UNEXPECTED; + } + + provider.getVoicePrivacyMode(aCallback); + }, + + sendMMI: function(aClientId, aMmi, aCallback) { + let provider = this._providers[aClientId]; + if (!provider) { + throw Cr.NS_ERROR_UNEXPECTED; + } + + provider.sendMMI(aMmi, aCallback); + }, + + cancelMMI: function(aClientId, aCallback) { + let provider = this._providers[aClientId]; + if (!provider) { + throw Cr.NS_ERROR_UNEXPECTED; + } + + provider.cancelMMI(aCallback); + }, + + setCallForwarding: function(aClientId, aOptions, aCallback) { + let provider = this._providers[aClientId]; + if (!provider) { + throw Cr.NS_ERROR_UNEXPECTED; + } + + provider.setCallForwarding(aOptions, aCallback); + }, + + getCallForwarding: function(aClientId, aReason, aCallback) { + let provider = this._providers[aClientId]; + if (!provider) { + throw Cr.NS_ERROR_UNEXPECTED; + } + + provider.getCallForwarding(aReason, aCallback); + }, + + setCallBarring: function(aClientId, aOptions, aCallback) { + let provider = this._providers[aClientId]; + if (!provider) { + throw Cr.NS_ERROR_UNEXPECTED; + } + + provider.setCallBarring(aOptions, aCallback); + }, + + getCallBarring: function(aClientId, aOptions, aCallback) { + let provider = this._providers[aClientId]; + if (!provider) { + throw Cr.NS_ERROR_UNEXPECTED; + } + + provider.getCallBarring(aOptions, aCallback); + }, + + changeCallBarringPassword: function(aClientId, aOptions, aCallback) { + let provider = this._providers[aClientId]; + if (!provider) { + throw Cr.NS_ERROR_UNEXPECTED; + } + + provider.changeCallBarringPassword(aOptions, aCallback); + }, + + setCallWaiting: function(aClientId, aEnabled, aCallback) { + let provider = this._providers[aClientId]; + if (!provider) { + throw Cr.NS_ERROR_UNEXPECTED; + } + + provider.setCallWaiting(aEnabled, aCallback); + }, + + getCallWaiting: function(aClientId, aCallback) { + let provider = this._providers[aClientId]; + if (!provider) { + throw Cr.NS_ERROR_UNEXPECTED; + } + + provider.getCallWaiting(aCallback); + }, + + setCallingLineIdRestriction: function(aClientId, aMode, aCallback) { + let provider = this._providers[aClientId]; + if (!provider) { + throw Cr.NS_ERROR_UNEXPECTED; + } + + provider.setCallingLineIdRestriction(aMode, aCallback); + }, + + getCallingLineIdRestriction: function(aClientId, aCallback) { + let provider = this._providers[aClientId]; + if (!provider) { + throw Cr.NS_ERROR_UNEXPECTED; + } + + provider.getCallingLineIdRestriction(aCallback); + }, + + exitEmergencyCbMode: function(aClientId, aCallback) { + let provider = this._providers[aClientId]; + if (!provider) { + throw Cr.NS_ERROR_UNEXPECTED; + } + + provider.exitEmergencyCbMode(aCallback); + }, + + setRadioEnabled: function(aClientId, aEnabled, aCallback) { + let provider = this._providers[aClientId]; + if (!provider) { + throw Cr.NS_ERROR_UNEXPECTED; + } + + provider.setRadioEnabled(aEnabled, aCallback); }, /** - * nsIGonkMobileConnectionService interface. + * nsIMobileConnectionGonkService interface. */ notifyVoiceInfoChanged: function(aClientId, aVoiceInfo) { if (DEBUG) { debug("notifyVoiceInfoChanged for " + aClientId + ": " + JSON.stringify(aVoiceInfo)); } - this.getItemByServiceId(aClientId).updateVoiceInfo(aVoiceInfo); + let provider = this._providers[aClientId]; + if (!provider) { + throw Cr.NS_ERROR_UNEXPECTED; + } + + provider.updateVoiceInfo(aVoiceInfo); }, notifyDataInfoChanged: function(aClientId, aDataInfo) { if (DEBUG) { debug("notifyDataInfoChanged for " + aClientId + ": " + JSON.stringify(aDataInfo)); } - this.getItemByServiceId(aClientId).updateDataInfo(aDataInfo); + let provider = this._providers[aClientId]; + if (!provider) { + throw Cr.NS_ERROR_UNEXPECTED; + } + + provider.updateDataInfo(aDataInfo); }, notifyUssdReceived: function(aClientId, aMessage, aSessionEnded) { if (DEBUG) { debug("notifyUssdReceived for " + aClientId + ": " + aMessage + " (sessionEnded : " + aSessionEnded + ")"); } - this.getItemByServiceId(aClientId) - .deliverListenerEvent("notifyUssdReceived", [aMessage, aSessionEnded]); + let provider = this._providers[aClientId]; + if (!provider) { + throw Cr.NS_ERROR_UNEXPECTED; + } + + provider.deliverListenerEvent("notifyUssdReceived", + [aMessage, aSessionEnded]); let info = { message: aMessage, sessionEnded: aSessionEnded, serviceId: aClientId }; gSystemMessenger.broadcastMessage("ussd-received", info); }, notifyDataError: function(aClientId, aMessage) { if (DEBUG) { debug("notifyDataError for " + aClientId + ": " + aMessage); } - this.getItemByServiceId(aClientId) - .deliverListenerEvent("notifyDataError", [aMessage]); + let provider = this._providers[aClientId]; + if (!provider) { + throw Cr.NS_ERROR_UNEXPECTED; + } + + provider.deliverListenerEvent("notifyDataError", [aMessage]); }, notifyEmergencyCallbackModeChanged: function(aClientId, aActive, aTimeoutMs) { if (DEBUG) { debug("notifyEmergencyCbModeChanged for " + aClientId + ": " + JSON.stringify({active: aActive, timeoutMs: aTimeoutMs})); } - this.getItemByServiceId(aClientId) - .deliverListenerEvent("notifyEmergencyCbModeChanged", - [aActive, aTimeoutMs]); + let provider = this._providers[aClientId]; + if (!provider) { + throw Cr.NS_ERROR_UNEXPECTED; + } + + provider.deliverListenerEvent("notifyEmergencyCbModeChanged", + [aActive, aTimeoutMs]); }, notifyOtaStatusChanged: function(aClientId, aStatus) { if (DEBUG) { debug("notifyOtaStatusChanged for " + aClientId + ": " + aStatus); } - this.getItemByServiceId(aClientId) - .deliverListenerEvent("notifyOtaStatusChanged", [aStatus]); + let provider = this._providers[aClientId]; + if (!provider) { + throw Cr.NS_ERROR_UNEXPECTED; + } + + provider.deliverListenerEvent("notifyOtaStatusChanged", [aStatus]); }, notifyIccChanged: function(aClientId, aIccId) { if (DEBUG) { debug("notifyIccChanged for " + aClientId + ": " + aIccId); } - this.getItemByServiceId(aClientId).updateIccId(aIccId); + let provider = this._providers[aClientId]; + if (!provider) { + throw Cr.NS_ERROR_UNEXPECTED; + } + + provider.updateIccId(aIccId); }, notifyRadioStateChanged: function(aClientId, aRadioState) { if (DEBUG) { debug("notifyRadioStateChanged for " + aClientId + ": " + aRadioState); } - this.getItemByServiceId(aClientId).updateRadioState(aRadioState); + let provider = this._providers[aClientId]; + if (!provider) { + throw Cr.NS_ERROR_UNEXPECTED; + } + + provider.updateRadioState(aRadioState); }, notifyNetworkInfoChanged: function(aClientId, aNetworkInfo) { if (DEBUG) { debug("notifyNetworkInfoChanged for " + aClientId + ": " + JSON.stringify(aNetworkInfo)); } - let provider = this.getItemByServiceId(aClientId); + let provider = this._providers[aClientId]; + if (!provider) { + throw Cr.NS_ERROR_UNEXPECTED; + } let isVoiceUpdated = false; let isDataUpdated = false; let operatorMessage = aNetworkInfo[RIL.NETWORK_INFO_OPERATOR]; let voiceMessage = aNetworkInfo[RIL.NETWORK_INFO_VOICE_REGISTRATION_STATE]; let dataMessage = aNetworkInfo[RIL.NETWORK_INFO_DATA_REGISTRATION_STATE]; let signalMessage = aNetworkInfo[RIL.NETWORK_INFO_SIGNAL]; let selectionMessage = aNetworkInfo[RIL.NETWORK_INFO_NETWORK_SELECTION_MODE]; @@ -1153,77 +1456,98 @@ MobileConnectionService.prototype = { }, notifySignalStrengthChanged: function(aClientId, aSignal) { if (DEBUG) { debug("notifySignalStrengthChanged for " + aClientId + ": " + JSON.stringify(aSignal)); } - this.getItemByServiceId(aClientId).updateSignalInfo(aSignal); + let provider = this._providers[aClientId]; + if (!provider) { + throw Cr.NS_ERROR_UNEXPECTED; + } + + provider.updateSignalInfo(aSignal); }, notifyOperatorChanged: function(aClientId, aOperator) { if (DEBUG) { debug("notifyOperatorChanged for " + aClientId + ": " + JSON.stringify(aOperator)); } - this.getItemByServiceId(aClientId).updateOperatorInfo(aOperator); + let provider = this._providers[aClientId]; + if (!provider) { + throw Cr.NS_ERROR_UNEXPECTED; + } + + provider.updateOperatorInfo(aOperator); }, notifyNetworkSelectModeChanged: function(aClientId, aMode) { if (DEBUG) { debug("notifyNetworkSelectModeChanged for " + aClientId + ": " + aMode); } - let provider = this.getItemByServiceId(aClientId); - if (provider.networkSelectionMode === aMode) { + let provider = this._providers[aClientId]; + if (!provider) { + throw Cr.NS_ERROR_UNEXPECTED; + } + + if (provider.networkSelectMode === aMode) { return; } - provider.networkSelectionMode = aMode; + provider.networkSelectMode = aMode; provider.deliverListenerEvent("notifyNetworkSelectionModeChanged"); }, notifySpnAvailable: function(aClientId) { if (DEBUG) { debug("notifySpnAvailable for " + aClientId); } - let provider = this.getItemByServiceId(aClientId); + let provider = this._providers[aClientId]; + if (!provider) { + throw Cr.NS_ERROR_UNEXPECTED; + } // Update voice roaming state provider.updateVoiceInfo({}); // Update data roaming state provider.updateDataInfo({}); }, notifyLastHomeNetworkChanged: function(aClientId, aNetwork) { if (DEBUG) { debug("notifyLastHomeNetworkChanged for " + aClientId + ": " + aNetwork); } - let provider = this.getItemByServiceId(aClientId); + let provider = this._providers[aClientId]; + if (!provider) { + throw Cr.NS_ERROR_UNEXPECTED; + } + if (provider.lastKnownHomeNetwork === aNetwork) { return; } provider.lastKnownHomeNetwork = aNetwork; provider.deliverListenerEvent("notifyLastKnownHomeNetworkChanged"); }, /** * nsIObserver interface. */ observe: function(aSubject, aTopic, aData) { switch (aTopic) { case NS_NETWORK_ACTIVE_CHANGED_TOPIC_ID: - for (let i = 0; i < this.numItems; i++) { + for (let i = 0; i < this._providers.length; i++) { let provider = this._providers[i]; // Update connected flag only. provider.updateDataInfo({}); } break; case NS_PREFBRANCH_PREFCHANGE_TOPIC_ID: if (aData === kPrefRilDebuggingEnabled) { this._updateDebugFlag(); @@ -1231,9 +1555,9 @@ MobileConnectionService.prototype = { break; case NS_XPCOM_SHUTDOWN_OBSERVER_ID: this._shutdown(); break; } } }; -this.NSGetFactory = XPCOMUtils.generateNSGetFactory([MobileConnectionService]); +this.NSGetFactory = XPCOMUtils.generateNSGetFactory([MobileConnectionGonkService]);
rename from dom/mobileconnection/gonk/MobileConnectionService.manifest rename to dom/mobileconnection/gonk/MobileConnectionGonkService.manifest --- a/dom/mobileconnection/gonk/MobileConnectionService.manifest +++ b/dom/mobileconnection/gonk/MobileConnectionGonkService.manifest @@ -1,2 +1,2 @@ -component {05e20430-fe65-4984-8df9-a6a504b24a91} MobileConnectionService.js -contract @mozilla.org/mobileconnection/gonkmobileconnectionservice;1 {05e20430-fe65-4984-8df9-a6a504b24a91} +component {05e20430-fe65-4984-8df9-a6a504b24a91} MobileConnectionGonkService.js +contract @mozilla.org/mobileconnection/mobileconnectiongonkservice;1 {05e20430-fe65-4984-8df9-a6a504b24a91}
new file mode 100644 --- /dev/null +++ b/dom/mobileconnection/interfaces/moz.build @@ -0,0 +1,21 @@ +# -*- Mode: python; c-basic-offset: 4; 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 += [ + 'nsICellInfo.idl', + 'nsIMobileCellInfo.idl', + 'nsIMobileConnectionInfo.idl', + 'nsIMobileConnectionService.idl', + 'nsIMobileNetworkInfo.idl', + 'nsINeighboringCellInfo.idl', +] + +if CONFIG['MOZ_WIDGET_TOOLKIT'] == 'gonk' and CONFIG['MOZ_B2G_RIL']: + XPIDL_SOURCES += [ + 'nsIMobileConnectionGonkService.idl', + ] + +XPIDL_MODULE = 'dom_mobileconnection'
rename from dom/mobileconnection/gonk/nsIGonkMobileConnectionService.idl rename to dom/mobileconnection/interfaces/nsIMobileConnectionGonkService.idl --- a/dom/mobileconnection/gonk/nsIGonkMobileConnectionService.idl +++ b/dom/mobileconnection/interfaces/nsIMobileConnectionGonkService.idl @@ -1,21 +1,21 @@ /* 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 "nsIMobileConnectionService.idl" %{C++ -#define GONK_MOBILECONNECTION_SERVICE_CONTRACTID \ - "@mozilla.org/mobileconnection/gonkmobileconnectionservice;1" +#define NS_MOBILECONNECTION_GONK_SERVICE_CONTRACTID \ + "@mozilla.org/mobileconnection/mobileconnectiongonkservice;1" %} -[scriptable, uuid(e54fa0a4-d357-48ef-9a1e-ffc9705b44b1)] -interface nsIGonkMobileConnectionService : nsIMobileConnectionService +[scriptable, uuid(c5baceda-247a-4018-855d-ad5b00f2e4e2)] +interface nsIMobileConnectionGonkService : nsIMobileConnectionService { void notifyNetworkInfoChanged(in unsigned long clientId, in jsval networkInfo); void notifyVoiceInfoChanged(in unsigned long clientId, in jsval voiceInfo); void notifyDataInfoChanged(in unsigned long clientId, in jsval dataInfo); void notifyDataError(in unsigned long clientId, in DOMString message);
--- a/dom/mobileconnection/interfaces/nsIMobileConnectionService.idl +++ b/dom/mobileconnection/interfaces/nsIMobileConnectionService.idl @@ -1,15 +1,14 @@ /* 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 nsIMobileConnection; interface nsIMobileConnectionInfo; interface nsIMobileNetworkInfo; interface nsIVariant; [scriptable, uuid(bc0d4d76-fd3a-4593-818f-cb6ff87fbb55)] interface nsIMobileConnectionListener : nsISupports { /** @@ -196,34 +195,23 @@ interface nsIMobileConnectionCallback : %{C++ #define NS_MOBILE_CONNECTION_SERVICE_CID \ { 0xc6f229d4, 0x16e2, 0x4600, \ { 0x87, 0x2a, 0x3d, 0x3d, 0xc5, 0xb8, 0x55, 0x41 } } #define NS_MOBILE_CONNECTION_SERVICE_CONTRACTID \ "@mozilla.org/mobileconnection/mobileconnectionservice;1" %} -[scriptable, uuid(eaba3c4a-0dd5-4919-b1a2-7812e49dbbcb)] +/** + * XPCOM component (in the content process) that provides the mobile + * network information. + */ +[scriptable, uuid(b50ad32d-f70e-4729-a947-e8cfdb6ba81f)] interface nsIMobileConnectionService : nsISupports { - readonly attribute unsigned long numItems; - - nsIMobileConnection getItemByServiceId(in unsigned long serviceId); -}; - -%{C++ -template<typename T> struct already_AddRefed; - -already_AddRefed<nsIMobileConnectionService> -NS_CreateMobileConnectionService(); -%} - -[scriptable, uuid(04db7331-54fe-4cf7-9347-b9481350f4c2)] -interface nsIMobileConnection : nsISupports -{ const long ICC_SERVICE_CLASS_VOICE = (1 << 0); const long ICC_SERVICE_CLASS_DATA = (1 << 1); const long ICC_SERVICE_CLASS_FAX = (1 << 2); const long ICC_SERVICE_CLASS_SMS = (1 << 3); const long ICC_SERVICE_CLASS_DATA_SYNC = (1 << 4); const long ICC_SERVICE_CLASS_DATA_ASYNC = (1 << 5); const long ICC_SERVICE_CLASS_PACKET = (1 << 6); const long ICC_SERVICE_CLASS_PAD = (1 << 7); @@ -265,447 +253,540 @@ interface nsIMobileConnection : nsISuppo * Calling line identification restriction constants. * * @see 3GPP TS 27.007 7.7 Defined values. */ const long CLIR_DEFAULT = 0; const long CLIR_INVOCATION = 1; const long CLIR_SUPPRESSION = 2; - readonly attribute unsigned long serviceId; - /** - * Called when any one who is interested in receiving unsolicited messages - * from this nsIMobileConnection instance. + * Called when a content process registers receiving unsolicited messages from + * RadioInterfaceLayer in the chrome process. Only a content process that has + * the 'mobileconnection' permission is allowed to register. */ - void registerListener(in nsIMobileConnectionListener listener); - void unregisterListener(in nsIMobileConnectionListener listener); + void registerListener(in unsigned long clientId, + in nsIMobileConnectionListener listener); + void unregisterListener(in unsigned long clientId, + in nsIMobileConnectionListener listener); /** - * String of format '<mcc>-<mnc>'. When changed, listener method - * 'notifyLastKnownNetworkChanged' is called. + * These two fields require the 'mobilenetwork' permission. */ - readonly attribute DOMString lastKnownNetwork; + DOMString getLastKnownNetwork(in unsigned long clientId); + DOMString getLastKnownHomeNetwork(in unsigned long clientId); /** - * String of format '<mcc>-<mnc>[-<spn>]'. When changed, listener method - * 'notifyLastKnownHomeNetworkChanged' is called. + * All fields below require the 'mobileconnection' permission. */ - readonly attribute DOMString lastKnownHomeNetwork; + + /** + * Get the connection information about the voice. + * + * @param clientId + * Indicate the RIL client, 0 ~ (number of client - 1). + * + * @return a nsIMobileConnectionInfo + */ + nsIMobileConnectionInfo getVoiceConnectionInfo(in unsigned long clientId); /** - * Connection information about the voice. + * Get the connection information about the data. + * + * @param clientId + * Indicate the RIL client, 0 ~ (number of client - 1). + * + * @return a nsIMobileConnectionInfo */ - readonly attribute nsIMobileConnectionInfo voice; + nsIMobileConnectionInfo getDataConnectionInfo(in unsigned long clientId); /** - * Connection information about the data. + * Get the integrated circuit card identifier of the SIM. + * + * @param clientId + * Indicate the RIL client, 0 ~ (number of client - 1). + * + * @return a DOMString indicates the iccId */ - readonly attribute nsIMobileConnectionInfo data; + DOMString getIccId(in unsigned long clientId); /** - * The integrated circuit card identifier of the SIM. + * Get the selection mode of the voice and data networks. + * + * @param clientId + * Indicate the RIL client, 0 ~ (number of client - 1). + * + * @return a DOMString + * Possible values: 'automatic', 'manual', null (unknown). */ - readonly attribute DOMString iccId; + DOMString getNetworkSelectionMode(in unsigned long clientId); /** - * The selection mode of the voice and data networks. Possible values are - * 'automatic', 'manual', null (unknown). + * Get the current radio state. + * + * @param clientId + * Indicate the RIL client, 0 ~ (number of client - 1). + * + * @return a DOMString + * Possible values: 'enabling', 'enabled', 'disabling', 'disabled', + * null (unknown). */ - readonly attribute DOMString networkSelectionMode; + DOMString getRadioState(in unsigned long clientId); /** - * Current radio state. Possible values are 'enabling', 'enabled', - * 'disabling', 'disabled', null (unknown). - */ - readonly attribute DOMString radioState; - - /** - * The network types supported by this radio. + * Get the network types that are supported by this radio. + * + * @param clientId + * Indicate the RIL client, 0 ~ (number of client - 1). * * @return an array of DOMString * Possible values: 'gsm', 'wcdma', 'cdma', 'evdo', 'lte'. */ - void getSupportedNetworkTypes([array, size_is(length)] out wstring types, - [retval] out unsigned long length); + nsIVariant getSupportedNetworkTypes(in unsigned long clientId); /** * Search for available networks. * + * @param clientId + * Indicate the RIL client, 0 ~ (number of client - 1). * @param requestCallback * Called when request is finished. * * If successful, the notifyGetNetworksSuccess() will be called. And the * result will be an array of nsIMobileNetworkInfo. * * Otherwise, the notifyError() will be called, and the error will be either * 'RadioNotAvailable', 'RequestNotSupported', 'IllegalSIMorME', or * 'GenericFailure'. */ - void getNetworks(in nsIMobileConnectionCallback requestCallback); + void getNetworks(in unsigned long clientId, + in nsIMobileConnectionCallback requestCallback); /** * Manually selects the passed in network, overriding the radio's current * selection. * + * @param clientId + * Indicate the RIL client, 0 ~ (number of client - 1). * @param network * The manually selecting network. * @param requestCallback * Called when request is finished. * * If successful, the notifySuccess() will be called. * * Otherwise, the notifyError() will be called, and the error will be either * 'RadioNotAvailable', 'RequestNotSupported', 'IllegalSIMorME', or * 'GenericFailure'. */ - void selectNetwork(in nsIMobileNetworkInfo network, + void selectNetwork(in unsigned long clientId, + in nsIMobileNetworkInfo network, in nsIMobileConnectionCallback requestCallback); /** * Tell the radio to automatically select a network. * + * @param clientId + * Indicate the RIL client, 0 ~ (number of client - 1). * @param requestCallback * Called when request is finished. * * If successful, the notifySuccess() will be called. * * Otherwise, the notifyError() will be called, and the error will be either * 'RadioNotAvailable', 'RequestNotSupported', 'IllegalSIMorME', or * 'GenericFailure'. */ - void selectNetworkAutomatically(in nsIMobileConnectionCallback requestCallback); + void selectNetworkAutomatically(in unsigned long clientId, + in nsIMobileConnectionCallback requestCallback); /** * Set preferred network type. * + * @param clientId + * Indicate the RIL client, 0 ~ (number of client - 1). * @param type * DOMString indicates the desired preferred network type. * Possible values: 'wcdma/gsm', 'gsm', 'wcdma', 'wcdma/gsm-auto', * 'cdma/evdo', 'cdma', 'evdo', 'wcdma/gsm/cdma/evdo', * 'lte/cdma/evdo', 'lte/wcdma/gsm', 'lte/wcdma/gsm/cdma/evdo' or * 'lte'. * @param requestCallback * Called when request is finished. * * If successful, the notifySuccess() will be called. * * Otherwise, the notifyError() will be called, and the error will be either * 'RadioNotAvailable', 'RequestNotSupported', 'InvalidParameter', * 'IllegalSIMorME', or 'GenericFailure'. */ - void setPreferredNetworkType(in DOMString type, + void setPreferredNetworkType(in unsigned long clientId, + in DOMString type, in nsIMobileConnectionCallback requestCallback); /** * Query current preferred network type. * + * @param clientId + * Indicate the RIL client, 0 ~ (number of client - 1). * @param requestCallback * Called when request is finished. * * If successful, the notifySuccessString() will be called. And the result * will be a string indicating the current preferred network type. The value * will be either 'wcdma/gsm', 'gsm', 'wcdma', 'wcdma/gsm-auto', 'cdma/evdo', * 'cdma', 'evdo', 'wcdma/gsm/cdma/evdo', 'lte/cdma/evdo', 'lte/wcdma/gsm', * 'lte/wcdma/gsm/cdma/evdo' or 'lte'. * * Otherwise, the notifyError() will be called, and the error will be either * 'RadioNotAvailable', 'RequestNotSupported', 'IllegalSIMorME', or * 'GenericFailure'. */ - void getPreferredNetworkType(in nsIMobileConnectionCallback requestCallback); + void getPreferredNetworkType(in unsigned long clientId, + in nsIMobileConnectionCallback requestCallback); /** * Set roaming preference. * + * @param clientId + * Indicate the RIL client, 0 ~ (number of client - 1). * @param mode * DOMString indicates the desired roaming preference. * Possible values: 'home', 'affiliated', or 'any'. * @param requestCallback * Called when request is finished. * * If successful, the notifySuccess() will be called. * * Otherwise, the notifyError() will be called, and the error will be either * 'RadioNotAvailable', 'RequestNotSupported', InvalidParameter', * 'IllegalSIMorME', or 'GenericFailure'. */ - void setRoamingPreference(in DOMString mode, + void setRoamingPreference(in unsigned long clientId, + in DOMString mode, in nsIMobileConnectionCallback requestCallback); /** * Query current roaming preference. * + * @param clientId + * Indicate the RIL client, 0 ~ (number of client - 1). * @param requestCallback * Called when request is finished. * * If successful, the notifySuccessWithString() will be called. And the result * will be a string indicating the current roaming preference. The value will * be either 'home', 'affiliated', or 'any'. * * Otherwise, the notifyError() will be called, and the error will be either * 'RadioNotAvailable', 'RequestNotSupported', 'IllegalSIMorME', or * 'GenericFailure'. */ - void getRoamingPreference(in nsIMobileConnectionCallback requestCallback); + void getRoamingPreference(in unsigned long clientId, + in nsIMobileConnectionCallback requestCallback); /** * Set voice privacy preference. * + * @param clientId + * Indicate the RIL client, 0 ~ (number of client - 1). * @param enabled * Boolean indicates the preferred voice privacy mode used in voice * scrambling in CDMA networks. 'True' means the enhanced voice security * is required. * @param requestCallback * Called when request is finished. * * If successful, the notifySuccess() will be called. * * Otherwise, the notifyError() will be called, and the error will be either * 'RadioNotAvailable', 'RequestNotSupported', 'IllegalSIMorME', or * 'GenericFailure'. */ - void setVoicePrivacyMode(in bool enabled, + void setVoicePrivacyMode(in unsigned long clientId, + in bool enabled, in nsIMobileConnectionCallback requestCallback); /** * Query current voice privacy mode. * + * @param clientId + * Indicate the RIL client, 0 ~ (number of client - 1). * @param requestCallback * Called when request is finished. * * If successful, the notifySuccessWithBoolean() will be called. And the result * will be a boolean indicating the current voice privacy mode. * * Otherwise, the notifyError() will be called, and the error will be either * 'RadioNotAvailable', 'RequestNotSupported', 'IllegalSIMorME', or * 'GenericFailure'. */ - void getVoicePrivacyMode(in nsIMobileConnectionCallback requestCallback); + void getVoicePrivacyMode(in unsigned long clientId, + in nsIMobileConnectionCallback requestCallback); /** * Send a MMI message. * + * @param clientId + * Indicate the RIL client, 0 ~ (number of client - 1). * @param mmi * DOMString containing an MMI string that can be associated to a * USSD request or other RIL functionality. * @param requestCallback * Called when request is finished. * * If successful, the notifySendCancelMmiSuccess() will be called. And the * result will contain the information about the mmi operation. * * Otherwise, the notifyError() will be called. */ - void sendMMI(in DOMString mmi, + void sendMMI(in unsigned long clientId, + in DOMString mmi, in nsIMobileConnectionCallback requestCallback); /** * Cancel the current MMI request if one exists. * + * @param clientId + * Indicate the RIL client, 0 ~ (number of client - 1). * @param requestCallback * Called when request is finished. * * If successful, the notifySendCancelMmiSuccess() will be called. And the * result will contain the information about the mmi operation. * * Otherwise, the notifyError() will be called. */ - void cancelMMI(in nsIMobileConnectionCallback requestCallback); + void cancelMMI(in unsigned long clientId, + in nsIMobileConnectionCallback requestCallback); /** * Queries current call forwarding options. * + * @param clientId + * Indicate the RIL client, 0 ~ (number of client - 1). * @param reason * Indicates the reason the call is being forwarded. It shall be one of * the nsIMobileConnectionService.CALL_FORWARD_REASON_* values. * @param requestCallback * Called when request is finished. * * If successful, the notifyGetCallForwardingSuccess() will be called. And the * result will be an array of MozCallForwardingOptions. * @see MozCallForwardingOptions for the detail of result. * * Otherwise, the notifyError() will be called, and the error will be either * 'RadioNotAvailable', 'RequestNotSupported', 'InvalidParameter', * 'IllegalSIMorME', or 'GenericFailure'. */ - void getCallForwarding(in unsigned short reason, + void getCallForwarding(in unsigned long clientId, + in unsigned short reason, in nsIMobileConnectionCallback requestCallback); /** * Configures call forwarding options. * + * @param clientId + * Indicate the RIL client, 0 ~ (number of client - 1). * @param options * An object containing the call forward rule to set. * @see MozCallForwardingOptions for the detail of options. * @param requestCallback * Called when request is finished. * * If successful, the notifySuccess() will be called. * * Otherwise, the notifyError() will be called, and the error will be either * 'RadioNotAvailable', 'RequestNotSupported', 'InvalidParameter', * 'IllegalSIMorME', or 'GenericFailure'. */ - void setCallForwarding(in jsval options, + void setCallForwarding(in unsigned long clientId, + in jsval options, in nsIMobileConnectionCallback requestCallback); /** * Queries current call barring status. * + * @param clientId + * Indicate the RIL client, 0 ~ (number of client - 1). * @param options * An object containing the call barring rule to query. No need to * specify 'enabled' property. * @see MozCallBarringOptions for the detail of options. * @param requestCallback * Called when request is finished. * * If successful, the notifyGetCallBarringSuccess() will be called. And the * result will contain correct 'enabled' property indicating the status of * this rule. * * Otherwise, the notifyError() will be called, and the error will be either * 'RadioNotAvailable', 'RequestNotSupported', 'InvalidParameter', * 'IllegalSIMorME', or 'GenericFailure'. */ - void getCallBarring(in jsval options, + void getCallBarring(in unsigned long clientId, + in jsval options, in nsIMobileConnectionCallback requestCallback); /** * Configures call barring option. * + * @param clientId + * Indicate the RIL client, 0 ~ (number of client - 1). * @param options * An object containing the call barring rule to set. * @see MozCallBarringOptions for the detail of options. * @param requestCallback * Called when request is finished. * * If successful, the notifySuccess() will be called. * * Otherwise, the notifyError() will be called, and the error will be either * 'RadioNotAvailable', 'RequestNotSupported', 'InvalidParameter', * 'IllegalSIMorME', or 'GenericFailure'. */ - void setCallBarring(in jsval options, + void setCallBarring(in unsigned long clientId, + in jsval options, in nsIMobileConnectionCallback requestCallback); /** * Change call barring facility password. * + * @param clientId + * Indicate the RIL client, 0 ~ (number of client - 1). * @param options * An object containing information about pin and newPin, and, * this object must have both "pin" and "newPin" attributes * to change the call barring facility password. * @see MozCallBarringOptions for the detail of options. * @param requestCallback * Called when request is finished. * * If successful, the notifySuccess() will be called. * * Otherwise, the notifyError() will be called, and the error will be either * 'RadioNotAvailable', 'RequestNotSupported', 'InvalidParameter', * 'IllegalSIMorME', or 'GenericFailure'. */ - void changeCallBarringPassword(in jsval options, + void changeCallBarringPassword(in unsigned long clientId, + in jsval options, in nsIMobileConnectionCallback requestCallback); /** * Configures call waiting options. * + * @param clientId + * Indicate the RIL client, 0 ~ (number of client - 1). * @param enabled * Boolean indicates the desired call waiting status. * @param requestCallback * Called when request is finished. * * If successful, the notifySuccess() will be called. * * Otherwise, the notifyError() will be called, and the error will be either * 'RadioNotAvailable', 'RequestNotSupported', 'IllegalSIMorME', or * 'GenericFailure'. */ - void setCallWaiting(in bool enabled, + void setCallWaiting(in unsigned long clientId, + in bool enabled, in nsIMobileConnectionCallback requestCallback); /** * Queries current call waiting options. * + * @param clientId + * Indicate the RIL client, 0 ~ (number of client - 1). * @param requestCallback * Called when request is finished. * * If successful, the notifySuccessWithBoolean() will be called. And the result * will be a boolean indicating the call waiting status. * * Otherwise, the notifyError() will be called, and the error will be either * 'RadioNotAvailable', 'RequestNotSupported', 'IllegalSIMorME', or * 'GenericFailure'. */ - void getCallWaiting(in nsIMobileConnectionCallback requestCallback); + void getCallWaiting(in unsigned long clientId, + in nsIMobileConnectionCallback requestCallback); /** * Enables or disables the presentation of the calling line identity (CLI) to * the called party when originating a call. * + * @param clientId + * Indicate the RIL client, 0 ~ (number of client - 1). * @param clirMode * One of the nsIMobileConnectionService.CLIR_* values. * @param requestCallback * Called when request is finished. * * If successful, the notifySuccess() will be called. * * Otherwise, the notifyError() will be called, and the error will be either * 'RadioNotAvailable', 'RequestNotSupported', 'InvalidParameter', * 'IllegalSIMorME', or 'GenericFailure'. */ - void setCallingLineIdRestriction(in unsigned short clirMode, + void setCallingLineIdRestriction(in unsigned long clientId, + in unsigned short clirMode, in nsIMobileConnectionCallback requestCallback); /** * Queries current CLIR status. * + * @param clientId + * Indicate the RIL client, 0 ~ (number of client - 1). * @param requestCallback * Called when request is finished. * * If successful, the notifyGetClirStatusSuccess() will be called. And the * result will be a an object containing CLIR 'n' and 'm' parameter. * @see MozClirStatus for the detail of result. * * Otherwise, the notifyError() will be called, and the error will be either * 'RadioNotAvailable', 'RequestNotSupported', 'IllegalSIMorME', or * 'GenericFailure'. */ - void getCallingLineIdRestriction(in nsIMobileConnectionCallback requestCallback); + void getCallingLineIdRestriction(in unsigned long clientId, + in nsIMobileConnectionCallback requestCallback); /** * Exit emergency callback mode. * + * @param clientId + * Indicate the RIL client, 0 ~ (number of client - 1). * @param requestCallback * Called when request is finished. * * If successful, the notifySuccess() will be called. * * Otherwise, the notifyError() will be called, and the error will be either * 'RadioNotAvailable', 'RequestNotSupported', 'IllegalSIMorME', or * 'GenericFailure'. */ - void exitEmergencyCbMode(in nsIMobileConnectionCallback requestCallback); + void exitEmergencyCbMode(in unsigned long clientId, + in nsIMobileConnectionCallback requestCallback); /** * Set radio enabled/disabled. * + * @param clientId + * Indicate the RIL client, 0 ~ (number of client - 1). * @param enabled * Boolean indicates the desired radio power. True to enable the radio. * @param requestCallback * Called when request is finished. * * If successful, the notifySuccess() will be called. * * Otherwise, the notifyError() will be called, and the error will be either * 'InvalidStateError', 'RadioNotAvailable', 'IllegalSIMorME', or * 'GenericFailure'. * * Note: Request is not available when radioState is null, 'enabling', or * 'disabling'. Calling the function in above conditions will receive * 'InvalidStateError' error. */ - void setRadioEnabled(in bool enabled, + void setRadioEnabled(in unsigned long clientId, + in bool enabled, in nsIMobileConnectionCallback requestCallback); };
--- a/dom/mobileconnection/ipc/MobileConnectionChild.cpp +++ b/dom/mobileconnection/ipc/MobileConnectionChild.cpp @@ -1,366 +1,157 @@ /* 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/mobileconnection/MobileConnectionChild.h" +#include "MobileConnectionChild.h" #include "MobileConnectionCallback.h" #include "mozilla/dom/MozMobileConnectionBinding.h" #include "nsComponentManagerUtils.h" using namespace mozilla::dom; using namespace mozilla::dom::mobileconnection; -NS_IMPL_ISUPPORTS(MobileConnectionChild, nsIMobileConnection) - -MobileConnectionChild::MobileConnectionChild(uint32_t aServiceId) - : mServiceId(aServiceId) - , mLive(true) -{ - MOZ_COUNT_CTOR(MobileConnectionChild); -} - void MobileConnectionChild::Init() { nsIMobileConnectionInfo* rawVoice; nsIMobileConnectionInfo* rawData; + nsTArray<nsString> types; SendInit(&rawVoice, &rawData, &mLastNetwork, &mLastHomeNetwork, &mIccId, - &mNetworkSelectionMode, &mRadioState, &mSupportedNetworkTypes); + &mNetworkSelectionMode, &mRadioState, &types); // Use dont_AddRef here because this instances is already AddRef-ed in // MobileConnectionIPCSerializer.h nsCOMPtr<nsIMobileConnectionInfo> voice = dont_AddRef(rawVoice); mVoice = new MobileConnectionInfo(nullptr); mVoice->Update(voice); // Use dont_AddRef here because this instances is already AddRef-ed in // MobileConnectionIPCSerializer.h nsCOMPtr<nsIMobileConnectionInfo> data = dont_AddRef(rawData); mData = new MobileConnectionInfo(nullptr); mData->Update(data); + + + // Initial SupportedNetworkTypes + nsresult rv; + mSupportedNetworkTypes = do_CreateInstance(NS_VARIANT_CONTRACTID, &rv); + + if (NS_FAILED(rv)) { + return; + } + + uint32_t arrayLen = types.Length(); + if (arrayLen == 0) { + mSupportedNetworkTypes->SetAsEmptyArray(); + } else { + // Note: The resulting nsIVariant dupes both the array and its elements. + const char16_t** array = reinterpret_cast<const char16_t**> + (NS_Alloc(arrayLen * sizeof(const char16_t***))); + if (array) { + for (uint32_t i = 0; i < arrayLen; ++i) { + array[i] = types[i].get(); + } + + mSupportedNetworkTypes->SetAsArray(nsIDataType::VTYPE_WCHAR_STR, + nullptr, + arrayLen, + reinterpret_cast<void*>(array)); + NS_Free(array); + } + } } void MobileConnectionChild::Shutdown() { if (mLive) { mLive = false; Send__delete__(this); } mListeners.Clear(); mVoice = nullptr; mData = nullptr; -} - -// nsIMobileConnection - -NS_IMETHODIMP -MobileConnectionChild::GetServiceId(uint32_t* aServiceId) -{ - *aServiceId = mServiceId; - return NS_OK; + mSupportedNetworkTypes = nullptr; } -NS_IMETHODIMP +void MobileConnectionChild::RegisterListener(nsIMobileConnectionListener* aListener) { - NS_ENSURE_TRUE(!mListeners.Contains(aListener), NS_ERROR_UNEXPECTED); - - mListeners.AppendObject(aListener); - return NS_OK; + if (!mListeners.Contains(aListener)) { + mListeners.AppendObject(aListener); + } } -NS_IMETHODIMP +void MobileConnectionChild::UnregisterListener(nsIMobileConnectionListener* aListener) { - NS_ENSURE_TRUE(mListeners.Contains(aListener), NS_ERROR_UNEXPECTED); - mListeners.RemoveObject(aListener); - return NS_OK; } -NS_IMETHODIMP -MobileConnectionChild::GetVoice(nsIMobileConnectionInfo** aVoice) +MobileConnectionInfo* +MobileConnectionChild::GetVoiceInfo() { - nsRefPtr<nsIMobileConnectionInfo> voice(mVoice); - voice.forget(aVoice); - return NS_OK; + return mVoice; } -NS_IMETHODIMP -MobileConnectionChild::GetData(nsIMobileConnectionInfo** aData) +MobileConnectionInfo* +MobileConnectionChild::GetDataInfo() { - nsRefPtr<nsIMobileConnectionInfo> data(mData); - data.forget(aData); - return NS_OK; + return mData; } -NS_IMETHODIMP +void MobileConnectionChild::GetIccId(nsAString& aIccId) { aIccId = mIccId; - return NS_OK; } -NS_IMETHODIMP +void MobileConnectionChild::GetRadioState(nsAString& aRadioState) { aRadioState = mRadioState; - return NS_OK; +} + +nsIVariant* +MobileConnectionChild::GetSupportedNetworkTypes() +{ + return mSupportedNetworkTypes; } -NS_IMETHODIMP -MobileConnectionChild::GetSupportedNetworkTypes(char16_t*** aTypes, - uint32_t* aLength) +void +MobileConnectionChild::GetLastNetwork(nsAString& aNetwork) { - NS_ENSURE_ARG(aTypes); - NS_ENSURE_ARG(aLength); - - *aLength = mSupportedNetworkTypes.Length(); - *aTypes = - static_cast<char16_t**>(nsMemory::Alloc((*aLength) * sizeof(char16_t*))); - NS_ENSURE_TRUE(*aTypes, NS_ERROR_OUT_OF_MEMORY); - - for (uint32_t i = 0; i < *aLength; i++) { - (*aTypes)[i] = ToNewUnicode(mSupportedNetworkTypes[i]); - } - - return NS_OK; + aNetwork = mLastNetwork; } -NS_IMETHODIMP -MobileConnectionChild::GetLastKnownNetwork(nsAString& aNetwork) +void +MobileConnectionChild::GetLastHomeNetwork(nsAString& aNetwork) { - aNetwork = mLastNetwork; - return NS_OK; + aNetwork = mLastHomeNetwork; } -NS_IMETHODIMP -MobileConnectionChild::GetLastKnownHomeNetwork(nsAString& aNetwork) -{ - aNetwork = mLastHomeNetwork; - return NS_OK; -} - -NS_IMETHODIMP +void MobileConnectionChild::GetNetworkSelectionMode(nsAString& aMode) { aMode = mNetworkSelectionMode; - return NS_OK; -} - -NS_IMETHODIMP -MobileConnectionChild::GetNetworks(nsIMobileConnectionCallback* aCallback) -{ - return SendRequest(GetNetworksRequest(), aCallback) ? NS_OK : NS_ERROR_FAILURE; -} - -NS_IMETHODIMP -MobileConnectionChild::SelectNetwork(nsIMobileNetworkInfo* aNetwork, - nsIMobileConnectionCallback* aCallback) -{ - nsCOMPtr<nsIMobileNetworkInfo> network = aNetwork; - // We release the ref after serializing process is finished in - // MobileConnectionIPCSerializer. - return SendRequest(SelectNetworkRequest(network.forget().take()), aCallback) - ? NS_OK : NS_ERROR_FAILURE; -} - -NS_IMETHODIMP -MobileConnectionChild::SelectNetworkAutomatically(nsIMobileConnectionCallback* aCallback) -{ - return SendRequest(SelectNetworkAutoRequest(), aCallback) - ? NS_OK : NS_ERROR_FAILURE; -} - - -NS_IMETHODIMP -MobileConnectionChild::SetPreferredNetworkType(const nsAString& aType, - nsIMobileConnectionCallback* aCallback) -{ - return SendRequest(SetPreferredNetworkTypeRequest(nsAutoString(aType)), - aCallback) - ? NS_OK : NS_ERROR_FAILURE; -} - -NS_IMETHODIMP -MobileConnectionChild::GetPreferredNetworkType(nsIMobileConnectionCallback* aCallback) -{ - return SendRequest(GetPreferredNetworkTypeRequest(), aCallback) - ? NS_OK : NS_ERROR_FAILURE; -} - -NS_IMETHODIMP -MobileConnectionChild::SetRoamingPreference(const nsAString& aMode, - nsIMobileConnectionCallback* aCallback) -{ - return SendRequest(SetRoamingPreferenceRequest(nsAutoString(aMode)), - aCallback) - ? NS_OK : NS_ERROR_FAILURE; -} - -NS_IMETHODIMP -MobileConnectionChild::GetRoamingPreference(nsIMobileConnectionCallback* aCallback) -{ - return SendRequest(GetRoamingPreferenceRequest(), aCallback) - ? NS_OK : NS_ERROR_FAILURE; -} - -NS_IMETHODIMP -MobileConnectionChild::SetVoicePrivacyMode(bool aEnabled, - nsIMobileConnectionCallback* aCallback) -{ - return SendRequest(SetVoicePrivacyModeRequest(aEnabled), aCallback) - ? NS_OK : NS_ERROR_FAILURE; -} - -NS_IMETHODIMP -MobileConnectionChild::GetVoicePrivacyMode(nsIMobileConnectionCallback* aCallback) -{ - return SendRequest(GetVoicePrivacyModeRequest(), aCallback) - ? NS_OK : NS_ERROR_FAILURE; -} - -NS_IMETHODIMP -MobileConnectionChild::SendMMI(const nsAString& aMmi, - nsIMobileConnectionCallback* aCallback) -{ - return SendRequest(SendMmiRequest(nsAutoString(aMmi)), aCallback) - ? NS_OK : NS_ERROR_FAILURE; -} - -NS_IMETHODIMP -MobileConnectionChild::CancelMMI(nsIMobileConnectionCallback* aCallback) -{ - return SendRequest(CancelMmiRequest(), aCallback) ? NS_OK : NS_ERROR_FAILURE; -} - -NS_IMETHODIMP -MobileConnectionChild::SetCallForwarding(JS::Handle<JS::Value> aOptions, - nsIMobileConnectionCallback* aCallback) -{ - AutoSafeJSContext cx; - IPC::MozCallForwardingOptions options; - if(!options.Init(cx, aOptions)) { - return NS_ERROR_TYPE_ERR; - } - - return SendRequest(SetCallForwardingRequest(options), aCallback) - ? NS_OK : NS_ERROR_FAILURE; -} - -NS_IMETHODIMP -MobileConnectionChild::GetCallForwarding(uint16_t aReason, - nsIMobileConnectionCallback* aCallback) -{ - return SendRequest(GetCallForwardingRequest(aReason), aCallback) - ? NS_OK : NS_ERROR_FAILURE; -} - -NS_IMETHODIMP -MobileConnectionChild::SetCallBarring(JS::Handle<JS::Value> aOptions, - nsIMobileConnectionCallback* aCallback) -{ - AutoSafeJSContext cx; - IPC::MozCallBarringOptions options; - if(!options.Init(cx, aOptions)) { - return NS_ERROR_TYPE_ERR; - } - - return SendRequest(SetCallBarringRequest(options), aCallback) - ? NS_OK : NS_ERROR_FAILURE; -} - -NS_IMETHODIMP -MobileConnectionChild::GetCallBarring(JS::Handle<JS::Value> aOptions, - nsIMobileConnectionCallback* aCallback) -{ - AutoSafeJSContext cx; - IPC::MozCallBarringOptions options; - if(!options.Init(cx, aOptions)) { - return NS_ERROR_TYPE_ERR; - } - - return SendRequest(GetCallBarringRequest(options), aCallback) - ? NS_OK : NS_ERROR_FAILURE; -} - -NS_IMETHODIMP -MobileConnectionChild::ChangeCallBarringPassword(JS::Handle<JS::Value> aOptions, - nsIMobileConnectionCallback* aCallback) -{ - AutoSafeJSContext cx; - IPC::MozCallBarringOptions options; - if(!options.Init(cx, aOptions)) { - return NS_ERROR_TYPE_ERR; - } - - return SendRequest(ChangeCallBarringPasswordRequest(options), aCallback) - ? NS_OK : NS_ERROR_FAILURE; -} - -NS_IMETHODIMP -MobileConnectionChild::SetCallWaiting(bool aEnabled, - nsIMobileConnectionCallback* aCallback) -{ - return SendRequest(SetCallWaitingRequest(aEnabled), aCallback) - ? NS_OK : NS_ERROR_FAILURE; -} - -NS_IMETHODIMP -MobileConnectionChild::GetCallWaiting(nsIMobileConnectionCallback* aCallback) -{ - return SendRequest(GetCallWaitingRequest(), aCallback) - ? NS_OK : NS_ERROR_FAILURE; -} - -NS_IMETHODIMP -MobileConnectionChild::SetCallingLineIdRestriction(uint16_t aMode, - nsIMobileConnectionCallback* aCallback) -{ - return SendRequest(SetCallingLineIdRestrictionRequest(aMode), aCallback) - ? NS_OK : NS_ERROR_FAILURE; -} - -NS_IMETHODIMP -MobileConnectionChild::GetCallingLineIdRestriction(nsIMobileConnectionCallback* aCallback) -{ - return SendRequest(GetCallingLineIdRestrictionRequest(), aCallback) - ? NS_OK : NS_ERROR_FAILURE; -} - -NS_IMETHODIMP -MobileConnectionChild::ExitEmergencyCbMode(nsIMobileConnectionCallback* aCallback) -{ - return SendRequest(ExitEmergencyCbModeRequest(), aCallback) - ? NS_OK : NS_ERROR_FAILURE; -} - -NS_IMETHODIMP -MobileConnectionChild::SetRadioEnabled(bool aEnabled, - nsIMobileConnectionCallback* aCallback) -{ - return SendRequest(SetRadioEnabledRequest(aEnabled), aCallback) - ? NS_OK : NS_ERROR_FAILURE; } bool -MobileConnectionChild::SendRequest(const MobileConnectionRequest& aRequest, - nsIMobileConnectionCallback* aCallback) +MobileConnectionChild::SendRequest(MobileConnectionRequest aRequest, + nsIMobileConnectionCallback* aRequestCallback) { NS_ENSURE_TRUE(mLive, false); // Deallocated in MobileConnectionChild::DeallocPMobileConnectionRequestChild(). - MobileConnectionRequestChild* actor = - new MobileConnectionRequestChild(aCallback); + MobileConnectionRequestChild* actor = new MobileConnectionRequestChild(aRequestCallback); SendPMobileConnectionRequestConstructor(actor, aRequest); return true; } void MobileConnectionChild::ActorDestroy(ActorDestroyReason why) {
--- a/dom/mobileconnection/ipc/MobileConnectionChild.h +++ b/dom/mobileconnection/ipc/MobileConnectionChild.h @@ -1,64 +1,93 @@ /* 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_mobileconnection_MobileConnectionChild_h #define mozilla_dom_mobileconnection_MobileConnectionChild_h +#include "mozilla/dom/MobileConnectionCallback.h" #include "mozilla/dom/MobileConnectionInfo.h" -#include "mozilla/dom/mobileconnection/PMobileConnectionChild.h" -#include "mozilla/dom/mobileconnection/PMobileConnectionRequestChild.h" +#include "mozilla/dom/PMobileConnectionChild.h" +#include "mozilla/dom/PMobileConnectionRequestChild.h" #include "nsCOMArray.h" #include "nsCOMPtr.h" #include "nsIMobileConnectionService.h" #include "nsIVariant.h" -class nsIMobileConnectionCallback; - namespace mozilla { namespace dom { namespace mobileconnection { /** * Child actor of PMobileConnection. The object is created by * MobileConnectionIPCService and destroyed after MobileConnectionIPCService is * shutdown. For multi-sim device, more than one instance will * be created and each instance represents a sim slot. */ -class MobileConnectionChild MOZ_FINAL : public PMobileConnectionChild - , public nsIMobileConnection +class MobileConnectionChild : public PMobileConnectionChild { + NS_INLINE_DECL_REFCOUNTING(MobileConnectionChild) + public: - NS_DECL_ISUPPORTS - NS_DECL_NSIMOBILECONNECTION - - MobileConnectionChild(uint32_t aServiceId); + MobileConnectionChild() + : mLive(true) + { + MOZ_COUNT_CTOR(MobileConnectionChild); + } void Init(); void Shutdown(); -private: - MobileConnectionChild() MOZ_DELETE; + void + RegisterListener(nsIMobileConnectionListener* aListener); + + void + UnregisterListener(nsIMobileConnectionListener* aListener); + + MobileConnectionInfo* + GetVoiceInfo(); + + MobileConnectionInfo* + GetDataInfo(); + + void + GetIccId(nsAString& aIccId); + + void + GetRadioState(nsAString& aRadioState); - // MOZ_FINAL suppresses -Werror,-Wdelete-non-virtual-dtor + nsIVariant* + GetSupportedNetworkTypes(); + + void + GetLastNetwork(nsAString& aNetwork); + + void + GetLastHomeNetwork(nsAString& aNetwork); + + void + GetNetworkSelectionMode(nsAString& aMode); + + bool + SendRequest(MobileConnectionRequest aRequest, + nsIMobileConnectionCallback* aRequestCallback); + +protected: + virtual ~MobileConnectionChild() { MOZ_COUNT_DTOR(MobileConnectionChild); + Shutdown(); } -protected: - bool - SendRequest(const MobileConnectionRequest& aRequest, - nsIMobileConnectionCallback* aCallback); - virtual void ActorDestroy(ActorDestroyReason why) MOZ_OVERRIDE; virtual PMobileConnectionRequestChild* AllocPMobileConnectionRequestChild(const MobileConnectionRequest& request) MOZ_OVERRIDE; virtual bool DeallocPMobileConnectionRequestChild(PMobileConnectionRequestChild* aActor) MOZ_OVERRIDE; @@ -102,27 +131,26 @@ protected: virtual bool RecvNotifyLastHomeNetworkChanged(const nsString& aNetwork) MOZ_OVERRIDE; virtual bool RecvNotifyNetworkSelectionModeChanged(const nsString& aMode) MOZ_OVERRIDE; private: - uint32_t mServiceId; bool mLive; nsCOMArray<nsIMobileConnectionListener> mListeners; + nsCOMPtr<nsIWritableVariant> mSupportedNetworkTypes; nsRefPtr<MobileConnectionInfo> mVoice; nsRefPtr<MobileConnectionInfo> mData; nsString mIccId; nsString mRadioState; nsString mLastNetwork; nsString mLastHomeNetwork; nsString mNetworkSelectionMode; - nsTArray<nsString> mSupportedNetworkTypes; }; /****************************************************************************** * PMobileConnectionRequestChild ******************************************************************************/ /** * Child actor of PMobileConnectionRequest. The object is created when an
--- a/dom/mobileconnection/ipc/MobileConnectionIPCSerializer.h +++ b/dom/mobileconnection/ipc/MobileConnectionIPCSerializer.h @@ -1,20 +1,20 @@ /* 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_mobileconnection_MobileConnectionIPCSerialiser_h -#define mozilla_dom_mobileconnection_MobileConnectionIPCSerialiser_h +#ifndef dom_mobileconnection_src_ipc_MobileConnectionIPCSerialiser_h +#define dom_mobileconnection_src_ipc_MobileConnectionIPCSerialiser_h #include "ipc/IPCMessageUtils.h" #include "mozilla/dom/MobileCellInfo.h" #include "mozilla/dom/MobileConnectionInfo.h" #include "mozilla/dom/MobileNetworkInfo.h" -#include "mozilla/dom/MozMobileConnectionBinding.h" +#include "MozMobileConnectionBinding.h" using mozilla::AutoSafeJSContext; using mozilla::dom::MobileNetworkInfo; using mozilla::dom::MobileCellInfo; using mozilla::dom::MobileConnectionInfo; typedef nsIMobileCellInfo* nsMobileCellInfo; typedef nsIMobileConnectionInfo* nsMobileConnectionInfo; @@ -741,9 +741,9 @@ struct ParamTraits<MozCallBarringOptions } return true; } }; } // namespace IPC -#endif // mozilla_dom_mobileconnection_MobileConnectionIPCSerialiser_h +#endif // dom_mobileconnection_src_ipc_MobileConnectionIPCSerialiser_h
--- a/dom/mobileconnection/ipc/MobileConnectionIPCService.cpp +++ b/dom/mobileconnection/ipc/MobileConnectionIPCService.cpp @@ -9,56 +9,386 @@ #include "mozilla/StaticPtr.h" using namespace mozilla; using namespace mozilla::dom; using namespace mozilla::dom::mobileconnection; NS_IMPL_ISUPPORTS(MobileConnectionIPCService, nsIMobileConnectionService) +StaticRefPtr<MobileConnectionIPCService> sService; + +/* static */MobileConnectionIPCService* +MobileConnectionIPCService::GetSingleton() +{ + MOZ_ASSERT(NS_IsMainThread()); + + if (sService) { + return sService; + } + + sService = new MobileConnectionIPCService(); + return sService; +} + MobileConnectionIPCService::MobileConnectionIPCService() { int32_t numRil = Preferences::GetInt("ril.numRadioInterfaces", 1); - mItems.SetLength(numRil); + for (int32_t i = 0; i < numRil; i++) { + // Deallocated in ContentChild::DeallocPMobileConnectionChild(). + nsRefPtr<MobileConnectionChild> client = new MobileConnectionChild(); + NS_ASSERTION(client, "This shouldn't fail!"); + + ContentChild::GetSingleton()->SendPMobileConnectionConstructor(client, i); + client->Init(); + + mClients.AppendElement(client); + } } MobileConnectionIPCService::~MobileConnectionIPCService() { - uint32_t count = mItems.Length(); + uint32_t count = mClients.Length(); for (uint32_t i = 0; i < count; i++) { - if (mItems[i]) { - mItems[i]->Shutdown(); - } + mClients[i]->Shutdown(); } + + mClients.Clear(); +} + +nsresult +MobileConnectionIPCService::SendRequest(uint32_t aClientId, + MobileConnectionRequest aRequest, + nsIMobileConnectionCallback* aRequestCallback) +{ + if (aClientId >= mClients.Length()) { + return NS_ERROR_FAILURE; + } + + mClients[aClientId]->SendRequest(aRequest, aRequestCallback); + return NS_OK; } // nsIMobileConnectionService NS_IMETHODIMP -MobileConnectionIPCService::GetNumItems(uint32_t* aNumItems) +MobileConnectionIPCService::RegisterListener(uint32_t aClientId, + nsIMobileConnectionListener* aListener) +{ + if (aClientId >= mClients.Length()) { + return NS_ERROR_FAILURE; + } + + mClients[aClientId]->RegisterListener(aListener); + return NS_OK; +} + +NS_IMETHODIMP +MobileConnectionIPCService::UnregisterListener(uint32_t aClientId, + nsIMobileConnectionListener* aListener) +{ + if (aClientId >= mClients.Length()) { + return NS_ERROR_FAILURE; + } + + mClients[aClientId]->UnregisterListener(aListener); + return NS_OK; +} + +NS_IMETHODIMP +MobileConnectionIPCService::GetLastKnownNetwork(uint32_t aClientId, + nsAString& aLastNetwork) +{ + if (aClientId >= mClients.Length()) { + return NS_ERROR_FAILURE; + } + + mClients[aClientId]->GetLastNetwork(aLastNetwork); + return NS_OK; +} + +NS_IMETHODIMP +MobileConnectionIPCService::GetLastKnownHomeNetwork(uint32_t aClientId, + nsAString& aLastNetwork) +{ + if (aClientId >= mClients.Length()) { + return NS_ERROR_FAILURE; + } + + mClients[aClientId]->GetLastHomeNetwork(aLastNetwork); + return NS_OK; +} + +NS_IMETHODIMP +MobileConnectionIPCService::GetVoiceConnectionInfo(uint32_t aClientId, + nsIMobileConnectionInfo** aInfo) { - *aNumItems = mItems.Length(); + if (aClientId >= mClients.Length()) { + return NS_ERROR_FAILURE; + } + + nsCOMPtr<nsIMobileConnectionInfo> info = mClients[aClientId]->GetVoiceInfo(); + info.forget(aInfo); + + return NS_OK; +} + +NS_IMETHODIMP +MobileConnectionIPCService::GetDataConnectionInfo(uint32_t aClientId, + nsIMobileConnectionInfo** aInfo) +{ + if (aClientId >= mClients.Length()) { + return NS_ERROR_FAILURE; + } + + nsCOMPtr<nsIMobileConnectionInfo> info = mClients[aClientId]->GetDataInfo(); + info.forget(aInfo); + + return NS_OK; +} + +NS_IMETHODIMP +MobileConnectionIPCService::GetIccId(uint32_t aClientId, nsAString& aIccId) +{ + if (aClientId >= mClients.Length()) { + return NS_ERROR_FAILURE; + } + + mClients[aClientId]->GetIccId(aIccId); + return NS_OK; +} + +NS_IMETHODIMP +MobileConnectionIPCService::GetNetworkSelectionMode(uint32_t aClientId, + nsAString& aNetworkSelectionMode) +{ + if (aClientId >= mClients.Length()) { + return NS_ERROR_FAILURE; + } + + mClients[aClientId]->GetNetworkSelectionMode(aNetworkSelectionMode); + return NS_OK; +} + +NS_IMETHODIMP +MobileConnectionIPCService::GetRadioState(uint32_t aClientId, + nsAString& aRadioState) +{ + if (aClientId >= mClients.Length()) { + return NS_ERROR_FAILURE; + } + + mClients[aClientId]->GetRadioState(aRadioState); + return NS_OK; +} + +NS_IMETHODIMP +MobileConnectionIPCService::GetSupportedNetworkTypes(uint32_t aClientId, + nsIVariant** aSupportedTypes) +{ + if (aClientId >= mClients.Length()) { + return NS_ERROR_FAILURE; + } + + nsCOMPtr<nsIVariant> supportedTypes = mClients[aClientId]->GetSupportedNetworkTypes(); + supportedTypes.forget(aSupportedTypes); + return NS_OK; } NS_IMETHODIMP -MobileConnectionIPCService::GetItemByServiceId(uint32_t aServiceId, - nsIMobileConnection** aItem) +MobileConnectionIPCService::GetNetworks(uint32_t aClientId, + nsIMobileConnectionCallback* aRequest) +{ + return SendRequest(aClientId, GetNetworksRequest(), aRequest); +} + +NS_IMETHODIMP +MobileConnectionIPCService::SelectNetwork(uint32_t aClientId, + nsIMobileNetworkInfo* aNetwork, + nsIMobileConnectionCallback* aRequest) +{ + nsCOMPtr<nsIMobileNetworkInfo> network = aNetwork; + // We release the ref after serializing process is finished in + // MobileConnectionIPCSerializer. + return SendRequest(aClientId, SelectNetworkRequest(network.forget().take()), aRequest); +} + +NS_IMETHODIMP +MobileConnectionIPCService::SelectNetworkAutomatically(uint32_t aClientId, + nsIMobileConnectionCallback* aRequest) { - NS_ENSURE_TRUE(aServiceId < mItems.Length(), NS_ERROR_INVALID_ARG); + return SendRequest(aClientId, SelectNetworkAutoRequest(), aRequest); +} + - if (!mItems[aServiceId]) { - nsRefPtr<MobileConnectionChild> child = new MobileConnectionChild(aServiceId); +NS_IMETHODIMP +MobileConnectionIPCService::SetPreferredNetworkType(uint32_t aClientId, + const nsAString& aType, + nsIMobileConnectionCallback* aRequest) +{ + return SendRequest(aClientId, + SetPreferredNetworkTypeRequest(nsAutoString(aType)), + aRequest); +} + +NS_IMETHODIMP +MobileConnectionIPCService::GetPreferredNetworkType(uint32_t aClientId, + nsIMobileConnectionCallback* aRequest) +{ + return SendRequest(aClientId, GetPreferredNetworkTypeRequest(), aRequest); +} - // |SendPMobileConnectionConstructor| adds another reference to the child - // actor and removes in |DeallocPMobileConnectionChild|. - ContentChild::GetSingleton()->SendPMobileConnectionConstructor(child, - aServiceId); - child->Init(); +NS_IMETHODIMP +MobileConnectionIPCService::SetRoamingPreference(uint32_t aClientId, + const nsAString& aMode, + nsIMobileConnectionCallback* aRequest) +{ + return SendRequest(aClientId, + SetRoamingPreferenceRequest(nsAutoString(aMode)), + aRequest); +} + +NS_IMETHODIMP +MobileConnectionIPCService::GetRoamingPreference(uint32_t aClientId, + nsIMobileConnectionCallback* aRequest) +{ + return SendRequest(aClientId, GetRoamingPreferenceRequest(), aRequest); +} + +NS_IMETHODIMP +MobileConnectionIPCService::SetVoicePrivacyMode(uint32_t aClientId, + bool aEnabled, + nsIMobileConnectionCallback* aRequest) +{ + return SendRequest(aClientId, SetVoicePrivacyModeRequest(aEnabled), aRequest); +} - mItems[aServiceId] = child; +NS_IMETHODIMP +MobileConnectionIPCService::GetVoicePrivacyMode(uint32_t aClientId, + nsIMobileConnectionCallback* aRequest) +{ + return SendRequest(aClientId, GetVoicePrivacyModeRequest(), aRequest); +} + +NS_IMETHODIMP +MobileConnectionIPCService::SendMMI(uint32_t aClientId, + const nsAString& aMmi, + nsIMobileConnectionCallback* aRequest) +{ + return SendRequest(aClientId, SendMmiRequest(nsAutoString(aMmi)), aRequest); +} + +NS_IMETHODIMP +MobileConnectionIPCService::CancelMMI(uint32_t aClientId, + nsIMobileConnectionCallback* aRequest) +{ + return SendRequest(aClientId, CancelMmiRequest(), aRequest); +} + +NS_IMETHODIMP +MobileConnectionIPCService::SetCallForwarding(uint32_t aClientId, + JS::Handle<JS::Value> aOptions, + nsIMobileConnectionCallback* aRequest) +{ + AutoSafeJSContext cx; + IPC::MozCallForwardingOptions options; + if(!options.Init(cx, aOptions)) { + return NS_ERROR_TYPE_ERR; } - nsRefPtr<nsIMobileConnection> item(mItems[aServiceId]); - item.forget(aItem); + return SendRequest(aClientId, SetCallForwardingRequest(options), aRequest); +} + +NS_IMETHODIMP +MobileConnectionIPCService::GetCallForwarding(uint32_t aClientId, + uint16_t aReason, + nsIMobileConnectionCallback* aRequest) +{ + return SendRequest(aClientId, GetCallForwardingRequest(aReason), aRequest); +} + +NS_IMETHODIMP +MobileConnectionIPCService::SetCallBarring(uint32_t aClientId, + JS::Handle<JS::Value> aOptions, + nsIMobileConnectionCallback* aRequest) +{ + AutoSafeJSContext cx; + IPC::MozCallBarringOptions options; + if(!options.Init(cx, aOptions)) { + return NS_ERROR_TYPE_ERR; + } + + return SendRequest(aClientId, SetCallBarringRequest(options), aRequest); +} + +NS_IMETHODIMP +MobileConnectionIPCService::GetCallBarring(uint32_t aClientId, + JS::Handle<JS::Value> aOptions, + nsIMobileConnectionCallback* aRequest) +{ + AutoSafeJSContext cx; + IPC::MozCallBarringOptions options; + if(!options.Init(cx, aOptions)) { + return NS_ERROR_TYPE_ERR; + } + + return SendRequest(aClientId, GetCallBarringRequest(options), aRequest); +} - return NS_OK; +NS_IMETHODIMP +MobileConnectionIPCService::ChangeCallBarringPassword(uint32_t aClientId, + JS::Handle<JS::Value> aOptions, + nsIMobileConnectionCallback* aRequest) +{ + AutoSafeJSContext cx; + IPC::MozCallBarringOptions options; + if(!options.Init(cx, aOptions)) { + return NS_ERROR_TYPE_ERR; + } + + return SendRequest(aClientId, ChangeCallBarringPasswordRequest(options), aRequest); +} + +NS_IMETHODIMP +MobileConnectionIPCService::SetCallWaiting(uint32_t aClientId, + bool aEnabled, + nsIMobileConnectionCallback* aRequest) +{ + return SendRequest(aClientId, SetCallWaitingRequest(aEnabled), aRequest); +} + +NS_IMETHODIMP +MobileConnectionIPCService::GetCallWaiting(uint32_t aClientId, + nsIMobileConnectionCallback* aRequest) +{ + return SendRequest(aClientId, GetCallWaitingRequest(), aRequest); } + +NS_IMETHODIMP +MobileConnectionIPCService::SetCallingLineIdRestriction(uint32_t aClientId, + uint16_t aMode, + nsIMobileConnectionCallback* aRequest) +{ + return SendRequest(aClientId, SetCallingLineIdRestrictionRequest(aMode), aRequest); +} + +NS_IMETHODIMP +MobileConnectionIPCService::GetCallingLineIdRestriction(uint32_t aClientId, + nsIMobileConnectionCallback* aRequest) +{ + return SendRequest(aClientId, GetCallingLineIdRestrictionRequest(), aRequest); +} + +NS_IMETHODIMP +MobileConnectionIPCService::ExitEmergencyCbMode(uint32_t aClientId, + nsIMobileConnectionCallback* aRequest) +{ + return SendRequest(aClientId, ExitEmergencyCbModeRequest(), aRequest); +} + +NS_IMETHODIMP +MobileConnectionIPCService::SetRadioEnabled(uint32_t aClientId, + bool aEnabled, + nsIMobileConnectionCallback* aRequest) +{ + return SendRequest(aClientId, SetRadioEnabledRequest(aEnabled), aRequest); +}
--- a/dom/mobileconnection/ipc/MobileConnectionIPCService.h +++ b/dom/mobileconnection/ipc/MobileConnectionIPCService.h @@ -1,35 +1,42 @@ /* 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_mobileconnection_MobileConnectionIPCService_h #define mozilla_dom_mobileconnection_MobileConnectionIPCService_h #include "nsCOMPtr.h" -#include "mozilla/dom/mobileconnection/MobileConnectionChild.h" +#include "MobileConnectionChild.h" #include "nsIMobileConnectionService.h" namespace mozilla { namespace dom { namespace mobileconnection { class MobileConnectionIPCService MOZ_FINAL : public nsIMobileConnectionService { public: NS_DECL_ISUPPORTS NS_DECL_NSIMOBILECONNECTIONSERVICE + static MobileConnectionIPCService* + GetSingleton(); + +private: MobileConnectionIPCService(); -private: - // MOZ_FINAL suppresses -Werror,-Wdelete-non-virtual-dtor ~MobileConnectionIPCService(); - nsTArray<nsRefPtr<MobileConnectionChild>> mItems; + /** Send request */ + nsresult + SendRequest(uint32_t aClientId, MobileConnectionRequest aRequest, + nsIMobileConnectionCallback* aRequestCallback); + + nsTArray<nsRefPtr<MobileConnectionChild>> mClients; }; -} // namespace mobileconnection -} // namespace dom -} // namespace mozilla +} // name space mobileconnection +} // name space dom +} // name space mozilla #endif // mozilla_dom_mobileconnection_MobileConnectionIPCService_h
--- a/dom/mobileconnection/ipc/MobileConnectionParent.cpp +++ b/dom/mobileconnection/ipc/MobileConnectionParent.cpp @@ -1,49 +1,47 @@ /* 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/mobileconnection/MobileConnectionParent.h" +#include "MobileConnectionParent.h" #include "mozilla/AppProcessChecker.h" #include "mozilla/dom/BindingUtils.h" -#include "mozilla/dom/mobileconnection/MobileConnectionIPCSerializer.h" +#include "mozilla/dom/MobileConnectionIPCSerializer.h" #include "mozilla/dom/MozMobileConnectionBinding.h" #include "mozilla/dom/ToJSValue.h" #include "nsIVariant.h" #include "nsJSUtils.h" using namespace mozilla; using namespace mozilla::dom; using namespace mozilla::dom::mobileconnection; MobileConnectionParent::MobileConnectionParent(uint32_t aClientId) - : mLive(true) + : mClientId(aClientId) + , mLive(true) { MOZ_COUNT_CTOR(MobileConnectionParent); - nsCOMPtr<nsIMobileConnectionService> service = - do_GetService(NS_MOBILE_CONNECTION_SERVICE_CONTRACTID); - NS_ASSERTION(service, "This shouldn't fail!"); + mService = do_GetService(NS_MOBILE_CONNECTION_SERVICE_CONTRACTID); + NS_ASSERTION(mService, "This shouldn't fail!"); - nsresult rv = service->GetItemByServiceId(aClientId, - getter_AddRefs(mMobileConnection)); - if (NS_SUCCEEDED(rv) && mMobileConnection) { - mMobileConnection->RegisterListener(this); + if (mService) { + mService->RegisterListener(mClientId, this); } } void MobileConnectionParent::ActorDestroy(ActorDestroyReason why) { mLive = false; - if (mMobileConnection) { - mMobileConnection->UnregisterListener(this); - mMobileConnection = nullptr; + if (mService) { + mService->UnregisterListener(mClientId, this); + mService = nullptr; } } bool MobileConnectionParent::RecvPMobileConnectionRequestConstructor(PMobileConnectionRequestParent* aActor, const MobileConnectionRequest& aRequest) { MobileConnectionRequestParent* actor = static_cast<MobileConnectionRequestParent*>(aActor); @@ -102,18 +100,17 @@ MobileConnectionParent::RecvPMobileConne PMobileConnectionRequestParent* MobileConnectionParent::AllocPMobileConnectionRequestParent(const MobileConnectionRequest& request) { if (!AssertAppProcessPermission(Manager(), "mobileconnection")) { return nullptr; } - MobileConnectionRequestParent* actor = - new MobileConnectionRequestParent(mMobileConnection); + MobileConnectionRequestParent* actor = new MobileConnectionRequestParent(mClientId); // Add an extra ref for IPDL. Will be released in // MobileConnectionParent::DeallocPMobileConnectionRequestParent(). actor->AddRef(); return actor; } bool MobileConnectionParent::DeallocPMobileConnectionRequestParent(PMobileConnectionRequestParent* aActor) @@ -128,69 +125,77 @@ MobileConnectionParent::RecvInit(nsMobil nsMobileConnectionInfo* aData, nsString* aLastKnownNetwork, nsString* aLastKnownHomeNetwork, nsString* aIccId, nsString* aNetworkSelectionMode, nsString* aRadioState, nsTArray<nsString>* aSupportedNetworkTypes) { - NS_ENSURE_TRUE(mMobileConnection, false); + NS_ENSURE_TRUE(mService, false); - NS_ENSURE_SUCCESS(mMobileConnection->GetVoice(aVoice), false); - NS_ENSURE_SUCCESS(mMobileConnection->GetData(aData), false); - NS_ENSURE_SUCCESS(mMobileConnection->GetLastKnownNetwork(*aLastKnownNetwork), false); - NS_ENSURE_SUCCESS(mMobileConnection->GetLastKnownHomeNetwork(*aLastKnownHomeNetwork), false); - NS_ENSURE_SUCCESS(mMobileConnection->GetIccId(*aIccId), false); - NS_ENSURE_SUCCESS(mMobileConnection->GetNetworkSelectionMode(*aNetworkSelectionMode), false); - NS_ENSURE_SUCCESS(mMobileConnection->GetRadioState(*aRadioState), false); + NS_ENSURE_SUCCESS(mService->GetVoiceConnectionInfo(mClientId, aVoice), false); + NS_ENSURE_SUCCESS(mService->GetDataConnectionInfo(mClientId, aData), false); + NS_ENSURE_SUCCESS(mService->GetLastKnownNetwork(mClientId, *aLastKnownNetwork), false); + NS_ENSURE_SUCCESS(mService->GetLastKnownHomeNetwork(mClientId, *aLastKnownHomeNetwork), false); + NS_ENSURE_SUCCESS(mService->GetIccId(mClientId, *aIccId), false); + NS_ENSURE_SUCCESS(mService->GetNetworkSelectionMode(mClientId, *aNetworkSelectionMode), false); + NS_ENSURE_SUCCESS(mService->GetRadioState(mClientId, *aRadioState), false); - char16_t** types = nullptr; - uint32_t length = 0; + nsCOMPtr<nsIVariant> variant; + mService->GetSupportedNetworkTypes(mClientId, getter_AddRefs(variant)); - nsresult rv = mMobileConnection->GetSupportedNetworkTypes(&types, &length); - NS_ENSURE_SUCCESS(rv, false); - - for (uint32_t i = 0; i < length; ++i) { - nsDependentString type(types[i]); - aSupportedNetworkTypes->AppendElement(type); + uint16_t type; + nsIID iid; + uint32_t count; + void* data; + if (NS_FAILED(variant->GetAsArray(&type, &iid, &count, &data))) { + return false; } - NS_FREE_XPCOM_ALLOCATED_POINTER_ARRAY(length, types); + // We expect the element type is wstring. + if (type == nsIDataType::VTYPE_WCHAR_STR) { + char16_t** rawArray = reinterpret_cast<char16_t**>(data); + for (uint32_t i = 0; i < count; ++i) { + nsDependentString networkType(rawArray[i]); + aSupportedNetworkTypes->AppendElement(networkType); + } + } + NS_Free(data); return true; } // nsIMobileConnectionListener NS_IMPL_ISUPPORTS(MobileConnectionParent, nsIMobileConnectionListener) NS_IMETHODIMP MobileConnectionParent::NotifyVoiceChanged() { NS_ENSURE_TRUE(mLive, NS_ERROR_FAILURE); nsresult rv; nsCOMPtr<nsIMobileConnectionInfo> info; - rv = mMobileConnection->GetVoice(getter_AddRefs(info)); + rv = mService->GetVoiceConnectionInfo(mClientId, getter_AddRefs(info)); NS_ENSURE_SUCCESS(rv, rv); // We release the ref after serializing process is finished in // MobileConnectionIPCSerializer. return SendNotifyVoiceInfoChanged(info.forget().take()) ? NS_OK : NS_ERROR_FAILURE; } NS_IMETHODIMP MobileConnectionParent::NotifyDataChanged() { NS_ENSURE_TRUE(mLive, NS_ERROR_FAILURE); nsresult rv; nsCOMPtr<nsIMobileConnectionInfo> info; - rv = mMobileConnection->GetData(getter_AddRefs(info)); + rv = mService->GetDataConnectionInfo(mClientId, getter_AddRefs(info)); NS_ENSURE_SUCCESS(rv, rv); // We release the ref after serializing process is finished in // MobileConnectionIPCSerializer. return SendNotifyDataInfoChanged(info.forget().take()) ? NS_OK : NS_ERROR_FAILURE; } NS_IMETHODIMP @@ -246,29 +251,29 @@ MobileConnectionParent::NotifyOtaStatusC } NS_IMETHODIMP MobileConnectionParent::NotifyIccChanged() { NS_ENSURE_TRUE(mLive, NS_ERROR_FAILURE); nsAutoString iccId; - mMobileConnection->GetIccId(iccId); + mService->GetIccId(mClientId, iccId); return SendNotifyIccChanged(iccId) ? NS_OK : NS_ERROR_FAILURE; } NS_IMETHODIMP MobileConnectionParent::NotifyRadioStateChanged() { NS_ENSURE_TRUE(mLive, NS_ERROR_FAILURE); nsresult rv; nsAutoString radioState; - rv = mMobileConnection->GetRadioState(radioState); + rv = mService->GetRadioState(mClientId, radioState); NS_ENSURE_SUCCESS(rv, rv); return SendNotifyRadioStateChanged(radioState) ? NS_OK : NS_ERROR_FAILURE; } NS_IMETHODIMP MobileConnectionParent::NotifyClirModeChanged(uint32_t aMode) { @@ -279,264 +284,264 @@ MobileConnectionParent::NotifyClirModeCh NS_IMETHODIMP MobileConnectionParent::NotifyLastKnownNetworkChanged() { NS_ENSURE_TRUE(mLive, NS_ERROR_FAILURE); nsresult rv; nsAutoString network; - rv = mMobileConnection->GetLastKnownNetwork(network); + rv = mService->GetLastKnownNetwork(mClientId, network); NS_ENSURE_SUCCESS(rv, rv); return SendNotifyLastNetworkChanged(network) ? NS_OK : NS_ERROR_FAILURE; } NS_IMETHODIMP MobileConnectionParent::NotifyLastKnownHomeNetworkChanged() { NS_ENSURE_TRUE(mLive, NS_ERROR_FAILURE); nsresult rv; nsAutoString network; - rv = mMobileConnection->GetLastKnownHomeNetwork(network); + rv = mService->GetLastKnownHomeNetwork(mClientId, network); NS_ENSURE_SUCCESS(rv, rv); return SendNotifyLastHomeNetworkChanged(network) ? NS_OK : NS_ERROR_FAILURE; } NS_IMETHODIMP MobileConnectionParent::NotifyNetworkSelectionModeChanged() { NS_ENSURE_TRUE(mLive, NS_ERROR_FAILURE); nsresult rv; nsAutoString mode; - rv = mMobileConnection->GetNetworkSelectionMode(mode); + rv = mService->GetNetworkSelectionMode(mClientId, mode); NS_ENSURE_SUCCESS(rv, rv); return SendNotifyNetworkSelectionModeChanged(mode) ? NS_OK : NS_ERROR_FAILURE; } /****************************************************************************** * PMobileConnectionRequestParent ******************************************************************************/ void MobileConnectionRequestParent::ActorDestroy(ActorDestroyReason why) { mLive = false; - mMobileConnection = nullptr; + mService = nullptr; } bool MobileConnectionRequestParent::DoRequest(const GetNetworksRequest& aRequest) { - NS_ENSURE_TRUE(mMobileConnection, false); + NS_ENSURE_TRUE(mService, false); - return NS_SUCCEEDED(mMobileConnection->GetNetworks(this)); + return NS_SUCCEEDED(mService->GetNetworks(mClientId, this)); } bool MobileConnectionRequestParent::DoRequest(const SelectNetworkRequest& aRequest) { - NS_ENSURE_TRUE(mMobileConnection, false); + NS_ENSURE_TRUE(mService, false); // Use dont_AddRef here because this instances is already AddRef-ed in // MobileConnectionIPCSerializer.h nsCOMPtr<nsIMobileNetworkInfo> network = dont_AddRef(aRequest.network()); - return NS_SUCCEEDED(mMobileConnection->SelectNetwork(network, this)); + return NS_SUCCEEDED(mService->SelectNetwork(mClientId, network, this)); } bool MobileConnectionRequestParent::DoRequest(const SelectNetworkAutoRequest& aRequest) { - NS_ENSURE_TRUE(mMobileConnection, false); + NS_ENSURE_TRUE(mService, false); - return NS_SUCCEEDED(mMobileConnection->SelectNetworkAutomatically(this)); + return NS_SUCCEEDED(mService->SelectNetworkAutomatically(mClientId, this)); } bool MobileConnectionRequestParent::DoRequest(const SetPreferredNetworkTypeRequest& aRequest) { - NS_ENSURE_TRUE(mMobileConnection, false); + NS_ENSURE_TRUE(mService, false); - return NS_SUCCEEDED(mMobileConnection->SetPreferredNetworkType(aRequest.type(), this)); + return NS_SUCCEEDED(mService->SetPreferredNetworkType(mClientId, aRequest.type(), this)); } bool MobileConnectionRequestParent::DoRequest(const GetPreferredNetworkTypeRequest& aRequest) { - NS_ENSURE_TRUE(mMobileConnection, false); + NS_ENSURE_TRUE(mService, false); - return NS_SUCCEEDED(mMobileConnection->GetPreferredNetworkType(this)); + return NS_SUCCEEDED(mService->GetPreferredNetworkType(mClientId, this)); } bool MobileConnectionRequestParent::DoRequest(const SetRoamingPreferenceRequest& aRequest) { - NS_ENSURE_TRUE(mMobileConnection, false); + NS_ENSURE_TRUE(mService, false); - return NS_SUCCEEDED(mMobileConnection->SetRoamingPreference(aRequest.mode(), this)); + return NS_SUCCEEDED(mService->SetRoamingPreference(mClientId, aRequest.mode(), this)); } bool MobileConnectionRequestParent::DoRequest(const GetRoamingPreferenceRequest& aRequest) { - NS_ENSURE_TRUE(mMobileConnection, false); + NS_ENSURE_TRUE(mService, false); - return NS_SUCCEEDED(mMobileConnection->GetRoamingPreference(this)); + return NS_SUCCEEDED(mService->GetRoamingPreference(mClientId, this)); } bool MobileConnectionRequestParent::DoRequest(const SetVoicePrivacyModeRequest& aRequest) { - NS_ENSURE_TRUE(mMobileConnection, false); + NS_ENSURE_TRUE(mService, false); - return NS_SUCCEEDED(mMobileConnection->SetVoicePrivacyMode(aRequest.enabled(), this)); + return NS_SUCCEEDED(mService->SetVoicePrivacyMode(mClientId, aRequest.enabled(), this)); } bool MobileConnectionRequestParent::DoRequest(const GetVoicePrivacyModeRequest& aRequest) { - NS_ENSURE_TRUE(mMobileConnection, false); + NS_ENSURE_TRUE(mService, false); - return NS_SUCCEEDED(mMobileConnection->GetVoicePrivacyMode(this)); + return NS_SUCCEEDED(mService->GetVoicePrivacyMode(mClientId, this)); } bool MobileConnectionRequestParent::DoRequest(const SendMmiRequest& aRequest) { - NS_ENSURE_TRUE(mMobileConnection, false); + NS_ENSURE_TRUE(mService, false); - return NS_SUCCEEDED(mMobileConnection->SendMMI(aRequest.mmi(), this)); + return NS_SUCCEEDED(mService->SendMMI(mClientId, aRequest.mmi(), this)); } bool MobileConnectionRequestParent::DoRequest(const CancelMmiRequest& aRequest) { - NS_ENSURE_TRUE(mMobileConnection, false); + NS_ENSURE_TRUE(mService, false); - return NS_SUCCEEDED(mMobileConnection->CancelMMI(this)); + return NS_SUCCEEDED(mService->CancelMMI(mClientId, this)); } bool MobileConnectionRequestParent::DoRequest(const SetCallForwardingRequest& aRequest) { - NS_ENSURE_TRUE(mMobileConnection, false); + NS_ENSURE_TRUE(mService, false); AutoSafeJSContext cx; JS::Rooted<JS::Value> options(cx); if (!ToJSValue(cx, aRequest.options(), &options)) { JS_ClearPendingException(cx); return false; } - return NS_SUCCEEDED(mMobileConnection->SetCallForwarding(options, this)); + return NS_SUCCEEDED(mService->SetCallForwarding(mClientId, options, this)); } bool MobileConnectionRequestParent::DoRequest(const GetCallForwardingRequest& aRequest) { - NS_ENSURE_TRUE(mMobileConnection, false); + NS_ENSURE_TRUE(mService, false); - return NS_SUCCEEDED(mMobileConnection->GetCallForwarding(aRequest.reason(), this)); + return NS_SUCCEEDED(mService->GetCallForwarding(mClientId, aRequest.reason(), this)); } bool MobileConnectionRequestParent::DoRequest(const SetCallBarringRequest& aRequest) { - NS_ENSURE_TRUE(mMobileConnection, false); + NS_ENSURE_TRUE(mService, false); AutoSafeJSContext cx; JS::Rooted<JS::Value> options(cx); if (!ToJSValue(cx, aRequest.options(), &options)) { JS_ClearPendingException(cx); return false; } - return NS_SUCCEEDED(mMobileConnection->SetCallBarring(options, this)); + return NS_SUCCEEDED(mService->SetCallBarring(mClientId, options, this)); } bool MobileConnectionRequestParent::DoRequest(const GetCallBarringRequest& aRequest) { - NS_ENSURE_TRUE(mMobileConnection, false); + NS_ENSURE_TRUE(mService, false); AutoSafeJSContext cx; JS::Rooted<JS::Value> options(cx); if (!ToJSValue(cx, aRequest.options(), &options)) { JS_ClearPendingException(cx); return false; } - return NS_SUCCEEDED(mMobileConnection->GetCallBarring(options, this)); + return NS_SUCCEEDED(mService->GetCallBarring(mClientId, options, this)); } bool MobileConnectionRequestParent::DoRequest(const ChangeCallBarringPasswordRequest& aRequest) { - NS_ENSURE_TRUE(mMobileConnection, false); + NS_ENSURE_TRUE(mService, false); AutoSafeJSContext cx; JS::Rooted<JS::Value> options(cx); if (!ToJSValue(cx, aRequest.options(), &options)) { JS_ClearPendingException(cx); return false; } - return NS_SUCCEEDED(mMobileConnection->ChangeCallBarringPassword(options, this)); + return NS_SUCCEEDED(mService->ChangeCallBarringPassword(mClientId, options, this)); } bool MobileConnectionRequestParent::DoRequest(const SetCallWaitingRequest& aRequest) { - NS_ENSURE_TRUE(mMobileConnection, false); + NS_ENSURE_TRUE(mService, false); - return NS_SUCCEEDED(mMobileConnection->SetCallWaiting(aRequest.enabled(), this)); + return NS_SUCCEEDED(mService->SetCallWaiting(mClientId, aRequest.enabled(), this)); } bool MobileConnectionRequestParent::DoRequest(const GetCallWaitingRequest& aRequest) { - NS_ENSURE_TRUE(mMobileConnection, false); + NS_ENSURE_TRUE(mService, false); - return NS_SUCCEEDED(mMobileConnection->GetCallWaiting(this)); + return NS_SUCCEEDED(mService->GetCallWaiting(mClientId, this)); } bool MobileConnectionRequestParent::DoRequest(const SetCallingLineIdRestrictionRequest& aRequest) { - NS_ENSURE_TRUE(mMobileConnection, false); + NS_ENSURE_TRUE(mService, false); - return NS_SUCCEEDED(mMobileConnection->SetCallingLineIdRestriction(aRequest.mode(), this)); + return NS_SUCCEEDED(mService->SetCallingLineIdRestriction(mClientId, aRequest.mode(), this)); } bool MobileConnectionRequestParent::DoRequest(const GetCallingLineIdRestrictionRequest& aRequest) { - NS_ENSURE_TRUE(mMobileConnection, false); + NS_ENSURE_TRUE(mService, false); - return NS_SUCCEEDED(mMobileConnection->GetCallingLineIdRestriction(this)); + return NS_SUCCEEDED(mService->GetCallingLineIdRestriction(mClientId, this)); } bool MobileConnectionRequestParent::DoRequest(const ExitEmergencyCbModeRequest& aRequest) { - NS_ENSURE_TRUE(mMobileConnection, false); + NS_ENSURE_TRUE(mService, false); - return NS_SUCCEEDED(mMobileConnection->ExitEmergencyCbMode(this)); + return NS_SUCCEEDED(mService->ExitEmergencyCbMode(mClientId, this)); } bool MobileConnectionRequestParent::DoRequest(const SetRadioEnabledRequest& aRequest) { - NS_ENSURE_TRUE(mMobileConnection, false); + NS_ENSURE_TRUE(mService, false); - return NS_SUCCEEDED(mMobileConnection->SetRadioEnabled(aRequest.enabled(), this)); + return NS_SUCCEEDED(mService->SetRadioEnabled(mClientId, aRequest.enabled(), this)); } nsresult MobileConnectionRequestParent::SendReply(const MobileConnectionReply& aReply) { NS_ENSURE_TRUE(mLive, NS_ERROR_FAILURE); return Send__delete__(this, aReply) ? NS_OK : NS_ERROR_FAILURE;
--- a/dom/mobileconnection/ipc/MobileConnectionParent.h +++ b/dom/mobileconnection/ipc/MobileConnectionParent.h @@ -1,17 +1,17 @@ /* 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_mobileconnection_MobileConnectionParent_h #define mozilla_dom_mobileconnection_MobileConnectionParent_h -#include "mozilla/dom/mobileconnection/PMobileConnectionParent.h" -#include "mozilla/dom/mobileconnection/PMobileConnectionRequestParent.h" +#include "mozilla/dom/PMobileConnectionParent.h" +#include "mozilla/dom/PMobileConnectionRequestParent.h" #include "nsIMobileConnectionInfo.h" #include "nsIMobileConnectionService.h" #include "nsServiceManagerUtils.h" namespace mozilla { namespace dom { namespace mobileconnection { @@ -50,18 +50,19 @@ protected: virtual bool RecvInit(nsMobileConnectionInfo* aVoice, nsMobileConnectionInfo* aData, nsString* aLastKnownNetwork, nsString* aLastKnownHomeNetwork, nsString* aIccId, nsString* aNetworkSelectionMode, nsString* aRadioState, nsTArray<nsString>* aSupportedNetworkTypes) MOZ_OVERRIDE; private: - nsCOMPtr<nsIMobileConnection> mMobileConnection; + uint32_t mClientId; bool mLive; + nsCOMPtr<nsIMobileConnectionService> mService; }; /****************************************************************************** * PMobileConnectionRequestParent ******************************************************************************/ /** * Parent actor of PMobileConnectionRequestParent. The object is created along @@ -72,21 +73,24 @@ private: */ class MobileConnectionRequestParent : public PMobileConnectionRequestParent , public nsIMobileConnectionCallback { public: NS_DECL_ISUPPORTS NS_DECL_NSIMOBILECONNECTIONCALLBACK - explicit MobileConnectionRequestParent(nsIMobileConnection* aMobileConnection) - : mMobileConnection(aMobileConnection) + explicit MobileConnectionRequestParent(uint32_t aClientId) + : mClientId(aClientId) , mLive(true) { MOZ_COUNT_CTOR(MobileConnectionRequestParent); + + mService = do_GetService(NS_MOBILE_CONNECTION_SERVICE_CONTRACTID); + NS_ASSERTION(mService, "This shouldn't fail!"); } bool DoRequest(const GetNetworksRequest& aRequest); bool DoRequest(const SelectNetworkRequest& aRequest); @@ -159,17 +163,18 @@ protected: virtual void ActorDestroy(ActorDestroyReason why); nsresult SendReply(const MobileConnectionReply& aReply); private: - nsCOMPtr<nsIMobileConnection> mMobileConnection; + uint32_t mClientId; bool mLive; + nsCOMPtr<nsIMobileConnectionService> mService; }; } // namespace mobileconnection } // namespace dom } // namespace mozilla #endif // mozilla_dom_mobileconnection_MobileConnectionParent_h
--- a/dom/mobileconnection/ipc/PMobileConnection.ipdl +++ b/dom/mobileconnection/ipc/PMobileConnection.ipdl @@ -5,17 +5,16 @@ * You can obtain one at http://mozilla.org/MPL/2.0/. */ include protocol PContent; include protocol PMobileConnectionRequest; include PMobileConnectionTypes; namespace mozilla { namespace dom { -namespace mobileconnection { sync protocol PMobileConnection { manager PContent; manages PMobileConnectionRequest; child: NotifyVoiceInfoChanged(nsMobileConnectionInfo aInfo); @@ -180,11 +179,10 @@ union MobileConnectionRequest SetCallWaitingRequest; GetCallWaitingRequest; SetCallingLineIdRestrictionRequest; GetCallingLineIdRestrictionRequest; ExitEmergencyCbModeRequest; SetRadioEnabledRequest; }; -} // namespace mobileconnection +} // namespace mozilla } // namespace dom -} // namespace mozilla
--- a/dom/mobileconnection/ipc/PMobileConnectionRequest.ipdl +++ b/dom/mobileconnection/ipc/PMobileConnectionRequest.ipdl @@ -4,17 +4,16 @@ * 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 PMobileConnection; include PMobileConnectionTypes; namespace mozilla { namespace dom { -namespace mobileconnection { protocol PMobileConnectionRequest { manager PMobileConnection; child: /** * Send when asynchronous request has completed. @@ -95,11 +94,10 @@ union MobileConnectionReply MobileConnectionReplySuccessCallForwarding; MobileConnectionReplySuccessCallBarring; MobileConnectionReplySuccessClirStatus; // Error MobileConnectionReplyError; MobileConnectionReplyErrorMmi; }; -} // namespace mobileconnection } // namespace dom } // namespace mozilla
--- a/dom/mobileconnection/ipc/PMobileConnectionTypes.ipdlh +++ b/dom/mobileconnection/ipc/PMobileConnectionTypes.ipdlh @@ -1,26 +1,24 @@ /* -*- 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/. */ -using nsMobileConnectionInfo from "mozilla/dom/mobileconnection/MobileConnectionIPCSerializer.h"; -using nsMobileNetworkInfo from "mozilla/dom/mobileconnection/MobileConnectionIPCSerializer.h"; +using nsMobileConnectionInfo from "mozilla/dom/MobileConnectionIPCSerializer.h"; +using nsMobileNetworkInfo from "mozilla/dom/MobileConnectionIPCSerializer.h"; using struct mozilla::void_t from "ipc/IPCMessageUtils.h"; -using struct IPC::MozCallForwardingOptions from "mozilla/dom/mobileconnection/MobileConnectionIPCSerializer.h"; -using struct IPC::MozCallBarringOptions from "mozilla/dom/mobileconnection/MobileConnectionIPCSerializer.h"; +using struct IPC::MozCallForwardingOptions from "mozilla/dom/MobileConnectionIPCSerializer.h"; +using struct IPC::MozCallBarringOptions from "mozilla/dom/MobileConnectionIPCSerializer.h"; namespace mozilla { namespace dom { -namespace mobileconnection { union AdditionalInformation { void_t; uint16_t; nsString[]; MozCallForwardingOptions[]; }; -} // namespace mobileconnection } // namespace dom } // namespace mozilla
--- a/dom/mobileconnection/moz.build +++ b/dom/mobileconnection/moz.build @@ -1,40 +1,35 @@ # -*- Mode: python; c-basic-offset: 4; 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/. +DIRS += ['interfaces'] + MOCHITEST_MANIFESTS += ['tests/mochitest/mochitest.ini'] EXPORTS.mozilla.dom += [ 'DOMMMIError.h', + 'ipc/MobileConnectionIPCSerializer.h', 'MobileCellInfo.h', 'MobileConnection.h', 'MobileConnectionArray.h', + 'MobileConnectionCallback.h', 'MobileConnectionInfo.h', 'MobileNetworkInfo.h', ] EXPORTS.mozilla.dom.mobileconnection += [ 'ipc/MobileConnectionChild.h', - 'ipc/MobileConnectionIPCSerializer.h', + 'ipc/MobileConnectionIPCService.h', 'ipc/MobileConnectionParent.h', ] -XPIDL_SOURCES += [ - 'interfaces/nsICellInfo.idl', - 'interfaces/nsIMobileCellInfo.idl', - 'interfaces/nsIMobileConnectionInfo.idl', - 'interfaces/nsIMobileConnectionService.idl', - 'interfaces/nsIMobileNetworkInfo.idl', - 'interfaces/nsINeighboringCellInfo.idl', -] - SOURCES += [ 'DOMMMIError.cpp', 'ipc/MobileConnectionChild.cpp', 'ipc/MobileConnectionIPCService.cpp', 'ipc/MobileConnectionParent.cpp', 'MobileCellInfo.cpp', 'MobileConnection.cpp', 'MobileConnectionArray.cpp', @@ -45,23 +40,18 @@ SOURCES += [ IPDL_SOURCES += [ 'ipc/PMobileConnection.ipdl', 'ipc/PMobileConnectionRequest.ipdl', 'ipc/PMobileConnectionTypes.ipdlh', ] if CONFIG['MOZ_WIDGET_TOOLKIT'] == 'gonk' and CONFIG['MOZ_B2G_RIL']: - XPIDL_SOURCES += [ - 'gonk/nsIGonkMobileConnectionService.idl', - ] EXTRA_COMPONENTS += [ - 'gonk/MobileConnectionService.js', - 'gonk/MobileConnectionService.manifest', + 'gonk/MobileConnectionGonkService.js', + 'gonk/MobileConnectionGonkService.manifest', ] FAIL_ON_WARNINGS = True include('/ipc/chromium/chromium-config.mozbuild') FINAL_LIBRARY = 'xul' - -XPIDL_MODULE = 'dom_mobileconnection'
--- a/dom/mobilemessage/MobileMessageManager.cpp +++ b/dom/mobilemessage/MobileMessageManager.cpp @@ -18,33 +18,20 @@ #include "mozilla/dom/ToJSValue.h" #include "mozilla/Preferences.h" #include "mozilla/Services.h" #include "nsIDOMMozMmsMessage.h" #include "nsIDOMMozSmsMessage.h" #include "nsIMmsService.h" #include "nsIMobileMessageCallback.h" #include "nsIMobileMessageDatabaseService.h" -#include "nsIMobileMessageService.h" #include "nsIObserverService.h" #include "nsISmsService.h" #include "nsServiceManagerUtils.h" // For do_GetService() -// Service instantiation -#include "ipc/SmsIPCService.h" -#include "MobileMessageService.h" -#ifdef MOZ_WIDGET_ANDROID -#include "android/MobileMessageDatabaseService.h" -#include "android/SmsService.h" -#elif defined(MOZ_WIDGET_GONK) && defined(MOZ_B2G_RIL) -#include "nsIRilMobileMessageDatabaseService.h" -#include "gonk/SmsService.h" -#endif -#include "nsXULAppAPI.h" // For XRE_GetProcessType() - #define RECEIVED_EVENT_NAME NS_LITERAL_STRING("received") #define RETRIEVING_EVENT_NAME NS_LITERAL_STRING("retrieving") #define SENDING_EVENT_NAME NS_LITERAL_STRING("sending") #define SENT_EVENT_NAME NS_LITERAL_STRING("sent") #define FAILED_EVENT_NAME NS_LITERAL_STRING("failed") #define DELIVERY_SUCCESS_EVENT_NAME NS_LITERAL_STRING("deliverysuccess") #define DELIVERY_ERROR_EVENT_NAME NS_LITERAL_STRING("deliveryerror") #define READ_SUCCESS_EVENT_NAME NS_LITERAL_STRING("readsuccess") @@ -694,67 +681,8 @@ MobileMessageManager::GetSmscAddress(con return nullptr; } return request.forget(); } } // namespace dom } // namespace mozilla - -already_AddRefed<nsISmsService> -NS_CreateSmsService() -{ - nsCOMPtr<nsISmsService> smsService; - - if (XRE_GetProcessType() == GeckoProcessType_Content) { - smsService = SmsIPCService::GetSingleton(); - } else { -#ifdef MOZ_WIDGET_ANDROID - smsService = new SmsService(); -#elif defined(MOZ_WIDGET_GONK) && defined(MOZ_B2G_RIL) - smsService = new SmsService(); -#endif - } - - return smsService.forget(); -} - -already_AddRefed<nsIMobileMessageDatabaseService> -NS_CreateMobileMessageDatabaseService() -{ - nsCOMPtr<nsIMobileMessageDatabaseService> mobileMessageDBService; - if (XRE_GetProcessType() == GeckoProcessType_Content) { - mobileMessageDBService = SmsIPCService::GetSingleton(); - } else { -#ifdef MOZ_WIDGET_ANDROID - mobileMessageDBService = new MobileMessageDatabaseService(); -#elif defined(MOZ_WIDGET_GONK) && defined(MOZ_B2G_RIL) - mobileMessageDBService = - do_CreateInstance(RIL_MOBILE_MESSAGE_DATABASE_SERVICE_CONTRACTID); -#endif - } - - return mobileMessageDBService.forget(); -} - -already_AddRefed<nsIMmsService> -NS_CreateMmsService() -{ - nsCOMPtr<nsIMmsService> mmsService; - - if (XRE_GetProcessType() == GeckoProcessType_Content) { - mmsService = SmsIPCService::GetSingleton(); - } else { -#if defined(MOZ_WIDGET_GONK) && defined(MOZ_B2G_RIL) - mmsService = do_CreateInstance("@mozilla.org/mms/rilmmsservice;1"); -#endif - } - - return mmsService.forget(); -} - -already_AddRefed<nsIMobileMessageService> -NS_CreateMobileMessageService() -{ - nsCOMPtr<nsIMobileMessageService> service = new MobileMessageService(); - return service.forget(); -}
--- a/dom/mobilemessage/MobileMessageService.cpp +++ b/dom/mobilemessage/MobileMessageService.cpp @@ -9,16 +9,30 @@ #include "DeletedMessageInfo.h" namespace mozilla { namespace dom { namespace mobilemessage { NS_IMPL_ISUPPORTS(MobileMessageService, nsIMobileMessageService) +/* static */ StaticRefPtr<MobileMessageService> MobileMessageService::sSingleton; + +/* static */ already_AddRefed<MobileMessageService> +MobileMessageService::GetInstance() +{ + if (!sSingleton) { + sSingleton = new MobileMessageService(); + ClearOnShutdown(&sSingleton); + } + + nsRefPtr<MobileMessageService> service = sSingleton.get(); + return service.forget(); +} + NS_IMETHODIMP MobileMessageService::CreateSmsMessage(int32_t aId, uint64_t aThreadId, const nsAString& aIccId, const nsAString& aDelivery, const nsAString& aDeliveryStatus, const nsAString& aSender, const nsAString& aReceiver,
--- a/dom/mobilemessage/MobileMessageService.h +++ b/dom/mobilemessage/MobileMessageService.h @@ -1,32 +1,35 @@ /* 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_mobilemessage_MobileMessageService_h #define mozilla_dom_mobilemessage_MobileMessageService_h -#include "mozilla/Attributes.h" // For MOZ_FINAL #include "nsIMobileMessageService.h" +#include "mozilla/ClearOnShutdown.h" +#include "mozilla/StaticPtr.h" namespace mozilla { namespace dom { namespace mobilemessage { class MobileMessageService MOZ_FINAL : public nsIMobileMessageService { public: NS_DECL_ISUPPORTS NS_DECL_NSIMOBILEMESSAGESERVICE - MobileMessageService() { MOZ_COUNT_CTOR(MobileMessageService); } + static already_AddRefed<MobileMessageService> GetInstance(); private: - // MOZ_FINAL suppresses -Werror,-Wdelete-non-virtual-dtor - ~MobileMessageService() { MOZ_COUNT_DTOR(MobileMessageService); } + ~MobileMessageService() {} + + static StaticRefPtr<MobileMessageService> sSingleton; + }; } // namespace mobilemessage } // namespace dom } // namespace mozilla #endif // mozilla_dom_mobilemessage_MobileMessageService_h
new file mode 100644 --- /dev/null +++ b/dom/mobilemessage/SmsServicesFactory.cpp @@ -0,0 +1,77 @@ +/* -*- Mode: C++; 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 "SmsServicesFactory.h" +#include "nsXULAppAPI.h" +#include "ipc/SmsIPCService.h" +#ifdef MOZ_WIDGET_ANDROID +#include "android/MobileMessageDatabaseService.h" +#include "android/SmsService.h" +#elif defined(MOZ_WIDGET_GONK) && defined(MOZ_B2G_RIL) +#include "gonk/SmsService.h" +#endif +#include "nsServiceManagerUtils.h" + +#define RIL_MMSSERVICE_CONTRACTID "@mozilla.org/mms/rilmmsservice;1" +#define RIL_MOBILE_MESSAGE_DATABASE_SERVICE_CONTRACTID "@mozilla.org/mobilemessage/rilmobilemessagedatabaseservice;1" + +namespace mozilla { +namespace dom { +namespace mobilemessage { + +/* static */ already_AddRefed<nsISmsService> +SmsServicesFactory::CreateSmsService() +{ + nsCOMPtr<nsISmsService> smsService; + + if (XRE_GetProcessType() == GeckoProcessType_Content) { + smsService = new SmsIPCService(); + } else { +#ifdef MOZ_WIDGET_ANDROID + smsService = new SmsService(); +#elif defined(MOZ_WIDGET_GONK) && defined(MOZ_B2G_RIL) + smsService = new SmsService(); +#endif + } + + return smsService.forget(); +} + +/* static */ already_AddRefed<nsIMobileMessageDatabaseService> +SmsServicesFactory::CreateMobileMessageDatabaseService() +{ + nsCOMPtr<nsIMobileMessageDatabaseService> mobileMessageDBService; + if (XRE_GetProcessType() == GeckoProcessType_Content) { + mobileMessageDBService = new SmsIPCService(); + } else { +#ifdef MOZ_WIDGET_ANDROID + mobileMessageDBService = new MobileMessageDatabaseService(); +#elif defined(MOZ_WIDGET_GONK) && defined(MOZ_B2G_RIL) + mobileMessageDBService = do_GetService(RIL_MOBILE_MESSAGE_DATABASE_SERVICE_CONTRACTID); +#endif + } + + return mobileMessageDBService.forget(); +} + +/* static */ already_AddRefed<nsIMmsService> +SmsServicesFactory::CreateMmsService() +{ + nsCOMPtr<nsIMmsService> mmsService; + + if (XRE_GetProcessType() == GeckoProcessType_Content) { + mmsService = new SmsIPCService(); + } else { +#if defined(MOZ_WIDGET_GONK) && defined(MOZ_B2G_RIL) + mmsService = do_CreateInstance(RIL_MMSSERVICE_CONTRACTID); +#endif + } + + return mmsService.forget(); +} + +} // namespace mobilemessage +} // namespace dom +} // namespace mozilla
new file mode 100644 --- /dev/null +++ b/dom/mobilemessage/SmsServicesFactory.h @@ -0,0 +1,31 @@ +/* -*- Mode: C++; 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/. */ + +#ifndef mozilla_dom_mobilemessage_SmsServicesFactory_h +#define mozilla_dom_mobilemessage_SmsServicesFactory_h + +#include "nsCOMPtr.h" + +class nsISmsService; +class nsIMmsService; +class nsIMobileMessageDatabaseService; + +namespace mozilla { +namespace dom { +namespace mobilemessage { + +class SmsServicesFactory +{ +public: + static already_AddRefed<nsISmsService> CreateSmsService(); + static already_AddRefed<nsIMobileMessageDatabaseService> CreateMobileMessageDatabaseService(); + static already_AddRefed<nsIMmsService> CreateMmsService(); +}; + +} // namespace mobilemessage +} // namespace dom +} // namespace mozilla + +#endif // mozilla_dom_mobilemessage_SmsServicesFactory_h
--- a/dom/mobilemessage/gonk/MmsService.js +++ b/dom/mobilemessage/gonk/MmsService.js @@ -323,19 +323,18 @@ MmsConnection.prototype = { }, /** * Return the roaming status of voice call. * * @return true if voice call is roaming. */ isVoiceRoaming: function() { - let connection = - gMobileConnectionService.getItemByServiceId(this.serviceId); - let isRoaming = connection && connection.voice && connection.voice.roaming; + let voice = gMobileConnectionService.getVoiceConnectionInfo(this.serviceId); + let isRoaming = voice.roaming; if (DEBUG) debug("isVoiceRoaming = " + isRoaming); return isRoaming; }, /** * Get phone number from iccInfo. * * If the icc card is gsm card, the phone number is in msisdn.
--- a/dom/mobilemessage/interfaces/nsIMmsService.idl +++ b/dom/mobilemessage/interfaces/nsIMmsService.idl @@ -1,14 +1,13 @@ /* 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 nsIMobileMessageCallback; interface nsIDOMBlob; %{C++ #define MMS_SERVICE_CID { 0x06d9124b, 0x80e0, 0x40ed, \ { 0x98, 0x71, 0x4d, 0x23, 0x4a, 0x0f, 0xd4, 0x31 } } #define MMS_SERVICE_CONTRACTID "@mozilla.org/mms/mmsservice;1" %} @@ -24,15 +23,8 @@ interface nsIMmsService : nsISupports void retrieve(in long id, in nsIMobileMessageCallback request); void sendReadReport(in DOMString messageID, in DOMString toAddress, in DOMString iccId); }; - -%{C++ -template<typename T> struct already_AddRefed; - -already_AddRefed<nsIMmsService> -NS_CreateMmsService(); -%}
--- a/dom/mobilemessage/interfaces/nsIMobileMessageDatabaseService.idl +++ b/dom/mobilemessage/interfaces/nsIMobileMessageDatabaseService.idl @@ -41,15 +41,8 @@ interface nsIMobileMessageDatabaseServic void markMessageRead(in long messageId, in boolean value, in boolean sendReadReport, in nsIMobileMessageCallback request); nsICursorContinueCallback createThreadCursor(in nsIMobileMessageCursorCallback callback); }; - -%{C++ -template<typename T> struct already_AddRefed; - -already_AddRefed<nsIMobileMessageDatabaseService> -NS_CreateMobileMessageDatabaseService(); -%}
--- a/dom/mobilemessage/interfaces/nsIMobileMessageService.idl +++ b/dom/mobilemessage/interfaces/nsIMobileMessageService.idl @@ -59,15 +59,8 @@ interface nsIMobileMessageService : nsIS in DOMString aLastMessageType); nsIDeletedMessageInfo createDeletedMessageInfo( [array, size_is(msgCount)] in long messageIds, in uint32_t msgCount, [array, size_is(threadCount)] in unsigned long long threadIds, in uint32_t threadCount); }; - -%{C++ -template<typename T> struct already_AddRefed; - -already_AddRefed<nsIMobileMessageService> -NS_CreateMobileMessageService(); -%}
--- a/dom/mobilemessage/interfaces/nsIRilMobileMessageDatabaseService.idl +++ b/dom/mobilemessage/interfaces/nsIRilMobileMessageDatabaseService.idl @@ -29,23 +29,16 @@ interface nsIRilMobileMessageDatabaseRec interface nsIRilMobileMessageDatabaseConcatenationCallback : nsISupports { /** * |aCompleteMessage|: jsval: the completely concatenated message. Noted, this value might be null. */ void notify(in nsresult aRv, in jsval aCompleteMessage); }; -%{C++ -#define RIL_MOBILE_MESSAGE_DATABASE_SERVICE_CID \ - { 0x29785f90, 0x6b5b, 0x11e2, { 0x92, 0x01, 0x3b, 0x28, 0x01, 0x70, 0xb2, 0xec } } -#define RIL_MOBILE_MESSAGE_DATABASE_SERVICE_CONTRACTID \ - "@mozilla.org/mobilemessage/rilmobilemessagedatabaseservice;1" -%} - [scriptable, uuid(0b437a5c-a2bc-11e3-bd1b-dbb173eb35f8)] interface nsIRilMobileMessageDatabaseService : nsIMobileMessageDatabaseService { /** * |aMessage| Object: should contain the following properties for internal use: * - |type| DOMString: "sms" or "mms" * - |timestamp| Number: the timestamp of received message * - |iccId| DOMString: [optional] the ICC ID of the SIM for receiving
--- a/dom/mobilemessage/interfaces/nsISmsService.idl +++ b/dom/mobilemessage/interfaces/nsISmsService.idl @@ -28,15 +28,8 @@ interface nsISmsService : nsISupports boolean isSilentNumber(in DOMString number); void addSilentNumber(in DOMString number); void removeSilentNumber(in DOMString number); void getSmscAddress(in unsigned long serviceId, in nsIMobileMessageCallback request); }; - -%{C++ -template<typename T> struct already_AddRefed; - -already_AddRefed<nsISmsService> -NS_CreateSmsService(); -%}
--- a/dom/mobilemessage/ipc/SmsIPCService.cpp +++ b/dom/mobilemessage/ipc/SmsIPCService.cpp @@ -27,19 +27,16 @@ const char* kObservedPrefs[] = { kPrefMmsDefaultServiceId, kPrefSmsDefaultServiceId, nullptr }; // TODO: Bug 767082 - WebSMS: sSmsChild leaks at shutdown PSmsChild* gSmsChild; -// SmsIPCService is owned by nsLayoutModule. -SmsIPCService* sSingleton = nullptr; - PSmsChild* GetSmsChild() { MOZ_ASSERT(NS_IsMainThread()); if (!gSmsChild) { gSmsChild = ContentChild::GetSingleton()->SendPSmsConstructor(); @@ -100,41 +97,23 @@ getDefaultServiceId(const char* aPrefKey } // anonymous namespace NS_IMPL_ISUPPORTS(SmsIPCService, nsISmsService, nsIMmsService, nsIMobileMessageDatabaseService, nsIObserver) -/* static */ already_AddRefed<SmsIPCService> -SmsIPCService::GetSingleton() -{ - MOZ_ASSERT(NS_IsMainThread()); - - if (!sSingleton) { - sSingleton = new SmsIPCService(); - } - - nsRefPtr<SmsIPCService> service = sSingleton; - return service.forget(); -} - SmsIPCService::SmsIPCService() { Preferences::AddStrongObservers(this, kObservedPrefs); mMmsDefaultServiceId = getDefaultServiceId(kPrefMmsDefaultServiceId); mSmsDefaultServiceId = getDefaultServiceId(kPrefSmsDefaultServiceId); } -SmsIPCService::~SmsIPCService() -{ - sSingleton = nullptr; -} - /* * Implementation of nsIObserver. */ NS_IMETHODIMP SmsIPCService::Observe(nsISupports* aSubject, const char* aTopic, const char16_t* aData)
--- a/dom/mobilemessage/ipc/SmsIPCService.h +++ b/dom/mobilemessage/ipc/SmsIPCService.h @@ -25,24 +25,20 @@ class SmsIPCService MOZ_FINAL : public n { public: NS_DECL_ISUPPORTS NS_DECL_NSISMSSERVICE NS_DECL_NSIMMSSERVICE NS_DECL_NSIMOBILEMESSAGEDATABASESERVICE NS_DECL_NSIOBSERVER - static already_AddRefed<SmsIPCService> - GetSingleton(); + SmsIPCService(); private: - SmsIPCService(); - - // MOZ_FINAL suppresses -Werror,-Wdelete-non-virtual-dtor - ~SmsIPCService(); + ~SmsIPCService() {} uint32_t mMmsDefaultServiceId; uint32_t mSmsDefaultServiceId; }; } // namespace mobilemessage } // namespace dom } // namespace mozilla
--- a/dom/mobilemessage/moz.build +++ b/dom/mobilemessage/moz.build @@ -8,16 +8,18 @@ DIRS += ['interfaces'] MOCHITEST_MANIFESTS += ['tests/mochitest/mochitest.ini'] XPCSHELL_TESTS_MANIFESTS += ['tests/xpcshell/xpcshell.ini'] EXPORTS.mozilla.dom.mobilemessage += [ 'Constants.h', # Required by almost all cpp files 'ipc/SmsChild.h', 'ipc/SmsParent.h', + 'MobileMessageService.h', # Required by nsLayoutModule.cpp + 'SmsServicesFactory.h', # Required by nsLayoutModule.cpp 'Types.h', # Required by IPDL SmsTypes.h ] if CONFIG['MOZ_WIDGET_TOOLKIT'] == 'android': SOURCES += [ 'android/MobileMessageDatabaseService.cpp', 'android/SmsService.cpp', ] @@ -55,16 +57,17 @@ UNIFIED_SOURCES += [ 'ipc/SmsParent.cpp', 'MmsMessage.cpp', 'MobileMessageCallback.cpp', 'MobileMessageCursorCallback.cpp', 'MobileMessageManager.cpp', 'MobileMessageService.cpp', 'MobileMessageThread.cpp', 'SmsMessage.cpp', + 'SmsServicesFactory.cpp', ] IPDL_SOURCES += [ 'ipc/PMobileMessageCursor.ipdl', 'ipc/PSms.ipdl', 'ipc/PSmsRequest.ipdl', 'ipc/SmsTypes.ipdlh', ]
--- a/dom/notification/ChromeNotifications.js +++ b/dom/notification/ChromeNotifications.js @@ -43,30 +43,37 @@ ChromeNotifications.prototype = { Services.obs.addObserver(this, "inner-window-destroyed", false); cpmm.addMessageListener("Notification:GetAllCrossOrigin:Return:OK", this); }, performResend: function(notifications) { let resentNotifications = 0; notifications.forEach(function(notification) { + let behavior; + try { + behavior = JSON.parse(notification.mozbehavior); + } catch(e) { + behavior = undefined; + } appNotifier.showAppNotification( notification.icon, notification.title, notification.body, null, { manifestURL: notification.origin, id: notification.alertName, dir: notification.dir, lang: notification.lang, tag: notification.tag, dbId: notification.id, timestamp: notification.timestamp, - data: notification.data + data: notification.data, + mozbehavior: behavior } ); resentNotifications++; }); try { this.resendCallback && this.resendCallback(resentNotifications); } catch (ex) {
--- a/dom/notification/Notification.cpp +++ b/dom/notification/Notification.cpp @@ -56,30 +56,33 @@ public: NS_IMETHOD Handle(const nsAString& aID, const nsAString& aTitle, const nsAString& aDir, const nsAString& aLang, const nsAString& aBody, const nsAString& aTag, const nsAString& aIcon, const nsAString& aData, + const nsAString& aBehavior, JSContext* aCx) { MOZ_ASSERT(!aID.IsEmpty()); RootedDictionary<NotificationOptions> options(aCx); options.mDir = Notification::StringToDirection(nsString(aDir)); options.mLang = aLang; options.mBody = aBody; options.mTag = aTag; options.mIcon = aIcon; - nsRefPtr<Notification> notification = Notification::CreateInternal(mWindow, - aID, - aTitle, - options); + options.mMozbehavior.Init(aBehavior); + nsRefPtr<Notification> notification; + notification = Notification::CreateInternal(mWindow, + aID, + aTitle, + options); ErrorResult rv; notification->InitFromBase64(aCx, aData, rv); if (rv.Failed()) { return rv.ErrorCode(); } notification->SetStoredState(true); @@ -390,20 +393,20 @@ NotificationObserver::Observe(nsISupport } return NS_OK; } Notification::Notification(const nsAString& aID, const nsAString& aTitle, const nsAString& aBody, NotificationDirection aDir, const nsAString& aLang, const nsAString& aTag, const nsAString& aIconUrl, - nsPIDOMWindow* aWindow) + const NotificationBehavior& aBehavior, nsPIDOMWindow* aWindow) : DOMEventTargetHelper(aWindow), mID(aID), mTitle(aTitle), mBody(aBody), mDir(aDir), mLang(aLang), - mTag(aTag), mIconUrl(aIconUrl), mIsClosed(false), mIsStored(false) + mTag(aTag), mIconUrl(aIconUrl), mBehavior(aBehavior), mIsClosed(false), mIsStored(false) { nsAutoString alertName; DebugOnly<nsresult> rv = GetOrigin(GetOwner(), alertName); MOZ_ASSERT(NS_SUCCEEDED(rv), "GetOrigin should not have failed"); // Get the notification name that is unique per origin + tag/ID. // The name of the alert is of the form origin#tag/ID. alertName.Append('#'); @@ -469,26 +472,33 @@ Notification::Constructor(const GlobalOb nsString dataString; nsCOMPtr<nsIStructuredCloneContainer> scContainer; scContainer = notification->GetDataCloneContainer(); if (scContainer) { scContainer->GetDataAsBase64(dataString); } + nsAutoString behavior; + if (!aOptions.mMozbehavior.ToJSON(behavior)) { + aRv.Throw(NS_ERROR_FAILURE); + return nullptr; + } + aRv = notificationStorage->Put(origin, id, aTitle, DirectionToString(aOptions.mDir), aOptions.mLang, aOptions.mBody, aOptions.mTag, aOptions.mIcon, alertName, - dataString); + dataString, + behavior); if (aRv.Failed()) { return nullptr; } notification->SetStoredState(true); return notification.forget(); @@ -519,16 +529,17 @@ Notification::CreateInternal(nsPIDOMWind nsRefPtr<Notification> notification = new Notification(id, aTitle, aOptions.mBody, aOptions.mDir, aOptions.mLang, aOptions.mTag, aOptions.mIcon, + aOptions.mMozbehavior, aWindow); return notification.forget(); } Notification::~Notification() {} NS_IMPL_CYCLE_COLLECTION_CLASS(Notification) NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN_INHERITED(Notification, DOMEventTargetHelper) @@ -567,32 +578,42 @@ Notification::ShowInternal() // We do not have permission to show a notification or alert service // is not available. DispatchTrustedEvent(NS_LITERAL_STRING("error")); return; } nsresult rv; nsAutoString absoluteUrl; - if (mIconUrl.Length() > 0) { - // Resolve image URL against document base URI. - nsIDocument* doc = GetOwner()->GetExtantDoc(); - if (doc) { - nsCOMPtr<nsIURI> baseUri = doc->GetBaseURI(); - if (baseUri) { + nsAutoString soundUrl; + // Resolve image URL against document base URI. + nsIDocument* doc = GetOwner()->GetExtantDoc(); + if (doc) { + nsCOMPtr<nsIURI> baseUri = doc->GetBaseURI(); + if (baseUri) { + if (mIconUrl.Length() > 0) { nsCOMPtr<nsIURI> srcUri; rv = nsContentUtils::NewURIWithDocumentCharset(getter_AddRefs(srcUri), mIconUrl, doc, baseUri); if (NS_SUCCEEDED(rv)) { nsAutoCString src; srcUri->GetSpec(src); absoluteUrl = NS_ConvertUTF8toUTF16(src); } } - + if (mBehavior.mSoundFile.Length() > 0) { + nsCOMPtr<nsIURI> srcUri; + rv = nsContentUtils::NewURIWithDocumentCharset(getter_AddRefs(srcUri), + mBehavior.mSoundFile, doc, baseUri); + if (NS_SUCCEEDED(rv)) { + nsAutoCString src; + srcUri->GetSpec(src); + soundUrl = NS_ConvertUTF8toUTF16(src); + } + } } } nsCOMPtr<nsIObserver> observer = new NotificationObserver(this); // mDataObjectContainer might be uninitialized here because the notification // was constructed with an undefined data property. nsString dataStr; @@ -618,16 +639,18 @@ Notification::ShowInternal() ops.mTextClickable = true; ops.mManifestURL = manifestUrl; ops.mId = mAlertName; ops.mDbId = mID; ops.mDir = DirectionToString(mDir); ops.mLang = mLang; ops.mTag = mTag; ops.mData = dataStr; + ops.mMozbehavior = mBehavior; + ops.mMozbehavior.mSoundFile = soundUrl; if (!ToJSValue(cx, ops, &val)) { NS_WARNING("Converting dict to object failed!"); return; } appNotifier->ShowAppNotification(mIconUrl, mTitle, mBody, observer, val);
--- a/dom/notification/Notification.h +++ b/dom/notification/Notification.h @@ -109,21 +109,22 @@ public: virtual JSObject* WrapObject(JSContext* aCx) MOZ_OVERRIDE; void GetData(JSContext* aCx, JS::MutableHandle<JS::Value> aRetval); void InitFromJSVal(JSContext* aCx, JS::Handle<JS::Value> aData, ErrorResult& aRv); void InitFromBase64(JSContext* aCx, const nsAString& aData, ErrorResult& aRv); + protected: Notification(const nsAString& aID, const nsAString& aTitle, const nsAString& aBody, NotificationDirection aDir, const nsAString& aLang, const nsAString& aTag, const nsAString& aIconUrl, - nsPIDOMWindow* aWindow); + const NotificationBehavior& aBehavior, nsPIDOMWindow* aWindow); static already_AddRefed<Notification> CreateInternal(nsPIDOMWindow* aWindow, const nsAString& aID, const nsAString& aTitle, const NotificationOptions& aOptions); void ShowInternal(); void CloseInternal(); @@ -164,16 +165,17 @@ protected: nsString mID; nsString mTitle; nsString mBody; NotificationDirection mDir; nsString mLang; nsString mTag; nsString mIconUrl; nsCOMPtr<nsIStructuredCloneContainer> mDataObjectContainer; + NotificationBehavior mBehavior; // It's null until GetData is first called nsCOMPtr<nsIVariant> mData; nsString mAlertName; bool mIsClosed;
--- a/dom/notification/NotificationStorage.js +++ b/dom/notification/NotificationStorage.js @@ -67,30 +67,31 @@ NotificationStorage.prototype = { if (DEBUG) debug("Topic: " + aTopic); if (aTopic == "xpcom-shutdown") { Services.obs.removeObserver(this, "xpcom-shutdown"); this.unregisterListeners(); } }, put: function(origin, id, title, dir, lang, body, tag, icon, alertName, - data) { + data, behavior) { if (DEBUG) { debug("PUT: " + id + ": " + title); } var notification = { id: id, title: title, dir: dir, lang: lang, body: body, tag: tag, icon: icon, alertName: alertName, timestamp: new Date().getTime(), origin: origin, - data: data + data: data, + behavior: behavior }; this._notifications[id] = notification; if (tag) { if (!this._byTag[origin]) { this._byTag[origin] = {}; } @@ -200,17 +201,18 @@ NotificationStorage.prototype = { try { callback.handle(notification.id, notification.title, notification.dir, notification.lang, notification.body, notification.tag, notification.icon, - notification.data); + notification.data, + notification.behavior); } catch (e) { if (DEBUG) { debug("Error calling callback handle: " + e); } } }); try { callback.done(); } catch (e) { if (DEBUG) { debug("Error calling callback done: " + e); }
--- a/dom/phonenumberutils/PhoneNumberUtils.jsm +++ b/dom/phonenumberutils/PhoneNumberUtils.jsm @@ -49,18 +49,17 @@ this.PhoneNumberUtils = { // In Multi-sim, there is more than one client in // iccProvider/mobileConnectionProvider. Each client represents a // icc/mobileConnection service. To maintain the backward compatibility with // single sim, we always use client 0 for now. Adding support for multiple // sim will be addressed in bug 926740, if needed. let clientId = 0; // Get network mcc - let connection = mobileConnection.getItemByServiceId(clientId); - let voice = connection && connection.voice; + let voice = mobileConnection.getVoiceConnectionInfo(clientId); if (voice && voice.network && voice.network.mcc) { mcc = voice.network.mcc; } // Get SIM mcc let iccInfo = icc.getIccInfo(clientId); if (!mcc && iccInfo && iccInfo.mcc) { mcc = iccInfo.mcc;
--- a/dom/system/NetworkGeolocationProvider.js +++ b/dom/system/NetworkGeolocationProvider.js @@ -407,24 +407,24 @@ WifiGeoPositionProvider.prototype = { getMobileInfo: function() { LOG("getMobileInfo called"); try { let radioService = Cc["@mozilla.org/ril;1"] .getService(Ci.nsIRadioInterfaceLayer); let service = Cc["@mozilla.org/mobileconnection/mobileconnectionservice;1"] .getService(Ci.nsIMobileConnectionService); + let numInterfaces = radioService.numRadioInterfaces; let result = []; - for (let i = 0; i < service.length; i++) { - LOG("Looking for SIM in slot:" + i + " of " + service.length); - let connection = service.getItemByServiceId(i); - let voice = connection && connection.voice; - let cell = voice && voice.cell; - let type = voice && voice.type; - let network = voice && voice.network; + for (let i = 0; i < numInterfaces; i++) { + LOG("Looking for SIM in slot:" + i + " of " + numInterfaces); + let voice = service.getVoiceConnectionInfo(i); + let cell = voice.cell; + let type = voice.type; + let network = voice.network; if (network && cell && type) { if (type === "gsm" || type === "gprs" || type === "edge") { type = "gsm"; } else { type = "wcdma"; } result.push({ radio: type,
--- a/dom/system/gonk/GonkGPSGeolocationProvider.cpp +++ b/dom/system/gonk/GonkGPSGeolocationProvider.cpp @@ -518,24 +518,20 @@ GonkGPSGeolocationProvider::SetReference nsCOMPtr<nsIMobileConnectionService> service = do_GetService(NS_MOBILE_CONNECTION_SERVICE_CONTRACTID); if (!service) { NS_WARNING("Cannot get MobileConnectionService"); return; } - nsCOMPtr<nsIMobileConnection> connection; + nsCOMPtr<nsIMobileConnectionInfo> voice; // TODO: Bug 878748 - B2G GPS: acquire correct RadioInterface instance in // MultiSIM configuration - service->GetItemByServiceId(0 /* Client Id */, getter_AddRefs(connection)); - NS_ENSURE_TRUE_VOID(connection); - - nsCOMPtr<nsIMobileConnectionInfo> voice; - connection->GetVoice(getter_AddRefs(voice)); + service->GetVoiceConnectionInfo(0 /* Client Id */, getter_AddRefs(voice)); if (voice) { nsCOMPtr<nsIMobileCellInfo> cell; voice->GetCell(getter_AddRefs(cell)); if (cell) { int32_t lac; int64_t cid; cell->GetGsmLocationAreaCode(&lac); @@ -946,38 +942,26 @@ GonkGPSGeolocationProvider::Observe(nsIS int32_t state; int32_t type; iface->GetState(&state); iface->GetType(&type); bool connected = (state == nsINetworkInterface::NETWORK_STATE_CONNECTED); bool roaming = false; int gpsNetworkType = ConvertToGpsNetworkType(type); if (gpsNetworkType >= 0) { - if (rilface) { - do { - nsCOMPtr<nsIMobileConnectionService> service = - do_GetService(NS_MOBILE_CONNECTION_SERVICE_CONTRACTID); - if (!service) { - break; - } - - nsCOMPtr<nsIMobileConnection> connection; - // TODO: Bug 878748 - B2G GPS: acquire correct RadioInterface instance in - // MultiSIM configuration - service->GetItemByServiceId(0 /* Client Id */, getter_AddRefs(connection)); - if (!connection) { - break; - } - - nsCOMPtr<nsIMobileConnectionInfo> voice; - connection->GetVoice(getter_AddRefs(voice)); - if (voice) { - voice->GetRoaming(&roaming); - } - } while (0); + nsCOMPtr<nsIMobileConnectionService> service = + do_GetService(NS_MOBILE_CONNECTION_SERVICE_CONTRACTID); + if (rilface && service) { + nsCOMPtr<nsIMobileConnectionInfo> voice; + // TODO: Bug 878748 - B2G GPS: acquire correct RadioInterface instance in + // MultiSIM configuration + service->GetVoiceConnectionInfo(0 /* Client Id */, getter_AddRefs(voice)); + if (voice) { + voice->GetRoaming(&roaming); + } } mAGpsRilInterface->update_network_state( connected, gpsNetworkType, roaming, /* extra_info = */ nullptr); } }
--- a/dom/system/gonk/NetworkManager.js +++ b/dom/system/gonk/NetworkManager.js @@ -854,19 +854,17 @@ NetworkManager.prototype = { } } }, dunRetryTimes: 0, dunRetryTimer: Cc["@mozilla.org/timer;1"].createInstance(Ci.nsITimer), setupDunConnection: function() { this.dunRetryTimer.cancel(); - let connection = - gMobileConnectionService.getItemByServiceId(this._dataDefaultServiceId); - let data = connection && connection.data; + let data = gMobileConnectionService.getDataConnectionInfo(this._dataDefaultServiceId); if (data && data.state === "registered") { this.dunRetryTimes = 0; ril.setupDataCallByType("dun"); this.dunConnectTimer.cancel(); this.dunConnectTimer. initWithCallback(this.onDunConnectTimerTimeout.bind(this), MOBILE_DUN_CONNECT_TIMEOUT, Ci.nsITimer.TYPE_ONE_SHOT); return;
--- a/dom/system/gonk/RadioInterfaceLayer.js +++ b/dom/system/gonk/RadioInterfaceLayer.js @@ -196,17 +196,17 @@ XPCOMUtils.defineLazyServiceGetter(this, "nsISystemWorkerManager"); XPCOMUtils.defineLazyServiceGetter(this, "gTelephonyService", "@mozilla.org/telephony/telephonyservice;1", "nsIGonkTelephonyService"); XPCOMUtils.defineLazyServiceGetter(this, "gMobileConnectionService", "@mozilla.org/mobileconnection/mobileconnectionservice;1", - "nsIGonkMobileConnectionService"); + "nsIMobileConnectionGonkService"); XPCOMUtils.defineLazyGetter(this, "WAP", function() { let wap = {}; Cu.import("resource://gre/modules/WapPushManager.js", wap); return wap; }); XPCOMUtils.defineLazyGetter(this, "PhoneNumberUtils", function() { @@ -579,41 +579,41 @@ XPCOMUtils.defineLazyGetter(this, "gRadi numCards = numCards == null ? this._getNumCards() : numCards; if (clientId === HW_DEFAULT_CLIENT_ID && numCards === 0) { return true; } return false; }, - _isValidStateForSetRadioEnabled: function(radioState) { + _isValidStateForSetRadioEnabled: function(clientId) { + let radioState = gMobileConnectionService.getRadioState(clientId); return radioState == RIL.GECKO_RADIOSTATE_ENABLED || radioState == RIL.GECKO_RADIOSTATE_DISABLED; }, - _isDummyForSetRadioEnabled: function(radioState, data) { + _isDummyForSetRadioEnabled: function(clientId, data) { + let radioState = gMobileConnectionService.getRadioState(clientId); return (radioState == RIL.GECKO_RADIOSTATE_ENABLED && data.enabled) || (radioState == RIL.GECKO_RADIOSTATE_DISABLED && !data.enabled); }, _handleMessage: function(message) { if (DEBUG) debug("RadioControl: handleMessage: " + JSON.stringify(message)); let clientId = message.clientId || 0; - let connection = - gMobileConnectionService.getItemByServiceId(clientId); - let radioState = connection && connection.radioState; - - if (!this._isValidStateForSetRadioEnabled(radioState)) { + let radioInterface = _ril.getRadioInterface(clientId); + + if (!this._isValidStateForSetRadioEnabled(clientId)) { message.data.errorMsg = "InvalidStateError"; message.callback(message.data); this._processNextMessage(); return; } - if (this._isDummyForSetRadioEnabled(radioState, message.data)) { + if (this._isDummyForSetRadioEnabled(clientId, message.data)) { message.callback(message.data); this._processNextMessage(); return; } if (message.data.enabled) { if (this._isRadioAbleToEnableAtClient(clientId)) { this._setRadioEnabledInternal(message); @@ -1397,22 +1397,19 @@ DataConnectionHandler.prototype = { let networkInterface = this.dataNetworkInterfaces.get("default"); if (!networkInterface) { if (DEBUG) { this.debug("No network interface for default data."); } return; } - let connection = - gMobileConnectionService.getItemByServiceId(this.clientId); - // This check avoids data call connection if the radio is not ready // yet after toggling off airplane mode. - let radioState = connection && connection.radioState; + let radioState = gMobileConnectionService.getRadioState(this.clientId); if (radioState != RIL.GECKO_RADIOSTATE_ENABLED) { if (DEBUG) { this.debug("RIL is not ready for data connection: radio's not ready"); } return; } // We only watch at "ril.data.enabled" flag changes for connecting or @@ -1422,22 +1419,20 @@ DataConnectionHandler.prototype = { // the new values and reconnect the data call. if (this.dataCallSettings.oldEnabled === this.dataCallSettings.enabled) { if (DEBUG) { this.debug("No changes for ril.data.enabled flag. Nothing to do."); } return; } - let dataInfo = connection && connection.data; + let dataInfo = gMobileConnectionService.getDataConnectionInfo(this.clientId); let isRegistered = - dataInfo && dataInfo.state == RIL.GECKO_MOBILE_CONNECTION_STATE_REGISTERED; let haveDataConnection = - dataInfo && dataInfo.type != RIL.GECKO_MOBILE_CONNECTION_STATE_UNKNOWN; if (!isRegistered || !haveDataConnection) { if (DEBUG) { this.debug("RIL is not ready for data connection: Phone's not " + "registered or doesn't have data connection."); } return; } @@ -1487,17 +1482,19 @@ DataConnectionHandler.prototype = { } return; } if (this._pendingApnSettings) { if (DEBUG) this.debug("We're changing apn settings, ignore any changes."); return; } - if (gRadioEnabledController.isDeactivatingDataCalls()) { + if (gRadioEnabledController.isDeactivatingDataCalls() || + radioState == RIL.GECKO_RADIOSTATE_ENABLING || + radioState == RIL.GECKO_RADIOSTATE_DISABLING) { // We're changing the radio power currently, ignore any changes. return; } if (DEBUG) { this.debug("Data call settings: connect data call."); } networkInterface.connect(); @@ -3000,18 +2997,18 @@ RadioInterface.prototype = { } // RIL:IccInfoChanged corresponds to a DOM event that gets fired only // when iccInfo has changed. gMessageManager.sendIccMessage("RIL:IccInfoChanged", this.clientId, message.iccid ? message : null); - // In bug 864489, icc related code will be move to gonk IccProvider, we may - // need a better way to notify icc change to MobileConnectionService. + // In bug 864489, icc related code will be move to IccGonkProvider, we may + // need a better way to notify icc change to MobileConnectionGonkProvider. gMobileConnectionService.notifyIccChanged(this.clientId, message.iccid || null); // Update lastKnownSimMcc. if (message.mcc) { try { Services.prefs.setCharPref("ril.lastKnownSimMcc", message.mcc.toString()); @@ -3700,28 +3697,25 @@ RadioInterface.prototype = { Services.obs.notifyObservers(domMessage, kSmsFailedObserverTopic, null); return; } if (!silent) { Services.obs.notifyObservers(domMessage, kSmsSendingObserverTopic, null); } - let connection = - gMobileConnectionService.getItemByServiceId(this.clientId); // If the radio is disabled or the SIM card is not ready, just directly // return with the corresponding error code. let errorCode; - let radioState = connection && connection.radioState; + let radioState = gMobileConnectionService.getRadioState(this.clientId); if (!PhoneNumberUtils.isPlainPhoneNumber(options.number)) { if (DEBUG) this.debug("Error! Address is invalid when sending SMS: " + options.number); errorCode = Ci.nsIMobileMessageCallback.INVALID_ADDRESS_ERROR; - } else if (radioState == null || - radioState == RIL.GECKO_RADIOSTATE_DISABLED) { + } else if (radioState == RIL.GECKO_RADIOSTATE_DISABLED) { if (DEBUG) this.debug("Error! Radio is disabled when sending SMS."); errorCode = Ci.nsIMobileMessageCallback.RADIO_DISABLED_ERROR; } else if (this.rilContext.cardState != "ready") { if (DEBUG) this.debug("Error! SIM card is not ready when sending SMS."); errorCode = Ci.nsIMobileMessageCallback.NO_SIM_CARD_ERROR; } if (errorCode) { if (silent) { @@ -4215,21 +4209,19 @@ DataCall.prototype = { }, setup: function() { if (DEBUG) { this.debug("Going to set up data connection with APN " + this.apnProfile.apn); } - let connection = - gMobileConnectionService.getItemByServiceId(this.clientId); - let dataInfo = connection && connection.data; - if (dataInfo == null || - dataInfo.state != RIL.GECKO_MOBILE_CONNECTION_STATE_REGISTERED || + let radioInterface = this.gRIL.getRadioInterface(this.clientId); + let dataInfo = gMobileConnectionService.getDataConnectionInfo(this.clientId); + if (dataInfo.state != RIL.GECKO_MOBILE_CONNECTION_STATE_REGISTERED || dataInfo.type == RIL.GECKO_MOBILE_CONNECTION_STATE_UNKNOWN) { return; } let radioTechType = dataInfo.type; let radioTechnology = RIL.GECKO_RADIO_TECH.indexOf(radioTechType); let authType = RIL.RIL_DATACALL_AUTH_TO_GECKO.indexOf(this.apnProfile.authtype); // Use the default authType if the value in database is invalid. @@ -4248,18 +4240,16 @@ DataCall.prototype = { if (RIL.RIL_DATACALL_PDP_TYPES.indexOf(pdpType) < 0) { if (DEBUG) { this.debug("Invalid pdpType '" + pdpType + "', using '" + RIL.GECKO_DATACALL_PDP_TYPE_DEFAULT + "'"); } pdpType = RIL.GECKO_DATACALL_PDP_TYPE_DEFAULT; } } - - let radioInterface = this.gRIL.getRadioInterface(this.clientId); radioInterface.sendWorkerMessage("setupDataCall", { radioTech: radioTechnology, apn: this.apnProfile.apn, user: this.apnProfile.user, passwd: this.apnProfile.password, chappap: authType, pdptype: pdpType });
--- a/dom/telephony/Telephony.cpp +++ b/dom/telephony/Telephony.cpp @@ -21,23 +21,16 @@ #include "nsServiceManagerUtils.h" #include "nsThreadUtils.h" #include "CallsList.h" #include "TelephonyCall.h" #include "TelephonyCallGroup.h" #include "TelephonyCallId.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 mozilla::ErrorResult; class Telephony::Listener : public nsITelephonyListener { Telephony* mTelephony; virtual ~Listener() {} @@ -740,24 +733,8 @@ Telephony::EnqueueEnumerationAck(const n return; } nsCOMPtr<nsIRunnable> task = new EnumerationAck(this, aType); if (NS_FAILED(NS_DispatchToCurrentThread(task))) { NS_WARNING("Failed to dispatch to current thread!"); } } - -already_AddRefed<nsITelephonyService> -NS_CreateTelephonyService() -{ - nsCOMPtr<nsITelephonyService> service; - - if (XRE_GetProcessType() == GeckoProcessType_Content) { - 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(); -}
new file mode 100644 --- /dev/null +++ b/dom/telephony/TelephonyFactory.cpp @@ -0,0 +1,30 @@ +/* -*- Mode: C++; 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 "mozilla/dom/telephony/TelephonyFactory.h" +#if defined(MOZ_WIDGET_GONK) && defined(MOZ_B2G_RIL) +#include "nsIGonkTelephonyService.h" +#endif +#include "nsServiceManagerUtils.h" +#include "nsXULAppAPI.h" +#include "ipc/TelephonyIPCService.h" + +USING_TELEPHONY_NAMESPACE + +/* static */ already_AddRefed<nsITelephonyService> +TelephonyFactory::CreateTelephonyService() +{ + nsCOMPtr<nsITelephonyService> service; + + if (XRE_GetProcessType() == GeckoProcessType_Content) { + service = new TelephonyIPCService(); +#if defined(MOZ_WIDGET_GONK) && defined(MOZ_B2G_RIL) + } else { + service = do_CreateInstance(GONK_TELEPHONY_SERVICE_CONTRACTID); +#endif + } + + return service.forget(); +}
new file mode 100644 --- /dev/null +++ b/dom/telephony/TelephonyFactory.h @@ -0,0 +1,24 @@ +/* -*- Mode: C++; 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/. */ + +#ifndef mozilla_dom_telephony_TelephonyFactory_h +#define mozilla_dom_telephony_TelephonyFactory_h + +#include "nsCOMPtr.h" +#include "mozilla/dom/telephony/TelephonyCommon.h" + +class nsITelephonyService; + +BEGIN_TELEPHONY_NAMESPACE + +class TelephonyFactory +{ +public: + static already_AddRefed<nsITelephonyService> CreateTelephonyService(); +}; + +END_TELEPHONY_NAMESPACE + +#endif // mozilla_dom_telephony_TelephonyFactory_h
--- a/dom/telephony/moz.build +++ b/dom/telephony/moz.build @@ -17,27 +17,29 @@ EXPORTS.mozilla.dom += [ 'TelephonyCallGroup.h', 'TelephonyCallId.h', ] EXPORTS.mozilla.dom.telephony += [ 'ipc/TelephonyChild.h', 'ipc/TelephonyParent.h', 'TelephonyCommon.h', + 'TelephonyFactory.h', ] UNIFIED_SOURCES += [ 'CallsList.cpp', 'ipc/TelephonyChild.cpp', 'ipc/TelephonyIPCService.cpp', 'ipc/TelephonyParent.cpp', 'Telephony.cpp', 'TelephonyCall.cpp', 'TelephonyCallGroup.cpp', 'TelephonyCallId.cpp', + 'TelephonyFactory.cpp', ] IPDL_SOURCES += [ 'ipc/PTelephony.ipdl', 'ipc/PTelephonyRequest.ipdl', 'ipc/TelephonyTypes.ipdlh' ]
--- a/dom/telephony/nsITelephonyService.idl +++ b/dom/telephony/nsITelephonyService.idl @@ -260,15 +260,8 @@ interface nsITelephonyService : nsISuppo void conferenceCall(in unsigned long clientId); void separateCall(in unsigned long clientId, in unsigned long callIndex); void holdConference(in unsigned long clientId); void resumeConference(in unsigned long clientId); attribute bool microphoneMuted; attribute bool speakerEnabled; }; - -%{C++ -template<typename T> struct already_AddRefed; - -already_AddRefed<nsITelephonyService> -NS_CreateTelephonyService(); -%}
--- a/dom/webidl/AppNotificationServiceOptions.webidl +++ b/dom/webidl/AppNotificationServiceOptions.webidl @@ -10,9 +10,10 @@ dictionary AppNotificationServiceOptions boolean textClickable = false; DOMString manifestURL = ""; DOMString id = ""; DOMString dbId = ""; DOMString dir = ""; DOMString lang = ""; DOMString tag = ""; DOMString data = ""; + NotificationBehavior mozbehavior = null; };
--- a/dom/webidl/MozIccManager.webidl +++ b/dom/webidl/MozIccManager.webidl @@ -97,16 +97,19 @@ interface MozIccManager : EventTarget const unsigned short STK_RESULT_NETWORK_CRNTLY_UNABLE_TO_PROCESS = 0x21; /** User did not accept the proactive command */ const unsigned short STK_RESULT_USER_NOT_ACCEPT = 0x22; /** User cleared down call before connection or network release */ const unsigned short STK_RESULT_USER_CLEAR_DOWN_CALL = 0x23; + /** Action in contradiction with the current timer state */ + const unsigned short STK_RESULT_ACTION_CONTRADICTION_TIMER_STATE = 0x24; + /** Launch browser generic error code */ const unsigned short STK_RESULT_LAUNCH_BROWSER_ERROR = 0x26; /** * Results '3X' indicate that it is not worth the UICC re-trying with an * identical command, as it will only get the same response. However, the * decision to retry lies with the application. */
--- a/dom/webidl/MozNFC.webidl +++ b/dom/webidl/MozNFC.webidl @@ -8,41 +8,47 @@ interface MozNFCManager { /** * API to check if the given application's manifest * URL is registered with the Chrome Process or not. * * Returns success if given manifestUrl is registered for 'onpeerready', * otherwise error */ + [CheckPermissions="nfc-manager"] DOMRequest checkP2PRegistration(DOMString manifestUrl); /** * Notify that user has accepted to share nfc message on P2P UI */ + [CheckPermissions="nfc-manager"] void notifyUserAcceptedP2P(DOMString manifestUrl); /** * Notify the status of sendFile operation */ + [CheckPermissions="nfc-manager"] void notifySendFileStatus(octet status, DOMString requestId); /** * Power on the NFC hardware and start polling for NFC tags or devices. */ + [CheckPermissions="nfc-manager"] DOMRequest startPoll(); /** * Stop polling for NFC tags or devices. i.e. enter low power mode. */ + [CheckPermissions="nfc-manager"] DOMRequest stopPoll(); /** * Power off the NFC hardware. */ + [CheckPermissions="nfc-manager"] DOMRequest powerOff(); }; [JSImplementation="@mozilla.org/navigatorNfc;1", NavigatorProperty="mozNfc", Func="Navigator::HasNFCSupport", CheckPermissions="nfc-read nfc-write", AvailableIn="CertifiedApps"]
--- a/dom/webidl/Notification.webidl +++ b/dom/webidl/Notification.webidl @@ -57,22 +57,30 @@ interface Notification : EventTarget { dictionary NotificationOptions { NotificationDirection dir = "auto"; DOMString lang = ""; DOMString body = ""; DOMString tag = ""; DOMString icon = ""; any data = null; + NotificationBehavior mozbehavior = null; }; dictionary GetNotificationOptions { DOMString tag; }; +dictionary NotificationBehavior { + boolean noscreen = false; + boolean noclear = false; + DOMString soundFile = ""; + sequence<unsigned long> vibrationPattern; +}; + enum NotificationPermission { "default", "denied", "granted" }; callback NotificationPermissionCallback = void (NotificationPermission permission);
--- a/layout/build/nsLayoutModule.cpp +++ b/layout/build/nsLayoutModule.cpp @@ -120,16 +120,25 @@ using mozilla::dom::bluetooth::Bluetooth #ifdef MOZ_WIDGET_GONK #include "AudioManager.h" using mozilla::dom::gonk::AudioManager; #include "nsVolumeService.h" using mozilla::system::nsVolumeService; #endif +#ifdef MOZ_B2G_RIL +#include "nsIMobileConnectionService.h" +#include "mozilla/dom/mobileconnection/MobileConnectionIPCService.h" +using mozilla::dom::mobileconnection::MobileConnectionIPCService; +#ifdef MOZ_WIDGET_GONK +#include "nsIMobileConnectionGonkService.h" +#endif +#endif + #include "AudioChannelAgent.h" using mozilla::dom::AudioChannelAgent; // Editor stuff #include "nsEditorCID.h" #include "nsEditor.h" #include "nsPlaintextEditor.h" #include "nsEditorController.h" //CID @@ -211,44 +220,48 @@ static void Shutdown(); #include "nsDeviceSensors.h" #ifdef MOZ_GAMEPAD #include "mozilla/dom/GamepadService.h" #endif #include "nsCSPService.h" #include "nsCSPContext.h" #include "nsISmsService.h" #include "nsIMmsService.h" -#include "nsIMobileConnectionService.h" #include "nsIMobileMessageService.h" #include "nsIMobileMessageDatabaseService.h" +#include "mozilla/dom/mobilemessage/MobileMessageService.h" +#include "mozilla/dom/mobilemessage/SmsServicesFactory.h" #include "nsIPowerManagerService.h" #include "nsIAlarmHalService.h" #include "nsIMediaManager.h" #include "nsMixedContentBlocker.h" #include "AudioChannelService.h" #include "mozilla/dom/DataStoreService.h" #include "mozilla/dom/power/PowerManagerService.h" #include "mozilla/dom/alarm/AlarmHalService.h" #include "mozilla/dom/time/TimeService.h" #include "StreamingProtocolService.h" +#include "mozilla/dom/telephony/TelephonyFactory.h" #include "nsITelephonyService.h" #ifdef MOZ_WIDGET_GONK #include "GonkGPSGeolocationProvider.h" #endif #include "MediaManager.h" #include "GMPService.h" using namespace mozilla; using namespace mozilla::dom; +using namespace mozilla::dom::mobilemessage; +using namespace mozilla::dom::telephony; using mozilla::dom::alarm::AlarmHalService; using mozilla::dom::power::PowerManagerService; using mozilla::dom::quota::QuotaManager; using mozilla::dom::workers::ServiceWorkerManager; using mozilla::dom::TCPSocketChild; using mozilla::dom::TCPSocketParent; using mozilla::dom::TCPServerSocketChild; using mozilla::dom::UDPSocketChild; @@ -312,22 +325,24 @@ NS_GENERIC_FACTORY_CONSTRUCTOR(AudioChan NS_GENERIC_FACTORY_CONSTRUCTOR(nsDeviceSensors) #ifndef MOZ_WIDGET_GONK #if defined(ANDROID) NS_GENERIC_FACTORY_CONSTRUCTOR(nsHapticFeedback) #endif #endif NS_GENERIC_FACTORY_CONSTRUCTOR_INIT(ThirdPartyUtil, Init) -NS_GENERIC_FACTORY_SINGLETON_CONSTRUCTOR(nsISmsService, NS_CreateSmsService) -NS_GENERIC_FACTORY_SINGLETON_CONSTRUCTOR(nsIMmsService, NS_CreateMmsService) +NS_GENERIC_FACTORY_SINGLETON_CONSTRUCTOR(nsISmsService, + SmsServicesFactory::CreateSmsService) +NS_GENERIC_FACTORY_SINGLETON_CONSTRUCTOR(nsIMmsService, + SmsServicesFactory::CreateMmsService) NS_GENERIC_FACTORY_SINGLETON_CONSTRUCTOR(nsIMobileMessageService, - NS_CreateMobileMessageService) + MobileMessageService::GetInstance) NS_GENERIC_FACTORY_SINGLETON_CONSTRUCTOR(nsIMobileMessageDatabaseService, - NS_CreateMobileMessageDatabaseService) + SmsServicesFactory::CreateMobileMessageDatabaseService) NS_GENERIC_FACTORY_SINGLETON_CONSTRUCTOR(nsIPowerManagerService, PowerManagerService::GetInstance) NS_GENERIC_FACTORY_SINGLETON_CONSTRUCTOR(nsIAlarmHalService, AlarmHalService::GetInstance) NS_GENERIC_FACTORY_SINGLETON_CONSTRUCTOR(nsITimeService, TimeService::GetInstance) NS_GENERIC_FACTORY_SINGLETON_CONSTRUCTOR(nsIStreamingProtocolControllerService, StreamingProtocolControllerService::GetInstance) @@ -343,20 +358,18 @@ NS_GENERIC_FACTORY_SINGLETON_CONSTRUCTOR GonkGPSGeolocationProvider::GetSingleton) // Since the nsVolumeService constructor calls into nsIPowerManagerService, // we need it to be constructed sometime after nsIPowerManagerService. NS_GENERIC_FACTORY_SINGLETON_CONSTRUCTOR(nsVolumeService, nsVolumeService::GetSingleton) #endif NS_GENERIC_FACTORY_SINGLETON_CONSTRUCTOR(nsIMediaManagerService, MediaManager::GetInstance) -NS_GENERIC_FACTORY_SINGLETON_CONSTRUCTOR(nsIMobileConnectionService, - NS_CreateMobileConnectionService) NS_GENERIC_FACTORY_SINGLETON_CONSTRUCTOR(nsITelephonyService, - NS_CreateTelephonyService) + TelephonyFactory::CreateTelephonyService) //----------------------------------------------------------------------------- static bool gInitialized = false; // Perform our one-time intialization for this module // static @@ -788,17 +801,19 @@ NS_DEFINE_NAMED_CID(NS_SYNTHVOICEREGISTR #ifdef ACCESSIBILITY NS_DEFINE_NAMED_CID(NS_ACCESSIBILITY_SERVICE_CID); #endif NS_DEFINE_NAMED_CID(TELEPHONY_SERVICE_CID); NS_DEFINE_NAMED_CID(GECKO_MEDIA_PLUGIN_SERVICE_CID); +#ifdef MOZ_B2G_RIL NS_DEFINE_NAMED_CID(NS_MOBILE_CONNECTION_SERVICE_CID); +#endif static nsresult CreateWindowCommandTableConstructor(nsISupports *aOuter, REFNSIID aIID, void **aResult) { nsresult rv; nsCOMPtr<nsIControllerCommandTable> commandTable = do_CreateInstance(NS_CONTROLLERCOMMANDTABLE_CONTRACTID, &rv); @@ -918,16 +933,41 @@ nsEditingCommandTableConstructor(nsISupp if (NS_FAILED(rv)) return rv; // we don't know here whether we're being created as an instance, // or a service, so we can't become immutable return commandTable->QueryInterface(aIID, aResult); } +#ifdef MOZ_B2G_RIL + +static nsresult +nsIMobileConnectionServiceConstructor(nsISupports *aOuter, REFNSIID aIID, + void **aResult) +{ + nsCOMPtr<nsIMobileConnectionService> service; + + if (XRE_GetProcessType() == GeckoProcessType_Content) { + service = MobileConnectionIPCService::GetSingleton(); + } else { +#ifdef MOZ_WIDGET_GONK + service = do_CreateInstance(NS_MOBILECONNECTION_GONK_SERVICE_CONTRACTID); +#endif + } + + if (!service) { + return NS_ERROR_NOT_AVAILABLE; + } + + return service->QueryInterface(aIID, aResult); +} + +#endif + static const mozilla::Module::CIDEntry kLayoutCIDs[] = { XPCONNECT_CIDENTRIES #ifdef DEBUG { &kNS_FRAME_UTIL_CID, false, nullptr, CreateNewFrameUtil }, { &kNS_LAYOUT_DEBUGGER_CID, false, nullptr, CreateNewLayoutDebugger }, #endif { &kNS_FRAMETRAVERSAL_CID, false, nullptr, CreateNewFrameTraversal }, { &kNS_BOXOBJECT_CID, false, nullptr, CreateNewBoxObject }, @@ -1073,17 +1113,19 @@ static const mozilla::Module::CIDEntry k { &kNS_MEDIAMANAGERSERVICE_CID, false, nullptr, nsIMediaManagerServiceConstructor }, #ifdef MOZ_GAMEPAD { &kNS_GAMEPAD_TEST_CID, false, nullptr, GamepadServiceTestConstructor }, #endif #ifdef ACCESSIBILITY { &kNS_ACCESSIBILITY_SERVICE_CID, false, nullptr, CreateA11yService }, #endif { &kTELEPHONY_SERVICE_CID, false, nullptr, nsITelephonyServiceConstructor }, - { &kNS_MOBILE_CONNECTION_SERVICE_CID, false, NULL, nsIMobileConnectionServiceConstructor }, +#ifdef MOZ_B2G_RIL + { &kNS_MOBILE_CONNECTION_SERVICE_CID, true, NULL, nsIMobileConnectionServiceConstructor }, +#endif { nullptr } }; static const mozilla::Module::ContractIDEntry kLayoutContracts[] = { XPCONNECT_CONTRACTS { "@mozilla.org/layout/xul-boxobject;1", &kNS_BOXOBJECT_CID }, #ifdef MOZ_XUL { "@mozilla.org/layout/xul-boxobject-listbox;1", &kNS_LISTBOXOBJECT_CID }, @@ -1231,17 +1273,19 @@ static const mozilla::Module::ContractID #endif { MEDIAMANAGERSERVICE_CONTRACTID, &kNS_MEDIAMANAGERSERVICE_CID }, #ifdef ACCESSIBILITY { "@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 }, +#ifdef MOZ_B2G_RIL { NS_MOBILE_CONNECTION_SERVICE_CONTRACTID, &kNS_MOBILE_CONNECTION_SERVICE_CID }, +#endif { nullptr } }; static const mozilla::Module::CategoryEntry kLayoutCategories[] = { XPCONNECT_CATEGORIES { "content-policy", NS_DATADOCUMENTCONTENTPOLICY_CONTRACTID, NS_DATADOCUMENTCONTENTPOLICY_CONTRACTID }, { "content-policy", NS_NODATAPROTOCOLCONTENTPOLICY_CONTRACTID, NS_NODATAPROTOCOLCONTENTPOLICY_CONTRACTID }, { "content-policy", "CSPService", CSPSERVICE_CONTRACTID }, @@ -1254,17 +1298,19 @@ static const mozilla::Module::CategoryEn #endif CONTENTDLF_CATEGORIES #ifdef MOZ_WIDGET_GONK { "profile-after-change", "Gonk System Worker Manager", SYSTEMWORKERMANAGER_CONTRACTID }, #endif #ifdef MOZ_B2G_BT { "profile-after-change", "Bluetooth Service", BLUETOOTHSERVICE_CONTRACTID }, #endif +#ifdef MOZ_B2G_RIL { "profile-after-change", "MobileConnection Service", NS_MOBILE_CONNECTION_SERVICE_CONTRACTID }, +#endif { nullptr } }; static void LayoutModuleDtor() { Shutdown(); nsContentUtils::XPCOMShutdown();
--- a/layout/generic/nsGfxScrollFrame.cpp +++ b/layout/generic/nsGfxScrollFrame.cpp @@ -2722,42 +2722,16 @@ ClipListsExceptCaret(nsDisplayListCollec ::ClipItemsExceptCaret(aLists->BorderBackground(), aBuilder, aClipFrame, aClip); ::ClipItemsExceptCaret(aLists->BlockBorderBackgrounds(), aBuilder, aClipFrame, aClip); ::ClipItemsExceptCaret(aLists->Floats(), aBuilder, aClipFrame, aClip); ::ClipItemsExceptCaret(aLists->PositionedDescendants(), aBuilder, aClipFrame, aClip); ::ClipItemsExceptCaret(aLists->Outlines(), aBuilder, aClipFrame, aClip); ::ClipItemsExceptCaret(aLists->Content(), aBuilder, aClipFrame, aClip); } -static bool -DisplayportExceedsMaxTextureSize(nsPresContext* aPresContext, const nsRect& aDisplayPort, bool aLowPrecision) -{ -#ifdef MOZ_WIDGET_GONK - // On B2G we actively run into max texture size limits because the displayport-sizing code - // in the AsyncPanZoomController code is slightly busted (bug 957668 will fix it properly). - // We sometimes end up requesting displayports for which the corresponding layer will be - // larger than the max GL texture size (which we assume to be 4096 here). - // If we run into this case, we should just not use the displayport at all and fall back to - // just making a ScrollInfoLayer so that we use the APZC's synchronous scrolling fallback - // mechanism. - // Note also that if we don't do this here, it is quite likely that the parent B2G process - // will kill this child process to prevent OOMs (see the patch that landed as part of bug - // 965945 for details). - gfxSize resolution = aPresContext->PresShell()->GetCumulativeResolution(); - if (aLowPrecision) { - resolution.width *= gfxPrefs::LowPrecisionResolution(); - resolution.height *= gfxPrefs::LowPrecisionResolution(); - } - return (aPresContext->AppUnitsToDevPixels(aDisplayPort.width) * resolution.width > 4096) || - (aPresContext->AppUnitsToDevPixels(aDisplayPort.height) * resolution.height > 4096); -#else - return false; -#endif -} - void ScrollFrameHelper::BuildDisplayList(nsDisplayListBuilder* aBuilder, const nsRect& aDirtyRect, const nsDisplayListSet& aLists) { if (aBuilder->IsForImageVisibility()) { mLastUpdateImagesPos = GetScrollPosition(); } @@ -2847,26 +2821,20 @@ ScrollFrameHelper::BuildDisplayList(nsDi *aBuilder, mOuter, displayportBase, &displayPort); } else { // For a root frmae, just get the value of the existing of the display // port, if any. usingDisplayport = nsLayoutUtils::GetDisplayPort(mOuter->GetContent(), &displayPort); } bool usingLowPrecision = gfxPrefs::UseLowPrecisionBuffer(); - if (usingDisplayport && DisplayportExceedsMaxTextureSize(mOuter->PresContext(), displayPort, usingLowPrecision)) { - usingDisplayport = false; - } if (usingDisplayport && usingLowPrecision) { // If we have low-res painting enabled we should check the critical displayport too nsRect critDp; - bool usingCritDp = nsLayoutUtils::GetCriticalDisplayPort(mOuter->GetContent(), &critDp); - if (usingCritDp && !critDp.IsEmpty() && DisplayportExceedsMaxTextureSize(mOuter->PresContext(), critDp, false)) { - usingDisplayport = false; - } + nsLayoutUtils::GetCriticalDisplayPort(mOuter->GetContent(), &critDp); } // Override the dirty rectangle if the displayport has been set. if (usingDisplayport) { dirtyRect = displayPort; } }
--- a/mobile/android/base/AndroidManifest.xml.in +++ b/mobile/android/base/AndroidManifest.xml.in @@ -144,16 +144,21 @@ <meta-data android:name="com.sec.minimode.icon.landscape.normal" android:resource="@drawable/icon" /> <intent-filter> <action android:name="org.mozilla.gecko.ACTION_ALERT_CALLBACK" /> </intent-filter> + <intent-filter> + <action android:name="org.mozilla.gecko.GUEST_SESSION_INPROGRESS" /> + <category android:name="android.intent.category.DEFAULT" /> + </intent-filter> + <!-- Notification API V2 --> <intent-filter> <action android:name="@ANDROID_PACKAGE_NAME@.helperBroadcastAction" /> <data android:scheme="moz-notification" /> <category android:name="android.intent.category.DEFAULT" /> </intent-filter> <intent-filter>
--- a/mobile/android/base/BrowserApp.java +++ b/mobile/android/base/BrowserApp.java @@ -180,17 +180,17 @@ public class BrowserApp extends GeckoApp public boolean checked; public boolean enabled = true; public boolean visible = true; public int parent; public boolean added; // So we can re-add after a locale change. } // The types of guest mdoe dialogs we show - private static enum GuestModeDialog { + public static enum GuestModeDialog { ENTERING, LEAVING } private Vector<MenuItemInfo> mAddonMenuItemsCache; private PropertyAnimator mMainLayoutAnimator; private static final Interpolator sTabsInterpolator = new Interpolator() { @@ -531,21 +531,25 @@ public class BrowserApp extends GeckoApp mBrowserChrome = (ViewGroup) findViewById(R.id.browser_chrome); mActionBarFlipper = (ViewFlipper) findViewById(R.id.browser_actionbar); mActionBar = (ActionModeCompatView) findViewById(R.id.actionbar); mBrowserToolbar = (BrowserToolbar) findViewById(R.id.browser_toolbar); mProgressView = (ToolbarProgressView) findViewById(R.id.progress); mBrowserToolbar.setProgressBar(mProgressView); - if (Intent.ACTION_VIEW.equals(intent.getAction())) { + + final String action = intent.getAction(); + if (Intent.ACTION_VIEW.equals(action)) { // Show the target URL immediately in the toolbar. mBrowserToolbar.setTitle(intent.getDataString()); Telemetry.sendUIEvent(TelemetryContract.Event.LOAD_URL, TelemetryContract.Method.INTENT); + } else if (GuestSession.NOTIFICATION_INTENT.equals(action)) { + GuestSession.handleIntent(this, intent); } if (NewTabletUI.isEnabled(this)) { findViewById(R.id.new_tablet_tab_strip).setVisibility(View.VISIBLE); } ((GeckoApp.MainLayout) mMainLayout).setTouchEventInterceptor(new HideOnTouchListener()); ((GeckoApp.MainLayout) mMainLayout).setMotionEventInterceptor(new MotionEventInterceptor() { @@ -655,16 +659,23 @@ public class BrowserApp extends GeckoApp if (mediaManagerClass != null) { try { Method init = mediaManagerClass.getMethod("init", Context.class); init.invoke(null, this); } catch(Exception ex) { Log.e(LOGTAG, "Error initializing media manager", ex); } } + + if (getProfile().inGuestMode()) { + GuestSession.showNotification(this); + } else { + // If we're restarting, we won't destroy the activity. Make sure we remove any guest notifications that might have been shown. + GuestSession.hideNotification(this); + } } private void registerOnboardingReceiver(Context context) { final LocalBroadcastManager lbm = LocalBroadcastManager.getInstance(this); // Receiver for launching first run start pane on new profile creation. mOnboardingReceiver = new BroadcastReceiver() { @Override @@ -1028,16 +1039,18 @@ public class BrowserApp extends GeckoApp mOrderedBroadcastHelper = null; } if (mBrowserHealthReporter != null) { mBrowserHealthReporter.uninit(); mBrowserHealthReporter = null; } + GuestSession.onDestroy(this); + EventDispatcher.getInstance().unregisterGeckoThreadListener((GeckoEventListener)this, "Menu:Update", "Reader:Added", "Reader:FaviconRequest", "Search:Keyword", "Prompt:ShowTop", "Accounts:Exist"); @@ -1808,21 +1821,21 @@ public class BrowserApp extends GeckoApp * tabs loaded by the time the user enters editing mode e.g. just after * the app starts. In this case, we simply fallback to an empty URL. */ private void enterEditingMode() { String url = ""; final Tab tab = Tabs.getInstance().getSelectedTab(); if (tab != null) { - final String userSearch = tab.getUserSearch(); + final String userRequested = tab.getUserRequested(); // Check to see if there's a user-entered search term, // which we save whenever the user performs a search. - url = (TextUtils.isEmpty(userSearch) ? tab.getURL() : userSearch); + url = (TextUtils.isEmpty(userRequested) ? tab.getURL() : userRequested); } enterEditingMode(url); } /** * Enters editing mode with the specified URL. This method will * always open the HISTORY page on about:home. @@ -2826,17 +2839,17 @@ public class BrowserApp extends GeckoApp // a chance. if (onContextItemSelected(item)) { return true; } return super.onOptionsItemSelected(item); } - private void showGuestModeDialog(final GuestModeDialog type) { + public void showGuestModeDialog(final GuestModeDialog type) { final Prompt ps = new Prompt(this, new Prompt.PromptCallback() { @Override public void onPromptFinished(String result) { try { int itemId = new JSONObject(result).getInt("button"); if (itemId == 0) { String args = ""; if (type == GuestModeDialog.ENTERING) { @@ -2918,16 +2931,18 @@ public class BrowserApp extends GeckoApp if (!mInitialized) { return; } // Only solicit feedback when the app has been launched from the icon shortcut. if (!Intent.ACTION_MAIN.equals(action)) { return; + } else if (GuestSession.NOTIFICATION_INTENT.equals(action)) { + GuestSession.handleIntent(this, intent); } // Check to see how many times the app has been launched. final String keyName = getPackageName() + ".feedback_launch_count"; final StrictMode.ThreadPolicy savedPolicy = StrictMode.allowThreadDiskReads(); // Faster on main thread with an async apply(). try {
--- a/mobile/android/base/GeckoApp.java +++ b/mobile/android/base/GeckoApp.java @@ -1428,22 +1428,16 @@ public abstract class GeckoApp } else { startupAction = StartupAction.NORMAL; } // Start migrating as early as possible, can do this in // parallel with Gecko load. checkMigrateProfile(); - Uri data = intent.getData(); - if (data != null && "http".equals(data.getScheme())) { - startupAction = StartupAction.PREFETCH; - ThreadUtils.postToBackgroundThread(new PrefetchRunnable(data.toString())); - } - Tabs.registerOnTabsChangedListener(this); initializeChrome(); // If we are doing a restore, read the session data and send it to Gecko if (!mIsRestoringActivity) { String restoreMessage = null; if (mShouldRestore) { @@ -1772,53 +1766,16 @@ public abstract class GeckoApp } } public String getDefaultUAString() { return HardwareUtils.isTablet() ? AppConstants.USER_AGENT_FENNEC_TABLET : AppConstants.USER_AGENT_FENNEC_MOBILE; } - public String getUAStringForHost(String host) { - // With our standard UA String, we get a 200 response code and - // client-side redirect from t.co. This bot-like UA gives us a - // 301 response code - if ("t.co".equals(host)) { - return AppConstants.USER_AGENT_BOT_LIKE; - } - return getDefaultUAString(); - } - - class PrefetchRunnable implements Runnable { - private String mPrefetchUrl; - - PrefetchRunnable(String prefetchUrl) { - mPrefetchUrl = prefetchUrl; - } - - @Override - public void run() { - HttpURLConnection connection = null; - try { - URL url = new URL(mPrefetchUrl); - // data url should have an http scheme - connection = (HttpURLConnection) url.openConnection(); - connection.setRequestProperty("User-Agent", getUAStringForHost(url.getHost())); - connection.setInstanceFollowRedirects(false); - connection.setRequestMethod("GET"); - connection.connect(); - } catch (Exception e) { - Log.e(LOGTAG, "Exception prefetching URL", e); - } finally { - if (connection != null) - connection.disconnect(); - } - } - } - private void processAlertCallback(Intent intent) { String alertName = ""; String alertCookie = ""; Uri data = intent.getData(); if (data != null) { alertName = data.getQueryParameter("name"); if (alertName == null) alertName = "";
--- a/mobile/android/base/GeckoProfile.java +++ b/mobile/android/base/GeckoProfile.java @@ -326,17 +326,17 @@ public final class GeckoProfile { return mLocked == LockState.LOCKED; } public boolean lock() { try { // If this dir doesn't exist getDir will create it for us final File lockFile = new File(getDir(), LOCK_FILE_NAME); final boolean result = lockFile.createNewFile(); - if (result) { + if (lockFile.exists()) { mLocked = LockState.LOCKED; } else { mLocked = LockState.UNLOCKED; } return result; } catch(IOException ex) { Log.e(LOGTAG, "Error locking profile", ex); }
new file mode 100644 --- /dev/null +++ b/mobile/android/base/GuestSession.java @@ -0,0 +1,50 @@ +package org.mozilla.gecko; + +import android.app.NotificationManager; +import android.app.PendingIntent; +import android.content.Intent; +import android.content.Context; +import android.content.Intent; +import android.content.res.Resources; +import android.net.Uri; +import android.support.v4.app.NotificationCompat; +import android.util.Log; + +// Utility methods for entering/exiting guest mode. +public class GuestSession { + public static final String NOTIFICATION_INTENT = "org.mozilla.gecko.GUEST_SESSION_INPROGRESS"; + + private static PendingIntent getNotificationIntent(Context context) { + Intent intent = new Intent(NOTIFICATION_INTENT); + return PendingIntent.getActivity(context, 0, intent, PendingIntent.FLAG_UPDATE_CURRENT); + } + + public static void showNotification(Context context) { + final NotificationCompat.Builder builder = new NotificationCompat.Builder(context); + final Resources res = context.getResources(); + builder.setContentTitle(res.getString(R.string.guest_browsing_notification_title)) + .setContentText(res.getString(R.string.guest_browsing_notification_text)) + .setSmallIcon(R.drawable.alert_guest) + .setOngoing(true) + .setContentIntent(getNotificationIntent(context)); + + final NotificationManager manager = (NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE); + manager.notify(R.id.guestNotification, builder.build()); + } + + public static void hideNotification(Context context) { + final NotificationManager manager = (NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE); + manager.cancel(R.id.guestNotification); + } + + public static void onDestroy(Context context) { + if (GeckoProfile.get(context).inGuestMode()) { + hideNotification(context); + } + } + + public static void handleIntent(BrowserApp context, Intent intent) { + context.showGuestModeDialog(BrowserApp.GuestModeDialog.LEAVING); + } + +}
new file mode 100644 --- /dev/null +++ b/mobile/android/base/RemoteClientsDialogFragment.java @@ -0,0 +1,125 @@ +/* -*- Mode: Java; c-basic-offset: 4; tab-width: 20; indent-tabs-mode: nil; -*- + * 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/. */ + +package org.mozilla.gecko; + +import java.util.ArrayList; +import java.util.List; + +import org.mozilla.gecko.TabsAccessor.RemoteClient; + +import android.app.AlertDialog; +import android.app.AlertDialog.Builder; +import android.app.Dialog; +import android.content.DialogInterface; +import android.os.Bundle; +import android.support.v4.app.DialogFragment; +import android.support.v4.app.Fragment; +import android.util.SparseBooleanArray; + +/** + * A dialog fragment that displays a list of remote clients. + * <p> + * The dialog allows both single (one tap) and multiple (checkbox) selection. + * The dialog's results are communicated via the {@link RemoteClientsListener} + * interface. Either the dialog fragment's <i>target fragment</i> (see + * {@link Fragment#setTargetFragment(Fragment, int)}), or the containing + * <i>activity</i>, must implement that interface. See + * {@link #notifyListener(List)} for details. + */ +public class RemoteClientsDialogFragment extends DialogFragment { + private static final String KEY_TITLE = "title"; + private static final String KEY_CHOICE_MODE = "choice_mode"; + private static final String KEY_POSITIVE_BUTTON_TEXT = "positive_button_text"; + private static final String KEY_CLIENTS = "clients"; + + public interface RemoteClientsListener { + // Always called on the main UI thread. + public void onClients(List<RemoteClient> clients); + } + + public enum ChoiceMode { + SINGLE, + MULTIPLE, + } + + public static RemoteClientsDialogFragment newInstance(String title, String positiveButtonText, ChoiceMode choiceMode, ArrayList<RemoteClient> clients) { + final RemoteClientsDialogFragment dialog = new RemoteClientsDialogFragment(); + final Bundle args = new Bundle(); + args.putString(KEY_TITLE, title); + args.putString(KEY_POSITIVE_BUTTON_TEXT, positiveButtonText); + args.putInt(KEY_CHOICE_MODE, choiceMode.ordinal()); + args.putParcelableArrayList(KEY_CLIENTS, clients); + dialog.setArguments(args); + return dialog; + } + + public RemoteClientsDialogFragment() { + // Empty constructor is required for DialogFragment. + } + + protected void notifyListener(List<RemoteClient> clients) { + RemoteClientsListener listener; + try { + listener = (RemoteClientsListener) getTargetFragment(); + } catch (ClassCastException e) { + try { + listener = (RemoteClientsListener) getActivity(); + } catch (ClassCastException f) { + throw new ClassCastException(getTargetFragment() + " or " + getActivity() + + " must implement RemoteClientsListener"); + } + } + listener.onClients(clients); + } + + @Override + public Dialog onCreateDialog(Bundle savedInstanceState) { + final String title = getArguments().getString(KEY_TITLE); + final String positiveButtonText = getArguments().getString(KEY_POSITIVE_BUTTON_TEXT); + final ChoiceMode choiceMode = ChoiceMode.values()[getArguments().getInt(KEY_CHOICE_MODE)]; + final ArrayList<RemoteClient> clients = getArguments().getParcelableArrayList(KEY_CLIENTS); + + final Builder builder = new AlertDialog.Builder(getActivity()); + builder.setTitle(title); + + final String[] clientNames = new String[clients.size()]; + for (int i = 0; i < clients.size(); i++) { + clientNames[i] = clients.get(i).name; + } + + if (choiceMode == ChoiceMode.MULTIPLE) { + builder.setMultiChoiceItems(clientNames, null, null); + builder.setPositiveButton(positiveButtonText, new DialogInterface.OnClickListener() { + @Override + public void onClick(DialogInterface dialogInterface, int which) { + if (which != Dialog.BUTTON_POSITIVE) { + return; + } + + final AlertDialog dialog = (AlertDialog) dialogInterface; + final SparseBooleanArray checkedItemPositions = dialog.getListView().getCheckedItemPositions(); + final ArrayList<RemoteClient> checked = new ArrayList<RemoteClient>(); + for (int i = 0; i < checkedItemPositions.size(); i++) { + if (checkedItemPositions.get(i)) { + checked.add(clients.get(i)); + } + } + notifyListener(checked); + } + }); + } else { + builder.setItems(clientNames, new DialogInterface.OnClickListener() { + public void onClick(DialogInterface dialog, int index) { + final ArrayList<RemoteClient> checked = new ArrayList<RemoteClient>(); + checked.add(clients.get(index)); + notifyListener(checked); + } + }); + } + + return builder.create(); + } +}
--- a/mobile/android/base/RemoteTabsExpandableListAdapter.java +++ b/mobile/android/base/RemoteTabsExpandableListAdapter.java @@ -103,28 +103,39 @@ public class RemoteTabsExpandableListAda final TextView nameView = (TextView) view.findViewById(R.id.client); nameView.setText(client.name); final TextView lastModifiedView = (TextView) view.findViewById(R.id.last_synced); final long now = System.currentTimeMillis(); lastModifiedView.setText(TabsAccessor.getLastSyncedString(context, now, client.lastModified)); - // This view exists only in some of our group views: it's present + // These views exists only in some of our group views: they are present // for the home panel groups and not for the tabs tray groups. // Therefore, we must handle null. final ImageView deviceTypeView = (ImageView) view.findViewById(R.id.device_type); if (deviceTypeView != null) { if ("desktop".equals(client.deviceType)) { deviceTypeView.setBackgroundResource(R.drawable.sync_desktop); } else { deviceTypeView.setBackgroundResource(R.drawable.sync_mobile); } } + final ImageView deviceExpandedView = (ImageView) view.findViewById(R.id.device_expanded); + if (deviceExpandedView != null) { + // If there are no tabs to display, don't show an indicator at all. + if (client.tabs.isEmpty()) { + deviceExpandedView.setBackgroundResource(0); + } else { + final int resourceId = isExpanded ? R.drawable.home_group_expanded : R.drawable.home_group_collapsed; + deviceExpandedView.setBackgroundResource(resourceId); + } + } + return view; } @Override public boolean isChildSelectable(int groupPosition, int childPosition) { return true; }
--- a/mobile/android/base/Tab.java +++ b/mobile/android/base/Tab.java @@ -33,17 +33,17 @@ import android.view.View; public class Tab { private static final String LOGTAG = "GeckoTab"; private static Pattern sColorPattern; private final int mId; private long mLastUsed; private String mUrl; private String mBaseDomain; - private String mUserSearch; + private String mUserRequested; // The original url requested. May be typed by the user or sent by an extneral app for example. private String mTitle; private Bitmap mFavicon; private String mFaviconUrl; private int mFaviconSize; private boolean mHasFeeds; private boolean mHasOpenSearch; private SiteIdentity mSiteIdentity; private boolean mReaderEnabled; @@ -92,17 +92,17 @@ public class Tab { NONE // Non error pages } public Tab(Context context, int id, String url, boolean external, int parentId, String title) { mAppContext = context.getApplicationContext(); mId = id; mUrl = url; mBaseDomain = ""; - mUserSearch = ""; + mUserRequested = ""; mExternal = external; mParentId = parentId; mTitle = title == null ? "" : title; mSiteIdentity = new SiteIdentity(); mHistoryIndex = -1; mContentType = ""; mZoomConstraints = new ZoomConstraints(false); mPluginViews = new ArrayList<View>(); @@ -142,19 +142,19 @@ public class Tab { return mParentId; } // may be null if user-entered query hasn't yet been resolved to a URI public synchronized String getURL() { return mUrl; } - // mUserSearch should never be null, but it may be an empty string - public synchronized String getUserSearch() { - return mUserSearch; + // mUserRequested should never be null, but it may be an empty string + public synchronized String getUserRequested() { + return mUserRequested; } // mTitle should never be null, but it may be an empty string public synchronized String getTitle() { return mTitle; } public String getDisplayTitle() { @@ -263,18 +263,18 @@ public class Tab { } public synchronized void updateURL(String url) { if (url != null && url.length() > 0) { mUrl = url; } } - private synchronized void updateUserSearch(String userSearch) { - mUserSearch = userSearch; + public synchronized void updateUserRequested(String userRequested) { + mUserRequested = userRequested; } public void setErrorType(String type) { if ("blocked".equals(type)) setErrorType(ErrorType.BLOCKED); else if ("certerror".equals(type)) setErrorType(ErrorType.CERT_ERROR); else if ("neterror".equals(type)) @@ -649,17 +649,17 @@ public class Tab { if (sameDocument) { // We can get a location change event for the same document with an anchor tag // Notify listeners so that buttons like back or forward will update themselves Tabs.getInstance().notifyListeners(this, Tabs.TabEvents.LOCATION_CHANGE, oldUrl); return; } setContentType(message.getString("contentType")); - updateUserSearch(message.getString("userSearch")); + updateUserRequested(message.getString("userRequested")); mBaseDomain = message.optString("baseDomain"); setHasFeeds(false); setHasOpenSearch(false); updateIdentityData(null); setReaderEnabled(false); setZoomConstraints(new ZoomConstraints(true)); setHasTouchListeners(false);
--- a/mobile/android/base/Tabs.java +++ b/mobile/android/base/Tabs.java @@ -483,16 +483,17 @@ public class Tabs implements GeckoEventL notifyListeners(tab, Tabs.TabEvents.STOP); } } } else if (event.equals("Content:LoadError")) { tab.handleContentLoaded(); notifyListeners(tab, Tabs.TabEvents.LOAD_ERROR); } else if (event.equals("Content:PageShow")) { notifyListeners(tab, TabEvents.PAGE_SHOW); + tab.updateUserRequested(message.getString("userRequested")); } else if (event.equals("DOMContentLoaded")) { tab.handleContentLoaded(); String backgroundColor = message.getString("bgColor"); if (backgroundColor != null) { tab.setBackgroundColor(backgroundColor); } else { // Default to white if no color is given tab.setBackgroundColor(Color.WHITE);
--- a/mobile/android/base/TabsAccessor.java +++ b/mobile/android/base/TabsAccessor.java @@ -15,16 +15,18 @@ import org.mozilla.gecko.db.BrowserContr import org.mozilla.gecko.util.ThreadUtils; import org.mozilla.gecko.util.UIAsyncTask; import android.content.ContentResolver; import android.content.ContentValues; import android.content.Context; import android.database.Cursor; import android.net.Uri; +import android.os.Parcel; +import android.os.Parcelable; import android.text.TextUtils; import android.text.format.DateUtils; import android.util.Log; public final class TabsAccessor { private static final String LOGTAG = "GeckoTabsAccessor"; public static final String[] TABS_PROJECTION_COLUMNS = new String[] { @@ -53,49 +55,109 @@ public final class TabsAccessor { private static final Pattern FILTERED_URL_PATTERN = Pattern.compile("^(about|chrome|wyciwyg|file):"); /** * A thin representation of a remote client. * <p> * We use the hash of the client's GUID as the ID in * {@link RemoteTabsExpandableListAdapter#getGroupId(int)}. */ - public static class RemoteClient { + public static class RemoteClient implements Parcelable { public final String guid; public final String name; public final long lastModified; public final String deviceType; public final ArrayList<RemoteTab> tabs; public RemoteClient(String guid, String name, long lastModified, String deviceType) { this.guid = guid; this.name = name; this.lastModified = lastModified; this.deviceType = deviceType; this.tabs = new ArrayList<RemoteTab>(); } + + @Override + public int describeContents() { + return 0; + } + + @Override + public void writeToParcel(Parcel parcel, int flags) { + parcel.writeString(guid); + parcel.writeString(name); + parcel.writeLong(lastModified); + parcel.writeString(deviceType); + parcel.writeTypedList(tabs); + } + + public static final Creator<RemoteClient> CREATOR = new Creator<RemoteClient>() { + @Override + public RemoteClient createFromParcel(final Parcel source) { + final String guid = source.readString(); + final String name = source.readString(); + final long lastModified = source.readLong(); + final String deviceType = source.readString(); + + final RemoteClient client = new RemoteClient(guid, name, lastModified, deviceType); + source.readTypedList(client.tabs, RemoteTab.CREATOR); + + return client; + } + + @Override + public RemoteClient[] newArray(final int size) { + return new RemoteClient[size]; + } + }; } /** * A thin representation of a remote tab. * <p> * We use the hash of the tab as the ID in * {@link RemoteTabsExpandableListAdapter#getClientId(int)}, and therefore we * must implement equality as well. These are generated functions. */ - public static class RemoteTab { + public static class RemoteTab implements Parcelable { public final String title; public final String url; public RemoteTab(String title, String url) { this.title = title; this.url = url; } @Override + public int describeContents() { + return 0; + } + + @Override + public void writeToParcel(Parcel parcel, int flags) { + parcel.writeString(title); + parcel.writeString(url); + } + + public static final Creator<RemoteTab> CREATOR = new Creator<RemoteTab>() { + @Override + public RemoteTab createFromParcel(final Parcel source) { + final String title = source.readString(); + final String url = source.readString(); + + return new RemoteTab(title, url); + } + + @Override + public RemoteTab[] newArray(final int size) { + return new RemoteTab[size]; + } + }; + + @Override public int hashCode() { final int prime = 31; int result = 1; result = prime * result + ((title == null) ? 0 : title.hashCode()); result = prime * result + ((url == null) ? 0 : url.hashCode()); return result; }
--- a/mobile/android/base/favicons/cache/FaviconCache.java +++ b/mobile/android/base/favicons/cache/FaviconCache.java @@ -95,18 +95,18 @@ public class FaviconCache { private static final String LOGTAG = "FaviconCache"; // The number of spaces to allocate for favicons in each node. private static final int NUM_FAVICON_SIZES = 4; // Dimensions of the largest favicon to store in the cache. Everything is downscaled to this. public final int maxCachedWidth; - // Retry failed favicons after 20 minutes. - public static final long FAILURE_RETRY_MILLISECONDS = 1000 * 60 * 20; + // Retry failed favicons after four hours. + public static final long FAILURE_RETRY_MILLISECONDS = 1000 * 60 * 60 * 4; // Map relating Favicon URLs with objects representing decoded favicons. // Since favicons may be container formats holding multiple icons, the underlying type holds a // sorted list of bitmap payloads in ascending order of size. The underlying type may be queried // for the least larger payload currently present. private final HashMap<String, FaviconsForURL> backingMap = new HashMap<String, FaviconsForURL>(); // And the same, but never evicted.
--- a/mobile/android/base/home/RemoteTabsExpandableListFragment.java +++ b/mobile/android/base/home/RemoteTabsExpandableListFragment.java @@ -1,19 +1,25 @@ /* -*- Mode: Java; c-basic-offset: 4; tab-width: 20; indent-tabs-mode: nil; -*- * 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/. */ package org.mozilla.gecko.home; +import java.util.ArrayList; import java.util.EnumSet; +import java.util.Iterator; import java.util.List; +import org.mozilla.gecko.GeckoSharedPrefs; import org.mozilla.gecko.R; +import org.mozilla.gecko.RemoteClientsDialogFragment; +import org.mozilla.gecko.RemoteClientsDialogFragment.ChoiceMode; +import org.mozilla.gecko.RemoteClientsDialogFragment.RemoteClientsListener; import org.mozilla.gecko.RemoteTabsExpandableListAdapter; import org.mozilla.gecko.TabsAccessor; import org.mozilla.gecko.TabsAccessor.RemoteClient; import org.mozilla.gecko.TabsAccessor.RemoteTab; import org.mozilla.gecko.Telemetry; import org.mozilla.gecko.TelemetryContract; import org.mozilla.gecko.fxa.FirefoxAccounts; import org.mozilla.gecko.home.HomePager.OnUrlOpenListener; @@ -22,50 +28,69 @@ import org.mozilla.gecko.widget.GeckoSwi import android.accounts.Account; import android.content.Context; import android.database.Cursor; import android.os.Bundle; import android.support.v4.app.LoaderManager.LoaderCallbacks; import android.support.v4.content.Loader; import android.util.Log; +import android.view.ContextMenu; +import android.view.ContextMenu.ContextMenuInfo; import android.view.LayoutInflater; +import android.view.MenuInflater; +import android.view.MenuItem; import android.view.View; +import android.view.View.OnClickListener; import android.view.ViewGroup; import android.view.ViewStub; import android.widget.ExpandableListAdapter; import android.widget.ExpandableListView; import android.widget.ExpandableListView.OnChildClickListener; import android.widget.ExpandableListView.OnGroupClickListener; import android.widget.ImageView; import android.widget.TextView; /** * Fragment that displays tabs from other devices in an <code>ExpandableListView<code>. * <p> * This is intended to be used on phones, and possibly in portrait mode on tablets. */ -public class RemoteTabsExpandableListFragment extends HomeFragment { +public class RemoteTabsExpandableListFragment extends HomeFragment implements RemoteClientsListener { // Logging tag name. private static final String LOGTAG = "GeckoRemoteTabsExpList"; // Cursor loader ID. private static final int LOADER_ID_REMOTE_TABS = 0; + // Dialog fragment TAG. + private static final String DIALOG_TAG_REMOTE_TABS = "dialog_tag_remote_tabs"; + private static final String[] STAGES_TO_SYNC_ON_REFRESH = new String[] { "clients", "tabs" }; + // Maintain group collapsed and hidden state. + // Only accessed from the UI thread. + private static RemoteTabsExpandableListState sState; + // Adapter for the list of remote tabs. private RemoteTabsExpandableListAdapter mAdapter; + // List of hidden remote clients. + // Only accessed from the UI thread. + private final ArrayList<RemoteClient> mHiddenClients = new ArrayList<RemoteClient>(); + // The view shown by the fragment. private HomeExpandableListView mList; // Reference to the View to display when there are no results. private View mEmptyView; + // The footer view to display when there are hidden devices not shown. + private View mFooterView; + // Callbacks used for the loader. private CursorLoaderCallbacks mCursorLoaderCallbacks; // Child refresh layout view. private GeckoSwipeRefreshLayout mRefreshLayout; // Sync listener that stops refreshing when a sync is completed. private RemoteTabsSyncListener mSyncStatusListener; @@ -112,42 +137,48 @@ public class RemoteTabsExpandableListFra mUrlOpenListener.onUrlOpen(tab.url, EnumSet.of(OnUrlOpenListener.Flags.ALLOW_SWITCH_TO_TAB)); return true; } }); mList.setOnGroupClickListener(new OnGroupClickListener() { @Override public boolean onGroupClick(ExpandableListView parent, View v, int groupPosition, long id) { - // Since we don't indicate the expansion state yet, don't allow - // collapsing groups at all. - return true; + final ExpandableListAdapter adapter = parent.getExpandableListAdapter(); + final RemoteClient client = (RemoteClient) adapter.getGroup(groupPosition); + if (client != null) { + // After we process this click, the group's expanded state will have flipped. + sState.setClientCollapsed(client.guid, mList.isGroupExpanded(groupPosition)); + } + + // We want the system to handle the click, expanding or collapsing as necessary. + return false; } }); // Show a context menu only for tabs (not for clients). mList.setContextMenuInfoFactory(new HomeContextMenuInfo.ExpandableFactory() { @Override public HomeContextMenuInfo makeInfoForAdapter(View view, int position, long id, ExpandableListAdapter adapter) { long packedPosition = mList.getExpandableListPosition(position); - if (ExpandableListView.getPackedPositionType(packedPosition) != ExpandableListView.PACKED_POSITION_TYPE_CHILD) { - return null; - } final int groupPosition = ExpandableListView.getPackedPositionGroup(packedPosition); - final int childPosition = ExpandableListView.getPackedPositionChild(packedPosition); - final Object child = adapter.getChild(groupPosition, childPosition); - if (child instanceof RemoteTab) { - final RemoteTab tab = (RemoteTab) child; + final int type = ExpandableListView.getPackedPositionType(packedPosition); + if (type == ExpandableListView.PACKED_POSITION_TYPE_CHILD) { + final int childPosition = ExpandableListView.getPackedPositionChild(packedPosition); + final RemoteTab tab = (RemoteTab) adapter.getChild(groupPosition, childPosition); final HomeContextMenuInfo info = new HomeContextMenuInfo(view, position, id); info.url = tab.url; info.title = tab.title; return info; - } else { - return null; + } else if (type == ExpandableListView.PACKED_POSITION_TYPE_GROUP) { + final RemoteClient client = (RemoteClient) adapter.getGroup(groupPosition); + final RemoteTabsClientContextMenuInfo info = new RemoteTabsClientContextMenuInfo(view, position, id, client); + return info; } + return null; } }); registerForContextMenu(mList); } @Override public void onDestroyView() { @@ -160,49 +191,190 @@ public class RemoteTabsExpandableListFra mSyncStatusListener = null; } } @Override public void onActivityCreated(Bundle savedInstanceState) { super.onActivityCreated(savedInstanceState); + // This races when multiple Fragments are created. That's okay: one + // will win, and thereafter, all will be okay. If we create and then + // drop an instance the shared SharedPreferences backing all the + // instances will maintain the state for us. Since everything happens on + // the UI thread, this doesn't even need to be volatile. + if (sState == null) { + sState = new RemoteTabsExpandableListState(GeckoSharedPrefs.forProfile(getActivity())); + } + + // There is an unfortunate interaction between ExpandableListViews and + // footer onClick handling. The footer view itself appears to not + // receive click events. Its children, however, do receive click events. + // Therefore, we attach an onClick handler to a child of the footer view + // itself. + mFooterView = LayoutInflater.from(getActivity()).inflate(R.layout.home_remote_tabs_hidden_devices_footer, mList, false); + final View view = mFooterView.findViewById(R.id.hidden_devices); + view.setClickable(true); + view.setOnClickListener(new OnClickListener() { + @Override + public void onClick(View v) { + final RemoteClientsDialogFragment dialog = RemoteClientsDialogFragment.newInstance( + getResources().getString(R.string.home_remote_tabs_hidden_devices_title), + getResources().getString(R.string.home_remote_tabs_unhide_selected_devices), + ChoiceMode.MULTIPLE, new ArrayList<RemoteClient>(mHiddenClients)); + dialog.setTargetFragment(RemoteTabsExpandableListFragment.this, 0); + dialog.show(getActivity().getSupportFragmentManager(), DIALOG_TAG_REMOTE_TABS); + } + }); + + // There is a delicate interaction, pre-KitKat, between + // {add,remove}FooterView and setAdapter. setAdapter wraps the adapter + // in a footer/header-managing adapter, which only happens (pre-KitKat) + // if a footer/header is present. Therefore, we add our footer before + // setting the adapter; and then we remove it afterward. From there on, + // we can add/remove it at will. + mList.addFooterView(mFooterView, null, true); + // Intialize adapter mAdapter = new RemoteTabsExpandableListAdapter(R.layout.home_remote_tabs_group, R.layout.home_remote_tabs_child, null); mList.setAdapter(mAdapter); + // Now the adapter is wrapped; we can remove our footer view. + mList.removeFooterView(mFooterView); + // Create callbacks before the initial loader is started mCursorLoaderCallbacks = new CursorLoaderCallbacks(); loadIfVisible(); } - private void updateUiFromClients(List<RemoteClient> clients) { - if (clients != null && !clients.isEmpty()) { - for (int i = 0; i < mList.getExpandableListAdapter().getGroupCount(); i++) { - mList.expandGroup(i); - } + @Override + public void onCreateContextMenu(ContextMenu menu, View view, ContextMenuInfo menuInfo) { + if (!(menuInfo instanceof RemoteTabsClientContextMenuInfo)) { + // Long pressed item was not a RemoteTabsGroup item. Superclass + // can handle this. + super.onCreateContextMenu(menu, view, menuInfo); return; } - // Cursor is empty, so set the empty view if it hasn't been set already. + // Long pressed item was a remote client; provide the appropriate menu. + final MenuInflater inflater = new MenuInflater(view.getContext()); + inflater.inflate(R.menu.home_remote_tabs_client_contextmenu, menu); + + final RemoteTabsClientContextMenuInfo info = (RemoteTabsClientContextMenuInfo) menuInfo; + menu.setHeaderTitle(info.client.name); + + // Hide unused menu items. + final boolean isHidden = sState.isClientHidden(info.client.guid); + final MenuItem item = menu.findItem(isHidden + ? R.id.home_remote_tabs_hide_client + : R.id.home_remote_tabs_show_client); + item.setVisible(false); + } + + @Override + public boolean onContextItemSelected(MenuItem item) { + if (super.onContextItemSelected(item)) { + // HomeFragment was able to handle to selected item. + return true; + } + + final ContextMenuInfo menuInfo = item.getMenuInfo(); + if (!(menuInfo instanceof RemoteTabsClientContextMenuInfo)) { + return false; + } + + final RemoteTabsClientContextMenuInfo info = (RemoteTabsClientContextMenuInfo) menuInfo; + + final int itemId = item.getItemId(); + if (itemId == R.id.home_remote_tabs_hide_client) { + sState.setClientHidden(info.client.guid, true); + getLoaderManager().restartLoader(LOADER_ID_REMOTE_TABS, null, mCursorLoaderCallbacks); + return true; + } else if (itemId == R.id.home_remote_tabs_show_client) { + sState.setClientHidden(info.client.guid, false); + getLoaderManager().restartLoader(LOADER_ID_REMOTE_TABS, null, mCursorLoaderCallbacks); + return true; + } + return false; + } + + private void updateUiFromClients(List<RemoteClient> clients, List<RemoteClient> hiddenClients) { + // We have three states: no clients (including hidden clients) at all; + // all clients hidden; some clients hidden. We want to show the empty + // list view only when we have no clients at all. This flag + // differentiates the first from the latter two states. + boolean displayedSomeClients = false; + + if (hiddenClients == null || hiddenClients.isEmpty()) { + mList.removeFooterView(mFooterView);