diff --git a/addon-sdk/source/lib/sdk/ui/button/view.js b/addon-sdk/source/lib/sdk/ui/button/view.js
index 02731a15d86..63b7aea31b8 100644
--- a/addon-sdk/source/lib/sdk/ui/button/view.js
+++ b/addon-sdk/source/lib/sdk/ui/button/view.js
@@ -142,7 +142,7 @@ function create(options) {
node.setAttribute('label', label);
node.setAttribute('tooltiptext', label);
node.setAttribute('image', image);
- node.setAttribute('sdk-button', 'true');
+ node.setAttribute('constrain-size', 'true');
views.set(id, {
area: this.currentArea,
diff --git a/addon-sdk/source/test/test-sandbox.js b/addon-sdk/source/test/test-sandbox.js
index ad342b8c5ca..ed4bb328fc6 100644
--- a/addon-sdk/source/test/test-sandbox.js
+++ b/addon-sdk/source/test/test-sandbox.js
@@ -57,7 +57,7 @@ exports['test exceptions'] = function(assert) {
} + '();');
}
catch (error) {
- assert.equal(error.fileName, '', 'no fileName reported');
+ assert.equal(error.fileName, '[System Principal]', 'No specific fileName reported');
assert.equal(error.lineNumber, 3, 'reports correct line number');
}
diff --git a/b2g/config/dolphin/sources.xml b/b2g/config/dolphin/sources.xml
index 5d82f965685..1e50839ce81 100644
--- a/b2g/config/dolphin/sources.xml
+++ b/b2g/config/dolphin/sources.xml
@@ -15,9 +15,9 @@
-
+
-
+
diff --git a/b2g/config/emulator-ics/sources.xml b/b2g/config/emulator-ics/sources.xml
index e3de5923517..da57a75cf09 100644
--- a/b2g/config/emulator-ics/sources.xml
+++ b/b2g/config/emulator-ics/sources.xml
@@ -19,8 +19,8 @@
-
-
+
+
diff --git a/b2g/config/emulator-jb/sources.xml b/b2g/config/emulator-jb/sources.xml
index 4b0d8a2b195..581bcce6808 100644
--- a/b2g/config/emulator-jb/sources.xml
+++ b/b2g/config/emulator-jb/sources.xml
@@ -17,8 +17,8 @@
-
-
+
+
diff --git a/b2g/config/emulator-kk/sources.xml b/b2g/config/emulator-kk/sources.xml
index 8da20ba9b18..8e75a513b1e 100644
--- a/b2g/config/emulator-kk/sources.xml
+++ b/b2g/config/emulator-kk/sources.xml
@@ -15,9 +15,9 @@
-
+
-
+
diff --git a/b2g/config/emulator-l/sources.xml b/b2g/config/emulator-l/sources.xml
index d876e8bb85e..7214d561a38 100644
--- a/b2g/config/emulator-l/sources.xml
+++ b/b2g/config/emulator-l/sources.xml
@@ -15,9 +15,9 @@
-
+
-
+
diff --git a/b2g/config/emulator/sources.xml b/b2g/config/emulator/sources.xml
index e3de5923517..da57a75cf09 100644
--- a/b2g/config/emulator/sources.xml
+++ b/b2g/config/emulator/sources.xml
@@ -19,8 +19,8 @@
-
-
+
+
diff --git a/b2g/config/flame-kk/sources.xml b/b2g/config/flame-kk/sources.xml
index c9e2f85dbfe..8e74f1047f7 100644
--- a/b2g/config/flame-kk/sources.xml
+++ b/b2g/config/flame-kk/sources.xml
@@ -15,9 +15,9 @@
-
+
-
+
diff --git a/b2g/config/flame/sources.xml b/b2g/config/flame/sources.xml
index 5eef347c9af..0d9e03a0a23 100644
--- a/b2g/config/flame/sources.xml
+++ b/b2g/config/flame/sources.xml
@@ -17,8 +17,8 @@
-
-
+
+
diff --git a/b2g/config/gaia.json b/b2g/config/gaia.json
index e4b9054bb29..7da0c765356 100644
--- a/b2g/config/gaia.json
+++ b/b2g/config/gaia.json
@@ -1,9 +1,9 @@
{
"git": {
- "git_revision": "8e28588496f82f8f069c171c65842d622b9d8d7d",
+ "git_revision": "2dd89fef4fae4d86fd313037ef384086c2e0e8a5",
"remote": "https://git.mozilla.org/releases/gaia.git",
"branch": ""
},
- "revision": "ff36a42838b338d750be214ac110c5cc4369b180",
+ "revision": "9b4f4ec031e567ece9b707841fa50d27d346cd83",
"repo_path": "integration/gaia-central"
}
diff --git a/b2g/config/nexus-4/sources.xml b/b2g/config/nexus-4/sources.xml
index 73fe6461967..3c18efe2317 100644
--- a/b2g/config/nexus-4/sources.xml
+++ b/b2g/config/nexus-4/sources.xml
@@ -17,8 +17,8 @@
-
-
+
+
diff --git a/b2g/config/nexus-5-l/sources.xml b/b2g/config/nexus-5-l/sources.xml
index 9b4a2d89047..378d922daf7 100644
--- a/b2g/config/nexus-5-l/sources.xml
+++ b/b2g/config/nexus-5-l/sources.xml
@@ -15,9 +15,9 @@
-
+
-
+
diff --git a/browser/base/content/browser-readinglist.js b/browser/base/content/browser-readinglist.js
index e41be1f6e90..7b846bf9142 100644
--- a/browser/base/content/browser-readinglist.js
+++ b/browser/base/content/browser-readinglist.js
@@ -252,7 +252,7 @@ let ReadingListUI = {
if (this.enabled && state == "valid") {
uri = gBrowser.currentURI;
if (uri.schemeIs("about"))
- uri = ReaderParent.parseReaderUrl(uri.spec);
+ uri = ReaderMode.getOriginalUrl(uri.spec);
else if (!uri.schemeIs("http") && !uri.schemeIs("https"))
uri = null;
}
@@ -309,7 +309,7 @@ let ReadingListUI = {
togglePageByBrowser: Task.async(function* (browser) {
let uri = browser.currentURI;
if (uri.spec.startsWith("about:reader?"))
- uri = ReaderParent.parseReaderUrl(uri.spec);
+ uri = ReaderMode.getOriginalUrl(uri.spec);
if (!uri)
return;
@@ -330,7 +330,7 @@ let ReadingListUI = {
isItemForCurrentBrowser(item) {
let currentURL = gBrowser.currentURI.spec;
if (currentURL.startsWith("about:reader?"))
- currentURL = ReaderParent.parseReaderUrl(currentURL);
+ currentURL = ReaderMode.getOriginalUrl(currentURL);
if (item.url == currentURL || item.resolvedURL == currentURL) {
return true;
diff --git a/browser/base/content/browser.js b/browser/base/content/browser.js
index f5ccc901379..b1689f76446 100644
--- a/browser/base/content/browser.js
+++ b/browser/base/content/browser.js
@@ -213,6 +213,9 @@ XPCOMUtils.defineLazyModuleGetter(this, "CastingApps",
XPCOMUtils.defineLazyModuleGetter(this, "SimpleServiceDiscovery",
"resource://gre/modules/SimpleServiceDiscovery.jsm");
+XPCOMUtils.defineLazyModuleGetter(this, "ReaderMode",
+ "resource://gre/modules/ReaderMode.jsm");
+
XPCOMUtils.defineLazyModuleGetter(this, "ReaderParent",
"resource:///modules/ReaderParent.jsm");
diff --git a/browser/base/content/nsContextMenu.js b/browser/base/content/nsContextMenu.js
index 04d385099cb..6f69ada6859 100644
--- a/browser/base/content/nsContextMenu.js
+++ b/browser/base/content/nsContextMenu.js
@@ -578,6 +578,7 @@ nsContextMenu.prototype = {
this.linkURI = null;
this.linkText = "";
this.linkProtocol = "";
+ this.linkDownload = "";
this.linkHasNoReferrer = false;
this.onMathML = false;
this.inFrame = false;
@@ -751,6 +752,14 @@ nsContextMenu.prototype = {
this.onMailtoLink = (this.linkProtocol == "mailto");
this.onSaveableLink = this.isLinkSaveable( this.link );
this.linkHasNoReferrer = BrowserUtils.linkHasNoReferrer(elem);
+ try {
+ if (elem.download) {
+ // Ignore download attribute on cross-origin links
+ this.principal.checkMayLoad(this.linkURI, false, true);
+ this.linkDownload = elem.download;
+ }
+ }
+ catch (ex) {}
}
// Background image? Don't bother if we've already found a
@@ -1171,7 +1180,8 @@ nsContextMenu.prototype = {
// Helper function to wait for appropriate MIME-type headers and
// then prompt the user with a file picker
- saveHelper: function(linkURL, linkText, dialogTitle, bypassCache, doc) {
+ saveHelper: function(linkURL, linkText, dialogTitle, bypassCache, doc,
+ linkDownload) {
// canonical def in nsURILoader.h
const NS_ERROR_SAVE_LINK_AS_TIMEOUT = 0x805d0020;
@@ -1277,6 +1287,8 @@ nsContextMenu.prototype = {
null, // aTriggeringPrincipal
Ci.nsILoadInfo.SEC_NORMAL,
Ci.nsIContentPolicy.TYPE_OTHER);
+ if (linkDownload)
+ channel.contentDispositionFilename = linkDownload;
if (channel instanceof Ci.nsIPrivateBrowsingChannel) {
let docIsPrivate = PrivateBrowsingUtils.isBrowserPrivate(gBrowser.selectedBrowser);
channel.setPrivate(docIsPrivate);
@@ -1313,7 +1325,8 @@ nsContextMenu.prototype = {
// Save URL of clicked-on link.
saveLink: function() {
urlSecurityCheck(this.linkURL, this.principal);
- this.saveHelper(this.linkURL, this.linkText, null, true, this.ownerDoc);
+ this.saveHelper(this.linkURL, this.linkText, null, true, this.ownerDoc,
+ this.linkDownload);
},
// Backwards-compatibility wrapper
@@ -1341,7 +1354,7 @@ nsContextMenu.prototype = {
else if (this.onVideo || this.onAudio) {
urlSecurityCheck(this.mediaURL, this.principal);
var dialogTitle = this.onVideo ? "SaveVideoTitle" : "SaveAudioTitle";
- this.saveHelper(this.mediaURL, null, dialogTitle, false, doc);
+ this.saveHelper(this.mediaURL, null, dialogTitle, false, doc, "");
}
},
diff --git a/browser/base/content/test/general/browser_readerMode.js b/browser/base/content/test/general/browser_readerMode.js
index 464fb7ec61e..c8d1cc4b4ef 100644
--- a/browser/base/content/test/general/browser_readerMode.js
+++ b/browser/base/content/test/general/browser_readerMode.js
@@ -17,7 +17,7 @@ const TEST_PATH = "http://example.com/browser/browser/base/content/test/general/
let readerButton = document.getElementById("reader-mode-button");
-add_task(function* () {
+add_task(function* test_reader_button() {
registerCleanupFunction(function() {
// Reset test prefs.
TEST_PREFS.forEach(([name, value]) => {
@@ -90,3 +90,16 @@ add_task(function* () {
yield promiseWaitForCondition(() => !readerButton.hidden);
is_element_visible(readerButton, "Reader mode button is present on a reader-able page");
});
+
+add_task(function* test_getOriginalUrl() {
+ let { ReaderMode } = Cu.import("resource://gre/modules/ReaderMode.jsm", {});
+ let url = "http://foo.com/article.html";
+
+ is(ReaderMode.getOriginalUrl("about:reader?url=" + encodeURIComponent(url)), url, "Found original URL from encoded URL");
+ is(ReaderMode.getOriginalUrl("about:reader?foobar"), null, "Did not find original URL from malformed reader URL");
+ is(ReaderMode.getOriginalUrl(url), null, "Did not find original URL from non-reader URL");
+
+ let badUrl = "http://foo.com/?;$%^^";
+ is(ReaderMode.getOriginalUrl("about:reader?url=" + encodeURIComponent(badUrl)), badUrl, "Found original URL from encoded malformed URL");
+ is(ReaderMode.getOriginalUrl("about:reader?url=" + badUrl), badUrl, "Found original URL from non-encoded malformed URL");
+});
diff --git a/browser/base/content/test/newtab/browser_newtab_block.js b/browser/base/content/test/newtab/browser_newtab_block.js
index bcb3d7baf57..9509786feec 100644
--- a/browser/base/content/test/newtab/browser_newtab_block.js
+++ b/browser/base/content/test/newtab/browser_newtab_block.js
@@ -6,7 +6,21 @@
* as expected. Pinned tabs should not be moved. Gaps will be re-filled
* if more sites are available.
*/
+
+gDirectorySource = "data:application/json," + JSON.stringify({
+ "suggested": [{
+ url: "http://suggested.com/",
+ imageURI: "data:image/png;base64,helloWORLD3",
+ title: "title",
+ type: "affiliate",
+ frecent_sites: ["example0.com"]
+ }]
+});
+
function runTests() {
+ let origIsTopPlacesSite = NewTabUtils.isTopPlacesSite;
+ NewTabUtils.isTopPlacesSite = (site) => false;
+
// we remove sites and expect the gaps to be filled as long as there still
// are some sites available
yield setLinks("0,1,2,3,4,5,6,7,8,9");
@@ -58,4 +72,16 @@ function runTests() {
yield blockCell(0);
checkGrid("1,2,3,4,5,6,7,9,8p");
+
+ // Test that blocking the targeted site also removes its associated suggested tile
+ NewTabUtils.isTopPlacesSite = origIsTopPlacesSite;
+ yield restore();
+ yield setLinks("0,1,2,3,4,5,6,7,8,9");
+ yield addNewTabPageTab();
+ yield customizeNewTabPage("enhanced");
+ checkGrid("http://suggested.com/,0,1,2,3,4,5,6,7,8,9");
+
+ yield blockCell(1);
+ yield addNewTabPageTab();
+ checkGrid("1,2,3,4,5,6,7,8,9");
}
diff --git a/browser/base/content/test/newtab/browser_newtab_enhanced.js b/browser/base/content/test/newtab/browser_newtab_enhanced.js
index 619ad8bf21b..a2ff6cd551d 100644
--- a/browser/base/content/test/newtab/browser_newtab_enhanced.js
+++ b/browser/base/content/test/newtab/browser_newtab_enhanced.js
@@ -109,7 +109,7 @@ function runTests() {
// Test that a suggested tile is not enhanced by a directory tile
let origIsTopPlacesSite = NewTabUtils.isTopPlacesSite;
NewTabUtils.isTopPlacesSite = () => true;
- yield setLinks("-1");
+ yield setLinks("-1,2,3,4,5,6,7,8");
// Test with enhanced = false
yield addNewTabPageTab();
@@ -119,7 +119,8 @@ function runTests() {
is(enhanced, "", "history link has no enhanced image");
is(title, "site#-1");
- is(getData(1), null, "there is only one link and it's a history link");
+ isnot(getData(7), null, "there are 8 history links");
+ is(getData(8), null, "there are 8 history links");
// Test with enhanced = true
@@ -138,5 +139,5 @@ function runTests() {
isnot(enhanced, "", "pinned history link has enhanced image");
is(title, "title");
- is(getData(2), null, "there is only a suggested link followed by an enhanced history link");
+ is(getData(9), null, "there is a suggested link followed by an enhanced history link and the remaining history links");
}
diff --git a/browser/base/content/urlbarBindings.xml b/browser/base/content/urlbarBindings.xml
index 3443ccdcf2c..0a43bab66c9 100644
--- a/browser/base/content/urlbarBindings.xml
+++ b/browser/base/content/urlbarBindings.xml
@@ -168,7 +168,7 @@ file, You can obtain one at http://mozilla.org/MPL/2.0/.
}
}
} else {
- let originalUrl = ReaderParent.parseReaderUrl(aValue);
+ let originalUrl = ReaderMode.getOriginalUrl(aValue);
if (originalUrl) {
returnValue = originalUrl;
}
diff --git a/browser/components/preferences/in-content/content.js b/browser/components/preferences/in-content/content.js
index f5c9ed80cb7..9845638a708 100644
--- a/browser/components/preferences/in-content/content.js
+++ b/browser/components/preferences/in-content/content.js
@@ -185,7 +185,7 @@ var gContentPane = {
*/
configureFonts: function ()
{
- gSubDialog.open("chrome://browser/content/preferences/fonts.xul");
+ gSubDialog.open("chrome://browser/content/preferences/fonts.xul", "resizable=no");
},
/**
@@ -194,7 +194,7 @@ var gContentPane = {
*/
configureColors: function ()
{
- gSubDialog.open("chrome://browser/content/preferences/colors.xul");
+ gSubDialog.open("chrome://browser/content/preferences/colors.xul", "resizable=no");
},
// LANGUAGES
diff --git a/browser/components/preferences/in-content/privacy.js b/browser/components/preferences/in-content/privacy.js
index 41e430c960d..97fa72316b4 100644
--- a/browser/components/preferences/in-content/privacy.js
+++ b/browser/components/preferences/in-content/privacy.js
@@ -511,7 +511,7 @@ var gPrivacyPane = {
*/
showClearPrivateDataSettings: function ()
{
- gSubDialog.open("chrome://browser/content/preferences/sanitize.xul");
+ gSubDialog.open("chrome://browser/content/preferences/sanitize.xul", "resizable=no");
},
diff --git a/browser/components/preferences/in-content/security.js b/browser/components/preferences/in-content/security.js
index 2385462710c..fea9f52922a 100644
--- a/browser/components/preferences/in-content/security.js
+++ b/browser/components/preferences/in-content/security.js
@@ -217,7 +217,7 @@ var gSecurityPane = {
changeMasterPassword: function ()
{
gSubDialog.open("chrome://mozapps/content/preferences/changemp.xul",
- null, null, this._initMasterPasswordUI.bind(this));
+ "resizable=no", null, this._initMasterPasswordUI.bind(this));
},
/**
diff --git a/browser/modules/DirectoryLinksProvider.jsm b/browser/modules/DirectoryLinksProvider.jsm
index bf483c542e2..ff4c491c95f 100644
--- a/browser/modules/DirectoryLinksProvider.jsm
+++ b/browser/modules/DirectoryLinksProvider.jsm
@@ -65,6 +65,9 @@ const SUGGESTED_FRECENCY = Infinity;
// Default number of times to show a link
const DEFAULT_FREQUENCY_CAP = 5;
+// The min number of visible (not blocked) history tiles to have before showing suggested tiles
+const MIN_VISIBLE_HISTORY_TILES = 8;
+
// Divide frecency by this amount for pings
const PING_SCORE_DIVISOR = 10000;
@@ -509,6 +512,7 @@ let DirectoryLinksProvider = {
this._lastDownloadMS = 0;
NewTabUtils.placesProvider.addObserver(this);
+ NewTabUtils.links.addObserver(this);
return Task.spawn(function() {
// get the last modified time of the links file if it exists
@@ -563,7 +567,7 @@ let DirectoryLinksProvider = {
onLinkChanged: function (aProvider, aLink) {
// Make sure NewTabUtils.links handles the notification first.
setTimeout(() => {
- if (this._handleLinkChanged(aLink)) {
+ if (this._handleLinkChanged(aLink) || this._shouldUpdateSuggestedTile()) {
this._updateSuggestedTile();
}
}, 0);
@@ -591,6 +595,38 @@ let DirectoryLinksProvider = {
}
},
+ _getCurrentTopSiteCount: function() {
+ let visibleTopSiteCount = 0;
+ for (let link of NewTabUtils.links.getLinks().slice(0, MIN_VISIBLE_HISTORY_TILES)) {
+ if (link && (link.type == "history" || link.type == "enhanced")) {
+ visibleTopSiteCount++;
+ }
+ }
+ return visibleTopSiteCount;
+ },
+
+ _shouldUpdateSuggestedTile: function() {
+ let sortedLinks = NewTabUtils.getProviderLinks(this);
+
+ let mostFrecentLink = {};
+ if (sortedLinks && sortedLinks.length) {
+ mostFrecentLink = sortedLinks[0]
+ }
+
+ let currTopSiteCount = this._getCurrentTopSiteCount();
+ if ((!mostFrecentLink.targetedSite && currTopSiteCount >= MIN_VISIBLE_HISTORY_TILES) ||
+ (mostFrecentLink.targetedSite && currTopSiteCount < MIN_VISIBLE_HISTORY_TILES)) {
+ // If mostFrecentLink has a targetedSite then mostFrecentLink is a suggested link.
+ // If we have enough history links (8+) to show a suggested tile and we are not
+ // already showing one, then we should update (to *attempt* to add a suggested tile).
+ // OR if we don't have enough history to show a suggested tile (<8) and we are
+ // currently showing one, we should update (to remove it).
+ return true;
+ }
+
+ return false;
+ },
+
/**
* Chooses and returns a suggested tile based on a user's top sites
* that we have an available suggested tile for.
@@ -620,8 +656,9 @@ let DirectoryLinksProvider = {
}
}
- if (this._topSitesWithSuggestedLinks.size == 0) {
- // There are no potential suggested links we can show.
+ if (this._topSitesWithSuggestedLinks.size == 0 || !this._shouldUpdateSuggestedTile()) {
+ // There are no potential suggested links we can show or not
+ // enough history for a suggested tile.
return;
}
diff --git a/browser/modules/ReaderParent.jsm b/browser/modules/ReaderParent.jsm
index dd18eb1a904..2068a4ae815 100644
--- a/browser/modules/ReaderParent.jsm
+++ b/browser/modules/ReaderParent.jsm
@@ -172,7 +172,7 @@ let ReaderParent = {
let url = browser.currentURI.spec;
if (url.startsWith("about:reader")) {
- let originalURL = this._getOriginalUrl(url);
+ let originalURL = ReaderMode.getOriginalUrl(url);
if (!originalURL) {
Cu.reportError("Error finding original URL for about:reader URL: " + url);
} else {
@@ -183,28 +183,6 @@ let ReaderParent = {
}
},
- parseReaderUrl: function(url) {
- if (!url.startsWith("about:reader?")) {
- return null;
- }
- return this._getOriginalUrl(url);
- },
-
- /**
- * Returns original URL from an about:reader URL.
- *
- * @param url An about:reader URL.
- * @return The original URL for the article, or null if we did not find
- * a properly formatted about:reader URL.
- */
- _getOriginalUrl: function(url) {
- let searchParams = new URLSearchParams(url.substring("about:reader?".length));
- if (!searchParams.has("url")) {
- return null;
- }
- return decodeURIComponent(searchParams.get("url"));
- },
-
/**
* Gets an article for a given URL. This method will download and parse a document.
*
diff --git a/browser/modules/Social.jsm b/browser/modules/Social.jsm
index 877db42f5a6..5f807a82a21 100644
--- a/browser/modules/Social.jsm
+++ b/browser/modules/Social.jsm
@@ -265,18 +265,19 @@ function CreateSocialStatusWidget(aId, aProvider) {
CustomizableUI.createWidget({
id: aId,
- type: 'custom',
+ type: "custom",
removable: true,
defaultArea: CustomizableUI.AREA_NAVBAR,
onBuild: function(aDocument) {
- let node = aDocument.createElement('toolbarbutton');
+ let node = aDocument.createElement("toolbarbutton");
node.id = this.id;
- node.setAttribute('class', 'toolbarbutton-1 chromeclass-toolbar-additional social-status-button badged-button');
+ node.setAttribute("class", "toolbarbutton-1 chromeclass-toolbar-additional social-status-button badged-button");
node.style.listStyleImage = "url(" + (aProvider.icon32URL || aProvider.iconURL) + ")";
node.setAttribute("origin", aProvider.origin);
node.setAttribute("label", aProvider.name);
node.setAttribute("tooltiptext", aProvider.name);
node.setAttribute("oncommand", "SocialStatus.showPopup(this);");
+ node.setAttribute("constrain-size", "true");
if (PrivateBrowsingUtils.isWindowPrivate(aDocument.defaultView))
node.setAttribute("disabled", "true");
@@ -298,14 +299,15 @@ function CreateSocialMarkWidget(aId, aProvider) {
CustomizableUI.createWidget({
id: aId,
- type: 'custom',
+ type: "custom",
removable: true,
defaultArea: CustomizableUI.AREA_NAVBAR,
onBuild: function(aDocument) {
- let node = aDocument.createElement('toolbarbutton');
+ let node = aDocument.createElement("toolbarbutton");
node.id = this.id;
- node.setAttribute('class', 'toolbarbutton-1 chromeclass-toolbar-additional social-mark-button');
- node.setAttribute('type', "socialmark");
+ node.setAttribute("class", "toolbarbutton-1 chromeclass-toolbar-additional social-mark-button");
+ node.setAttribute("type", "socialmark");
+ node.setAttribute("constrain-size", "true");
node.style.listStyleImage = "url(" + (aProvider.unmarkedIcon || aProvider.icon32URL || aProvider.iconURL) + ")";
node.setAttribute("origin", aProvider.origin);
diff --git a/browser/modules/test/xpcshell/test_DirectoryLinksProvider.js b/browser/modules/test/xpcshell/test_DirectoryLinksProvider.js
index 79c7e2b7c31..7faa9d97ac4 100644
--- a/browser/modules/test/xpcshell/test_DirectoryLinksProvider.js
+++ b/browser/modules/test/xpcshell/test_DirectoryLinksProvider.js
@@ -223,6 +223,42 @@ function run_test() {
});
}
+add_task(function test_shouldUpdateSuggestedTile() {
+ let suggestedLink = {
+ targetedSite: "somesite.com"
+ };
+
+ // DirectoryLinksProvider has no suggested tile and no top sites => no need to update
+ do_check_eq(DirectoryLinksProvider._getCurrentTopSiteCount(), 0);
+ isIdentical(NewTabUtils.getProviderLinks(), []);
+ do_check_eq(DirectoryLinksProvider._shouldUpdateSuggestedTile(), false);
+
+ // DirectoryLinksProvider has a suggested tile and no top sites => need to update
+ let origGetProviderLinks = NewTabUtils.getProviderLinks;
+ NewTabUtils.getProviderLinks = (provider) => [suggestedLink];
+
+ do_check_eq(DirectoryLinksProvider._getCurrentTopSiteCount(), 0);
+ isIdentical(NewTabUtils.getProviderLinks(), [suggestedLink]);
+ do_check_eq(DirectoryLinksProvider._shouldUpdateSuggestedTile(), true);
+
+ // DirectoryLinksProvider has a suggested tile and 8 top sites => no need to update
+ let origCurrentTopSiteCount = DirectoryLinksProvider._getCurrentTopSiteCount;
+ DirectoryLinksProvider._getCurrentTopSiteCount = () => 8;
+
+ do_check_eq(DirectoryLinksProvider._getCurrentTopSiteCount(), 8);
+ isIdentical(NewTabUtils.getProviderLinks(), [suggestedLink]);
+ do_check_eq(DirectoryLinksProvider._shouldUpdateSuggestedTile(), false);
+
+ // DirectoryLinksProvider has no suggested tile and 8 top sites => need to update
+ NewTabUtils.getProviderLinks = origGetProviderLinks;
+ do_check_eq(DirectoryLinksProvider._getCurrentTopSiteCount(), 8);
+ isIdentical(NewTabUtils.getProviderLinks(), []);
+ do_check_eq(DirectoryLinksProvider._shouldUpdateSuggestedTile(), true);
+
+ // Cleanup
+ DirectoryLinksProvider._getCurrentTopSiteCount = origCurrentTopSiteCount;
+});
+
add_task(function test_updateSuggestedTile() {
let topSites = ["site0.com", "1040.com", "site2.com", "hrblock.com", "site4.com", "freetaxusa.com", "site6.com"];
@@ -246,6 +282,9 @@ add_task(function test_updateSuggestedTile() {
return links;
}
+ let origCurrentTopSiteCount = DirectoryLinksProvider._getCurrentTopSiteCount;
+ DirectoryLinksProvider._getCurrentTopSiteCount = () => 8;
+
do_check_eq(DirectoryLinksProvider._updateSuggestedTile(), undefined);
function TestFirstRun() {
@@ -346,6 +385,7 @@ add_task(function test_updateSuggestedTile() {
yield promiseCleanDirectoryLinksProvider();
NewTabUtils.isTopPlacesSite = origIsTopPlacesSite;
NewTabUtils.getProviderLinks = origGetProviderLinks;
+ DirectoryLinksProvider._getCurrentTopSiteCount = origCurrentTopSiteCount;
});
add_task(function test_suggestedLinksMap() {
@@ -436,6 +476,9 @@ add_task(function test_suggestedAttributes() {
let origIsTopPlacesSite = NewTabUtils.isTopPlacesSite;
NewTabUtils.isTopPlacesSite = () => true;
+ let origCurrentTopSiteCount = DirectoryLinksProvider._getCurrentTopSiteCount;
+ DirectoryLinksProvider._getCurrentTopSiteCount = () => 8;
+
let frecent_sites = ["top.site.com"];
let imageURI = "https://image/";
let title = "the title";
@@ -478,6 +521,7 @@ add_task(function test_suggestedAttributes() {
// Cleanup.
NewTabUtils.isTopPlacesSite = origIsTopPlacesSite;
+ DirectoryLinksProvider._getCurrentTopSiteCount = origCurrentTopSiteCount;
gLinks.removeProvider(DirectoryLinksProvider);
DirectoryLinksProvider.removeObserver(gLinks);
});
@@ -487,6 +531,9 @@ add_task(function test_frequencyCappedSites_views() {
let origIsTopPlacesSite = NewTabUtils.isTopPlacesSite;
NewTabUtils.isTopPlacesSite = () => true;
+ let origCurrentTopSiteCount = DirectoryLinksProvider._getCurrentTopSiteCount;
+ DirectoryLinksProvider._getCurrentTopSiteCount = () => 8;
+
let testUrl = "http://frequency.capped/link";
let targets = ["top.site.com"];
let data = {
@@ -548,6 +595,7 @@ add_task(function test_frequencyCappedSites_views() {
// Cleanup.
NewTabUtils.isTopPlacesSite = origIsTopPlacesSite;
+ DirectoryLinksProvider._getCurrentTopSiteCount = origCurrentTopSiteCount;
gLinks.removeProvider(DirectoryLinksProvider);
DirectoryLinksProvider.removeObserver(gLinks);
Services.prefs.setCharPref(kPingUrlPref, kPingUrl);
@@ -558,6 +606,9 @@ add_task(function test_frequencyCappedSites_click() {
let origIsTopPlacesSite = NewTabUtils.isTopPlacesSite;
NewTabUtils.isTopPlacesSite = () => true;
+ let origCurrentTopSiteCount = DirectoryLinksProvider._getCurrentTopSiteCount;
+ DirectoryLinksProvider._getCurrentTopSiteCount = () => 8;
+
let testUrl = "http://frequency.capped/link";
let targets = ["top.site.com"];
let data = {
@@ -613,6 +664,7 @@ add_task(function test_frequencyCappedSites_click() {
// Cleanup.
NewTabUtils.isTopPlacesSite = origIsTopPlacesSite;
+ DirectoryLinksProvider._getCurrentTopSiteCount = origCurrentTopSiteCount;
gLinks.removeProvider(DirectoryLinksProvider);
DirectoryLinksProvider.removeObserver(gLinks);
Services.prefs.setCharPref(kPingUrlPref, kPingUrl);
@@ -1089,6 +1141,8 @@ add_task(function test_DirectoryLinksProvider_getEnhancedLink() {
add_task(function test_DirectoryLinksProvider_enhancedURIs() {
let origIsTopPlacesSite = NewTabUtils.isTopPlacesSite;
NewTabUtils.isTopPlacesSite = () => true;
+ let origCurrentTopSiteCount = DirectoryLinksProvider._getCurrentTopSiteCount;
+ DirectoryLinksProvider._getCurrentTopSiteCount = () => 8;
let data = {
"suggested": [
@@ -1129,6 +1183,7 @@ add_task(function test_DirectoryLinksProvider_enhancedURIs() {
// Cleanup.
NewTabUtils.isTopPlacesSite = origIsTopPlacesSite;
+ DirectoryLinksProvider._getCurrentTopSiteCount = origCurrentTopSiteCount;
gLinks.removeProvider(DirectoryLinksProvider);
});
diff --git a/browser/themes/linux/browser.css b/browser/themes/linux/browser.css
index c7054267188..f01efae4c38 100644
--- a/browser/themes/linux/browser.css
+++ b/browser/themes/linux/browser.css
@@ -595,12 +595,12 @@ menuitem:not([type]):not(.menuitem-tooltip):not(.menuitem-iconic-tooltip) {
}
/* Help SDK icons fit: */
-toolbarbutton[sdk-button="true"][cui-areatype="toolbar"] > .toolbarbutton-icon,
-toolbarbutton[sdk-button="true"][cui-areatype="toolbar"] > .toolbarbutton-badge-container > .toolbarbutton-icon {
+toolbarbutton[constrain-size="true"][cui-areatype="toolbar"] > .toolbarbutton-icon,
+toolbarbutton[constrain-size="true"][cui-areatype="toolbar"] > .toolbarbutton-badge-container > .toolbarbutton-icon {
width: 16px;
}
-:-moz-any(#TabsToolbar, #nav-bar) toolbarbutton[sdk-button="true"][cui-areatype="toolbar"] > .toolbarbutton-icon {
+:-moz-any(#TabsToolbar, #nav-bar) toolbarbutton[constrain-size="true"][cui-areatype="toolbar"] > .toolbarbutton-icon {
/* XXXgijs box models strike again: this is 16px + 2 * 7px padding + 2 * 1px border (from the rules above) */
width: 32px;
}
diff --git a/browser/themes/osx/browser.css b/browser/themes/osx/browser.css
index 1d352b7d69a..5358ce66bcf 100644
--- a/browser/themes/osx/browser.css
+++ b/browser/themes/osx/browser.css
@@ -1353,8 +1353,8 @@ toolbar .toolbarbutton-1:not(:-moz-any(@primaryToolbarButtons@)) > .toolbarbutto
}
/* Help SDK icons fit: */
-toolbarbutton[sdk-button="true"][cui-areatype="toolbar"] > .toolbarbutton-icon,
-toolbarbutton[sdk-button="true"][cui-areatype="toolbar"] > .toolbarbutton-badge-container > .toolbarbutton-icon {
+toolbarbutton[constrain-size="true"][cui-areatype="toolbar"] > .toolbarbutton-icon,
+toolbarbutton[constrain-size="true"][cui-areatype="toolbar"] > .toolbarbutton-badge-container > .toolbarbutton-icon {
width: 16px;
}
diff --git a/browser/themes/shared/customizableui/panelUIOverlay.inc.css b/browser/themes/shared/customizableui/panelUIOverlay.inc.css
index a6612ac3f4e..8148dbb7a4e 100644
--- a/browser/themes/shared/customizableui/panelUIOverlay.inc.css
+++ b/browser/themes/shared/customizableui/panelUIOverlay.inc.css
@@ -300,10 +300,10 @@ toolbarpaletteitem[place="panel"]:not([haswideitem=true]) > .toolbarbutton-1 {
}
/* Help SDK buttons fit in. */
-toolbarpaletteitem[place="palette"] > toolbarbutton[sdk-button="true"] > .toolbarbutton-icon,
-toolbarpaletteitem[place="palette"] > toolbarbutton[sdk-button="true"] > .toolbarbutton-badge-container > .toolbarbutton-icon,
-toolbarbutton[sdk-button="true"][cui-areatype="menu-panel"] > .toolbarbutton-icon,
-toolbarbutton[sdk-button="true"][cui-areatype="menu-panel"] > .toolbarbutton-badge-container > .toolbarbutton-icon {
+toolbarpaletteitem[place="palette"] > toolbarbutton[constrain-size="true"] > .toolbarbutton-icon,
+toolbarpaletteitem[place="palette"] > toolbarbutton[constrain-size="true"] > .toolbarbutton-badge-container > .toolbarbutton-icon,
+toolbarbutton[constrain-size="true"][cui-areatype="menu-panel"] > .toolbarbutton-icon,
+toolbarbutton[constrain-size="true"][cui-areatype="menu-panel"] > .toolbarbutton-badge-container > .toolbarbutton-icon {
height: 32px;
width: 32px;
}
diff --git a/browser/themes/windows/browser.css b/browser/themes/windows/browser.css
index dbe27936365..0263086ad1a 100644
--- a/browser/themes/windows/browser.css
+++ b/browser/themes/windows/browser.css
@@ -733,12 +733,12 @@ toolbarbutton[cui-areatype="toolbar"] > :-moz-any(@nestedButtons@) > .toolbarbut
}
/* Help SDK icons fit: */
-toolbarbutton[sdk-button="true"][cui-areatype="toolbar"] > .toolbarbutton-icon,
-toolbarbutton[sdk-button="true"][cui-areatype="toolbar"] > .toolbarbutton-badge-container > .toolbarbutton-icon {
+toolbarbutton[constrain-size="true"][cui-areatype="toolbar"] > .toolbarbutton-icon,
+toolbarbutton[constrain-size="true"][cui-areatype="toolbar"] > .toolbarbutton-badge-container > .toolbarbutton-icon {
width: 16px;
}
-#nav-bar toolbarbutton[sdk-button="true"][cui-areatype="toolbar"] > .toolbarbutton-icon {
+#nav-bar toolbarbutton[constrain-size="true"][cui-areatype="toolbar"] > .toolbarbutton-icon {
/* XXXgijs box models strike again: this is 16px + 2 * 7px padding + 2 * 1px border (from the rules above) */
width: 32px;
}
@@ -1630,13 +1630,6 @@ richlistitem[type~="action"][actiontype="switchtab"] > .ac-url-box > .ac-action-
}
-toolbarbutton[type="socialmark"] > .toolbarbutton-icon {
- width: auto;
- height: auto;
- max-width: 32px;
- max-height: 24px;
-}
-
/* fixup corners for share panel */
.social-panel > .social-panel-frame {
border-radius: inherit;
diff --git a/caps/nsPrincipal.cpp b/caps/nsPrincipal.cpp
index 4d57071f26a..8c39a0dc578 100644
--- a/caps/nsPrincipal.cpp
+++ b/caps/nsPrincipal.cpp
@@ -980,8 +980,21 @@ nsExpandedPrincipal::IsOnCSSUnprefixingWhitelist()
void
nsExpandedPrincipal::GetScriptLocation(nsACString& aStr)
{
- // Is that a good idea to list it's principals?
aStr.Assign(EXPANDED_PRINCIPAL_SPEC);
+ aStr.AppendLiteral(" (");
+
+ for (size_t i = 0; i < mPrincipals.Length(); ++i) {
+ if (i != 0) {
+ aStr.AppendLiteral(", ");
+ }
+
+ nsAutoCString spec;
+ nsJSPrincipals::get(mPrincipals.ElementAt(i))->GetScriptLocation(spec);
+
+ aStr.Append(spec);
+
+ }
+ aStr.Append(")");
}
#ifdef DEBUG
diff --git a/gfx/gl/GLContextProviderEGL.cpp b/gfx/gl/GLContextProviderEGL.cpp
index 11c1329e6f7..91a31e723db 100644
--- a/gfx/gl/GLContextProviderEGL.cpp
+++ b/gfx/gl/GLContextProviderEGL.cpp
@@ -446,6 +446,9 @@ GLContextEGL::ReleaseSurface() {
if (mOwnsContext) {
mozilla::gl::DestroySurface(mSurface);
}
+ if (mSurface == mSurfaceOverride) {
+ mSurfaceOverride = EGL_NO_SURFACE;
+ }
mSurface = EGL_NO_SURFACE;
}
@@ -813,6 +816,41 @@ GLContextProviderEGL::CreateForWindow(nsIWidget *aWidget)
return glContext.forget();
}
+#if defined(ANDROID)
+EGLSurface
+GLContextProviderEGL::CreateEGLSurface(void* aWindow)
+{
+ if (!sEGLLibrary.EnsureInitialized()) {
+ MOZ_CRASH("Failed to load EGL library!\n");
+ }
+
+ EGLConfig config;
+ if (!CreateConfig(&config)) {
+ MOZ_CRASH("Failed to create EGLConfig!\n");
+ }
+
+ MOZ_ASSERT(aWindow);
+
+ EGLSurface surface = sEGLLibrary.fCreateWindowSurface(EGL_DISPLAY(), config, aWindow, 0);
+
+ if (surface == EGL_NO_SURFACE) {
+ MOZ_CRASH("Failed to create EGLSurface!\n");
+ }
+
+ return surface;
+}
+
+void
+GLContextProviderEGL::DestroyEGLSurface(EGLSurface surface)
+{
+ if (!sEGLLibrary.EnsureInitialized()) {
+ MOZ_CRASH("Failed to load EGL library!\n");
+ }
+
+ sEGLLibrary.fDestroySurface(EGL_DISPLAY(), surface);
+}
+#endif // defined(ANDROID)
+
already_AddRefed
GLContextEGL::CreateEGLPBufferOffscreenContext(const gfxIntSize& size)
{
diff --git a/gfx/gl/GLContextProviderImpl.h b/gfx/gl/GLContextProviderImpl.h
index 9e87170c823..fa4d253fe22 100644
--- a/gfx/gl/GLContextProviderImpl.h
+++ b/gfx/gl/GLContextProviderImpl.h
@@ -10,6 +10,9 @@
#ifndef GL_CONTEXT_PROVIDER_NAME
#error GL_CONTEXT_PROVIDER_NAME not defined
#endif
+#if defined(ANDROID)
+typedef void* EGLSurface;
+#endif // defined(ANDROID)
class GL_CONTEXT_PROVIDER_NAME
{
@@ -76,6 +79,11 @@ public:
static already_AddRefed
CreateWrappingExisting(void* aContext, void* aSurface);
+#if defined(ANDROID)
+ static EGLSurface CreateEGLSurface(void* aWindow);
+ static void DestroyEGLSurface(EGLSurface surface);
+#endif // defined(ANDROID)
+
/**
* Get a pointer to the global context, creating it if it doesn't exist.
*/
diff --git a/gfx/layers/composite/LayerManagerComposite.cpp b/gfx/layers/composite/LayerManagerComposite.cpp
index d634a97834f..7d6a73cffcc 100644
--- a/gfx/layers/composite/LayerManagerComposite.cpp
+++ b/gfx/layers/composite/LayerManagerComposite.cpp
@@ -55,6 +55,11 @@
#include "nsRegion.h" // for nsIntRegion, etc
#ifdef MOZ_WIDGET_ANDROID
#include
+#include "AndroidBridge.h"
+#include "opengl/CompositorOGL.h"
+#include "GLContextEGL.h"
+#include "GLContextProvider.h"
+#include "ScopedGLHelpers.h"
#endif
#include "GeckoProfiler.h"
#include "TextRenderer.h" // for TextRenderer
@@ -307,6 +312,9 @@ LayerManagerComposite::EndTransaction(DrawPaintedLayerCallback aCallback,
ApplyOcclusionCulling(mRoot, opaque);
Render();
+#ifdef MOZ_WIDGET_ANDROID
+ RenderToPresentationSurface();
+#endif
mGeometryChanged = false;
} else {
// Modified layer tree
@@ -769,6 +777,175 @@ LayerManagerComposite::Render()
RecordFrame();
}
+#ifdef MOZ_WIDGET_ANDROID
+class ScopedCompositorProjMatrix {
+public:
+ ScopedCompositorProjMatrix(CompositorOGL* aCompositor, const Matrix4x4& aProjMatrix):
+ mCompositor(aCompositor),
+ mOriginalProjMatrix(mCompositor->GetProjMatrix())
+ {
+ mCompositor->SetProjMatrix(aProjMatrix);
+ }
+
+ ~ScopedCompositorProjMatrix()
+ {
+ mCompositor->SetProjMatrix(mOriginalProjMatrix);
+ }
+private:
+ CompositorOGL* const mCompositor;
+ const Matrix4x4 mOriginalProjMatrix;
+};
+
+class ScopedCompostitorSurfaceSize {
+public:
+ ScopedCompostitorSurfaceSize(CompositorOGL* aCompositor, const gfx::IntSize& aSize) :
+ mCompositor(aCompositor),
+ mOriginalSize(mCompositor->GetDestinationSurfaceSize())
+ {
+ mCompositor->SetDestinationSurfaceSize(aSize);
+ }
+ ~ScopedCompostitorSurfaceSize()
+ {
+ mCompositor->SetDestinationSurfaceSize(mOriginalSize);
+ }
+private:
+ CompositorOGL* const mCompositor;
+ const gfx::IntSize mOriginalSize;
+};
+
+class ScopedCompositorRenderOffset {
+public:
+ ScopedCompositorRenderOffset(CompositorOGL* aCompositor, const ScreenPoint& aOffset) :
+ mCompositor(aCompositor),
+ mOriginalOffset(mCompositor->GetScreenRenderOffset())
+ {
+ mCompositor->SetScreenRenderOffset(aOffset);
+ }
+ ~ScopedCompositorRenderOffset()
+ {
+ mCompositor->SetScreenRenderOffset(mOriginalOffset);
+ }
+private:
+ CompositorOGL* const mCompositor;
+ const ScreenPoint mOriginalOffset;
+};
+
+class ScopedContextSurfaceOverride {
+public:
+ ScopedContextSurfaceOverride(GLContextEGL* aContext, void* aSurface) :
+ mContext(aContext)
+ {
+ MOZ_ASSERT(aSurface);
+ mContext->SetEGLSurfaceOverride(aSurface);
+ mContext->MakeCurrent(true);
+ }
+ ~ScopedContextSurfaceOverride()
+ {
+ mContext->SetEGLSurfaceOverride(EGL_NO_SURFACE);
+ mContext->MakeCurrent(true);
+ }
+private:
+ GLContextEGL* const mContext;
+};
+
+void
+LayerManagerComposite::RenderToPresentationSurface()
+{
+ if (!AndroidBridge::Bridge()) {
+ return;
+ }
+
+ void* window = AndroidBridge::Bridge()->GetPresentationWindow();
+
+ if (!window) {
+ return;
+ }
+
+ EGLSurface surface = AndroidBridge::Bridge()->GetPresentationSurface();
+
+ if (!surface) {
+ //create surface;
+ surface = GLContextProviderEGL::CreateEGLSurface(window);
+ if (!surface) {
+ return;
+ }
+
+ AndroidBridge::Bridge()->SetPresentationSurface(surface);
+ }
+
+ CompositorOGL* compositor = static_cast(mCompositor.get());
+ GLContext* gl = compositor->gl();
+ GLContextEGL* egl = GLContextEGL::Cast(gl);
+
+ if (!egl) {
+ return;
+ }
+
+ const IntSize windowSize = AndroidBridge::Bridge()->GetNativeWindowSize(window);
+
+ if ((windowSize.width <= 0) || (windowSize.height <= 0)) {
+ return;
+ }
+
+ const int actualWidth = windowSize.width;
+ const int actualHeight = windowSize.height;
+
+ const gfx::IntSize originalSize = compositor->GetDestinationSurfaceSize();
+
+ const int pageWidth = originalSize.width;
+ const int pageHeight = originalSize.height;
+
+ float scale = 1.0;
+
+ if ((pageWidth > actualWidth) || (pageHeight > actualHeight)) {
+ const float scaleWidth = (float)actualWidth / (float)pageWidth;
+ const float scaleHeight = (float)actualHeight / (float)pageHeight;
+ scale = scaleWidth <= scaleHeight ? scaleWidth : scaleHeight;
+ }
+
+ const gfx::IntSize actualSize(actualWidth, actualHeight);
+ ScopedCompostitorSurfaceSize overrideSurfaceSize(compositor, actualSize);
+
+ const ScreenPoint offset((actualWidth - (int)(scale * pageWidth)) / 2, 0);
+ ScopedCompositorRenderOffset overrideRenderOffset(compositor, offset);
+ ScopedContextSurfaceOverride overrideSurface(egl, surface);
+
+ nsIntRegion invalid;
+ Rect bounds(0.0f, 0.0f, scale * pageWidth, (float)actualHeight);
+ Rect rect, actualBounds;
+
+ mCompositor->BeginFrame(invalid, nullptr, bounds, &rect, &actualBounds);
+
+ // Override the projection matrix since the presentation frame buffer
+ // is probably not the same size as the device frame buffer. The override
+ // projection matrix also scales the content to fit into the presentation
+ // frame buffer.
+ Matrix viewMatrix;
+ viewMatrix.PreTranslate(-1.0, 1.0);
+ viewMatrix.PreScale((2.0f * scale) / (float)actualWidth, (2.0f * scale) / (float)actualHeight);
+ viewMatrix.PreScale(1.0f, -1.0f);
+ viewMatrix.PreTranslate((int)((float)offset.x / scale), offset.y);
+
+ Matrix4x4 projMatrix = Matrix4x4::From2D(viewMatrix);
+
+ ScopedCompositorProjMatrix overrideProjMatrix(compositor, projMatrix);
+
+ // The Java side of Fennec sets a scissor rect that accounts for
+ // chrome such as the URL bar. Override that so that the entire frame buffer
+ // is cleared.
+ ScopedScissorRect screen(egl, 0, 0, actualWidth, actualHeight);
+ egl->fClearColor(0.0, 0.0, 0.0, 0.0);
+ egl->fClear(LOCAL_GL_COLOR_BUFFER_BIT);
+
+ const nsIntRect clipRect = nsIntRect(0, 0, (int)(scale * pageWidth), actualHeight);
+ RootLayer()->Prepare(RenderTargetPixel::FromUntyped(clipRect));
+ RootLayer()->RenderLayer(clipRect);
+
+ mCompositor->EndFrame();
+ mCompositor->SetFBAcquireFence(mRoot);
+}
+#endif
+
static void
SubtractTransformedRegion(nsIntRegion& aRegion,
const nsIntRegion& aRegionToSubtract,
diff --git a/gfx/layers/composite/LayerManagerComposite.h b/gfx/layers/composite/LayerManagerComposite.h
index ca5f0712926..34b851079af 100644
--- a/gfx/layers/composite/LayerManagerComposite.h
+++ b/gfx/layers/composite/LayerManagerComposite.h
@@ -278,6 +278,9 @@ private:
* Render the current layer tree to the active target.
*/
void Render();
+#ifdef MOZ_WIDGET_ANDROID
+ void RenderToPresentationSurface();
+#endif
/**
* Render debug overlays such as the FPS/FrameCounter above the frame.
diff --git a/gfx/layers/ipc/CompositorParent.cpp b/gfx/layers/ipc/CompositorParent.cpp
index 4d7647d02f4..db4dfba1044 100644
--- a/gfx/layers/ipc/CompositorParent.cpp
+++ b/gfx/layers/ipc/CompositorParent.cpp
@@ -800,6 +800,22 @@ CompositorParent::SchedulePauseOnCompositorThread()
lock.Wait();
}
+bool
+CompositorParent::ScheduleResumeOnCompositorThread()
+{
+ MonitorAutoLock lock(mResumeCompositionMonitor);
+
+ CancelableTask *resumeTask =
+ NewRunnableMethod(this, &CompositorParent::ResumeComposition);
+ MOZ_ASSERT(CompositorLoop());
+ CompositorLoop()->PostTask(FROM_HERE, resumeTask);
+
+ // Wait until the resume has actually been processed by the compositor thread
+ lock.Wait();
+
+ return !mPaused;
+}
+
bool
CompositorParent::ScheduleResumeOnCompositorThread(int width, int height)
{
diff --git a/gfx/layers/ipc/CompositorParent.h b/gfx/layers/ipc/CompositorParent.h
index 66e5d5a60ab..e066ec29e7b 100644
--- a/gfx/layers/ipc/CompositorParent.h
+++ b/gfx/layers/ipc/CompositorParent.h
@@ -226,6 +226,7 @@ public:
* Returns true if a surface was obtained and the resume succeeded; false
* otherwise.
*/
+ bool ScheduleResumeOnCompositorThread();
bool ScheduleResumeOnCompositorThread(int width, int height);
virtual void ScheduleComposition();
diff --git a/gfx/layers/opengl/CompositorOGL.h b/gfx/layers/opengl/CompositorOGL.h
index ff82fa5956c..94f7205ded7 100644
--- a/gfx/layers/opengl/CompositorOGL.h
+++ b/gfx/layers/opengl/CompositorOGL.h
@@ -304,6 +304,19 @@ public:
const gfx::Matrix4x4& GetProjMatrix() const {
return mProjMatrix;
}
+
+ void SetProjMatrix(const gfx::Matrix4x4& aProjMatrix) {
+ mProjMatrix = aProjMatrix;
+ }
+
+ const gfx::IntSize GetDestinationSurfaceSize() const {
+ return gfx::IntSize (mSurfaceSize.width, mSurfaceSize.height);
+ }
+
+ const ScreenPoint& GetScreenRenderOffset() const {
+ return mRenderOffset;
+ }
+
private:
virtual gfx::IntSize GetWidgetSize() const override
{
diff --git a/js/xpconnect/src/Sandbox.cpp b/js/xpconnect/src/Sandbox.cpp
index 8ee810ed841..229e5742e92 100644
--- a/js/xpconnect/src/Sandbox.cpp
+++ b/js/xpconnect/src/Sandbox.cpp
@@ -1507,7 +1507,7 @@ xpc::EvalInSandbox(JSContext* cx, HandleObject sandboxArg, const nsAString& sour
NS_ENSURE_TRUE(prin, NS_ERROR_FAILURE);
nsAutoCString filenameBuf;
- if (!filename.IsVoid()) {
+ if (!filename.IsVoid() && filename.Length() != 0) {
filenameBuf.Assign(filename);
} else {
// Default to the spec of the principal.
diff --git a/js/xpconnect/tests/unit/test_sandbox_name.js b/js/xpconnect/tests/unit/test_sandbox_name.js
new file mode 100644
index 00000000000..44e6bbcd40d
--- /dev/null
+++ b/js/xpconnect/tests/unit/test_sandbox_name.js
@@ -0,0 +1,28 @@
+"use strict";
+
+const { utils: Cu, interfaces: Ci, classes: Cc } = Components;
+
+/**
+ * Test that the name of a sandbox contains the name of all principals.
+ */
+function test_sandbox_name() {
+ let names = [
+ "http://example.com/?" + Math.random(),
+ "http://example.org/?" + Math.random()
+ ];
+ let sandbox = Cu.Sandbox(names);
+ let fileName = Cu.evalInSandbox(
+ "(new Error()).fileName",
+ sandbox,
+ "latest" /*js version*/,
+ ""/*file name*/
+ );
+
+ for (let name of names) {
+ Assert.ok(fileName.indexOf(name) != -1, `Name ${name} appears in ${fileName}`);
+ }
+};
+
+function run_test() {
+ test_sandbox_name();
+}
diff --git a/js/xpconnect/tests/unit/xpcshell.ini b/js/xpconnect/tests/unit/xpcshell.ini
index b3a4a78ee3e..5c446da9f8d 100644
--- a/js/xpconnect/tests/unit/xpcshell.ini
+++ b/js/xpconnect/tests/unit/xpcshell.ini
@@ -99,6 +99,7 @@ skip-if = os == "android" # native test components aren't available on Android
[test_sandbox_atob.js]
[test_isProxy.js]
[test_getObjectPrincipal.js]
+[test_sandbox_name.js]
[test_watchdog_enable.js]
head = head_watchdog.js
[test_watchdog_disable.js]
diff --git a/mobile/android/base/BrowserApp.java b/mobile/android/base/BrowserApp.java
index 7ade38f9f9c..cd524706543 100644
--- a/mobile/android/base/BrowserApp.java
+++ b/mobile/android/base/BrowserApp.java
@@ -779,6 +779,7 @@ public class BrowserApp extends GeckoApp
"Menu:Add",
"Menu:Remove",
"Reader:Share",
+ "Sanitize:ClearHistory",
"Settings:Show",
"Telemetry:Gather",
"Updater:Launch");
@@ -1324,6 +1325,7 @@ public class BrowserApp extends GeckoApp
"Menu:Add",
"Menu:Remove",
"Reader:Share",
+ "Sanitize:ClearHistory",
"Settings:Show",
"Telemetry:Gather",
"Updater:Launch");
@@ -1360,6 +1362,16 @@ public class BrowserApp extends GeckoApp
}
}
+ private void handleClearHistory(final boolean clearSearchHistory) {
+ final BrowserDB db = getProfile().getDB();
+ ThreadUtils.postToBackgroundThread(new Runnable() {
+ @Override
+ public void run() {
+ db.clearHistory(getContentResolver(), clearSearchHistory);
+ }
+ });
+ }
+
private void shareCurrentUrl() {
Tab tab = Tabs.getInstance().getSelectedTab();
if (tab == null) {
@@ -1636,7 +1648,9 @@ public class BrowserApp extends GeckoApp
final String title = message.getString("title");
final String url = message.getString("url");
GeckoAppShell.openUriExternal(url, "text/plain", "", "", Intent.ACTION_SEND, title);
-
+ } else if ("Sanitize:ClearHistory".equals(event)) {
+ handleClearHistory(message.optBoolean("clearSearchHistory", false));
+ callback.sendSuccess(true);
} else if ("Settings:Show".equals(event)) {
final String resource =
message.optString(GeckoPreferences.INTENT_EXTRA_RESOURCES, null);
diff --git a/mobile/android/base/GeckoApp.java b/mobile/android/base/GeckoApp.java
index d756576d5b0..82157868b95 100644
--- a/mobile/android/base/GeckoApp.java
+++ b/mobile/android/base/GeckoApp.java
@@ -523,16 +523,6 @@ public abstract class GeckoApp
outState.putString(SAVED_STATE_PRIVATE_SESSION, mPrivateBrowsingSession);
}
- void handleClearHistory(final boolean clearSearchHistory) {
- final BrowserDB db = getProfile().getDB();
- ThreadUtils.postToBackgroundThread(new Runnable() {
- @Override
- public void run() {
- db.clearHistory(getContentResolver(), clearSearchHistory);
- }
- });
- }
-
public void addTab() { }
public void addPrivateTab() { }
@@ -625,10 +615,6 @@ public abstract class GeckoApp
} else if ("PrivateBrowsing:Data".equals(event)) {
mPrivateBrowsingSession = message.optString("session", null);
- } else if ("Sanitize:ClearHistory".equals(event)) {
- handleClearHistory(message.optBoolean("clearSearchHistory", false));
- callback.sendSuccess(true);
-
} else if ("Session:StatePurged".equals(event)) {
onStatePurged();
@@ -1547,7 +1533,6 @@ public abstract class GeckoApp
"Locale:Set",
"Permissions:Data",
"PrivateBrowsing:Data",
- "Sanitize:ClearHistory",
"Session:StatePurged",
"Share:Text",
"SystemUI:Visibility",
@@ -2039,7 +2024,6 @@ public abstract class GeckoApp
"Locale:Set",
"Permissions:Data",
"PrivateBrowsing:Data",
- "Sanitize:ClearHistory",
"Session:StatePurged",
"Share:Text",
"SystemUI:Visibility",
diff --git a/mobile/android/base/GeckoAppShell.java b/mobile/android/base/GeckoAppShell.java
index 5a9916bddf4..4b5c675ae97 100644
--- a/mobile/android/base/GeckoAppShell.java
+++ b/mobile/android/base/GeckoAppShell.java
@@ -294,6 +294,9 @@ public class GeckoAppShell
public static native SurfaceBits getSurfaceBits(Surface surface);
+ public static native void addPresentationSurface(Surface surface);
+ public static native void removePresentationSurface(Surface surface);
+
public static native void onFullScreenPluginHidden(View view);
public static class CreateShortcutFaviconLoadedListener implements OnFaviconLoadedListener {
diff --git a/mobile/android/base/MediaPlayerManager.java b/mobile/android/base/MediaPlayerManager.java
index 68f943b7aab..91ba5fc6147 100644
--- a/mobile/android/base/MediaPlayerManager.java
+++ b/mobile/android/base/MediaPlayerManager.java
@@ -5,6 +5,9 @@
package org.mozilla.gecko;
+import android.app.Presentation;
+import android.content.Context;
+import android.os.Build;
import android.os.Bundle;
import android.support.v4.app.Fragment;
import android.support.v7.media.MediaControlIntent;
@@ -12,6 +15,13 @@ import android.support.v7.media.MediaRouteSelector;
import android.support.v7.media.MediaRouter;
import android.support.v7.media.MediaRouter.RouteInfo;
import android.util.Log;
+import android.view.Display;
+import android.view.Surface;
+import android.view.SurfaceHolder;
+import android.view.SurfaceView;
+import android.view.ViewGroup;
+import android.view.ViewGroup.LayoutParams;
+import android.view.WindowManager;
import com.google.android.gms.cast.CastMediaControlIntent;
@@ -61,6 +71,7 @@ public class MediaPlayerManager extends Fragment implements NativeEventListener
private MediaRouter mediaRouter = null;
private final Map displays = new HashMap();
+ private GeckoPresentation presentation = null;
@Override
public void onCreate(Bundle savedInstanceState) {
@@ -135,19 +146,23 @@ public class MediaPlayerManager extends Fragment implements NativeEventListener
displays.remove(route.getId());
GeckoAppShell.sendEventToGecko(GeckoEvent.createBroadcastEvent(
"MediaPlayer:Removed", route.getId()));
+ updatePresentation();
}
@SuppressWarnings("unused")
public void onRouteSelected(MediaRouter router, int type, MediaRouter.RouteInfo route) {
+ updatePresentation();
}
// These methods aren't used by the support version Media Router
@SuppressWarnings("unused")
public void onRouteUnselected(MediaRouter router, int type, RouteInfo route) {
+ updatePresentation();
}
@Override
public void onRoutePresentationDisplayChanged(MediaRouter router, RouteInfo route) {
+ updatePresentation();
}
@Override
@@ -159,6 +174,7 @@ public class MediaPlayerManager extends Fragment implements NativeEventListener
debug("onRouteAdded: route=" + route);
final GeckoMediaPlayer display = getMediaPlayerForRoute(route);
saveAndNotifyOfDisplay("MediaPlayer:Added", route, display);
+ updatePresentation();
}
@Override
@@ -166,6 +182,7 @@ public class MediaPlayerManager extends Fragment implements NativeEventListener
debug("onRouteChanged: route=" + route);
final GeckoMediaPlayer display = displays.get(route.getId());
saveAndNotifyOfDisplay("MediaPlayer:Changed", route, display);
+ updatePresentation();
}
private void saveAndNotifyOfDisplay(final String eventName,
@@ -221,4 +238,86 @@ public class MediaPlayerManager extends Fragment implements NativeEventListener
.build();
mediaRouter.addCallback(selectorBuilder, callback, MediaRouter.CALLBACK_FLAG_REQUEST_DISCOVERY);
}
+
+ @Override
+ public void onStop() {
+ super.onStop();
+ if (presentation != null) {
+ presentation.dismiss();
+ presentation = null;
+ }
+ }
+
+ private void updatePresentation() {
+ if (Build.VERSION.SDK_INT < Build.VERSION_CODES.JELLY_BEAN_MR1) {
+ return;
+ }
+
+ if (mediaRouter == null) {
+ return;
+ }
+
+ MediaRouter.RouteInfo route = mediaRouter.getSelectedRoute();
+ Display display = route != null ? route.getPresentationDisplay() : null;
+
+ if (display != null) {
+ if ((presentation != null) && (presentation.getDisplay() != display)) {
+ presentation.dismiss();
+ presentation = null;
+ }
+
+ if (presentation == null) {
+ presentation = new GeckoPresentation(getActivity(), display);
+
+ try {
+ presentation.show();
+ } catch (WindowManager.InvalidDisplayException ex) {
+ Log.w(LOGTAG, "Couldn't show presentation! Display was removed in "
+ + "the meantime.", ex);
+ presentation = null;
+ }
+ }
+ } else if (presentation != null) {
+ presentation.dismiss();
+ presentation = null;
+ }
+ }
+
+ private static class SurfaceListener implements SurfaceHolder.Callback {
+ @Override
+ public void surfaceChanged(SurfaceHolder holder, int format, int width,
+ int height) {
+ // Surface changed so force a composite
+ GeckoAppShell.scheduleComposite();
+ }
+
+ @Override
+ public void surfaceCreated(SurfaceHolder holder) {
+ GeckoAppShell.addPresentationSurface(holder.getSurface());
+ GeckoAppShell.scheduleComposite();
+ }
+
+ @Override
+ public void surfaceDestroyed(SurfaceHolder holder) {
+ GeckoAppShell.removePresentationSurface(holder.getSurface());
+ }
+ }
+
+ private final static class GeckoPresentation extends Presentation {
+ private SurfaceView mView;
+ public GeckoPresentation(Context context, Display display) {
+ super(context, display);
+ }
+
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+
+ mView = new SurfaceView(getContext());
+ setContentView(mView, new ViewGroup.LayoutParams(
+ ViewGroup.LayoutParams.MATCH_PARENT,
+ ViewGroup.LayoutParams.MATCH_PARENT));
+ mView.getHolder().addCallback(new SurfaceListener());
+ }
+ }
}
diff --git a/mobile/android/base/TextSelection.java b/mobile/android/base/TextSelection.java
index 46fe172415e..d7dcfb2f53c 100644
--- a/mobile/android/base/TextSelection.java
+++ b/mobile/android/base/TextSelection.java
@@ -4,6 +4,7 @@
package org.mozilla.gecko;
+import android.content.res.Resources;
import org.mozilla.gecko.gfx.BitmapUtils;
import org.mozilla.gecko.gfx.BitmapUtils.BitmapLoader;
import org.mozilla.gecko.gfx.Layer;
@@ -16,6 +17,7 @@ import org.mozilla.gecko.util.FloatUtils;
import org.mozilla.gecko.util.GeckoEventListener;
import org.mozilla.gecko.util.ThreadUtils;
import org.mozilla.gecko.ActionModeCompat.Callback;
+import org.mozilla.gecko.AppConstants.Versions;
import android.content.Context;
import android.app.Activity;
@@ -279,11 +281,23 @@ class TextSelection extends Layer implements GeckoEventListener {
final int actionEnum = obj.optBoolean("showAsAction") ? GeckoMenuItem.SHOW_AS_ACTION_ALWAYS : GeckoMenuItem.SHOW_AS_ACTION_NEVER;
menuitem.setShowAsAction(actionEnum, R.attr.menuItemActionModeStyle);
- BitmapUtils.getDrawable(anchorHandle.getContext(), obj.optString("icon"), new BitmapLoader() {
+ final String iconString = obj.optString("icon");
+ BitmapUtils.getDrawable(anchorHandle.getContext(), iconString, new BitmapLoader() {
@Override
public void onBitmapFound(Drawable d) {
if (d != null) {
menuitem.setIcon(d);
+
+ // Dynamically add padding to align the share icon on GB devices.
+ // To be removed in bug 1122752.
+ if (Versions.preHC && "drawable://ic_menu_share".equals(iconString)) {
+ final View view = menuitem.getActionView();
+
+ final Resources res = view.getContext().getResources();
+ final int padding = res.getDimensionPixelSize(R.dimen.ab_share_padding);
+
+ view.setPadding(padding, padding, padding, padding);
+ }
}
}
});
diff --git a/mobile/android/base/resources/values/dimens.xml b/mobile/android/base/resources/values/dimens.xml
index fcacc0ccc1e..62690a2002e 100644
--- a/mobile/android/base/resources/values/dimens.xml
+++ b/mobile/android/base/resources/values/dimens.xml
@@ -213,6 +213,10 @@
10dip
2dip
+
+ 12dp
+
- 0.571
diff --git a/mobile/android/chrome/content/Reader.js b/mobile/android/chrome/content/Reader.js
index afc96e5893d..9792386a136 100644
--- a/mobile/android/chrome/content/Reader.js
+++ b/mobile/android/chrome/content/Reader.js
@@ -5,8 +5,6 @@
"use strict";
-XPCOMUtils.defineLazyModuleGetter(this, "ReaderMode", "resource://gre/modules/ReaderMode.jsm");
-
let Reader = {
// These values should match those defined in BrowserContract.java.
STATUS_UNFETCHED: 0,
diff --git a/mobile/android/chrome/content/browser.js b/mobile/android/chrome/content/browser.js
index 5c69e8ea9ee..ff0a2f98e44 100644
--- a/mobile/android/chrome/content/browser.js
+++ b/mobile/android/chrome/content/browser.js
@@ -113,6 +113,8 @@ XPCOMUtils.defineLazyModuleGetter(this, "Notifications",
XPCOMUtils.defineLazyModuleGetter(this, "GMPInstallManager",
"resource://gre/modules/GMPInstallManager.jsm");
+XPCOMUtils.defineLazyModuleGetter(this, "ReaderMode", "resource://gre/modules/ReaderMode.jsm");
+
let lazilyLoadedBrowserScripts = [
["SelectHelper", "chrome://browser/content/SelectHelper.js"],
["InputWidgetHelper", "chrome://browser/content/InputWidgetHelper.js"],
@@ -4562,16 +4564,7 @@ Tab.prototype = {
},
_stripAboutReaderURL: function (url) {
- if (!url.startsWith("about:reader")) {
- return url;
- }
-
- // From ReaderParent._getOriginalUrl (browser/modules/ReaderParent.jsm).
- let searchParams = new URLSearchParams(url.substring("about:reader?".length));
- if (!searchParams.has("url")) {
- return url;
- }
- return decodeURIComponent(searchParams.get("url"));
+ return ReaderMode.getOriginalUrl(url) || url;
},
// Properties used to cache security state used to update the UI
diff --git a/mozglue/android/jni-stubs.inc b/mozglue/android/jni-stubs.inc
index 92fb10fa904..6d2726366b6 100644
--- a/mozglue/android/jni-stubs.inc
+++ b/mozglue/android/jni-stubs.inc
@@ -305,6 +305,44 @@ Java_org_mozilla_gecko_GeckoAppShell_getSurfaceBits(JNIEnv * arg0, jclass arg1,
#ifdef JNI_STUBS
+typedef void (*Java_org_mozilla_gecko_GeckoAppShell_addPresentationSurface_t)(JNIEnv *, jclass, jobject);
+static Java_org_mozilla_gecko_GeckoAppShell_addPresentationSurface_t f_Java_org_mozilla_gecko_GeckoAppShell_addPresentationSurface;
+extern "C" NS_EXPORT void JNICALL
+Java_org_mozilla_gecko_GeckoAppShell_addPresentationSurface(JNIEnv * arg0, jclass arg1, jobject arg2) {
+ if (!f_Java_org_mozilla_gecko_GeckoAppShell_addPresentationSurface) {
+ arg0->ThrowNew(arg0->FindClass("java/lang/UnsupportedOperationException"),
+ "JNI Function called before it was loaded");
+ return ;
+ }
+ f_Java_org_mozilla_gecko_GeckoAppShell_addPresentationSurface(arg0, arg1, arg2);
+}
+#endif
+
+#ifdef JNI_BINDINGS
+ xul_dlsym("Java_org_mozilla_gecko_GeckoAppShell_addPresentationSurface", &f_Java_org_mozilla_gecko_GeckoAppShell_addPresentationSurface);
+#endif
+
+#ifdef JNI_STUBS
+
+typedef void (*Java_org_mozilla_gecko_GeckoAppShell_removePresentationSurface_t)(JNIEnv *, jclass, jobject);
+static Java_org_mozilla_gecko_GeckoAppShell_removePresentationSurface_t f_Java_org_mozilla_gecko_GeckoAppShell_removePresentationSurface;
+extern "C" NS_EXPORT void JNICALL
+Java_org_mozilla_gecko_GeckoAppShell_removePresentationSurface(JNIEnv * arg0, jclass arg1, jobject arg2) {
+ if (!f_Java_org_mozilla_gecko_GeckoAppShell_removePresentationSurface) {
+ arg0->ThrowNew(arg0->FindClass("java/lang/UnsupportedOperationException"),
+ "JNI Function called before it was loaded");
+ return ;
+ }
+ f_Java_org_mozilla_gecko_GeckoAppShell_removePresentationSurface(arg0, arg1, arg2);
+}
+#endif
+
+#ifdef JNI_BINDINGS
+ xul_dlsym("Java_org_mozilla_gecko_GeckoAppShell_removePresentationSurface", &f_Java_org_mozilla_gecko_GeckoAppShell_removePresentationSurface);
+#endif
+
+#ifdef JNI_STUBS
+
typedef void (*Java_org_mozilla_gecko_GeckoAppShell_onFullScreenPluginHidden_t)(JNIEnv *, jclass, jobject);
static Java_org_mozilla_gecko_GeckoAppShell_onFullScreenPluginHidden_t f_Java_org_mozilla_gecko_GeckoAppShell_onFullScreenPluginHidden;
extern "C" NS_EXPORT void JNICALL
diff --git a/testing/docker/builder/Dockerfile b/testing/docker/builder/Dockerfile
index 77c9ce6f9b2..56bd625e91c 100644
--- a/testing/docker/builder/Dockerfile
+++ b/testing/docker/builder/Dockerfile
@@ -21,7 +21,7 @@ RUN git config --global user.email "mozilla@example.com" && \
git config --global user.name "mozilla"
# VCS Tools
-RUN npm install -g taskcluster-vcs@2.3.4
+RUN npm install -g taskcluster-vcs@2.3.5
# TODO enable worker
# TODO volume mount permissions will be an issue
diff --git a/testing/docker/phone-builder/Dockerfile b/testing/docker/phone-builder/Dockerfile
index bff90e9ec1e..e82cbbea9c6 100644
--- a/testing/docker/phone-builder/Dockerfile
+++ b/testing/docker/phone-builder/Dockerfile
@@ -4,9 +4,10 @@ MAINTAINER Wander Lairson Costa
# Add utilities and configuration
ADD bin /home/worker/bin
ADD config /home/worker/.aws/config
-ADD system-setup.sh /tmp/system-setup.sh
-RUN /tmp/system-setup.sh
+RUN yum install -y bc lzop
+RUN pip install awscli
+RUN npm install -g bower gulp apm grunt-cli
# Set a default command useful for debugging
ENTRYPOINT ["validate_task.py"]
diff --git a/testing/docker/phone-builder/VERSION b/testing/docker/phone-builder/VERSION
index 8cbf02c396d..43b29618309 100644
--- a/testing/docker/phone-builder/VERSION
+++ b/testing/docker/phone-builder/VERSION
@@ -1 +1 @@
-0.0.12
+0.0.13
diff --git a/testing/docker/phone-builder/system-setup.sh b/testing/docker/phone-builder/system-setup.sh
deleted file mode 100755
index e21f16d1627..00000000000
--- a/testing/docker/phone-builder/system-setup.sh
+++ /dev/null
@@ -1,9 +0,0 @@
-#!/bin/sh
-
-pip install awscli
-
-# Necessary for dolhin kernel building
-yum install -y bc
-
-# Remove ourselves
-rm -f $0
diff --git a/testing/taskcluster/scripts/phone-builder/build-lightsaber-nightly.sh b/testing/taskcluster/scripts/phone-builder/build-lightsaber-nightly.sh
new file mode 100755
index 00000000000..57e25a99b9d
--- /dev/null
+++ b/testing/taskcluster/scripts/phone-builder/build-lightsaber-nightly.sh
@@ -0,0 +1,49 @@
+#! /bin/bash -vex
+
+. pre-build.sh
+
+if [ 0$B2G_DEBUG -ne 0 ]; then
+ DEBUG_SUFFIX=-debug
+fi
+
+if [ $TARGET == "aries" -o $TARGET == "shinano" ]; then
+ # caching objects might be dangerous for some devices (aka aries)
+ rm -rf $WORKSPACE/B2G/objdir*
+ rm -rf $WORKSPACE/B2G/out
+fi
+
+aws s3 cp s3://b2g-nightly-credentials/balrog_credentials .
+mar_file=b2g-${TARGET%%-*}-gecko-update.mar
+
+./mozharness/scripts/b2g_lightsaber.py \
+ --config b2g/taskcluster-lightsaber-nightly.py \
+ --config balrog/staging.py \
+ "$debug_flag" \
+ --disable-mock \
+ --variant=$VARIANT \
+ --work-dir=$WORKSPACE/B2G \
+ --gaia-languages-file locales/languages_all.json \
+ --log-level=debug \
+ --target=$TARGET \
+ --b2g-config-dir=$TARGET \
+ --checkout-revision=$GECKO_HEAD_REV \
+ --base-repo=$GECKO_BASE_REPOSITORY \
+ --repo=$GECKO_HEAD_REPOSITORY \
+ --platform $TARGET \
+ --complete-mar-url https://queue.taskcluster.net/v1/task/$TASK_ID/runs/$RUN_ID/artifacts/public/build/$mar_file \
+
+# Don't cache backups
+rm -rf $WORKSPACE/B2G/backup-*
+rm -f balrog_credentials
+
+mkdir -p $HOME/artifacts
+mkdir -p $HOME/artifacts-public
+
+mv $WORKSPACE/B2G/upload-public/$mar_file $HOME/artifacts-public/
+mv $WORKSPACE/B2G/upload/sources.xml $HOME/artifacts/sources.xml
+#mv $WORKSPACE/B2G/upload/b2g-*.crashreporter-symbols.zip $HOME/artifacts/b2g-crashreporter-symbols.zip
+mv $WORKSPACE/B2G/upload/b2g-*.android-arm.tar.gz $HOME/artifacts/b2g-android-arm.tar.gz
+mv $WORKSPACE/B2G/upload/${TARGET}.zip $HOME/artifacts/${TARGET}.zip
+mv $WORKSPACE/B2G/upload/gaia.zip $HOME/artifacts/gaia.zip
+ccache -s
+
diff --git a/testing/taskcluster/scripts/phone-builder/build-phone-nightly.sh b/testing/taskcluster/scripts/phone-builder/build-phone-nightly.sh
index 8a3af888465..b9ececab7dd 100755
--- a/testing/taskcluster/scripts/phone-builder/build-phone-nightly.sh
+++ b/testing/taskcluster/scripts/phone-builder/build-phone-nightly.sh
@@ -11,7 +11,6 @@ if [ ! -d $HOME/.ssh ]; then
fi
aws s3 cp s3://b2g-nightly-credentials/balrog_credentials .
-aws s3 cp s3://b2g-nightly-credentials/b2g-rsa $HOME/.ssh/
./mozharness/scripts/b2g_build.py \
--config b2g/taskcluster-phone-nightly.py \
@@ -28,12 +27,11 @@ aws s3 cp s3://b2g-nightly-credentials/b2g-rsa $HOME/.ssh/
--base-repo=$GECKO_BASE_REPOSITORY \
--repo=$GECKO_HEAD_REPOSITORY \
--platform $TARGET \
- --complete-mar-url https://queue.taskcluster.net/v1/task/$TASK_ID/runs/0/artifacts/public/build/b2g-${TARGET%%-*}-gecko-update.mar \
+ --complete-mar-url https://queue.taskcluster.net/v1/task/$TASK_ID/runs/$RUN_ID/artifacts/public/build/b2g-${TARGET%%-*}-gecko-update.mar \
# Don't cache backups
rm -rf $WORKSPACE/B2G/backup-*
rm -f balrog_credentials
-rm -f $HOME/.ssh/b2g-rsa
mkdir -p $HOME/artifacts
mkdir -p $HOME/artifacts-public
diff --git a/testing/taskcluster/scripts/phone-builder/pre-build.sh b/testing/taskcluster/scripts/phone-builder/pre-build.sh
index cce46cd77d4..8699953a649 100755
--- a/testing/taskcluster/scripts/phone-builder/pre-build.sh
+++ b/testing/taskcluster/scripts/phone-builder/pre-build.sh
@@ -19,14 +19,7 @@ test $VARIANT
. ../builder/setup-ccache.sh
-# First check if the mozharness directory is available. This is intended to be
-# used locally in development to test mozharness changes:
-#
-# $ docker -v your_mozharness:/home/worker/mozharness ...
-#
-if [ ! -d mozharness ]; then
- tc-vcs checkout mozharness $MOZHARNESS_REPOSITORY $MOZHARNESS_REPOSITORY $MOZHARNESS_REV $MOZHARNESS_REF
-fi
+tc-vcs checkout mozharness $MOZHARNESS_REPOSITORY $MOZHARNESS_REPOSITORY $MOZHARNESS_REV $MOZHARNESS_REF
# Figure out where the remote manifest is so we can use caches for it.
MANIFEST=$(repository-url.py $GECKO_HEAD_REPOSITORY $GECKO_HEAD_REV b2g/config/$TARGET/sources.xml)
diff --git a/testing/taskcluster/tasks/branches/base_job_flags.yml b/testing/taskcluster/tasks/branches/base_job_flags.yml
index adc5506de85..91b11673b85 100644
--- a/testing/taskcluster/tasks/branches/base_job_flags.yml
+++ b/testing/taskcluster/tasks/branches/base_job_flags.yml
@@ -22,6 +22,7 @@ flags:
- dolphin-eng
- dolphin-512
- dolphin-512-eng
+ - aries-nightly
tests:
- cppunit
diff --git a/testing/taskcluster/tasks/branches/cypress/job_flags.yml b/testing/taskcluster/tasks/branches/cypress/job_flags.yml
index 30d08855f2a..1820ee53386 100644
--- a/testing/taskcluster/tasks/branches/cypress/job_flags.yml
+++ b/testing/taskcluster/tasks/branches/cypress/job_flags.yml
@@ -18,6 +18,12 @@ builds:
types:
opt:
task: tasks/builds/b2g_flame_kk_eng.yml
+ aries-nightly:
+ platforms:
+ - b2g
+ types:
+ opt:
+ task: tasks/builds/b2g_aries_lightsaber_nightly.yml
tests:
gaia-build:
diff --git a/testing/taskcluster/tasks/builds/b2g_aries_lightsaber_nightly.yml b/testing/taskcluster/tasks/builds/b2g_aries_lightsaber_nightly.yml
new file mode 100644
index 00000000000..345b9a097cb
--- /dev/null
+++ b/testing/taskcluster/tasks/builds/b2g_aries_lightsaber_nightly.yml
@@ -0,0 +1,35 @@
+$inherits:
+ from: 'tasks/builds/b2g_phone_base.yml'
+ variables:
+ build_name: 'aries'
+ build_type: 'nightly'
+task:
+ workerType: flame-kk
+ scopes:
+ - 'docker-worker:cache:build-aries-lightsaber-nightly'
+ metadata:
+ name: '[TC] B2G Aries Nightly'
+
+ payload:
+ cache:
+ build-aries-lightsaber-nightly: /home/worker/workspace
+ env:
+ TARGET: 'aries'
+ DEBUG: 0
+ command:
+ - >
+ checkout-gecko workspace &&
+ cd ./workspace/gecko/testing/taskcluster/scripts/phone-builder &&
+ buildbot_step 'Build' ./build-lightsaber-nightly.sh $HOME/workspace
+
+ extra:
+ treeherder:
+ symbol: B
+ groupSymbol: Aries
+ groupName: Aries Device Image
+ machine:
+ platform: b2g-device-image
+ locations:
+ img: 'private/build/aries.zip'
+ mar: 'public/build/b2g-aries-gecko-update.mar'
+
diff --git a/toolkit/components/build/nsToolkitCompsCID.h b/toolkit/components/build/nsToolkitCompsCID.h
index b911c08b9c1..34742c79165 100644
--- a/toolkit/components/build/nsToolkitCompsCID.h
+++ b/toolkit/components/build/nsToolkitCompsCID.h
@@ -2,12 +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/. */
-#if defined(MOZ_UPDATER)
-# if !defined(MOZ_WIDGET_ANDROID)
-# define USE_MOZ_UPDATER
-# endif
-#endif
-
#define NS_ALERTSERVICE_CONTRACTID \
"@mozilla.org/alerts-service;1"
@@ -90,7 +84,7 @@
#define NS_APPSTARTUP_CONTRACTID \
"@mozilla.org/toolkit/app-startup;1"
-#if defined(USE_MOZ_UPDATER)
+#if defined(MOZ_UPDATER) && !defined(MOZ_WIDGET_ANDROID)
#define NS_UPDATEPROCESSOR_CONTRACTID \
"@mozilla.org/updates/update-processor;1"
#endif
@@ -173,7 +167,7 @@
#define NS_FAVICONSERVICE_CID \
{ 0x984e3259, 0x9266, 0x49cf, { 0xb6, 0x05, 0x60, 0xb0, 0x22, 0xa0, 0x07, 0x56 } }
-#if defined(USE_MOZ_UPDATER)
+#if defined(MOZ_UPDATER) && !defined(MOZ_WIDGET_ANDROID)
#define NS_UPDATEPROCESSOR_CID \
{ 0xf3dcf644, 0x79e8, 0x4f59, { 0xa1, 0xbb, 0x87, 0x84, 0x54, 0x48, 0x8e, 0xf9 } }
#endif
diff --git a/toolkit/components/build/nsToolkitCompsModule.cpp b/toolkit/components/build/nsToolkitCompsModule.cpp
index c6ecbb81619..2b27a11c92a 100644
--- a/toolkit/components/build/nsToolkitCompsModule.cpp
+++ b/toolkit/components/build/nsToolkitCompsModule.cpp
@@ -7,7 +7,7 @@
#include "nsUserInfo.h"
#include "nsToolkitCompsCID.h"
#include "nsFindService.h"
-#if defined(USE_MOZ_UPDATER)
+#if defined(MOZ_UPDATER) && !defined(MOZ_WIDGET_ANDROID)
#include "nsUpdateDriver.h"
#endif
@@ -109,7 +109,7 @@ nsUrlClassifierDBServiceConstructor(nsISupports *aOuter, REFNSIID aIID,
#endif
NS_GENERIC_FACTORY_CONSTRUCTOR(nsBrowserStatusFilter)
-#if defined(USE_MOZ_UPDATER)
+#if defined(MOZ_UPDATER) && !defined(MOZ_WIDGET_ANDROID)
NS_GENERIC_FACTORY_CONSTRUCTOR(nsUpdateProcessor)
#endif
NS_GENERIC_FACTORY_CONSTRUCTOR(FinalizationWitnessService)
@@ -141,7 +141,7 @@ NS_DEFINE_NAMED_CID(NS_URLCLASSIFIERSTREAMUPDATER_CID);
NS_DEFINE_NAMED_CID(NS_URLCLASSIFIERUTILS_CID);
#endif
NS_DEFINE_NAMED_CID(NS_BROWSERSTATUSFILTER_CID);
-#if defined(USE_MOZ_UPDATER)
+#if defined(MOZ_UPDATER) && !defined(MOZ_WIDGET_ANDROID)
NS_DEFINE_NAMED_CID(NS_UPDATEPROCESSOR_CID);
#endif
NS_DEFINE_NAMED_CID(FINALIZATIONWITNESSSERVICE_CID);
@@ -173,7 +173,7 @@ static const Module::CIDEntry kToolkitCIDs[] = {
{ &kNS_URLCLASSIFIERUTILS_CID, false, nullptr, nsUrlClassifierUtilsConstructor },
#endif
{ &kNS_BROWSERSTATUSFILTER_CID, false, nullptr, nsBrowserStatusFilterConstructor },
-#if defined(USE_MOZ_UPDATER)
+#if defined(MOZ_UPDATER) && !defined(MOZ_WIDGET_ANDROID)
{ &kNS_UPDATEPROCESSOR_CID, false, nullptr, nsUpdateProcessorConstructor },
#endif
{ &kFINALIZATIONWITNESSSERVICE_CID, false, nullptr, FinalizationWitnessServiceConstructor },
@@ -207,7 +207,7 @@ static const Module::ContractIDEntry kToolkitContracts[] = {
{ NS_URLCLASSIFIERUTILS_CONTRACTID, &kNS_URLCLASSIFIERUTILS_CID },
#endif
{ NS_BROWSERSTATUSFILTER_CONTRACTID, &kNS_BROWSERSTATUSFILTER_CID },
-#if defined(USE_MOZ_UPDATER)
+#if defined(MOZ_UPDATER) && !defined(MOZ_WIDGET_ANDROID)
{ NS_UPDATEPROCESSOR_CONTRACTID, &kNS_UPDATEPROCESSOR_CID },
#endif
{ FINALIZATIONWITNESSSERVICE_CONTRACTID, &kFINALIZATIONWITNESSSERVICE_CID },
diff --git a/toolkit/components/moz.build b/toolkit/components/moz.build
index 41694c5a006..9daf31898cc 100644
--- a/toolkit/components/moz.build
+++ b/toolkit/components/moz.build
@@ -48,6 +48,7 @@ DIRS += [
'statusfilter',
'telemetry',
'thumbnails',
+ 'timermanager',
'typeaheadfind',
'urlformatter',
'viewconfig',
diff --git a/toolkit/components/reader/AboutReader.jsm b/toolkit/components/reader/AboutReader.jsm
index 1c24db776b8..64fa223660b 100644
--- a/toolkit/components/reader/AboutReader.jsm
+++ b/toolkit/components/reader/AboutReader.jsm
@@ -8,6 +8,7 @@ let Ci = Components.interfaces, Cc = Components.classes, Cu = Components.utils;
this.EXPORTED_SYMBOLS = [ "AboutReader" ];
+Cu.import("resource://gre/modules/ReaderMode.jsm");
Cu.import("resource://gre/modules/Services.jsm");
Cu.import("resource://gre/modules/XPCOMUtils.jsm");
@@ -734,9 +735,8 @@ AboutReader.prototype = {
this._domainElement.href = article.url;
let articleUri = Services.io.newURI(article.url, null, null);
- this._domainElement.innerHTML = this._stripHost(articleUri.host);
-
- this._creditsElement.innerHTML = article.byline;
+ this._domainElement.textContent = this._stripHost(articleUri.host);
+ this._creditsElement.textContent = article.byline;
this._titleElement.textContent = article.title;
this._doc.title = article.title;
@@ -787,12 +787,7 @@ AboutReader.prototype = {
*/
_getOriginalUrl: function(win) {
let url = win ? win.location.href : this._win.location.href;
- let searchParams = new URLSearchParams(url.split("?")[1]);
- if (!searchParams.has("url")) {
- Cu.reportError("Error finding original URL for about:reader URL: " + url);
- return url;
- }
- return decodeURIComponent(searchParams.get("url"));
+ return ReaderMode.getOriginalUrl(url) || url;
},
_setupSegmentedButton: function Reader_setupSegmentedButton(id, options, initialValue, callback) {
diff --git a/toolkit/components/reader/ReaderMode.jsm b/toolkit/components/reader/ReaderMode.jsm
index b4cab82eea0..20e107670d8 100644
--- a/toolkit/components/reader/ReaderMode.jsm
+++ b/toolkit/components/reader/ReaderMode.jsm
@@ -67,6 +67,31 @@ this.ReaderMode = {
}
},
+ /**
+ * Returns original URL from an about:reader URL.
+ *
+ * @param url An about:reader URL.
+ * @return The original URL for the article, or null if we did not find
+ * a properly formatted about:reader URL.
+ */
+ getOriginalUrl: function(url) {
+ if (!url.startsWith("about:reader?")) {
+ return null;
+ }
+
+ let searchParams = new URLSearchParams(url.substring("about:reader?".length));
+ if (!searchParams.has("url")) {
+ return null;
+ }
+ let encodedURL = searchParams.get("url");
+ try {
+ return decodeURIComponent(encodedURL);
+ } catch (e) {
+ Cu.reportError("Error decoding original URL: " + e);
+ return encodedURL;
+ }
+ },
+
/**
* Decides whether or not a document is reader-able without parsing the whole thing.
*
diff --git a/toolkit/components/satchel/AutoCompleteE10S.jsm b/toolkit/components/satchel/AutoCompleteE10S.jsm
index 87bc198de3a..77d0a0a6e6a 100644
--- a/toolkit/components/satchel/AutoCompleteE10S.jsm
+++ b/toolkit/components/satchel/AutoCompleteE10S.jsm
@@ -84,11 +84,12 @@ this.AutoCompleteE10S = {
messageManager.addMessageListener("FormAutoComplete:ClosePopup", this);
},
- _initPopup: function(browserWindow, rect) {
+ _initPopup: function(browserWindow, rect, direction) {
this.browser = browserWindow.gBrowser.selectedBrowser;
this.popup = this.browser.autoCompletePopup;
this.popup.hidden = false;
this.popup.setAttribute("width", rect.width);
+ this.popup.style.direction = direction;
this.x = rect.left;
this.y = rect.top + rect.height;
@@ -137,8 +138,9 @@ this.AutoCompleteE10S = {
search: function(message) {
let browserWindow = message.target.ownerDocument.defaultView;
let rect = message.data;
+ let direction = message.data.direction;
- this._initPopup(browserWindow, rect);
+ this._initPopup(browserWindow, rect, direction);
let formAutoComplete = Cc["@mozilla.org/satchel/form-autocomplete;1"]
.getService(Ci.nsIFormAutoComplete);
diff --git a/toolkit/components/satchel/nsFormAutoComplete.js b/toolkit/components/satchel/nsFormAutoComplete.js
index 150965a63f2..4544c8e6419 100644
--- a/toolkit/components/satchel/nsFormAutoComplete.js
+++ b/toolkit/components/satchel/nsFormAutoComplete.js
@@ -372,9 +372,10 @@ FormAutoCompleteChild.prototype = {
this.stopAutoCompleteSearch();
}
- let rect = BrowserUtils.getElementBoundingScreenRect(aField);
-
let window = aField.ownerDocument.defaultView;
+
+ let rect = BrowserUtils.getElementBoundingScreenRect(aField);
+ let direction = window.getComputedStyle(aField).direction;
let topLevelDocshell = window.QueryInterface(Ci.nsIInterfaceRequestor)
.getInterface(Ci.nsIDocShell)
.sameTypeRootTreeItem
@@ -389,7 +390,8 @@ FormAutoCompleteChild.prototype = {
left: rect.left,
top: rect.top,
width: rect.width,
- height: rect.height
+ height: rect.height,
+ direction: direction,
});
let search = this._pendingSearch = {};
diff --git a/toolkit/components/timermanager/moz.build b/toolkit/components/timermanager/moz.build
new file mode 100644
index 00000000000..d9dfac4d29c
--- /dev/null
+++ b/toolkit/components/timermanager/moz.build
@@ -0,0 +1,21 @@
+# -*- Mode: python; c-basic-offset: 4; indent-tabs-mode: nil; tab-width: 40 -*-
+# vim: set filetype=python:
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+XPIDL_MODULE = 'update'
+
+XPCSHELL_TESTS_MANIFESTS += ['tests/unit/xpcshell.ini']
+
+XPIDL_SOURCES += [
+ 'nsIUpdateTimerManager.idl',
+]
+
+EXTRA_COMPONENTS += [
+ 'nsUpdateTimerManager.js',
+ 'nsUpdateTimerManager.manifest',
+]
+
+with Files('**'):
+ BUG_COMPONENT = ('Toolkit', 'Application Update')
diff --git a/toolkit/mozapps/update/nsIUpdateTimerManager.idl b/toolkit/components/timermanager/nsIUpdateTimerManager.idl
similarity index 100%
rename from toolkit/mozapps/update/nsIUpdateTimerManager.idl
rename to toolkit/components/timermanager/nsIUpdateTimerManager.idl
diff --git a/toolkit/mozapps/update/nsUpdateTimerManager.js b/toolkit/components/timermanager/nsUpdateTimerManager.js
similarity index 100%
rename from toolkit/mozapps/update/nsUpdateTimerManager.js
rename to toolkit/components/timermanager/nsUpdateTimerManager.js
diff --git a/toolkit/mozapps/update/nsUpdateTimerManager.manifest b/toolkit/components/timermanager/nsUpdateTimerManager.manifest
similarity index 100%
rename from toolkit/mozapps/update/nsUpdateTimerManager.manifest
rename to toolkit/components/timermanager/nsUpdateTimerManager.manifest
diff --git a/toolkit/mozapps/update/tests/unit_timermanager/consumerNotifications.js b/toolkit/components/timermanager/tests/unit/consumerNotifications.js
similarity index 100%
rename from toolkit/mozapps/update/tests/unit_timermanager/consumerNotifications.js
rename to toolkit/components/timermanager/tests/unit/consumerNotifications.js
diff --git a/toolkit/mozapps/update/tests/unit_timermanager/xpcshell.ini b/toolkit/components/timermanager/tests/unit/xpcshell.ini
similarity index 100%
rename from toolkit/mozapps/update/tests/unit_timermanager/xpcshell.ini
rename to toolkit/components/timermanager/tests/unit/xpcshell.ini
diff --git a/toolkit/modules/NewTabUtils.jsm b/toolkit/modules/NewTabUtils.jsm
index 9776fb31884..1ccba141eb9 100644
--- a/toolkit/modules/NewTabUtils.jsm
+++ b/toolkit/modules/NewTabUtils.jsm
@@ -471,11 +471,23 @@ let PinnedLinks = {
* Singleton that keeps track of all blocked links in the grid.
*/
let BlockedLinks = {
+ /**
+ * A list of objects that are observing blocked link changes.
+ */
+ _observers: [],
+
/**
* The cached list of blocked links.
*/
_links: null,
+ /**
+ * Registers an object that will be notified when the blocked links change.
+ */
+ addObserver: function (aObserver) {
+ this._observers.push(aObserver);
+ },
+
/**
* The list of blocked links.
*/
@@ -487,10 +499,11 @@ let BlockedLinks = {
},
/**
- * Blocks a given link.
+ * Blocks a given link. Adjusts siteMap accordingly, and notifies listeners.
* @param aLink The link to block.
*/
block: function BlockedLinks_block(aLink) {
+ this._callObservers("onLinkBlocked", aLink);
this.links[toHash(aLink.url)] = 1;
this.save();
@@ -499,13 +512,14 @@ let BlockedLinks = {
},
/**
- * Unblocks a given link.
+ * Unblocks a given link. Adjusts siteMap accordingly, and notifies listeners.
* @param aLink The link to unblock.
*/
unblock: function BlockedLinks_unblock(aLink) {
if (this.isBlocked(aLink)) {
delete this.links[toHash(aLink.url)];
this.save();
+ this._callObservers("onLinkUnblocked", aLink);
}
},
@@ -537,6 +551,18 @@ let BlockedLinks = {
*/
resetCache: function BlockedLinks_resetCache() {
this._links = null;
+ },
+
+ _callObservers(methodName, ...args) {
+ for (let obs of this._observers) {
+ if (typeof(obs[methodName]) == "function") {
+ try {
+ obs[methodName](...args);
+ } catch (err) {
+ Cu.reportError(err);
+ }
+ }
+ }
}
};
@@ -719,6 +745,8 @@ let Links = {
* A mapping from each provider to an object { sortedLinks, siteMap, linkMap }.
* sortedLinks is the cached, sorted array of links for the provider.
* siteMap is a mapping from base domains to URL count associated with the domain.
+ * The count does not include blocked URLs. siteMap is used to look up a
+ * user's top sites that can be targeted with a suggested tile.
* linkMap is a Map from link URLs to link objects.
*/
_providers: new Map(),
@@ -737,6 +765,18 @@ let Links = {
*/
_populateCallbacks: [],
+ /**
+ * A list of objects that are observing links updates.
+ */
+ _observers: [],
+
+ /**
+ * Registers an object that will be notified when links updates.
+ */
+ addObserver: function (aObserver) {
+ this._observers.push(aObserver);
+ },
+
/**
* Adds a link provider.
* @param aProvider The link provider.
@@ -861,11 +901,19 @@ let Links = {
},
_incrementSiteMap: function(map, link) {
+ if (NewTabUtils.blockedLinks.isBlocked(link)) {
+ // Don't count blocked URLs.
+ return;
+ }
let site = NewTabUtils.extractSite(link.url);
map.set(site, (map.get(site) || 0) + 1);
},
_decrementSiteMap: function(map, link) {
+ if (NewTabUtils.blockedLinks.isBlocked(link)) {
+ // Blocked URLs are not included in map.
+ return;
+ }
let site = NewTabUtils.extractSite(link.url);
let previousURLCount = map.get(site);
if (previousURLCount === 1) {
@@ -875,6 +923,37 @@ let Links = {
}
},
+ /**
+ * Update the siteMap cache based on the link given and whether we need
+ * to increment or decrement it. We do this by iterating over all stored providers
+ * to find which provider this link already exists in. For providers that
+ * have this link, we will adjust siteMap for them accordingly.
+ *
+ * @param aLink The link that will affect siteMap
+ * @param increment A boolean for whether to increment or decrement siteMap
+ */
+ _adjustSiteMapAndNotify: function(aLink, increment=true) {
+ for (let [provider, cache] of this._providers) {
+ // We only update siteMap if aLink is already stored in linkMap.
+ if (cache.linkMap.get(aLink.url)) {
+ if (increment) {
+ this._incrementSiteMap(cache.siteMap, aLink);
+ continue;
+ }
+ this._decrementSiteMap(cache.siteMap, aLink);
+ }
+ }
+ this._callObservers("onLinkChanged", aLink);
+ },
+
+ onLinkBlocked: function(aLink) {
+ this._adjustSiteMapAndNotify(aLink, false);
+ },
+
+ onLinkUnblocked: function(aLink) {
+ this._adjustSiteMapAndNotify(aLink);
+ },
+
populateProviderCache: function(provider, callback) {
if (!this._providers.has(provider)) {
throw new Error("Can only populate provider cache for existing provider.");
@@ -1095,6 +1174,18 @@ let Links = {
this.resetCache();
},
+ _callObservers(methodName, ...args) {
+ for (let obs of this._observers) {
+ if (typeof(obs[methodName]) == "function") {
+ try {
+ obs[methodName](this, ...args);
+ } catch (err) {
+ Cu.reportError(err);
+ }
+ }
+ }
+ },
+
/**
* Adds a sanitization observer and turns itself into a no-op after the first
* invokation.
@@ -1235,6 +1326,7 @@ this.NewTabUtils = {
if (this.initWithoutProviders()) {
PlacesProvider.init();
Links.addProvider(PlacesProvider);
+ BlockedLinks.addObserver(Links);
}
},
diff --git a/toolkit/moz.build b/toolkit/moz.build
index b0c87ae0d64..e7e4a3faebe 100644
--- a/toolkit/moz.build
+++ b/toolkit/moz.build
@@ -23,10 +23,17 @@ DIRS += [
'webapps',
]
-DIRS += ['mozapps/update']
+if CONFIG['MOZ_UPDATER'] and CONFIG['MOZ_WIDGET_TOOLKIT'] != 'android':
+ DIRS += ['mozapps/update']
if CONFIG['MOZ_MAINTENANCE_SERVICE']:
- DIRS += ['components/maintenanceservice']
+# Including mozapps/update/common-standalone allows the maintenance service
+# to be built so the maintenance service can be used for things other than
+# updating applications.
+ DIRS += [
+ 'mozapps/update/common-standalone',
+ 'components/maintenanceservice'
+ ]
DIRS += ['xre']
@@ -61,6 +68,3 @@ with Files('mozapps/plugins/*'):
with Files('mozapps/preferences/*'):
BUG_COMPONENT = ('Toolkit', 'Preferences')
-
-with Files('mozapps/update/*'):
- BUG_COMPONENT = ('Toolkit', 'Application Update')
diff --git a/toolkit/mozapps/update/common-standalone/moz.build b/toolkit/mozapps/update/common-standalone/moz.build
index dbc787b437b..5e66f579180 100644
--- a/toolkit/mozapps/update/common-standalone/moz.build
+++ b/toolkit/mozapps/update/common-standalone/moz.build
@@ -10,3 +10,5 @@ include('../common/sources.mozbuild')
if CONFIG['OS_ARCH'] == 'WINNT':
USE_STATIC_LIBS = True
+
+FAIL_ON_WARNINGS = True
diff --git a/toolkit/mozapps/update/common/moz.build b/toolkit/mozapps/update/common/moz.build
index 2e9b89d747b..044433696ef 100644
--- a/toolkit/mozapps/update/common/moz.build
+++ b/toolkit/mozapps/update/common/moz.build
@@ -25,3 +25,5 @@ srcdir = '.'
include('sources.mozbuild')
FINAL_LIBRARY = 'xul'
+
+FAIL_ON_WARNINGS = True
diff --git a/toolkit/mozapps/update/moz.build b/toolkit/mozapps/update/moz.build
index 0d2d9dadc2f..334547d75e9 100644
--- a/toolkit/mozapps/update/moz.build
+++ b/toolkit/mozapps/update/moz.build
@@ -4,47 +4,32 @@
# License, v. 2.0. If a copy of the MPL was not distributed with this
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
-if CONFIG['MOZ_WIDGET_TOOLKIT'] != 'android':
- if CONFIG['MOZ_UPDATER'] or CONFIG['MOZ_MAINTENANCE_SERVICE']:
- # If only the maintenance service is installed and not
- # the updater, then the maintenance service may still be
- # used for other things. We need to build update/common
- # which the maintenance service uses.
- DIRS += ['common']
- if CONFIG['OS_ARCH'] == 'WINNT':
- DIRS += ['common-standalone']
-
- if CONFIG['MOZ_UPDATER']:
- DIRS += ['updater']
-
XPIDL_MODULE = 'update'
-XPCSHELL_TESTS_MANIFESTS += ['tests/unit_timermanager/xpcshell.ini']
+DIRS += [
+ 'common',
+ 'updater',
+]
XPIDL_SOURCES += [
- 'nsIUpdateTimerManager.idl',
+ 'nsIUpdateService.idl',
]
+TEST_DIRS += ['tests']
+
EXTRA_COMPONENTS += [
- 'nsUpdateTimerManager.js',
- 'nsUpdateTimerManager.manifest',
+ 'nsUpdateService.js',
+ 'nsUpdateService.manifest',
+ 'nsUpdateServiceStub.js',
]
-if CONFIG['MOZ_UPDATER']:
- TEST_DIRS += ['tests']
-
- XPIDL_SOURCES += [
- 'nsIUpdateService.idl',
- ]
-
- EXTRA_COMPONENTS += [
- 'nsUpdateService.js',
- 'nsUpdateService.manifest',
- 'nsUpdateServiceStub.js',
- ]
-
- EXTRA_JS_MODULES += [
- 'UpdateTelemetry.jsm',
- ]
+EXTRA_JS_MODULES += [
+ 'UpdateTelemetry.jsm',
+]
JAR_MANIFESTS += ['jar.mn']
+
+FAIL_ON_WARNINGS = True
+
+with Files('**'):
+ BUG_COMPONENT = ('Toolkit', 'Application Update')
diff --git a/toolkit/mozapps/update/tests/Makefile.in b/toolkit/mozapps/update/tests/Makefile.in
index bba7be0c67c..1a8baec0838 100644
--- a/toolkit/mozapps/update/tests/Makefile.in
+++ b/toolkit/mozapps/update/tests/Makefile.in
@@ -18,8 +18,6 @@ xpcshell-data_FILES := $(filter-out $(pp_const_file),$(wildcard $(srcdir)/data/
xpcshell-data_DEST := $(XPCSHELLTESTROOT)/data
xpcshell-data_TARGET := misc
-# Android doesn't use the Mozilla updater or the toolkit update UI
-ifneq (android,$(MOZ_WIDGET_TOOLKIT))
ifndef MOZ_PROFILE_GENERATE
ifdef COMPILE_ENVIRONMENT
INSTALL_TARGETS += xpcshell-helper
@@ -47,11 +45,8 @@ INI_TEST_FILES = \
MOZ_WINCONSOLE = 1
-endif # Not Android
-
include $(topsrcdir)/config/rules.mk
-ifneq (android,$(MOZ_WIDGET_TOOLKIT))
# TestAUSReadStrings runs during check in the following directory with a Unicode
# char in order to test bug 473417 on Windows.
ifeq ($(OS_ARCH),WINNT)
@@ -67,4 +62,3 @@ check::
done
$(INSTALL) $(FINAL_TARGET)/TestAUSReadStrings$(BIN_SUFFIX) $(DEPTH)/_tests/updater/$(bug473417dir)/
@$(RUN_TEST_PROGRAM) $(DEPTH)/_tests/updater/$(bug473417dir)/TestAUSReadStrings$(BIN_SUFFIX)
-endif # Not Android
diff --git a/toolkit/mozapps/update/tests/moz.build b/toolkit/mozapps/update/tests/moz.build
index 9081e5be43f..4642f47c135 100644
--- a/toolkit/mozapps/update/tests/moz.build
+++ b/toolkit/mozapps/update/tests/moz.build
@@ -8,37 +8,35 @@ HAS_MISC_RULE = True
XPCSHELL_TESTS_MANIFESTS += ['unit_aus_update/xpcshell.ini']
-if CONFIG['MOZ_WIDGET_TOOLKIT'] != 'android':
- MOCHITEST_CHROME_MANIFESTS += ['chrome/chrome.ini']
- XPCSHELL_TESTS_MANIFESTS += ['unit_base_updater/xpcshell.ini']
+MOCHITEST_CHROME_MANIFESTS += ['chrome/chrome.ini']
+XPCSHELL_TESTS_MANIFESTS += ['unit_base_updater/xpcshell.ini']
- if CONFIG['MOZ_MAINTENANCE_SERVICE']:
- XPCSHELL_TESTS_MANIFESTS += ['unit_service_updater/xpcshell.ini']
+if CONFIG['MOZ_MAINTENANCE_SERVICE']:
+ XPCSHELL_TESTS_MANIFESTS += ['unit_service_updater/xpcshell.ini']
- SimplePrograms([
- 'TestAUSHelper',
- 'TestAUSReadStrings',
- ])
+SimplePrograms([
+ 'TestAUSHelper',
+ 'TestAUSReadStrings',
+])
- LOCAL_INCLUDES += [
- '/toolkit/mozapps/update',
- '/toolkit/mozapps/update/common',
+LOCAL_INCLUDES += [
+ '/toolkit/mozapps/update',
+ '/toolkit/mozapps/update/common',
+]
+
+if CONFIG['OS_ARCH'] == 'WINNT':
+ USE_LIBS += [
+ 'updatecommon-standalone',
]
- if CONFIG['OS_ARCH'] == 'WINNT':
- USE_LIBS += [
- 'updatecommon-standalone',
- ]
- else:
- USE_LIBS += [
- 'updatecommon',
- ]
-
- if CONFIG['OS_ARCH'] == 'WINNT':
- OS_LIBS += [
- 'wintrust',
- 'shlwapi',
- ]
+ OS_LIBS += [
+ 'wintrust',
+ 'shlwapi',
+ ]
+else:
+ USE_LIBS += [
+ 'updatecommon',
+ ]
for var in ('MOZ_APP_NAME', 'MOZ_APP_BASENAME', 'MOZ_APP_DISPLAYNAME',
'MOZ_APP_VENDOR', 'BIN_SUFFIX', 'MOZ_DEBUG'):
diff --git a/toolkit/mozapps/update/tests/unit_aus_update/xpcshell.ini b/toolkit/mozapps/update/tests/unit_aus_update/xpcshell.ini
index 871c633552e..4ff7e3ac4ed 100644
--- a/toolkit/mozapps/update/tests/unit_aus_update/xpcshell.ini
+++ b/toolkit/mozapps/update/tests/unit_aus_update/xpcshell.ini
@@ -5,7 +5,6 @@
[DEFAULT]
head = head_update.js
tail =
-skip-if = toolkit == 'android'
[canCheckForAndCanApplyUpdates.js]
[urlConstruction.js]
diff --git a/toolkit/mozapps/update/tests/unit_base_updater/xpcshell.ini b/toolkit/mozapps/update/tests/unit_base_updater/xpcshell.ini
index 8b853da784e..491a9d1d815 100644
--- a/toolkit/mozapps/update/tests/unit_base_updater/xpcshell.ini
+++ b/toolkit/mozapps/update/tests/unit_base_updater/xpcshell.ini
@@ -9,7 +9,6 @@
[DEFAULT]
head = head_update.js
tail =
-skip-if = toolkit == 'android'
[marSuccessComplete.js]
[marSuccessPartial.js]
diff --git a/toolkit/mozapps/update/updater/updater-xpcshell/moz.build b/toolkit/mozapps/update/updater/updater-xpcshell/moz.build
index 7f16ee89e2c..81eef713d19 100644
--- a/toolkit/mozapps/update/updater/updater-xpcshell/moz.build
+++ b/toolkit/mozapps/update/updater/updater-xpcshell/moz.build
@@ -10,3 +10,4 @@ updater_rel_path = '../'
NO_DIST_INSTALL = True
DEFINES['UPDATER_XPCSHELL_CERT'] = True
include('../updater-common.build')
+FAIL_ON_WARNINGS = True
diff --git a/toolkit/themes/osx/global/jar.mn b/toolkit/themes/osx/global/jar.mn
index 251ef392f84..f465be9f0f3 100644
--- a/toolkit/themes/osx/global/jar.mn
+++ b/toolkit/themes/osx/global/jar.mn
@@ -6,13 +6,13 @@ toolkit.jar:
% skin global classic/1.0 %skin/classic/global/
skin/classic/global/10pct_transparent_grey.png
skin/classic/global/50pct_transparent_grey.png
- skin/classic/global/about.css (../../windows/global/about.css)
- skin/classic/global/aboutCache.css (../../windows/global/aboutCache.css)
- skin/classic/global/aboutCacheEntry.css (../../windows/global/aboutCacheEntry.css)
- skin/classic/global/aboutMemory.css (../../windows/global/aboutMemory.css)
- skin/classic/global/aboutReader.css (../../windows/global/aboutReader.css)
- skin/classic/global/aboutSupport.css (../../windows/global/aboutSupport.css)
- skin/classic/global/appPicker.css (../../windows/global/appPicker.css)
+ skin/classic/global/about.css (../../shared/about.css)
+ skin/classic/global/aboutCache.css (../../shared/aboutCache.css)
+ skin/classic/global/aboutCacheEntry.css (../../shared/aboutCacheEntry.css)
+ skin/classic/global/aboutMemory.css (../../shared/aboutMemory.css)
+ skin/classic/global/aboutReader.css (../../shared/aboutReader.css)
+ skin/classic/global/aboutSupport.css (../../shared/aboutSupport.css)
+ skin/classic/global/appPicker.css (../../shared/appPicker.css)
skin/classic/global/arrow.css
skin/classic/global/autocomplete.css
skin/classic/global/button.css
diff --git a/toolkit/themes/windows/global/about.css b/toolkit/themes/shared/about.css
similarity index 100%
rename from toolkit/themes/windows/global/about.css
rename to toolkit/themes/shared/about.css
diff --git a/toolkit/themes/windows/global/aboutCache.css b/toolkit/themes/shared/aboutCache.css
similarity index 100%
rename from toolkit/themes/windows/global/aboutCache.css
rename to toolkit/themes/shared/aboutCache.css
diff --git a/toolkit/themes/windows/global/aboutCacheEntry.css b/toolkit/themes/shared/aboutCacheEntry.css
similarity index 100%
rename from toolkit/themes/windows/global/aboutCacheEntry.css
rename to toolkit/themes/shared/aboutCacheEntry.css
diff --git a/toolkit/themes/windows/global/aboutMemory.css b/toolkit/themes/shared/aboutMemory.css
similarity index 100%
rename from toolkit/themes/windows/global/aboutMemory.css
rename to toolkit/themes/shared/aboutMemory.css
diff --git a/toolkit/themes/windows/global/aboutReader.css b/toolkit/themes/shared/aboutReader.css
similarity index 100%
rename from toolkit/themes/windows/global/aboutReader.css
rename to toolkit/themes/shared/aboutReader.css
diff --git a/toolkit/themes/windows/global/aboutSupport.css b/toolkit/themes/shared/aboutSupport.css
similarity index 100%
rename from toolkit/themes/windows/global/aboutSupport.css
rename to toolkit/themes/shared/aboutSupport.css
diff --git a/toolkit/themes/windows/global/appPicker.css b/toolkit/themes/shared/appPicker.css
similarity index 100%
rename from toolkit/themes/windows/global/appPicker.css
rename to toolkit/themes/shared/appPicker.css
diff --git a/toolkit/themes/windows/global/jar.mn b/toolkit/themes/windows/global/jar.mn
index 100357a1717..024f3ca0acf 100644
--- a/toolkit/themes/windows/global/jar.mn
+++ b/toolkit/themes/windows/global/jar.mn
@@ -4,13 +4,13 @@
toolkit.jar:
% skin global classic/1.0 %skin/classic/global/
- skin/classic/global/about.css
- skin/classic/global/aboutCache.css
- skin/classic/global/aboutCacheEntry.css
- skin/classic/global/aboutMemory.css
- skin/classic/global/aboutReader.css
- skin/classic/global/aboutSupport.css
- skin/classic/global/appPicker.css
+ skin/classic/global/about.css (../../shared/about.css)
+ skin/classic/global/aboutCache.css (../../shared/aboutCache.css)
+ skin/classic/global/aboutCacheEntry.css (../../shared/aboutCacheEntry.css)
+ skin/classic/global/aboutMemory.css (../../shared/aboutMemory.css)
+ skin/classic/global/aboutReader.css (../../shared/aboutReader.css)
+ skin/classic/global/aboutSupport.css (../../shared/aboutSupport.css)
+ skin/classic/global/appPicker.css (../../shared/appPicker.css)
skin/classic/global/arrow.css
* skin/classic/global/autocomplete.css
skin/classic/global/button.css
diff --git a/toolkit/xre/nsAppRunner.cpp b/toolkit/xre/nsAppRunner.cpp
index 614831fdf9b..827806b2bce 100644
--- a/toolkit/xre/nsAppRunner.cpp
+++ b/toolkit/xre/nsAppRunner.cpp
@@ -23,7 +23,9 @@
#include "nsAppRunner.h"
#include "mozilla/AppData.h"
+#if defined(MOZ_UPDATER) && !defined(MOZ_WIDGET_ANDROID)
#include "nsUpdateDriver.h"
+#endif
#include "ProfileReset.h"
#ifdef MOZ_INSTRUMENT_EVENT_LOOP
@@ -3718,7 +3720,7 @@ XREMain::XRE_mainStartup(bool* aExitFlag)
}
#endif
-#if defined(USE_MOZ_UPDATER)
+#if defined(MOZ_UPDATER) && !defined(MOZ_WIDGET_ANDROID)
// Check for and process any available updates
nsCOMPtr updRoot;
bool persistent;
diff --git a/toolkit/xre/nsUpdateDriver.h b/toolkit/xre/nsUpdateDriver.h
index 6c6c0a520de..104b0520d24 100644
--- a/toolkit/xre/nsUpdateDriver.h
+++ b/toolkit/xre/nsUpdateDriver.h
@@ -8,13 +8,11 @@
#define nsUpdateDriver_h__
#include "nscore.h"
-#ifdef MOZ_UPDATER
#include "nsIUpdateService.h"
#include "nsIThread.h"
#include "nsCOMPtr.h"
#include "nsString.h"
#include "mozilla/Attributes.h"
-#endif
class nsIFile;
@@ -57,7 +55,6 @@ nsresult ProcessUpdates(nsIFile *greDir, nsIFile *appDir,
nsIFile *osApplyToDir = nullptr,
ProcessType *pid = nullptr);
-#ifdef MOZ_UPDATER
// The implementation of the update processor handles the task of loading the
// updater application for staging an update.
// XXX ehsan this is living in this file in order to make use of the existing
@@ -107,6 +104,4 @@ private:
nsCOMPtr mProcessWatcher;
StagedUpdateInfo mInfo;
};
-#endif
-
#endif // nsUpdateDriver_h__
diff --git a/widget/android/AndroidBridge.cpp b/widget/android/AndroidBridge.cpp
index f68f469224b..c2d1b522393 100644
--- a/widget/android/AndroidBridge.cpp
+++ b/widget/android/AndroidBridge.cpp
@@ -44,6 +44,7 @@
#include "MediaCodec.h"
#include "SurfaceTexture.h"
+#include "GLContextProvider.h"
using namespace mozilla;
using namespace mozilla::gfx;
@@ -821,6 +822,8 @@ AndroidBridge::OpenGraphicsLibraries()
ANativeWindow_setBuffersGeometry = (int (*)(void*, int, int, int)) dlsym(handle, "ANativeWindow_setBuffersGeometry");
ANativeWindow_lock = (int (*)(void*, void*, void*)) dlsym(handle, "ANativeWindow_lock");
ANativeWindow_unlockAndPost = (int (*)(void*))dlsym(handle, "ANativeWindow_unlockAndPost");
+ ANativeWindow_getWidth = (int (*)(void*))dlsym(handle, "ANativeWindow_getWidth");
+ ANativeWindow_getHeight = (int (*)(void*))dlsym(handle, "ANativeWindow_getHeight");
// This is only available in Honeycomb and ICS. It was removed in Jelly Bean
ANativeWindow_fromSurfaceTexture = (void* (*)(JNIEnv*, jobject))dlsym(handle, "ANativeWindow_fromSurfaceTexture");
@@ -1275,6 +1278,16 @@ AndroidBridge::ReleaseNativeWindow(void *window)
// have nothing to do here. We should probably ref it.
}
+IntSize
+AndroidBridge::GetNativeWindowSize(void* window)
+{
+ if (!window || !ANativeWindow_getWidth || !ANativeWindow_getHeight) {
+ return IntSize(0, 0);
+ }
+
+ return IntSize(ANativeWindow_getWidth(window), ANativeWindow_getHeight(window));
+}
+
void*
AndroidBridge::AcquireNativeWindowFromSurfaceTexture(JNIEnv* aEnv, jobject aSurfaceTexture)
{
@@ -1508,7 +1521,9 @@ void AndroidBridge::SyncFrameMetrics(const ParentLayerPoint& aScrollOffset, floa
}
AndroidBridge::AndroidBridge()
- : mLayerClient(nullptr)
+ : mLayerClient(nullptr),
+ mPresentationWindow(nullptr),
+ mPresentationSurface(nullptr)
{
}
@@ -2036,6 +2051,51 @@ AndroidBridge::RunDelayedUiThreadTasks()
return -1;
}
+void*
+AndroidBridge::GetPresentationWindow()
+{
+ return mPresentationWindow;
+}
+
+void
+AndroidBridge::SetPresentationWindow(void* aPresentationWindow)
+{
+ if (mPresentationWindow) {
+ const bool wasAlreadyPaused = nsWindow::IsCompositionPaused();
+ if (!wasAlreadyPaused) {
+ nsWindow::SchedulePauseComposition();
+ }
+
+ mPresentationWindow = aPresentationWindow;
+ if (mPresentationSurface) {
+ // destroy the egl surface!
+ // The compositor is paused so it should be okay to destroy
+ // the surface here.
+ mozilla::gl::GLContextProvider::DestroyEGLSurface(mPresentationSurface);
+ mPresentationSurface = nullptr;
+ }
+
+ if (!wasAlreadyPaused) {
+ nsWindow::ScheduleResumeComposition();
+ }
+ }
+ else {
+ mPresentationWindow = aPresentationWindow;
+ }
+}
+
+EGLSurface
+AndroidBridge::GetPresentationSurface()
+{
+ return mPresentationSurface;
+}
+
+void
+AndroidBridge::SetPresentationSurface(EGLSurface aPresentationSurface)
+{
+ mPresentationSurface = aPresentationSurface;
+}
+
Object::LocalRef AndroidBridge::ChannelCreate(Object::Param stream) {
JNIEnv* const env = GetJNIForThread();
auto rv = Object::LocalRef::Adopt(env, env->CallStaticObjectMethod(
diff --git a/widget/android/AndroidBridge.h b/widget/android/AndroidBridge.h
index c792d21731d..8e1aaf625d4 100644
--- a/widget/android/AndroidBridge.h
+++ b/widget/android/AndroidBridge.h
@@ -21,6 +21,7 @@
#include "nsIMIMEInfo.h"
#include "nsColor.h"
#include "gfxRect.h"
+#include "mozilla/gfx/Point.h"
#include "nsIAndroidBridge.h"
#include "nsIMobileMessageCallback.h"
@@ -264,6 +265,7 @@ public:
void *AcquireNativeWindow(JNIEnv* aEnv, jobject aSurface);
void ReleaseNativeWindow(void *window);
+ mozilla::gfx::IntSize GetNativeWindowSize(void* window);
void *AcquireNativeWindowFromSurfaceTexture(JNIEnv* aEnv, jobject aSurface);
void ReleaseNativeWindowForSurfaceTexture(void *window);
@@ -426,6 +428,8 @@ protected:
int (* ANativeWindow_lock)(void *window, void *outBuffer, void *inOutDirtyBounds);
int (* ANativeWindow_unlockAndPost)(void *window);
+ int (* ANativeWindow_getWidth)(void * window);
+ int (* ANativeWindow_getHeight)(void * window);
int (* Surface_lock)(void* surface, void* surfaceInfo, void* region, bool block);
int (* Surface_unlockAndPost)(void* surface);
@@ -439,6 +443,15 @@ private:
public:
void PostTaskToUiThread(Task* aTask, int aDelayMs);
int64_t RunDelayedUiThreadTasks();
+
+ void* GetPresentationWindow();
+ void SetPresentationWindow(void* aPresentationWindow);
+
+ EGLSurface GetPresentationSurface();
+ void SetPresentationSurface(EGLSurface aPresentationSurface);
+private:
+ void* mPresentationWindow;
+ EGLSurface mPresentationSurface;
};
class AutoJNIClass {
diff --git a/widget/android/AndroidJNI.cpp b/widget/android/AndroidJNI.cpp
index dbd177df453..3200c8c7942 100644
--- a/widget/android/AndroidJNI.cpp
+++ b/widget/android/AndroidJNI.cpp
@@ -811,6 +811,27 @@ cleanup:
return surfaceBits;
}
+NS_EXPORT void JNICALL
+Java_org_mozilla_gecko_GeckoAppShell_addPresentationSurface(JNIEnv* jenv, jclass, jobject surface)
+{
+ if (surface != NULL) {
+ void* window = AndroidBridge::Bridge()->AcquireNativeWindow(jenv, surface);
+ if (window) {
+ AndroidBridge::Bridge()->SetPresentationWindow(window);
+ }
+ }
+}
+
+NS_EXPORT void JNICALL
+Java_org_mozilla_gecko_GeckoAppShell_removePresentationSurface(JNIEnv* jenv, jclass, jobject surface)
+{
+ void* window = AndroidBridge::Bridge()->GetPresentationWindow();
+ if (window) {
+ AndroidBridge::Bridge()->SetPresentationWindow(nullptr);
+ AndroidBridge::Bridge()->ReleaseNativeWindow(window);
+ }
+}
+
NS_EXPORT void JNICALL
Java_org_mozilla_gecko_GeckoAppShell_onFullScreenPluginHidden(JNIEnv* jenv, jclass, jobject view)
{
diff --git a/widget/android/nsWindow.cpp b/widget/android/nsWindow.cpp
index 028b7e55f40..1a432c8c150 100644
--- a/widget/android/nsWindow.cpp
+++ b/widget/android/nsWindow.cpp
@@ -2454,6 +2454,29 @@ nsWindow::ScheduleComposite()
}
}
+bool
+nsWindow::IsCompositionPaused()
+{
+ return sCompositorPaused;
+}
+
+void
+nsWindow::SchedulePauseComposition()
+{
+ if (sCompositorParent) {
+ sCompositorParent->SchedulePauseOnCompositorThread();
+ sCompositorPaused = true;
+ }
+}
+
+void
+nsWindow::ScheduleResumeComposition()
+{
+ if (sCompositorParent && sCompositorParent->ScheduleResumeOnCompositorThread()) {
+ sCompositorPaused = false;
+ }
+}
+
void
nsWindow::ScheduleResumeComposition(int width, int height)
{
diff --git a/widget/android/nsWindow.h b/widget/android/nsWindow.h
index d3915089f93..648abca0dc9 100644
--- a/widget/android/nsWindow.h
+++ b/widget/android/nsWindow.h
@@ -156,7 +156,10 @@ public:
static void SetCompositor(mozilla::layers::LayerManager* aLayerManager,
mozilla::layers::CompositorParent* aCompositorParent,
mozilla::layers::CompositorChild* aCompositorChild);
+ static bool IsCompositionPaused();
static void ScheduleComposite();
+ static void SchedulePauseComposition();
+ static void ScheduleResumeComposition();
static void ScheduleResumeComposition(int width, int height);
static void ForceIsFirstPaint();
static float ComputeRenderIntegrity();