diff --git a/b2g/app/b2g.js b/b2g/app/b2g.js index 73cc8138eeca..baea1419827b 100644 --- a/b2g/app/b2g.js +++ b/b2g/app/b2g.js @@ -554,6 +554,8 @@ pref("hal.processPriorityManager.gonk.masterOomScoreAdjust", 0); pref("hal.processPriorityManager.gonk.masterKillUnderMB", 1); pref("hal.processPriorityManager.gonk.foregroundOomScoreAdjust", 67); pref("hal.processPriorityManager.gonk.foregroundKillUnderMB", 4); +pref("hal.processPriorityManager.gonk.backgroundHomescreenOomScoreAdjust", 200); +pref("hal.processPriorityManager.gonk.backgroundHomescreenKillUnderMB", 5); pref("hal.processPriorityManager.gonk.backgroundOomScoreAdjust", 400); pref("hal.processPriorityManager.gonk.backgroundKillUnderMB", 8); pref("hal.processPriorityManager.gonk.notifyLowMemUnderMB", 10); diff --git a/b2g/config/tooltool-manifests/macosx64/releng.manifest b/b2g/config/tooltool-manifests/macosx64/releng.manifest index 3cb17242b31a..26e984142146 100644 --- a/b2g/config/tooltool-manifests/macosx64/releng.manifest +++ b/b2g/config/tooltool-manifests/macosx64/releng.manifest @@ -1,6 +1,6 @@ [ { -"clang_version": "r169730" +"clang_version": "r170377" }, { "size": 47, @@ -9,8 +9,8 @@ "filename": "setup.sh" }, { -"size": 56115091, -"digest": "d7188264f28d6f6a84fab9737520cad22fe3d575917a87fc110d0b9a2033617c35da83530ea20553f5c55a996459f750fa2d0c49288c1fb9671f6252a92cf4c9", +"size": 56131193, +"digest": "a1e705d3a72e0e95eeb15722f538a3908277f9f756909ce5e67f0a09b8531c1ba7fcc4816e20795af2e98839e0308b1bc6df95308cda310ae06abf21d429624f", "algorithm": "sha512", "filename": "clang.tar.bz2" } diff --git a/browser/base/content/test/social/Makefile.in b/browser/base/content/test/social/Makefile.in index 10a591bc7ccf..2d26d8a3d0f3 100644 --- a/browser/base/content/test/social/Makefile.in +++ b/browser/base/content/test/social/Makefile.in @@ -20,7 +20,7 @@ _BROWSER_FILES = \ browser_social_mozSocial_API.js \ browser_social_isVisible.js \ browser_social_chatwindow.js \ - $(filter disabled-temporarily--bug-820489, browser_social_multiprovider.js) \ + browser_social_multiprovider.js \ social_panel.html \ social_share_image.png \ social_sidebar.html \ diff --git a/browser/base/content/test/social/browser_social_toolbar.js b/browser/base/content/test/social/browser_social_toolbar.js index 72e6a0c9a83a..f28bbc1717a9 100644 --- a/browser/base/content/test/social/browser_social_toolbar.js +++ b/browser/base/content/test/social/browser_social_toolbar.js @@ -17,6 +17,23 @@ function test() { } var tests = { + testProfileNone: function(next, useNull) { + let profile = useNull ? null : {}; + Social.provider.updateUserProfile(profile); + // check dom values + let portrait = document.getElementsByClassName("social-statusarea-user-portrait")[0].getAttribute("src"); + // this is the default image for the profile area when not logged in. + is(portrait, "chrome://global/skin/icons/information-32.png", "portrait is empty"); + let userDetailsBroadcaster = document.getElementById("socialBroadcaster_userDetails"); + let notLoggedInStatusValue = userDetailsBroadcaster.getAttribute("notLoggedInLabel"); + let userButton = document.getElementsByClassName("social-statusarea-loggedInStatus")[0]; + ok(!userButton.hidden, "username is visible"); + is(userButton.getAttribute("label"), notLoggedInStatusValue, "label reflects not being logged in"); + next(); + }, + testProfileNull: function(next) { + this.testProfileNone(next, true); + }, testProfileSet: function(next) { let profile = { portrait: "https://example.com/portrait.jpg", diff --git a/browser/components/places/content/downloadsView.js b/browser/components/places/content/downloadsView.js index 0ccc5029f053..90cf7cab0612 100644 --- a/browser/components/places/content/downloadsView.js +++ b/browser/components/places/content/downloadsView.js @@ -118,6 +118,12 @@ DownloadElementShell.prototype = { throw new Error("Unexpected download element state"); }, + get _downloadURIObj() { + if (!("__downloadURIObj" in this)) + this.__downloadURIObj = NetUtil.newURI(this.downloadURI); + return this.__downloadURIObj; + }, + get _icon() { if (this._targetFileURI) return "moz-icon://" + this._targetFileURI + "?size=32"; @@ -136,7 +142,7 @@ DownloadElementShell.prototype = { let value; try { value = PlacesUtils.annotations.getPageAnnotation( - NetUtil.newURI(this.downloadURI), aAnnotation); + this._downloadURIObj, aAnnotation); } catch(ex) { if (aDefaultValue === undefined) { @@ -466,7 +472,7 @@ DownloadElementShell.prototype = { if (this._dataItem) this._dataItem.remove(); if (this._placesNode) - PlacesUtils.bhistory.removePage(NetUtil.newURI(this.downloadURI)); + PlacesUtils.bhistory.removePage(this._downloadURIObj); break; } case "downloadsCmd_retry": { @@ -577,18 +583,35 @@ DownloadsPlacesView.prototype = { } }, - // Given a data item for a session download, or a places node for a past - // download, updates the view as necessary. - // 1. If the given data is a places node, we check whether there are any - // element for the same download url. If there are, then we just reset - // their places node. Otherwise we add a new download element. - // 2. If the given data is a data item, we first check if there's an history - // download in the list that is not associated with a data item. If we found - // one, we use it for the data item as well and reposition it alongside the - // other session downloads. If we don't, then we go ahead and create a new - // element for the download. + /** + * Given a data item for a session download, or a places node for a past + * download, updates the view as necessary. + * 1. If the given data is a places node, we check whether there are any + * elements for the same download url. If there are, then we just reset + * their places node. Otherwise we add a new download element. + * 2. If the given data is a data item, we first check if there's a history + * download in the list that is not associated with a data item. If we + * found one, we use it for the data item as well and reposition it + * alongside the other session downloads. If we don't, then we go ahead + * and create a new element for the download. + * + * @param aDataItem + * The data item of a session download. Set to null for history + * downloads data. + * @param [optional] aPlacesNode + * The places node for a history download. Required if there's no data + * item. + * @param [optional] aNewest + * @see onDataItemAdded. Ignored for history downlods. + * @param [optional] aDocumentFragment + * To speed up the appending of multiple elements to the end of the + * list which are coming in a single batch (i.e. invalidateContainer), + * a document fragment may be passed to which the new elements would + * be appended. It's the caller's job to ensure the fragment is merged + * to the richlistbox at the end. + */ _addDownloadData: - function DPV_addDownload(aDataItem, aPlacesNode, aNewest) { + function DPV_addDownload(aDataItem, aPlacesNode, aNewest = false, aDocumentFragment = null) { let downloadURI = aPlacesNode ? aPlacesNode.uri : aDataItem.uri; let shellsForURI = this._downloadElementsShellsForURI.get(downloadURI, null); if (!shellsForURI) { @@ -658,12 +681,13 @@ DownloadsPlacesView.prototype = { } else if (aDataItem) { let before = this._lastSessionDownloadElement ? - this._lastSessionDownloadElement.nextSibling : this._richlistbox.firstChild - this._richlistbox.insertBefore(newOrUpdatedShell.element, before) + this._lastSessionDownloadElement.nextSibling : this._richlistbox.firstChild; + this._richlistbox.insertBefore(newOrUpdatedShell.element, before); this._lastSessionDownloadElement = newOrUpdatedShell.element; } else { - this._richlistbox.appendChild(newOrUpdatedShell.element); + let appendTo = aDocumentFragment || this._richlistbox; + appendTo.appendChild(newOrUpdatedShell.element); } if (this.searchTerm) { @@ -821,18 +845,22 @@ DownloadsPlacesView.prototype = { this._removeHistoryDownloadFromView(element._shell.placesNode); } + let elementsToAppendFragment = document.createDocumentFragment(); for (let i = 0; i < aContainer.childCount; i++) { try { - this._addDownloadData(null, aContainer.getChild(i), false) + this._addDownloadData(null, aContainer.getChild(i), false, + elementsToAppendFragment); } catch(ex) { Cu.reportError(ex); } } + + this._richlistbox.appendChild(elementsToAppendFragment); }, nodeInserted: function DPV_nodeInserted(aParent, aPlacesNode) { - this._addDownloadData(null, aPlacesNode, false); + this._addDownloadData(null, aPlacesNode); }, nodeRemoved: function DPV_nodeRemoved(aParent, aPlacesNode, aOldIndex) { @@ -895,7 +923,7 @@ DownloadsPlacesView.prototype = { }, onDataItemRemoved: function DPV_onDataItemRemoved(aDataItem) { - this._removeSessionDownloadFromView(aDataItem) + this._removeSessionDownloadFromView(aDataItem); }, getViewItem: function(aDataItem) @@ -939,7 +967,7 @@ DownloadsPlacesView.prototype = { Services.clipboard.getData(trans, Services.clipboard.kGlobalClipboard); - // Getting the data or creating the nsIURI might fail + // Getting the data or creating the nsIURI might fail. try { let data = {}; trans.getAnyTransferData({}, data, {}); diff --git a/browser/components/sessionstore/src/SessionStore.jsm b/browser/components/sessionstore/src/SessionStore.jsm index 9b721e68ffd7..fc119082dabe 100644 --- a/browser/components/sessionstore/src/SessionStore.jsm +++ b/browser/components/sessionstore/src/SessionStore.jsm @@ -1273,8 +1273,8 @@ let SessionStoreInternal = { // If this tab was in the middle of restoring or still needs to be restored, // we need to reset that state. If the tab was restoring, we will attempt to // restore the next tab. - let previousState; - if (previousState = browser.__SS_restoreState) { + let previousState = browser.__SS_restoreState; + if (previousState) { this._resetTabRestoringState(aTab); if (previousState == TAB_STATE_RESTORING) this.restoreNextTab(); diff --git a/browser/components/sessionstore/test/Makefile.in b/browser/components/sessionstore/test/Makefile.in index 415f06819748..5d848ca5617e 100644 --- a/browser/components/sessionstore/test/Makefile.in +++ b/browser/components/sessionstore/test/Makefile.in @@ -142,6 +142,7 @@ else MOCHITEST_BROWSER_FILES += \ browser_248970_a.js \ browser_248970_b.js \ ++ browser_248970_b_perwindowpb.js \ browser_354894.js \ browser_394759_privatebrowsing.js \ $(NULL) diff --git a/browser/components/sessionstore/test/browser_248970_b_perwindowpb.js b/browser/components/sessionstore/test/browser_248970_b_perwindowpb.js new file mode 100644 index 000000000000..13334fb28d5f --- /dev/null +++ b/browser/components/sessionstore/test/browser_248970_b_perwindowpb.js @@ -0,0 +1,167 @@ +/* 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/. */ + +function test() { + /** Test (B) for Bug 248970 **/ + waitForExplicitFinish(); + + let windowsToClose = []; + let file = Services.dirsvc.get("TmpD", Ci.nsIFile); + let filePath = file.path; + let fieldList = { + "//input[@name='input']": Date.now().toString(), + "//input[@name='spaced 1']": Math.random().toString(), + "//input[3]": "three", + "//input[@type='checkbox']": true, + "//input[@name='uncheck']": false, + "//input[@type='radio'][1]": false, + "//input[@type='radio'][2]": true, + "//input[@type='radio'][3]": false, + "//select": 2, + "//select[@multiple]": [1, 3], + "//textarea[1]": "", + "//textarea[2]": "Some text... " + Math.random(), + "//textarea[3]": "Some more text\n" + new Date(), + "//input[@type='file']": filePath + }; + + registerCleanupFunction(function() { + windowsToClose.forEach(function(win) { + win.close(); + }); + }); + + function test(aLambda) { + try { + return aLambda() || true; + } catch(ex) { } + return false; + } + + function getElementByXPath(aTab, aQuery) { + let doc = aTab.linkedBrowser.contentDocument; + let xptype = Ci.nsIDOMXPathResult.FIRST_ORDERED_NODE_TYPE; + return doc.evaluate(aQuery, doc, null, xptype, null).singleNodeValue; + } + + function setFormValue(aTab, aQuery, aValue) { + let node = getElementByXPath(aTab, aQuery); + if (typeof aValue == "string") + node.value = aValue; + else if (typeof aValue == "boolean") + node.checked = aValue; + else if (typeof aValue == "number") + node.selectedIndex = aValue; + else + Array.forEach(node.options, function(aOpt, aIx) + (aOpt.selected = aValue.indexOf(aIx) > -1)); + } + + function compareFormValue(aTab, aQuery, aValue) { + let node = getElementByXPath(aTab, aQuery); + if (!node) + return false; + if (node instanceof Ci.nsIDOMHTMLInputElement) + return aValue == (node.type == "checkbox" || node.type == "radio" ? + node.checked : node.value); + if (node instanceof Ci.nsIDOMHTMLTextAreaElement) + return aValue == node.value; + if (!node.multiple) + return aValue == node.selectedIndex; + return Array.every(node.options, function(aOpt, aIx) + (aValue.indexOf(aIx) > -1) == aOpt.selected); + } + + ////////////////////////////////////////////////////////////////// + // Test (B) : Session data restoration between windows // + ////////////////////////////////////////////////////////////////// + + let rootDir = getRootDirectory(gTestPath); + const testURL = rootDir + "browser_248970_b_sample.html"; + const testURL2 = "http://mochi.test:8888/browser/" + + "browser/components/sessionstore/test/browser_248970_b_sample.html"; + + whenNewWindowLoaded(false, function(aWin) { + windowsToClose.push(aWin); + + // get closed tab count + let count = ss.getClosedTabCount(aWin); + let max_tabs_undo = + Services.prefs.getIntPref("browser.sessionstore.max_tabs_undo"); + ok(0 <= count && count <= max_tabs_undo, + "getClosedTabCount should return zero or at most max_tabs_undo"); + + // setup a state for tab (A) so we can check later that is restored + let key = "key"; + let value = "Value " + Math.random(); + let state = { entries: [{ url: testURL }], extData: { key: value } }; + + // public session, add new tab: (A) + let tab_A = aWin.gBrowser.addTab(testURL); + ss.setTabState(tab_A, JSON.stringify(state)); + whenBrowserLoaded(tab_A.linkedBrowser, function() { + // make sure that the next closed tab will increase getClosedTabCount + Services.prefs.setIntPref( + "browser.sessionstore.max_tabs_undo", max_tabs_undo + 1) + + // populate tab_A with form data + for (let i in fieldList) + setFormValue(tab_A, i, fieldList[i]); + + // public session, close tab: (A) + aWin.gBrowser.removeTab(tab_A); + + // verify that closedTabCount increased + ok(ss.getClosedTabCount(aWin) > count, + "getClosedTabCount has increased after closing a tab"); + + // verify tab: (A), in undo list + let tab_A_restored = test(function() ss.undoCloseTab(aWin, 0)); + ok(tab_A_restored, "a tab is in undo list"); + whenBrowserLoaded(tab_A_restored.linkedBrowser, function() { + is(testURL, tab_A_restored.linkedBrowser.currentURI.spec, + "it's the same tab that we expect"); + aWin.gBrowser.removeTab(tab_A_restored); + + whenNewWindowLoaded(true, function(aWin) { + windowsToClose.push(aWin); + + // setup a state for tab (B) so we can check that its duplicated + // properly + let key1 = "key1"; + let value1 = "Value " + Math.random(); + let state1 = { + entries: [{ url: testURL2 }], extData: { key1: value1 } + }; + + let tab_B = aWin.gBrowser.addTab(testURL2); + ss.setTabState(tab_B, JSON.stringify(state1)); + whenBrowserLoaded(tab_B.linkedBrowser, function() { + // populate tab: (B) with different form data + for (let item in fieldList) + setFormValue(tab_B, item, fieldList[item]); + + // duplicate tab: (B) + let tab_C = aWin.gBrowser.duplicateTab(tab_B); + whenBrowserLoaded(tab_C.linkedBrowser, function() { + // verify the correctness of the duplicated tab + is(ss.getTabValue(tab_C, key1), value1, + "tab successfully duplicated - correct state"); + + for (let item in fieldList) + ok(compareFormValue(tab_C, item, fieldList[item]), + "The value for \"" + item + "\" was correctly duplicated"); + + // private browsing session, close tab: (C) and (B) + aWin.gBrowser.removeTab(tab_C); + aWin.gBrowser.removeTab(tab_B); + + finish(); + }); + }); + }); + }); + }); + }); +} diff --git a/browser/components/sessionstore/test/head.js b/browser/components/sessionstore/test/head.js index 78439d947955..5ede7a0c9c65 100644 --- a/browser/components/sessionstore/test/head.js +++ b/browser/components/sessionstore/test/head.js @@ -277,3 +277,11 @@ function closeAllButPrimaryWindow() { } } } + +function whenNewWindowLoaded(aIsPrivate, aCallback) { + let win = OpenBrowserWindow({private: aIsPrivate}); + win.addEventListener("load", function onLoad() { + win.removeEventListener("load", onLoad, false); + aCallback(win); + }, false); +} diff --git a/browser/components/tabview/ui.js b/browser/components/tabview/ui.js index 5e70e5aae2cb..33a1ed6d1501 100644 --- a/browser/components/tabview/ui.js +++ b/browser/components/tabview/ui.js @@ -64,6 +64,7 @@ let UI = { // the operation interactive. _maxInteractiveWait: 250, +#ifndef MOZ_PER_WINDOW_PRIVATE_BROWSING // Variable: _privateBrowsing // Keeps track of info related to private browsing, including: // transitionMode - whether we're entering or exiting PB @@ -72,7 +73,8 @@ let UI = { transitionMode: "", wasInTabView: false }, - +#endif + // Variable: _storageBusy // Tells whether the storage is currently busy or not. _storageBusy: false, @@ -595,8 +597,13 @@ let UI = { // ---------- // Function: storageBusy +#ifdef MOZ_PER_WINDOW_PRIVATE_BROWSING + // Pauses the storage activity that conflicts with sessionstore updates. + // Calls can be nested. +#else // Pauses the storage activity that conflicts with sessionstore updates and // private browsing mode switches. Calls can be nested. +#endif storageBusy: function UI_storageBusy() { if (this._storageBusy) return; @@ -649,6 +656,7 @@ let UI = { gWindow.removeEventListener("SSWindowStateReady", handleSSWindowStateReady, false); }); +#ifndef MOZ_PER_WINDOW_PRIVATE_BROWSING // Private Browsing: // When transitioning to PB, we exit Panorama if necessary (making note of the // fact that we were there so we can return after PB) and make sure we @@ -689,6 +697,7 @@ let UI = { Services.obs.removeObserver(pbObserver, "private-browsing-change-granted"); Services.obs.removeObserver(pbObserver, "private-browsing-transition-complete"); }); +#endif // TabOpen this._eventListeners.open = function (event) { @@ -714,7 +723,11 @@ let UI = { if (self._currentTab == tab) self._closedSelectedTabInTabView = true; } else { +#ifdef MOZ_PER_WINDOW_PRIVATE_BROWSING + // If we're currently in the process of session store update, +#else // If we're currently in the process of entering private browsing, +#endif // we don't want to go to the Tab View UI. if (self._storageBusy) return; @@ -825,9 +838,14 @@ let UI = { if (this.isTabViewVisible()) { // We want to zoom in if: // 1) we didn't just restore a tab via Ctrl+Shift+T +#ifdef MOZ_PER_WINDOW_PRIVATE_BROWSING + // 2) the currently selected tab is the last created tab and has a tabItem + if (!this.restoredClosedTab && +#else // 2) we're not in the middle of switching from/to private browsing // 3) the currently selected tab is the last created tab and has a tabItem if (!this.restoredClosedTab && !this._privateBrowsing.transitionMode && +#endif this._lastOpenedTab == tab && tab._tabViewTabItem) { tab._tabViewTabItem.zoomIn(true); this._lastOpenedTab = null; @@ -1012,8 +1030,10 @@ let UI = { #ifdef XP_MACOSX "fullScreen", #endif - "closeWindow", "tabview", "undoCloseTab", "undoCloseWindow", - "privatebrowsing" + "closeWindow", "tabview", "undoCloseTab", "undoCloseWindow" +#ifndef MOZ_PER_WINDOW_PRIVATE_BROWSING + , "privatebrowsing" +#endif ].forEach(function(key) { let element = gWindow.document.getElementById("key_" + key); let code = element.getAttribute("key").toLocaleLowerCase().charCodeAt(0); diff --git a/browser/config/tooltool-manifests/linux32/clang.manifest b/browser/config/tooltool-manifests/linux32/clang.manifest index 988484b307ca..50059dc267a8 100644 --- a/browser/config/tooltool-manifests/linux32/clang.manifest +++ b/browser/config/tooltool-manifests/linux32/clang.manifest @@ -1,6 +1,6 @@ [ { -"clang_version": "r169730" +"clang_version": "r170377" }, { "size": 47, @@ -9,8 +9,8 @@ "filename": "setup.sh" }, { -"size": 61875575, -"digest": "7098e1cc85a8ae45672333320c7673c284023366fbe6d4fab3e9276960b7f92fd74ee63d0ad6c43a86fd96a1b886408993479260ac897fa6fe101c4a9fb807b1", +"size": 61878564, +"digest": "bc344ad6cb8f4d7b25447a8f06ae3a22c6b90283fcc70f28f12578bdaf01ec960a774cdc215bdda4960cef04b6a991e462daeeda4f7e802bf65e6c9a3967f66c", "algorithm": "sha512", "filename": "clang.tar.bz2" } diff --git a/browser/config/tooltool-manifests/linux64/clang.manifest b/browser/config/tooltool-manifests/linux64/clang.manifest index cca45ccdcc93..4590d52259c7 100644 --- a/browser/config/tooltool-manifests/linux64/clang.manifest +++ b/browser/config/tooltool-manifests/linux64/clang.manifest @@ -1,6 +1,6 @@ [ { -"clang_version": "r169730" +"clang_version": "r170377" }, { "size": 47, @@ -9,8 +9,8 @@ "filename": "setup.sh" }, { -"size": 62279267, -"digest": "0c9f87e3d7675feaa79b6d5d0997c8f370785901b8668f51da3339ae674291b3946e9d76629adb1c4ccd15aa851d84e4cd39ddd9032c916cc75233fe73c68f2e", +"size": 62277867, +"digest": "b9c6ab4069e336fcbe705f07fd2beda37aecfd4078863898826c9591305b92f3f3f762e7f5c1b0eeb7e0fb1c0dacbca60f24868e0b3181bd34dcd9c5d44d20ee", "algorithm": "sha512", "filename": "clang.tar.bz2" } diff --git a/browser/config/tooltool-manifests/macosx32/releng.manifest b/browser/config/tooltool-manifests/macosx32/releng.manifest index 3cb17242b31a..26e984142146 100644 --- a/browser/config/tooltool-manifests/macosx32/releng.manifest +++ b/browser/config/tooltool-manifests/macosx32/releng.manifest @@ -1,6 +1,6 @@ [ { -"clang_version": "r169730" +"clang_version": "r170377" }, { "size": 47, @@ -9,8 +9,8 @@ "filename": "setup.sh" }, { -"size": 56115091, -"digest": "d7188264f28d6f6a84fab9737520cad22fe3d575917a87fc110d0b9a2033617c35da83530ea20553f5c55a996459f750fa2d0c49288c1fb9671f6252a92cf4c9", +"size": 56131193, +"digest": "a1e705d3a72e0e95eeb15722f538a3908277f9f756909ce5e67f0a09b8531c1ba7fcc4816e20795af2e98839e0308b1bc6df95308cda310ae06abf21d429624f", "algorithm": "sha512", "filename": "clang.tar.bz2" } diff --git a/browser/config/tooltool-manifests/macosx64/releng.manifest b/browser/config/tooltool-manifests/macosx64/releng.manifest index 3cb17242b31a..26e984142146 100644 --- a/browser/config/tooltool-manifests/macosx64/releng.manifest +++ b/browser/config/tooltool-manifests/macosx64/releng.manifest @@ -1,6 +1,6 @@ [ { -"clang_version": "r169730" +"clang_version": "r170377" }, { "size": 47, @@ -9,8 +9,8 @@ "filename": "setup.sh" }, { -"size": 56115091, -"digest": "d7188264f28d6f6a84fab9737520cad22fe3d575917a87fc110d0b9a2033617c35da83530ea20553f5c55a996459f750fa2d0c49288c1fb9671f6252a92cf4c9", +"size": 56131193, +"digest": "a1e705d3a72e0e95eeb15722f538a3908277f9f756909ce5e67f0a09b8531c1ba7fcc4816e20795af2e98839e0308b1bc6df95308cda310ae06abf21d429624f", "algorithm": "sha512", "filename": "clang.tar.bz2" } diff --git a/browser/confvars.sh b/browser/confvars.sh index 9167f80ce2fe..c92ed79bad34 100755 --- a/browser/confvars.sh +++ b/browser/confvars.sh @@ -23,40 +23,6 @@ if test "$OS_ARCH" = "WINNT"; then fi fi -# The value of ACCEPTED_MAR_CHANNEL_IDS should usually be the same as the value -# MAR_CHANNEL_ID. If more than one ID is needed, then you should use a comma -# separated list of values. -# The MAR_CHANNEL_ID must not contain the following 3 characters: ",\t " -case "$MOZ_UPDATE_CHANNEL" in -release|aurora|esr) - ACCEPTED_MAR_CHANNEL_IDS=firefox-mozilla-$MOZ_UPDATE_CHANNEL - MAR_CHANNEL_ID=firefox-mozilla-$MOZ_UPDATE_CHANNEL - ;; -beta) - ACCEPTED_MAR_CHANNEL_IDS=firefox-mozilla-beta,firefox-mozilla-release - MAR_CHANNEL_ID=firefox-mozilla-beta - ;; -*) - ACCEPTED_MAR_CHANNEL_IDS=firefox-mozilla-central - MAR_CHANNEL_ID=firefox-mozilla-central - ;; -esac - -# MOZ_APP_DISPLAYNAME will be set by branding/configure.sh -# Changing MOZ_*BRANDING_DIRECTORY requires a clobber to ensure correct results, -# because branding dependencies are broken. -# MOZ_BRANDING_DIRECTORY is the default branding directory used when none is -# specified. It should never point to the "official" branding directory. -# For mozilla-beta, mozilla-release, or mozilla-central repositories, use -# "nightly" branding (until bug 659568 is fixed). -# For the mozilla-aurora repository, use "aurora". -MOZ_OFFICIAL_BRANDING_DIRECTORY=browser/branding/official -if test "$MOZ_UPDATE_CHANNEL" = "aurora"; then - MOZ_BRANDING_DIRECTORY=browser/branding/aurora -else - MOZ_BRANDING_DIRECTORY=browser/branding/nightly -fi - MOZ_CHROME_FILE_FORMAT=omni MOZ_SAFE_BROWSING=1 MOZ_SERVICES_AITC=1 @@ -67,7 +33,23 @@ MOZ_SERVICES_NOTIFICATIONS=1 MOZ_SERVICES_SYNC=1 MOZ_APP_VERSION=$FIREFOX_VERSION MOZ_EXTENSIONS_DEFAULT=" gio" +# MOZ_APP_DISPLAYNAME will be set by branding/configure.sh +# Changing MOZ_*BRANDING_DIRECTORY requires a clobber to ensure correct results, +# because branding dependencies are broken. +# MOZ_BRANDING_DIRECTORY is the default branding directory used when none is +# specified. It should never point to the "official" branding directory. +# For mozilla-beta, mozilla-release, or mozilla-central repositories, use +# "nightly" branding (until bug 659568 is fixed). +# For the mozilla-aurora repository, use "aurora". +MOZ_BRANDING_DIRECTORY=browser/branding/nightly +MOZ_OFFICIAL_BRANDING_DIRECTORY=browser/branding/official MOZ_APP_ID={ec8030f7-c20a-464f-9b0e-13a3a9e97384} +# This should usually be the same as the value MAR_CHANNEL_ID. +# If more than one ID is needed, then you should use a comma separated list +# of values. +ACCEPTED_MAR_CHANNEL_IDS=firefox-mozilla-central +# The MAR_CHANNEL_ID must not contain the following 3 characters: ",\t " +MAR_CHANNEL_ID=firefox-mozilla-central MOZ_PROFILE_MIGRATOR=1 MOZ_EXTENSION_MANAGER=1 MOZ_APP_STATIC_INI=1 diff --git a/browser/modules/NewTabUtils.jsm b/browser/modules/NewTabUtils.jsm index 08075dfd6c97..83ccc26d7499 100644 --- a/browser/modules/NewTabUtils.jsm +++ b/browser/modules/NewTabUtils.jsm @@ -539,7 +539,7 @@ let PlacesProvider = { handleResult: function (aResultSet) { let row; - while (row = aResultSet.getNextRow()) { + while ((row = aResultSet.getNextRow())) { let url = row.getResultByIndex(1); if (LinkChecker.checkLoadURI(url)) { let title = row.getResultByIndex(2); diff --git a/build/Makefile.in b/build/Makefile.in index 42e0f49e1ae6..2899aabda40b 100644 --- a/build/Makefile.in +++ b/build/Makefile.in @@ -57,6 +57,12 @@ APP_INI_DEPS += $(DEPTH)/config/buildid DEFINES += -DGRE_MILESTONE=$(GRE_MILESTONE) -DAPP_BUILDID=$(APP_BUILDID) +# Set a flag that can be used in pref files to disable features if +# we are not building for Aurora or Nightly. +ifeq (,$(findstring a,$(GRE_MILESTONE))) +PREF_PPFLAGS += -DRELEASE_BUILD +endif + DEFINES += -DMOZ_APP_VERSION="$(MOZ_APP_VERSION)" APP_INI_DEPS += $(DEPTH)/config/autoconf.mk diff --git a/build/autoconf/android.m4 b/build/autoconf/android.m4 index e717caece53b..8fe98f0b8e33 100644 --- a/build/autoconf/android.m4 +++ b/build/autoconf/android.m4 @@ -54,7 +54,7 @@ arm-linux*-android*|*-linuxandroid*) android_tool_prefix="arm-linux-androideabi" ;; i?86-*android*) - android_tool_prefix="i686-android-linux" + android_tool_prefix="i686-linux-android" ;; mipsel-*android*) android_tool_prefix="mipsel-linux-android" @@ -119,6 +119,17 @@ case "$target" in fi fi + dnl Old NDK support. If minimum requirement is changed to NDK r8b, + dnl please remove this. + case "$target_cpu" in + i?86) + if ! test -e "$android_toolchain"/bin/"$android_tool_prefix"-gcc; then + dnl Old NDK toolchain name + android_tool_prefix="i686-android-linux" + fi + ;; + esac + dnl set up compilers TOOLCHAIN_PREFIX="$android_toolchain/bin/$android_tool_prefix-" AS="$android_toolchain"/bin/"$android_tool_prefix"-as diff --git a/build/unix/build-clang/build-clang.py b/build/unix/build-clang/build-clang.py index 1dd6cb4167c3..e758c5813b4a 100755 --- a/build/unix/build-clang/build-clang.py +++ b/build/unix/build-clang/build-clang.py @@ -3,7 +3,7 @@ # 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/. -llvm_revision = "169730" +llvm_revision = "170377" moz_version = "moz0" ############################################## diff --git a/content/base/src/nsAttrValue.h b/content/base/src/nsAttrValue.h index 2b5e183604b1..04c7ba6a50b8 100644 --- a/content/base/src/nsAttrValue.h +++ b/content/base/src/nsAttrValue.h @@ -19,12 +19,11 @@ #include "nsMargin.h" #include "nsCOMPtr.h" #include "SVGAttrValueWrapper.h" +#include "nsTArrayForwardDeclare.h" class nsAString; class nsIAtom; class nsIDocument; -template class nsTArray; -struct nsTArrayDefaultAllocator; class nsStyledElementNotElementCSSInlineStyle; struct MiscContainer; @@ -426,7 +425,7 @@ private: int32_t EnumTableEntryToValue(const EnumTable* aEnumTable, const EnumTable* aTableEntry); - static nsTArray* sEnumTableArray; + static nsTArray* sEnumTableArray; uintptr_t mBits; }; diff --git a/content/base/src/nsFrameLoader.cpp b/content/base/src/nsFrameLoader.cpp index 79bb88d64e44..71e24d0a1649 100644 --- a/content/base/src/nsFrameLoader.cpp +++ b/content/base/src/nsFrameLoader.cpp @@ -2064,6 +2064,14 @@ nsFrameLoader::TryRemoteBrowser() nsCOMPtr element = do_QueryInterface(mOwnerContent); mRemoteBrowser->SetOwnerElement(element); + // If we're an app, send the frame element's mozapptype down to the child + // process. This ends up in TabChild::GetAppType(). + if (ownApp) { + nsAutoString appType; + mOwnerContent->GetAttr(kNameSpaceID_None, nsGkAtoms::mozapptype, appType); + mRemoteBrowser->SendSetAppType(appType); + } + nsCOMPtr rootItem; parentAsItem->GetRootTreeItem(getter_AddRefs(rootItem)); nsCOMPtr rootWin = do_GetInterface(rootItem); diff --git a/content/base/src/nsGkAtomList.h b/content/base/src/nsGkAtomList.h index 9c0a476d57e4..ad3d0d506ff6 100644 --- a/content/base/src/nsGkAtomList.h +++ b/content/base/src/nsGkAtomList.h @@ -89,6 +89,7 @@ GK_ATOM(mozapp, "mozapp") GK_ATOM(applet, "applet") GK_ATOM(applyImports, "apply-imports") GK_ATOM(applyTemplates, "apply-templates") +GK_ATOM(mozapptype, "mozapptype") GK_ATOM(archive, "archive") GK_ATOM(area, "area") GK_ATOM(article, "article") diff --git a/content/canvas/src/WebGLContextGL.cpp b/content/canvas/src/WebGLContextGL.cpp index ca492942b288..0dffcd6dc9fe 100644 --- a/content/canvas/src/WebGLContextGL.cpp +++ b/content/canvas/src/WebGLContextGL.cpp @@ -1064,6 +1064,7 @@ WebGLContext::DeleteTexture(WebGLTexture *tex) if (mBoundFramebuffer) mBoundFramebuffer->DetachTexture(tex); + WebGLuint activeTexture = mActiveTexture; for (int32_t i = 0; i < mGLMaxTextureUnits; i++) { if ((tex->Target() == LOCAL_GL_TEXTURE_2D && mBound2DTextures[i] == tex) || (tex->Target() == LOCAL_GL_TEXTURE_CUBE_MAP && mBoundCubeMapTextures[i] == tex)) @@ -1072,7 +1073,7 @@ WebGLContext::DeleteTexture(WebGLTexture *tex) BindTexture(tex->Target(), static_cast(nullptr)); } } - ActiveTexture(LOCAL_GL_TEXTURE0 + mActiveTexture); + ActiveTexture(LOCAL_GL_TEXTURE0 + activeTexture); tex->RequestDelete(); } diff --git a/content/media/nsDOMMediaStream.cpp b/content/media/nsDOMMediaStream.cpp index c18433cec2fa..5943cc6ba654 100644 --- a/content/media/nsDOMMediaStream.cpp +++ b/content/media/nsDOMMediaStream.cpp @@ -95,18 +95,20 @@ nsDOMLocalMediaStream::CreateSourceStream(uint32_t aHintContents) } already_AddRefed -nsDOMMediaStream::CreateTrackUnionStream() +nsDOMMediaStream::CreateTrackUnionStream(uint32_t aHintContents) { nsRefPtr stream = new nsDOMMediaStream(); + stream->SetHintContents(aHintContents); MediaStreamGraph* gm = MediaStreamGraph::GetInstance(); stream->mStream = gm->CreateTrackUnionStream(stream); return stream.forget(); } already_AddRefed -nsDOMLocalMediaStream::CreateTrackUnionStream() +nsDOMLocalMediaStream::CreateTrackUnionStream(uint32_t aHintContents) { nsRefPtr stream = new nsDOMLocalMediaStream(); + stream->SetHintContents(aHintContents); MediaStreamGraph* gm = MediaStreamGraph::GetInstance(); stream->mStream = gm->CreateTrackUnionStream(stream); return stream.forget(); diff --git a/content/media/nsDOMMediaStream.h b/content/media/nsDOMMediaStream.h index 9c149a027671..b108788d53ac 100644 --- a/content/media/nsDOMMediaStream.h +++ b/content/media/nsDOMMediaStream.h @@ -70,7 +70,7 @@ public: /** * Create an nsDOMMediaStream whose underlying stream is a TrackUnionStream. */ - static already_AddRefed CreateTrackUnionStream(); + static already_AddRefed CreateTrackUnionStream(uint32_t aHintContents = 0); protected: // MediaStream is owned by the graph, but we tell it when to die, and it won't @@ -106,7 +106,7 @@ public: /** * Create an nsDOMLocalMediaStream whose underlying stream is a TrackUnionStream. */ - static already_AddRefed CreateTrackUnionStream(); + static already_AddRefed CreateTrackUnionStream(uint32_t aHintContents = 0); }; #endif /* NSDOMMEDIASTREAM_H_ */ diff --git a/content/media/ogg/OggReader.cpp b/content/media/ogg/OggReader.cpp index 673c41ac37cc..72f28896dc27 100644 --- a/content/media/ogg/OggReader.cpp +++ b/content/media/ogg/OggReader.cpp @@ -421,14 +421,17 @@ nsresult OggReader::DecodeVorbis(ogg_packet* aPacket) { nsresult OggReader::DecodeOpus(ogg_packet* aPacket) { NS_ASSERTION(aPacket->granulepos != -1, "Must know opus granulepos!"); - // Maximum value is 63*2880. + // Maximum value is 63*2880, so there's no chance of overflow. int32_t frames_number = opus_packet_get_nb_frames(aPacket->packet, aPacket->bytes); + if (frames_number <= 0) + return NS_ERROR_FAILURE; // Invalid packet header. int32_t samples = opus_packet_get_samples_per_frame(aPacket->packet, (opus_int32) mOpusState->mRate); int32_t frames = frames_number*samples; - if (frames <= 0) + // A valid Opus packet must be between 2.5 and 120 ms long. + if (frames < 120 || frames > 5760) return NS_ERROR_FAILURE; uint32_t channels = mOpusState->mChannels; nsAutoArrayPtr buffer(new AudioDataValue[frames * channels]); diff --git a/docshell/shistory/public/nsISHistoryInternal.idl b/docshell/shistory/public/nsISHistoryInternal.idl index 34b14960c74a..aa2e99135931 100644 --- a/docshell/shistory/public/nsISHistoryInternal.idl +++ b/docshell/shistory/public/nsISHistoryInternal.idl @@ -18,11 +18,10 @@ interface nsIDocShell; #define NS_SHISTORY_INTERNAL_CONTRACTID "@mozilla.org/browser/shistory-internal;1" -template class nsTArray; -struct nsTArrayDefaultAllocator; +#include "nsTArrayForwardDeclare.h" %} -[ref] native nsDocshellIDArray(nsTArray); +[ref] native nsDocshellIDArray(nsTArray); [scriptable, uuid(f9348014-0239-11e2-b029-3d38e719eb2d)] interface nsISHistoryInternal: nsISupports diff --git a/dom/apps/src/Webapps.jsm b/dom/apps/src/Webapps.jsm index 81a9290b219e..9cc885fdc716 100644 --- a/dom/apps/src/Webapps.jsm +++ b/dom/apps/src/Webapps.jsm @@ -868,15 +868,26 @@ this.DOMApplicationRegistry = { }, cancelDownload: function cancelDownload(aManifestURL) { - // We can't cancel appcache downloads for now. - if (!this.downloads[aManifestURL]) { + debug("cancelDownload " + aManifestURL); + let download = this.downloads[aManifestURL]; + if (!download) { + debug("Could not find a download for " + aManifestURL); return; } - // This is a HTTP channel. - let download = this.downloads[aManifestURL] - download.channel.cancel(Cr.NS_BINDING_ABORTED); - let app = this.webapps[download.appId]; + if (download.cacheUpdate) { + // Cancel hosted app download. + try { + download.cacheUpdate.cancel(); + } catch (e) { debug (e); } + } else if (download.channel) { + // Cancel packaged app download. + download.channel.cancel(Cr.NS_BINDING_ABORTED); + } else { + return; + } + + let app = this.webapps[download.appId]; app.progress = 0; app.installState = download.previousState; app.downloading = false; @@ -1038,26 +1049,42 @@ this.DOMApplicationRegistry = { aProfileDir, aOfflineCacheObserver, aIsUpdate) { - // if the manifest has an appcache_path property, use it to populate the appcache - if (aManifest.appcache_path) { - let appcacheURI = Services.io.newURI(aManifest.fullAppcachePath(), null, null); - let docURI = Services.io.newURI(aManifest.fullLaunchPath(), null, null); - // We determine the app's 'installState' according to its previous - // state. Cancelled download should remain as 'pending'. Successfully - // installed apps should morph to 'updating'. - if (aIsUpdate) { - aApp.installState = "updating"; - } - // We set the 'downloading' flag right before starting the app - // download/update. - aApp.downloading = true; - let cacheUpdate = aProfileDir - ? updateSvc.scheduleCustomProfileUpdate(appcacheURI, docURI, aProfileDir) - : updateSvc.scheduleAppUpdate(appcacheURI, docURI, aApp.localId, false); - cacheUpdate.addObserver(new AppcacheObserver(aApp), false); - if (aOfflineCacheObserver) { - cacheUpdate.addObserver(aOfflineCacheObserver, false); - } + if (!aManifest.appcache_path) { + return; + } + + // If the manifest has an appcache_path property, use it to populate the + // appcache. + let appcacheURI = Services.io.newURI(aManifest.fullAppcachePath(), + null, null); + let docURI = Services.io.newURI(aManifest.fullLaunchPath(), null, null); + + // We determine the app's 'installState' according to its previous + // state. Cancelled downloads should remain as 'pending'. Successfully + // installed apps should morph to 'updating'. + if (aIsUpdate) { + aApp.installState = "updating"; + } + + // We set the 'downloading' flag right before starting the app + // download/update. + aApp.downloading = true; + let cacheUpdate = aProfileDir + ? updateSvc.scheduleCustomProfileUpdate(appcacheURI, docURI, aProfileDir) + : updateSvc.scheduleAppUpdate(appcacheURI, docURI, aApp.localId, false); + + // We save the download details for potential further usage like cancelling + // it. + let download = { + cacheUpdate: cacheUpdate, + appId: this._appIdForManifestURL(aApp.manifestURL), + previousState: aIsUpdate ? "installed" : "pending" + }; + this.downloads[aApp.manifestURL] = download; + + cacheUpdate.addObserver(new AppcacheObserver(aApp), false); + if (aOfflineCacheObserver) { + cacheUpdate.addObserver(aOfflineCacheObserver, false); } }, @@ -1714,11 +1741,11 @@ this.DOMApplicationRegistry = { let requestChannel = NetUtil.newChannel(aManifest.fullPackagePath()) .QueryInterface(Ci.nsIHttpChannel); - self.downloads[aApp.manifestURL] = - { channel:requestChannel, - appId: id, - previousState: aIsUpdate ? "installed" : "pending" - }; + self.downloads[aApp.manifestURL] = { + channel: requestChannel, + appId: id, + previousState: aIsUpdate ? "installed" : "pending" + }; let lastProgressTime = 0; requestChannel.notificationCallbacks = { diff --git a/dom/bindings/BindingUtils.h b/dom/bindings/BindingUtils.h index c6becef0cdf8..43fd25ecdd6d 100644 --- a/dom/bindings/BindingUtils.h +++ b/dom/bindings/BindingUtils.h @@ -1370,6 +1370,10 @@ public: return mImpl.ref(); } + // If we ever decide to add conversion operators for optional arrays + // like the ones Nullable has, we'll need to ensure that Maybe<> has + // the boolean before the actual data. + private: // Forbid copy-construction and assignment Optional(const Optional& other) MOZ_DELETE; diff --git a/dom/bindings/Nullable.h b/dom/bindings/Nullable.h index 8b2cc08642b3..5fb573929418 100644 --- a/dom/bindings/Nullable.h +++ b/dom/bindings/Nullable.h @@ -8,6 +8,7 @@ #define mozilla_dom_Nullable_h #include "mozilla/Assertions.h" +#include "nsTArrayForwardDeclare.h" namespace mozilla { namespace dom { @@ -17,17 +18,19 @@ template struct Nullable { private: - T mValue; + // mIsNull MUST COME FIRST because otherwise the casting in our array + // conversion operators would shift where it is found in the struct. bool mIsNull; + T mValue; public: Nullable() : mIsNull(true) {} - Nullable(T aValue) - : mValue(aValue) - , mIsNull(false) + explicit Nullable(T aValue) + : mIsNull(false) + , mValue(aValue) {} void SetValue(T aValue) { @@ -60,6 +63,23 @@ public: bool IsNull() const { return mIsNull; } + + // Make it possible to use a const Nullable of an array type with other + // array types. + template + operator const Nullable< nsTArray >&() const { + // Make sure that T is ok to reinterpret to nsTArray + const nsTArray& arr = mValue; + (void)arr; + return *reinterpret_cast >*>(this); + } + template + operator const Nullable< FallibleTArray >&() const { + // Make sure that T is ok to reinterpret to FallibleTArray + const FallibleTArray& arr = mValue; + (void)arr; + return *reinterpret_cast >*>(this); + } }; } // namespace dom diff --git a/dom/bluetooth/BluetoothDevice.cpp b/dom/bluetooth/BluetoothDevice.cpp index 82bbd6cad616..3b3f5a1d3532 100644 --- a/dom/bluetooth/BluetoothDevice.cpp +++ b/dom/bluetooth/BluetoothDevice.cpp @@ -181,7 +181,7 @@ BluetoothDevice::Notify(const BluetoothSignal& aData) if (aData.name().EqualsLiteral("PropertyChanged")) { NS_ASSERTION(aData.value().type() == BluetoothValue::TArrayOfBluetoothNamedValue, "PropertyChanged: Invalid value type"); - InfallibleTArray arr = aData.value().get_ArrayOfBluetoothNamedValue(); + InfallibleTArray arr(aData.value().get_ArrayOfBluetoothNamedValue()); NS_ASSERTION(arr.Length() == 1, "Got more than one property in a change message!"); BluetoothNamedValue v = arr[0]; diff --git a/dom/bluetooth/BluetoothService.cpp b/dom/bluetooth/BluetoothService.cpp index 141b336d9366..0d3fa407d975 100644 --- a/dom/bluetooth/BluetoothService.cpp +++ b/dom/bluetooth/BluetoothService.cpp @@ -703,7 +703,7 @@ BluetoothService::Observe(nsISupports* aSubject, const char* aTopic, void BluetoothService::Notify(const BluetoothSignal& aData) { - InfallibleTArray arr = aData.value().get_ArrayOfBluetoothNamedValue(); + InfallibleTArray arr(aData.value().get_ArrayOfBluetoothNamedValue()); nsString type; JSContext* cx = nsContentUtils::GetSafeJSContext(); diff --git a/dom/bluetooth/ipc/BluetoothParent.cpp b/dom/bluetooth/ipc/BluetoothParent.cpp index 8e6bf7669bab..7093742b0fbf 100644 --- a/dom/bluetooth/ipc/BluetoothParent.cpp +++ b/dom/bluetooth/ipc/BluetoothParent.cpp @@ -393,9 +393,8 @@ BluetoothRequestParent::DoRequest(const DevicePropertiesRequest& aRequest) MOZ_ASSERT(mService); MOZ_ASSERT(mRequestType == Request::TDevicePropertiesRequest); - // Have to copy because our array types don't match up nsresult rv = - mService->GetPairedDevicePropertiesInternal(nsTArray(aRequest.addresses()), + mService->GetPairedDevicePropertiesInternal(aRequest.addresses(), mReplyRunnable.get()); NS_ENSURE_SUCCESS(rv, false); diff --git a/dom/bluetooth/linux/BluetoothDBusService.cpp b/dom/bluetooth/linux/BluetoothDBusService.cpp index 170cecf80a36..203c14b94689 100644 --- a/dom/bluetooth/linux/BluetoothDBusService.cpp +++ b/dom/bluetooth/linux/BluetoothDBusService.cpp @@ -1720,7 +1720,7 @@ public: BluetoothValue v = mSignal.value(); if (v.type() == BluetoothValue::TArrayOfBluetoothNamedValue && v.get_ArrayOfBluetoothNamedValue().Length() ) { - InfallibleTArray arr = v.get_ArrayOfBluetoothNamedValue(); + const InfallibleTArray& arr = v.get_ArrayOfBluetoothNamedValue(); NS_ASSERTION(arr[0].value().type() == BluetoothValue::TnsString, "failed to get_nsString"); devicePath = arr[0].value().get_nsString(); } @@ -1737,11 +1737,11 @@ public: NS_WARNING("Getting properties failed!"); return NS_ERROR_FAILURE; } - InfallibleTArray properties = prop.get_ArrayOfBluetoothNamedValue(); + InfallibleTArray properties(prop.get_ArrayOfBluetoothNamedValue()); if (v.type() == BluetoothValue::TArrayOfBluetoothNamedValue) { // Return original dbus message parameters and also device name // for agent events "RequestConfirmation", "RequestPinCode", and "RequestPasskey" - InfallibleTArray parameters = v.get_ArrayOfBluetoothNamedValue(); + InfallibleTArray parameters(v.get_ArrayOfBluetoothNamedValue()); // For consistency, append path nsString path = parameters[0].value(); @@ -1804,7 +1804,7 @@ public: BluetoothValue values = InfallibleTArray(); - for (int i = 0; i < mDeviceAddresses.Length(); i++) { + for (uint32_t i = 0; i < mDeviceAddresses.Length(); i++) { BluetoothValue v; if (!GetPropertiesInternal(mDeviceAddresses[i], DBUS_DEVICE_IFACE, v)) { nsAutoString errorStr; diff --git a/dom/browser-element/BrowserElementScrolling.js b/dom/browser-element/BrowserElementScrolling.js index ddf73c4ff18b..79b5d7fcd66b 100644 --- a/dom/browser-element/BrowserElementScrolling.js +++ b/dom/browser-element/BrowserElementScrolling.js @@ -4,7 +4,7 @@ const ContentPanning = { init: function cp_init() { - ['mousedown', 'mouseup', 'mousemove', 'touchstart', 'touchend', 'touchmove'].forEach(function(type) { + ['mousedown', 'mouseup', 'mousemove'].forEach(function(type) { addEventListener(type, ContentPanning, false); }); @@ -12,41 +12,15 @@ const ContentPanning = { addMessageListener("Gesture:DoubleTap", this._recvDoubleTap.bind(this)); }, - evtFilter: '', - _filterEvent: function cp_filterEvent(evt) { - switch (this.evtFilter) { - case 'mouse': - if (evt.type == 'touchstart' || evt.type == 'touchend' || evt.type == 'touchmove') { - return false; - } - break; - case 'touch': - if (evt.type == 'mousedown' || evt.type == 'mouseup' || evt.type == 'mousemove') { - return false; - } - break; - } - return true; - }, handleEvent: function cp_handleEvent(evt) { - // determine scrolling detection is based on touch or mouse event at runtime - if (!this.evtFilter) { - if (evt.type == 'touchstart') this.evtFilter = 'touch'; - else if (evt.type == 'mousedown') this.evtFilter = 'mouse'; - } - if (evt.defaultPrevented || !this._filterEvent(evt)) return; - switch (evt.type) { case 'mousedown': - case 'touchstart': this.onTouchStart(evt); break; case 'mousemove': - case 'touchmove': this.onTouchMove(evt); break; case 'mouseup': - case 'touchend': this.onTouchEnd(evt); break; case 'click': @@ -63,39 +37,12 @@ const ContentPanning = { position: new Point(0 , 0), - findFirstTouch: function cp_findFirstTouch(touches) { - if (!('trackingId' in this)) return undefined; - - for (let i = 0; i < touches.length; i++) { - if (touches[i].identifier === this.trackingId) - return touches[i]; - } - return undefined; - }, - onTouchStart: function cp_onTouchStart(evt) { - let target, screenX, screenY; - if (this.evtFilter == 'touch') { - if ('trackingId' in this) { - return; - } - - let firstTouch = evt.changedTouches[0]; - this.trackingId = firstTouch.identifier; - target = firstTouch.target; - screenX = firstTouch.screenX; - screenY = firstTouch.screenY; - } else { - target = evt.target; - screenX = evt.screenX; - screenY = evt.screenY; - } - this.dragging = true; this.panning = false; let oldTarget = this.target; - [this.target, this.scrollCallback] = this.getPannable(target); + [this.target, this.scrollCallback] = this.getPannable(evt.target); // If we found a target, that means we have found a scrollable subframe. In // this case, and if we are using async panning and zooming on the parent @@ -104,7 +51,7 @@ const ContentPanning = { // time we get a touch end). if (this.target != null && ContentPanning._asyncPanZoomForViewportFrame) { var os = Cc["@mozilla.org/observer-service;1"].getService(Ci.nsIObserverService); - os.notifyObservers(docShell, 'detect-scrollable-subframe', null); + os.notifyObservers(docShell, 'cancel-default-pan-zoom', null); } // If there is a pan animation running (from a previous pan gesture) and @@ -120,24 +67,18 @@ const ContentPanning = { } - this.position.set(screenX, screenY); + this.position.set(evt.screenX, evt.screenY); KineticPanning.record(new Point(0, 0), evt.timeStamp); }, onTouchEnd: function cp_onTouchEnd(evt) { - if (this.evtFilter == 'touch' && !this.findFirstTouch(evt.changedTouches)) - return; - if (!this.dragging) return; this.dragging = false; - this.isScrolling = false; this.onTouchMove(evt); - delete this.trackingId; - - let click = (this.evtFilter == 'touch') ? true : evt.detail; + let click = evt.detail; if (this.target && click && (this.panning || this.preventNextClick)) { let target = this.target; let view = target.ownerDocument ? target.ownerDocument.defaultView @@ -149,54 +90,23 @@ const ContentPanning = { KineticPanning.start(this); }, - isScrolling: false, // Scrolling gesture is executed in BrowserElementScrolling onTouchMove: function cp_onTouchMove(evt) { if (!this.dragging || !this.scrollCallback) return; - let screenX, screenY; - if (this.evtFilter == 'touch') { - let firstTouch = this.findFirstTouch(evt.changedTouches); - if (evt.touches.length > 1 || !firstTouch) - return; - screenX = firstTouch.screenX; - screenY = firstTouch.screenY; - } else { - screenX = evt.screenX; - screenY = evt.screenY; - } - let current = this.position; - let delta = new Point(screenX - current.x, screenY - current.y); - current.set(screenX, screenY); + let delta = new Point(evt.screenX - current.x, evt.screenY - current.y); + current.set(evt.screenX, evt.screenY); KineticPanning.record(delta, evt.timeStamp); - let success = this.scrollCallback(delta.scale(-1)); + this.scrollCallback(delta.scale(-1)); - // Stop async-pan-zooming if the subframe is really scrolled. - if (!this.isScrolling && ContentPanning._asyncPanZoomForViewportFrame) { - if (success) { - var os = Cc["@mozilla.org/observer-service;1"].getService(Ci.nsIObserverService); - os.notifyObservers(docShell, 'cancel-default-pan-zoom', null); - } else { - // Let AsyncPanZoomController handle the scrolling gesture. - delete this.trackingId; - return; - } - } - - // Successfully scroll the inner scrollable region. - if (success && !this.isScrolling) { - this.isScrolling = true; - } - // If a pan action happens, cancel the active state of the // current target. if (!this.panning && KineticPanning.isPan()) { this.panning = true; this._resetActive(); } - evt.stopPropagation(); evt.preventDefault(); }, diff --git a/dom/camera/GonkCameraControl.cpp b/dom/camera/GonkCameraControl.cpp index 588409bb1340..08daf0bd6b8b 100644 --- a/dom/camera/GonkCameraControl.cpp +++ b/dom/camera/GonkCameraControl.cpp @@ -47,6 +47,16 @@ using namespace mozilla::dom; using namespace mozilla::layers; using namespace android; +/** + * See bug 783682. Most camera implementations, despite claiming they + * support 'yuv420p' as a preview format, actually ignore this setting + * and return 'yuv420sp' data anyway. We have come across a new implementation + * that, while reporting that 'yuv420p' is supported *and* has been accepted, + * still returns the frame data in 'yuv420sp' anyway. So for now, since + * everyone seems to return this format, we just force it. + */ +#define FORCE_PREVIEW_FORMAT_YUV420SP 1 + static const char* getKeyText(uint32_t aKey) { switch (aKey) { @@ -189,7 +199,11 @@ nsGonkCameraControl::nsGonkCameraControl(uint32_t aCameraId, nsIThread* aCameraT , mHeight(0) , mLastPictureWidth(0) , mLastPictureHeight(0) +#if !FORCE_PREVIEW_FORMAT_YUV420SP , mFormat(PREVIEW_FORMAT_UNKNOWN) +#else + , mFormat(PREVIEW_FORMAT_YUV420SP) +#endif , mFps(30) , mDiscardedFrameCount(0) , mMediaProfiles(nullptr) @@ -217,15 +231,21 @@ nsGonkCameraControl::Init() PullParametersImpl(); // Try to set preferred image format and frame rate +#if !FORCE_PREVIEW_FORMAT_YUV420SP DOM_CAMERA_LOGI("Camera preview formats: %s\n", mParams.get(mParams.KEY_SUPPORTED_PREVIEW_FORMATS)); const char* const PREVIEW_FORMAT = "yuv420p"; const char* const BAD_PREVIEW_FORMAT = "yuv420sp"; mParams.setPreviewFormat(PREVIEW_FORMAT); mParams.setPreviewFrameRate(mFps); +#else + mParams.setPreviewFormat("yuv420sp"); + mParams.setPreviewFrameRate(mFps); +#endif PushParametersImpl(); // Check that our settings stuck PullParametersImpl(); +#if !FORCE_PREVIEW_FORMAT_YUV420SP const char* format = mParams.getPreviewFormat(); if (strcmp(format, PREVIEW_FORMAT) == 0) { mFormat = PREVIEW_FORMAT_YUV420P; /* \o/ */ @@ -236,6 +256,7 @@ nsGonkCameraControl::Init() mFormat = PREVIEW_FORMAT_UNKNOWN; DOM_CAMERA_LOGE("Camera ignored our request for '%s' preview, returned UNSUPPORTED format '%s'\n", PREVIEW_FORMAT, format); } +#endif // Check the frame rate and log if the camera ignored our setting uint32_t fps = mParams.getPreviewFrameRate(); diff --git a/dom/identity/nsDOMIdentity.js b/dom/identity/nsDOMIdentity.js index 937b1836fdfe..c84d4c6c841d 100644 --- a/dom/identity/nsDOMIdentity.js +++ b/dom/identity/nsDOMIdentity.js @@ -9,6 +9,11 @@ const {classes: Cc, interfaces: Ci, utils: Cu} = Components; const PREF_DEBUG = "toolkit.identity.debug"; const PREF_ENABLED = "dom.identity.enabled"; +// Bug 822450: Workaround for Bug 821740. When testing with marionette, +// relax navigator.id.request's requirement that it be handling native +// events. Synthetic marionette events are ok. +const PREF_SYNTHETIC_EVENTS_OK = "dom.identity.syntheticEventsOk"; + // Maximum length of a string that will go through IPC const MAX_STRING_LENGTH = 2048; // Maximum number of times navigator.id.request can be called for a document @@ -47,7 +52,14 @@ nsDOMIdentity.prototype = { raiseAuthenticationFailure: 'r', }, - // nsIDOMIdentity + // require native events unless syntheticEventsOk is set + get nativeEventsRequired() { + if (Services.prefs.prefHasUserValue(PREF_SYNTHETIC_EVENTS_OK)) { + return !Services.prefs.getBoolPref(PREF_SYNTHETIC_EVENTS_OK); + } + return true; + }, + /** * Relying Party (RP) APIs */ @@ -115,7 +127,8 @@ nsDOMIdentity.prototype = { // input handler is when we are handling the (deprecated) get() or // getVerifiedEmail() calls, which make use of an RP context // marked as _internal. - if (!util.isHandlingUserInput && !aOptions._internal) { + if (this.nativeEventsRequired && !util.isHandlingUserInput && !aOptions._internal) { + this._log("request: rejecting non-native event"); return; } diff --git a/dom/indexedDB/IDBIndex.cpp b/dom/indexedDB/IDBIndex.cpp index 465b07d08e5e..fedcab1c5e90 100644 --- a/dom/indexedDB/IDBIndex.cpp +++ b/dom/indexedDB/IDBIndex.cpp @@ -1668,7 +1668,7 @@ GetAllHelper::UnpackResponseFromParentProcess( for (uint32_t index = 0; index < cloneInfos.Length(); index++) { const SerializedStructuredCloneReadInfo srcInfo = cloneInfos[index]; - const InfallibleTArray blobs = blobArrays[index].blobsChild(); + const InfallibleTArray& blobs = blobArrays[index].blobsChild(); StructuredCloneReadInfo* destInfo = mCloneReadInfos.AppendElement(); if (!destInfo->SetFromSerialized(srcInfo)) { diff --git a/dom/indexedDB/IDBObjectStore.cpp b/dom/indexedDB/IDBObjectStore.cpp index 1f16d2629bfc..d5b1fd4e80c6 100644 --- a/dom/indexedDB/IDBObjectStore.cpp +++ b/dom/indexedDB/IDBObjectStore.cpp @@ -3907,7 +3907,7 @@ GetAllHelper::UnpackResponseFromParentProcess( for (uint32_t index = 0; index < cloneInfos.Length(); index++) { const SerializedStructuredCloneReadInfo srcInfo = cloneInfos[index]; - const InfallibleTArray blobs = blobArrays[index].blobsChild(); + const InfallibleTArray& blobs = blobArrays[index].blobsChild(); StructuredCloneReadInfo* destInfo = mCloneReadInfos.AppendElement(); if (!destInfo->SetFromSerialized(srcInfo)) { diff --git a/dom/ipc/PBrowser.ipdl b/dom/ipc/PBrowser.ipdl index e1ae01bf0119..d7ef6a9f3f16 100644 --- a/dom/ipc/PBrowser.ipdl +++ b/dom/ipc/PBrowser.ipdl @@ -382,6 +382,20 @@ child: uint32_t renderFlags, bool flushLayout, nsIntSize renderSize); + /** + * Send the child its app type. The app type identifies the kind of app + * shown in this PBrowser. Currently, the only recognized app type is + * "homescreen". + * + * The value here corresponds to the "mozapptype" attribute on iframes. For + * example,