--- a/b2g/config/emulator-ics/sources.xml
+++ b/b2g/config/emulator-ics/sources.xml
@@ -7,17 +7,17 @@
<remote fetch="https://git.mozilla.org/releases" name="mozillaorg"/>
<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="59605a7c026ff06cc1613af3938579b1dddc6cfe">
<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="ffb527b84594396ed611edf0a8a5a130d60a742f"/>
+ <project name="gaia.git" path="gaia" remote="mozillaorg" revision="0eadf61ef60f13324fe8290d8c2b516d98230fdc"/>
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="15e8982284c4560f9c74c2b9fe8bb361ebfe0cb6"/>
<project name="rilproxy" path="rilproxy" remote="b2g" revision="827214fcf38d6569aeb5c6d6f31cb296d1f09272"/>
<project name="platform_hardware_ril" path="hardware/ril" remote="b2g" revision="d11f524d00cacf5ba0dfbf25e4aa2158b1c3a036"/>
<project name="platform_external_qemu" path="external/qemu" remote="b2g" revision="022eadd5917615ff00c47eaaafa792b45e9c8a28"/>
<project name="moztt" path="external/moztt" remote="b2g" revision="3d5c964015967ca8c86abe6dbbebee3cb82b1609"/>
<project name="apitrace" path="external/apitrace" remote="apitrace" revision="a314508e397c8f1814228d36259ea8708034444e"/>
<!-- 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
@@ -6,17 +6,17 @@
<remote fetch="https://git.mozilla.org/external/caf" name="caf"/>
<remote fetch="https://git.mozilla.org/releases" name="mozillaorg"/>
<!-- B2G specific things. -->
<project name="platform_build" path="build" remote="b2g" revision="97a5b461686757dbb8ecab2aac5903e41d2e1afe">
<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="ffb527b84594396ed611edf0a8a5a130d60a742f"/>
+ <project name="gaia" path="gaia" remote="mozillaorg" revision="0eadf61ef60f13324fe8290d8c2b516d98230fdc"/>
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="15e8982284c4560f9c74c2b9fe8bb361ebfe0cb6"/>
<project name="moztt" path="external/moztt" remote="b2g" revision="3d5c964015967ca8c86abe6dbbebee3cb82b1609"/>
<project name="apitrace" path="external/apitrace" remote="apitrace" revision="a314508e397c8f1814228d36259ea8708034444e"/>
<project name="valgrind" path="external/valgrind" remote="b2g" revision="905bfa3548eb75cf1792d0d8412b92113bbd4318"/>
<project name="vex" path="external/VEX" remote="b2g" revision="c3d7efc45414f1b44cd9c479bb2758c91c4707c0"/>
<!-- 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/sources.xml
+++ b/b2g/config/emulator/sources.xml
@@ -7,17 +7,17 @@
<remote fetch="https://git.mozilla.org/releases" name="mozillaorg"/>
<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="59605a7c026ff06cc1613af3938579b1dddc6cfe">
<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="ffb527b84594396ed611edf0a8a5a130d60a742f"/>
+ <project name="gaia.git" path="gaia" remote="mozillaorg" revision="0eadf61ef60f13324fe8290d8c2b516d98230fdc"/>
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="15e8982284c4560f9c74c2b9fe8bb361ebfe0cb6"/>
<project name="rilproxy" path="rilproxy" remote="b2g" revision="827214fcf38d6569aeb5c6d6f31cb296d1f09272"/>
<project name="platform_hardware_ril" path="hardware/ril" remote="b2g" revision="d11f524d00cacf5ba0dfbf25e4aa2158b1c3a036"/>
<project name="platform_external_qemu" path="external/qemu" remote="b2g" revision="022eadd5917615ff00c47eaaafa792b45e9c8a28"/>
<project name="moztt" path="external/moztt" remote="b2g" revision="3d5c964015967ca8c86abe6dbbebee3cb82b1609"/>
<project name="apitrace" path="external/apitrace" remote="apitrace" revision="a314508e397c8f1814228d36259ea8708034444e"/>
<!-- Stock Android things -->
<project name="platform/abi/cpp" path="abi/cpp" revision="dd924f92906085b831bf1cbbc7484d3c043d613c"/>
--- a/b2g/config/gaia.json
+++ b/b2g/config/gaia.json
@@ -1,4 +1,4 @@
{
- "revision": "894a7f2886a7a727ce03edadbbea936ceb4aaeba",
+ "revision": "35ef07425e808811af0462a6ba08c36409236846",
"repo_path": "/integration/gaia-central"
}
--- a/b2g/config/hamachi/sources.xml
+++ b/b2g/config/hamachi/sources.xml
@@ -6,17 +6,17 @@
<remote fetch="https://git.mozilla.org/releases" name="mozillaorg"/>
<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="59605a7c026ff06cc1613af3938579b1dddc6cfe">
<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="ffb527b84594396ed611edf0a8a5a130d60a742f"/>
+ <project name="gaia.git" path="gaia" remote="mozillaorg" revision="0eadf61ef60f13324fe8290d8c2b516d98230fdc"/>
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="15e8982284c4560f9c74c2b9fe8bb361ebfe0cb6"/>
<project name="rilproxy" path="rilproxy" remote="b2g" revision="827214fcf38d6569aeb5c6d6f31cb296d1f09272"/>
<project name="librecovery" path="librecovery" remote="b2g" revision="84f2f2fce22605e17d511ff1767e54770067b5b5"/>
<project name="moztt" path="external/moztt" remote="b2g" revision="3d5c964015967ca8c86abe6dbbebee3cb82b1609"/>
<project name="apitrace" path="external/apitrace" remote="apitrace" revision="a314508e397c8f1814228d36259ea8708034444e"/>
<!-- 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
@@ -5,17 +5,17 @@
<remote fetch="https://git.mozilla.org/external/caf" name="caf"/>
<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="59605a7c026ff06cc1613af3938579b1dddc6cfe">
<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="ffb527b84594396ed611edf0a8a5a130d60a742f"/>
+ <project name="gaia.git" path="gaia" remote="mozillaorg" revision="0eadf61ef60f13324fe8290d8c2b516d98230fdc"/>
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="15e8982284c4560f9c74c2b9fe8bb361ebfe0cb6"/>
<project name="rilproxy" path="rilproxy" remote="b2g" revision="827214fcf38d6569aeb5c6d6f31cb296d1f09272"/>
<project name="librecovery" path="librecovery" remote="b2g" revision="84f2f2fce22605e17d511ff1767e54770067b5b5"/>
<project name="moztt" path="external/moztt" remote="b2g" revision="3d5c964015967ca8c86abe6dbbebee3cb82b1609"/>
<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/inari/sources.xml
+++ b/b2g/config/inari/sources.xml
@@ -7,17 +7,17 @@
<remote fetch="https://git.mozilla.org/releases" name="mozillaorg"/>
<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="59605a7c026ff06cc1613af3938579b1dddc6cfe">
<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="ffb527b84594396ed611edf0a8a5a130d60a742f"/>
+ <project name="gaia.git" path="gaia" remote="mozillaorg" revision="0eadf61ef60f13324fe8290d8c2b516d98230fdc"/>
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="15e8982284c4560f9c74c2b9fe8bb361ebfe0cb6"/>
<project name="rilproxy" path="rilproxy" remote="b2g" revision="827214fcf38d6569aeb5c6d6f31cb296d1f09272"/>
<project name="librecovery" path="librecovery" remote="b2g" revision="84f2f2fce22605e17d511ff1767e54770067b5b5"/>
<project name="moztt" path="external/moztt" remote="b2g" revision="3d5c964015967ca8c86abe6dbbebee3cb82b1609"/>
<project name="apitrace" path="external/apitrace" remote="apitrace" revision="a314508e397c8f1814228d36259ea8708034444e"/>
<!-- Stock Android things -->
<project name="platform/abi/cpp" path="abi/cpp" revision="6426040f1be4a844082c9769171ce7f5341a5528"/>
<project name="platform/bionic" path="bionic" revision="cd5dfce80bc3f0139a56b58aca633202ccaee7f8"/>
--- a/b2g/config/leo/sources.xml
+++ b/b2g/config/leo/sources.xml
@@ -6,17 +6,17 @@
<remote fetch="https://git.mozilla.org/releases" name="mozillaorg"/>
<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="59605a7c026ff06cc1613af3938579b1dddc6cfe">
<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="ffb527b84594396ed611edf0a8a5a130d60a742f"/>
+ <project name="gaia.git" path="gaia" remote="mozillaorg" revision="0eadf61ef60f13324fe8290d8c2b516d98230fdc"/>
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="15e8982284c4560f9c74c2b9fe8bb361ebfe0cb6"/>
<project name="rilproxy" path="rilproxy" remote="b2g" revision="827214fcf38d6569aeb5c6d6f31cb296d1f09272"/>
<project name="librecovery" path="librecovery" remote="b2g" revision="84f2f2fce22605e17d511ff1767e54770067b5b5"/>
<project name="moztt" path="external/moztt" remote="b2g" revision="3d5c964015967ca8c86abe6dbbebee3cb82b1609"/>
<project name="apitrace" path="external/apitrace" remote="apitrace" revision="a314508e397c8f1814228d36259ea8708034444e"/>
<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/config/mako/sources.xml
+++ b/b2g/config/mako/sources.xml
@@ -6,17 +6,17 @@
<remote fetch="https://git.mozilla.org/external/caf" name="caf"/>
<remote fetch="https://git.mozilla.org/releases" name="mozillaorg"/>
<!-- B2G specific things. -->
<project name="platform_build" path="build" remote="b2g" revision="97a5b461686757dbb8ecab2aac5903e41d2e1afe">
<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="ffb527b84594396ed611edf0a8a5a130d60a742f"/>
+ <project name="gaia" path="gaia" remote="mozillaorg" revision="0eadf61ef60f13324fe8290d8c2b516d98230fdc"/>
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="15e8982284c4560f9c74c2b9fe8bb361ebfe0cb6"/>
<project name="moztt" path="external/moztt" remote="b2g" revision="3d5c964015967ca8c86abe6dbbebee3cb82b1609"/>
<project name="apitrace" path="external/apitrace" remote="apitrace" revision="a314508e397c8f1814228d36259ea8708034444e"/>
<project name="valgrind" path="external/valgrind" remote="b2g" revision="905bfa3548eb75cf1792d0d8412b92113bbd4318"/>
<project name="vex" path="external/VEX" remote="b2g" revision="c3d7efc45414f1b44cd9c479bb2758c91c4707c0"/>
<!-- 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
@@ -6,17 +6,17 @@
<remote fetch="https://git.mozilla.org/releases" name="mozillaorg"/>
<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="59605a7c026ff06cc1613af3938579b1dddc6cfe">
<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="ffb527b84594396ed611edf0a8a5a130d60a742f"/>
+ <project name="gaia.git" path="gaia" remote="mozillaorg" revision="0eadf61ef60f13324fe8290d8c2b516d98230fdc"/>
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="15e8982284c4560f9c74c2b9fe8bb361ebfe0cb6"/>
<project name="rilproxy" path="rilproxy" remote="b2g" revision="827214fcf38d6569aeb5c6d6f31cb296d1f09272"/>
<project name="librecovery" path="librecovery" remote="b2g" revision="84f2f2fce22605e17d511ff1767e54770067b5b5"/>
<project name="moztt" path="external/moztt" remote="b2g" revision="3d5c964015967ca8c86abe6dbbebee3cb82b1609"/>
<project name="apitrace" path="external/apitrace" remote="apitrace" revision="a314508e397c8f1814228d36259ea8708034444e"/>
<project name="gonk-patches" path="patches" remote="b2g" revision="223a2421006e8f5da33f516f6891c87cae86b0f6"/>
<!-- Stock Android things -->
<project name="platform/abi/cpp" path="abi/cpp" revision="6426040f1be4a844082c9769171ce7f5341a5528"/>
--- a/browser/base/content/browser-charsetmenu.inc
+++ b/browser/base/content/browser-charsetmenu.inc
@@ -1,21 +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/.
-#filter substitution
-
-#expand <menu id="__ID_PREFIX__charsetMenu"
+<menu id="charsetMenu"
label="&charsetMenu.label;"
#ifndef OMIT_ACCESSKEYS
accesskey="&charsetMenu.accesskey;"
#endif
- oncommand="MultiplexHandler(event)"
+ oncommand="BrowserSetForcedCharacterSet(event.target.getAttribute('charset'));"
#ifdef OMIT_ACCESSKEYS
-#expand onpopupshowing="CharsetMenu.build(event.target, '__ID_PREFIX__', false);"
+ onpopupshowing="CharsetMenu.build(event.target, false);"
#else
-#expand onpopupshowing="CharsetMenu.build(event.target, '__ID_PREFIX__');"
+ onpopupshowing="CharsetMenu.build(event.target);"
#endif
- onpopupshown="UpdateMenus(event);">
+ onpopupshown="UpdateCurrentCharset(this);">
<menupopup>
</menupopup>
</menu>
--- a/browser/base/content/browser.js
+++ b/browser/base/content/browser.js
@@ -5134,132 +5134,57 @@ function handleDroppedLink(event, url, n
loadURI(data.url, null, data.postData, false);
});
// Keep the event from being handled by the dragDrop listeners
// built-in to gecko if they happen to be above us.
event.preventDefault();
};
-function MultiplexHandler(event)
-{ try {
- var node = event.target;
- var name = node.getAttribute('name');
-
- if (name == 'detectorGroup') {
- BrowserCharsetReload();
- SelectDetector(event, false);
- } else if (name == 'charsetGroup') {
- var charset = node.getAttribute('id');
- charset = charset.substring(charset.indexOf('charset.') + 'charset.'.length);
- BrowserSetForcedCharacterSet(charset);
- } else if (name == 'charsetCustomize') {
- //do nothing - please remove this else statement, once the charset prefs moves to the pref window
- } else {
- BrowserSetForcedCharacterSet(node.getAttribute('id'));
- }
- } catch(ex) { alert(ex); }
-}
-
-function SelectDetector(event, doReload)
-{
- var uri = event.target.getAttribute("id");
- var prefvalue = uri.substring(uri.indexOf('chardet.') + 'chardet.'.length);
- if ("off" == prefvalue) { // "off" is special value to turn off the detectors
- prefvalue = "";
- }
-
- try {
- var str = Cc["@mozilla.org/supports-string;1"].
- createInstance(Ci.nsISupportsString);
-
- str.data = prefvalue;
- gPrefService.setComplexValue("intl.charset.detector", Ci.nsISupportsString, str);
- if (doReload)
- window.content.location.reload();
- }
- catch (ex) {
- dump("Failed to set the intl.charset.detector preference.\n");
- }
-}
-
function BrowserSetForcedCharacterSet(aCharset)
{
- gBrowser.docShell.gatherCharsetMenuTelemetry();
- gBrowser.docShell.charset = aCharset;
- // Save the forced character-set
- if (!PrivateBrowsingUtils.isWindowPrivate(window))
- PlacesUtils.setCharsetForURI(getWebNavigation().currentURI, aCharset);
+ if (aCharset) {
+ gBrowser.docShell.gatherCharsetMenuTelemetry();
+ gBrowser.docShell.charset = aCharset;
+ // Save the forced character-set
+ if (!PrivateBrowsingUtils.isWindowPrivate(window))
+ PlacesUtils.setCharsetForURI(getWebNavigation().currentURI, aCharset);
+ }
BrowserCharsetReload();
}
function BrowserCharsetReload()
{
BrowserReloadWithFlags(nsIWebNavigation.LOAD_FLAGS_CHARSET_CHANGE);
}
-function charsetMenuGetElement(parent, id) {
- return parent.getElementsByAttribute("id", id)[0];
+function charsetMenuGetElement(parent, charset) {
+ return parent.getElementsByAttribute("charset", charset)[0];
}
function UpdateCurrentCharset(target) {
// extract the charset from DOM
var wnd = document.commandDispatcher.focusedWindow;
if ((window == wnd) || (wnd == null)) wnd = window.content;
// Uncheck previous item
if (gPrevCharset) {
- var pref_item = charsetMenuGetElement(target, "charset." + gPrevCharset);
+ var pref_item = charsetMenuGetElement(target, gPrevCharset);
if (pref_item)
pref_item.setAttribute('checked', 'false');
}
- var menuitem = charsetMenuGetElement(target, "charset." + FoldCharset(wnd.document.characterSet));
+ var menuitem = charsetMenuGetElement(target, CharsetMenu.foldCharset(wnd.document.characterSet));
if (menuitem) {
menuitem.setAttribute('checked', 'true');
}
}
-function FoldCharset(charset) {
- // For substantially similar encodings, treat two encodings as the same
- // for the purpose of the check mark.
- if (charset == "ISO-8859-8-I") {
- return "windows-1255";
- }
-
- if (charset == "gb18030") {
- return "gbk";
- }
-
- return charset;
-}
-
-function UpdateCharsetDetector(target) {
- var prefvalue;
-
- try {
- prefvalue = gPrefService.getComplexValue("intl.charset.detector", Ci.nsIPrefLocalizedString).data;
- }
- catch (ex) {}
-
- if (!prefvalue)
- prefvalue = "off";
-
- var menuitem = charsetMenuGetElement(target, "chardet." + prefvalue);
- if (menuitem)
- menuitem.setAttribute("checked", "true");
-}
-
-function UpdateMenus(event) {
- UpdateCurrentCharset(event.target);
- UpdateCharsetDetector(event.target);
-}
-
function charsetLoadListener() {
- var charset = FoldCharset(window.content.document.characterSet);
+ var charset = CharsetMenu.foldCharset(window.content.document.characterSet);
if (charset.length > 0 && (charset != gLastBrowserCharset)) {
gPrevCharset = gLastBrowserCharset;
gLastBrowserCharset = charset;
}
}
var gPageStyleMenu = {
--- a/content/base/public/Element.h
+++ b/content/base/public/Element.h
@@ -954,17 +954,18 @@ protected:
*
* For the boolean parameters, consider using the named bools above to aid
* code readability.
*
* @param aNamespaceID namespace of attribute
* @param aAttribute local-name of attribute
* @param aPrefix aPrefix of attribute
* @param aOldValue previous value of attribute. Only needed if
- * aFireMutation is true.
+ * aFireMutation is true or if the element is a
+ * custom element (in web components).
* @param aParsedValue parsed new value of attribute
* @param aModType nsIDOMMutationEvent::MODIFICATION or ADDITION. Only
* needed if aFireMutation or aNotify is true.
* @param aFireMutation should mutation-events be fired?
* @param aNotify should we notify document-observers?
* @param aCallAfterSetAttr should we call AfterSetAttr?
*/
nsresult SetAttrAndNotify(int32_t aNamespaceID,
--- a/content/base/public/FragmentOrElement.h
+++ b/content/base/public/FragmentOrElement.h
@@ -202,20 +202,23 @@ public:
virtual void AppendTextTo(nsAString& aResult) MOZ_OVERRIDE;
virtual nsIContent *GetBindingParent() const MOZ_OVERRIDE;
virtual nsXBLBinding *GetXBLBinding() const MOZ_OVERRIDE;
virtual void SetXBLBinding(nsXBLBinding* aBinding,
nsBindingManager* aOldBindingManager = nullptr) MOZ_OVERRIDE;
virtual ShadowRoot *GetShadowRoot() const MOZ_OVERRIDE;
virtual ShadowRoot *GetContainingShadow() const MOZ_OVERRIDE;
virtual void SetShadowRoot(ShadowRoot* aBinding) MOZ_OVERRIDE;
- virtual nsIContent *GetXBLInsertionParent() const;
- virtual void SetXBLInsertionParent(nsIContent* aContent);
+ virtual nsIContent *GetXBLInsertionParent() const MOZ_OVERRIDE;
+ virtual void SetXBLInsertionParent(nsIContent* aContent) MOZ_OVERRIDE;
virtual bool IsLink(nsIURI** aURI) const MOZ_OVERRIDE;
+ virtual CustomElementData *GetCustomElementData() const MOZ_OVERRIDE;
+ virtual void SetCustomElementData(CustomElementData* aData) MOZ_OVERRIDE;
+
virtual void DestroyContent() MOZ_OVERRIDE;
virtual void SaveSubtreeState() MOZ_OVERRIDE;
virtual const nsAttrValue* DoGetClasses() const MOZ_OVERRIDE;
NS_IMETHOD WalkContentStyleRules(nsRuleWalker* aRuleWalker) MOZ_OVERRIDE;
nsIHTMLCollection* Children();
uint32_t ChildElementCount()
@@ -373,16 +376,21 @@ public:
* XBL binding installed on the element.
*/
nsRefPtr<nsXBLBinding> mXBLBinding;
/**
* XBL binding installed on the lement.
*/
nsCOMPtr<nsIContent> mXBLInsertionParent;
+
+ /**
+ * Web components custom element data.
+ */
+ nsAutoPtr<CustomElementData> mCustomElementData;
};
protected:
void GetMarkup(bool aIncludeSelf, nsAString& aMarkup);
void SetInnerHTMLInternal(const nsAString& aInnerHTML, ErrorResult& aError);
// Override from nsINode
virtual nsINode::nsSlots* CreateSlots() MOZ_OVERRIDE;
--- a/content/base/public/nsContentUtils.h
+++ b/content/base/public/nsContentUtils.h
@@ -522,16 +522,22 @@ public:
* @param aBuffer the buffer to check
* @param aLength the length of the buffer
* @param aCharset empty if not found
* @return boolean indicating whether a BOM was detected.
*/
static bool CheckForBOM(const unsigned char* aBuffer, uint32_t aLength,
nsACString& aCharset);
+ /**
+ * Returns true if |aName| is a valid name to be registered via
+ * document.registerElement.
+ */
+ static bool IsCustomElementName(nsIAtom* aName);
+
static nsresult CheckQName(const nsAString& aQualifiedName,
bool aNamespaceAware = true,
const char16_t** aColon = nullptr);
static nsresult SplitQName(const nsIContent* aNamespaceResolver,
const nsAFlatString& aQName,
int32_t *aNamespace, nsIAtom **aLocalName);
--- a/content/base/public/nsIContent.h
+++ b/content/base/public/nsIContent.h
@@ -18,16 +18,17 @@ class nsAttrValue;
class nsAttrName;
class nsTextFragment;
class nsIFrame;
class nsXBLBinding;
namespace mozilla {
namespace dom {
class ShadowRoot;
+struct CustomElementData;
} // namespace dom
namespace widget {
struct IMEState;
} // namespace widget
} // namespace mozilla
enum nsLinkState {
eLinkState_Unvisited = 1,
@@ -672,16 +673,32 @@ public:
* tree. For nodes that are not filtered into an insertion point, this
* simply returns their DOM parent in the original DOM tree.
*
* @return the flattened tree parent
*/
nsIContent *GetFlattenedTreeParent() const;
/**
+ * Gets the custom element data used by web components custom element.
+ * Custom element data is created at the first attempt to enqueue a callback.
+ *
+ * @return The custom element data or null if none.
+ */
+ virtual mozilla::dom::CustomElementData *GetCustomElementData() const = 0;
+
+ /**
+ * Sets the custom element data, ownership of the
+ * callback data is taken by this content.
+ *
+ * @param aCallbackData The custom element data.
+ */
+ virtual void SetCustomElementData(mozilla::dom::CustomElementData* aData) = 0;
+
+ /**
* API to check if this is a link that's traversed in response to user input
* (e.g. a click event). Specializations for HTML/SVG/generic XML allow for
* different types of link in different types of content.
*
* @param aURI Required out param. If this content is a link, a new nsIURI
* set to this link's URI will be passed out.
*
* @note The out param, aURI, is guaranteed to be set to a non-null pointer
--- a/content/base/public/nsIDocument.h
+++ b/content/base/public/nsIDocument.h
@@ -91,24 +91,26 @@ namespace css {
class Loader;
class ImageLoader;
} // namespace css
namespace dom {
class Attr;
class CDATASection;
class Comment;
+struct CustomElementDefinition;
class DocumentFragment;
class DocumentType;
class DOMImplementation;
class Element;
struct ElementRegistrationOptions;
class EventTarget;
class FrameRequestCallback;
class HTMLBodyElement;
+struct LifecycleCallbackArgs;
class Link;
class GlobalObject;
class NodeFilter;
class NodeIterator;
class ProcessingInstruction;
class Touch;
class TreeWalker;
class UndoManager;
@@ -117,18 +119,18 @@ template<typename> class OwningNonNull;
template<typename> class Sequence;
template<typename, typename> class CallbackObjectHolder;
typedef CallbackObjectHolder<NodeFilter, nsIDOMNodeFilter> NodeFilterHolder;
} // namespace dom
} // namespace mozilla
#define NS_IDOCUMENT_IID \
-{ 0x56a350f4, 0xc286, 0x440c, \
- { 0x85, 0xb1, 0xb6, 0x55, 0x77, 0xeb, 0x63, 0xfd } }
+{ 0x595492bc, 0xa26d, 0x46a9, \
+ { 0xa9, 0x35, 0x0c, 0x40, 0xdd, 0xc2, 0x77, 0x51 } }
// Flag for AddStyleSheet().
#define NS_STYLESHEET_FROM_CATALOG (1 << 0)
// Enum for requesting a particular type of document when creating a doc
enum DocumentFlavor {
DocumentFlavorLegacyGuess, // compat with old code until made HTML5-compliant
DocumentFlavorHTML, // HTMLDocument with HTMLness bit set to true
@@ -1981,20 +1983,46 @@ public:
void GetCompatMode(nsString& retval) const;
void GetCharacterSet(nsAString& retval) const;
// Skip GetContentType, because our NS_IMETHOD version above works fine here.
// GetDoctype defined above
Element* GetDocumentElement() const
{
return GetRootElement();
}
+
+ enum ElementCallbackType {
+ eCreated,
+ eEnteredView,
+ eLeftView,
+ eAttributeChanged
+ };
+
+ /**
+ * Registers an unresolved custom element that is a candidate for
+ * upgrade when the definition is registered via registerElement.
+ * |aTypeName| is the name of the custom element type, if it is not
+ * provided, then element name is used. |aTypeName| should be provided
+ * when registering a custom element that extends an existing
+ * element. e.g. <button is="x-button">.
+ */
+ virtual nsresult RegisterUnresolvedElement(Element* aElement,
+ nsIAtom* aTypeName = nullptr) = 0;
+ virtual void EnqueueLifecycleCallback(ElementCallbackType aType,
+ Element* aCustomElement,
+ mozilla::dom::LifecycleCallbackArgs* aArgs = nullptr,
+ mozilla::dom::CustomElementDefinition* aDefinition = nullptr) = 0;
+ virtual void SwizzleCustomElement(Element* aElement,
+ const nsAString& aTypeExtension,
+ uint32_t aNamespaceID,
+ mozilla::ErrorResult& rv) = 0;
virtual JSObject*
- Register(JSContext* aCx, const nsAString& aName,
- const mozilla::dom::ElementRegistrationOptions& aOptions,
- mozilla::ErrorResult& rv) = 0;
+ RegisterElement(JSContext* aCx, const nsAString& aName,
+ const mozilla::dom::ElementRegistrationOptions& aOptions,
+ mozilla::ErrorResult& rv) = 0;
already_AddRefed<nsContentList>
GetElementsByTagName(const nsAString& aTagName)
{
return NS_GetContentList(this, kNameSpaceID_Unknown, aTagName);
}
already_AddRefed<nsContentList>
GetElementsByTagNameNS(const nsAString& aNamespaceURI,
const nsAString& aLocalName,
@@ -2002,16 +2030,23 @@ public:
already_AddRefed<nsContentList>
GetElementsByClassName(const nsAString& aClasses);
// GetElementById defined above
already_AddRefed<Element> CreateElement(const nsAString& aTagName,
mozilla::ErrorResult& rv);
already_AddRefed<Element> CreateElementNS(const nsAString& aNamespaceURI,
const nsAString& aQualifiedName,
mozilla::ErrorResult& rv);
+ virtual already_AddRefed<Element> CreateElement(const nsAString& aTagName,
+ const nsAString& aTypeExtension,
+ mozilla::ErrorResult& rv) = 0;
+ virtual already_AddRefed<Element> CreateElementNS(const nsAString& aNamespaceURI,
+ const nsAString& aQualifiedName,
+ const nsAString& aTypeExtension,
+ mozilla::ErrorResult& rv) = 0;
already_AddRefed<mozilla::dom::DocumentFragment>
CreateDocumentFragment() const;
already_AddRefed<nsTextNode> CreateTextNode(const nsAString& aData) const;
already_AddRefed<mozilla::dom::Comment>
CreateComment(const nsAString& aData) const;
already_AddRefed<mozilla::dom::ProcessingInstruction>
CreateProcessingInstruction(const nsAString& target, const nsAString& data,
mozilla::ErrorResult& rv) const;
--- a/content/base/src/Element.cpp
+++ b/content/base/src/Element.cpp
@@ -356,16 +356,32 @@ Element::GetBindingURL(nsIDocument *aDoc
JSObject*
Element::WrapObject(JSContext *aCx, JS::Handle<JSObject*> aScope)
{
JS::Rooted<JSObject*> obj(aCx, nsINode::WrapObject(aCx, aScope));
if (!obj) {
return nullptr;
}
+ // Custom element prototype swizzling.
+ CustomElementData* data = GetCustomElementData();
+ if (obj && data) {
+ // If this is a registered custom element then fix the prototype.
+ JSAutoCompartment ac(aCx, obj);
+ nsDocument* document = static_cast<nsDocument*>(OwnerDoc());
+ JS::Rooted<JSObject*> prototype(aCx);
+ document->GetCustomPrototype(NodeInfo()->NamespaceID(), data->mType, &prototype);
+ if (prototype) {
+ if (!JS_WrapObject(aCx, &prototype) || !JS_SetPrototype(aCx, obj, prototype)) {
+ dom::Throw(aCx, NS_ERROR_FAILURE);
+ return nullptr;
+ }
+ }
+ }
+
nsIDocument* doc;
if (HasFlag(NODE_FORCE_XBL_BINDINGS)) {
doc = OwnerDoc();
}
else {
doc = GetCurrentDoc();
}
@@ -1136,16 +1152,21 @@ Element::BindToTree(nsIDocument* aDocume
// We no longer need to track the subtree pointer (and in fact we'll assert
// if we do this any later).
ClearSubtreeRootPointer();
// Being added to a document.
SetInDocument();
+ if (GetCustomElementData()) {
+ // Enqueue an enteredView callback for the custom element.
+ aDocument->EnqueueLifecycleCallback(nsIDocument::eEnteredView, this);
+ }
+
// Unset this flag since we now really are in a document.
UnsetFlags(NODE_FORCE_XBL_BINDINGS |
// And clear the lazy frame construction bits.
NODE_NEEDS_FRAME | NODE_DESCENDANTS_NEED_FRAMES |
// And the restyle bits
ELEMENT_ALL_RESTYLE_FLAGS);
// Propagate scoped style sheet tracking bit.
@@ -1293,16 +1314,21 @@ Element::UnbindFromTree(bool aDeep, bool
// anonymous content that the document is changing.
if (HasFlag(NODE_MAY_BE_IN_BINDING_MNGR)) {
nsContentUtils::AddScriptRunner(
new RemoveFromBindingManagerRunnable(document->BindingManager(), this,
document));
}
document->ClearBoxObjectFor(this);
+
+ if (GetCustomElementData()) {
+ // Enqueue a leftView callback for the custom element.
+ document->EnqueueLifecycleCallback(nsIDocument::eLeftView, this);
+ }
}
// Ensure that CSS transitions don't continue on an element at a
// different place in the tree (even if reinserted before next
// animation refresh).
// FIXME (Bug 522599): Need a test for this.
if (HasFlag(NODE_HAS_PROPERTIES)) {
DeleteProperty(nsGkAtoms::transitionsOfBeforeProperty);
@@ -1660,18 +1686,20 @@ Element::MaybeCheckSameAttrVal(int32_t a
// coming from the content sink and will almost certainly have no previous
// value. Even if we do, setting the value is cheap when we have no
// listeners and don't plan to notify. The check for aNotify here is an
// optimization, the check for *aHasListeners is a correctness issue.
if (*aHasListeners || aNotify) {
nsAttrInfo info(GetAttrInfo(aNamespaceID, aName));
if (info.mValue) {
// Check whether the old value is the same as the new one. Note that we
- // only need to actually _get_ the old value if we have listeners.
- if (*aHasListeners) {
+ // only need to actually _get_ the old value if we have listeners or
+ // if the element is a custom element (because it may have an
+ // attribute changed callback).
+ if (*aHasListeners || GetCustomElementData()) {
// Need to store the old value.
//
// If the current attribute value contains a pointer to some other data
// structure that gets updated in the process of setting the attribute
// we'll no longer have the old value of the attribute. Therefore, we
// should serialize the attribute value now to keep a snapshot.
//
// We have to serialize the value anyway in order to create the
@@ -1847,16 +1875,30 @@ Element::SetAttrAndNotify(int32_t aNames
nsRefPtr<nsXBLBinding> binding = GetXBLBinding();
if (binding) {
binding->AttributeChanged(aName, aNamespaceID, false, aNotify);
}
}
UpdateState(aNotify);
+ nsIDocument* ownerDoc = OwnerDoc();
+ if (ownerDoc && GetCustomElementData()) {
+ nsCOMPtr<nsIAtom> oldValueAtom = aOldValue.GetAsAtom();
+ nsCOMPtr<nsIAtom> newValueAtom = aValueForAfterSetAttr.GetAsAtom();
+ LifecycleCallbackArgs args = {
+ nsDependentAtomString(aName),
+ aModType == nsIDOMMutationEvent::ADDITION ?
+ NullString() : nsDependentAtomString(oldValueAtom),
+ nsDependentAtomString(newValueAtom)
+ };
+
+ ownerDoc->EnqueueLifecycleCallback(nsIDocument::eAttributeChanged, this, &args);
+ }
+
if (aCallAfterSetAttr) {
rv = AfterSetAttr(aNamespaceID, aName, &aValueForAfterSetAttr, aNotify);
NS_ENSURE_SUCCESS(rv, rv);
if (aNamespaceID == kNameSpaceID_None && aName == nsGkAtoms::dir) {
OnSetDirAttr(this, &aValueForAfterSetAttr,
hadValidDir, hadDirAuto, aNotify);
}
@@ -2030,16 +2072,28 @@ Element::UnsetAttr(int32_t aNameSpaceID,
nsRefPtr<nsXBLBinding> binding = GetXBLBinding();
if (binding) {
binding->AttributeChanged(aName, aNameSpaceID, true, aNotify);
}
}
UpdateState(aNotify);
+ nsIDocument* ownerDoc = OwnerDoc();
+ if (ownerDoc && GetCustomElementData()) {
+ nsCOMPtr<nsIAtom> oldValueAtom = oldValue.GetAsAtom();
+ LifecycleCallbackArgs args = {
+ nsDependentAtomString(aName),
+ nsDependentAtomString(oldValueAtom),
+ NullString()
+ };
+
+ ownerDoc->EnqueueLifecycleCallback(nsIDocument::eAttributeChanged, this, &args);
+ }
+
if (aNotify) {
nsNodeUtils::AttributeChanged(this, aNameSpaceID, aName,
nsIDOMMutationEvent::REMOVAL);
}
rv = AfterSetAttr(aNameSpaceID, aName, nullptr, aNotify);
NS_ENSURE_SUCCESS(rv, rv);
--- a/content/base/src/FragmentOrElement.cpp
+++ b/content/base/src/FragmentOrElement.cpp
@@ -558,16 +558,22 @@ FragmentOrElement::nsDOMSlots::Traverse(
NS_CYCLE_COLLECTION_NOTE_EDGE_NAME(cb, "mSlots->mContainingShadow");
cb.NoteXPCOMChild(NS_ISUPPORTS_CAST(nsIContent*, mContainingShadow));
NS_CYCLE_COLLECTION_NOTE_EDGE_NAME(cb, "mSlots->mChildrenList");
cb.NoteXPCOMChild(NS_ISUPPORTS_CAST(nsIDOMNodeList*, mChildrenList));
NS_CYCLE_COLLECTION_NOTE_EDGE_NAME(cb, "mSlots->mClassList");
cb.NoteXPCOMChild(mClassList.get());
+
+ if (mCustomElementData) {
+ for (uint32_t i = 0; i < mCustomElementData->mCallbackQueue.Length(); i++) {
+ mCustomElementData->mCallbackQueue[i]->Traverse(cb);
+ }
+ }
}
void
FragmentOrElement::nsDOMSlots::Unlink(bool aIsXUL)
{
mStyle = nullptr;
mSMILOverrideStyle = nullptr;
if (mAttributeMap) {
@@ -577,16 +583,17 @@ FragmentOrElement::nsDOMSlots::Unlink(bo
if (aIsXUL)
NS_IF_RELEASE(mControllers);
mXBLBinding = nullptr;
mXBLInsertionParent = nullptr;
mShadowRoot = nullptr;
mContainingShadow = nullptr;
mChildrenList = nullptr;
mUndoManager = nullptr;
+ mCustomElementData = nullptr;
if (mClassList) {
mClassList->DropReference();
mClassList = nullptr;
}
}
size_t
FragmentOrElement::nsDOMSlots::SizeOfIncludingThis(MallocSizeOf aMallocSizeOf) const
@@ -1008,16 +1015,34 @@ FragmentOrElement::SetXBLInsertionParent
{
nsDOMSlots *slots = DOMSlots();
if (aContent) {
SetFlags(NODE_MAY_BE_IN_BINDING_MNGR);
}
slots->mXBLInsertionParent = aContent;
}
+CustomElementData*
+FragmentOrElement::GetCustomElementData() const
+{
+ nsDOMSlots *slots = GetExistingDOMSlots();
+ if (slots) {
+ return slots->mCustomElementData;
+ }
+ return nullptr;
+}
+
+void
+FragmentOrElement::SetCustomElementData(CustomElementData* aData)
+{
+ nsDOMSlots *slots = DOMSlots();
+ MOZ_ASSERT(!slots->mCustomElementData, "Custom element data may not be changed once set.");
+ slots->mCustomElementData = aData;
+}
+
nsresult
FragmentOrElement::InsertChildAt(nsIContent* aKid,
uint32_t aIndex,
bool aNotify)
{
NS_PRECONDITION(aKid, "null ptr");
return doInsertChildAt(aKid, aIndex, aNotify, mAttrsAndChildren);
--- a/content/base/src/moz.build
+++ b/content/base/src/moz.build
@@ -193,16 +193,17 @@ MSVC_ENABLE_PGO = True
include('/ipc/chromium/chromium-config.mozbuild')
FINAL_LIBRARY = 'gklayout'
LOCAL_INCLUDES += [
'/caps/include',
'/content/html/content/src',
'/content/html/document/src',
+ '/content/svg/content/src',
'/content/xml/content/src',
'/content/xml/document/src',
'/content/xul/content/src',
'/content/xul/document/src',
'/docshell/base',
'/dom/base',
'/dom/events',
'/dom/ipc',
--- a/content/base/src/nsContentUtils.cpp
+++ b/content/base/src/nsContentUtils.cpp
@@ -60,16 +60,17 @@
#include "nsContentList.h"
#include "nsContentPolicyUtils.h"
#include "nsCPrefetchService.h"
#include "nsCRT.h"
#include "nsCycleCollectionParticipant.h"
#include "nsCycleCollector.h"
#include "nsDataHashtable.h"
#include "nsDocShellCID.h"
+#include "nsDocument.h"
#include "nsDOMCID.h"
#include "nsDOMDataTransfer.h"
#include "nsDOMJSUtils.h"
#include "nsDOMMutationObserver.h"
#include "nsDOMTouchEvent.h"
#include "nsError.h"
#include "nsEventDispatcher.h"
#include "nsEventListenerManager.h"
@@ -2418,16 +2419,49 @@ nsContentUtils::NewURIWithDocumentCharse
nsIURI* aBaseURI)
{
return NS_NewURI(aResult, aSpec,
aDocument ? aDocument->GetDocumentCharacterSet().get() : nullptr,
aBaseURI, sIOService);
}
// static
+bool
+nsContentUtils::IsCustomElementName(nsIAtom* aName)
+{
+ // The custom element name identifies a custom element and is a sequence of
+ // alphanumeric ASCII characters that must match the NCName production and
+ // contain a U+002D HYPHEN-MINUS character.
+ nsDependentAtomString str(aName);
+ const char16_t* colon;
+ if (NS_FAILED(nsContentUtils::CheckQName(str, false, &colon)) || colon ||
+ str.FindChar('-') == -1) {
+ return false;
+ }
+
+ // The custom element name must not be one of the following values:
+ // annotation-xml
+ // color-profile
+ // font-face
+ // font-face-src
+ // font-face-uri
+ // font-face-format
+ // font-face-name
+ // missing-glyph
+ return aName != nsGkAtoms::annotation_xml_ &&
+ aName != nsGkAtoms::colorProfile &&
+ aName != nsGkAtoms::font_face &&
+ aName != nsGkAtoms::font_face_src &&
+ aName != nsGkAtoms::font_face_uri &&
+ aName != nsGkAtoms::font_face_format &&
+ aName != nsGkAtoms::font_face_name &&
+ aName != nsGkAtoms::missingGlyph;
+}
+
+// static
nsresult
nsContentUtils::CheckQName(const nsAString& aQualifiedName,
bool aNamespaceAware,
const char16_t** aColon)
{
const char* colon = nullptr;
const char16_t* begin = aQualifiedName.BeginReading();
const char16_t* end = aQualifiedName.EndReading();
@@ -4752,16 +4786,17 @@ nsContentUtils::EnterMicroTask()
}
void
nsContentUtils::LeaveMicroTask()
{
MOZ_ASSERT(NS_IsMainThread());
if (--sMicroTaskLevel == 0) {
nsDOMMutationObserver::HandleMutations();
+ nsDocument::ProcessBaseElementQueue();
}
}
bool
nsContentUtils::IsInMicroTask()
{
MOZ_ASSERT(NS_IsMainThread());
return sMicroTaskLevel != 0;
--- a/content/base/src/nsDocument.cpp
+++ b/content/base/src/nsDocument.cpp
@@ -158,30 +158,32 @@
#include "mozilla/dom/EncodingUtils.h"
#include "mozilla/dom/quota/QuotaManager.h"
#include "nsDOMNavigationTiming.h"
#include "nsEventStateManager.h"
#include "nsSMILAnimationController.h"
#include "imgIContainer.h"
#include "nsSVGUtils.h"
+#include "SVGElementFactory.h"
#include "nsRefreshDriver.h"
// FOR CSP (autogenerated by xpidl)
#include "nsIContentSecurityPolicy.h"
#include "nsCSPService.h"
#include "nsHTMLStyleSheet.h"
#include "nsHTMLCSSStyleSheet.h"
#include "mozilla/dom/DOMImplementation.h"
#include "mozilla/dom/ShadowRoot.h"
#include "mozilla/dom/Comment.h"
#include "nsTextNode.h"
#include "mozilla/dom/Link.h"
#include "mozilla/dom/HTMLElementBinding.h"
+#include "mozilla/dom/SVGElementBinding.h"
#include "nsXULAppAPI.h"
#include "nsDOMTouchEvent.h"
#include "mozilla/dom/Touch.h"
#include "DictionaryHelpers.h"
#include "GeneratedEvents.h"
#include "mozilla/Preferences.h"
@@ -307,16 +309,105 @@ nsIdentifierMapEntry::RemoveContentChang
struct FireChangeArgs {
Element* mFrom;
Element* mTo;
bool mImageOnly;
bool mHaveImageOverride;
};
+namespace mozilla {
+namespace dom {
+
+void
+CustomElementCallback::Call()
+{
+ ErrorResult rv;
+ switch (mType) {
+ case nsIDocument::eCreated:
+ // For the duration of this callback invocation, the element is being created
+ // flag must be set to true.
+ mOwnerData->mElementIsBeingCreated = true;
+ mOwnerData->mCreatedCallbackInvoked = true;
+ static_cast<LifecycleCreatedCallback *>(mCallback.get())->Call(mThisObject, rv);
+ mOwnerData->mElementIsBeingCreated = false;
+ break;
+ case nsIDocument::eEnteredView:
+ static_cast<LifecycleEnteredViewCallback *>(mCallback.get())->Call(mThisObject, rv);
+ break;
+ case nsIDocument::eLeftView:
+ static_cast<LifecycleLeftViewCallback *>(mCallback.get())->Call(mThisObject, rv);
+ break;
+ case nsIDocument::eAttributeChanged:
+ static_cast<LifecycleAttributeChangedCallback *>(mCallback.get())->Call(mThisObject,
+ mArgs.name, mArgs.oldValue, mArgs.newValue, rv);
+ break;
+ }
+}
+
+void
+CustomElementCallback::Traverse(nsCycleCollectionTraversalCallback& aCb) const
+{
+ NS_CYCLE_COLLECTION_NOTE_EDGE_NAME(aCb, "mThisObject");
+ aCb.NoteXPCOMChild(mThisObject);
+
+ NS_CYCLE_COLLECTION_NOTE_EDGE_NAME(aCb, "mCallback");
+ aCb.NoteXPCOMChild(mCallback);
+}
+
+CustomElementCallback::CustomElementCallback(Element* aThisObject,
+ nsIDocument::ElementCallbackType aCallbackType,
+ mozilla::dom::CallbackFunction* aCallback,
+ CustomElementData* aOwnerData)
+ : mThisObject(aThisObject),
+ mCallback(aCallback),
+ mType(aCallbackType),
+ mOwnerData(aOwnerData)
+{
+}
+
+CustomElementDefinition::CustomElementDefinition(JSObject* aPrototype,
+ nsIAtom* aType,
+ nsIAtom* aLocalName,
+ LifecycleCallbacks* aCallbacks,
+ uint32_t aNamespaceID,
+ uint32_t aDocOrder)
+ : mPrototype(aPrototype),
+ mType(aType),
+ mLocalName(aLocalName),
+ mCallbacks(aCallbacks),
+ mNamespaceID(aNamespaceID),
+ mDocOrder(aDocOrder)
+{
+}
+
+CustomElementData::CustomElementData(nsIAtom* aType)
+ : mType(aType),
+ mCurrentCallback(-1),
+ mElementIsBeingCreated(false),
+ mCreatedCallbackInvoked(true),
+ mAssociatedMicroTask(-1)
+{
+}
+
+void
+CustomElementData::RunCallbackQueue()
+{
+ // Note: It's possible to re-enter this method.
+ while (static_cast<uint32_t>(++mCurrentCallback) < mCallbackQueue.Length()) {
+ mCallbackQueue[mCurrentCallback]->Call();
+ }
+
+ mCallbackQueue.Clear();
+ mCurrentCallback = -1;
+}
+
+} // namespace dom
+} // namespace mozilla
+
static PLDHashOperator
FireChangeEnumerator(nsIdentifierMapEntry::ChangeCallbackEntry *aEntry, void *aArg)
{
FireChangeArgs* args = static_cast<FireChangeArgs*>(aArg);
// Don't fire image changes for non-image observers, and don't fire element
// changes for image observers when an image override is active.
if (aEntry->mKey.mForImage ? (args->mHaveImageOverride && !args->mImageOnly) :
args->mImageOnly)
@@ -1433,16 +1524,22 @@ nsDocument::nsDocument(const char* aCont
("DOCUMENT %p created", this));
if (!gCspPRLog)
gCspPRLog = PR_NewLogModule("CSP");
#endif
// Start out mLastStyleSheetSet as null, per spec
SetDOMStringToNull(mLastStyleSheetSet);
+
+ if (sProcessingStack.empty()) {
+ sProcessingStack.construct();
+ // Add the base queue sentinel to the processing stack.
+ sProcessingStack.ref().AppendElement((CustomElementData*) nullptr);
+ }
}
static PLDHashOperator
ClearAllBoxObjects(nsIContent* aKey, nsPIBoxObject* aBoxObject, void* aUserArg)
{
if (aBoxObject) {
aBoxObject->Clear();
}
@@ -1508,17 +1605,19 @@ nsDocument::~nsDocument()
}
Accumulate(Telemetry::MIXED_CONTENT_PAGE_LOAD, mixedContentLevel);
}
}
mInDestructor = true;
mInUnlinkOrDeletion = true;
- mCustomPrototypes.Clear();
+ if (mRegistry) {
+ mRegistry->Clear();
+ }
mozilla::DropJSObjects(this);
// Clear mObservers to keep it in sync with the mutationobserver list
mObservers.Clear();
if (mStyleSheetSetList) {
mStyleSheetSetList->Disconnect();
@@ -1678,16 +1777,67 @@ NS_IMPL_CYCLE_COLLECTION_CAN_SKIP_IN_CC_
return Element::CanSkipInCC(tmp);
NS_IMPL_CYCLE_COLLECTION_CAN_SKIP_IN_CC_END
NS_IMPL_CYCLE_COLLECTION_CAN_SKIP_THIS_BEGIN(nsDocument)
return Element::CanSkipThis(tmp);
NS_IMPL_CYCLE_COLLECTION_CAN_SKIP_THIS_END
static PLDHashOperator
+CustomDefinitionsTraverse(CustomElementHashKey* aKey,
+ CustomElementDefinition* aDefinition,
+ void* aArg)
+{
+ nsCycleCollectionTraversalCallback* cb =
+ static_cast<nsCycleCollectionTraversalCallback*>(aArg);
+
+ nsAutoPtr<LifecycleCallbacks>& callbacks = aDefinition->mCallbacks;
+
+ if (callbacks->mAttributeChangedCallback.WasPassed()) {
+ NS_CYCLE_COLLECTION_NOTE_EDGE_NAME(*cb,
+ "mCustomDefinitions->mCallbacks->mAttributeChangedCallback");
+ cb->NoteXPCOMChild(aDefinition->mCallbacks->mAttributeChangedCallback.Value());
+ }
+
+ if (callbacks->mCreatedCallback.WasPassed()) {
+ NS_CYCLE_COLLECTION_NOTE_EDGE_NAME(*cb,
+ "mCustomDefinitions->mCallbacks->mCreatedCallback");
+ cb->NoteXPCOMChild(aDefinition->mCallbacks->mCreatedCallback.Value());
+ }
+
+ if (callbacks->mEnteredViewCallback.WasPassed()) {
+ NS_CYCLE_COLLECTION_NOTE_EDGE_NAME(*cb,
+ "mCustomDefinitions->mCallbacks->mEnteredViewCallback");
+ cb->NoteXPCOMChild(aDefinition->mCallbacks->mEnteredViewCallback.Value());
+ }
+
+ if (callbacks->mLeftViewCallback.WasPassed()) {
+ NS_CYCLE_COLLECTION_NOTE_EDGE_NAME(*cb,
+ "mCustomDefinitions->mCallbacks->mLeftViewCallback");
+ cb->NoteXPCOMChild(aDefinition->mCallbacks->mLeftViewCallback.Value());
+ }
+
+ return PL_DHASH_NEXT;
+}
+
+static PLDHashOperator
+CandidatesTraverse(CustomElementHashKey* aKey,
+ nsTArray<nsRefPtr<Element>>* aData,
+ void* aArg)
+{
+ nsCycleCollectionTraversalCallback *cb =
+ static_cast<nsCycleCollectionTraversalCallback*>(aArg);
+ for (size_t i = 0; i < aData->Length(); ++i) {
+ NS_CYCLE_COLLECTION_NOTE_EDGE_NAME(*cb, "mCandidatesMap->Element");
+ cb->NoteXPCOMChild(aData->ElementAt(i));
+ }
+ return PL_DHASH_NEXT;
+}
+
+static PLDHashOperator
SubDocTraverser(PLDHashTable *table, PLDHashEntryHdr *hdr, uint32_t number,
void *arg)
{
SubDocMapEntry *entry = static_cast<SubDocMapEntry*>(hdr);
nsCycleCollectionTraversalCallback *cb =
static_cast<nsCycleCollectionTraversalCallback*>(arg);
NS_CYCLE_COLLECTION_NOTE_EDGE_NAME(*cb, "mSubDocuments entry->mKey");
@@ -1842,50 +1992,60 @@ NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_
cb.NoteXPCOMChild(tmp->mFrameRequestCallbacks[i].mCallback.GetISupports());
}
// Traverse animation components
if (tmp->mAnimationController) {
tmp->mAnimationController->Traverse(&cb);
}
+ if (tmp->mRegistry) {
+ tmp->mRegistry->mCustomDefinitions.EnumerateRead(CustomDefinitionsTraverse, &cb);
+ tmp->mRegistry->mCandidatesMap.EnumerateRead(CandidatesTraverse, &cb);
+ }
+
if (tmp->mSubDocuments && tmp->mSubDocuments->ops) {
PL_DHashTableEnumerate(tmp->mSubDocuments, SubDocTraverser, &cb);
}
if (tmp->mCSSLoader) {
tmp->mCSSLoader->TraverseCachedSheets(cb);
}
for (uint32_t i = 0; i < tmp->mHostObjectURIs.Length(); ++i) {
nsHostObjectProtocolHandler::Traverse(tmp->mHostObjectURIs[i], cb);
}
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
-
-struct CustomPrototypeTraceArgs {
+struct CustomDefinitionTraceArgs
+{
const TraceCallbacks& callbacks;
void* closure;
};
-
static PLDHashOperator
-CustomPrototypeTrace(const nsAString& aName, JS::Heap<JSObject*>& aObject, void *aArg)
-{
- CustomPrototypeTraceArgs* traceArgs = static_cast<CustomPrototypeTraceArgs*>(aArg);
- MOZ_ASSERT(aObject, "Protocol object value must not be null");
- traceArgs->callbacks.Trace(&aObject, "mCustomPrototypes entry", traceArgs->closure);
+CustomDefinitionTrace(CustomElementHashKey *aKey,
+ CustomElementDefinition *aData,
+ void *aArg)
+{
+ CustomDefinitionTraceArgs* traceArgs = static_cast<CustomDefinitionTraceArgs*>(aArg);
+ MOZ_ASSERT(aData, "Definition must not be null");
+ traceArgs->callbacks.Trace(&aData->mPrototype, "mCustomDefinitions prototype",
+ traceArgs->closure);
return PL_DHASH_NEXT;
}
NS_IMPL_CYCLE_COLLECTION_CLASS(nsDocument)
NS_IMPL_CYCLE_COLLECTION_TRACE_BEGIN(nsDocument)
- CustomPrototypeTraceArgs customPrototypeArgs = { aCallbacks, aClosure };
- tmp->mCustomPrototypes.Enumerate(CustomPrototypeTrace, &customPrototypeArgs);
+ CustomDefinitionTraceArgs customDefinitionArgs = { aCallbacks, aClosure };
+ if (tmp->mRegistry) {
+ tmp->mRegistry->mCustomDefinitions.EnumerateRead(CustomDefinitionTrace,
+ &customDefinitionArgs);
+ }
if (tmp->PreservingWrapper()) {
NS_IMPL_CYCLE_COLLECTION_TRACE_JSVAL_MEMBER_CALLBACK(mExpandoAndGeneration.expando);
}
NS_IMPL_CYCLE_COLLECTION_TRACE_PRESERVED_WRAPPER
NS_IMPL_CYCLE_COLLECTION_TRACE_END
NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(nsDocument)
@@ -1946,17 +2106,19 @@ NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(ns
// nsDocument has a pretty complex destructor, so we're going to
// assume that *most* cycles you actually want to break somewhere
// else, and not unlink an awful lot here.
tmp->mIdentifierMap.Clear();
tmp->mExpandoAndGeneration.Unlink();
- tmp->mCustomPrototypes.Clear();
+ if (tmp->mRegistry) {
+ tmp->mRegistry->Clear();
+ }
if (tmp->mAnimationController) {
tmp->mAnimationController->Unlink();
}
tmp->mPendingTitleChangeEvent.Revoke();
if (tmp->mCSSLoader) {
@@ -2150,17 +2312,19 @@ nsDocument::ResetToURI(nsIURI *aURI, nsI
mChildren.RemoveChildAt(i);
nsNodeUtils::ContentRemoved(this, content, i, previousSibling);
content->UnbindFromTree();
}
mCachedRootElement = nullptr;
}
mInUnlinkOrDeletion = oldVal;
- mCustomPrototypes.Clear();
+ if (mRegistry) {
+ mRegistry->Clear();
+ }
// Reset our stylesheets
ResetStylesheetsToURI(aURI);
// Release the listener manager
if (mListenerManager) {
mListenerManager->Disconnect();
mListenerManager = nullptr;
@@ -4342,16 +4506,17 @@ nsDocument::SetScriptGlobalObject(nsIScr
#endif
bool allowDNSPrefetch;
docShell->GetAllowDNSPrefetch(&allowDNSPrefetch);
mAllowDNSPrefetch = allowDNSPrefetch;
}
}
MaybeRescheduleAnimationFrameNotifications();
+ mRegistry = new Registry();
}
// Remember the pointer to our window (or lack there of), to avoid
// having to QI every time it's asked for.
nsCOMPtr<nsPIDOMWindow> window = do_QueryInterface(mScriptGlobalObject);
mWindow = window;
// Now that we know what our window is, we can flush the CSP errors to the
@@ -4985,16 +5150,74 @@ nsIDocument::CreateElement(const nsAStri
rv = CreateElem(needsLowercase ? lcTagName : aTagName,
nullptr, mDefaultElementType, getter_AddRefs(content));
if (rv.Failed()) {
return nullptr;
}
return dont_AddRef(content.forget().get()->AsElement());
}
+void
+nsDocument::SwizzleCustomElement(Element* aElement,
+ const nsAString& aTypeExtension,
+ uint32_t aNamespaceID,
+ ErrorResult& rv)
+{
+ nsCOMPtr<nsIAtom> typeAtom(do_GetAtom(aTypeExtension));
+ nsCOMPtr<nsIAtom> tagAtom = aElement->Tag();
+ if (!mRegistry || tagAtom == typeAtom) {
+ return;
+ }
+
+ CustomElementDefinition* data;
+ CustomElementHashKey key(aNamespaceID, typeAtom);
+ if (!mRegistry->mCustomDefinitions.Get(&key, &data)) {
+ // The type extension doesn't exist in the registry,
+ // thus we don't need to swizzle, but it is possibly
+ // an upgrade candidate.
+ RegisterUnresolvedElement(aElement, typeAtom);
+ return;
+ }
+
+ if (data->mLocalName != tagAtom) {
+ // The element doesn't match the local name for the
+ // definition, thus the element isn't a custom element
+ // and we don't need to do anything more.
+ return;
+ }
+
+ if (!aElement->HasAttr(kNameSpaceID_None, nsGkAtoms::is)) {
+ // Swizzling in the parser happens after the "is" attribute is added.
+ aElement->SetAttr(kNameSpaceID_None, nsGkAtoms::is, aTypeExtension, true);
+ }
+
+ // Enqueuing the created callback will set the CustomElementData on the
+ // element, causing prototype swizzling to occur in Element::WrapObject.
+ EnqueueLifecycleCallback(nsIDocument::eCreated, aElement, nullptr, data);
+}
+
+already_AddRefed<Element>
+nsDocument::CreateElement(const nsAString& aTagName,
+ const nsAString& aTypeExtension,
+ ErrorResult& rv)
+{
+ nsRefPtr<Element> elem = nsIDocument::CreateElement(aTagName, rv);
+ if (rv.Failed()) {
+ return nullptr;
+ }
+
+ SwizzleCustomElement(elem, aTypeExtension,
+ GetDefaultNamespaceID(), rv);
+ if (rv.Failed()) {
+ return nullptr;
+ }
+
+ return elem.forget();
+}
+
NS_IMETHODIMP
nsDocument::CreateElementNS(const nsAString& aNamespaceURI,
const nsAString& aQualifiedName,
nsIDOMElement** aReturn)
{
*aReturn = nullptr;
ErrorResult rv;
nsCOMPtr<Element> element =
@@ -5022,16 +5245,46 @@ nsIDocument::CreateElementNS(const nsASt
rv = NS_NewElement(getter_AddRefs(element), nodeInfo.forget(),
NOT_FROM_PARSER);
if (rv.Failed()) {
return nullptr;
}
return element.forget();
}
+already_AddRefed<Element>
+nsDocument::CreateElementNS(const nsAString& aNamespaceURI,
+ const nsAString& aQualifiedName,
+ const nsAString& aTypeExtension,
+ ErrorResult& rv)
+{
+ nsRefPtr<Element> elem = nsIDocument::CreateElementNS(aNamespaceURI,
+ aQualifiedName,
+ rv);
+ if (rv.Failed()) {
+ return nullptr;
+ }
+
+ int32_t nameSpaceId = kNameSpaceID_Wildcard;
+ if (!aNamespaceURI.EqualsLiteral("*")) {
+ rv = nsContentUtils::NameSpaceManager()->RegisterNameSpace(aNamespaceURI,
+ nameSpaceId);
+ if (rv.Failed()) {
+ return nullptr;
+ }
+ }
+
+ SwizzleCustomElement(elem, aTypeExtension, nameSpaceId, rv);
+ if (rv.Failed()) {
+ return nullptr;
+ }
+
+ return elem.forget();
+}
+
NS_IMETHODIMP
nsDocument::CreateTextNode(const nsAString& aData, nsIDOMText** aReturn)
{
*aReturn = nsIDocument::CreateTextNode(aData).get();
return NS_OK;
}
already_AddRefed<nsTextNode>
@@ -5206,67 +5459,358 @@ nsIDocument::CreateAttributeNS(const nsA
return nullptr;
}
nsRefPtr<Attr> attribute = new Attr(nullptr, nodeInfo.forget(),
EmptyString(), true);
return attribute.forget();
}
-static bool
-CustomElementConstructor(JSContext *aCx, unsigned aArgc, JS::Value* aVp)
+bool
+nsDocument::CustomElementConstructor(JSContext* aCx, unsigned aArgc, JS::Value* aVp)
{
JS::CallArgs args = JS::CallArgsFromVp(aArgc, aVp);
JS::Rooted<JSObject*> global(aCx,
JS_GetGlobalForObject(aCx, &args.callee()));
nsCOMPtr<nsPIDOMWindow> window = do_QueryWrapper(aCx, global);
MOZ_ASSERT(window, "Should have a non-null window");
- nsIDocument* document = window->GetDoc();
+ nsDocument* document = static_cast<nsDocument*>(window->GetDoc());
// Function name is the type of the custom element.
JSString* jsFunName =
JS_GetFunctionId(JS_ValueToFunction(aCx, args.calleev()));
nsDependentJSString elemName;
if (!elemName.init(aCx, jsFunName)) {
- return false;
- }
+ return true;
+ }
+
+ nsCOMPtr<nsIAtom> typeAtom(do_GetAtom(elemName));
+ CustomElementHashKey key(kNameSpaceID_None, typeAtom);
+ CustomElementDefinition* definition;
+ if (!document->mRegistry->mCustomDefinitions.Get(&key, &definition)) {
+ return true;
+ }
+
+ nsDependentAtomString localName(definition->mLocalName);
nsCOMPtr<nsIContent> newElement;
- nsresult rv = document->CreateElem(elemName, nullptr, kNameSpaceID_XHTML,
+ nsresult rv = document->CreateElem(localName, nullptr,
+ definition->mNamespaceID,
getter_AddRefs(newElement));
+ NS_ENSURE_SUCCESS(rv, true);
+
+ ErrorResult errorResult;
+ nsCOMPtr<Element> element = do_QueryInterface(newElement);
+ document->SwizzleCustomElement(element, elemName, definition->mNamespaceID,
+ errorResult);
+ if (errorResult.Failed()) {
+ return true;
+ }
+
rv = nsContentUtils::WrapNative(aCx, global, newElement, newElement,
args.rval());
- NS_ENSURE_SUCCESS(rv, false);
+ NS_ENSURE_SUCCESS(rv, true);
return true;
}
+nsresult
+nsDocument::RegisterUnresolvedElement(Element* aElement, nsIAtom* aTypeName)
+{
+ if (!mRegistry) {
+ return NS_OK;
+ }
+
+ nsINodeInfo* info = aElement->NodeInfo();
+
+ // Candidate may be a custom element through extension,
+ // in which case the custom element type name will not
+ // match the element tag name. e.g. <button is="x-button">.
+ nsCOMPtr<nsIAtom> typeName = aTypeName;
+ if (!typeName) {
+ typeName = info->NameAtom();
+ }
+
+ CustomElementHashKey key(info->NamespaceID(), typeName);
+ if (mRegistry->mCustomDefinitions.Get(&key)) {
+ return NS_OK;
+ }
+
+ nsTArray<nsRefPtr<Element>>* unresolved;
+ mRegistry->mCandidatesMap.Get(&key, &unresolved);
+ if (!unresolved) {
+ unresolved = new nsTArray<nsRefPtr<Element>>();
+ // Ownership of unresolved is taken by mCandidatesMap.
+ mRegistry->mCandidatesMap.Put(&key, unresolved);
+ }
+
+ nsRefPtr<Element>* elem = unresolved->AppendElement();
+ *elem = aElement;
+
+ return NS_OK;
+}
+
+namespace {
+
+class ProcessStackRunner MOZ_FINAL : public nsIRunnable
+{
+ public:
+ ProcessStackRunner(bool aIsBaseQueue = false)
+ : mIsBaseQueue(aIsBaseQueue)
+ {
+ }
+ NS_DECL_ISUPPORTS
+ NS_IMETHOD Run() MOZ_OVERRIDE
+ {
+ nsDocument::ProcessTopElementQueue(mIsBaseQueue);
+ return NS_OK;
+ }
+ bool mIsBaseQueue;
+};
+
+NS_IMPL_ISUPPORTS1(ProcessStackRunner, nsIRunnable);
+
+} // anonymous namespace
+
+void
+nsDocument::EnqueueLifecycleCallback(nsIDocument::ElementCallbackType aType,
+ Element* aCustomElement,
+ LifecycleCallbackArgs* aArgs,
+ CustomElementDefinition* aDefinition)
+{
+ if (!mRegistry) {
+ // The element might not belong to a document that
+ // has a browsing context, and thus no registry.
+ return;
+ }
+
+ CustomElementData* elementData = aCustomElement->GetCustomElementData();
+
+ // Let DEFINITION be ELEMENT's definition
+ CustomElementDefinition* definition = aDefinition;
+ if (!definition) {
+ nsINodeInfo* info = aCustomElement->NodeInfo();
+
+ // Make sure we get the correct definition in case the element
+ // is a extended custom element e.g. <button is="x-button">.
+ nsCOMPtr<nsIAtom> typeAtom = elementData ?
+ elementData->mType.get() : info->NameAtom();
+
+ CustomElementHashKey key(info->NamespaceID(), typeAtom);
+ if (!mRegistry->mCustomDefinitions.Get(&key, &definition) ||
+ definition->mLocalName != info->NameAtom()) {
+ // Trying to enqueue a callback for an element that is not
+ // a custom element. We are done, nothing to do.
+ return;
+ }
+ }
+
+ if (!elementData) {
+ // Create the custom element data the first time
+ // that we try to enqueue a callback.
+ elementData = new CustomElementData(definition->mType);
+ // aCustomElement takes ownership of elementData
+ aCustomElement->SetCustomElementData(elementData);
+ MOZ_ASSERT(aType == nsIDocument::eCreated,
+ "First callback should be the created callback");
+ }
+
+ // Let CALLBACK be the callback associated with the key NAME in CALLBACKS.
+ CallbackFunction* func = nullptr;
+ switch (aType) {
+ case nsIDocument::eCreated:
+ if (definition->mCallbacks->mCreatedCallback.WasPassed()) {
+ func = definition->mCallbacks->mCreatedCallback.Value();
+ }
+ break;
+
+ case nsIDocument::eEnteredView:
+ if (definition->mCallbacks->mEnteredViewCallback.WasPassed()) {
+ func = definition->mCallbacks->mEnteredViewCallback.Value();
+ }
+ break;
+
+ case nsIDocument::eLeftView:
+ if (definition->mCallbacks->mLeftViewCallback.WasPassed()) {
+ func = definition->mCallbacks->mLeftViewCallback.Value();
+ }
+ break;
+
+ case nsIDocument::eAttributeChanged:
+ if (definition->mCallbacks->mAttributeChangedCallback.WasPassed()) {
+ func = definition->mCallbacks->mAttributeChangedCallback.Value();
+ }
+ break;
+ }
+
+ // If there is no such callback, stop.
+ if (!func) {
+ return;
+ }
+
+ if (aType == nsIDocument::eCreated) {
+ elementData->mCreatedCallbackInvoked = false;
+ } else if (!elementData->mCreatedCallbackInvoked) {
+ // Callbacks other than created callback must not be enqueued
+ // until after the created callback has been invoked.
+ return;
+ }
+
+ // Add CALLBACK to ELEMENT's callback queue.
+ CustomElementCallback* callback = new CustomElementCallback(aCustomElement,
+ aType,
+ func,
+ elementData);
+ // Ownership of callback is taken by mCallbackQueue.
+ elementData->mCallbackQueue.AppendElement(callback);
+ if (aArgs) {
+ callback->SetArgs(*aArgs);
+ }
+
+ if (!elementData->mElementIsBeingCreated) {
+ CustomElementData* lastData =
+ sProcessingStack.ref().SafeLastElement(nullptr);
+
+ // A new element queue needs to be pushed if the queue at the
+ // top of the stack is associated with another microtask level.
+ // Don't push a queue for the level 0 microtask (base element queue)
+ // because we don't want to process the queue until the
+ // microtask checkpoint.
+ bool shouldPushElementQueue = nsContentUtils::MicroTaskLevel() > 0 &&
+ (!lastData || lastData->mAssociatedMicroTask <
+ static_cast<int32_t>(nsContentUtils::MicroTaskLevel()));
+
+ // Push a new element queue onto the processing stack when appropriate
+ // (when we enter a new microtask).
+ if (shouldPushElementQueue) {
+ // Push a sentinel value on the processing stack to mark the
+ // boundary between the element queues.
+ sProcessingStack.ref().AppendElement((CustomElementData*) nullptr);
+ }
+
+ sProcessingStack.ref().AppendElement(elementData);
+ elementData->mAssociatedMicroTask =
+ static_cast<int32_t>(nsContentUtils::MicroTaskLevel());
+
+ // Add a script runner to pop and process the element queue at
+ // the top of the processing stack.
+ if (shouldPushElementQueue) {
+ // Lifecycle callbacks enqueued by user agent implementation
+ // should be invoked prior to returning control back to script.
+ // Create a script runner to process the top of the processing
+ // stack as soon as it is safe to run script.
+ nsContentUtils::AddScriptRunner(new ProcessStackRunner());
+ }
+ }
+}
+
+// static
+void
+nsDocument::ProcessBaseElementQueue()
+{
+ // Prevent re-entrance. Also, if a microtask checkpoint is reached
+ // and there is no processing stack to process, then we are done.
+ if (sProcessingBaseElementQueue || sProcessingStack.empty()) {
+ return;
+ }
+
+ MOZ_ASSERT(nsContentUtils::MicroTaskLevel() == 0);
+ sProcessingBaseElementQueue = true;
+ nsContentUtils::AddScriptRunner(new ProcessStackRunner(true));
+}
+
+// static
+void
+nsDocument::ProcessTopElementQueue(bool aIsBaseQueue)
+{
+ MOZ_ASSERT(nsContentUtils::IsSafeToRunScript());
+
+ nsTArray<CustomElementData*>& stack = sProcessingStack.ref();
+ uint32_t firstQueue = stack.LastIndexOf((CustomElementData*) nullptr);
+
+ if (aIsBaseQueue && firstQueue != 0) {
+ return;
+ }
+
+ for (uint32_t i = firstQueue + 1; i < stack.Length(); ++i) {
+ // Callback queue may have already been processed in an earlier
+ // element queue or in an element queue that was popped
+ // off more recently.
+ if (stack[i]->mAssociatedMicroTask != -1) {
+ stack[i]->RunCallbackQueue();
+ stack[i]->mAssociatedMicroTask = -1;
+ }
+ }
+
+ // If this was actually the base element queue, don't bother trying to pop
+ // the first "queue" marker (sentinel).
+ if (firstQueue != 0) {
+ stack.SetLength(firstQueue);
+ } else {
+ // Don't pop sentinel for base element queue.
+ stack.SetLength(1);
+ sProcessingBaseElementQueue = false;
+ }
+}
+
bool
nsDocument::RegisterEnabled()
{
static bool sPrefValue =
Preferences::GetBool("dom.webcomponents.enabled", false);
return sPrefValue;
}
+// static
+Maybe<nsTArray<mozilla::dom::CustomElementData*>>
+nsDocument::sProcessingStack;
+
+// static
+bool
+nsDocument::sProcessingBaseElementQueue;
+
JSObject*
-nsDocument::Register(JSContext* aCx, const nsAString& aName,
- const ElementRegistrationOptions& aOptions,
- ErrorResult& rv)
-{
+nsDocument::RegisterElement(JSContext* aCx, const nsAString& aType,
+ const ElementRegistrationOptions& aOptions,
+ ErrorResult& rv)
+{
+ if (!mRegistry) {
+ rv.Throw(NS_ERROR_DOM_NOT_SUPPORTED_ERR);
+ return nullptr;
+ }
+
+ Registry::DefinitionMap& definitions = mRegistry->mCustomDefinitions;
+
+ // Unconditionally convert TYPE to lowercase.
+ nsAutoString lcType;
+ nsContentUtils::ASCIIToLower(aType, lcType);
+
+ // Only convert NAME to lowercase in HTML documents. Note that NAME is
+ // options.extends.
nsAutoString lcName;
- nsContentUtils::ASCIIToLower(aName, lcName);
- if (!StringBeginsWith(lcName, NS_LITERAL_STRING("x-"))) {
- rv.Throw(NS_ERROR_DOM_INVALID_CHARACTER_ERR);
+ if (IsHTML()) {
+ nsContentUtils::ASCIIToLower(aOptions.mExtends, lcName);
+ } else {
+ lcName.Assign(aOptions.mExtends);
+ }
+
+ nsCOMPtr<nsIAtom> typeAtom(do_GetAtom(lcType));
+ if (!nsContentUtils::IsCustomElementName(typeAtom)) {
+ rv.Throw(NS_ERROR_DOM_SYNTAX_ERR);
return nullptr;
}
- if (NS_FAILED(nsContentUtils::CheckQName(lcName, false))) {
- rv.Throw(NS_ERROR_DOM_INVALID_CHARACTER_ERR);
+
+ // If there already exists a definition with the same TYPE, set ERROR to
+ // DuplicateDefinition and stop.
+ // Note that we need to find existing custom elements from either namespace.
+ CustomElementHashKey duplicateFinder(kNameSpaceID_None, typeAtom);
+ if (definitions.Get(&duplicateFinder)) {
+ rv.Throw(NS_ERROR_DOM_NOT_SUPPORTED_ERR);
return nullptr;
}
nsIGlobalObject* sgo = GetScopeObject();
if (!sgo) {
rv.Throw(NS_ERROR_UNEXPECTED);
return nullptr;
}
@@ -5276,119 +5820,181 @@ nsDocument::Register(JSContext* aCx, con
JS::Handle<JSObject*> htmlProto(
HTMLElementBinding::GetProtoObject(aCx, global));
if (!htmlProto) {
rv.Throw(NS_ERROR_OUT_OF_MEMORY);
return nullptr;
}
+ int32_t namespaceID = kNameSpaceID_XHTML;
JS::Rooted<JSObject*> protoObject(aCx);
if (!aOptions.mPrototype) {
protoObject = JS_NewObject(aCx, nullptr, htmlProto, JS::NullPtr());
if (!protoObject) {
rv.Throw(NS_ERROR_UNEXPECTED);
return nullptr;
}
} else {
- // If a prototype is provided, we must check to ensure that it inherits
- // from HTMLElement.
+ // If a prototype is provided, we must check to ensure that it is from the
+ // same browsing context as us.
protoObject = aOptions.mPrototype;
- if (!JS_WrapObject(aCx, &protoObject)) {
+ if (JS_GetGlobalForObject(aCx, protoObject) != global) {
+ rv.Throw(NS_ERROR_DOM_NOT_SUPPORTED_ERR);
+ return nullptr;
+ }
+
+ // If PROTOTYPE is already an interface prototype object for any interface
+ // object or PROTOTYPE has a non-configurable property named constructor,
+ // throw a NotSupportedError and stop.
+ const js::Class* clasp = js::GetObjectClass(protoObject);
+ if (IsDOMIfaceAndProtoClass(clasp)) {
+ rv.Throw(NS_ERROR_DOM_NOT_SUPPORTED_ERR);
+ return nullptr;
+ }
+
+ JS::Rooted<JSPropertyDescriptor> descRoot(aCx);
+ JS::MutableHandle<JSPropertyDescriptor> desc(&descRoot);
+ if(!JS_GetPropertyDescriptor(aCx, protoObject, "constructor", 0, desc)) {
rv.Throw(NS_ERROR_UNEXPECTED);
return nullptr;
}
- // Check the proto chain for HTMLElement prototype.
- JS::Rooted<JSObject*> protoProto(aCx);
- if (!JS_GetPrototype(aCx, protoObject, &protoProto)) {
- rv.Throw(NS_ERROR_UNEXPECTED);
+ // Check if non-configurable
+ if (desc.isPermanent()) {
+ rv.Throw(NS_ERROR_DOM_NOT_SUPPORTED_ERR);
return nullptr;
}
+
+ JS::Handle<JSObject*> svgProto(
+ SVGElementBinding::GetProtoObject(aCx, global));
+ if (!svgProto) {
+ rv.Throw(NS_ERROR_OUT_OF_MEMORY);
+ return nullptr;
+ }
+
+ JS::Rooted<JSObject*> protoProto(aCx, protoObject);
+
+ // If PROTOTYPE's interface inherits from SVGElement, set NAMESPACE to SVG
+ // Namespace.
while (protoProto) {
if (protoProto == htmlProto) {
break;
}
+
+ if (protoProto == svgProto) {
+ namespaceID = kNameSpaceID_SVG;
+ break;
+ }
+
if (!JS_GetPrototype(aCx, protoProto, &protoProto)) {
rv.Throw(NS_ERROR_UNEXPECTED);
return nullptr;
}
}
-
- if (!protoProto) {
- rv.Throw(NS_ERROR_DOM_TYPE_MISMATCH_ERR);
+ }
+
+ // If name was provided and not null...
+ nsCOMPtr<nsIAtom> nameAtom;
+ if (!lcName.IsEmpty()) {
+ // Let BASE be the element interface for NAME and NAMESPACE.
+ bool known = false;
+ nameAtom = do_GetAtom(lcName);
+ if (namespaceID == kNameSpaceID_XHTML) {
+ nsIParserService* ps = nsContentUtils::GetParserService();
+ if (!ps) {
+ rv.Throw(NS_ERROR_UNEXPECTED);
+ return nullptr;
+ }
+
+ known =
+ ps->HTMLCaseSensitiveAtomTagToId(nameAtom) != eHTMLTag_userdefined;
+ } else {
+ known = SVGElementFactory::Exists(nameAtom);
+ }
+
+ // If BASE does not exist or is an interface for a custom element, set ERROR
+ // to InvalidName and stop.
+ // If BASE exists, then it cannot be an interface for a custom element.
+ if (!known) {
+ rv.Throw(NS_ERROR_DOM_SYNTAX_ERR);
return nullptr;
}
- }
-
- // Associate the prototype with the custom element.
- mCustomPrototypes.Put(lcName, protoObject);
+ } else {
+ // If NAMESPACE is SVG Namespace, set ERROR to InvalidName and stop.
+ if (namespaceID == kNameSpaceID_SVG) {
+ rv.Throw(NS_ERROR_UNEXPECTED);
+ return nullptr;
+ }
+
+ nameAtom = typeAtom;
+ }
+
+ nsAutoPtr<LifecycleCallbacks> callbacksHolder(new LifecycleCallbacks());
+ JS::RootedValue rootedv(aCx, JS::ObjectValue(*protoObject));
+ if (!callbacksHolder->Init(aCx, rootedv)) {
+ return nullptr;
+ }
+
+ // Associate the definition with the custom element.
+ CustomElementHashKey key(namespaceID, typeAtom);
+ LifecycleCallbacks* callbacks = callbacksHolder.forget();
+ CustomElementDefinition* definition =
+ new CustomElementDefinition(protoObject,
+ typeAtom,
+ nameAtom,
+ callbacks,
+ namespaceID,
+ 0 /* TODO dependent on HTML imports. Bug 877072 */);
+ definitions.Put(&key, definition);
// Do element upgrade.
- nsRefPtr<nsContentList> list = GetElementsByTagName(lcName);
- for (uint32_t i = 0; i < list->Length(false); i++) {
- nsCOMPtr<nsINode> oldNode = list->Item(i, false);
-
- // TODO(wchen): Perform upgrade on Shadow DOM when implemented.
- // Bug 806506.
- nsCOMPtr<nsINode> newNode;
- rv = nsNodeUtils::Clone(oldNode, true, getter_AddRefs(newNode));
- if (rv.Failed()) {
- return nullptr;
- }
-
- nsINode* parentNode = oldNode->GetParentNode();
- MOZ_ASSERT(parentNode, "Node obtained by GetElementsByTagName.");
- nsCOMPtr<Element> newElement = do_QueryInterface(newNode);
- MOZ_ASSERT(newElement, "Cloned of node obtained by GetElementsByTagName.");
-
- parentNode->ReplaceChild(*newNode, *oldNode, rv);
- if (rv.Failed()) {
- return nullptr;
- }
-
- // Dispatch elementreplaced to replaced elements.
- nsCOMPtr<nsIDOMEvent> event;
- rv = CreateEvent(NS_LITERAL_STRING("elementreplace"), getter_AddRefs(event));
- if (rv.Failed()) {
- return nullptr;
- }
-
- if (aOptions.mLifecycle.mCreated) {
- // Don't abort the upgrade algorithm if the callback throws an
- // exception.
- ErrorResult dummy;
- aOptions.mLifecycle.mCreated->Call(newElement, dummy);
- }
-
- nsCOMPtr<nsIDOMElementReplaceEvent> ptEvent = do_QueryInterface(event);
- MOZ_ASSERT(ptEvent);
-
- nsCOMPtr<nsIDOMElement> element = do_QueryInterface(newElement);
- rv = ptEvent->InitElementReplaceEvent(NS_LITERAL_STRING("elementreplace"),
- false, false, element);
- if (rv.Failed()) {
- return nullptr;
- }
-
- event->SetTrusted(true);
- event->SetTarget(oldNode);
- nsEventDispatcher::DispatchDOMEvent(oldNode, nullptr, event,
- nullptr, nullptr);
- }
-
- nsContentUtils::DispatchTrustedEvent(this, static_cast<nsIDocument*>(this),
- NS_LITERAL_STRING("elementupgrade"),
- true, true);
+ nsAutoPtr<nsTArray<nsRefPtr<Element>>> candidates;
+ mRegistry->mCandidatesMap.RemoveAndForget(&key, candidates);
+ if (candidates) {
+ for (size_t i = 0; i < candidates->Length(); ++i) {
+ Element *elem = candidates->ElementAt(i);
+
+ // Make sure that the element name matches the name in the definition.
+ // (e.g. a definition for x-button extending button should match
+ // <button is="x-button"> but not <x-button>.
+ if (elem->NodeInfo()->NameAtom() != nameAtom) {
+ // Skip over this element because definition does not apply.
+ continue;
+ }
+
+ nsWrapperCache* cache;
+ CallQueryInterface(elem, &cache);
+ MOZ_ASSERT(cache, "Element doesn't support wrapper cache?");
+
+ JS::RootedObject wrapper(aCx);
+ if ((wrapper = cache->GetWrapper())) {
+ if (!JS_SetPrototype(aCx, wrapper, protoObject)) {
+ continue;
+ }
+ }
+
+ EnqueueLifecycleCallback(nsIDocument::eCreated, elem, nullptr, definition);
+ if (elem->GetCurrentDoc()) {
+ // Normally callbacks can not be enqueued until the created
+ // callback has been invoked, however, the entered view callback
+ // in element upgrade is an exception so pretend the created
+ // callback has been invoked.
+ elem->GetCustomElementData()->mCreatedCallbackInvoked = true;
+
+ EnqueueLifecycleCallback(nsIDocument::eEnteredView, elem, nullptr, definition);
+ }
+ }
+ }
// Create constructor to return. Store the name of the custom element as the
// name of the function.
- JSFunction* constructor = JS_NewFunction(aCx, CustomElementConstructor, 0,
+ JSFunction* constructor = JS_NewFunction(aCx, nsDocument::CustomElementConstructor, 0,
JSFUN_CONSTRUCTOR, JS::NullPtr(),
- NS_ConvertUTF16toUTF8(lcName).get());
+ NS_ConvertUTF16toUTF8(lcType).get());
JSObject* constructorObject = JS_GetFunctionObject(constructor);
return constructorObject;
}
NS_IMETHODIMP
nsDocument::GetElementsByTagName(const nsAString& aTagname,
nsIDOMNodeList** aReturn)
{
@@ -7846,17 +8452,19 @@ nsDocument::Destroy()
mLayoutHistoryState = nullptr;
// Shut down our external resource map. We might not need this for
// leak-fixing if we fix nsDocumentViewer to do cycle-collection, but
// tearing down all those frame trees right now is the right thing to do.
mExternalResourceMap.Shutdown();
- mCustomPrototypes.Clear();
+ if (mRegistry) {
+ mRegistry->Clear();
+ }
// XXX We really should let cycle collection do this, but that currently still
// leaks (see https://bugzilla.mozilla.org/show_bug.cgi?id=406684).
ReleaseWrapper(static_cast<nsINode*>(this));
}
void
nsDocument::RemovedFromDocShell()
@@ -11102,16 +11710,17 @@ nsIDocument::GetMozPointerLockElement()
return pointerLockedElement;
}
void
nsDocument::XPCOMShutdown()
{
gPendingPointerLockRequest = nullptr;
+ sProcessingStack.destroyIfConstructed();
}
void
nsDocument::UpdateVisibilityState()
{
dom::VisibilityState oldState = mVisibilityState;
mVisibilityState = GetVisibilityState();
if (oldState != mVisibilityState) {
--- a/content/base/src/nsDocument.h
+++ b/content/base/src/nsDocument.h
@@ -1,9 +1,10 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* vim: set ts=2 sw=2 et 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/. */
/*
* Base class for all our document implementations.
*/
@@ -94,16 +95,18 @@ class nsWindowSizes;
class nsHtml5TreeOpExecutor;
class nsDocumentOnStack;
class nsPointerLockPermissionRequest;
class nsISecurityConsoleMessage;
namespace mozilla {
namespace dom {
class UndoManager;
+class LifecycleCallbacks;
+class CallbackFunction;
}
}
/**
* Right now our identifier map entries contain information for 'name'
* and 'id' mappings of a given string. This is so that
* nsHTMLDocument::ResolveName only has to do one hash lookup instead
* of two. It's not clear whether this still matters for performance.
@@ -232,16 +235,163 @@ private:
// empty if there are no elements with this ID.
// The elements are stored as weak pointers.
nsSmallVoidArray mIdContentList;
nsRefPtr<nsBaseContentList> mNameContentList;
nsAutoPtr<nsTHashtable<ChangeCallbackEntry> > mChangeCallbacks;
nsRefPtr<Element> mImageElement;
};
+namespace mozilla {
+namespace dom {
+
+class CustomElementHashKey : public PLDHashEntryHdr
+{
+public:
+ typedef CustomElementHashKey *KeyType;
+ typedef const CustomElementHashKey *KeyTypePointer;
+
+ CustomElementHashKey(int32_t aNamespaceID, nsIAtom *aAtom)
+ : mNamespaceID(aNamespaceID),
+ mAtom(aAtom)
+ {}
+ CustomElementHashKey(const CustomElementHashKey *aKey)
+ : mNamespaceID(aKey->mNamespaceID),
+ mAtom(aKey->mAtom)
+ {}
+ ~CustomElementHashKey()
+ {}
+
+ KeyType GetKey() const { return const_cast<KeyType>(this); }
+ bool KeyEquals(const KeyTypePointer aKey) const
+ {
+ MOZ_ASSERT(mNamespaceID != kNameSpaceID_None,
+ "This equals method is not transitive, nor symmetric. "
+ "A key with a namespace of kNamespaceID_None should "
+ "not be stored in a hashtable.");
+ return (kNameSpaceID_None == aKey->mNamespaceID ||
+ mNamespaceID == aKey->mNamespaceID) &&
+ aKey->mAtom == mAtom;
+ }
+
+ static KeyTypePointer KeyToPointer(KeyType aKey) { return aKey; }
+ static PLDHashNumber HashKey(const KeyTypePointer aKey)
+ {
+ return aKey->mAtom->hash();
+ }
+ enum { ALLOW_MEMMOVE = true };
+
+private:
+ int32_t mNamespaceID;
+ nsCOMPtr<nsIAtom> mAtom;
+};
+
+struct LifecycleCallbackArgs
+{
+ nsString name;
+ nsString oldValue;
+ nsString newValue;
+};
+
+struct CustomElementData;
+
+class CustomElementCallback
+{
+public:
+ CustomElementCallback(Element* aThisObject,
+ nsIDocument::ElementCallbackType aCallbackType,
+ mozilla::dom::CallbackFunction* aCallback,
+ CustomElementData* aOwnerData);
+ void Traverse(nsCycleCollectionTraversalCallback& aCb) const;
+ void Call();
+ void SetArgs(LifecycleCallbackArgs& aArgs)
+ {
+ MOZ_ASSERT(mType == nsIDocument::eAttributeChanged,
+ "Arguments are only used by attribute changed callback.");
+ mArgs = aArgs;
+ }
+
+private:
+ // The this value to use for invocation of the callback.
+ nsRefPtr<mozilla::dom::Element> mThisObject;
+ nsRefPtr<mozilla::dom::CallbackFunction> mCallback;
+ // The type of callback (eCreated, eEnteredView, etc.)
+ nsIDocument::ElementCallbackType mType;
+ // Arguments to be passed to the callback,
+ // used by the attribute changed callback.
+ LifecycleCallbackArgs mArgs;
+ // CustomElementData that contains this callback in the
+ // callback queue.
+ CustomElementData* mOwnerData;
+};
+
+// Each custom element has an associated callback queue and an element is
+// being created flag.
+struct CustomElementData
+{
+ CustomElementData(nsIAtom* aType);
+ // Objects in this array are transient and empty after each microtask
+ // checkpoint.
+ nsTArray<nsAutoPtr<CustomElementCallback>> mCallbackQueue;
+ // Custom element type, for <button is="x-button"> or <x-button>
+ // this would be x-button.
+ nsCOMPtr<nsIAtom> mType;
+ // The callback that is next to be processed upon calling RunCallbackQueue.
+ int32_t mCurrentCallback;
+ // Element is being created flag as described in the custom elements spec.
+ bool mElementIsBeingCreated;
+ // Flag to determine if the created callback has been invoked, thus it
+ // determines if other callbacks can be enqueued.
+ bool mCreatedCallbackInvoked;
+ // The microtask level associated with the callbacks in the callback queue,
+ // it is used to determine if a new queue needs to be pushed onto the
+ // processing stack.
+ int32_t mAssociatedMicroTask;
+
+ // Empties the callback queue.
+ void RunCallbackQueue();
+};
+
+// The required information for a custom element as defined in:
+// https://dvcs.w3.org/hg/webcomponents/raw-file/tip/spec/custom/index.html
+struct CustomElementDefinition
+{
+ CustomElementDefinition(JSObject* aPrototype,
+ nsIAtom* aType,
+ nsIAtom* aLocalName,
+ mozilla::dom::LifecycleCallbacks* aCallbacks,
+ uint32_t aNamespaceID,
+ uint32_t aDocOrder);
+
+ // The prototype to use for new custom elements of this type.
+ JS::Heap<JSObject *> mPrototype;
+
+ // The type (name) for this custom element.
+ nsCOMPtr<nsIAtom> mType;
+
+ // The localname to (e.g. <button is=type> -- this would be button).
+ nsCOMPtr<nsIAtom> mLocalName;
+
+ // The lifecycle callbacks to call for this custom element.
+ nsAutoPtr<mozilla::dom::LifecycleCallbacks> mCallbacks;
+
+ // Whether we're currently calling the created callback for a custom element
+ // of this type.
+ bool mElementIsBeingCreated;
+
+ // Element namespace.
+ int32_t mNamespaceID;
+
+ // The document custom element order.
+ uint32_t mDocOrder;
+};
+
+} // namespace dom
+} // namespace mozilla
+
class nsDocHeaderData
{
public:
nsDocHeaderData(nsIAtom* aField, const nsAString& aData)
: mField(aField), mData(aData), mNext(nullptr)
{
}
@@ -991,35 +1141,67 @@ public:
// Posts an event to call UpdateVisibilityState
virtual void PostVisibilityUpdateEvent() MOZ_OVERRIDE;
virtual void DocAddSizeOfExcludingThis(nsWindowSizes* aWindowSizes) const MOZ_OVERRIDE;
// DocAddSizeOfIncludingThis is inherited from nsIDocument.
virtual nsIDOMNode* AsDOMNode() MOZ_OVERRIDE { return this; }
- void GetCustomPrototype(const nsAString& aElementName, JS::MutableHandle<JSObject*> prototype)
+ virtual void EnqueueLifecycleCallback(nsIDocument::ElementCallbackType aType,
+ Element* aCustomElement,
+ mozilla::dom::LifecycleCallbackArgs* aArgs = nullptr,
+ mozilla::dom::CustomElementDefinition* aDefinition = nullptr) MOZ_OVERRIDE;
+
+ static void ProcessTopElementQueue(bool aIsBaseQueue = false);
+
+ void GetCustomPrototype(int32_t aNamespaceID,
+ nsIAtom* aAtom,
+ JS::MutableHandle<JSObject*> prototype)
{
- mCustomPrototypes.Get(aElementName, prototype.address());
+ if (!mRegistry) {
+ prototype.set(nullptr);
+ return;
+ }
+
+ mozilla::dom::CustomElementHashKey key(aNamespaceID, aAtom);
+ mozilla::dom::CustomElementDefinition* definition;
+ if (mRegistry->mCustomDefinitions.Get(&key, &definition)) {
+ prototype.set(definition->mPrototype);
+ } else {
+ prototype.set(nullptr);
+ }
}
static bool RegisterEnabled();
+ virtual nsresult RegisterUnresolvedElement(mozilla::dom::Element* aElement,
+ nsIAtom* aTypeName = nullptr) MOZ_OVERRIDE;
+
// WebIDL bits
virtual mozilla::dom::DOMImplementation*
GetImplementation(mozilla::ErrorResult& rv) MOZ_OVERRIDE;
virtual JSObject*
- Register(JSContext* aCx, const nsAString& aName,
- const mozilla::dom::ElementRegistrationOptions& aOptions,
- mozilla::ErrorResult& rv) MOZ_OVERRIDE;
+ RegisterElement(JSContext* aCx, const nsAString& aName,
+ const mozilla::dom::ElementRegistrationOptions& aOptions,
+ mozilla::ErrorResult& rv) MOZ_OVERRIDE;
virtual nsIDOMStyleSheetList* StyleSheets() MOZ_OVERRIDE;
virtual void SetSelectedStyleSheetSet(const nsAString& aSheetSet) MOZ_OVERRIDE;
virtual void GetLastStyleSheetSet(nsString& aSheetSet) MOZ_OVERRIDE;
virtual nsIDOMDOMStringList* StyleSheetSets() MOZ_OVERRIDE;
virtual void EnableStyleSheetsForSet(const nsAString& aSheetSet) MOZ_OVERRIDE;
+ using nsIDocument::CreateElement;
+ using nsIDocument::CreateElementNS;
+ virtual already_AddRefed<Element> CreateElement(const nsAString& aTagName,
+ const nsAString& aTypeExtension,
+ mozilla::ErrorResult& rv) MOZ_OVERRIDE;
+ virtual already_AddRefed<Element> CreateElementNS(const nsAString& aNamespaceURI,
+ const nsAString& aQualifiedName,
+ const nsAString& aTypeExtension,
+ mozilla::ErrorResult& rv) MOZ_OVERRIDE;
protected:
friend class nsNodeUtils;
friend class nsDocumentOnStack;
void IncreaseStackRefCnt()
{
++mStackRefCnt;
@@ -1170,19 +1352,69 @@ protected:
// full-screen element onto this stack, and when we cancel full-screen we
// pop one off this stack, restoring the previous full-screen state
nsTArray<nsWeakPtr> mFullScreenStack;
// The root of the doc tree in which this document is in. This is only
// non-null when this document is in fullscreen mode.
nsWeakPtr mFullscreenRoot;
- // Hashtable for custom element prototypes in web components.
- // Custom prototypes are in the document's compartment.
- nsJSThingHashtable<nsStringHashKey, JSObject*> mCustomPrototypes;
+private:
+ struct Registry
+ {
+ NS_INLINE_DECL_REFCOUNTING(Registry)
+
+ typedef nsClassHashtable<mozilla::dom::CustomElementHashKey,
+ mozilla::dom::CustomElementDefinition>
+ DefinitionMap;
+ typedef nsClassHashtable<mozilla::dom::CustomElementHashKey,
+ nsTArray<nsRefPtr<mozilla::dom::Element>>>
+ CandidateMap;
+
+ // Hashtable for custom element definitions in web components.
+ // Custom prototypes are in the document's compartment.
+ DefinitionMap mCustomDefinitions;
+
+ // The "upgrade candidates map" from the web components spec. Maps from a
+ // namespace id and local name to a list of elements to upgrade if that
+ // element is registered as a custom element.
+ CandidateMap mCandidatesMap;
+
+ void Clear()
+ {
+ mCustomDefinitions.Clear();
+ mCandidatesMap.Clear();
+ }
+ };
+
+ // Array representing the processing stack in the custom elements
+ // specification. The processing stack is conceptually a stack of
+ // element queues. Each queue is represented by a sequence of
+ // CustomElementData in this array, separated by nullptr that
+ // represent the boundaries of the items in the stack. The first
+ // queue in the stack is the base element queue.
+ static mozilla::Maybe<nsTArray<mozilla::dom::CustomElementData*>> sProcessingStack;
+
+ // Flag to prevent re-entrance into base element queue as described in the
+ // custom elements speicification.
+ static bool sProcessingBaseElementQueue;
+
+ static bool CustomElementConstructor(JSContext* aCx, unsigned aArgc, JS::Value* aVp);
+
+public:
+ static void ProcessBaseElementQueue();
+
+ // Modify the prototype and "is" attribute of newly created custom elements.
+ virtual void SwizzleCustomElement(Element* aElement,
+ const nsAString& aTypeExtension,
+ uint32_t aNamespaceID,
+ mozilla::ErrorResult& rv);
+
+ // The "registry" from the web components spec.
+ nsRefPtr<Registry> mRegistry;
nsRefPtr<nsEventListenerManager> mListenerManager;
nsCOMPtr<nsIDOMStyleSheetList> mDOMStyleSheets;
nsRefPtr<nsDOMStyleSheetSetList> mStyleSheetSetList;
nsRefPtr<nsScriptLoader> mScriptLoader;
nsDocHeaderData* mHeaderData;
/* mIdentifierMap works as follows for IDs:
* 1) Attribute changes affect the table immediately (removing and adding
--- a/content/base/src/nsGenericDOMDataNode.cpp
+++ b/content/base/src/nsGenericDOMDataNode.cpp
@@ -708,16 +708,27 @@ nsGenericDOMDataNode::SetXBLInsertionPar
{
nsDataSlots *slots = DataSlots();
if (aContent) {
SetFlags(NODE_MAY_BE_IN_BINDING_MNGR);
}
slots->mXBLInsertionParent = aContent;
}
+CustomElementData *
+nsGenericDOMDataNode::GetCustomElementData() const
+{
+ return nullptr;
+}
+
+void
+nsGenericDOMDataNode::SetCustomElementData(CustomElementData* aData)
+{
+}
+
bool
nsGenericDOMDataNode::IsNodeOfType(uint32_t aFlags) const
{
return !(aFlags & ~(eCONTENT | eDATA_NODE));
}
void
nsGenericDOMDataNode::SaveSubtreeState()
--- a/content/base/src/nsGenericDOMDataNode.h
+++ b/content/base/src/nsGenericDOMDataNode.h
@@ -156,21 +156,24 @@ public:
virtual nsIContent *GetBindingParent() const MOZ_OVERRIDE;
virtual nsXBLBinding *GetXBLBinding() const MOZ_OVERRIDE;
virtual void SetXBLBinding(nsXBLBinding* aBinding,
nsBindingManager* aOldBindingManager = nullptr) MOZ_OVERRIDE;
virtual mozilla::dom::ShadowRoot *GetContainingShadow() const MOZ_OVERRIDE;
virtual mozilla::dom::ShadowRoot *GetShadowRoot() const MOZ_OVERRIDE;
virtual void SetShadowRoot(mozilla::dom::ShadowRoot* aShadowRoot) MOZ_OVERRIDE;
- virtual nsIContent *GetXBLInsertionParent() const;
- virtual void SetXBLInsertionParent(nsIContent* aContent);
+ virtual nsIContent *GetXBLInsertionParent() const MOZ_OVERRIDE;
+ virtual void SetXBLInsertionParent(nsIContent* aContent) MOZ_OVERRIDE;
virtual bool IsNodeOfType(uint32_t aFlags) const MOZ_OVERRIDE;
virtual bool IsLink(nsIURI** aURI) const MOZ_OVERRIDE;
+ virtual mozilla::dom::CustomElementData* GetCustomElementData() const MOZ_OVERRIDE;
+ virtual void SetCustomElementData(mozilla::dom::CustomElementData* aData) MOZ_OVERRIDE;
+
virtual nsIAtom* DoGetID() const MOZ_OVERRIDE;
virtual const nsAttrValue* DoGetClasses() const MOZ_OVERRIDE;
NS_IMETHOD WalkContentStyleRules(nsRuleWalker* aRuleWalker) MOZ_OVERRIDE;
NS_IMETHOD_(bool) IsAttributeMapped(const nsIAtom* aAttribute) const;
virtual nsChangeHint GetAttributeChangeHint(const nsIAtom* aAttribute,
int32_t aModType) const;
virtual nsIAtom *GetClassAttributeName() const;
--- a/content/base/src/nsGkAtomList.h
+++ b/content/base/src/nsGkAtomList.h
@@ -470,16 +470,17 @@ GK_ATOM(inputmode, "inputmode")
GK_ATOM(ins, "ins")
GK_ATOM(insertafter, "insertafter")
GK_ATOM(insertbefore, "insertbefore")
GK_ATOM(instanceOf, "instanceOf")
GK_ATOM(int32, "int32")
GK_ATOM(int64, "int64")
GK_ATOM(integer, "integer")
GK_ATOM(intersection, "intersection")
+GK_ATOM(is, "is")
GK_ATOM(iscontainer, "iscontainer")
GK_ATOM(isempty, "isempty")
GK_ATOM(ismap, "ismap")
GK_ATOM(itemid, "itemid")
GK_ATOM(itemprop, "itemprop")
GK_ATOM(itemref, "itemref")
GK_ATOM(itemscope, "itemscope")
GK_ATOM(itemtype, "itemtype")
--- a/content/base/test/chrome/test_document_register.xul
+++ b/content/base/test/chrome/test_document_register.xul
@@ -19,17 +19,17 @@ https://bugzilla.mozilla.org/show_bug.cg
<!-- test code goes here -->
<script type="application/javascript"><![CDATA[
/** Test for Bug 783129 **/
SimpleTest.waitForExplicitFinish();
function startTests() {
- var c = $("fooframe").contentDocument.register("x-foo");
+ var c = $("fooframe").contentDocument.registerElement("x-foo");
var elem = new c();
is(elem.tagName, "X-FOO", "Constructor should create an x-foo element.");
var anotherElem = $("fooframe").contentDocument.createElement("x-foo");
is(anotherElem.tagName, "X-FOO", "createElement should create an x-foo element.");
SimpleTest.finish();
}
--- a/content/html/content/src/HTMLUnknownElement.cpp
+++ b/content/html/content/src/HTMLUnknownElement.cpp
@@ -11,28 +11,15 @@
NS_IMPL_NS_NEW_HTML_ELEMENT(Unknown)
namespace mozilla {
namespace dom {
JSObject*
HTMLUnknownElement::WrapNode(JSContext *aCx, JS::Handle<JSObject*> aScope)
{
- JS::Rooted<JSObject*> obj(aCx,
- HTMLUnknownElementBinding::Wrap(aCx, aScope, this));
- if (obj && Substring(NodeName(), 0, 2).LowerCaseEqualsLiteral("x-")) {
- // If we have a registered x-tag then we fix the prototype.
- JSAutoCompartment ac(aCx, obj);
- nsDocument* document = static_cast<nsDocument*>(OwnerDoc());
- JS::Rooted<JSObject*> prototype(aCx);
- document->GetCustomPrototype(LocalName(), &prototype);
- if (prototype) {
- NS_ENSURE_TRUE(JS_WrapObject(aCx, &prototype), nullptr);
- NS_ENSURE_TRUE(JS_SetPrototype(aCx, obj, prototype), nullptr);
- }
- }
- return obj;
+ return HTMLUnknownElementBinding::Wrap(aCx, aScope, this);
}
NS_IMPL_ELEMENT_CLONE(HTMLUnknownElement)
} // namespace dom
} // namespace mozilla
--- a/content/html/content/test/test_ignoreuserfocus.html
+++ b/content/html/content/test/test_ignoreuserfocus.html
@@ -36,17 +36,17 @@
var witness = document.createElement("input");
witness.setAttribute("type", "text");
var witness2 = document.createElement("input");
witness2.setAttribute("type", "text");
var iframe = document.createElement("iframe");
iframe.setAttribute("mozbrowser", "true");
iframe.setAttribute("ignoreuserfocus", "true");
- iframe.setAttribute("height", "500px");
+ iframe.setAttribute("height", "300px");
iframe.setAttribute("src", "file_ignoreuserfocus.html");
iframe.addEventListener('load', function (e) {
// Get privileged iframe because mozbrowser iframe is not same origin
// with the parent. We need to access its content through the wrapper.
var privilegedIframe = SpecialPowers.wrap(iframe);
privilegedIframe.contentWindow.addEventListener("MozAfterPaint", function afterPaint(e) {
privilegedIframe.contentWindow.removeEventListener("MozAfterPaint", afterPaint);
@@ -97,17 +97,16 @@
isnot(document.activeElement, iframe, "[explicit innerIframe.focus()] iframe should not have the focus");
witness.focus();
synthesizeMouseAtCenter(innerIframe, {}, iframeWindow);
is(document.activeElement, witness, "[synthesize mouse click inner iframe] witness should have the focus");
// Test the case when iframe contains <area> and .focus()
// is called and explicit focus using mouse
- witness.focus();
// Wait for paint to setup frame for area. Currently the area frame
// map is reset for each paint. If we are in the middle of a paint
// then the area will not be focusable.
privilegedIframe.contentWindow.addEventListener("MozAfterPaint", function afterPaintArea(e) {
privilegedIframe.contentWindow.removeEventListener("MozAfterPaint", afterPaintArea);
var innerArea = privilegedIframe.contentDocument.getElementsByTagName("area")[0];
innerArea.focus();
@@ -121,17 +120,22 @@
witness.focus();
is(document.activeElement, witness, "witness should have the focus");
synthesizeKey("VK_TAB", {});
isnot(document.activeElement, iframe, "[synthesize tab key] iframe should not have the focus");
is(document.activeElement, witness2, "witness2 should have the focus");
SimpleTest.finish();
});
+ witness.focus();
+ // force reflow
+ var reflow = iframe.offsetLeft;
});
+ // force reflow
+ var reflow = iframe.offsetLeft;
});
document.body.appendChild(witness);
document.body.appendChild(iframe);
document.body.appendChild(witness2);
}
addEventListener("load", function() {
SpecialPowers.addPermission("browser", true, document);
--- a/content/html/document/src/nsHTMLContentSink.cpp
+++ b/content/html/document/src/nsHTMLContentSink.cpp
@@ -252,19 +252,41 @@ NS_NewHTMLElement(Element** aResult, alr
nsIParserService* parserService = nsContentUtils::GetParserService();
if (!parserService)
return NS_ERROR_OUT_OF_MEMORY;
nsIAtom *name = nodeInfo->NameAtom();
NS_ASSERTION(nodeInfo->NamespaceEquals(kNameSpaceID_XHTML),
"Trying to HTML elements that don't have the XHTML namespace");
-
- *aResult = CreateHTMLElement(parserService->
- HTMLCaseSensitiveAtomTagToId(name),
+
+ // Per the Custom Element specification, unknown tags that are valid custom
+ // element names should be HTMLElement instead of HTMLUnknownElement.
+ int32_t tag = parserService->HTMLCaseSensitiveAtomTagToId(name);
+ if (tag == eHTMLTag_userdefined &&
+ nsContentUtils::IsCustomElementName(name)) {
+ NS_IF_ADDREF(*aResult = NS_NewHTMLElement(nodeInfo.forget(), aFromParser));
+ if (!*aResult) {
+ return NS_ERROR_OUT_OF_MEMORY;
+ }
+
+ nsIDocument* doc = aNodeInfo.get()->GetDocument();
+
+ // Element may be unresolved at this point.
+ doc->RegisterUnresolvedElement(*aResult);
+
+ // Try to enqueue a created callback. The custom element data will be set
+ // and created callback will be enqueued if the custom element type
+ // has already been registered.
+ doc->EnqueueLifecycleCallback(nsIDocument::eCreated, *aResult);
+
+ return NS_OK;
+ }
+
+ *aResult = CreateHTMLElement(tag,
nodeInfo.forget(), aFromParser).get();
return *aResult ? NS_OK : NS_ERROR_OUT_OF_MEMORY;
}
already_AddRefed<nsGenericHTMLElement>
CreateHTMLElement(uint32_t aNodeType, already_AddRefed<nsINodeInfo> aNodeInfo,
FromParser aFromParser)
{
--- a/content/html/document/src/nsHTMLDocument.h
+++ b/content/html/document/src/nsHTMLDocument.h
@@ -81,16 +81,18 @@ public:
return mWriteLevel != uint32_t(0);
}
virtual NS_HIDDEN_(nsContentList*) GetForms();
virtual NS_HIDDEN_(nsContentList*) GetFormControls();
// nsIDOMDocument interface
+ using nsDocument::CreateElement;
+ using nsDocument::CreateElementNS;
NS_FORWARD_NSIDOMDOCUMENT(nsDocument::)
// And explicitly import the things from nsDocument that we just shadowed
using nsDocument::GetImplementation;
using nsDocument::GetTitle;
using nsDocument::SetTitle;
using nsDocument::GetLastStyleSheetSet;
using nsDocument::MozSetImageElement;
--- a/content/svg/content/src/SVGElementFactory.cpp
+++ b/content/svg/content/src/SVGElementFactory.cpp
@@ -98,16 +98,24 @@ void
SVGElementFactory::Shutdown()
{
if (sTagAtomTable) {
PL_HashTableDestroy(sTagAtomTable);
sTagAtomTable = nullptr;
}
}
+bool
+SVGElementFactory::Exists(nsIAtom *aTag)
+{
+ MOZ_ASSERT(sTagAtomTable, "no lookup table, needs SVGElementFactory::Init");
+ void* tag = PL_HashTableLookupConst(sTagAtomTable, aTag);
+ return tag != nullptr;
+}
+
nsresult
NS_NewSVGElement(Element** aResult, already_AddRefed<nsINodeInfo> aNodeInfo,
FromParser aFromParser)
{
NS_ASSERTION(sTagAtomTable, "no lookup table, needs SVGElementFactory::Init");
nsIAtom* name = aNodeInfo.get()->NameAtom();
--- a/content/svg/content/src/SVGElementFactory.h
+++ b/content/svg/content/src/SVGElementFactory.h
@@ -1,21 +1,25 @@
/* -*- 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_SVGElementFactory_h
#define mozilla_dom_SVGElementFactory_h
+class nsIAtom;
+
namespace mozilla {
namespace dom {
class SVGElementFactory {
public:
static void Init();
static void Shutdown();
+
+ static bool Exists(nsIAtom *aTag);
};
} // namespace dom
} // namespace mozilla
#endif /* mozilla_dom_SVGElementFactory_h */
--- a/content/xul/document/src/XULDocument.h
+++ b/content/xul/document/src/XULDocument.h
@@ -139,16 +139,18 @@ public:
// nsINode interface overrides
virtual nsresult Clone(nsINodeInfo *aNodeInfo, nsINode **aResult) const MOZ_OVERRIDE;
// nsIDOMNode interface
NS_FORWARD_NSIDOMNODE_TO_NSINODE
// nsIDOMDocument interface
+ using nsDocument::CreateElement;
+ using nsDocument::CreateElementNS;
NS_FORWARD_NSIDOMDOCUMENT(XMLDocument::)
// And explicitly import the things from nsDocument that we just shadowed
using nsDocument::GetImplementation;
using nsDocument::GetTitle;
using nsDocument::SetTitle;
using nsDocument::GetLastStyleSheetSet;
using nsDocument::MozSetImageElement;
using nsDocument::GetMozFullScreenElement;
new file mode 100644
--- /dev/null
+++ b/dom/ipc/ColorPickerParent.cpp
@@ -0,0 +1,87 @@
+/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
+ * vim: set sw=4 ts=8 et 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 "ColorPickerParent.h"
+#include "nsComponentManagerUtils.h"
+#include "nsIDocument.h"
+#include "nsIDOMWindow.h"
+#include "mozilla/unused.h"
+#include "mozilla/dom/Element.h"
+#include "mozilla/dom/TabParent.h"
+
+using mozilla::unused;
+using namespace mozilla::dom;
+
+NS_IMPL_ISUPPORTS1(ColorPickerParent::ColorPickerShownCallback,
+ nsIColorPickerShownCallback);
+
+NS_IMETHODIMP
+ColorPickerParent::ColorPickerShownCallback::Update(const nsAString& aColor)
+{
+ if (mColorPickerParent) {
+ unused << mColorPickerParent->SendUpdate(nsString(aColor));
+ }
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+ColorPickerParent::ColorPickerShownCallback::Done(const nsAString& aColor)
+{
+ if (mColorPickerParent) {
+ unused << mColorPickerParent->Send__delete__(mColorPickerParent,
+ nsString(aColor));
+ }
+ return NS_OK;
+}
+
+void
+ColorPickerParent::ColorPickerShownCallback::Destroy()
+{
+ mColorPickerParent = nullptr;
+}
+
+bool
+ColorPickerParent::CreateColorPicker()
+{
+ mPicker = do_CreateInstance("@mozilla.org/colorpicker;1");
+ if (!mPicker) {
+ return false;
+ }
+
+ Element* ownerElement = static_cast<TabParent*>(Manager())->GetOwnerElement();
+ if (!ownerElement) {
+ return false;
+ }
+
+ nsCOMPtr<nsIDOMWindow> window = do_QueryInterface(ownerElement->OwnerDoc()->GetWindow());
+ if (!window) {
+ return false;
+ }
+
+ return NS_SUCCEEDED(mPicker->Init(window, mTitle, mInitialColor));
+}
+
+bool
+ColorPickerParent::RecvOpen()
+{
+ if (!CreateColorPicker()) {
+ unused << Send__delete__(this, mInitialColor);
+ return true;
+ }
+
+ mCallback = new ColorPickerShownCallback(this);
+
+ mPicker->Open(mCallback);
+ return true;
+};
+
+void
+ColorPickerParent::ActorDestroy(ActorDestroyReason aWhy)
+{
+ if (mCallback) {
+ mCallback->Destroy();
+ }
+}
new file mode 100644
--- /dev/null
+++ b/dom/ipc/ColorPickerParent.h
@@ -0,0 +1,60 @@
+/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*-
+ * vim: set sw=4 ts=8 et 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_ColorPickerParent_h
+#define mozilla_dom_ColorPickerParent_h
+
+#include "mozilla/dom/PColorPickerParent.h"
+#include "nsIColorPicker.h"
+
+namespace mozilla {
+namespace dom {
+
+class ColorPickerParent : public PColorPickerParent
+{
+ public:
+ ColorPickerParent(const nsString& aTitle,
+ const nsString& aInitialColor)
+ : mTitle(aTitle)
+ , mInitialColor(aInitialColor)
+ {}
+
+ virtual ~ColorPickerParent() {}
+
+ virtual bool RecvOpen() MOZ_OVERRIDE;
+ virtual void ActorDestroy(ActorDestroyReason aWhy) MOZ_OVERRIDE;
+
+ class ColorPickerShownCallback MOZ_FINAL
+ : public nsIColorPickerShownCallback
+ {
+ public:
+ ColorPickerShownCallback(ColorPickerParent* aColorPickerParnet)
+ : mColorPickerParent(aColorPickerParnet)
+ {}
+
+ NS_DECL_ISUPPORTS
+ NS_DECL_NSICOLORPICKERSHOWNCALLBACK
+
+ void Destroy();
+
+ private:
+ ColorPickerParent* mColorPickerParent;
+ };
+
+ private:
+ bool CreateColorPicker();
+
+ nsRefPtr<ColorPickerShownCallback> mCallback;
+ nsCOMPtr<nsIColorPicker> mPicker;
+
+ nsString mTitle;
+ nsString mInitialColor;
+};
+
+} // namespace dom
+} // namespace mozilla
+
+#endif // mozilla_dom_ColorPickerParent_h
\ No newline at end of file
--- a/dom/ipc/PBrowser.ipdl
+++ b/dom/ipc/PBrowser.ipdl
@@ -1,16 +1,17 @@
/* -*- Mode: C++; c-basic-offset: 4; indent-tabs-mode: nil; tab-width: 8 -*- */
/* vim: set sw=4 ts=8 et tw=80 ft=cpp : */
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
include protocol PBlob;
+include protocol PColorPicker;
include protocol PContent;
include protocol PContentDialog;
include protocol PDocumentRenderer;
include protocol PContentPermissionRequest;
include protocol PFilePicker;
include protocol PRenderFrame;
include protocol POfflineCacheUpdate;
include protocol PIndexedDB;
@@ -52,16 +53,17 @@ using mozilla::CSSToScreenScale from "Un
namespace mozilla {
namespace dom {
intr protocol PBrowser
{
manager PContent;
+ manages PColorPicker;
manages PContentDialog;
manages PDocumentRenderer;
manages PContentPermissionRequest;
manages PFilePicker;
manages PRenderFrame;
manages POfflineCacheUpdate;
manages PIndexedDB;
@@ -217,16 +219,22 @@ parent:
/**
* Show/hide a tooltip when the mouse hovers over an element in the content
* document.
*/
ShowTooltip(uint32_t x, uint32_t y, nsString tooltip);
HideTooltip();
/**
+ * Create an asynchronous color picker on the parent side,
+ * but don't open it yet.
+ */
+ PColorPicker(nsString title, nsString initialColor);
+
+ /**
* Initiates an asynchronous request for permission for the
* provided principal.
*
* @param aRequests
* The array of permissions to request.
* @param aPrincipal
* The principal of the request.
*
new file mode 100644
--- /dev/null
+++ b/dom/ipc/PColorPicker.ipdl
@@ -0,0 +1,27 @@
+/* -*- Mode: C++; c-basic-offset: 4; indent-tabs-mode: nil; tab-width: 8 -*- */
+/* vim: set sw=4 ts=8 et tw=80 ft=cpp : */
+
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+include protocol PBrowser;
+
+namespace mozilla {
+namespace dom {
+
+protocol PColorPicker
+{
+ manager PBrowser;
+
+parent:
+ Open();
+
+child:
+ Update(nsString color);
+
+ __delete__(nsString color);
+};
+
+} // namespace dom
+} // namespace mozilla
--- a/dom/ipc/TabChild.cpp
+++ b/dom/ipc/TabChild.cpp
@@ -70,16 +70,18 @@
#include "StructuredCloneUtils.h"
#include "nsViewportInfo.h"
#include "JavaScriptChild.h"
#include "APZCCallbackHelper.h"
#include "nsILoadContext.h"
#include "ipc/nsGUIEventIPC.h"
#include "mozilla/gfx/Matrix.h"
+#include "nsColorPickerProxy.h"
+
#ifdef DEBUG
#include "PCOMContentPermissionRequestChild.h"
#endif /* DEBUG */
#define BROWSER_ELEMENT_CHILD_SCRIPT \
NS_LITERAL_STRING("chrome://global/content/BrowserElementChild.js")
using namespace mozilla;
@@ -2088,16 +2090,31 @@ TabChild::RecvPDocumentRendererConstruct
renderFlags, flushLayout,
renderSize, data);
if (!ret)
return true; // silently ignore
return PDocumentRendererChild::Send__delete__(actor, renderSize, data);
}
+PColorPickerChild*
+TabChild::AllocPColorPickerChild(const nsString&, const nsString&)
+{
+ NS_RUNTIMEABORT("unused");
+ return nullptr;
+}
+
+bool
+TabChild::DeallocPColorPickerChild(PColorPickerChild* aColorPicker)
+{
+ nsColorPickerProxy* picker = static_cast<nsColorPickerProxy*>(aColorPicker);
+ NS_RELEASE(picker);
+ return true;
+}
+
PContentDialogChild*
TabChild::AllocPContentDialogChild(const uint32_t&,
const nsCString&,
const nsCString&,
const InfallibleTArray<int>&,
const InfallibleTArray<nsString>&)
{
return new ContentDialogChild();
--- a/dom/ipc/TabChild.h
+++ b/dom/ipc/TabChild.h
@@ -273,23 +273,29 @@ public:
virtual bool RecvPDocumentRendererConstructor(PDocumentRendererChild* actor,
const nsRect& documentRect,
const gfx::Matrix& transform,
const nsString& bgcolor,
const uint32_t& renderFlags,
const bool& flushLayout,
const nsIntSize& renderSize) MOZ_OVERRIDE;
+ virtual PColorPickerChild*
+ AllocPColorPickerChild(const nsString& title, const nsString& initialColor) MOZ_OVERRIDE;
+ virtual bool DeallocPColorPickerChild(PColorPickerChild* actor) MOZ_OVERRIDE;
+
+
virtual PContentDialogChild* AllocPContentDialogChild(const uint32_t&,
const nsCString&,
const nsCString&,
const InfallibleTArray<int>&,
const InfallibleTArray<nsString>&)
MOZ_OVERRIDE;
virtual bool DeallocPContentDialogChild(PContentDialogChild* aDialog) MOZ_OVERRIDE;
+
static void ParamsToArrays(nsIDialogParamBlock* aParams,
InfallibleTArray<int>& aIntParams,
InfallibleTArray<nsString>& aStringParams);
static void ArraysToParams(const InfallibleTArray<int>& aIntParams,
const InfallibleTArray<nsString>& aStringParams,
nsIDialogParamBlock* aParams);
#ifdef DEBUG
--- a/dom/ipc/TabParent.cpp
+++ b/dom/ipc/TabParent.cpp
@@ -50,16 +50,17 @@
#include "nsIWindowWatcher.h"
#include "nsPIDOMWindow.h"
#include "nsPrintfCString.h"
#include "nsServiceManagerUtils.h"
#include "nsThreadUtils.h"
#include "private/pprio.h"
#include "PermissionMessageUtils.h"
#include "StructuredCloneUtils.h"
+#include "ColorPickerParent.h"
#include "JavaScriptParent.h"
#include "FilePickerParent.h"
#include "TabChild.h"
#include "LoadContext.h"
#include "nsNetCID.h"
#include <algorithm>
using namespace mozilla::dom;
@@ -1620,16 +1621,30 @@ TabParent::GetAuthPrompt(uint32_t aPromp
window = do_QueryInterface(frame->OwnerDoc()->GetWindow());
// Get an auth prompter for our window so that the parenting
// of the dialogs works as it should when using tabs.
return wwatch->GetPrompt(window, iid,
reinterpret_cast<void**>(aResult));
}
+PColorPickerParent*
+TabParent::AllocPColorPickerParent(const nsString& aTitle,
+ const nsString& aInitialColor)
+{
+ return new ColorPickerParent(aTitle, aInitialColor);
+}
+
+bool
+TabParent::DeallocPColorPickerParent(PColorPickerParent* actor)
+{
+ delete actor;
+ return true;
+}
+
PContentDialogParent*
TabParent::AllocPContentDialogParent(const uint32_t& aType,
const nsCString& aName,
const nsCString& aFeatures,
const InfallibleTArray<int>& aIntParams,
const InfallibleTArray<nsString>& aStringParams)
{
ContentDialogParent* parent = new ContentDialogParent();
--- a/dom/ipc/TabParent.h
+++ b/dom/ipc/TabParent.h
@@ -182,16 +182,21 @@ public:
const ViewID& aViewId,
const CSSRect& aRect) MOZ_OVERRIDE;
virtual bool RecvUpdateZoomConstraints(const uint32_t& aPresShellId,
const ViewID& aViewId,
const bool& aIsRoot,
const ZoomConstraints& aConstraints) MOZ_OVERRIDE;
virtual bool RecvContentReceivedTouch(const ScrollableLayerGuid& aGuid,
const bool& aPreventDefault) MOZ_OVERRIDE;
+
+ virtual PColorPickerParent*
+ AllocPColorPickerParent(const nsString& aTitle, const nsString& aInitialColor) MOZ_OVERRIDE;
+ virtual bool DeallocPColorPickerParent(PColorPickerParent* aColorPicker) MOZ_OVERRIDE;
+
virtual PContentDialogParent*
AllocPContentDialogParent(const uint32_t& aType,
const nsCString& aName,
const nsCString& aFeatures,
const InfallibleTArray<int>& aIntParams,
const InfallibleTArray<nsString>& aStringParams) MOZ_OVERRIDE;
virtual bool DeallocPContentDialogParent(PContentDialogParent* aDialog) MOZ_OVERRIDE
{
--- a/dom/ipc/moz.build
+++ b/dom/ipc/moz.build
@@ -35,16 +35,17 @@ EXPORTS.mozilla.dom += [
EXPORTS.mozilla += [
'AppProcessChecker.h',
'PreallocatedProcessManager.h',
'ProcessPriorityManager.h',
]
UNIFIED_SOURCES += [
'AppProcessChecker.cpp',
+ 'ColorPickerParent.cpp',
'ContentChild.cpp',
'ContentParent.cpp',
'ContentProcess.cpp',
'CrashReporterParent.cpp',
'FilePickerParent.cpp',
'PermissionMessageUtils.cpp',
'PreallocatedProcessManager.cpp',
'ProcessPriorityManager.cpp',
@@ -63,16 +64,17 @@ SOURCES += [
'CrashReporterChild.cpp',
]
IPDL_SOURCES += [
'DOMTypes.ipdlh',
'PBlob.ipdl',
'PBlobStream.ipdl',
'PBrowser.ipdl',
+ 'PColorPicker.ipdl',
'PContent.ipdl',
'PContentDialog.ipdl',
'PContentPermission.ipdlh',
'PContentPermissionRequest.ipdl',
'PCrashReporter.ipdl',
'PDocumentRenderer.ipdl',
'PFilePicker.ipdl',
'PMemoryReportRequest.ipdl',
--- a/dom/mobileconnection/interfaces/nsIDOMMobileConnection.idl
+++ b/dom/mobileconnection/interfaces/nsIDOMMobileConnection.idl
@@ -138,18 +138,19 @@ interface nsIDOMMozMobileConnection : ns
nsIDOMDOMRequest selectNetworkAutomatically();
/**
* Set preferred network type
*
* @param type
* DOMString indicates the desired preferred network type.
* Possible values: 'wcdma/gsm', 'gsm', 'wcdma', 'wcdma/gsm-auto',
- * 'cdma/evdo', 'cdma', 'evdo', or
- * 'wcdma/gsm/cdma/evdo'.
+ * 'cdma/evdo', 'cdma', 'evdo', 'wcdma/gsm/cdma/evdo',
+ * 'lte/cdma/evdo', 'lte/wcdma/gsm',
+ * 'lte/wcdma/gsm/cdma/evdo' or 'lte'.
*
* If successful, the request's onsuccess will be called.
*
* Otherwise, the request's onerror will be called, and the request's error
* will be either 'RadioNotAvailable', 'RequestNotSupported',
* 'InvalidParameter', 'ModeNotSupported' or 'GenericFailure'
*
* TODO: param "type" should be a WebIDL enum when this interface is converted
@@ -158,17 +159,18 @@ interface nsIDOMMozMobileConnection : ns
nsIDOMDOMRequest setPreferredNetworkType(in DOMString type);
/**
* Query current preferred network type
*
* If successful, the request's onsuccess will be called. And the request's
* 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', or 'wcdma/gsm/cdma/evdo'.
+ * 'cdma/evdo', 'cdma', 'evdo', 'wcdma/gsm/cdma/evdo', 'lte/cdma/evdo',
+ * 'lte/wcdma/gsm', 'lte/wcdma/gsm/cdma/evdo' or 'lte'.
*
* Otherwise, the request's onerror will be called, and the request's error
* will be either 'RadioNotAvailable', 'RequestNotSupported',
* or 'GenericFailure'
*/
nsIDOMDOMRequest getPreferredNetworkType();
/**
--- a/dom/mobileconnection/tests/marionette/test_mobile_preferred_network_type.js
+++ b/dom/mobileconnection/tests/marionette/test_mobile_preferred_network_type.js
@@ -1,153 +1,131 @@
/* Any copyright is dedicated to the Public Domain.
http://creativecommons.org/publicdomain/zero/1.0/ */
MARIONETTE_TIMEOUT = 60000;
+MARIONETTE_HEAD_JS = "mobile_header.js";
-SpecialPowers.addPermission("mobileconnection", true, document);
+function doSetAndVerifyPreferredNetworkType(preferredNetworkType, callback) {
+ log("setPreferredNetworkType to '" + preferredNetworkType + "'.");
+ let setRequest = mobileConnection.setPreferredNetworkType(preferredNetworkType);
+ ok(setRequest instanceof DOMRequest,
+ "setRequest instanceof " + setRequest.constructor);
+
+ setRequest.onsuccess = function() {
+ log("Verify preferred network.");
+ let getRequest = mobileConnection.getPreferredNetworkType();
+ ok(getRequest instanceof DOMRequest,
+ "getRequest instanceof " + getRequest.constructor);
+
+ getRequest.onsuccess = function() {
+ is(getRequest.result, preferredNetworkType, "Check preferred network type.");
+ callback();
+ };
+
+ getRequest.onerror = function() {
+ ok(false, "getPreferredNetworkType got error: " + getRequest.error.name);
+ callback();
+ };
+ };
-let connection = navigator.mozMobileConnections[0];
-ok(connection instanceof MozMobileConnection,
- "connection is instanceof " + connection.constructor);
+ setRequest.onerror = function() {
+ ok(false, "setPreferredNetwork got error: " + setRequest.error.name);
+ callback();
+ };
+}
+
+function doFailToSetPreferredNetworkType(preferredNetworkType, expectedError, callback) {
+ log("setPreferredNetworkType to '" + preferredNetworkType + "'.");
+ let request = mobileConnection.setPreferredNetworkType(preferredNetworkType);
+ ok(request instanceof DOMRequest,
+ "request instanceof " + request.constructor);
-function testSupportedNetworkTypes() {
- let supportedNetworkTypes = connection.supportedNetworkTypes;
+ request.onsuccess = function() {
+ ok(false, "Should not success");
+ callback();
+ };
+
+ request.onerror = function() {
+ is(request.error.name, expectedError, "Check error message.");
+ callback();
+ };
+}
+
+/* Test supportedNetworkTypes */
+taskHelper.push(function testSupportedNetworkTypes() {
+ let supportedNetworkTypes = mobileConnection.supportedNetworkTypes;
ok(Array.isArray(supportedNetworkTypes), "supportedNetworkTypes should be an array");
ok(supportedNetworkTypes.indexOf("gsm") >= 0, "Should support 'gsm'");
ok(supportedNetworkTypes.indexOf("wcdma") >= 0, "Should support 'wcdma'");
ok(supportedNetworkTypes.indexOf("cdma") >= 0, "Should support 'cdma'");
ok(supportedNetworkTypes.indexOf("evdo") >= 0, "Should support 'evdo'");
- runNextTest();
-}
-
-function setPreferredNetworkType(type, callback) {
- log("setPreferredNetworkType: " + type);
-
- let request = connection.setPreferredNetworkType(type);
- ok(request instanceof DOMRequest,
- "request instanceof " + request.constructor);
-
- request.onsuccess = function onsuccess() {
- ok(true, "request success");
- callback();
- }
- request.onerror = function onerror() {
- ok(false, request.error);
- callback();
- }
-}
-
-function getPreferredNetworkType(callback) {
- log("getPreferredNetworkType");
-
- let request = connection.getPreferredNetworkType();
- ok(request instanceof DOMRequest,
- "request instanceof " + request.constructor);
+ taskHelper.runNext();
+});
- request.onsuccess = function onsuccess() {
- ok(true, "request success");
- log("getPreferredNetworkType: " + request.result);
- callback(request.result);
- }
- request.onerror = function onerror() {
- ok(false, request.error);
- callback();
- }
-}
-
-function failToSetPreferredNetworkType(type, expectedError, callback) {
- log("failToSetPreferredNetworkType: " + type + ", expected error: "
- + expectedError);
-
- let request = connection.setPreferredNetworkType(type);
- ok(request instanceof DOMRequest,
- "request instanceof " + request.constructor);
+/* Test switching to supported preferred types */
+taskHelper.push(function testPreferredNetworkTypes() {
+ let supportedTypes = [
+ 'gsm',
+ 'wcdma',
+ 'wcdma/gsm-auto',
+ 'cdma/evdo',
+ 'evdo',
+ 'cdma',
+ 'wcdma/gsm/cdma/evdo',
+ // Restore to default
+ 'wcdma/gsm'
+ ];
- request.onsuccess = function onsuccess() {
- ok(false, "request should not succeed");
- callback();
- }
- request.onerror = function onerror() {
- ok(true, "request error");
- is(request.error.name, expectedError);
- callback();
- }
-}
-
-function setAndVerifyNetworkType(type) {
- setPreferredNetworkType(type, function() {
- getPreferredNetworkType(function(result) {
- is(result, type);
- testPreferredNetworkTypes();
- });
- });
-}
+ // Run all test data.
+ (function do_call() {
+ let type = supportedTypes.shift();
+ if (!type) {
+ taskHelper.runNext();
+ return;
+ }
+ doSetAndVerifyPreferredNetworkType(type, do_call);
+ })();
+});
-function testPreferredNetworkTypes() {
- let networkType = supportedTypes.shift();
- if (!networkType) {
- runNextTest();
- return;
- }
- setAndVerifyNetworkType(networkType);
-}
+/* Test switching to unsupported preferred types */
+taskHelper.push(function testUnsupportedPreferredNetworkTypes() {
+ // Currently emulator doesn't support lte network
+ let unsupportedTypes = [
+ 'lte/cdma/evdo',
+ 'lte/wcdma/gsm',
+ 'lte/wcdma/gsm/cdma/evdo',
+ 'lte'
+ ];
-function failToSetAndVerifyNetworkType(type, expectedError, previousType) {
- failToSetPreferredNetworkType(type, expectedError, function() {
- getPreferredNetworkType(function(result) {
- // should return the previous selected type.
- is(result, previousType);
- testInvalidNetworkTypes();
- });
- });
-}
-
-function testInvalidNetworkTypes() {
- let networkType = invalidTypes.shift();
- if (!networkType) {
- runNextTest();
- return;
- }
- failToSetAndVerifyNetworkType(networkType, "InvalidParameter",
- "wcdma/gsm");
-}
+ // Run all test data.
+ (function do_call() {
+ let type = unsupportedTypes.shift();
+ if (!type) {
+ taskHelper.runNext();
+ return;
+ }
+ doFailToSetPreferredNetworkType(type, "ModeNotSupported", do_call);
+ })();
+});
-let supportedTypes = [
- 'gsm',
- 'wcdma',
- 'wcdma/gsm-auto',
- 'cdma/evdo',
- 'evdo',
- 'cdma',
- 'wcdma/gsm/cdma/evdo',
- 'wcdma/gsm' // restore to default
-];
-
-let invalidTypes = [
- ' ',
- 'AnInvalidType'
-];
+/* Test switching to invalid preferred types */
+taskHelper.push(function testInvalidPreferredNetworkTypes() {
+ let invalidTypes = [
+ ' ',
+ 'AnInvalidType'
+ ];
-let tests = [
- testSupportedNetworkTypes,
- testPreferredNetworkTypes,
- testInvalidNetworkTypes
-];
+ // Run all test data.
+ (function do_call() {
+ let type = invalidTypes.shift();
+ if (!type) {
+ taskHelper.runNext();
+ return;
+ }
+ doFailToSetPreferredNetworkType(type, "InvalidParameter", do_call);
+ })();
+});
-function runNextTest() {
- let test = tests.shift();
- if (!test) {
- cleanUp();
- return;
- }
-
- test();
-}
-
-function cleanUp() {
- SpecialPowers.removePermission("mobileconnection", document);
- finish();
-}
-
-runNextTest();
+// Start test
+taskHelper.runNext();
--- a/dom/system/gonk/ril_consts.js
+++ b/dom/system/gonk/ril_consts.js
@@ -407,26 +407,34 @@ this.NETWORK_INFO_MESSAGE_TYPES = [
this.GECKO_PREFERRED_NETWORK_TYPE_WCDMA_GSM = "wcdma/gsm";
this.GECKO_PREFERRED_NETWORK_TYPE_GSM_ONLY = "gsm";
this.GECKO_PREFERRED_NETWORK_TYPE_WCDMA_ONLY = "wcdma";
this.GECKO_PREFERRED_NETWORK_TYPE_WCDMA_GSM_AUTO = "wcdma/gsm-auto";
this.GECKO_PREFERRED_NETWORK_TYPE_CDMA_EVDO = "cdma/evdo";
this.GECKO_PREFERRED_NETWORK_TYPE_CDMA_ONLY = "cdma";
this.GECKO_PREFERRED_NETWORK_TYPE_EVDO_ONLY = "evdo";
this.GECKO_PREFERRED_NETWORK_TYPE_WCDMA_GSM_CDMA_EVDO = "wcdma/gsm/cdma/evdo";
+this.GECKO_PREFERRED_NETWORK_TYPE_LTE_CDMA_EVDO = "lte/cdma/evdo";
+this.GECKO_PREFERRED_NETWORK_TYPE_LTE_WCDMA_GSM = "lte/wcdma/gsm";
+this.GECKO_PREFERRED_NETWORK_TYPE_LTE_WCDMA_GSM_CDMA_EVDO = "lte/wcdma/gsm/cdma/evdo";
+this.GECKO_PREFERRED_NETWORK_TYPE_LTE_ONLY = "lte";
this.GECKO_PREFERRED_NETWORK_TYPE_DEFAULT = GECKO_PREFERRED_NETWORK_TYPE_WCDMA_GSM;
this.RIL_PREFERRED_NETWORK_TYPE_TO_GECKO = [
GECKO_PREFERRED_NETWORK_TYPE_WCDMA_GSM,
GECKO_PREFERRED_NETWORK_TYPE_GSM_ONLY,
GECKO_PREFERRED_NETWORK_TYPE_WCDMA_ONLY,
GECKO_PREFERRED_NETWORK_TYPE_WCDMA_GSM_AUTO,
GECKO_PREFERRED_NETWORK_TYPE_CDMA_EVDO,
GECKO_PREFERRED_NETWORK_TYPE_CDMA_ONLY,
GECKO_PREFERRED_NETWORK_TYPE_EVDO_ONLY,
- GECKO_PREFERRED_NETWORK_TYPE_WCDMA_GSM_CDMA_EVDO
+ GECKO_PREFERRED_NETWORK_TYPE_WCDMA_GSM_CDMA_EVDO,
+ GECKO_PREFERRED_NETWORK_TYPE_LTE_CDMA_EVDO,
+ GECKO_PREFERRED_NETWORK_TYPE_LTE_WCDMA_GSM,
+ GECKO_PREFERRED_NETWORK_TYPE_LTE_WCDMA_GSM_CDMA_EVDO,
+ GECKO_PREFERRED_NETWORK_TYPE_LTE_ONLY
];
this.GECKO_SUPPORTED_NETWORK_TYPES_DEFAULT = "gsm,wcdma,cdma,evdo";
this.GECKO_SUPPORTED_NETWORK_TYPES = [
"gsm",
"wcdma",
"cdma",
"evdo",
@@ -2437,61 +2445,105 @@ this.GECKO_CARDSTATE_UNDETECTED
this.GECKO_CARDSTATE_ILLEGAL = "illegal";
this.GECKO_CARDSTATE_UNKNOWN = "unknown";
this.GECKO_CARDSTATE_PIN_REQUIRED = "pinRequired";
this.GECKO_CARDSTATE_PUK_REQUIRED = "pukRequired";
this.GECKO_CARDSTATE_PERSONALIZATION_IN_PROGRESS = "personalizationInProgress";
this.GECKO_CARDSTATE_PERSONALIZATION_READY = "personalizationReady";
this.GECKO_CARDSTATE_NETWORK_LOCKED = "networkLocked";
this.GECKO_CARDSTATE_NETWORK_SUBSET_LOCKED = "networkSubsetLocked";
+this.GECKO_CARDSTATE_NETWORK1_LOCKED = "network1Locked";
+this.GECKO_CARDSTATE_NETWORK2_LOCKED = "network2Locked";
+this.GECKO_CARDSTATE_HRPD_NETWORK_LOCKED = "hrpdNetworkLocked";
this.GECKO_CARDSTATE_CORPORATE_LOCKED = "corporateLocked";
this.GECKO_CARDSTATE_SERVICE_PROVIDER_LOCKED = "serviceProviderLocked";
this.GECKO_CARDSTATE_SIM_LOCKED = "simPersonalizationLock";
+this.GECKO_CARDSTATE_RUIM_CORPORATE_LOCKED = "ruimCorporateLocked";
+this.GECKO_CARDSTATE_RUIM_SERVICE_PROVIDER_LOCKED = "ruimServiceProviderLocked";
+this.GECKO_CARDSTATE_RUIM_LOCKED = "ruimPersonalizationLock";
this.GECKO_CARDSTATE_NETWORK_PUK_REQUIRED = "networkPukRequired";
this.GECKO_CARDSTATE_NETWORK_SUBSET_PUK_REQUIRED = "networkSubsetPukRequired";
+this.GECKO_CARDSTATE_NETWORK1_PUK_REQUIRED = "network1PukRequired";
+this.GECKO_CARDSTATE_NETWORK2_PUK_REQUIRED = "network2PukRequired";
+this.GECKO_CARDSTATE_HRPD_NETWORK_PUK_REQUIRED = "hrpdNetworkPukRequired";
this.GECKO_CARDSTATE_CORPORATE_PUK_REQUIRED = "corporatePukRequired";
this.GECKO_CARDSTATE_SERVICE_PROVIDER_PUK_REQUIRED = "serviceProviderPukRequired";
this.GECKO_CARDSTATE_SIM_PUK_REQUIRED = "simPersonalizationPukRequired";
+this.GECKO_CARDSTATE_RUIM_CORPORATE_PUK_REQUIRED = "ruimCorporatePukRequired";
+this.GECKO_CARDSTATE_RUIM_SERVICE_PROVIDER_PUK_REQUIRED = "ruimServiceProviderPukRequired";
+this.GECKO_CARDSTATE_RUIM_PUK_REQUIRED = "ruimPersonalizationPukRequired";
this.GECKO_CARDSTATE_READY = "ready";
this.GECKO_CARDSTATE_PERMANENT_BLOCKED = "permanentBlocked";
this.GECKO_CARDLOCK_PIN = "pin";
this.GECKO_CARDLOCK_PIN2 = "pin2";
this.GECKO_CARDLOCK_PUK = "puk";
this.GECKO_CARDLOCK_PUK2 = "puk2";
this.GECKO_CARDLOCK_FDN = "fdn";
this.GECKO_CARDLOCK_NCK = "nck";
+this.GECKO_CARDLOCK_NCK1 = "nck1";
+this.GECKO_CARDLOCK_NCK2 = "nck2";
+this.GECKO_CARDLOCK_HNCK = "hnck";
this.GECKO_CARDLOCK_CCK = "cck";
this.GECKO_CARDLOCK_SPCK = "spck";
+this.GECKO_CARDLOCK_RCCK = "rcck";
+this.GECKO_CARDLOCK_RSPCK = "rspck";
this.GECKO_CARDLOCK_NCK_PUK = "nckPuk";
+this.GECKO_CARDLOCK_NCK1_PUK = "nck1Puk";
+this.GECKO_CARDLOCK_NCK2_PUK = "nck2Puk";
+this.GECKO_CARDLOCK_HNCK_PUK = "hnckPuk";
this.GECKO_CARDLOCK_CCK_PUK = "cckPuk";
this.GECKO_CARDLOCK_SPCK_PUK = "spckPuk";
+this.GECKO_CARDLOCK_RCCK_PUK = "rcckPuk";
+this.GECKO_CARDLOCK_RSPCK_PUK = "rspckPuk";
// See ril.h RIL_PersoSubstate
this.PERSONSUBSTATE = {};
PERSONSUBSTATE[CARD_PERSOSUBSTATE_UNKNOWN] = GECKO_CARDSTATE_UNKNOWN;
PERSONSUBSTATE[CARD_PERSOSUBSTATE_IN_PROGRESS] = GECKO_CARDSTATE_PERSONALIZATION_IN_PROGRESS;
PERSONSUBSTATE[CARD_PERSOSUBSTATE_READY] = GECKO_CARDSTATE_PERSONALIZATION_READY;
PERSONSUBSTATE[CARD_PERSOSUBSTATE_SIM_NETWORK] = GECKO_CARDSTATE_NETWORK_LOCKED;
PERSONSUBSTATE[CARD_PERSOSUBSTATE_SIM_NETWORK_SUBSET] = GECKO_CARDSTATE_NETWORK_SUBSET_LOCKED;
PERSONSUBSTATE[CARD_PERSOSUBSTATE_SIM_CORPORATE] = GECKO_CARDSTATE_CORPORATE_LOCKED;
PERSONSUBSTATE[CARD_PERSOSUBSTATE_SIM_SERVICE_PROVIDER] = GECKO_CARDSTATE_SERVICE_PROVIDER_LOCKED;
PERSONSUBSTATE[CARD_PERSOSUBSTATE_SIM_SIM] = GECKO_CARDSTATE_SIM_LOCKED;
PERSONSUBSTATE[CARD_PERSOSUBSTATE_SIM_NETWORK_PUK] = GECKO_CARDSTATE_NETWORK_PUK_REQUIRED;
PERSONSUBSTATE[CARD_PERSOSUBSTATE_SIM_NETWORK_SUBSET_PUK] = GECKO_CARDSTATE_NETWORK_SUBSET_PUK_REQUIRED;
PERSONSUBSTATE[CARD_PERSOSUBSTATE_SIM_CORPORATE_PUK] = GECKO_CARDSTATE_CORPORATE_PUK_REQUIRED;
PERSONSUBSTATE[CARD_PERSOSUBSTATE_SIM_SERVICE_PROVIDER_PUK] = GECKO_CARDSTATE_SERVICE_PROVIDER_PUK_REQUIRED;
+PERSONSUBSTATE[CARD_PERSOSUBSTATE_RUIM_NETWORK1] = GECKO_CARDSTATE_NETWORK1_LOCKED;
+PERSONSUBSTATE[CARD_PERSOSUBSTATE_RUIM_NETWORK2] = GECKO_CARDSTATE_NETWORK2_LOCKED;
+PERSONSUBSTATE[CARD_PERSOSUBSTATE_RUIM_HRPD] = GECKO_CARDSTATE_HRPD_NETWORK_LOCKED;
+PERSONSUBSTATE[CARD_PERSOSUBSTATE_RUIM_CORPORATE] = GECKO_CARDSTATE_RUIM_CORPORATE_LOCKED;
+PERSONSUBSTATE[CARD_PERSOSUBSTATE_RUIM_SERVICE_PROVIDER] = GECKO_CARDSTATE_RUIM_SERVICE_PROVIDER_LOCKED;
+PERSONSUBSTATE[CARD_PERSOSUBSTATE_RUIM_RUIM] = GECKO_CARDSTATE_RUIM_LOCKED;
+PERSONSUBSTATE[CARD_PERSOSUBSTATE_RUIM_NETWORK1_PUK] = GECKO_CARDSTATE_NETWORK1_PUK_REQUIRED;
+PERSONSUBSTATE[CARD_PERSOSUBSTATE_RUIM_NETWORK2_PUK] = GECKO_CARDSTATE_NETWORK2_PUK_REQUIRED;
+PERSONSUBSTATE[CARD_PERSOSUBSTATE_RUIM_HRPD_PUK] = GECKO_CARDSTATE_HRPD_NETWORK_PUK_REQUIRED;
+PERSONSUBSTATE[CARD_PERSOSUBSTATE_RUIM_CORPORATE_PUK] = GECKO_CARDSTATE_RUIM_CORPORATE_PUK_REQUIRED;
+PERSONSUBSTATE[CARD_PERSOSUBSTATE_RUIM_SERVICE_PROVIDER_PUK] = GECKO_CARDSTATE_RUIM_SERVICE_PROVIDER_PUK_REQUIRED;
+PERSONSUBSTATE[CARD_PERSOSUBSTATE_RUIM_RUIM_PUK] = GECKO_CARDSTATE_RUIM_PUK_REQUIRED;
this.GECKO_PERSO_LOCK_TO_CARD_PERSO_LOCK = {};
GECKO_PERSO_LOCK_TO_CARD_PERSO_LOCK[GECKO_CARDLOCK_NCK] = CARD_PERSOSUBSTATE_SIM_NETWORK;
+GECKO_PERSO_LOCK_TO_CARD_PERSO_LOCK[GECKO_CARDLOCK_NCK1] = CARD_PERSOSUBSTATE_RUIM_NETWORK1;
+GECKO_PERSO_LOCK_TO_CARD_PERSO_LOCK[GECKO_CARDLOCK_NCK2] = CARD_PERSOSUBSTATE_RUIM_NETWORK2;
+GECKO_PERSO_LOCK_TO_CARD_PERSO_LOCK[GECKO_CARDLOCK_HNCK] = CARD_PERSOSUBSTATE_RUIM_HRPD;
GECKO_PERSO_LOCK_TO_CARD_PERSO_LOCK[GECKO_CARDLOCK_CCK] = CARD_PERSOSUBSTATE_SIM_CORPORATE;
GECKO_PERSO_LOCK_TO_CARD_PERSO_LOCK[GECKO_CARDLOCK_SPCK] = CARD_PERSOSUBSTATE_SIM_SERVICE_PROVIDER;
+GECKO_PERSO_LOCK_TO_CARD_PERSO_LOCK[GECKO_CARDLOCK_RCCK] = CARD_PERSOSUBSTATE_RUIM_CORPORATE;
+GECKO_PERSO_LOCK_TO_CARD_PERSO_LOCK[GECKO_CARDLOCK_RSPCK] = CARD_PERSOSUBSTATE_RUIM_SERVICE_PROVIDER;
GECKO_PERSO_LOCK_TO_CARD_PERSO_LOCK[GECKO_CARDLOCK_NCK_PUK] = CARD_PERSOSUBSTATE_SIM_NETWORK_PUK;
+GECKO_PERSO_LOCK_TO_CARD_PERSO_LOCK[GECKO_CARDLOCK_NCK1_PUK] = CARD_PERSOSUBSTATE_RUIM_NETWORK1_PUK;
+GECKO_PERSO_LOCK_TO_CARD_PERSO_LOCK[GECKO_CARDLOCK_NCK2_PUK] = CARD_PERSOSUBSTATE_RUIM_NETWORK2_PUK;
+GECKO_PERSO_LOCK_TO_CARD_PERSO_LOCK[GECKO_CARDLOCK_HNCK_PUK] = CARD_PERSOSUBSTATE_RUIM_HRPD_PUK;
GECKO_PERSO_LOCK_TO_CARD_PERSO_LOCK[GECKO_CARDLOCK_CCK_PUK] = CARD_PERSOSUBSTATE_SIM_CORPORATE_PUK;
GECKO_PERSO_LOCK_TO_CARD_PERSO_LOCK[GECKO_CARDLOCK_SPCK_PUK] = CARD_PERSOSUBSTATE_SIM_SERVICE_PROVIDER_PUK;
+GECKO_PERSO_LOCK_TO_CARD_PERSO_LOCK[GECKO_CARDLOCK_RCCK_PUK] = CARD_PERSOSUBSTATE_RUIM_CORPORATE_PUK;
+GECKO_PERSO_LOCK_TO_CARD_PERSO_LOCK[GECKO_CARDLOCK_RSPCK_PUK] = CARD_PERSOSUBSTATE_RUIM_SERVICE_PROVIDER_PUK;
this.GECKO_NETWORK_SELECTION_UNKNOWN = null;
this.GECKO_NETWORK_SELECTION_AUTOMATIC = "automatic";
this.GECKO_NETWORK_SELECTION_MANUAL = "manual";
this.GECKO_MOBILE_CONNECTION_STATE_UNKNOWN = null;
this.GECKO_MOBILE_CONNECTION_STATE_NOTSEARCHING = "notSearching";
this.GECKO_MOBILE_CONNECTION_STATE_SEARCHING = "searching";
--- a/dom/system/gonk/ril_worker.js
+++ b/dom/system/gonk/ril_worker.js
@@ -482,25 +482,35 @@ RilObject.prototype = {
break;
case GECKO_CARDLOCK_PUK:
this.enterICCPUK(options);
break;
case GECKO_CARDLOCK_PUK2:
this.enterICCPUK2(options);
break;
case GECKO_CARDLOCK_NCK:
- case GECKO_CARDLOCK_CCK: // Fall through.
- case GECKO_CARDLOCK_SPCK: {
+ case GECKO_CARDLOCK_NCK1:
+ case GECKO_CARDLOCK_NCK2:
+ case GECKO_CARDLOCK_HNCK:
+ case GECKO_CARDLOCK_CCK:
+ case GECKO_CARDLOCK_SPCK:
+ case GECKO_CARDLOCK_RCCK: // Fall through.
+ case GECKO_CARDLOCK_RSPCK: {
let type = GECKO_PERSO_LOCK_TO_CARD_PERSO_LOCK[options.lockType];
this.enterDepersonalization(type, options.pin, options);
break;
}
case GECKO_CARDLOCK_NCK_PUK:
- case GECKO_CARDLOCK_CCK_PUK: // Fall through.
- case GECKO_CARDLOCK_SPCK_PUK: {
+ case GECKO_CARDLOCK_NCK1_PUK:
+ case GECKO_CARDLOCK_NCK2_PUK:
+ case GECKO_CARDLOCK_HNCK_PUK:
+ case GECKO_CARDLOCK_CCK_PUK:
+ case GECKO_CARDLOCK_SPCK_PUK:
+ case GECKO_CARDLOCK_RCCK_PUK: // Fall through.
+ case GECKO_CARDLOCK_RSPCK_PUK: {
let type = GECKO_PERSO_LOCK_TO_CARD_PERSO_LOCK[options.lockType];
this.enterDepersonalization(type, options.puk, options);
break;
}
default:
options.errorMsg = "Unsupported Card Lock.";
options.success = false;
this.sendChromeMessage(options);
--- a/dom/system/gonk/tests/test_ril_worker_icc.js
+++ b/dom/system/gonk/tests/test_ril_worker_icc.js
@@ -2104,46 +2104,75 @@ add_test(function test_error_message_upd
add_test(function test_personalization_state() {
let worker = newUint8Worker();
let context = worker.ContextPool._contexts[0];
let ril = context.RIL;
context.ICCRecordHelper.readICCID = function fakeReadICCID() {};
- function testPersonalization(cardPersoState, geckoCardState) {
+ function testPersonalization(isCdma, cardPersoState, geckoCardState) {
let iccStatus = {
cardState: CARD_STATE_PRESENT,
- gsmUmtsSubscriptionAppIndex: 0,
+ gsmUmtsSubscriptionAppIndex: (!isCdma) ? 0 : -1,
+ cdmaSubscriptionAppIndex: (isCdma) ? 0 : -1,
apps: [
{
app_state: CARD_APPSTATE_SUBSCRIPTION_PERSO,
perso_substate: cardPersoState
}],
};
+ ril._isCdma = isCdma;
ril._processICCStatus(iccStatus);
do_check_eq(ril.cardState, geckoCardState);
}
- testPersonalization(CARD_PERSOSUBSTATE_SIM_NETWORK,
+ // Test GSM personalization state.
+ testPersonalization(false, CARD_PERSOSUBSTATE_SIM_NETWORK,
GECKO_CARDSTATE_NETWORK_LOCKED);
- testPersonalization(CARD_PERSOSUBSTATE_SIM_CORPORATE,
+ testPersonalization(false, CARD_PERSOSUBSTATE_SIM_CORPORATE,
GECKO_CARDSTATE_CORPORATE_LOCKED);
- testPersonalization(CARD_PERSOSUBSTATE_SIM_SERVICE_PROVIDER,
+ testPersonalization(false, CARD_PERSOSUBSTATE_SIM_SERVICE_PROVIDER,
GECKO_CARDSTATE_SERVICE_PROVIDER_LOCKED);
- testPersonalization(CARD_PERSOSUBSTATE_SIM_NETWORK_PUK,
+ testPersonalization(false, CARD_PERSOSUBSTATE_SIM_NETWORK_PUK,
GECKO_CARDSTATE_NETWORK_PUK_REQUIRED);
- testPersonalization(CARD_PERSOSUBSTATE_SIM_CORPORATE_PUK,
+ testPersonalization(false, CARD_PERSOSUBSTATE_SIM_CORPORATE_PUK,
GECKO_CARDSTATE_CORPORATE_PUK_REQUIRED);
- testPersonalization(CARD_PERSOSUBSTATE_SIM_SERVICE_PROVIDER_PUK,
+ testPersonalization(false, CARD_PERSOSUBSTATE_SIM_SERVICE_PROVIDER_PUK,
GECKO_CARDSTATE_SERVICE_PROVIDER_PUK_REQUIRED);
- testPersonalization(CARD_PERSOSUBSTATE_READY,
+ testPersonalization(false, CARD_PERSOSUBSTATE_READY,
GECKO_CARDSTATE_PERSONALIZATION_READY);
+ // Test CDMA personalization state.
+ testPersonalization(true, CARD_PERSOSUBSTATE_RUIM_NETWORK1,
+ GECKO_CARDSTATE_NETWORK1_LOCKED);
+ testPersonalization(true, CARD_PERSOSUBSTATE_RUIM_NETWORK2,
+ GECKO_CARDSTATE_NETWORK2_LOCKED);
+ testPersonalization(true, CARD_PERSOSUBSTATE_RUIM_HRPD,
+ GECKO_CARDSTATE_HRPD_NETWORK_LOCKED);
+ testPersonalization(true, CARD_PERSOSUBSTATE_RUIM_CORPORATE,
+ GECKO_CARDSTATE_RUIM_CORPORATE_LOCKED);
+ testPersonalization(true, CARD_PERSOSUBSTATE_RUIM_SERVICE_PROVIDER,
+ GECKO_CARDSTATE_RUIM_SERVICE_PROVIDER_LOCKED);
+ testPersonalization(true, CARD_PERSOSUBSTATE_RUIM_RUIM,
+ GECKO_CARDSTATE_RUIM_LOCKED);
+ testPersonalization(true, CARD_PERSOSUBSTATE_RUIM_NETWORK1_PUK,
+ GECKO_CARDSTATE_NETWORK1_PUK_REQUIRED);
+ testPersonalization(true, CARD_PERSOSUBSTATE_RUIM_NETWORK2_PUK,
+ GECKO_CARDSTATE_NETWORK2_PUK_REQUIRED);
+ testPersonalization(true, CARD_PERSOSUBSTATE_RUIM_HRPD_PUK,
+ GECKO_CARDSTATE_HRPD_NETWORK_PUK_REQUIRED);
+ testPersonalization(true, CARD_PERSOSUBSTATE_RUIM_CORPORATE_PUK,
+ GECKO_CARDSTATE_RUIM_CORPORATE_PUK_REQUIRED);
+ testPersonalization(true, CARD_PERSOSUBSTATE_RUIM_SERVICE_PROVIDER_PUK,
+ GECKO_CARDSTATE_RUIM_SERVICE_PROVIDER_PUK_REQUIRED);
+ testPersonalization(true, CARD_PERSOSUBSTATE_RUIM_RUIM_PUK,
+ GECKO_CARDSTATE_RUIM_PUK_REQUIRED);
+
run_next_test();
});
/**
* Verify SIM app_state in _processICCStatus
*/
add_test(function test_card_app_state() {
let worker = newUint8Worker();
@@ -2291,21 +2320,31 @@ add_test(function test_unlock_card_lock_
let context = worker.ContextPool._contexts[0];
let ril = context.RIL;
let buf = context.Buf;
const pin = "12345678";
const puk = "12345678";
let GECKO_CARDLOCK_TO_PASSWORD_TYPE = {};
GECKO_CARDLOCK_TO_PASSWORD_TYPE[GECKO_CARDLOCK_NCK] = "pin";
+ GECKO_CARDLOCK_TO_PASSWORD_TYPE[GECKO_CARDLOCK_NCK1] = "pin";
+ GECKO_CARDLOCK_TO_PASSWORD_TYPE[GECKO_CARDLOCK_NCK2] = "pin";
+ GECKO_CARDLOCK_TO_PASSWORD_TYPE[GECKO_CARDLOCK_HNCK] = "pin";
GECKO_CARDLOCK_TO_PASSWORD_TYPE[GECKO_CARDLOCK_CCK] = "pin";
GECKO_CARDLOCK_TO_PASSWORD_TYPE[GECKO_CARDLOCK_SPCK] = "pin";
+ GECKO_CARDLOCK_TO_PASSWORD_TYPE[GECKO_CARDLOCK_RCCK] = "pin";
+ GECKO_CARDLOCK_TO_PASSWORD_TYPE[GECKO_CARDLOCK_RSPCK] = "pin";
GECKO_CARDLOCK_TO_PASSWORD_TYPE[GECKO_CARDLOCK_NCK_PUK] = "puk";
+ GECKO_CARDLOCK_TO_PASSWORD_TYPE[GECKO_CARDLOCK_NCK1_PUK] = "puk";
+ GECKO_CARDLOCK_TO_PASSWORD_TYPE[GECKO_CARDLOCK_NCK2_PUK] = "puk";
+ GECKO_CARDLOCK_TO_PASSWORD_TYPE[GECKO_CARDLOCK_HNCK_PUK] = "puk";
GECKO_CARDLOCK_TO_PASSWORD_TYPE[GECKO_CARDLOCK_CCK_PUK] = "puk";
GECKO_CARDLOCK_TO_PASSWORD_TYPE[GECKO_CARDLOCK_SPCK_PUK] = "puk";
+ GECKO_CARDLOCK_TO_PASSWORD_TYPE[GECKO_CARDLOCK_RCCK_PUK] = "puk";
+ GECKO_CARDLOCK_TO_PASSWORD_TYPE[GECKO_CARDLOCK_RSPCK_PUK] = "puk";
function do_test(aLock, aPassword) {
buf.sendParcel = function fakeSendParcel () {
// Request Type.
do_check_eq(this.readInt32(), REQUEST_ENTER_NETWORK_DEPERSONALIZATION_CODE);
// Token : we don't care
this.readInt32();
@@ -2319,21 +2358,31 @@ add_test(function test_unlock_card_lock_
};
let lock = {lockType: aLock};
lock[GECKO_CARDLOCK_TO_PASSWORD_TYPE[aLock]] = aPassword;
ril.iccUnlockCardLock(lock);
}
do_test(GECKO_CARDLOCK_NCK, pin);
+ do_test(GECKO_CARDLOCK_NCK1, pin);
+ do_test(GECKO_CARDLOCK_NCK2, pin);
+ do_test(GECKO_CARDLOCK_HNCK, pin);
do_test(GECKO_CARDLOCK_CCK, pin);
do_test(GECKO_CARDLOCK_SPCK, pin);
+ do_test(GECKO_CARDLOCK_RCCK, pin);
+ do_test(GECKO_CARDLOCK_RSPCK, pin);
do_test(GECKO_CARDLOCK_NCK_PUK, puk);
+ do_test(GECKO_CARDLOCK_NCK1_PUK, puk);
+ do_test(GECKO_CARDLOCK_NCK2_PUK, puk);
+ do_test(GECKO_CARDLOCK_HNCK_PUK, puk);
do_test(GECKO_CARDLOCK_CCK_PUK, puk);
do_test(GECKO_CARDLOCK_SPCK_PUK, puk);
+ do_test(GECKO_CARDLOCK_RCCK_PUK, puk);
+ do_test(GECKO_CARDLOCK_RSPCK_PUK, puk);
run_next_test();
});
/**
* Verify MCC and MNC parsing
*/
add_test(function test_mcc_mnc_parsing() {
--- a/dom/tests/mochitest/webcomponents/mochitest.ini
+++ b/dom/tests/mochitest/webcomponents/mochitest.ini
@@ -1,16 +1,20 @@
[DEFAULT]
+support-files =
+ inert_style.css
[test_bug900724.html]
[test_content_element.html]
[test_nested_content_element.html]
[test_dyanmic_content_element_matching.html]
[test_document_register.html]
+[test_document_register_base_queue.html]
[test_document_register_lifecycle.html]
+[test_document_register_parser.html]
+[test_document_register_stack.html]
[test_template.html]
[test_shadow_root.html]
[test_shadow_root_inert_element.html]
-[inert_style.css]
[test_shadow_root_style.html]
[test_shadow_root_style_multiple_shadow.html]
[test_shadow_root_style_order.html]
[test_style_fallback_content.html]
--- a/dom/tests/mochitest/webcomponents/test_document_register.html
+++ b/dom/tests/mochitest/webcomponents/test_document_register.html
@@ -1,90 +1,171 @@
<!DOCTYPE HTML>
<html>
<!--
https://bugzilla.mozilla.org/show_bug.cgi?id=783129
-->
<head>
- <title>Test for document.register using custom prototype</title>
+ <title>Test for document.registerElement using custom prototype</title>
<script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
-<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
+</head>
+<body>
+<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=783129">Bug 783129</a>
+<div>
+<x-unresolved id="unresolved"></x-unresolved>
+</div>
<script>
-var gElementUpgraded = false;
-var gElementReplaced = false;
-function elementUpgrade() {
- gElementUpgraded = true;
-
- // Check for prototype on upgraded element.
- var documentElement = document.getElementById("grabme");
- ok(documentElement.hello, "Upgraded element should inherit 'hello' method from prototype.");
- documentElement.hello();
-
- var customChild = document.getElementById("kid");
- ok(customChild, "Upgrade should preserve children.");
- ok(customChild.parentNode == documentElement, "Parent should be updated to new custom element.");
-
- // Try creating new element and checking for prototype.
- var constructedElement = document.createElement("x-hello");
- ok(constructedElement.hello, "Created element should inherit 'hello' method from prototype.");
- constructedElement.hello();
+function testRegisterExtend(tag, extend, proto, expectException) {
+ try {
+ document.registerElement(tag, { prototype: proto, extends: extend });
+ ok(!expectException, "Registered " + tag + " extending " + extend + " containing " + proto + " in proto chain.");
+ } catch (ex) {
+ ok(expectException, "Did not register " + tag + " extending " + extend + " containing " + proto + " in proto chain.");
+ }
}
-function elementReplace(e) {
- gElementReplaced = true;
-
- ok(e.upgrade != e.target, "Upgraded element should be different from the target.");
- ok(e.upgrade.firstElementChild.id == "kid", "Upgrade element should have a child.");
- ok(e.target.firstElementChild.id == "kid", "Replacement element should have a child.");
+function testRegisterSimple(tag, proto, expectException) {
+ try {
+ document.registerElement(tag, { prototype: proto });
+ ok(!expectException, "Registered " + tag + " containing " + proto + " in proto chain.");
+ } catch (ex) {
+ ok(expectException, "Did not register " + tag + " containing " + proto + " in proto chain.");
+ }
}
function startTest() {
- // Create a prototype that inheits from HTMLElement.
- var customProto = {};
- customProto.__proto__ = HTMLElement.prototype;
- customProto.hello = function() {
- ok(true, "Custom element should use provided prototype.");
- };
+ // Test registering some simple prototypes.
+ testRegisterSimple("x-html-obj-elem", Object.create(HTMLElement.prototype), false);
+ testRegisterSimple("x-html-obj-p", Object.create(HTMLParagraphElement.prototype), false);
+
+ // If prototype is an interface prototype object for any interface object,
+ // registration will throw.
+ testRegisterSimple("x-html-elem", HTMLElement.prototype, true);
+ testRegisterSimple("x-html-select", HTMLSelectElement.prototype, true);
+ testRegisterSimple("some-elem", HTMLElement.prototype, true);
+ testRegisterSimple("x-html-p", HTMLParagraphElement.prototype, true);
+ testRegisterSimple("x-html-span", HTMLSpanElement.prototype, true);
+ testRegisterSimple("x-svg-proto", SVGElement.prototype, true);
+
+ // Make sure the prototype on unresolved elements is HTMLElement not HTMLUnknownElement.
+ var unresolved = document.getElementById("unresolved");
+ is(unresolved.__proto__, HTMLElement.prototype, "Unresolved custom elements should have HTMLElement as prototype.");
+
+ var anotherUnresolved = document.createElement("maybe-custom-element");
+ is(anotherUnresolved.__proto__, HTMLElement.prototype, "Unresolved custom elements should have HTMLElement as prototype.");
+
+ // Registering without a prototype should automatically create one inheriting from HTMLElement.
+ testRegisterSimple("x-elem-no-proto", null, false);
+ var simpleElem = document.createElement("x-elem-no-proto");
+ is(simpleElem.__proto__.__proto__, HTMLElement.prototype, "Default prototype should inherit from HTMLElement");
- var oldElem = document.getElementById("grabme");
- oldElem.addEventListener("elementreplace", elementReplace);
+ var simpleProto = Object.create(HTMLElement.prototype);
+ testRegisterSimple("x-elem-simple-proto", simpleProto, false);
+ var simpleProtoElem = document.createElement("x-elem-simple-proto");
+ is(simpleProtoElem.__proto__, simpleProto, "Custom element should use registered prototype.");
+ var anotherSimpleElem = document.createElementNS("http://www.w3.org/1999/xhtml", "x-elem-simple-proto");
+ is(anotherSimpleElem.__proto__, simpleProto, "Custom element should use registered prototype.");
+
+ // Test registering some invalid prototypes.
+ testRegisterSimple("x-invalid-number", 42, true);
+ testRegisterSimple("x-invalid-boolean", false, true);
+ testRegisterSimple("x-invalid-float", 1.0, true);
+ // Can not register with a prototype that inherits from SVGElement
+ // without extending an existing element type.
+ testRegisterSimple("x-html-obj-svg", Object.create(SVGElement.prototype), true);
+ // A prototype with a non-configurable "constructor" property must throw.
+ var nonConfigProto = Object.create(HTMLElement.prototype,
+ { constructor: { configurable: false, value: function() {} } });
+ testRegisterSimple("x-non-config-proto", nonConfigProto, true);
- document.addEventListener("elementupgrade", elementUpgrade);
- var elementConstructor = document.register("x-hello", { prototype: customProto });
+ // Test invalid custom element names.
+ testRegisterSimple("invalid", Object.create(HTMLElement.prototype), true);
+ testRegisterSimple("annotation-xml", Object.create(HTMLElement.prototype), true);
+ testRegisterSimple("color-profile", Object.create(HTMLElement.prototype), true);
+ testRegisterSimple("font-face", Object.create(HTMLElement.prototype), true);
+ testRegisterSimple("font-face-src", Object.create(HTMLElement.prototype), true);
+ testRegisterSimple("font-face-uri", Object.create(HTMLElement.prototype), true);
+ testRegisterSimple("font-face-format", Object.create(HTMLElement.prototype), true);
+ testRegisterSimple("font-face-name", Object.create(HTMLElement.prototype), true);
+ testRegisterSimple("missing-glyph", Object.create(HTMLElement.prototype), true);
- // Try creating new element and checking for prototype.
- var constructedElement = new elementConstructor();
- ok(constructedElement.hello, "Created element should inherit 'hello' method from prototype.");
- constructedElement.hello();
+ // Test registering elements that extend from an existing element.
+ testRegisterExtend("x-extend-span", "span", Object.create(HTMLElement.prototype), false);
+ testRegisterExtend("x-extend-span-caps", "SPAN", Object.create(HTMLElement.prototype), false);
+
+ // Test registering elements that extend from a non-existing element.
+ testRegisterExtend("x-extend-span-nonexist", "nonexisting", Object.create(HTMLElement.prototype), true);
+ testRegisterExtend("x-extend-svg-nonexist", "nonexisting", Object.create(SVGElement.prototype), true);
- ok(!oldElem.hello, "Element obtained prior to registration should not have inherited prototype.");
+ // Test registration with duplicate type.
+ testRegisterSimple("x-dupe-me", Object.create(HTMLElement.prototype), false);
+ testRegisterSimple("x-dupe-me", Object.create(HTMLElement.prototype), true);
+ testRegisterSimple("X-DUPE-ME", Object.create(HTMLElement.prototype), true);
+ testRegisterSimple("x-dupe-me", null, true);
+ testRegisterExtend("x-dupe-me", "span", Object.create(HTMLElement.prototype), true);
+ testRegisterExtend("x-dupe-me", "shape", Object.create(SVGElement.prototype), true);
- ok(gElementUpgraded && gElementReplaced, "Upgrade and replace events should have been fired.");
+ testRegisterExtend("x-svg-dupe-me", "circle", Object.create(SVGElement.prototype), false);
+ testRegisterSimple("x-svg-dupe-me", Object.create(HTMLElement.prototype), true);
+ testRegisterSimple("X-SVG-DUPE-ME", Object.create(HTMLElement.prototype), true);
+ testRegisterSimple("x-svg-dupe-me", null, true);
+ testRegisterExtend("x-svg-dupe-me", "span", Object.create(HTMLElement.prototype), true);
+ testRegisterExtend("x-svg-dupe-me", "shape", Object.create(SVGElement.prototype), true);
- // Check that custom elements registered without a prototype inherit from HTMLElement.
- document.register("x-bye");
- var byeElement = document.createElement("x-bye");
- ok(byeElement.__proto__.__proto__, HTMLElement.prototype, "Element registered without prototype should inherit from HTMLElement.");
+ // document.createElement with extended type.
+ var extendedProto = Object.create(HTMLButtonElement.prototype);
+ var buttonConstructor = document.registerElement("x-extended-button", { prototype: extendedProto, extends: "button" });
+ var extendedButton = document.createElement("button", "x-extended-button");
+ is(extendedButton.tagName, "BUTTON", "Created element should have local name of BUTTON");
+ is(extendedButton.__proto__, extendedProto, "Created element should have the prototype of the extended type.");
+ is(extendedButton.getAttribute("is"), "x-extended-button", "The |is| attribute of the created element should be the extended type.");
+
+ // document.createElementNS with different namespace than definition.
+ var svgButton = document.createElementNS("http://www.w3.org/2000/svg", "button", "x-extended-button");
+ isnot(svgButton.__proto__, extendedProto, "Definition for element is in html namespace, registration should not apply for SVG elements.");
+
+ // document.createElement with non-existant extended type.
+ var normalButton = document.createElement("button", "x-non-existant");
+ is(normalButton.__proto__, HTMLButtonElement.prototype, "When the extended type doesn't exist, prototype should not change.");
- // Check that element registration with a prototype that does not inherit from HTMLElement results in exception.
- try {
- document.register("x-foo", { "prototype": {} });
- ok(false, "Prototype that does not inherit from HTMLElement should throw exception");
- } catch (ex) {
- ok(true, "Prototype that does not inherit from HTMLElement should throw exception");
- }
+ // document.createElement with exteneded type that does not match with local name of element.
+ var normalDiv = document.createElement("div", "x-extended-button");
+ is(normalDiv.__proto__, HTMLDivElement.prototype, "Prototype should not change when local name of extended type defintion does not match.");
+
+ // Custom element constructor.
+ var constructedButton = new buttonConstructor();
+ is(constructedButton.tagName, "BUTTON", "Created element should have local name of BUTTON");
+ is(constructedButton.__proto__, extendedProto, "Created element should have the prototype of the extended type.");
+ is(constructedButton.getAttribute("is"), "x-extended-button", "The |is| attribute of the created element should be the extended type.");
- SimpleTest.finish();
+ // document.createElementNS with extended type.
+ var svgExtendedProto = Object.create(SVGTextElement.prototype);
+ var svgConstructor = document.registerElement("x-extended-text", { prototype: svgExtendedProto, extends: "text"});
+ var extendedText = document.createElementNS("http://www.w3.org/2000/svg", "text", "x-extended-text");
+ is(extendedText.tagName, "text", "Created element should have a local name of |text|.");
+ is(extendedText.__proto__, svgExtendedProto, "Created element have the registered prototype.");
+ is(extendedText.getAttribute("is"), "x-extended-text", "The |is| attribute of the created element should be the extended type.");
+
+ // document.createElement with different namespace than definition for extended element.
+ var htmlText = document.createElement("text", "x-extended-text");
+ isnot(htmlText.__proto__, svgExtendedProto, "Definition for element in SVG namespace should not apply to HTML elements.");
+
+ // Custom element constructor for a SVG element.
+ var constructedText = new svgConstructor();
+ is(constructedText.tagName, "text", "Created element should have a local name of |text|.");
+ is(constructedText.__proto__, svgExtendedProto, "Created element have the registered prototype.");
+ is(constructedText.getAttribute("is"), "x-extended-text", "The |is| attribute of the created element should be the extended type.");
+
+ // Try creating an element with a custom element name, but not in the html namespace.
+ var htmlNamespaceProto = Object.create(HTMLElement.prototype);
+ document.registerElement("x-in-html-namespace", { prototype: htmlNamespaceProto });
+ var wrongNamespaceElem = document.createElementNS("http://www.w3.org/2000/svg", "x-in-html-namespace");
+ isnot(wrongNamespaceElem.__proto__, htmlNamespaceProto, "Definition for element in html namespace should not apply to SVG elements.");
}
-SimpleTest.waitForExplicitFinish();
-</script>
+startTest();
-</head>
-<body onload="startTest()">
-<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=783129">Bug 783129</a>
-<x-hello id="grabme">
-<div id="kid"></div>
-</x-hello>
+</script>
</body>
</html>
new file mode 100644
--- /dev/null
+++ b/dom/tests/mochitest/webcomponents/test_document_register_base_queue.html
@@ -0,0 +1,48 @@
+<!DOCTYPE HTML>
+<html>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=783129
+-->
+<head>
+ <title>Test for document.registerElement lifecycle callback</title>
+ <script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
+<script>
+var p = Object.create(HTMLElement.prototype);
+
+var createdCallbackCallCount = 0;
+
+// By the time the base element queue is processed via the microtask,
+// both x-hello elements should be in the document.
+p.createdCallback = function() {
+ var one = document.getElementById("one");
+ var two = document.getElementById("two");
+ isnot(one, null, "First x-hello element should be in the tree.");
+ isnot(two, null, "Second x-hello element should be in the tree.");
+ createdCallbackCallCount++;
+ if (createdCallbackCallCount == 2) {
+ SimpleTest.finish();
+ }
+
+ if (createdCallbackCallCount > 2) {
+ ok(false, "Created callback called too much.");
+ }
+};
+
+p.attributeChangedCallback = function(name, oldValue, newValue) {
+ ok(false, "Attribute changed callback should not be called because callbacks should not be queued until created callback invoked.");
+};
+
+document.registerElement("x-hello", { prototype: p });
+
+SimpleTest.waitForExplicitFinish();
+</script>
+</head>
+<body>
+<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=783129">Bug 783129</a>
+<x-hello id="one"></x-hello>
+<x-hello id="two"></x-hello>
+<script>
+</script>
+</body>
+</html>
--- a/dom/tests/mochitest/webcomponents/test_document_register_lifecycle.html
+++ b/dom/tests/mochitest/webcomponents/test_document_register_lifecycle.html
@@ -1,49 +1,402 @@
<!DOCTYPE HTML>
<html>
<!--
https://bugzilla.mozilla.org/show_bug.cgi?id=783129
-->
<head>
- <title>Test for document.register lifecycle callback</title>
+ <title>Test for document.registerElement lifecycle callback</title>
<script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
-
+</head>
+<body>
+<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=783129">Bug 783129</a>
+<div id="container">
+ <x-hello id="hello"></x-hello>
+ <button id="extbutton" is="x-button"></button>
+</div>
<script>
-var gLifecycleCallbackCalled = false;
+var container = document.getElementById("container");
+
+// Tests callbacks after registering element type that is already in the document.
+// create element in document -> register -> remove from document
+function testRegisterUnresolved() {
+ var helloElem = document.getElementById("hello");
+
+ var createdCallbackCalled = false;
+ var enteredViewCallbackCalled = false;
+ var leftViewCallbackCalled = false;
+
+ var p = Object.create(HTMLElement.prototype);
+ p.createdCallback = function() {
+ is(helloElem.__proto__, p, "Prototype should be adjusted just prior to invoking the created callback.");
+ is(createdCallbackCalled, false, "Created callback should only be called once in this tests.");
+ is(this, helloElem, "The 'this' value should be the custom element.");
+ createdCallbackCalled = true;
+ };
+
+ p.enteredViewCallback = function() {
+ is(createdCallbackCalled, true, "Created callback should be called before enteredView");
+ is(enteredViewCallbackCalled, false, "enteredView callback should only be called once in this test.");
+ is(this, helloElem, "The 'this' value should be the custom element.");
+ enteredViewCallbackCalled = true;
+ };
+
+ p.leftViewCallback = function() {
+ is(enteredViewCallbackCalled, true, "enteredView callback should be called before leftView");
+ is(leftViewCallbackCalled, false, "leftView callback should only be called once in this test.");
+ leftViewCallbackCalled = true;
+ is(this, helloElem, "The 'this' value should be the custom element.");
+ runNextTest();
+ };
+
+ p.attributeChangedCallback = function(name, oldValue, newValue) {
+ ok(false, "attributeChanged callback should never be called in this test.");
+ };
+
+ document.registerElement("x-hello", { prototype: p });
+ is(createdCallbackCalled, true, "created callback should be called when control returns to script from user agent code");
+
+ // Remove element from document to trigger leftView callback.
+ container.removeChild(helloElem);
+}
-var lifecycleCallbacks = {
- created: function() {
- is(this.getAttribute("id"), "grabme", "|this| value should be the upgrade element");
- gLifecycleCallbackCalled = true;
- }
-};
+// Tests callbacks after registering an extended element type that is already in the document.
+// create element in document -> register -> remove from document
+function testRegisterUnresolvedExtended() {
+ var buttonElem = document.getElementById("extbutton");
+
+ var createdCallbackCalled = false;
+ var enteredViewCallbackCalled = false;
+ var leftViewCallbackCalled = false;
+
+ var p = Object.create(HTMLButtonElement.prototype);
+ p.createdCallback = function() {
+ is(buttonElem.__proto__, p, "Prototype should be adjusted just prior to invoking the created callback.");
+ is(createdCallbackCalled, false, "Created callback should only be called once in this tests.");
+ is(this, buttonElem, "The 'this' value should be the custom element.");
+ createdCallbackCalled = true;
+ };
+
+ p.enteredViewCallback = function() {
+ is(createdCallbackCalled, true, "Created callback should be called before enteredView");
+ is(enteredViewCallbackCalled, false, "enteredView callback should only be called once in this test.");
+ is(this, buttonElem, "The 'this' value should be the custom element.");
+ enteredViewCallbackCalled = true;
+ };
+
+ p.leftViewCallback = function() {
+ is(enteredViewCallbackCalled, true, "enteredView callback should be called before leftView");
+ is(leftViewCallbackCalled, false, "leftView callback should only be called once in this test.");
+ leftViewCallbackCalled = true;
+ is(this, buttonElem, "The 'this' value should be the custom element.");
+ runNextTest();
+ };
+
+ p.attributeChangedCallback = function(name, oldValue, newValue) {
+ ok(false, "attributeChanged callback should never be called in this test.");
+ };
+
+ document.registerElement("x-button", { prototype: p, extends: "button" });
+ is(createdCallbackCalled, true, "created callback should be called when control returns to script from user agent code");
+
+ // Remove element from document to trigger leftView callback.
+ container.removeChild(buttonElem);
+}
+
+function testInnerHTML() {
+ var createdCallbackCalled = false;
-function startTest() {
- var HtmlProto = function() {};
- HtmlProto.prototype = HTMLElement.prototype;
+ var p = Object.create(HTMLElement.prototype);
+ p.createdCallback = function() {
+ is(createdCallbackCalled, false, "created callback should only be called once in this test.");
+ createdCallbackCalled = true;
+ };
+
+ document.registerElement("x-inner-html", { prototype: p });
+ var div = document.createElement(div);
+ div.innerHTML = '<x-inner-html></x-inner-html>';
+ is(createdCallbackCalled, true, "created callback should be called after setting innerHTML.");
+ runNextTest();
+}
+
+function testInnerHTMLExtended() {
+ var createdCallbackCalled = false;
+
+ var p = Object.create(HTMLButtonElement.prototype);
+ p.createdCallback = function() {
+ is(createdCallbackCalled, false, "created callback should only be called once in this test.");
+ createdCallbackCalled = true;
+ };
+
+ document.registerElement("x-inner-html-extended", { prototype: p, extends: "button" });
+ var div = document.createElement(div);
+ div.innerHTML = '<button is="x-inner-html-extended"></button>';
+ is(createdCallbackCalled, true, "created callback should be called after setting innerHTML.");
+ runNextTest();
+}
+
+function testInnerHTMLUpgrade() {
+ var createdCallbackCalled = false;
+
+ var div = document.createElement(div);
+ div.innerHTML = '<x-inner-html-upgrade></x-inner-html-upgrade>';
+
+ var p = Object.create(HTMLElement.prototype);
+ p.createdCallback = function() {
+ is(createdCallbackCalled, false, "created callback should only be called once in this test.");
+ createdCallbackCalled = true;
+ };
+
+ document.registerElement("x-inner-html-upgrade", { prototype: p });
+ is(createdCallbackCalled, true, "created callback should be called after registering.");
+ runNextTest();
+}
- // Create a prototype that inheits from HTMLElement.
- var customProto = new HtmlProto();
- customProto.hello = function() {
- ok(true, "Custom element should use provided prototype.");
+function testInnerHTMLExtendedUpgrade() {
+ var createdCallbackCalled = false;
+
+ var div = document.createElement(div);
+ div.innerHTML = '<button is="x-inner-html-extended-upgrade"></button>';
+
+ var p = Object.create(HTMLButtonElement.prototype);
+ p.createdCallback = function() {
+ is(createdCallbackCalled, false, "created callback should only be called once in this test.");
+ createdCallbackCalled = true;
+ };
+
+ document.registerElement("x-inner-html-extended-upgrade", { prototype: p, extends: "button" });
+ is(createdCallbackCalled, true, "created callback should be called after registering.");
+ runNextTest();
+}
+
+// Test callback when creating element after registering an element type.
+// register -> create element -> insert into document -> remove from document
+function testRegisterResolved() {
+ var createdCallbackCalled = false;
+ var enteredViewCallbackCalled = false;
+ var leftViewCallbackCalled = false;
+
+ var createdCallbackThis;
+
+ var p = Object.create(HTMLElement.prototype);
+ p.createdCallback = function() {
+ is(createdCallbackCalled, false, "Created callback should only be called once in this test.");
+ createdCallbackThis = this;
+ createdCallbackCalled = true;
+ };
+
+ p.enteredViewCallback = function() {
+ is(createdCallbackCalled, true, "created callback should be called before enteredView callback.");
+ is(enteredViewCallbackCalled, false, "enteredView callback should only be called on in this test.");
+ is(this, createdElement, "The 'this' value should be the custom element.");
+ enteredViewCallbackCalled = true;
+ };
+
+ p.leftViewCallback = function() {
+ is(enteredViewCallbackCalled, true, "enteredView callback should be called before leftView");
+ is(leftViewCallbackCalled, false, "leftView callback should only be called once in this test.");
+ is(this, createdElement, "The 'this' value should be the custom element.");
+ leftViewCallbackCalled = true;
+ runNextTest();
};
- var elementConstructor = document.register("x-hello", { prototype: customProto, lifecycle: lifecycleCallbacks });
+ p.attributeChangedCallback = function() {
+ ok(false, "attributeChanged callback should never be called in this test.");
+ };
+
+ document.registerElement("x-resolved", { prototype: p });
+ is(createdCallbackCalled, false, "Created callback should not be called when custom element instance has not been created.");
+
+ var createdElement = document.createElement("x-resolved");
+ is(createdCallbackThis, createdElement, "The 'this' value in the created callback should be the custom element.");
+ is(createdElement.__proto__, p, "Prototype of custom element should be the registered prototype.");
+
+ // Insert element into document to trigger enteredView callback.
+ container.appendChild(createdElement);
+
+ // Remove element from document to trigger leftView callback.
+ container.removeChild(createdElement);
+}
+
+// Callbacks should always be the same ones when registered.
+function testChangingCallback() {
+ var p = Object.create(HTMLElement.prototype);
+ var callbackCalled = false;
+ p.attributeChangedCallback = function(name, oldValue, newValue) {
+ is(callbackCalled, false, "Callback should only be called once in this test.");
+ callbackCalled = true;
+ runNextTest();
+ };
+
+ document.registerElement("x-test-callback", { prototype: p });
+
+ p.attributeChangedCallback = function(name, oldValue, newValue) {
+ ok(false, "Only callbacks at registration should be called.");
+ };
+
+ var elem = document.createElement("x-test-callback");
+ elem.setAttribute("foo", "bar");
+}
+
+function testAttributeChanged() {
+ var createdCallbackCalled = false;
+
+ var createdElement;
+ var createdCallbackThis;
+
+ var p = Object.create(HTMLElement.prototype);
+ p.createdCallback = function() {
+ is(createdCallbackCalled, false, "Created callback should only be called once in this test.");
+ createdCallbackThis = this;
+ createdCallbackCalled = true;
+ };
+
+ // Sequence of callback arguments that we expect from attribute changed callback
+ // after changing attributes values in a specific order.
+ var expectedCallbackArguments = [
+ // [oldValue, newValue]
+ [null, "newvalue"], // Setting the attribute value to "newvalue"
+ ["newvalue", "nextvalue"], // Changing the attribute value from "newvalue" to "nextvalue"
+ ["nextvalue", ""], // Changing the attribute value from "nextvalue" to empty string
+ ["", null], // Removing the attribute.
+ ];
+
+ p.attributeChangedCallback = function(name, oldValue, newValue) {
+ is(createdCallbackCalled, true, "created callback should be called before attribute changed.");
+ is(this, createdElement, "The 'this' value should be the custom element.");
+ ok(expectedCallbackArguments.length > 0, "Attribute changed callback should not be called more than expected.");
+
+ is(name, "changeme", "name arugment in attribute changed callback should be the name of the changed attribute.");
+
+ var expectedArgs = expectedCallbackArguments.shift();
+ is(oldValue, expectedArgs[0], "The old value argument should match the expected value.");
+ is(newValue, expectedArgs[1], "The new value argument should match the expected value.");
+
+ if (expectedCallbackArguments.length === 0) {
+ // Done with the attribute changed callback test.
+ runNextTest();
+ }
+ };
+
+ document.registerElement("x-attrchange", { prototype: p });
+
+ var createdElement = document.createElement("x-attrchange");
+ is(createdCallbackThis, createdElement, "The 'this' value in the created callback should be the custom element.");
+ createdElement.setAttribute("changeme", "newvalue");
+ createdElement.setAttribute("changeme", "nextvalue");
+ createdElement.setAttribute("changeme", "");
+ createdElement.removeAttribute("changeme");
+}
- ok(gLifecycleCallbackCalled, "Lifecycle callback should be called.");
+function testAttributeChangedExtended() {
+ var p = Object.create(HTMLButtonElement.prototype);
+ var callbackCalled = false;
+ p.attributeChangedCallback = function(name, oldValue, newValue) {
+ is(callbackCalled, false, "Callback should only be called once in this test.");
+ callbackCalled = true;
+ runNextTest();
+ };
+
+ document.registerElement("x-extended-attribute-change", { prototype: p, extends: "button" });
+
+ var elem = document.createElement("button", "x-extended-attribute-change");
+ elem.setAttribute("foo", "bar");
+}
+
+// Creates a custom element that is an upgrade candidate (no registration)
+// and mutate the element in ways that would call callbacks for registered
+// elements.
+function testUpgradeCandidate() {
+ var createdElement = document.createElement("x-upgrade-candidate");
+ container.appendChild(createdElement);
+ createdElement.setAttribute("foo", "bar");
+ container.removeChild(createdElement);
+ ok(true, "Nothing bad should happen when trying to mutating upgrade candidates.");
+ runNextTest();
+}
+
+function testNotInDocEnterLeave() {
+ var p = Object.create(HTMLElement.prototype);
+
+ p.enteredView = function() {
+ ok(false, "enteredView should not be called when not entering the document.");
+ };
+
+ p.leftView = function() {
+ ok(false, "leaveView should not be called when not leaving the document.");
+ };
+
+ var createdElement = document.createElement("x-destined-for-fragment");
+
+ document.registerElement("x-destined-for-fragment", { prototype: p });
+
+ var fragment = new DocumentFragment();
+ fragment.appendChild(createdElement);
+ fragment.removeChild(createdElement);
+
+ var divNotInDoc = document.createElement("div");
+ divNotInDoc.appendChild(createdElement);
+ divNotInDoc.removeChild(createdElement);
- SimpleTest.finish();
+ runNextTest();
+}
+
+function testEnterLeaveView() {
+ var enteredViewCallbackCalled = false;
+ var leftViewCallbackCalled = false;
+
+ var p = Object.create(HTMLElement.prototype);
+ p.enteredViewCallback = function() {
+ is(enteredViewCallbackCalled, false, "enteredView callback should only be called on in this test.");
+ enteredViewCallbackCalled = true;
+ };
+
+ p.leftViewCallback = function() {
+ is(enteredViewCallbackCalled, true, "enteredView callback should be called before leftView");
+ is(leftViewCallbackCalled, false, "leftView callback should only be called once in this test.");
+ leftViewCallbackCalled = true;
+ runNextTest();
+ };
+
+ var div = document.createElement("div");
+ document.registerElement("x-element-in-div", { prototype: p });
+ var customElement = document.createElement("x-element-in-div");
+ div.appendChild(customElement);
+ is(enteredViewCallbackCalled, false, "Appending a custom element to a node that is not in the document should not call the enteredView callback.");
+
+ container.appendChild(div);
+ container.removeChild(div);
+}
+
+var testFunctions = [
+ testRegisterUnresolved,
+ testRegisterUnresolvedExtended,
+ testInnerHTML,
+ testInnerHTMLExtended,
+ testInnerHTMLUpgrade,
+ testInnerHTMLExtendedUpgrade,
+ testRegisterResolved,
+ testAttributeChanged,
+ testAttributeChangedExtended,
+ testUpgradeCandidate,
+ testChangingCallback,
+ testNotInDocEnterLeave,
+ testEnterLeaveView,
+ SimpleTest.finish
+];
+
+function runNextTest() {
+ if (testFunctions.length > 0) {
+ var nextTestFunction = testFunctions.shift();
+ nextTestFunction();
+ }
}
SimpleTest.waitForExplicitFinish();
-</script>
-</head>
-<body onload="startTest()">
-<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=783129">Bug 783129</a>
-<x-hello id="grabme">
-<div id="kid"></div>
-</x-hello>
+runNextTest();
+
+</script>
</body>
</html>
new file mode 100644
--- /dev/null
+++ b/dom/tests/mochitest/webcomponents/test_document_register_parser.html
@@ -0,0 +1,47 @@
+<!DOCTYPE HTML>
+<html>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=783129
+-->
+<head>
+ <title>Test for document.registerElement for elements created by the parser</title>
+ <script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
+<script>
+
+var extendedButtonProto = Object.create(HTMLButtonElement.prototype);
+var buttonCallbackCalled = false;
+extendedButtonProto.createdCallback = function() {
+ is(buttonCallbackCalled, false, "created callback for x-button should only be called once.");
+ is(this.tagName, "BUTTON", "Only the <button> element should be upgraded.");
+ buttonCallbackCalled = true;
+};
+
+document.registerElement("x-button", { prototype: extendedButtonProto, extends: "button" });
+
+var divProto = Object.create(HTMLDivElement.prototype);
+var divCallbackCalled = false;
+divProto.createdCallback = function() {
+ is(divCallbackCalled, false, "created callback for x-div should only be called once.");
+ is(buttonCallbackCalled, true, "crated callback should be called for x-button before x-div.");
+ is(this.tagName, "X-DIV", "Only the <x-div> element should be upgraded.");
+ divCallbackCalled = true;
+ SimpleTest.finish();
+};
+
+document.registerElement("x-div", { prototype: divProto });
+
+SimpleTest.waitForExplicitFinish();
+</script>
+</head>
+<body>
+<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=783129">Bug 783129</a>
+<button is="x-button"></button><!-- should be upgraded -->
+<x-button></x-button><!-- should not be upgraded -->
+<span is="x-button"></span><!-- should not be upgraded -->
+<div is="x-div"></div><!-- should not be upgraded -->
+<x-div></x-div><!-- should be upgraded -->
+<script>
+</script>
+</body>
+</html>
new file mode 100644
--- /dev/null
+++ b/dom/tests/mochitest/webcomponents/test_document_register_stack.html
@@ -0,0 +1,152 @@
+<!DOCTYPE HTML>
+<html>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=783129
+-->
+<head>
+ <title>Test for document.registerElement lifecycle callback</title>
+ <script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
+</head>
+<body>
+<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=783129">Bug 783129</a>
+<div id="container">
+</div>
+<script>
+
+var container = document.getElementById("container");
+
+// Test changing attributes in the created callback on an element
+// created after registration.
+function testChangeAttributeInCreatedCallback() {
+ var createdCallbackCalled = false;
+ var attributeChangedCallbackCalled = false;
+
+ var p = Object.create(HTMLElement.prototype);
+ p.createdCallback = function() {
+ is(createdCallbackCalled, false, "Created callback should be called before enteredView callback.");
+ createdCallbackCalled = true;
+ is(attributeChangedCallbackCalled, false, "Attribute changed callback should not have been called prior to setting the attribute.");
+ this.setAttribute("foo", "bar");
+ is(attributeChangedCallbackCalled, false, "While element is being created, element should not be added to the current element callback queue.");
+ };
+
+ p.attributeChangedCallback = function(name, oldValue, newValue) {
+ is(createdCallbackCalled, true, "attributeChanged callback should be called after the created callback because it was enqueued during created callback.");
+ is(attributeChangedCallbackCalled, false, "attributeChanged callback should only be called once in this tests.");
+ is(newValue, "bar", "The new value should be 'bar'");
+ attributeChangedCallbackCalled = true;
+ runNextTest();
+ };
+
+ document.registerElement("x-one", { prototype: p });
+ document.createElement("x-one");
+}
+
+function testChangeAttributeInEnteredViewCallback() {
+ var p = Object.create(HTMLElement.prototype);
+ var attributeChangedCallbackCalled = false;
+ var enteredViewCallbackCalled = false;
+
+ p.enteredViewCallback = function() {
+ is(enteredViewCallbackCalled, false, "enteredView callback should be called only once in this test.");
+ enteredViewCallbackCalled = true;
+ is(attributeChangedCallbackCalled, false, "Attribute changed callback should not be called before changing attribute.");
+ this.setAttribute("foo", "bar");
+ is(attributeChangedCallbackCalled, true, "Transition from user-agent implementation to script should result in attribute changed callback being called.");
+ runNextTest();
+ };
+
+ p.attributeChangedCallback = function() {
+ is(enteredViewCallbackCalled, true, "enteredView callback should have been called prior to attribute changed callback.");
+ is(attributeChangedCallbackCalled, false, "attributeChanged callback should only be called once in this tests.");
+ attributeChangedCallbackCalled = true;
+ };
+
+ document.registerElement("x-two", { prototype: p });
+ var elem = document.createElement("x-two");
+
+ var container = document.getElementById("container");
+ container.appendChild(elem);
+}
+
+function testLeaveViewInEnteredViewCallback() {
+ var p = Object.create(HTMLElement.prototype);
+ var enteredViewCallbackCalled = false;
+ var leftViewCallbackCalled = false;
+ var container = document.getElementById("container");
+
+ p.enteredViewCallback = function() {
+ is(this.parentNode, container, "Parent node should the container in which the node was appended.");
+ is(enteredViewCallbackCalled, false, "enteredView callback should be called only once in this test.");
+ enteredViewCallbackCalled = true;
+ is(leftViewCallbackCalled, false, "leftView callback should not be called prior to removing element from document.");
+ container.removeChild(this);
+ is(leftViewCallbackCalled, true, "Transition from user-agent implementation to script should run left view callback.");
+ runNextTest();
+ };
+
+ p.leftViewCallback = function() {
+ is(leftViewCallbackCalled, false, "The left view callback should only be called once in this test.");
+ is(enteredViewCallbackCalled, true, "The entered view callback should be called prior to left view callback.");
+ leftViewCallbackCalled = true;
+ };
+
+ document.registerElement("x-three", { prototype: p });
+ var elem = document.createElement("x-three");
+
+ container.appendChild(elem);
+}
+
+function testStackedAttributeChangedCallback() {
+ var p = Object.create(HTMLElement.prototype);
+ var attributeChangedCallbackCount = 0;
+
+ var attributeSequence = ["foo", "bar", "baz"];
+
+ p.attributeChangedCallback = function(attrName, oldValue, newValue) {
+ if (newValue == "baz") {
+ return;
+ }
+
+ var nextAttribute = attributeSequence.shift();
+ ok(true, nextAttribute);
+ // Setting this attribute will call this function again, when
+ // control returns to the script, the last attribute in the sequence should
+ // be set on the element.
+ this.setAttribute("foo", nextAttribute);
+ is(this.getAttribute("foo"), "baz", "The last value in the sequence should be the value of the attribute.");
+
+ attributeChangedCallbackCount++;
+ if (attributeChangedCallbackCount == 3) {
+ runNextTest();
+ }
+ };
+
+ document.registerElement("x-four", { prototype: p });
+ var elem = document.createElement("x-four");
+ elem.setAttribute("foo", "changeme");
+}
+
+var testFunctions = [
+ testChangeAttributeInCreatedCallback,
+ testChangeAttributeInEnteredViewCallback,
+ testLeaveViewInEnteredViewCallback,
+ testStackedAttributeChangedCallback,
+ SimpleTest.finish
+];
+
+function runNextTest() {
+ if (testFunctions.length > 0) {
+ var nextTestFunction = testFunctions.shift();
+ nextTestFunction();
+ }
+}
+
+SimpleTest.waitForExplicitFinish();
+
+runNextTest();
+
+</script>
+</body>
+</html>
--- a/dom/webidl/Document.webidl
+++ b/dom/webidl/Document.webidl
@@ -235,17 +235,25 @@ partial interface Document {
partial interface Document {
readonly attribute Element? mozPointerLockElement;
void mozExitPointerLock ();
};
//http://dvcs.w3.org/hg/webcomponents/raw-file/tip/spec/custom/index.html#dfn-document-register
partial interface Document {
[Throws, Pref="dom.webcomponents.enabled"]
- object register(DOMString name, optional ElementRegistrationOptions options);
+ object registerElement(DOMString name, optional ElementRegistrationOptions options);
+};
+
+//http://dvcs.w3.org/hg/webcomponents/raw-file/tip/spec/custom/index.html#dfn-document-register
+partial interface Document {
+ [NewObject, Throws]
+ Element createElement(DOMString localName, DOMString typeExtension);
+ [NewObject, Throws]
+ Element createElementNS(DOMString? namespace, DOMString qualifiedName, DOMString typeExtension);
};
// http://dvcs.w3.org/hg/webperf/raw-file/tip/specs/PageVisibility/Overview.html#sec-document-interface
partial interface Document {
readonly attribute boolean hidden;
readonly attribute boolean mozHidden;
readonly attribute VisibilityState visibilityState;
readonly attribute VisibilityState mozVisibilityState;
--- a/dom/webidl/DummyBinding.webidl
+++ b/dom/webidl/DummyBinding.webidl
@@ -3,12 +3,13 @@
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
* You can obtain one at http://mozilla.org/MPL/2.0/.
*/
// Dummy bindings that we need to force generation of things that
// aren't actually referenced anywhere in IDL yet but are used in C++.
interface DummyInterface {
+ void lifecycleCallbacks(optional LifecycleCallbacks arg);
};
interface DummyInterfaceWorkers {
};
--- a/dom/webidl/MozIcc.webidl
+++ b/dom/webidl/MozIcc.webidl
@@ -24,21 +24,25 @@ interface MozIcc : EventTarget
*/
attribute EventHandler oniccinfochange;
// Integrated Circuit Card State.
/**
* Indicates the state of the device's ICC.
*
- * Possible values: 'illegal', 'unknown', 'pinRequired',
- * 'pukRequired', 'personalizationInProgress', 'networkLocked',
- * 'corporateLocked', 'serviceProviderLocked', 'networkPukRequired',
- * 'corporatePukRequired', 'serviceProviderPukRequired',
- * 'personalizationReady', 'ready', 'permanentBlocked'.
+ * Possible values: 'illegal', 'unknown', 'pinRequired', 'pukRequired',
+ * 'personalizationInProgress', 'networkLocked', 'network1Locked',
+ * 'network2Locked', 'hrpdNetworkLocked', 'corporateLocked',
+ * 'serviceProviderLocked', 'ruimCorporateLocked', 'ruimServiceProviderLocked',
+ * 'networkPukRequired', 'network1PukRequired', 'network2PukRequired',
+ * 'hrpdNetworkPukRequired', 'corporatePukRequired',
+ * 'serviceProviderPukRequired', 'ruimCorporatePukRequired',
+ * 'ruimServiceProviderPukRequired', 'personalizationReady', 'ready',
+ * 'permanentBlocked'.
*
* Once the ICC becomes undetectable, cardstatechange event will be notified.
* Also, the attribute is set to null and this MozIcc object becomes invalid.
* Calling asynchronous functions raises exception then.
*/
readonly attribute DOMString? cardState;
/**
@@ -154,44 +158,104 @@ interface MozIcc : EventTarget
* puk: "...",
* newPin: "..."});
*
* (3) Network depersonalization. Unlocking the network control key (NCK).
*
* unlockCardLock({lockType: "nck",
* pin: "..."});
*
- * (4) Corporate depersonalization. Unlocking the corporate control key (CCK).
+ * (4) Network type 1 depersonalization. Unlocking the network type 1 control
+ * key (NCK1).
+ *
+ * unlockCardLock({lockType: "nck1",
+ * pin: "..."});
+ *
+ * (5) Network type 2 depersonalization. Unlocking the network type 2 control
+ * key (NCK2).
+ *
+ * unlockCardLock({lockType: "nck2",
+ * pin: "..."});
+ *
+ * (6) HRPD network depersonalization. Unlocking the HRPD network control key
+ * (HNCK).
+ *
+ * unlockCardLock({lockType: "hnck",
+ * pin: "..."});
+ *
+ * (7) Corporate depersonalization. Unlocking the corporate control key (CCK).
*
* unlockCardLock({lockType: "cck",
* pin: "..."});
*
- * (5) Service Provider depersonalization. Unlocking the service provider
+ * (8) Service provider depersonalization. Unlocking the service provider
* control key (SPCK).
*
* unlockCardLock({lockType: "spck",
* pin: "..."});
*
- * (6) Network PUK depersonalization. Unlocking the network control key (NCK).
+ * (9) RUIM corporate depersonalization. Unlocking the RUIM corporate control
+ * key (RCCK).
+ *
+ * unlockCardLock({lockType: "rcck",
+ * pin: "..."});
+ *
+ * (10) RUIM service provider depersonalization. Unlocking the RUIM service
+ * provider control key (RSPCK).
+ *
+ * unlockCardLock({lockType: "rspck",
+ * pin: "..."});
+ *
+ * (11) Network PUK depersonalization. Unlocking the network control key (NCK).
*
* unlockCardLock({lockType: "nckPuk",
* puk: "..."});
*
- * (7) Corporate PUK depersonalization. Unlocking the corporate control key
- * (CCK).
+ * (12) Network type 1 PUK depersonalization. Unlocking the network type 1
+ * control key (NCK1).
+ *
+ * unlockCardLock({lockType: "nck1Puk",
+ * pin: "..."});
+ *
+ * (13) Network type 2 PUK depersonalization. Unlocking the Network type 2
+ * control key (NCK2).
+ *
+ * unlockCardLock({lockType: "nck2Puk",
+ * pin: "..."});
+ *
+ * (14) HRPD network PUK depersonalization. Unlocking the HRPD network control
+ * key (HNCK).
+ *
+ * unlockCardLock({lockType: "hnckPuk",
+ * pin: "..."});
+ *
+ * (15) Corporate PUK depersonalization. Unlocking the corporate control key
+ * (CCK).
*
* unlockCardLock({lockType: "cckPuk",
* puk: "..."});
*
- * (8) Service Provider PUK depersonalization. Unlocking the service provider
- * control key (SPCK).
+ * (16) Service provider PUK depersonalization. Unlocking the service provider
+ * control key (SPCK).
*
* unlockCardLock({lockType: "spckPuk",
* puk: "..."});
*
+ * (17) RUIM corporate PUK depersonalization. Unlocking the RUIM corporate
+ * control key (RCCK).
+ *
+ * unlockCardLock({lockType: "rcckPuk",
+ * puk: "..."});
+ *
+ * (18) RUIM service provider PUK depersonalization. Unlocking the service
+ * provider control key (SPCK).
+ *
+ * unlockCardLock({lockType: "rspckPuk",
+ * puk: "..."});
+ *
* @return a DOMRequest.
* The request's result will be an object containing
* information about the unlock operation.
*
* Examples:
*
* (1) Unlocking failed:
*
--- a/dom/webidl/WebComponents.webidl
+++ b/dom/webidl/WebComponents.webidl
@@ -6,18 +6,23 @@
* The origin of this IDL file is
* http://dvcs.w3.org/hg/webcomponents/raw-file/tip/spec/custom/index.html
*
* Copyright © 2012 W3C® (MIT, ERCIM, Keio), All Rights Reserved. W3C
* liability, trademark and document use rules apply.
*/
callback LifecycleCreatedCallback = void();
+callback LifecycleEnteredViewCallback = void();
+callback LifecycleLeftViewCallback = void();
+callback LifecycleAttributeChangedCallback = void(DOMString attrName, DOMString? oldValue, DOMString? newValue);
dictionary LifecycleCallbacks {
- LifecycleCreatedCallback? created = null;
+ LifecycleCreatedCallback? createdCallback;
+ LifecycleEnteredViewCallback? enteredViewCallback;
+ LifecycleLeftViewCallback? leftViewCallback;
+ LifecycleAttributeChangedCallback? attributeChangedCallback;
};
dictionary ElementRegistrationOptions {
object? prototype = null;
- LifecycleCallbacks lifecycle;
+ DOMString? extends = null;
};
-
--- a/gfx/tests/gtest/TestAsyncPanZoomController.cpp
+++ b/gfx/tests/gtest/TestAsyncPanZoomController.cpp
@@ -708,26 +708,32 @@ TEST(AsyncPanZoomController, MediumPress
mcc->CheckHasDelayedTask();
EXPECT_CALL(*mcc, HandleSingleTap(CSSIntPoint(10, 10), 0, apzc->GetGuid())).Times(1);
mcc->RunDelayedTask();
apzc->Destroy();
}
-TEST(AsyncPanZoomController, LongPress) {
+void
+DoLongPressTest(bool aShouldUseTouchAction, uint32_t aBehavior) {
nsRefPtr<MockContentControllerDelayed> mcc = new MockContentControllerDelayed();
nsRefPtr<TestAPZCTreeManager> tm = new TestAPZCTreeManager();
nsRefPtr<TestAsyncPanZoomController> apzc = new TestAsyncPanZoomController(
0, mcc, tm, AsyncPanZoomController::USE_GESTURE_DETECTOR);
apzc->SetFrameMetrics(TestFrameMetrics());
apzc->NotifyLayersUpdated(TestFrameMetrics(), true);
apzc->UpdateZoomConstraints(ZoomConstraints(false, CSSToScreenScale(1.0), CSSToScreenScale(1.0)));
+ nsTArray<uint32_t> values;
+ values.AppendElement(aBehavior);
+ apzc->SetTouchActionEnabled(aShouldUseTouchAction);
+ apzc->SetAllowedTouchBehavior(values);
+
int time = 0;
nsEventStatus status = ApzcDown(apzc, 10, 10, time);
EXPECT_EQ(nsEventStatus_eConsumeNoDefault, status);
MockFunction<void(std::string checkPointName)> check;
{
@@ -834,16 +840,27 @@ TEST(AsyncPanZoomController, LongPressPr
apzc->SampleContentTransformForFrame(testStartTime, &viewTransformOut, pointOut);
EXPECT_EQ(pointOut, ScreenPoint());
EXPECT_EQ(viewTransformOut, ViewTransform());
apzc->Destroy();
}
+TEST(AsyncPanZoomController, LongPress) {
+ DoLongPressTest(false, mozilla::layers::AllowedTouchBehavior::NONE);
+}
+
+TEST(AsyncPanZoomController, LongPressPanAndZoom) {
+ DoLongPressTest(true, mozilla::layers::AllowedTouchBehavior::HORIZONTAL_PAN
+ | mozilla::layers::AllowedTouchBehavior::VERTICAL_PAN
+ | mozilla::layers::AllowedTouchBehavior::ZOOM);
+}
+
+
// Layer tree for HitTesting1
static already_AddRefed<mozilla::layers::Layer>
CreateTestLayerTree1(nsRefPtr<LayerManager>& aLayerManager, nsTArray<nsRefPtr<Layer> >& aLayers) {
const char* layerTreeSyntax = "c(ttcc)";
// LayerID 0 1234
nsIntRegion layerVisibleRegion[] = {
nsIntRegion(nsIntRect(0,0,100,100)),
nsIntRegion(nsIntRect(0,0,100,100)),
--- a/parser/html/nsHtml5TreeOperation.cpp
+++ b/parser/html/nsHtml5TreeOperation.cpp
@@ -430,34 +430,50 @@ nsHtml5TreeOperation::Perform(nsHtml5Tre
int32_t len = attributes->getLength();
for (int32_t i = len; i > 0;) {
--i;
// prefix doesn't need regetting. it is always null or a static atom
// local name is never null
nsCOMPtr<nsIAtom> localName =
Reget(attributes->getLocalNameNoBoundsCheck(i));
+ nsCOMPtr<nsIAtom> prefix = attributes->getPrefixNoBoundsCheck(i);
+ int32_t nsuri = attributes->getURINoBoundsCheck(i);
+
if (ns == kNameSpaceID_XHTML &&
nsHtml5Atoms::a == name &&
nsHtml5Atoms::name == localName) {
// This is an HTML5-incompliant Geckoism.
// Remove when fixing bug 582361
NS_ConvertUTF16toUTF8 cname(*(attributes->getValueNoBoundsCheck(i)));
NS_ConvertUTF8toUTF16 uv(nsUnescape(cname.BeginWriting()));
- newContent->SetAttr(attributes->getURINoBoundsCheck(i),
+ newContent->SetAttr(nsuri,
localName,
- attributes->getPrefixNoBoundsCheck(i),
+ prefix,
uv,
false);
} else {
- newContent->SetAttr(attributes->getURINoBoundsCheck(i),
+ nsString& value = *(attributes->getValueNoBoundsCheck(i));
+
+ newContent->SetAttr(nsuri,
localName,
- attributes->getPrefixNoBoundsCheck(i),
- *(attributes->getValueNoBoundsCheck(i)),
+ prefix,
+ value,
false);
+
+ // Custom element prototype swizzling may be needed if there is an
+ // "is" attribute.
+ if (kNameSpaceID_None == nsuri && !prefix && nsGkAtoms::is == localName) {
+ ErrorResult errorResult;
+ newContent->OwnerDoc()->SwizzleCustomElement(newContent,
+ value,
+ newContent->GetNameSpaceID(),
+ errorResult);
+
+ }
}
}
return rv;
}
case eTreeOpSetFormElement: {
nsIContent* node = *(mOne.node);
nsIContent* parent = *(mTwo.node);
--- a/toolkit/components/viewsource/content/viewSource.js
+++ b/toolkit/components/viewsource/content/viewSource.js
@@ -652,92 +652,21 @@ function BrowserCharsetReload()
if (isHistoryEnabled()) {
gPageLoader.loadPage(gPageLoader.currentDescriptor,
gPageLoader.DISPLAY_NORMAL);
} else {
gBrowser.reloadWithFlags(Ci.nsIWebNavigation.LOAD_FLAGS_CHARSET_CHANGE);
}
}
-function BrowserSetForcedCharacterSet(aCharset)
-{
- gBrowser.docShell.charset = aCharset;
- BrowserCharsetReload();
-}
-
-function MultiplexHandler(event)
-{
- var node = event.target;
- var name = node.getAttribute("name");
-
- if (name == "detectorGroup") {
- SelectDetector(event);
- BrowserCharsetReload();
- } else if (name == "charsetGroup") {
- var charset = node.getAttribute("id");
- charset = charset.substring(charset.indexOf("charset.") + "charset.".length);
- BrowserSetForcedCharacterSet(charset);
- }
-}
-
-function SelectDetector(event)
+function BrowserSetCharacterSet(aEvent)
{
- var uri = event.target.getAttribute("id");
- var prefvalue = uri.substring(uri.indexOf("chardet.") + "chardet.".length);
- if ("off" == prefvalue) { // "off" is special value to turn off the detectors
- prefvalue = "";
- }
-
- try {
- var str = Cc["@mozilla.org/supports-string;1"].
- createInstance(Ci.nsISupportsString);
- str.data = prefvalue;
- gPrefService.setComplexValue("intl.charset.detector", Ci.nsISupportsString, str);
- }
- catch (ex) {
- dump("Failed to set the intl.charset.detector preference.\n");
- }
-}
-
-function FoldCharset(charset) {
- // For substantially similar encodings, treat two encodings as the same
- // for the purpose of the check mark.
- if (charset == "ISO-8859-8-I") {
- return "windows-1255";
- } else if (charset == "gb18030") {
- return "gbk";
- }
- return charset;
-}
-
-function UpdateCurrentCharset() {
- var menuitem = document.getElementById("charset." + FoldCharset(content.document.characterSet));
- if (menuitem)
- menuitem.setAttribute("checked", "true");
-}
-
-function UpdateCharsetDetector() {
- var prefvalue;
-
- try {
- prefvalue = gPrefService.getComplexValue("intl.charset.detector", Ci.nsIPrefLocalizedString).data;
- }
- catch (ex) {}
-
- if (!prefvalue)
- prefvalue = "off";
-
- var menuitem = document.getElementById("chardet." + prefvalue);
- if (menuitem)
- menuitem.setAttribute("checked", "true");
-}
-
-function UpdateMenus() {
- UpdateCurrentCharset();
- UpdateCharsetDetector();
+ if (aEvent.target.hasAttribute("charset"))
+ gBrowser.docShell.charset = aEvent.target.getAttribute("charset");
+ BrowserCharsetReload();
}
function BrowserForward(aEvent) {
try {
gBrowser.goForward();
}
catch(ex) {
}
--- a/toolkit/components/viewsource/content/viewSource.xul
+++ b/toolkit/components/viewsource/content/viewSource.xul
@@ -196,21 +196,20 @@
key="key_textZoomReset"/>
</menupopup>
</menu>
<!-- Charset Menu -->
<menu id="charsetMenu"
label="&charsetMenu.label;"
accesskey="&charsetMenu.accesskey;"
- oncommand="MultiplexHandler(event);"
+ oncommand="BrowserSetCharacterSet(event);"
onpopupshowing="CharsetMenu.build(event.target);"
- onpopupshown="UpdateMenus();">
- <menupopup>
- </menupopup>
+ onpopupshown="CharsetMenu.update(event, content.document.characterSet);">
+ <menupopup/>
</menu>
<menuseparator/>
<menuitem id="menu_wrapLongLines" type="checkbox" command="cmd_wrapLongLines"
label="&menu_wrapLongLines.title;" accesskey="&menu_wrapLongLines.accesskey;"/>
<menuitem type="checkbox" id="menu_highlightSyntax" command="cmd_highlightSyntax"
label="&menu_highlightSyntax.label;" accesskey="&menu_highlightSyntax.accesskey;"/>
</menupopup>
</menu>
--- a/toolkit/modules/CharsetMenu.jsm
+++ b/toolkit/modules/CharsetMenu.jsm
@@ -9,17 +9,17 @@ const { classes: Cc, interfaces: Ci, uti
Cu.import("resource://gre/modules/Services.jsm");
Cu.import("resource://gre/modules/XPCOMUtils.jsm");
XPCOMUtils.defineLazyGetter(this, "gBundle", function() {
const kUrl = "chrome://global/locale/charsetMenu.properties";
return Services.strings.createBundle(kUrl);
});
const kAutoDetectors = [
- ["off", "off"],
+ ["off", ""],
["ja", "ja_parallel_state_machine"],
["ru", "ruprob"],
["uk", "ukprob"]
];
/**
* This set contains encodings that are in the Encoding Standard, except:
* - XSS-dangerous encodings (except ISO-2022-JP which is assumed to be
@@ -84,56 +84,81 @@ const kEncodings = new Set([
// Always at the start of the menu, in this order, followed by a separator.
const kPinned = [
"UTF-8",
"windows-1252"
];
kPinned.forEach(x => kEncodings.delete(x));
+function CharsetComparator(a, b) {
+ // Normal sorting sorts the part in parenthesis in an order that
+ // happens to make the less frequently-used items first.
+ let titleA = a.label.replace(/\(.*/, "") + b.value;
+ let titleB = b.label.replace(/\(.*/, "") + a.value;
+ // Secondarily reverse sort by encoding name to sort "windows" or
+ // "shift_jis" first.
+ return titleA.localeCompare(titleB) || b.value.localeCompare(a.value);
+}
+
+function SetDetector(event) {
+ let str = Cc["@mozilla.org/supports-string;1"].createInstance(Ci.nsISupportsString);
+ str.data = event.target.getAttribute("detector");
+ Services.prefs.setComplexValue("intl.charset.detector", Ci.nsISupportsString, str);
+}
+
+function UpdateDetectorMenu(event) {
+ event.stopPropagation();
+ let detector = Services.prefs.getComplexValue("intl.charset.detector", Ci.nsIPrefLocalizedString);
+ let menuitem = this.getElementsByAttribute("detector", detector).item(0);
+ if (menuitem) {
+ menuitem.setAttribute("checked", "true");
+ }
+}
let gDetectorInfoCache, gCharsetInfoCache, gPinnedInfoCache;
let CharsetMenu = {
- build: function(parent, idPrefix="", showAccessKeys=true) {
+ build: function(parent, showAccessKeys=true, showDetector=true) {
function createDOMNode(doc, nodeInfo) {
let node = doc.createElement("menuitem");
node.setAttribute("type", "radio");
- node.setAttribute("name", nodeInfo.name);
+ node.setAttribute("name", nodeInfo.name + "Group");
+ node.setAttribute(nodeInfo.name, nodeInfo.value);
node.setAttribute("label", nodeInfo.label);
if (showAccessKeys && nodeInfo.accesskey) {
node.setAttribute("accesskey", nodeInfo.accesskey);
}
- if (idPrefix) {
- node.id = idPrefix + nodeInfo.id;
- } else {
- node.id = nodeInfo.id;
- }
return node;
}
- if (parent.childElementCount > 0) {
+ if (parent.hasChildNodes()) {
// Detector menu or charset menu already built
return;
}
+ this._ensureDataReady();
let doc = parent.ownerDocument;
- let menuNode = doc.createElement("menu");
- menuNode.setAttribute("label", gBundle.GetStringFromName("charsetMenuAutodet"));
- if (showAccessKeys) {
- menuNode.setAttribute("accesskey", gBundle.GetStringFromName("charsetMenuAutodet.key"));
- }
- parent.appendChild(menuNode);
+ if (showDetector) {
+ let menuNode = doc.createElement("menu");
+ menuNode.setAttribute("label", gBundle.GetStringFromName("charsetMenuAutodet"));
+ if (showAccessKeys) {
+ menuNode.setAttribute("accesskey", gBundle.GetStringFromName("charsetMenuAutodet.key"));
+ }
+ parent.appendChild(menuNode);
- let menuPopupNode = doc.createElement("menupopup");
- menuNode.appendChild(menuPopupNode);
+ let menuPopupNode = doc.createElement("menupopup");
+ menuNode.appendChild(menuPopupNode);
+ menuPopupNode.addEventListener("command", SetDetector);
+ menuPopupNode.addEventListener("popupshown", UpdateDetectorMenu);
- this._ensureDataReady();
- gDetectorInfoCache.forEach(detectorInfo => menuPopupNode.appendChild(createDOMNode(doc, detectorInfo)));
- parent.appendChild(doc.createElement("menuseparator"));
+ gDetectorInfoCache.forEach(detectorInfo => menuPopupNode.appendChild(createDOMNode(doc, detectorInfo)));
+ parent.appendChild(doc.createElement("menuseparator"));
+ }
+
gPinnedInfoCache.forEach(charsetInfo => parent.appendChild(createDOMNode(doc, charsetInfo)));
parent.appendChild(doc.createElement("menuseparator"));
gCharsetInfoCache.forEach(charsetInfo => parent.appendChild(createDOMNode(doc, charsetInfo)));
},
getData: function() {
this._ensureDataReady();
return {
@@ -142,68 +167,40 @@ let CharsetMenu = {
otherCharsets: gCharsetInfoCache
};
},
_ensureDataReady: function() {
if (!gDetectorInfoCache) {
gDetectorInfoCache = this.getDetectorInfo();
gPinnedInfoCache = this.getCharsetInfo(kPinned, false);
- gCharsetInfoCache = this.getCharsetInfo([...kEncodings]);
+ gCharsetInfoCache = this.getCharsetInfo(kEncodings);
}
},
getDetectorInfo: function() {
return kAutoDetectors.map(([detectorName, nodeId]) => ({
- id: "chardet." + nodeId,
label: this._getDetectorLabel(detectorName),
accesskey: this._getDetectorAccesskey(detectorName),
- name: "detectorGroup",
+ name: "detector",
+ value: nodeId
}));
},
getCharsetInfo: function(charsets, sort=true) {
- let list = charsets.map(charset => ({
- id: "charset." + charset,
+ let list = [{
label: this._getCharsetLabel(charset),
accesskey: this._getCharsetAccessKey(charset),
- name: "charsetGroup",
- }));
-
- if (!sort) {
- return list;
- }
+ name: "charset",
+ value: charset
+ } for (charset of charsets)];
- list.sort(function (a, b) {
- let titleA = a.label;
- let titleB = b.label;
- // Normal sorting sorts the part in parenthesis in an order that
- // happens to make the less frequently-used items first.
- let index;
- if ((index = titleA.indexOf("(")) > -1) {
- titleA = titleA.substring(0, index);
- }
- if ((index = titleB.indexOf("(")) > -1) {
- titleA = titleB.substring(0, index);
- }
- let comp = titleA.localeCompare(titleB);
- if (comp) {
- return comp;
- }
- // secondarily reverse sort by encoding name to sort "windows" or
- // "shift_jis" first. This works regardless of localization, because
- // the ids aren't localized.
- if (a.id < b.id) {
- return 1;
- }
- if (b.id < a.id) {
- return -1;
- }
- return 0;
- });
+ if (sort) {
+ list.sort(CharsetComparator);
+ }
return list;
},
_getDetectorLabel: function(detector) {
try {
return gBundle.GetStringFromName("charsetMenuAutodet." + detector);
} catch (ex) {}
return detector;
@@ -230,12 +227,36 @@ let CharsetMenu = {
// Localization key has been revised
charset = "gbk.bis";
}
try {
return gBundle.GetStringFromName(charset + ".key");
} catch (ex) {}
return "";
},
+
+ /**
+ * For substantially similar encodings, treat two encodings as the same
+ * for the purpose of the check mark.
+ */
+ foldCharset: function(charset) {
+ switch (charset) {
+ case "ISO-8859-8-I":
+ return "windows-1255";
+
+ case "gb18030":
+ return "gbk";
+
+ default:
+ return charset;
+ }
+ },
+
+ update: function(event, charset) {
+ let menuitem = event.target.getElementsByAttribute("charset", this.foldCharset(charset)).item(0);
+ if (menuitem) {
+ menuitem.setAttribute("checked", "true");
+ }
+ },
};
Object.freeze(CharsetMenu);
--- a/toolkit/xre/glxtest.cpp
+++ b/toolkit/xre/glxtest.cpp
@@ -204,17 +204,17 @@ static void glxtest()
void* glXBindTexImageEXT = glXGetProcAddress("glXBindTexImageEXT");
///// Get GL vendor/renderer/versions strings /////
enum { bufsize = 1024 };
char buf[bufsize];
const GLubyte *vendorString = glGetString(GL_VENDOR);
const GLubyte *rendererString = glGetString(GL_RENDERER);
const GLubyte *versionString = glGetString(GL_VERSION);
-
+
if (!vendorString || !rendererString || !versionString)
fatal_error("glGetString returned null");
int length = snprintf(buf, bufsize,
"VENDOR\n%s\nRENDERER\n%s\nVERSION\n%s\nTFP\n%s\n",
vendorString,
rendererString,
versionString,
@@ -224,17 +224,26 @@ static void glxtest()
///// Clean up. Indeed, the parent process might fail to kill us (e.g. if it doesn't need to check GL info)
///// so we might be staying alive for longer than expected, so it's important to consume as little memory as
///// possible. Also we want to check that we're able to do that too without generating X errors.
glXMakeCurrent(dpy, None, nullptr); // must release the GL context before destroying it
glXDestroyContext(dpy, context);
XDestroyWindow(dpy, window);
XFreeColormap(dpy, swa.colormap);
+
+#ifdef NS_FREE_PERMANENT_DATA // conditionally defined in nscore.h, don't forget to #include it above
XCloseDisplay(dpy);
+#else
+ // This XSync call wanted to be instead:
+ // XCloseDisplay(dpy);
+ // but this can cause 1-minute stalls on certain setups using Nouveau, see bug 973192
+ XSync(dpy, False);
+#endif
+
dlclose(libgl);
///// Finally write data to the pipe
write(write_end_of_the_pipe, buf, length);
}
/** \returns true in the child glxtest process, false in the parent process */
bool fire_glxtest_process()
--- a/widget/xpwidgets/moz.build
+++ b/widget/xpwidgets/moz.build
@@ -21,16 +21,17 @@ UNIFIED_SOURCES += [
'GfxInfoWebGL.cpp',
'InputData.cpp',
'nsBaseAppShell.cpp',
'nsBaseDragService.cpp',
'nsBaseScreen.cpp',
'nsClipboardHelper.cpp',
'nsClipboardPrivacyHandler.cpp',
'nsClipboardProxy.cpp',
+ 'nsColorPickerProxy.cpp',
'nsContentProcessWidgetFactory.cpp',
'nsFilePickerProxy.cpp',
'nsHTMLFormatConverter.cpp',
'nsIdleService.cpp',
'nsIWidgetListener.cpp',
'nsPrimitiveHelpers.cpp',
'nsPrintOptionsImpl.cpp',
'nsPrintSession.cpp',
new file mode 100644
--- /dev/null
+++ b/widget/xpwidgets/nsColorPickerProxy.cpp
@@ -0,0 +1,60 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
+ *
+ * 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 "nsColorPickerProxy.h"
+
+#include "mozilla/dom/TabChild.h"
+
+using namespace mozilla::dom;
+
+NS_IMPL_ISUPPORTS1(nsColorPickerProxy, nsIColorPicker)
+
+/* void init (in nsIDOMWindow parent, in AString title, in short mode); */
+NS_IMETHODIMP
+nsColorPickerProxy::Init(nsIDOMWindow* aParent, const nsAString& aTitle,
+ const nsAString& aInitialColor)
+{
+ TabChild* tabChild = TabChild::GetFrom(aParent);
+ if (!tabChild) {
+ return NS_ERROR_FAILURE;
+ }
+
+ tabChild->SendPColorPickerConstructor(this,
+ nsString(aTitle),
+ nsString(aInitialColor));
+ NS_ADDREF_THIS();
+ return NS_OK;
+}
+
+/* void open (in nsIColorPickerShownCallback aColorPickerShownCallback); */
+NS_IMETHODIMP
+nsColorPickerProxy::Open(nsIColorPickerShownCallback* aColorPickerShownCallback)
+{
+ NS_ENSURE_STATE(!mCallback);
+ mCallback = aColorPickerShownCallback;
+
+ SendOpen();
+ return NS_OK;
+}
+
+bool
+nsColorPickerProxy::RecvUpdate(const nsString& aColor)
+{
+ if (mCallback) {
+ mCallback->Update(aColor);
+ }
+ return true;
+}
+
+bool
+nsColorPickerProxy::Recv__delete__(const nsString& aColor)
+{
+ if (mCallback) {
+ mCallback->Done(aColor);
+ mCallback = nullptr;
+ }
+ return true;
+}
\ No newline at end of file
new file mode 100644
--- /dev/null
+++ b/widget/xpwidgets/nsColorPickerProxy.h
@@ -0,0 +1,32 @@
+/* -*- 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 nsColorPickerProxy_h
+#define nsColorPickerProxy_h
+
+#include "nsIColorPicker.h"
+
+#include "mozilla/dom/PColorPickerChild.h"
+
+class nsColorPickerProxy MOZ_FINAL : public nsIColorPicker,
+ public mozilla::dom::PColorPickerChild
+{
+public:
+ NS_DECL_ISUPPORTS
+ NS_DECL_NSICOLORPICKER
+
+ nsColorPickerProxy() {}
+ ~nsColorPickerProxy() {}
+
+ virtual bool RecvUpdate(const nsString& aColor) MOZ_OVERRIDE;
+ virtual bool Recv__delete__(const nsString& aColor) MOZ_OVERRIDE;
+
+private:
+ nsCOMPtr<nsIColorPickerShownCallback> mCallback;
+ nsString mTitle;
+ nsString mInitialColor;
+};
+
+#endif // nsColorPickerProxy_h
--- a/widget/xpwidgets/nsContentProcessWidgetFactory.cpp
+++ b/widget/xpwidgets/nsContentProcessWidgetFactory.cpp
@@ -3,38 +3,44 @@
*/
/* 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/ModuleUtils.h"
#include "nsWidgetsCID.h"
#include "nsClipboardProxy.h"
+#include "nsColorPickerProxy.h"
#include "nsFilePickerProxy.h"
using namespace mozilla;
#ifndef MOZ_B2G
NS_GENERIC_FACTORY_CONSTRUCTOR(nsClipboardProxy)
+NS_GENERIC_FACTORY_CONSTRUCTOR(nsColorPickerProxy)
NS_GENERIC_FACTORY_CONSTRUCTOR(nsFilePickerProxy)
NS_DEFINE_NAMED_CID(NS_CLIPBOARD_CID);
+NS_DEFINE_NAMED_CID(NS_COLORPICKER_CID);
NS_DEFINE_NAMED_CID(NS_FILEPICKER_CID);
static const mozilla::Module::CIDEntry kWidgetCIDs[] = {
{ &kNS_CLIPBOARD_CID, false, nullptr, nsClipboardProxyConstructor,
Module::CONTENT_PROCESS_ONLY },
+ { &kNS_COLORPICKER_CID, false, nullptr, nsColorPickerProxyConstructor,
+ Module::CONTENT_PROCESS_ONLY },
{ &kNS_FILEPICKER_CID, false, nullptr, nsFilePickerProxyConstructor,
Module::CONTENT_PROCESS_ONLY },
{ nullptr }
};
static const mozilla::Module::ContractIDEntry kWidgetContracts[] = {
{ "@mozilla.org/widget/clipboard;1", &kNS_CLIPBOARD_CID, Module::CONTENT_PROCESS_ONLY },
+ { "@mozilla.org/colorpicker;1", &kNS_COLORPICKER_CID, Module::CONTENT_PROCESS_ONLY },
{ "@mozilla.org/filepicker;1", &kNS_FILEPICKER_CID, Module::CONTENT_PROCESS_ONLY },
{ nullptr }
};
static const mozilla::Module kWidgetModule = {
mozilla::Module::kVersion,
kWidgetCIDs,
kWidgetContracts
--- a/xpfe/components/autocomplete/resources/content/autocomplete.xml
+++ b/xpfe/components/autocomplete/resources/content/autocomplete.xml
@@ -5,24 +5,24 @@
<bindings id="autocompleteBindings"
xmlns="http://www.mozilla.org/xbl"
xmlns:html="http://www.w3.org/1999/xhtml"
xmlns:xul="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
xmlns:xbl="http://www.mozilla.org/xbl">
- <binding id="autocomplete" role="xulcombobox"
+ <binding id="autocomplete" role="xul:combobox"
extends="chrome://global/content/bindings/textbox.xml#textbox">
<resources>
<stylesheet src="chrome://global/content/autocomplete.css"/>
<stylesheet src="chrome://global/skin/autocomplete.css"/>
</resources>
- <content sizetopopup="pref">
+ <content>
<children includes="menupopup"/>
<xul:hbox class="autocomplete-textbox-container" flex="1" align="center">
<children includes="image|deck|stack|box">
<xul:image class="autocomplete-icon" allowevents="true"/>
</children>
<xul:hbox class="textbox-input-box" flex="1" xbl:inherits="context,tooltiptext=inputtooltiptext">
@@ -1623,16 +1623,19 @@
<binding id="history-dropmarker" extends="chrome://global/content/bindings/general.xml#dropmarker">
<implementation>
<method name="showPopup">
<body><![CDATA[
var textbox = document.getBindingParent(this);
var kids = textbox.getElementsByClassName("autocomplete-history-popup");
if (kids.item(0) && textbox.getAttribute("open") != "true") { // Open history popup
+ var w = textbox.boxObject.width;
+ if (w != kids[0].boxObject.width)
+ kids[0].width = w;
kids[0].showPopup(textbox, -1, -1, "popup", "bottomleft", "topleft");
textbox.setAttribute("open", "true");
}
]]></body>
</method>
</implementation>
<handlers>