diff --git a/.lock b/.lock new file mode 100644 index 000000000000..e69de29bb2d1 diff --git a/b2g/config/emulator-ics/sources.xml b/b2g/config/emulator-ics/sources.xml index cd9144a415f4..228cb9bea14e 100644 --- a/b2g/config/emulator-ics/sources.xml +++ b/b2g/config/emulator-ics/sources.xml @@ -19,7 +19,7 @@ - + diff --git a/b2g/config/emulator-jb/sources.xml b/b2g/config/emulator-jb/sources.xml index 55c6cf851cd7..5c5de49e830d 100644 --- a/b2g/config/emulator-jb/sources.xml +++ b/b2g/config/emulator-jb/sources.xml @@ -17,7 +17,7 @@ - + diff --git a/b2g/config/emulator-kk/sources.xml b/b2g/config/emulator-kk/sources.xml index 0c772017ffcf..6e1b7effe75f 100644 --- a/b2g/config/emulator-kk/sources.xml +++ b/b2g/config/emulator-kk/sources.xml @@ -15,7 +15,7 @@ - + diff --git a/b2g/config/emulator/sources.xml b/b2g/config/emulator/sources.xml index cd9144a415f4..228cb9bea14e 100644 --- a/b2g/config/emulator/sources.xml +++ b/b2g/config/emulator/sources.xml @@ -19,7 +19,7 @@ - + diff --git a/b2g/config/flame/sources.xml b/b2g/config/flame/sources.xml index 22e267004ca9..fda8b59317fd 100644 --- a/b2g/config/flame/sources.xml +++ b/b2g/config/flame/sources.xml @@ -17,7 +17,7 @@ - + diff --git a/b2g/config/gaia.json b/b2g/config/gaia.json index 691d26ff1445..032b9e35ceb8 100644 --- a/b2g/config/gaia.json +++ b/b2g/config/gaia.json @@ -4,6 +4,6 @@ "remote": "", "branch": "" }, - "revision": "f99184595c66043518af436b6b09bf02c4d0cd4f", + "revision": "ac2ad84f3387c493bc6c2b1c0496b0fc10a49a49", "repo_path": "/integration/gaia-central" } diff --git a/b2g/config/hamachi/sources.xml b/b2g/config/hamachi/sources.xml index 2fc1b02a51ca..d9480e1fd113 100644 --- a/b2g/config/hamachi/sources.xml +++ b/b2g/config/hamachi/sources.xml @@ -17,7 +17,7 @@ - + diff --git a/b2g/config/helix/sources.xml b/b2g/config/helix/sources.xml index c867c88cad60..f57af41c3ec0 100644 --- a/b2g/config/helix/sources.xml +++ b/b2g/config/helix/sources.xml @@ -15,7 +15,7 @@ - + diff --git a/b2g/config/nexus-4/sources.xml b/b2g/config/nexus-4/sources.xml index ce5e02141a76..0f774290d9aa 100644 --- a/b2g/config/nexus-4/sources.xml +++ b/b2g/config/nexus-4/sources.xml @@ -17,7 +17,7 @@ - + diff --git a/b2g/config/wasabi/sources.xml b/b2g/config/wasabi/sources.xml index f056b84c2999..2af3f4aea56c 100644 --- a/b2g/config/wasabi/sources.xml +++ b/b2g/config/wasabi/sources.xml @@ -17,7 +17,7 @@ - + diff --git a/browser/base/content/aboutneterror/netError.css b/browser/base/content/aboutneterror/netError.css index 51fc83cdfb44..e4c6d6c7041a 100644 --- a/browser/base/content/aboutneterror/netError.css +++ b/browser/base/content/aboutneterror/netError.css @@ -45,6 +45,7 @@ ul { #errorTryAgain { margin-top: 1.2em; + min-width: 150px } #errorContainer { diff --git a/browser/base/content/browser.css b/browser/base/content/browser.css index 8e18e90c2f24..56cf111d783e 100644 --- a/browser/base/content/browser.css +++ b/browser/base/content/browser.css @@ -320,6 +320,14 @@ toolbar:not(#TabsToolbar) > #personal-bookmarks { min-width: 25ch; } +/* Apply crisp rendering for favicons at exactly 2dppx resolution */ +@media (resolution: 2dppx) { + .searchbar-engine-image, + .searchbar-engine-menuitem > .menu-iconic-left > .menu-iconic-icon { + image-rendering: -moz-crisp-edges; + } +} + #urlbar, .searchbar-textbox { /* Setting a width and min-width to let the location & search bars maintain @@ -472,6 +480,20 @@ toolbarbutton.bookmark-item { max-width: 13em; } +/* Apply crisp rendering for favicons at exactly 2dppx resolution */ +@media (resolution: 2dppx) { + .alltabs-popup > .menuitem-iconic > .menu-iconic-left > .menu-iconic-icon, + .menuitem-with-favicon > .menu-iconic-left > .menu-iconic-icon { + image-rendering: -moz-crisp-edges; + } + + .bookmark-item > .toolbarbutton-icon, + .bookmark-item > .menu-iconic-left > .menu-iconic-icon, + #personal-bookmarks[cui-areatype="toolbar"] > #bookmarks-toolbar-placeholder > .toolbarbutton-icon { + image-rendering: -moz-crisp-edges; + } +} + #editBMPanel_tagsSelector { /* override default listbox width from xul.css */ width: auto; @@ -629,6 +651,13 @@ window[chromehidden~="toolbar"] toolbar:not(.toolbar-primary):not(.chromeclass-m height: 16px; } +/* Apply crisp rendering for favicons at exactly 2dppx resolution */ +@media (resolution: 2dppx) { + .ctrlTab-favicon { + image-rendering: -moz-crisp-edges; + } +} + .ctrlTab-preview { -moz-binding: url("chrome://browser/content/browser-tabPreviews.xml#ctrlTab-preview"); } @@ -832,6 +861,15 @@ chatbar { max-height: 0; } +/* Apply crisp rendering for favicons at exactly 2dppx resolution */ +@media (resolution: 2dppx) { + #social-sidebar-favico, + .social-status-button, + .chat-status-icon { + image-rendering: -moz-crisp-edges; + } +} + /** See bug 872317 for why the following rule is necessary. */ #downloads-button { @@ -1000,6 +1038,15 @@ chatbox:-moz-full-screen-ancestor > .chat-titlebar { list-style-image: none; } +/* Apply crisp rendering for favicons at exactly 2dppx resolution */ +@media (resolution: 2dppx) { + #PanelUI-recentlyClosedWindows > toolbarbutton > .toolbarbutton-icon, + #PanelUI-recentlyClosedTabs > toolbarbutton > .toolbarbutton-icon, + #PanelUI-historyItems > toolbarbutton > .toolbarbutton-icon { + image-rendering: -moz-crisp-edges; + } +} + #customization-panelHolder { overflow-y: hidden; } diff --git a/browser/base/content/tabbrowser.css b/browser/base/content/tabbrowser.css index d5d9ee608ccf..bc5860e7114a 100644 --- a/browser/base/content/tabbrowser.css +++ b/browser/base/content/tabbrowser.css @@ -44,6 +44,13 @@ tabpanels { z-index: 2; } +/* Apply crisp rendering for favicons at exactly 2dppx resolution */ +@media (resolution: 2dppx) { + .tab-icon-image { + image-rendering: -moz-crisp-edges; + } +} + .tab-icon-image:not([src]):not([pinned]), .tab-throbber:not([busy]), .tab-throbber[busy] + .tab-icon-image { diff --git a/browser/components/places/content/places.css b/browser/components/places/content/places.css index 5151cca8254b..de3cc91d84ff 100644 --- a/browser/components/places/content/places.css +++ b/browser/components/places/content/places.css @@ -14,3 +14,12 @@ tree[type="places"] { menupopup[placespopup="true"] { -moz-binding: url("chrome://browser/content/places/menu.xml#places-popup-base"); } + +/* Apply crisp rendering for favicons at exactly 2dppx resolution */ +@media (resolution: 2dppx) { + #bookmarksChildren, + .sidebar-placesTreechildren, + .placesTree > treechildren { + image-rendering: -moz-crisp-edges; + } +} diff --git a/browser/components/preferences/handlers.css b/browser/components/preferences/handlers.css index abac7d575e9f..d5f100831e68 100644 --- a/browser/components/preferences/handlers.css +++ b/browser/components/preferences/handlers.css @@ -23,3 +23,11 @@ listitem.offlineapp { -moz-binding: url("chrome://browser/content/preferences/handlers.xml#offlineapp"); } + +/* Apply crisp rendering for favicons at exactly 2dppx resolution */ +@media (resolution: 2dppx) { + #handlersView > richlistitem, + .actionsMenu > menupopup > menuitem > .menu-iconic-left { + image-rendering: -moz-crisp-edges; + } +} diff --git a/browser/components/tabview/tabview.css b/browser/components/tabview/tabview.css index 8ab4b6c2466c..8f3ff20279f8 100644 --- a/browser/components/tabview/tabview.css +++ b/browser/components/tabview/tabview.css @@ -65,6 +65,13 @@ body { position: absolute; } +/* Apply crisp rendering for favicons at exactly 2dppx resolution */ +@media (resolution: 2dppx) { + .favicon > img { + image-rendering: -moz-crisp-edges; + } +} + .close { position: absolute; cursor: pointer; diff --git a/browser/devtools/markupview/markup-view.js b/browser/devtools/markupview/markup-view.js index 22bef8fc7a04..3f059677be08 100644 --- a/browser/devtools/markupview/markup-view.js +++ b/browser/devtools/markupview/markup-view.js @@ -13,7 +13,6 @@ const DEFAULT_MAX_CHILDREN = 100; const COLLAPSE_ATTRIBUTE_LENGTH = 120; const COLLAPSE_DATA_URL_REGEX = /^data.+base64/; const COLLAPSE_DATA_URL_LENGTH = 60; -const CONTAINER_FLASHING_DURATION = 500; const NEW_SELECTION_HIGHLIGHTER_TIMER = 1000; const {UndoStack} = require("devtools/shared/undo"); @@ -112,6 +111,11 @@ function MarkupView(aInspector, aFrame, aControllerWindow) { exports.MarkupView = MarkupView; MarkupView.prototype = { + /** + * How long does a node flash when it mutates (in ms). + */ + CONTAINER_FLASHING_DURATION: 500, + _selectedContainer: null, _initTooltips: function() { @@ -1578,7 +1582,7 @@ MarkupContainer.prototype = { } this._flashMutationTimer = contentWin.setTimeout(() => { this.flashed = false; - }, CONTAINER_FLASHING_DURATION); + }, this.markup.CONTAINER_FLASHING_DURATION); } }, diff --git a/browser/devtools/markupview/test/browser_markupview_mutation_02.js b/browser/devtools/markupview/test/browser_markupview_mutation_02.js index 7aae473747d8..c7a12d3bd203 100644 --- a/browser/devtools/markupview/test/browser_markupview_mutation_02.js +++ b/browser/devtools/markupview/test/browser_markupview_mutation_02.js @@ -55,6 +55,10 @@ const TEST_DATA = [{ let test = asyncTest(function*() { let {inspector} = yield addTab(TEST_URL).then(openInspector); + // Make sure mutated nodes flash for a very long time so we can more easily + // assert they do + inspector.markup.CONTAINER_FLASHING_DURATION = 1000 * 60 * 60; + info("Getting the root node to test mutations on"); let rootNode = getNode(".list"); let rootNodeFront = yield getNodeFront(".list", inspector); @@ -88,4 +92,9 @@ function* assertNodeFlashing(nodeFront, inspector) { ok(container, "Markup container for node found"); ok(container.tagState.classList.contains("theme-bg-contrast"), "Markup container for node is flashing"); + + // Clear the mutation flashing timeout now that we checked the node was flashing + let markup = inspector.markup; + markup._frame.contentWindow.clearTimeout(container._flashMutationTimer); + container._flashMutationTimer = null; } diff --git a/browser/themes/osx/browser.css b/browser/themes/osx/browser.css index 112adcd82654..f3d6501857b1 100644 --- a/browser/themes/osx/browser.css +++ b/browser/themes/osx/browser.css @@ -387,14 +387,6 @@ toolbarbutton.bookmark-item > menupopup { opacity: 0.7; } -@media (min-resolution: 2dppx) { - .bookmark-item > .toolbarbutton-icon, - .bookmark-item > .menu-iconic-left > .menu-iconic-icon, - #personal-bookmarks[cui-areatype="toolbar"] > #bookmarks-toolbar-placeholder > .toolbarbutton-icon { - image-rendering: -moz-crisp-edges; - } -} - #bookmarks-toolbar-placeholder { list-style-image: url("chrome://browser/skin/places/bookmarksToolbar.png") !important; } @@ -2798,7 +2790,6 @@ toolbarbutton.chevron > .toolbarbutton-menu-dropmarker { .tab-icon-image { list-style-image: url("chrome://mozapps/skin/places/defaultFavicon@2x.png"); - image-rendering: -moz-crisp-edges; } .tab-throbber[busy] { diff --git a/browser/themes/osx/searchbar.css b/browser/themes/osx/searchbar.css index 93023fee176a..0a45f7510b04 100644 --- a/browser/themes/osx/searchbar.css +++ b/browser/themes/osx/searchbar.css @@ -47,11 +47,6 @@ } @media (min-resolution: 2dppx) { - .searchbar-engine-image, - .searchbar-engine-menuitem > .menu-iconic-left > .menu-iconic-icon { - image-rendering: -moz-crisp-edges; - } - .searchbar-engine-image { list-style-image: url("chrome://mozapps/skin/places/defaultFavicon@2x.png"); } diff --git a/browser/themes/shared/incontentprefs/preferences.css b/browser/themes/shared/incontentprefs/preferences.css index 83434349b26f..93576c6d9422 100644 --- a/browser/themes/shared/incontentprefs/preferences.css +++ b/browser/themes/shared/incontentprefs/preferences.css @@ -167,7 +167,7 @@ prefpane { #typeColumn > .treecol-sortdirection[sortDirection=descending], #actionColumn > .treecol-sortdirection[sortDirection=descending] { -moz-appearance: none; - list-style-image: url("chrome://browser/skin/preferences/in-content/sorter.png"); + list-style-image: url("chrome://browser/skin/in-content/sorter.png"); } #typeColumn > .treecol-sortdirection[sortDirection=descending], @@ -182,7 +182,7 @@ prefpane { #actionColumn > .treecol-sortdirection[sortDirection=descending] { width: 12px; height: 8px; - list-style-image: url("chrome://browser/skin/preferences/in-content/sorter@2x.png"); + list-style-image: url("chrome://browser/skin/in-content/sorter@2x.png"); } } diff --git a/browser/themes/shared/newtab/controls.svg b/browser/themes/shared/newtab/controls.svg index a37a3a7a42a3..3985f331c3b8 100644 --- a/browser/themes/shared/newtab/controls.svg +++ b/browser/themes/shared/newtab/controls.svg @@ -19,16 +19,11 @@ } .glyphShape-style-hover-gear { - fill: url(#gradient-linear-hover-gear); - } - .glyphShape-style-hover-gear-dropshadow { - fill: #000; - fill-opacity: .5; - filter: url(#filter-shadow-drop); + fill: #4a90e2; } .glyphShape-style-hover-pin { - fill: #0092e5; + fill: #4a90e2; } .glyphShape-style-hover-delete { @@ -57,14 +52,6 @@ - - - - - @@ -79,7 +66,6 @@ - diff --git a/dom/base/Navigator.cpp b/dom/base/Navigator.cpp index 03d5b45a2834..c39aafc1808d 100644 --- a/dom/base/Navigator.cpp +++ b/dom/base/Navigator.cpp @@ -1542,9 +1542,82 @@ Navigator::GetFeature(const nsAString& aName, ErrorResult& aRv) } } + p->MaybeResolve(JS::UndefinedHandleValue); + return p.forget(); +} + +already_AddRefed +Navigator::HasFeature(const nsAString& aName, ErrorResult& aRv) +{ + nsCOMPtr go = do_QueryInterface(mWindow); + nsRefPtr p = Promise::Create(go, aRv); + if (aRv.Failed()) { + return nullptr; + } + NS_NAMED_LITERAL_STRING(apiWindowPrefix, "api.window."); if (StringBeginsWith(aName, apiWindowPrefix)) { const nsAString& featureName = Substring(aName, apiWindowPrefix.Length()); + + // Temporary hardcoded entry points due to technical constraints + if (featureName.EqualsLiteral("Navigator.mozTCPSocket")) { + p->MaybeResolve(Preferences::GetBool("dom.mozTCPSocket.enabled")); + return p.forget(); + } + + if (featureName.EqualsLiteral("Navigator.mozMobileConnections") || + featureName.EqualsLiteral("MozMobileNetworkInfo")) { + p->MaybeResolve(Preferences::GetBool("dom.mobileconnection.enabled")); + return p.forget(); + } + + if (featureName.EqualsLiteral("Navigator.mozInputMethod")) { + p->MaybeResolve(Preferences::GetBool("dom.mozInputMethod.enabled")); + return p.forget(); + } + + if (featureName.EqualsLiteral("Navigator.mozContacts")) { + p->MaybeResolve(true); + return p.forget(); + } + + if (featureName.EqualsLiteral("Navigator.getDeviceStorage")) { + p->MaybeResolve(Preferences::GetBool("device.storage.enabled")); + return p.forget(); + } + + if (featureName.EqualsLiteral("Navigator.mozNetworkStats")) { + p->MaybeResolve(Preferences::GetBool("dom.mozNetworkStats.enabled")); + return p.forget(); + } + + if (featureName.EqualsLiteral("Navigator.push")) { + p->MaybeResolve(Preferences::GetBool("services.push.enabled")); + return p.forget(); + } + + if (featureName.EqualsLiteral("Navigator.mozAlarms")) { + p->MaybeResolve(Preferences::GetBool("dom.mozAlarms.enabled")); + return p.forget(); + } + + if (featureName.EqualsLiteral("Navigator.mozCameras")) { + p->MaybeResolve(true); + return p.forget(); + } + +#ifdef MOZ_B2G + if (featureName.EqualsLiteral("Navigator.getMobileIdAssertion")) { + p->MaybeResolve(true); + return p.forget(); + } +#endif + + if (featureName.EqualsLiteral("XMLHttpRequest.mozSystem")) { + p->MaybeResolve(true); + return p.forget(); + } + if (IsFeatureDetectible(featureName)) { p->MaybeResolve(true); } else { @@ -1559,7 +1632,6 @@ Navigator::GetFeature(const nsAString& aName, ErrorResult& aRv) return p.forget(); } - PowerManager* Navigator::GetMozPower(ErrorResult& aRv) { @@ -2371,7 +2443,8 @@ Navigator::HasMobileIdSupport(JSContext* aCx, JSObject* aGlobal) uint32_t permission = nsIPermissionManager::UNKNOWN_ACTION; permMgr->TestPermissionFromPrincipal(principal, "mobileid", &permission); - return permission != nsIPermissionManager::UNKNOWN_ACTION; + return permission == nsIPermissionManager::PROMPT_ACTION || + permission == nsIPermissionManager::ALLOW_ACTION; } #endif diff --git a/dom/base/Navigator.h b/dom/base/Navigator.h index f19779c04fa4..c676673e095b 100644 --- a/dom/base/Navigator.h +++ b/dom/base/Navigator.h @@ -172,6 +172,9 @@ public: already_AddRefed GetFeature(const nsAString& aName, ErrorResult& aRv); + already_AddRefed HasFeature(const nsAString &aName, + ErrorResult& aRv); + bool Vibrate(uint32_t aDuration); bool Vibrate(const nsTArray& aDuration); uint32_t MaxTouchPoints(); diff --git a/dom/base/test/mochitest.ini b/dom/base/test/mochitest.ini index c988349f39f2..8b8ac1b030ce 100644 --- a/dom/base/test/mochitest.ini +++ b/dom/base/test/mochitest.ini @@ -43,6 +43,7 @@ skip-if = buildapp == 'mulet' || buildapp == 'b2g' || toolkit == 'android' || e1 [test_gsp-standards.html] [test_getFeature_with_perm.html] [test_getFeature_without_perm.html] +[test_hasFeature.html] [test_history_document_open.html] [test_history_state_null.html] [test_Image_constructor.html] diff --git a/dom/base/test/test_hasFeature.html b/dom/base/test/test_hasFeature.html new file mode 100644 index 000000000000..b793a2d0eb29 --- /dev/null +++ b/dom/base/test/test_hasFeature.html @@ -0,0 +1,78 @@ + + + + + + Test for Bug 1009645 + + + + +Mozilla Bug 1009645 + + + diff --git a/dom/bindings/Configuration.py b/dom/bindings/Configuration.py index 0fa5b5328f89..2a97393531bf 100644 --- a/dom/bindings/Configuration.py +++ b/dom/bindings/Configuration.py @@ -447,17 +447,27 @@ class Descriptor(DescriptorProvider): if permissionsIndex is not None: self.checkPermissionsIndicesForMembers[m.identifier.name] = permissionsIndex - self.featureDetectibleThings = set() - if self.interface.getExtendedAttribute("FeatureDetectible") is not None: - if self.interface.getNavigatorProperty(): - self.featureDetectibleThings.add("Navigator.%s" % self.interface.getNavigatorProperty()) - else: - assert(self.interface.ctor() is not None) - self.featureDetectibleThings.add(self.interface.identifier.name) + def isTestInterface(iface): + return (iface.identifier.name in ["TestInterface", + "TestJSImplInterface", + "TestRenamedInterface"]) - for m in self.interface.members: - if m.getExtendedAttribute("FeatureDetectible") is not None: - self.featureDetectibleThings.add("%s.%s" % (self.interface.identifier.name, m.identifier.name)) + self.featureDetectibleThings = set() + if not isTestInterface(self.interface): + if (self.interface.getExtendedAttribute("CheckPermissions") or + self.interface.getExtendedAttribute("AvailableIn") == "PrivilegedApps"): + if self.interface.getNavigatorProperty(): + self.featureDetectibleThings.add("Navigator.%s" % self.interface.getNavigatorProperty()) + else: + iface = self.interface.identifier.name + self.featureDetectibleThings.add(iface) + for m in self.interface.members: + self.featureDetectibleThings.add("%s.%s" % (iface, m.identifier.name)) + + for m in self.interface.members: + if (m.getExtendedAttribute("CheckPermissions") or + m.getExtendedAttribute("AvailableIn") == "PrivilegedApps"): + self.featureDetectibleThings.add("%s.%s" % (self.interface.identifier.name, m.identifier.name)) # Build the prototype chain. self.prototypeChain = [] diff --git a/dom/bindings/parser/WebIDL.py b/dom/bindings/parser/WebIDL.py index acc7fcdf5657..930af4e12faf 100644 --- a/dom/bindings/parser/WebIDL.py +++ b/dom/bindings/parser/WebIDL.py @@ -669,22 +669,6 @@ class IDLInterface(IDLObjectWithScope): [self.location]) assert not parent or isinstance(parent, IDLInterface) - if self.getExtendedAttribute("FeatureDetectible"): - if not (self.getExtendedAttribute("Func") or - self.getExtendedAttribute("AvailableIn") or - self.getExtendedAttribute("CheckPermissions")): - raise WebIDLError("[FeatureDetectible] is only allowed in combination " - "with [Func], [AvailableIn] or [CheckPermissions]", - [self.location]) - if self.getExtendedAttribute("Pref"): - raise WebIDLError("[FeatureDetectible] must not be specified " - "in combination with [Pref]", - [self.location]) - if not self.hasInterfaceObject(): - raise WebIDLError("[FeatureDetectible] not allowed on interface " - "with [NoInterfaceObject]", - [self.location]) - self.parent = parent assert iter(self.members) @@ -1207,8 +1191,7 @@ class IDLInterface(IDLObjectWithScope): identifier == "OverrideBuiltins" or identifier == "ChromeOnly" or identifier == "Unforgeable" or - identifier == "LegacyEventInit" or - identifier == "FeatureDetectible"): + identifier == "LegacyEventInit"): # Known extended attributes that do not take values if not attr.noArguments(): raise WebIDLError("[%s] must take no arguments" % identifier, @@ -3174,18 +3157,6 @@ class IDLAttribute(IDLInterfaceMember): raise WebIDLError("An attribute with [SameObject] must have an " "interface type as its type", [self.location]) - if self.getExtendedAttribute("FeatureDetectible"): - if not (self.getExtendedAttribute("Func") or - self.getExtendedAttribute("AvailableIn") or - self.getExtendedAttribute("CheckPermissions")): - raise WebIDLError("[FeatureDetectible] is only allowed in combination " - "with [Func], [AvailableIn] or [CheckPermissions]", - [self.location]) - if self.getExtendedAttribute("Pref"): - raise WebIDLError("[FeatureDetectible] must not be specified " - "in combination with [Pref]", - [self.location]) - def validate(self): IDLInterfaceMember.validate(self) @@ -3324,8 +3295,7 @@ class IDLAttribute(IDLInterfaceMember): identifier == "Frozen" or identifier == "AvailableIn" or identifier == "NewObject" or - identifier == "CheckPermissions" or - identifier == "FeatureDetectible"): + identifier == "CheckPermissions"): # Known attributes that we don't need to do anything with here pass else: @@ -3730,18 +3700,6 @@ class IDLMethod(IDLInterfaceMember, IDLScope): def finish(self, scope): IDLInterfaceMember.finish(self, scope) - if self.getExtendedAttribute("FeatureDetectible"): - if not (self.getExtendedAttribute("Func") or - self.getExtendedAttribute("AvailableIn") or - self.getExtendedAttribute("CheckPermissions")): - raise WebIDLError("[FeatureDetectible] is only allowed in combination " - "with [Func], [AvailableIn] or [CheckPermissions]", - [self.location]) - if self.getExtendedAttribute("Pref"): - raise WebIDLError("[FeatureDetectible] must not be specified " - "in combination with [Pref]", - [self.location]) - overloadWithPromiseReturnType = None overloadWithoutPromiseReturnType = None for overload in self._overloads: @@ -3922,8 +3880,7 @@ class IDLMethod(IDLInterfaceMember, IDLScope): convertExposedAttrToGlobalNameSet(attr, self._exposureGlobalNames) elif (identifier == "Pure" or identifier == "CrossOriginCallable" or - identifier == "WebGLHandlesContextLoss" or - identifier == "FeatureDetectible"): + identifier == "WebGLHandlesContextLoss"): # Known no-argument attributes. if not attr.noArguments(): raise WebIDLError("[%s] must take no arguments" % identifier, diff --git a/dom/devicestorage/DeviceStorage.h b/dom/devicestorage/DeviceStorage.h index 8f376bc2eb31..a7a374dcb855 100644 --- a/dom/devicestorage/DeviceStorage.h +++ b/dom/devicestorage/DeviceStorage.h @@ -342,8 +342,9 @@ private: #ifdef MOZ_WIDGET_GONK nsString mLastStatus; + nsString mLastStorageStatus; void DispatchStatusChangeEvent(nsAString& aStatus); - void DispatchStorageStatusChangeEvent(nsAString& aVolumeStatus); + void DispatchStorageStatusChangeEvent(nsAString& aStorageStatus); #endif // nsIDOMDeviceStorage.type diff --git a/dom/devicestorage/nsDeviceStorage.cpp b/dom/devicestorage/nsDeviceStorage.cpp index 51474687d100..f3e66cbeb77a 100644 --- a/dom/devicestorage/nsDeviceStorage.cpp +++ b/dom/devicestorage/nsDeviceStorage.cpp @@ -4161,13 +4161,19 @@ nsDOMDeviceStorage::DispatchStatusChangeEvent(nsAString& aStatus) } void -nsDOMDeviceStorage::DispatchStorageStatusChangeEvent(nsAString& aVolumeStatus) +nsDOMDeviceStorage::DispatchStorageStatusChangeEvent(nsAString& aStorageStatus) { + if (aStorageStatus == mLastStorageStatus) { + // We've already sent this status, don't bother sending it again. + return; + } + mLastStorageStatus = aStorageStatus; + DeviceStorageChangeEventInit init; init.mBubbles = true; init.mCancelable = false; init.mPath = mStorageName; - init.mReason = aVolumeStatus; + init.mReason = aStorageStatus; nsRefPtr event = DeviceStorageChangeEvent::Constructor(this, NS_LITERAL_STRING("storage-state-change"), diff --git a/dom/permission/tests/test_idle.html b/dom/permission/tests/test_idle.html index 595ee622cf1e..ef37c3efd6bd 100644 --- a/dom/permission/tests/test_idle.html +++ b/dom/permission/tests/test_idle.html @@ -36,7 +36,6 @@ function verifier(success, failure) { var gData = [ { perm: ["idle"], - settings: [["dom.idle-observers-api.enabled", true]], verifier: verifier.toSource(), } ] diff --git a/dom/system/gonk/ril_worker.js b/dom/system/gonk/ril_worker.js index c515bcf81086..1a94ebde4b34 100644 --- a/dom/system/gonk/ril_worker.js +++ b/dom/system/gonk/ril_worker.js @@ -1589,8 +1589,7 @@ RilObject.prototype = { return; } - if (this.voiceRegistrationState.emergencyCallsOnly || - options.isDialEmergency) { + if (this.voiceRegistrationState.emergencyCallsOnly) { onerror(RIL_CALL_FAILCAUSE_TO_GECKO_CALL_ERROR[CALL_FAIL_UNOBTAINABLE_NUMBER]); return; } @@ -1615,6 +1614,7 @@ RilObject.prototype = { } options.request = REQUEST_DIAL; + options.isEmergency = false; this.sendDialRequest(options); }, @@ -1637,6 +1637,8 @@ RilObject.prototype = { options.request = RILQUIRKS_REQUEST_USE_DIAL_EMERGENCY_CALL ? REQUEST_DIAL_EMERGENCY_CALL : REQUEST_DIAL; + options.isEmergency = true; + if (this.radioState == GECKO_RADIOSTATE_OFF) { if (DEBUG) { this.context.debug("Automatically enable radio for an emergency call."); @@ -4109,10 +4111,6 @@ RilObject.prototype = { newCall.isOutgoing = true; } - if (newCall.isEmergency === undefined) { - newCall.isEmergency = false; - } - // Set flag for conference. newCall.isConference = newCall.isMpty ? true : false; diff --git a/dom/telephony/gonk/TelephonyService.js b/dom/telephony/gonk/TelephonyService.js index 635195b499d2..0265d32426da 100644 --- a/dom/telephony/gonk/TelephonyService.js +++ b/dom/telephony/gonk/TelephonyService.js @@ -23,7 +23,7 @@ const GONK_TELEPHONYSERVICE_CONTRACTID = const GONK_TELEPHONYSERVICE_CID = Components.ID("{67d26434-d063-4d28-9f48-5b3189788155}"); -const NS_XPCOM_SHUTDOWN_OBSERVER_ID = "xpcom-shutdown"; +const NS_XPCOM_SHUTDOWN_OBSERVER_ID = "xpcom-shutdown"; const NS_PREFBRANCH_PREFCHANGE_TOPIC_ID = "nsPref:changed"; @@ -41,6 +41,7 @@ const CDMA_SECOND_CALL_INDEX = 2; const DIAL_ERROR_INVALID_STATE_ERROR = "InvalidStateError"; const DIAL_ERROR_OTHER_CONNECTION_IN_USE = "OtherConnectionInUse"; +const DIAL_ERROR_BAD_NUMBER = RIL.GECKO_CALL_ERROR_BAD_NUMBER; const AUDIO_STATE_NO_CALL = 0; const AUDIO_STATE_INCOMING = 1; @@ -428,112 +429,119 @@ TelephonyService.prototype = { return hasConference ? numCalls + 1 : numCalls; }, + _addCdmaChildCall: function(aClientId, aNumber, aParentId) { + let childCall = { + callIndex: CDMA_SECOND_CALL_INDEX, + state: RIL.CALL_STATE_DIALING, + number: aNumber, + isOutgoing: true, + isEmergency: false, + isConference: false, + isSwitchable: false, + isMergeable: true, + parentId: aParentId + }; + + // Manual update call state according to the request response. + this.notifyCallStateChanged(aClientId, childCall); + + childCall.state = RIL.CALL_STATE_ACTIVE; + this.notifyCallStateChanged(aClientId, childCall); + + let parentCall = this._currentCalls[aClientId][childCall.parentId]; + parentCall.childId = CDMA_SECOND_CALL_INDEX; + parentCall.state = RIL.CALL_STATE_HOLDING; + parentCall.isSwitchable = false; + parentCall.isMergeable = true; + this.notifyCallStateChanged(aClientId, parentCall); + }, + isDialing: false, - dial: function(aClientId, aNumber, aIsEmergency, aTelephonyCallback) { - if (DEBUG) debug("Dialing " + (aIsEmergency ? "emergency " : "") + aNumber); + dial: function(aClientId, aNumber, aIsDialEmergency, aCallback) { + if (DEBUG) debug("Dialing " + (aIsDialEmergency ? "emergency " : "") + aNumber); if (this.isDialing) { if (DEBUG) debug("Error: Already has a dialing call."); - aTelephonyCallback.notifyDialError(DIAL_ERROR_INVALID_STATE_ERROR); + aCallback.notifyDialError(DIAL_ERROR_INVALID_STATE_ERROR); return; } - // Select a proper clientId for dialEmergency. - if (aIsEmergency) { - aClientId = gRadioInterfaceLayer.getClientIdForEmergencyCall() ; - if (aClientId === -1) { - if (DEBUG) debug("Error: No client is avaialble for emergency call."); - aTelephonyCallback.notifyDialError(DIAL_ERROR_INVALID_STATE_ERROR); - return; - } - } - // For DSDS, if there is aleady a call on SIM 'aClientId', we cannot place // any new call on other SIM. if (this._hasCallsOnOtherClient(aClientId)) { if (DEBUG) debug("Error: Already has a call on other sim."); - aTelephonyCallback.notifyDialError(DIAL_ERROR_OTHER_CONNECTION_IN_USE); + aCallback.notifyDialError(DIAL_ERROR_OTHER_CONNECTION_IN_USE); return; } // We can only have at most two calls on the same line (client). if (this._numCallsOnLine(aClientId) >= 2) { if (DEBUG) debug("Error: Has more than 2 calls on line."); - aTelephonyCallback.notifyDialError(DIAL_ERROR_INVALID_STATE_ERROR); + aCallback.notifyDialError(DIAL_ERROR_INVALID_STATE_ERROR); return; } // We don't try to be too clever here, as the phone is probably in the // locked state. Let's just check if it's a number without normalizing - if (!aIsEmergency) { + if (!aIsDialEmergency) { aNumber = gPhoneNumberUtils.normalize(aNumber); } // Validate the number. + // Note: isPlainPhoneNumber also accepts USSD and SS numbers if (!gPhoneNumberUtils.isPlainPhoneNumber(aNumber)) { - // Note: isPlainPhoneNumber also accepts USSD and SS numbers - if (DEBUG) debug("Number '" + aNumber + "' is not viable. Drop."); - let errorMsg = RIL.RIL_CALL_FAILCAUSE_TO_GECKO_CALL_ERROR[RIL.CALL_FAIL_UNOBTAINABLE_NUMBER]; - aTelephonyCallback.notifyDialError(errorMsg); + if (DEBUG) debug("Error: Number '" + aNumber + "' is not viable. Drop."); + aCallback.notifyDialError(DIAL_ERROR_BAD_NUMBER); return; } - function onCdmaDialSuccess(aCallIndex) { - let indexes = Object.keys(this._currentCalls[aClientId]); - if (indexes.length == 0) { - aTelephonyCallback.notifyDialSuccess(aCallIndex); + if (this._isEmergencyNumber(aNumber)) { + // Select a proper clientId for dialEmergency. + aClientId = gRadioInterfaceLayer.getClientIdForEmergencyCall() ; + + if (aClientId === -1) { + if (DEBUG) debug("Error: No client is avaialble for emergency call."); + aCallback.notifyDialError(DIAL_ERROR_INVALID_STATE_ERROR); return; } - // RIL doesn't hold the 2nd call. We create one by ourselves. - let childCall = { - callIndex: CDMA_SECOND_CALL_INDEX, - state: RIL.CALL_STATE_DIALING, - number: aNumber, - isOutgoing: true, - isEmergency: false, - isConference: false, - isSwitchable: false, - isMergeable: true, - parentId: indexes[0] - }; - aTelephonyCallback.notifyDialSuccess(CDMA_SECOND_CALL_INDEX); + this._dialInternal(aClientId, "dialEmergencyNumber", aNumber, aCallback); + } else { + // Shouldn't dial a non-emergency number by dialEmergency. + if (aIsDialEmergency) { + if (DEBUG) debug("Error: dialEmergency with a non-emergency number"); + aCallback.notifyDialError(DIAL_ERROR_BAD_NUMBER); + return; + } - // Manual update call state according to the request response. - this.notifyCallStateChanged(aClientId, childCall); + this._dialInternal(aClientId, "dialNonEmergencyNumber", aNumber, aCallback); + } + }, - childCall.state = RIL.CALL_STATE_ACTIVE; - this.notifyCallStateChanged(aClientId, childCall); - - let parentCall = this._currentCalls[aClientId][childCall.parentId]; - parentCall.childId = CDMA_SECOND_CALL_INDEX; - parentCall.state = RIL.CALL_STATE_HOLDING; - parentCall.isSwitchable = false; - parentCall.isMergeable = true; - this.notifyCallStateChanged(aClientId, parentCall); - }; - - let isEmergencyNumber = this._isEmergencyNumber(aNumber); - let msg = isEmergencyNumber ? - "dialEmergencyNumber" : - "dialNonEmergencyNumber"; + _dialInternal: function(aClientId, aMsg, aNumber, aCallback) { this.isDialing = true; - this._getClient(aClientId).sendWorkerMessage(msg, { - number: aNumber, - isEmergency: isEmergencyNumber, - isDialEmergency: aIsEmergency - }, (function(response) { + this._getClient(aClientId).sendWorkerMessage(aMsg, + {number: aNumber}, + (function(response) { this.isDialing = false; if (!response.success) { - aTelephonyCallback.notifyDialError(response.errorMsg); + aCallback.notifyDialError(response.errorMsg); return false; } - if (response.isCdma) { - onCdmaDialSuccess.call(this, response.callIndex); + if (!response.isCdma) { + aCallback.notifyDialSuccess(response.callIndex); } else { - aTelephonyCallback.notifyDialSuccess(response.callIndex); + let currentCallId = Object.keys(this._currentCalls[aClientId])[0]; + if (currentCallId === undefined) { + aCallback.notifyDialSuccess(response.callIndex); + } else { + // RIL doesn't hold the 2nd call. We create one by ourselves. + aCallback.notifyDialSuccess(CDMA_SECOND_CALL_INDEX); + this._addCdmaChildCall(aClientId, aNumber, currentCallId); + } } + return false; }).bind(this)); }, @@ -615,7 +623,7 @@ TelephonyService.prototype = { this.notifyCallStateChanged(aClientId, call); } this.notifyConferenceCallStateChanged(RIL.CALL_STATE_ACTIVE); - }; + } this._getClient(aClientId).sendWorkerMessage("conferenceCall", null, (function(response) { @@ -660,7 +668,7 @@ TelephonyService.prototype = { let childCall = this._currentCalls[aClientId][childId]; this.notifyCallDisconnected(aClientId, childCall); - }; + } this._getClient(aClientId).sendWorkerMessage("separateCall", { callIndex: aCallIndex @@ -825,28 +833,25 @@ TelephonyService.prototype = { aCall.clientId = aClientId; this._updateActiveCall(aCall); + function pick(arg, defaultValue) { + return typeof arg !== 'undefined' ? arg : defaultValue; + } + let call = this._currentCalls[aClientId][aCall.callIndex]; if (call) { call.state = aCall.state; call.isConference = aCall.isConference; - call.isEmergency = aCall.isEmergency; - call.isSwitchable = aCall.isSwitchable != null ? - aCall.isSwitchable : call.isSwitchable; - call.isMergeable = aCall.isMergeable != null ? - aCall.isMergeable : call.isMergeable; + call.isEmergency = pick(aCall.isEmergency, call.isEmergency); + call.isSwitchable = pick(aCall.isSwitchable, call.isSwitchable); + call.isMergeable = pick(aCall.isMergeable, call.isMergeable); } else { call = aCall; - call.isSwitchable = aCall.isSwitchable != null ? - aCall.isSwitchable : true; - call.isMergeable = aCall.isMergeable != null ? - aCall.isMergeable : true; - - call.numberPresentation = aCall.numberPresentation != null ? - aCall.numberPresentation : nsITelephonyService.CALL_PRESENTATION_ALLOWED; - call.name = aCall.name != null ? - aCall.name : ""; - call.namePresentation = aCall.namePresentation != null ? - aCall.namePresentation : nsITelephonyService.CALL_PRESENTATION_ALLOWED; + call.isEmergency = pick(aCall.isEmergency, this._isEmergencyNumber(aCall.number)); + call.isSwitchable = pick(aCall.isSwitchable, true); + call.isMergeable = pick(aCall.isMergeable, true); + call.name = pick(aCall.name, ""); + call.numberPresentaation = pick(aCall.numberPresentation, nsITelephonyService.CALL_PRESENTATION_ALLOWED); + call.namePresentaation = pick(aCall.namePresentation, nsITelephonyService.CALL_PRESENTATION_ALLOWED); this._currentCalls[aClientId][aCall.callIndex] = call; } diff --git a/dom/webidl/Navigator.webidl b/dom/webidl/Navigator.webidl index b9cccf0cfaea..1014855adfbb 100644 --- a/dom/webidl/Navigator.webidl +++ b/dom/webidl/Navigator.webidl @@ -86,6 +86,9 @@ interface NavigatorStorageUtils { interface NavigatorFeatures { [CheckPermissions="feature-detection", Throws] Promise getFeature(DOMString name); + + [CheckPermissions="feature-detection", Throws] + Promise hasFeature(DOMString name); }; // Things that definitely need to be in the spec and and are not for some @@ -195,13 +198,13 @@ partial interface Navigator { /** * Navigator requests to add an idle observer to the existing window. */ - [Throws, CheckPermissions="idle", Pref="dom.idle-observers-api.enabled"] + [Throws, CheckPermissions="idle"] void addIdleObserver(MozIdleObserver aIdleObserver); /** * Navigator requests to remove an idle observer from the existing window. */ - [Throws, CheckPermissions="idle", Pref="dom.idle-observers-api.enabled"] + [Throws, CheckPermissions="idle"] void removeIdleObserver(MozIdleObserver aIdleObserver); /** diff --git a/dom/webidl/ResourceStats.webidl b/dom/webidl/ResourceStats.webidl index 6d6c2f0d2105..b356a3eec7ed 100644 --- a/dom/webidl/ResourceStats.webidl +++ b/dom/webidl/ResourceStats.webidl @@ -7,7 +7,6 @@ [CheckPermissions="resourcestats-manage", Pref="dom.resource_stats.enabled", AvailableIn="CertifiedApps", -// FeatureDetectible, // This should be specified after Bug 1009645 is resolved. JSImplementation="@mozilla.org/networkStatsData;1"] interface NetworkStatsData { @@ -19,7 +18,6 @@ interface NetworkStatsData [CheckPermissions="resourcestats-manage", Pref="dom.resource_stats.enabled", AvailableIn="CertifiedApps", -// FeatureDetectible, // This should be specified after Bug 1009645 is resolved. JSImplementation="@mozilla.org/powerStatsData;1"] interface PowerStatsData { @@ -30,7 +28,6 @@ interface PowerStatsData [CheckPermissions="resourcestats-manage", Pref="dom.resource_stats.enabled", AvailableIn="CertifiedApps", -// FeatureDetectible, // This should be specified after Bug 1009645 is resolved. JSImplementation="@mozilla.org/resourceStats;1"] interface ResourceStats { diff --git a/dom/webidl/ResourceStatsManager.webidl b/dom/webidl/ResourceStatsManager.webidl index d7facef475a1..dfb59ea47dc5 100644 --- a/dom/webidl/ResourceStatsManager.webidl +++ b/dom/webidl/ResourceStatsManager.webidl @@ -73,7 +73,6 @@ dictionary ResourceStatsAlarmOptions [CheckPermissions="resourcestats-manage", Pref="dom.resource_stats.enabled", AvailableIn="CertifiedApps", -// FeatureDetectible, // This should be specified after Bug 1009645 is resolved. JSImplementation="@mozilla.org/resourceStatsAlarm;1"] interface ResourceStatsAlarm { @@ -117,7 +116,6 @@ interface ResourceStatsAlarm Pref="dom.resource_stats.enabled", Constructor(ResourceType type), AvailableIn="CertifiedApps", -// FeatureDetectible, // This should be specified after Bug 1009645 is resolved. JSImplementation="@mozilla.org/resourceStatsManager;1"] interface ResourceStatsManager { diff --git a/mobile/android/base/toolbar/TabCounter.java b/mobile/android/base/toolbar/TabCounter.java index b991ac46dc9a..770edc373ff5 100644 --- a/mobile/android/base/toolbar/TabCounter.java +++ b/mobile/android/base/toolbar/TabCounter.java @@ -133,7 +133,7 @@ public class TabCounter extends ThemedTextSwitcher @Override public View makeView() { - return mInflater.inflate(mLayoutId, this, false); + return mInflater.inflate(mLayoutId, null); } } diff --git a/toolkit/components/search/SearchSuggestionController.jsm b/toolkit/components/search/SearchSuggestionController.jsm index 74f4413916f8..64aeb5a41e52 100644 --- a/toolkit/components/search/SearchSuggestionController.jsm +++ b/toolkit/components/search/SearchSuggestionController.jsm @@ -17,6 +17,16 @@ const SEARCH_RESPONSE_SUGGESTION_JSON = "application/x-suggestions+json"; const DEFAULT_FORM_HISTORY_PARAM = "searchbar-history"; const HTTP_OK = 200; const REMOTE_TIMEOUT = 500; // maximum time (ms) to wait before giving up on a remote suggestions +const BROWSER_SUGGEST_PREF = "browser.search.suggest.enabled"; + +/** + * Remote search suggestions will be shown if gRemoteSuggestionsEnabled + * is true. Global because only one pref observer is needed for all instances. + */ +let gRemoteSuggestionsEnabled = Services.prefs.getBoolPref(BROWSER_SUGGEST_PREF); +Services.prefs.addObserver(BROWSER_SUGGEST_PREF, function(aSubject, aTopic, aData) { + gRemoteSuggestionsEnabled = Services.prefs.getBoolPref(BROWSER_SUGGEST_PREF); +}, false); /** * SearchSuggestionController.jsm exists as a helper module to allow multiple consumers to request and display @@ -124,7 +134,7 @@ this.SearchSuggestionController.prototype = { this._searchString = searchTerm; // Remote results - if (searchTerm && this.maxRemoteResults && + if (searchTerm && gRemoteSuggestionsEnabled && this.maxRemoteResults && engine.supportsResponseType(SEARCH_RESPONSE_SUGGESTION_JSON)) { this._deferredRemoteResult = this._fetchRemote(searchTerm, engine, privateMode); promises.push(this._deferredRemoteResult.promise); diff --git a/toolkit/components/search/nsSearchSuggestions.js b/toolkit/components/search/nsSearchSuggestions.js index cbe7e5e64110..8e232bf651fc 100644 --- a/toolkit/components/search/nsSearchSuggestions.js +++ b/toolkit/components/search/nsSearchSuggestions.js @@ -2,10 +2,6 @@ * 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/. */ -const BROWSER_SUGGEST_PREF = "browser.search.suggest.enabled"; -const XPCOM_SHUTDOWN_TOPIC = "xpcom-shutdown"; -const NS_PREFBRANCH_PREFCHANGE_TOPIC_ID = "nsPref:changed"; - const { classes: Cc, interfaces: Ci, utils: Cu, results: Cr } = Components; Cu.import("resource://gre/modules/XPCOMUtils.jsm"); @@ -28,8 +24,6 @@ function SuggestAutoComplete() { SuggestAutoComplete.prototype = { _init: function() { - this._addObservers(); - this._suggestEnabled = Services.prefs.getBoolPref(BROWSER_SUGGEST_PREF); this._suggestionController = new SearchSuggestionController(obj => this.onResultsReturned(obj)); }, @@ -39,11 +33,6 @@ SuggestAutoComplete.prototype = { return this._suggestionLabel = bundle.GetStringFromName("suggestion_label"); }, - /** - * Search suggestions will be shown if this._suggestEnabled is true. - */ - _suggestEnabled: null, - /** * The object implementing nsIAutoCompleteObserver that we notify when * we have found results @@ -178,32 +167,6 @@ SuggestAutoComplete.prototype = { this._suggestionController.stop(); }, - /** - * nsIObserver - */ - observe: function SAC_observe(aSubject, aTopic, aData) { - switch (aTopic) { - case NS_PREFBRANCH_PREFCHANGE_TOPIC_ID: - this._suggestEnabled = Services.prefs.getBoolPref(BROWSER_SUGGEST_PREF); - break; - case XPCOM_SHUTDOWN_TOPIC: - this._removeObservers(); - break; - } - }, - - _addObservers: function SAC_addObservers() { - Services.prefs.addObserver(BROWSER_SUGGEST_PREF, this, false); - - Services.obs.addObserver(this, XPCOM_SHUTDOWN_TOPIC, false); - }, - - _removeObservers: function SAC_removeObservers() { - Services.prefs.removeObserver(BROWSER_SUGGEST_PREF, this); - - Services.obs.removeObserver(this, XPCOM_SHUTDOWN_TOPIC); - }, - // nsISupports QueryInterface: XPCOMUtils.generateQI([Ci.nsIAutoCompleteSearch, Ci.nsIAutoCompleteObserver]) diff --git a/toolkit/components/search/tests/xpcshell/test_searchSuggest.js b/toolkit/components/search/tests/xpcshell/test_searchSuggest.js index 36ea60dc9302..b80bebf8621c 100644 --- a/toolkit/components/search/tests/xpcshell/test_searchSuggest.js +++ b/toolkit/components/search/tests/xpcshell/test_searchSuggest.js @@ -278,6 +278,49 @@ add_task(function* one_of_each() { do_check_eq(result.remote[0], "letter B"); }); +add_task(function* local_result_returned_remote_result_disabled() { + Services.prefs.setBoolPref("browser.search.suggest.enabled", false); + let controller = new SearchSuggestionController(); + controller.maxLocalResults = 1; + controller.maxRemoteResults = 1; + let result = yield controller.fetch("letter ", false, getEngine); + do_check_eq(result.term, "letter "); + do_check_eq(result.local.length, 1); + do_check_eq(result.local[0], "letter A"); + do_check_eq(result.remote.length, 0); + Services.prefs.clearUserPref("browser.search.suggest.enabled"); +}); + +add_task(function* local_result_returned_remote_result_disabled_after_creation_of_controller() { + let controller = new SearchSuggestionController(); + controller.maxLocalResults = 1; + controller.maxRemoteResults = 1; + Services.prefs.setBoolPref("browser.search.suggest.enabled", false); + let result = yield controller.fetch("letter ", false, getEngine); + do_check_eq(result.term, "letter "); + do_check_eq(result.local.length, 1); + do_check_eq(result.local[0], "letter A"); + do_check_eq(result.remote.length, 0); +}); + +add_task(function* one_of_each_disabled_before_creation_enabled_after_creation_of_controller() { + Services.prefs.setBoolPref("browser.search.suggest.enabled", false); + let controller = new SearchSuggestionController(); + controller.maxLocalResults = 1; + controller.maxRemoteResults = 1; + Services.prefs.setBoolPref("browser.search.suggest.enabled", true); + let result = yield controller.fetch("letter ", false, getEngine); + do_check_eq(result.term, "letter "); + do_check_eq(result.local.length, 1); + do_check_eq(result.local[0], "letter A"); + do_check_eq(result.remote.length, 1); + do_check_eq(result.remote[0], "letter B"); +}); + +add_task(function* clear_suggestions_pref() { + Services.prefs.clearUserPref("browser.search.suggest.enabled"); +}); + add_task(function* one_local_zero_remote() { let controller = new SearchSuggestionController(); controller.maxLocalResults = 1; diff --git a/toolkit/content/autocomplete.css b/toolkit/content/autocomplete.css new file mode 100644 index 000000000000..249c7ebf9c10 --- /dev/null +++ b/toolkit/content/autocomplete.css @@ -0,0 +1,13 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +@namespace url("http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"); +@namespace html url("http://www.w3.org/1999/xhtml"); + +/* Apply crisp rendering for favicons at exactly 2dppx resolution */ +@media (resolution: 2dppx) { + .ac-site-icon { + image-rendering: -moz-crisp-edges; + } +} diff --git a/toolkit/content/jar.mn b/toolkit/content/jar.mn index 60000211d24d..54ad0d66e551 100644 --- a/toolkit/content/jar.mn +++ b/toolkit/content/jar.mn @@ -11,6 +11,7 @@ toolkit.jar: * content/global/xul.css (xul.css) content/global/textbox.css (textbox.css) content/global/menulist.css (menulist.css) + content/global/autocomplete.css (autocomplete.css) content/global/about.js (about.js) content/global/about.xhtml (about.xhtml) content/global/aboutAbout.js (aboutAbout.js) diff --git a/toolkit/content/widgets/autocomplete.xml b/toolkit/content/widgets/autocomplete.xml index 58dc9af6f4dc..cb83860817cb 100644 --- a/toolkit/content/widgets/autocomplete.xml +++ b/toolkit/content/widgets/autocomplete.xml @@ -19,6 +19,7 @@ + @@ -598,6 +599,7 @@ + @@ -929,6 +931,7 @@ extends="chrome://global/content/bindings/popup.xml#popup"> + diff --git a/toolkit/devtools/server/protocol.js b/toolkit/devtools/server/protocol.js index e3290728eca2..9176ee2a447d 100644 --- a/toolkit/devtools/server/protocol.js +++ b/toolkit/devtools/server/protocol.js @@ -448,13 +448,11 @@ let Option = Class({ }, write: function(arg, ctx, name) { - if (!arg) { - return undefined; - } - let v = arg[name] || undefined; - if (v === undefined) { + // Ignore if arg is undefined or null; allow other falsy values + if (arg == undefined || arg[name] == undefined) { return undefined; } + let v = arg[name]; return this.type.write(v, ctx); }, read: function(v, ctx, outArgs, name) { diff --git a/toolkit/devtools/server/tests/unit/test_protocol_simple.js b/toolkit/devtools/server/tests/unit/test_protocol_simple.js index 8bb6d285fa6a..264baf811483 100644 --- a/toolkit/devtools/server/tests/unit/test_protocol_simple.js +++ b/toolkit/devtools/server/tests/unit/test_protocol_simple.js @@ -132,8 +132,18 @@ let RootActor = protocol.ActorClass({ oneway: true }), + emitFalsyOptions: method(function() { + events.emit(this, "falsyOptions", { zero: 0, farce: false }); + }, { + oneway: true + }), + events: { - "oneway": { a: Arg(0) } + "oneway": { a: Arg(0) }, + "falsyOptions": { + zero: Option(0), + farce: Option(0) + } } }); @@ -223,7 +233,7 @@ function run_test() trace.expectReceive({"from":""}); do_check_true(typeof(ret.option1) === "undefined"); do_check_true(typeof(ret.option2) === "undefined"); - }).then(ret => { + }).then(() => { // Explicitly call an optional argument... return rootClient.optionalArgs(5, 10); }).then(ret => { @@ -268,6 +278,18 @@ function run_test() }); do_check_true(typeof(rootClient.testOneWay("hello")) === "undefined"); return deferred.promise; + }).then(() => { + let deferred = promise.defer(); + rootClient.on("falsyOptions", res => { + trace.expectSend({"type":"emitFalsyOptions", "to":""}); + trace.expectReceive({"type":"falsyOptions", "farce":false, "zero": 0, "from":""}); + + do_check_true(res.zero === 0); + do_check_true(res.farce === false); + deferred.resolve(); + }); + rootClient.emitFalsyOptions(); + return deferred.promise; }).then(() => { client.close(() => { do_test_finished(); diff --git a/toolkit/mozapps/extensions/test/browser/browser_openH264.js b/toolkit/mozapps/extensions/test/browser/browser_openH264.js index 8754d7e5a77f..7e33c0f6b7ac 100644 --- a/toolkit/mozapps/extensions/test/browser/browser_openH264.js +++ b/toolkit/mozapps/extensions/test/browser/browser_openH264.js @@ -262,6 +262,7 @@ add_task(function* testUpdateButton() { yield gInstallDeferred.promise; Assert.equal(gInstalledAddonId, OPENH264_PLUGIN_ID); + delete OpenH264Scope.GMPInstallManager; }); add_task(function* test_cleanup() { diff --git a/toolkit/themes/osx/global/autocomplete.css b/toolkit/themes/osx/global/autocomplete.css index 92d6e2a17761..318af07b6a10 100644 --- a/toolkit/themes/osx/global/autocomplete.css +++ b/toolkit/themes/osx/global/autocomplete.css @@ -114,12 +114,6 @@ treechildren.autocomplete-treebody::-moz-tree-cell-text(selected) { -moz-margin-end: 5px; } -@media (min-resolution: 2dppx) { - image.ac-site-icon { - image-rendering: -moz-crisp-edges; - } -} - .ac-type-icon { width: 16px; height: 16px;