Merge mozilla-central to mozilla-inbound

This commit is contained in:
Carsten "Tomcat" Book 2014-12-12 13:57:12 +01:00
commit 799a81bce4
44 changed files with 422 additions and 653 deletions

View File

@ -22,8 +22,17 @@
var thisTabDocAcc = getTabDocAccessible();
var thisDocTabPanelAcc = thisTabDocAcc.parent.parent;
var tabPanelsAcc = thisDocTabPanelAcc.parent;
var newDocTabPanelAcc = tabPanelsAcc.lastChild.firstChild;
return newDocTabPanelAcc.firstChild;
var newDocTabPanelAcc = tabPanelsAcc.firstChild;
var nextAcc = newDocTabPanelAcc;
while (nextAcc = nextAcc.nextSibling) {
// Find the last accessible for a browser with about:mozilla loaded.
if (nextAcc.firstChild.DOMNode.currentURI.spec == "about:mozilla") {
newDocTabPanelAcc = nextAcc;
}
}
return newDocTabPanelAcc.firstChild.firstChild;
}
function linkChecker(aID)

View File

@ -15,25 +15,6 @@
src="../role.js"></script>
<script type="application/javascript"
src="../states.js"></script>
<script type="application/javascript">
// Front end stuff sometimes likes to stuff things in the hidden window(s)
// in which case there's accessibles for that content.
Components.utils.import("resource://gre/modules/Services.jsm");
// Force the creation of an accessible for the hidden window's document.
var doc = Services.appShell.hiddenDOMWindow.document;
gAccRetrieval.getAccessibleFor(doc);
// The private hidden window will be lazily created that's why we need to do
// it here *before* loading '../events.js' or else we'll have a duplicate
// reorder event.
var privateDoc = Services.appShell.hiddenPrivateDOMWindow.document;
// Force the creation of an accessible for the private hidden window's doc.
gAccRetrieval.getAccessibleFor(privateDoc);
</script>
<script type="application/javascript"
src="../events.js"></script>
@ -193,12 +174,6 @@
var accTree = {
role: ROLE_APP_ROOT,
children: [
{
role: ROLE_CHROME_WINDOW
},
{
role: ROLE_CHROME_WINDOW
},
{
role: ROLE_CHROME_WINDOW
},

View File

@ -31,10 +31,15 @@
is(root.parentDocument, null,
"Wrong parent document of root accessible");
is(root.childDocumentCount, 1,
ok(root.childDocumentCount >= 1,
"Wrong child document count of root accessible");
is(root.getChildDocumentAt(0), tabDoc,
"Wrong child document at index 0 of root accessible");
var tabDocumentFound = false;
for (var i = 0; i < root.childDocumentCount && !tabDocumentFound; i++) {
tabDocumentFound = root.getChildDocumentAt(i) == tabDoc;
}
ok(tabDocumentFound,
"Tab document not found in children of the root accessible");
is(tabDoc.parentDocument, root,
"Wrong parent document of tab document");

View File

@ -169,6 +169,23 @@
]
}
]
},
{
// notificationbox
role: ROLE_PROPERTYPAGE,
children: [
{
// browser
role: ROLE_INTERNAL_FRAME,
children: [
{
// #document ("about:newtab" preloaded)
role: ROLE_APPLICATION
// children: [ ... ] // Ignore document content.
}
]
}
]
}
]
};

View File

@ -15,7 +15,7 @@
<project name="platform_build" path="build" remote="b2g" revision="3ab0d9c70f0b2e1ededc679112c392303f037361">
<copyfile dest="Makefile" src="core/root.mk"/>
</project>
<project name="gaia" path="gaia" remote="mozillaorg" revision="1d9ae9cca415ad093beba9521c429350e1f2b14d"/>
<project name="gaia" path="gaia" remote="mozillaorg" revision="0de95b4017de73e72c897e2dcb87564d8f3756eb"/>
<project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="50ad16a280fe9cfa0716f8c6ba16afdf7f266b49"/>
<project name="librecovery" path="librecovery" remote="b2g" revision="891e5069c0ad330d8191bf8c7b879c814258c89f"/>

View File

@ -19,7 +19,7 @@
<copyfile dest="Makefile" src="core/root.mk"/>
</project>
<project name="fake-dalvik" path="dalvik" remote="b2g" revision="ca1f327d5acc198bb4be62fa51db2c039032c9ce"/>
<project name="gaia.git" path="gaia" remote="mozillaorg" revision="1d9ae9cca415ad093beba9521c429350e1f2b14d"/>
<project name="gaia.git" path="gaia" remote="mozillaorg" revision="0de95b4017de73e72c897e2dcb87564d8f3756eb"/>
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="50ad16a280fe9cfa0716f8c6ba16afdf7f266b49"/>
<project name="rilproxy" path="rilproxy" remote="b2g" revision="827214fcf38d6569aeb5c6d6f31cb296d1f09272"/>
<project name="platform_hardware_ril" path="hardware/ril" remote="b2g" revision="d5d3f93914558b6f168447b805cd799c8233e300"/>

View File

@ -17,7 +17,7 @@
</project>
<project name="rilproxy" path="rilproxy" remote="b2g" revision="827214fcf38d6569aeb5c6d6f31cb296d1f09272"/>
<project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
<project name="gaia" path="gaia" remote="mozillaorg" revision="1d9ae9cca415ad093beba9521c429350e1f2b14d"/>
<project name="gaia" path="gaia" remote="mozillaorg" revision="0de95b4017de73e72c897e2dcb87564d8f3756eb"/>
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="50ad16a280fe9cfa0716f8c6ba16afdf7f266b49"/>
<project name="moztt" path="external/moztt" remote="b2g" revision="fe893bb760a3bb64375f62fdf4762a58c59df9ef"/>
<project name="apitrace" path="external/apitrace" remote="apitrace" revision="58aee9864c193acfd03fa196af399d0659ba506d"/>

View File

@ -15,7 +15,7 @@
<project name="platform_build" path="build" remote="b2g" revision="3ab0d9c70f0b2e1ededc679112c392303f037361">
<copyfile dest="Makefile" src="core/root.mk"/>
</project>
<project name="gaia" path="gaia" remote="mozillaorg" revision="1d9ae9cca415ad093beba9521c429350e1f2b14d"/>
<project name="gaia" path="gaia" remote="mozillaorg" revision="0de95b4017de73e72c897e2dcb87564d8f3756eb"/>
<project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="50ad16a280fe9cfa0716f8c6ba16afdf7f266b49"/>
<project name="librecovery" path="librecovery" remote="b2g" revision="891e5069c0ad330d8191bf8c7b879c814258c89f"/>

View File

@ -19,7 +19,7 @@
<copyfile dest="Makefile" src="core/root.mk"/>
</project>
<project name="fake-dalvik" path="dalvik" remote="b2g" revision="ca1f327d5acc198bb4be62fa51db2c039032c9ce"/>
<project name="gaia.git" path="gaia" remote="mozillaorg" revision="1d9ae9cca415ad093beba9521c429350e1f2b14d"/>
<project name="gaia.git" path="gaia" remote="mozillaorg" revision="0de95b4017de73e72c897e2dcb87564d8f3756eb"/>
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="50ad16a280fe9cfa0716f8c6ba16afdf7f266b49"/>
<project name="rilproxy" path="rilproxy" remote="b2g" revision="827214fcf38d6569aeb5c6d6f31cb296d1f09272"/>
<project name="platform_hardware_ril" path="hardware/ril" remote="b2g" revision="d5d3f93914558b6f168447b805cd799c8233e300"/>

View File

@ -15,7 +15,7 @@
<project name="platform_build" path="build" remote="b2g" revision="3ab0d9c70f0b2e1ededc679112c392303f037361">
<copyfile dest="Makefile" src="core/root.mk"/>
</project>
<project name="gaia" path="gaia" remote="mozillaorg" revision="1d9ae9cca415ad093beba9521c429350e1f2b14d"/>
<project name="gaia" path="gaia" remote="mozillaorg" revision="0de95b4017de73e72c897e2dcb87564d8f3756eb"/>
<project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="50ad16a280fe9cfa0716f8c6ba16afdf7f266b49"/>
<project name="librecovery" path="librecovery" remote="b2g" revision="891e5069c0ad330d8191bf8c7b879c814258c89f"/>

View File

@ -17,7 +17,7 @@
</project>
<project name="librecovery" path="librecovery" remote="b2g" revision="891e5069c0ad330d8191bf8c7b879c814258c89f"/>
<project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
<project name="gaia" path="gaia" remote="mozillaorg" revision="1d9ae9cca415ad093beba9521c429350e1f2b14d"/>
<project name="gaia" path="gaia" remote="mozillaorg" revision="0de95b4017de73e72c897e2dcb87564d8f3756eb"/>
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="50ad16a280fe9cfa0716f8c6ba16afdf7f266b49"/>
<project name="moztt" path="external/moztt" remote="b2g" revision="fe893bb760a3bb64375f62fdf4762a58c59df9ef"/>
<project name="apitrace" path="external/apitrace" remote="apitrace" revision="58aee9864c193acfd03fa196af399d0659ba506d"/>

View File

@ -4,6 +4,6 @@
"remote": "",
"branch": ""
},
"revision": "f1f983cfb1e42dbc6723c192f73c16bf098b6b4b",
"revision": "21a79199c8869df69769148db45cf08aff37e315",
"repo_path": "integration/gaia-central"
}

View File

@ -17,7 +17,7 @@
<copyfile dest="Makefile" src="core/root.mk"/>
</project>
<project name="fake-dalvik" path="dalvik" remote="b2g" revision="ca1f327d5acc198bb4be62fa51db2c039032c9ce"/>
<project name="gaia.git" path="gaia" remote="mozillaorg" revision="1d9ae9cca415ad093beba9521c429350e1f2b14d"/>
<project name="gaia.git" path="gaia" remote="mozillaorg" revision="0de95b4017de73e72c897e2dcb87564d8f3756eb"/>
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="50ad16a280fe9cfa0716f8c6ba16afdf7f266b49"/>
<project name="librecovery" path="librecovery" remote="b2g" revision="891e5069c0ad330d8191bf8c7b879c814258c89f"/>
<project name="moztt" path="external/moztt" remote="b2g" revision="fe893bb760a3bb64375f62fdf4762a58c59df9ef"/>

View File

@ -15,7 +15,7 @@
<copyfile dest="Makefile" src="core/root.mk"/>
</project>
<project name="fake-dalvik" path="dalvik" remote="b2g" revision="ca1f327d5acc198bb4be62fa51db2c039032c9ce"/>
<project name="gaia.git" path="gaia" remote="mozillaorg" revision="1d9ae9cca415ad093beba9521c429350e1f2b14d"/>
<project name="gaia.git" path="gaia" remote="mozillaorg" revision="0de95b4017de73e72c897e2dcb87564d8f3756eb"/>
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="50ad16a280fe9cfa0716f8c6ba16afdf7f266b49"/>
<project name="rilproxy" path="rilproxy" remote="b2g" revision="827214fcf38d6569aeb5c6d6f31cb296d1f09272"/>
<project name="librecovery" path="librecovery" remote="b2g" revision="891e5069c0ad330d8191bf8c7b879c814258c89f"/>

View File

@ -17,7 +17,7 @@
</project>
<project name="rilproxy" path="rilproxy" remote="b2g" revision="827214fcf38d6569aeb5c6d6f31cb296d1f09272"/>
<project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
<project name="gaia" path="gaia" remote="mozillaorg" revision="1d9ae9cca415ad093beba9521c429350e1f2b14d"/>
<project name="gaia" path="gaia" remote="mozillaorg" revision="0de95b4017de73e72c897e2dcb87564d8f3756eb"/>
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="50ad16a280fe9cfa0716f8c6ba16afdf7f266b49"/>
<project name="moztt" path="external/moztt" remote="b2g" revision="fe893bb760a3bb64375f62fdf4762a58c59df9ef"/>
<project name="apitrace" path="external/apitrace" remote="apitrace" revision="58aee9864c193acfd03fa196af399d0659ba506d"/>

View File

@ -17,7 +17,7 @@
<copyfile dest="Makefile" src="core/root.mk"/>
</project>
<project name="fake-dalvik" path="dalvik" remote="b2g" revision="ca1f327d5acc198bb4be62fa51db2c039032c9ce"/>
<project name="gaia.git" path="gaia" remote="mozillaorg" revision="1d9ae9cca415ad093beba9521c429350e1f2b14d"/>
<project name="gaia.git" path="gaia" remote="mozillaorg" revision="0de95b4017de73e72c897e2dcb87564d8f3756eb"/>
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="50ad16a280fe9cfa0716f8c6ba16afdf7f266b49"/>
<project name="rilproxy" path="rilproxy" remote="b2g" revision="827214fcf38d6569aeb5c6d6f31cb296d1f09272"/>
<project name="librecovery" path="librecovery" remote="b2g" revision="891e5069c0ad330d8191bf8c7b879c814258c89f"/>

View File

@ -11,6 +11,7 @@ XPCOMUtils.defineLazyModuleGetter(this, "fxaMigrator",
const PREF_SYNC_START_DOORHANGER = "services.sync.ui.showSyncStartDoorhanger";
const DOORHANGER_ACTIVATE_DELAY_MS = 5000;
const SYNC_MIGRATION_NOTIFICATION_TITLE = "fxa-migration";
let gFxAccounts = {
@ -157,7 +158,7 @@ let gFxAccounts = {
setTimeout(() => this.onSyncStart(), DOORHANGER_ACTIVATE_DELAY_MS);
} else {
this._inCustomizationMode = event.type == "customizationstarting";
this.updateUI();
this.updateAppMenuItem();
}
},
@ -182,8 +183,13 @@ let gFxAccounts = {
},
updateUI: function () {
this.updateAppMenuItem();
this.updateMigrationNotification();
},
updateAppMenuItem: function () {
if (this._migrationInfo) {
this.showMigrationUI();
this.updateAppMenuItemForMigration();
return;
}
@ -241,32 +247,74 @@ let gFxAccounts = {
});
},
showMigrationUI: Task.async(function* () {
updateAppMenuItemForMigration: Task.async(function* () {
let status = null;
let label = null;
switch (this._migrationInfo.state) {
case fxaMigrator.STATE_USER_FXA:
status = "migrate-signup";
label = this.strings.formatStringFromName("needUser",
label = this.strings.formatStringFromName("needUserShort",
[this.button.getAttribute("fxabrandname")], 1);
break;
case fxaMigrator.STATE_USER_FXA_VERIFIED:
if (this._migrationInfo.email) {
status = "migrate-verify";
label = this.strings.formatStringFromName("needVerifiedUser",
[this._migrationInfo.email],
1);
}
status = "migrate-verify";
label = this.strings.formatStringFromName("needVerifiedUserShort",
[this._migrationInfo.email],
1);
break;
}
if (label && status) {
this.button.label = label;
this.button.hidden = false;
this.button.setAttribute("fxastatus", status);
} else {
Cu.reportError("Could not update menu panel button given migration " +
"state: " + this._migrationInfo.state);
this.button.label = label;
this.button.hidden = false;
this.button.setAttribute("fxastatus", status);
}),
updateMigrationNotification: Task.async(function* () {
if (!this._migrationInfo) {
Weave.Notifications.removeAll(SYNC_MIGRATION_NOTIFICATION_TITLE);
return;
}
if (gBrowser.currentURI.spec.split("?")[0] == "about:accounts") {
// If the current tab is about:accounts, assume the user just completed a
// migration step and don't bother them with a redundant notification.
return;
}
let note = null;
switch (this._migrationInfo.state) {
case fxaMigrator.STATE_USER_FXA: {
let msg = this.strings.GetStringFromName("needUserLong");
let upgradeLabel =
this.strings.GetStringFromName("upgradeToFxA.label");
let upgradeAccessKey =
this.strings.GetStringFromName("upgradeToFxA.accessKey");
note = new Weave.Notification(
undefined, msg, undefined, Weave.Notifications.PRIORITY_WARNING, [
new Weave.NotificationButton(upgradeLabel, upgradeAccessKey, () => {
fxaMigrator.createFxAccount(window);
}),
]
);
break;
}
case fxaMigrator.STATE_USER_FXA_VERIFIED: {
let msg =
this.strings.formatStringFromName("needVerifiedUserLong",
[this._migrationInfo.email], 1);
let resendLabel =
this.strings.GetStringFromName("resendVerificationEmail.label");
let resendAccessKey =
this.strings.GetStringFromName("resendVerificationEmail.accessKey");
note = new Weave.Notification(
undefined, msg, undefined, Weave.Notifications.PRIORITY_INFO, [
new Weave.NotificationButton(resendLabel, resendAccessKey, () => {
fxaMigrator.resendVerificationMail();
}),
]
);
break;
}
}
note.title = SYNC_MIGRATION_NOTIFICATION_TITLE;
Weave.Notifications.replaceTitle(note);
}),
onMenuPanelCommand: function (event) {

View File

@ -13,8 +13,6 @@ let CloudSync = null;
// gSyncUI handles updating the tools menu and displaying notifications.
let gSyncUI = {
DEFAULT_EOL_URL: "https://www.mozilla.org/firefox/?utm_source=synceol",
_obs: ["weave:service:sync:start",
"weave:service:quota:remaining",
"weave:service:setup-complete",
@ -27,7 +25,6 @@ let gSyncUI = {
"weave:ui:sync:error",
"weave:ui:sync:finish",
"weave:ui:clear-error",
"weave:eol",
],
_unloaded: false,
@ -260,32 +257,6 @@ let gSyncUI = {
return brand.get("brandShortName");
},
onEOLNotice: function (data) {
let code = data.code;
let kind = (code == "hard-eol") ? "error" : "warning";
let url = data.url || gSyncUI.DEFAULT_EOL_URL;
let title = this._stringBundle.GetStringFromName(kind + ".sync.eol.label");
let description = this._stringBundle.formatStringFromName(kind + ".sync.eol.description",
[this._getAppName()],
1);
let buttons = [];
buttons.push(new Weave.NotificationButton(
this._stringBundle.GetStringFromName("sync.eol.learnMore.label"),
this._stringBundle.GetStringFromName("sync.eol.learnMore.accesskey"),
function() {
window.openUILinkIn(url, "tab");
return true;
}
));
let priority = (kind == "error") ? Weave.Notifications.PRIORITY_WARNING :
Weave.Notifications.PRIORITY_INFO;
let notification = new Weave.Notification(title, description, null, priority, buttons);
Weave.Notifications.replaceTitle(notification);
},
openServerStatus: function () {
let statusURL = Services.prefs.getCharPref("services.sync.statusURL");
window.openUILinkIn(statusURL, "tab");
@ -551,9 +522,6 @@ let gSyncUI = {
case "weave:ui:clear-error":
this.clearError();
break;
case "weave:eol":
this.onEOLNotice(subject);
break;
}
},

View File

@ -154,9 +154,6 @@ XPCOMUtils.defineLazyModuleGetter(this, "SafeBrowsing",
"resource://gre/modules/SafeBrowsing.jsm");
#endif
XPCOMUtils.defineLazyModuleGetter(this, "gBrowserNewTabPreloader",
"resource:///modules/BrowserNewTabPreloader.jsm", "BrowserNewTabPreloader");
XPCOMUtils.defineLazyModuleGetter(this, "gCustomizationTabPreloader",
"resource:///modules/CustomizationTabPreloader.jsm", "CustomizationTabPreloader");

View File

@ -669,6 +669,12 @@
if (event.target != otherWin.document)
return;
let detachEvent = new aChatbox.contentWindow.CustomEvent("socialFrameDetached", {
bubbles: true,
cancelable: true,
});
aChatbox.contentDocument.dispatchEvent(detachEvent);
otherWin.removeEventListener("load", _chatLoad, true);
let otherChatbox = otherWin.document.getElementById("chatter");
aChatbox.swapDocShells(otherChatbox);

View File

@ -1513,6 +1513,134 @@
</body>
</method>
<field name="_preloadedBrowser">null</field>
<method name="_getPreloadedBrowser">
<body>
<![CDATA[
if (!this._isPreloadingEnabled()) {
return null;
}
// The preloaded browser might be null.
let browser = this._preloadedBrowser;
// Consume the browser.
this._preloadedBrowser = null;
// Attach the nsIFormFillController now that we know the browser
// will be used. If we do that before and the preloaded browser
// won't be consumed until shutdown then we leak a docShell.
if (browser && this.hasAttribute("autocompletepopup")) {
browser.setAttribute("autocompletepopup", this.getAttribute("autocompletepopup"));
browser.attachFormFill();
}
return browser;
]]>
</body>
</method>
<method name="_isPreloadingEnabled">
<body>
<![CDATA[
// Preloading for the newtab page is enabled when the pref is true
// and the URL is "about:newtab". We do not support preloading for
// custom newtab URLs.
return Services.prefs.getBoolPref("browser.newtab.preload") &&
!Services.prefs.prefHasUserValue("browser.newtab.url");
]]>
</body>
</method>
<method name="_createPreloadBrowser">
<body>
<![CDATA[
// Do nothing if we have a preloaded browser already
// or preloading of newtab pages is disabled.
if (this._preloadedBrowser || !this._isPreloadingEnabled()) {
return;
}
let browser = this._createBrowser({isPreloadBrowser: true});
this._preloadedBrowser = browser;
let notificationbox = this.getNotificationBox(browser);
this.mPanelContainer.appendChild(notificationbox);
browser.loadURI(BROWSER_NEW_TAB_URL);
browser.docShellIsActive = false;
]]>
</body>
</method>
<method name="_createBrowser">
<parameter name="aParams"/>
<body>
<![CDATA[
const NS_XUL = "http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul";
let remote = aParams && aParams.remote;
let uriIsAboutBlank = aParams && aParams.uriIsAboutBlank;
let isPreloadBrowser = aParams && aParams.isPreloadBrowser;
let b = document.createElementNS(NS_XUL, "browser");
b.setAttribute("type", "content-targetable");
b.setAttribute("message", "true");
b.setAttribute("messagemanagergroup", "browsers");
b.setAttribute("contextmenu", this.getAttribute("contentcontextmenu"));
b.setAttribute("tooltip", this.getAttribute("contenttooltip"));
if (remote)
b.setAttribute("remote", "true");
if (window.gShowPageResizers && window.windowState == window.STATE_NORMAL) {
b.setAttribute("showresizer", "true");
}
if (!isPreloadBrowser && this.hasAttribute("autocompletepopup"))
b.setAttribute("autocompletepopup", this.getAttribute("autocompletepopup"));
if (this.hasAttribute("selectpopup"))
b.setAttribute("selectpopup", this.getAttribute("selectpopup"));
b.setAttribute("autoscrollpopup", this._autoScrollPopup.id);
// Create the browserStack container
var stack = document.createElementNS(NS_XUL, "stack");
stack.className = "browserStack";
stack.appendChild(b);
stack.setAttribute("flex", "1");
// Create the browserContainer
var browserContainer = document.createElementNS(NS_XUL, "vbox");
browserContainer.className = "browserContainer";
browserContainer.appendChild(stack);
browserContainer.setAttribute("flex", "1");
// Create the sidebar container
var browserSidebarContainer = document.createElementNS(NS_XUL,
"hbox");
browserSidebarContainer.className = "browserSidebarContainer";
browserSidebarContainer.appendChild(browserContainer);
browserSidebarContainer.setAttribute("flex", "1");
// Add the Message and the Browser to the box
var notificationbox = document.createElementNS(NS_XUL,
"notificationbox");
notificationbox.setAttribute("flex", "1");
notificationbox.appendChild(browserSidebarContainer);
// Prevent the superfluous initial load of a blank document
// if we're going to load something other than about:blank.
if (!uriIsAboutBlank) {
b.setAttribute("nodefaultsrc", "true");
}
return b;
]]>
</body>
</method>
<method name="addTab">
<parameter name="aURI"/>
<parameter name="aReferrerURI"/>
@ -1583,55 +1711,23 @@
if (aOwner)
t.owner = aOwner;
var b = document.createElementNS(
"http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul",
"browser");
b.setAttribute("type", "content-targetable");
b.setAttribute("message", "true");
b.setAttribute("messagemanagergroup", "browsers");
b.setAttribute("contextmenu", this.getAttribute("contentcontextmenu"));
b.setAttribute("tooltip", this.getAttribute("contenttooltip"));
let b;
let usingPreloadedContent = false;
let isPrivateWindow = PrivateBrowsingUtils.isWindowPrivate(window);
if (remote)
b.setAttribute("remote", "true");
if (window.gShowPageResizers && window.windowState == window.STATE_NORMAL) {
b.setAttribute("showresizer", "true");
// If we open a new tab with the newtab URL,
// check if there is a preloaded browser ready.
if (aURI == BROWSER_NEW_TAB_URL && !isPrivateWindow) {
b = this._getPreloadedBrowser();
usingPreloadedContent = !!b;
}
if (this.hasAttribute("autocompletepopup"))
b.setAttribute("autocompletepopup", this.getAttribute("autocompletepopup"));
if (this.hasAttribute("selectpopup"))
b.setAttribute("selectpopup", this.getAttribute("selectpopup"));
b.setAttribute("autoscrollpopup", this._autoScrollPopup.id);
// Create the browserStack container
var stack = document.createElementNS(NS_XUL, "stack");
stack.className = "browserStack";
stack.appendChild(b);
stack.setAttribute("flex", "1");
// Create the browserContainer
var browserContainer = document.createElementNS(NS_XUL, "vbox");
browserContainer.className = "browserContainer";
browserContainer.appendChild(stack);
browserContainer.setAttribute("flex", "1");
// Create the sidebar container
var browserSidebarContainer = document.createElementNS(NS_XUL,
"hbox");
browserSidebarContainer.className = "browserSidebarContainer";
browserSidebarContainer.appendChild(browserContainer);
browserSidebarContainer.setAttribute("flex", "1");
// Add the Message and the Browser to the box
var notificationbox = document.createElementNS(NS_XUL,
"notificationbox");
notificationbox.setAttribute("flex", "1");
notificationbox.appendChild(browserSidebarContainer);
if (!b) {
// No preloaded browser found, create one.
b = this._createBrowser({remote, uriIsAboutBlank});
}
let notificationbox = this.getNotificationBox(b);
var position = this.tabs.length - 1;
var uniqueId = this._generateUniquePanelID();
notificationbox.id = uniqueId;
@ -1642,19 +1738,16 @@
t.lastAccessed = Date.now();
this.tabContainer._setPositionalAttributes();
// Prevent the superfluous initial load of a blank document
// if we're going to load something other than about:blank.
if (!uriIsAboutBlank) {
b.setAttribute("nodefaultsrc", "true");
// Inject the <browser> into the DOM if necessary.
if (!notificationbox.parentNode) {
// NB: this appendChild call causes us to run constructors for the
// browser element, which fires off a bunch of notifications. Some
// of those notifications can cause code to run that inspects our
// state, so it is important that the tab element is fully
// initialized by this point.
this.mPanelContainer.appendChild(notificationbox);
}
// NB: this appendChild call causes us to run constructors for the
// browser element, which fires off a bunch of notifications. Some
// of those notifications can cause code to run that inspects our
// state, so it is important that the tab element is fully
// initialized by this point.
this.mPanelContainer.appendChild(notificationbox);
// We've waited until the tab is in the DOM to set the label. This
// allows the TabLabelModified event to be properly dispatched.
if (!aURI || isBlankPageURL(aURI)) {
@ -1677,16 +1770,9 @@
b.droppedLinkHandler = handleDroppedLink;
// If we just created a new tab that loads the default
// newtab url, swap in a preloaded page if possible.
// Do nothing if we're a private window.
let docShellsSwapped = false;
if (aURI == BROWSER_NEW_TAB_URL &&
!PrivateBrowsingUtils.isWindowPrivate(window) &&
!gMultiProcessBrowser) {
docShellsSwapped = gBrowserNewTabPreloader.newTab(t);
} else if (aURI == "about:customizing") {
docShellsSwapped = gCustomizationTabPreloader.newTab(t);
// Swap in a preloaded customize tab, if available.
if (aURI == "about:customizing") {
usingPreloadedContent = gCustomizationTabPreloader.newTab(t);
}
// Dispatch a new tab notification. We do this once we're
@ -1698,7 +1784,7 @@
// If we didn't swap docShells with a preloaded browser
// then let's just continue loading the page normally.
if (!docShellsSwapped && !uriIsAboutBlank) {
if (!usingPreloadedContent && !uriIsAboutBlank) {
// pretend the user typed this so it'll be available till
// the document successfully loads
if (aURI && gInitialPages.indexOf(aURI) == -1)
@ -4279,6 +4365,9 @@
// without any scrolling and when the tabbar has already
// overflowed.
this.mTabstrip._updateScrollButtonsDisabledState();
// Preload the next about:newtab if there isn't one already.
this.tabbrowser._createPreloadBrowser();
]]></body>
</method>

View File

@ -2,6 +2,7 @@
* http://creativecommons.org/publicdomain/zero/1.0/ */
const STATE_CHANGED_TOPIC = "fxa-migration:state-changed";
const NOTIFICATION_TITLE = "fxa-migration";
let imports = {};
Cu.import("resource://services-sync/FxaMigrator.jsm", imports);
@ -9,30 +10,42 @@ Cu.import("resource://services-sync/FxaMigrator.jsm", imports);
add_task(function* test() {
// Fake the state where we need an FxA user.
let buttonPromise = promiseButtonMutation();
Services.obs.notifyObservers(null, "fxa-migration:state-changed",
Services.obs.notifyObservers(null, STATE_CHANGED_TOPIC,
fxaMigrator.STATE_USER_FXA);
let buttonState = yield buttonPromise;
assertButtonState(buttonState, "migrate-signup", true);
Assert.ok(Weave.Notifications.notifications.some(n => {
return n.title == NOTIFICATION_TITLE;
}), "Needs-user notification should be present");
// Fake the state where we need a verified FxA user.
buttonPromise = promiseButtonMutation();
let email = Cc["@mozilla.org/supports-string;1"].
createInstance(Ci.nsISupportsString);
email.data = "foo@example.com";
Services.obs.notifyObservers(email, "fxa-migration:state-changed",
Services.obs.notifyObservers(email, STATE_CHANGED_TOPIC,
fxaMigrator.STATE_USER_FXA_VERIFIED);
buttonState = yield buttonPromise;
assertButtonState(buttonState, "migrate-verify", true,
"foo@example.com not verified");
let note = Weave.Notifications.notifications.find(n => {
return n.title == NOTIFICATION_TITLE;
});
Assert.ok(!!note, "Needs-verification notification should be present");
Assert.ok(note.description.contains(email.data),
"Needs-verification notification should include email");
// Fake the state where no migration is needed.
buttonPromise = promiseButtonMutation();
Services.obs.notifyObservers(null, "fxa-migration:state-changed", null);
Services.obs.notifyObservers(null, STATE_CHANGED_TOPIC, null);
buttonState = yield buttonPromise;
// In this case, the front end has called fxAccounts.getSignedInUser() to
// update the button label and status. But since there isn't actually a user,
// the button is left with no fxastatus.
assertButtonState(buttonState, "", true);
Assert.ok(!Weave.Notifications.notifications.some(n => {
return n.title == NOTIFICATION_TITLE;
}), "Migration notifications should no longer be present");
});
function assertButtonState(buttonState, expectedStatus, expectedVisible,

View File

@ -11,7 +11,6 @@ const CAPTURE_PREF = "browser.pagethumbnails.capturing_disabled";
function runTests() {
let imports = {};
Cu.import("resource://gre/modules/PageThumbs.jsm", imports);
Cu.import("resource:///modules/BrowserNewTabPreloader.jsm", imports);
// Disable captures.
let originalDisabledState = Services.prefs.getBoolPref(CAPTURE_PREF);
@ -31,32 +30,15 @@ function runTests() {
yield setLinks("-1");
// We need a handle to a hidden, pre-loaded newtab so we can verify that it
// doesn't allow background captures. Add a newtab, which triggers creation
// of a hidden newtab, and then keep calling BrowserNewTabPreloader.newTab
// until it returns true, meaning that it swapped the passed-in tab's docshell
// for the hidden newtab docshell.
let tab = gWindow.gBrowser.addTab("about:blank");
yield addNewTabPageTab();
// doesn't allow background captures. Ensure we have a preloaded browser.
gBrowser._createPreloadBrowser();
// When newtab is loaded very quickly (which is what happens in 99% of cases)
// there is no need to wait so no tests are run. Because each test requires
// either a pass, fail or todo we run a dummy test here.
ok(true, "Each test requires at least one pass, fail or todo so here is a pass.");
// Wait for the preloaded browser to load.
yield waitForBrowserLoad(gBrowser._preloadedBrowser);
let swapWaitCount = 0;
let swapped = imports.BrowserNewTabPreloader.newTab(tab);
while (!swapped) {
if (++swapWaitCount == 10) {
ok(false, "Timed out waiting for newtab docshell swap.");
return;
}
// Give the hidden newtab some time to finish loading.
yield wait(2000);
info("Checking newtab swap " + swapWaitCount);
swapped = imports.BrowserNewTabPreloader.newTab(tab);
}
// The tab's docshell is now the previously hidden newtab docshell.
// We're now ready to use the preloaded browser.
BrowserOpenTab();
let tab = gBrowser.selectedTab;
let doc = tab.linkedBrowser.contentDocument;
// Enable captures.
@ -67,8 +49,11 @@ function runTests() {
if (data != url)
return;
Services.obs.removeObserver(onCreate, "page-thumbnail:create");
ok(true, "thumbnail created after preloaded tab was shown");
// Test finished!
Services.prefs.setBoolPref(CAPTURE_PREF, originalDisabledState);
gBrowser.removeTab(tab);
file.remove(false);
TestRunner.next();
}, "page-thumbnail:create", false);
@ -76,7 +61,3 @@ function runTests() {
info("Waiting for thumbnail capture");
yield true;
}
function wait(ms) {
setTimeout(TestRunner.next, ms);
}

View File

@ -374,21 +374,27 @@ function addNewTabPageTabPromise() {
}
}
// The new tab page might have been preloaded in the background.
if (browser.contentDocument.readyState == "complete") {
waitForCondition(() => !browser.contentDocument.hidden).then(whenNewTabLoaded);
return deferred.promise;
}
// Wait for the new tab page to be loaded.
browser.addEventListener("load", function onLoad() {
browser.removeEventListener("load", onLoad, true);
whenNewTabLoaded();
}, true);
waitForBrowserLoad(browser, function () {
// Wait for the document to become visible in case it was preloaded.
waitForCondition(() => !browser.contentDocument.hidden).then(whenNewTabLoaded);
});
return deferred.promise;
}
function waitForBrowserLoad(browser, callback = TestRunner.next) {
if (browser.contentDocument.readyState == "complete") {
executeSoon(callback);
return;
}
browser.addEventListener("load", function onLoad() {
browser.removeEventListener("load", onLoad, true);
executeSoon(callback);
}, true);
}
/**
* Compares the current grid arrangement with the given pattern.
* @param the pattern (see below)

View File

@ -828,9 +828,15 @@ let MozLoopServiceInternal = {
let window = chatbox.contentWindow;
window.addEventListener("unload", function onUnloadChat(evt) {
UITour.notify("Loop:ChatWindowClosed");
});
function socialFrameChanged(eventName) {
UITour.availableTargetsCache.clear();
UITour.notify(eventName);
}
window.addEventListener("socialFrameHide", socialFrameChanged.bind(null, "Loop:ChatWindowHidden"));
window.addEventListener("socialFrameShow", socialFrameChanged.bind(null, "Loop:ChatWindowShown"));
window.addEventListener("socialFrameDetached", socialFrameChanged.bind(null, "Loop:ChatWindowDetached"));
window.addEventListener("unload", socialFrameChanged.bind(null, "Loop:ChatWindowClosed"));
injectLoopAPI(window);

View File

@ -53,9 +53,6 @@ XPCOMUtils.defineLazyModuleGetter(this, "PageThumbs",
XPCOMUtils.defineLazyModuleGetter(this, "NewTabUtils",
"resource://gre/modules/NewTabUtils.jsm");
XPCOMUtils.defineLazyModuleGetter(this, "BrowserNewTabPreloader",
"resource:///modules/BrowserNewTabPreloader.jsm");
XPCOMUtils.defineLazyModuleGetter(this, "CustomizationTabPreloader",
"resource:///modules/CustomizationTabPreloader.jsm");
@ -791,7 +788,6 @@ BrowserGlue.prototype = {
Cu.reportError("Could not end startup crash tracking in quit-application-granted: " + e);
}
BrowserNewTabPreloader.uninit();
CustomizationTabPreloader.uninit();
WebappManager.uninit();
#ifdef NIGHTLY_BUILD

View File

@ -1,7 +1,19 @@
# LOCALIZATION NOTE (needUser)
# %S = Firefox Accounts brand name from syncBrand.dtd
needUser = %S required for sync
# 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/.
# LOCALIZATION NOTE (needVerifiedUser)
# LOCALIZATION NOTE (needUserShort)
# %S = Firefox Accounts brand name from syncBrand.dtd
needUserShort = %S required for sync
needUserLong = We've rebuilt Sync to make it easier for everyone. Please upgrade to a Firefox Account to continue syncing.
upgradeToFxA.label = Upgrade
upgradeToFxA.accessKey = U
# LOCALIZATION NOTE (needVerifiedUserShort, needVerifiedUserLong)
# %S = Email address of user's Firefox Account
needVerifiedUser = %S not verified
needVerifiedUserShort = %S not verified
needVerifiedUserLong = Please click the verification link in the email sent to %S
resendVerificationEmail.label = Resend
resendVerificationEmail.accessKey = R

View File

@ -1,379 +0,0 @@
/* 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/. */
"use strict";
this.EXPORTED_SYMBOLS = ["BrowserNewTabPreloader"];
const Cu = Components.utils;
const Cc = Components.classes;
const Ci = Components.interfaces;
Cu.import("resource://gre/modules/Services.jsm");
Cu.import("resource://gre/modules/XPCOMUtils.jsm");
Cu.import("resource://gre/modules/Promise.jsm");
const HTML_NS = "http://www.w3.org/1999/xhtml";
const XUL_NS = "http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul";
const XUL_PAGE = "data:application/vnd.mozilla.xul+xml;charset=utf-8,<window%20id='win'/>";
const NEWTAB_URL = "about:newtab";
const PREF_NEWTAB_URL = "browser.newtab.url";
const PREF_NEWTAB_PRELOAD = "browser.newtab.preload";
// The interval between swapping in a preload docShell and kicking off the
// next preload in the background.
const PRELOADER_INTERVAL_MS = 600;
// The number of miliseconds we'll wait after we received a notification that
// causes us to update our list of browsers and tabbrowser sizes. This acts as
// kind of a damper when too many events are occuring in quick succession.
const PRELOADER_UPDATE_DELAY_MS = 3000;
const TOPIC_TIMER_CALLBACK = "timer-callback";
const TOPIC_DELAYED_STARTUP = "browser-delayed-startup-finished";
const TOPIC_XUL_WINDOW_CLOSED = "xul-window-destroyed";
const BROWSER_CONTENT_SCRIPT = "chrome://browser/content/content.js";
function isPreloadingEnabled() {
return Services.prefs.getBoolPref(PREF_NEWTAB_PRELOAD) &&
!Services.prefs.prefHasUserValue(PREF_NEWTAB_URL);
}
function createTimer(obj, delay) {
let timer = Cc["@mozilla.org/timer;1"].createInstance(Ci.nsITimer);
timer.init(obj, delay, Ci.nsITimer.TYPE_ONE_SHOT);
return timer;
}
function clearTimer(timer) {
if (timer) {
timer.cancel();
}
return null;
}
this.BrowserNewTabPreloader = {
uninit: function Preloader_uninit() {
HostFrame.destroy();
HiddenBrowsers.uninit();
},
newTab: function Preloader_newTab(aTab) {
if (!isPreloadingEnabled()) {
return false;
}
let win = aTab.ownerDocument.defaultView;
if (win.gBrowser) {
let utils = win.QueryInterface(Ci.nsIInterfaceRequestor)
.getInterface(Ci.nsIDOMWindowUtils);
let {width, height} = utils.getBoundsWithoutFlushing(win.gBrowser);
let hiddenBrowser = HiddenBrowsers.get(width, height)
if (hiddenBrowser) {
return hiddenBrowser.swapWithNewTab(aTab);
}
}
return false;
}
};
Object.freeze(BrowserNewTabPreloader);
let HiddenBrowsers = {
_browsers: null,
_updateTimer: null,
_topics: [
TOPIC_DELAYED_STARTUP,
TOPIC_XUL_WINDOW_CLOSED
],
_init: function () {
this._browsers = new Map();
this._updateBrowserSizes();
this._topics.forEach(t => Services.obs.addObserver(this, t, false));
},
uninit: function () {
if (this._browsers) {
this._topics.forEach(t => Services.obs.removeObserver(this, t, false));
this._updateTimer = clearTimer(this._updateTimer);
for (let [key, browser] of this._browsers) {
browser.destroy();
}
this._browsers = null;
}
},
get: function (width, height) {
// Initialize if this is the first call.
if (!this._browsers) {
this._init();
}
let key = width + "x" + height;
if (!this._browsers.has(key)) {
// Update all browsers' sizes if we can't find a matching one.
this._updateBrowserSizes();
}
// We should now have a matching browser.
if (this._browsers.has(key)) {
return this._browsers.get(key);
}
// We should never be here. Return the first browser we find.
Cu.reportError("NewTabPreloader: no matching browser found after updating");
for (let [size, browser] of this._browsers) {
return browser;
}
// We should really never be here.
Cu.reportError("NewTabPreloader: not even a single browser was found?");
return null;
},
observe: function (subject, topic, data) {
if (topic === TOPIC_TIMER_CALLBACK) {
this._updateTimer = null;
this._updateBrowserSizes();
} else {
this._updateTimer = clearTimer(this._updateTimer);
this._updateTimer = createTimer(this, PRELOADER_UPDATE_DELAY_MS);
}
},
_updateBrowserSizes: function () {
let sizes = this._collectTabBrowserSizes();
let toRemove = [];
// Iterate all browsers and check that they
// each can be assigned to one of the sizes.
for (let [key, browser] of this._browsers) {
if (sizes.has(key)) {
// We already have a browser for that size, great!
sizes.delete(key);
} else {
// This browser is superfluous or needs to be resized.
toRemove.push(browser);
this._browsers.delete(key);
}
}
// Iterate all sizes that we couldn't find a browser for.
for (let [key, {width, height}] of sizes) {
let browser;
if (toRemove.length) {
// Let's just resize one of the superfluous
// browsers and put it back into the map.
browser = toRemove.shift();
browser.resize(width, height);
} else {
// No more browsers to reuse, create a new one.
browser = new HiddenBrowser(width, height);
}
this._browsers.set(key, browser);
}
// Finally, remove all browsers we don't need anymore.
toRemove.forEach(b => b.destroy());
},
_collectTabBrowserSizes: function () {
let sizes = new Map();
function tabBrowserBounds() {
let wins = Services.ww.getWindowEnumerator("navigator:browser");
while (wins.hasMoreElements()) {
let win = wins.getNext();
if (win.gBrowser) {
let utils = win.QueryInterface(Ci.nsIInterfaceRequestor)
.getInterface(Ci.nsIDOMWindowUtils);
yield utils.getBoundsWithoutFlushing(win.gBrowser);
}
}
}
// Collect the sizes of all <tabbrowser>s out there.
for (let {width, height} of tabBrowserBounds()) {
if (width > 0 && height > 0) {
let key = width + "x" + height;
if (!sizes.has(key)) {
sizes.set(key, {width: width, height: height});
}
}
}
return sizes;
}
};
function HiddenBrowser(width, height) {
this.resize(width, height);
this._createBrowser();
}
HiddenBrowser.prototype = {
_width: null,
_height: null,
_timer: null,
get isPreloaded() {
return this._browser &&
this._browser.contentDocument &&
this._browser.contentDocument.readyState === "complete" &&
this._browser.currentURI.spec === NEWTAB_URL;
},
swapWithNewTab: function (aTab) {
if (!this.isPreloaded || this._timer) {
return false;
}
let win = aTab.ownerDocument.defaultView;
let tabbrowser = win.gBrowser;
if (!tabbrowser) {
return false;
}
// Swap docShells.
tabbrowser.swapNewTabWithBrowser(aTab, this._browser);
// Load all delayed frame scripts attached to the "browers" message manager.
// The browser content script was already loaded, so don't load it again.
let mm = aTab.linkedBrowser.messageManager;
let scripts = win.getGroupMessageManager("browsers").getDelayedFrameScripts();
Array.forEach(scripts, ([script, runGlobal]) => {
if (script != BROWSER_CONTENT_SCRIPT) {
mm.loadFrameScript(script, true, runGlobal);
}
});
// Remove the browser, it will be recreated by a timer.
this._removeBrowser();
// Start a timer that will kick off preloading the next newtab page.
this._timer = createTimer(this, PRELOADER_INTERVAL_MS);
// Signal that we swapped docShells.
return true;
},
observe: function () {
this._timer = null;
// Start pre-loading the new tab page.
this._createBrowser();
},
resize: function (width, height) {
this._width = width;
this._height = height;
this._applySize();
},
destroy: function () {
this._removeBrowser();
this._timer = clearTimer(this._timer);
},
_applySize: function () {
if (this._browser) {
this._browser.style.width = this._width + "px";
this._browser.style.height = this._height + "px";
}
},
_createBrowser: function () {
HostFrame.get().then(aFrame => {
let doc = aFrame.document;
this._browser = doc.createElementNS(XUL_NS, "browser");
this._browser.setAttribute("type", "content");
this._browser.setAttribute("src", NEWTAB_URL);
this._applySize();
doc.getElementById("win").appendChild(this._browser);
// The browser might not have a docShell here if the HostFrame was
// destroyed while the promise was resolved. Simply bail out.
if (!this._browser.docShell) {
return;
}
// Let the docShell be inactive so that document.hidden=true.
this._browser.docShell.isActive = false;
this._browser.messageManager.loadFrameScript(BROWSER_CONTENT_SCRIPT,
true);
});
},
_removeBrowser: function () {
if (this._browser) {
this._browser.remove();
this._browser = null;
}
}
};
let HostFrame = {
_frame: null,
_deferred: null,
get hiddenDOMDocument() {
return Services.appShell.hiddenDOMWindow.document;
},
get isReady() {
return this.hiddenDOMDocument.readyState === "complete";
},
get: function () {
if (!this._deferred) {
this._deferred = Promise.defer();
this._create();
}
return this._deferred.promise;
},
destroy: function () {
if (this._frame) {
if (!Cu.isDeadWrapper(this._frame)) {
this._frame.removeEventListener("load", this, true);
this._frame.remove();
}
this._frame = null;
this._deferred = null;
}
},
handleEvent: function () {
let contentWindow = this._frame.contentWindow;
if (contentWindow.location.href === XUL_PAGE) {
this._frame.removeEventListener("load", this, true);
this._deferred.resolve(contentWindow);
} else {
contentWindow.location = XUL_PAGE;
}
},
_create: function () {
if (this.isReady) {
let doc = this.hiddenDOMDocument;
this._frame = doc.createElementNS(HTML_NS, "iframe");
this._frame.addEventListener("load", this, true);
doc.documentElement.appendChild(this._frame);
} else {
let flags = Ci.nsIThread.DISPATCH_NORMAL;
Services.tm.currentThread.dispatch(() => this._create(), flags);
}
}
};

View File

@ -142,6 +142,16 @@ this.UITour = {
return loopBrowser.contentDocument.querySelector(".room-list");
},
}],
["loop-selectedRoomButtons", {
infoPanelPosition: "leftcenter bottomright",
query: (aDocument) => {
let chatbox = aDocument.querySelector("chatbox[src^='about\:loopconversation'][selected]");
if (!chatbox || !chatbox.contentDocument) {
return null;
}
return chatbox.contentDocument.querySelector(".call-action-group");
},
}],
["loop-signInUpLink", {
query: (aDocument) => {
let loopBrowser = aDocument.querySelector("#loop-notification-panel > #loop");
@ -1375,8 +1385,7 @@ this.UITour = {
hideLoopPanelAnnotations: function(aEvent) {
UITour.hideAnnotationsForPanel(aEvent, (aTarget) => {
// TODO: Bug 1104927 - Handle the conversation targets separately.
return aTarget.targetName.startsWith("loop-");
return aTarget.targetName.startsWith("loop-") && aTarget.targetName != "loop-selectedRoomButtons";
});
},

View File

@ -11,7 +11,6 @@ XPCSHELL_TESTS_MANIFESTS += [
]
EXTRA_JS_MODULES += [
'BrowserNewTabPreloader.jsm',
'BrowserUITelemetry.jsm',
'CastingApps.jsm',
'Chat.jsm',

View File

@ -90,9 +90,12 @@ let tests = [
gContentAPI.observe((event, params) => {
is(event, "Loop:ChatWindowOpened", "Check Loop:ChatWindowOpened notification");
gContentAPI.observe((event, params) => {
is(event, "Loop:ChatWindowClosed", "Check Loop:ChatWindowClosed notification");
is(event, "Loop:ChatWindowShown", "Check Loop:ChatWindowShown notification");
gContentAPI.observe((event, params) => {
ok(false, "No more notifications should have arrived");
is(event, "Loop:ChatWindowClosed", "Check Loop:ChatWindowClosed notification");
gContentAPI.observe((event, params) => {
ok(false, "No more notifications should have arrived");
});
});
done();
});

View File

@ -1345,6 +1345,11 @@ nsDocShell::LoadURI(nsIURI * aURI,
if (!IsNavigationAllowed(true, false)) {
return NS_OK; // JS may not handle returning of an error code
}
if (DoAppRedirectIfNeeded(aURI, aLoadInfo, aFirstParty)) {
return NS_OK;
}
nsCOMPtr<nsIURI> referrer;
nsCOMPtr<nsIInputStream> postStream;
nsCOMPtr<nsIInputStream> headersStream;
@ -6586,10 +6591,6 @@ nsDocShell::ForceRefreshURI(nsIURI * aURI,
loadInfo->SetLoadType(nsIDocShellLoadInfo::loadRefresh);
}
if (DoAppRedirectIfNeeded(aURI, loadInfo, true)) {
return NS_OK;
}
/*
* LoadURI(...) will cancel all refresh timers... This causes the
* Timer and its refreshData instance to be released...

View File

@ -135,7 +135,7 @@ public class OverlayActionService extends Service {
OverlayToastHelper.showFailureToast(getApplicationContext(), shareMethod.getFailureMessage());
break;
default:
Assert.isTrue(false, "Unknown share method result code: " + result);
Assert.fail("Unknown share method result code: " + result);
break;
}
}

View File

@ -163,7 +163,7 @@ public class SendTabDeviceListArrayAdapter extends ArrayAdapter<ParcelableClient
showDummyRecord(getContext().getResources().getString(R.string.overlay_share_send_other));
break;
default:
Assert.isTrue(false, "Unexpected state transition: " + newState);
Assert.fail("Unexpected state transition: " + newState);
}
}

View File

@ -48,18 +48,15 @@ public final class Prefs {
}
}
/* Prefs must be created on application startup or service startup.
* TODO: turn into regular singleton if Context dependency can be removed. */
public static void createGlobalInstance(Context c) {
if (sInstance != null) {
return;
public static Prefs getInstance(Context c) {
if (sInstance == null) {
sInstance = new Prefs(c);
}
sInstance = new Prefs(c);
return sInstance;
}
/* Only access after CreatePrefsInstance(Context) has been called at startup. */
public static Prefs getInstance() {
assert(sInstance != null);
// Allows code without a context handle to grab the prefs. The caller must null check the return value.
public static Prefs getInstanceWithoutContext() {
return sInstance;
}

View File

@ -4,6 +4,7 @@
package org.mozilla.mozstumbler.service.stumblerthread;
import android.content.Context;
import android.content.Intent;
import android.location.Location;
import android.os.AsyncTask;
@ -16,7 +17,6 @@ import org.mozilla.mozstumbler.service.Prefs;
import org.mozilla.mozstumbler.service.stumblerthread.blocklist.WifiBlockListInterface;
import org.mozilla.mozstumbler.service.stumblerthread.datahandling.DataStorageManager;
import org.mozilla.mozstumbler.service.stumblerthread.scanners.ScanManager;
import org.mozilla.mozstumbler.service.stumblerthread.scanners.cellscanner.CellScanner;
import org.mozilla.mozstumbler.service.uploadthread.UploadAlarmReceiver;
import org.mozilla.mozstumbler.service.utils.NetworkUtils;
import org.mozilla.mozstumbler.service.utils.PersistentIntentService;
@ -68,8 +68,8 @@ public class StumblerService extends PersistentIntentService
mScanManager.setWifiBlockList(list);
}
public Prefs getPrefs() {
return Prefs.getInstance();
public Prefs getPrefs(Context c) {
return Prefs.getInstance(c);
}
public void checkPrefs() {
@ -116,7 +116,8 @@ public class StumblerService extends PersistentIntentService
// use (i.e. Fennec), init() can be called from this class's dedicated thread.
// Safe to call more than once, ensure added code complies with that intent.
protected void init() {
Prefs.createGlobalInstance(this);
// Ensure Prefs is created, so internal utility code can use getInstanceWithoutContext
Prefs.getInstance(this);
NetworkUtils.createGlobalInstance(this);
DataStorageManager.createGlobalInstance(this, this);
@ -150,7 +151,7 @@ public class StumblerService extends PersistentIntentService
}
if (!sFirefoxStumblingEnabled.get()) {
Prefs.getInstance().setFirefoxScanEnabled(false);
Prefs.getInstance(StumblerService.this).setFirefoxScanEnabled(false);
}
if (DataStorageManager.getInstance() != null) {
@ -182,7 +183,7 @@ public class StumblerService extends PersistentIntentService
return;
}
final boolean isScanEnabledInPrefs = Prefs.getInstance().getFirefoxScanEnabled();
final boolean isScanEnabledInPrefs = Prefs.getInstance(this).getFirefoxScanEnabled();
if (!isScanEnabledInPrefs && intent.getBooleanExtra(ACTION_NOT_FROM_HOST_APP, false)) {
stopSelf();
@ -198,7 +199,7 @@ public class StumblerService extends PersistentIntentService
// This is the only upload trigger in Firefox mode
// Firefox triggers this ~4 seconds after startup (after Gecko is loaded), add a small delay to avoid
// clustering with other operations that are triggered at this time.
final long lastAttemptedTime = Prefs.getInstance().getLastAttemptedUploadTime();
final long lastAttemptedTime = Prefs.getInstance(this).getLastAttemptedUploadTime();
final long timeNow = System.currentTimeMillis();
if (timeNow - lastAttemptedTime < PASSIVE_UPLOAD_FREQ_GUARD_MSEC) {
@ -207,23 +208,23 @@ public class StumblerService extends PersistentIntentService
Log.d(LOG_TAG, "Upload attempt too frequent.");
}
} else {
Prefs.getInstance().setLastAttemptedUploadTime(timeNow);
Prefs.getInstance(this).setLastAttemptedUploadTime(timeNow);
UploadAlarmReceiver.scheduleAlarm(this, DELAY_IN_SEC_BEFORE_STARTING_UPLOAD_IN_PASSIVE_MODE, false /* no repeat*/);
}
}
if (!isScanEnabledInPrefs) {
Prefs.getInstance().setFirefoxScanEnabled(true);
Prefs.getInstance(this).setFirefoxScanEnabled(true);
}
String apiKey = intent.getStringExtra(ACTION_EXTRA_MOZ_API_KEY);
if (apiKey != null && !apiKey.equals(Prefs.getInstance().getMozApiKey())) {
Prefs.getInstance().setMozApiKey(apiKey);
if (apiKey != null && !apiKey.equals(Prefs.getInstance(this).getMozApiKey())) {
Prefs.getInstance(this).setMozApiKey(apiKey);
}
String userAgent = intent.getStringExtra(ACTION_EXTRA_USER_AGENT);
if (userAgent != null && !userAgent.equals(Prefs.getInstance().getUserAgent())) {
Prefs.getInstance().setUserAgent(userAgent);
if (userAgent != null && !userAgent.equals(Prefs.getInstance(this).getUserAgent())) {
Prefs.getInstance(this).setUserAgent(userAgent);
}
if (!mScanManager.isScanning()) {

View File

@ -164,7 +164,11 @@ public class GPSScanner implements LocationListener {
mBlockList.updateBlocks();
}
mAutoGeofencing = Prefs.getInstance().getGeofenceHere();
Prefs prefs = Prefs.getInstanceWithoutContext();
if (prefs == null) {
return;
}
mAutoGeofencing = prefs.getGeofenceHere();
}
public boolean isGeofenced() {
@ -186,7 +190,7 @@ public class GPSScanner implements LocationListener {
String provider = location.getProvider();
if (!provider.toLowerCase().contains("gps")) {
sendToLogActivity(logMsg + "Discard fused/network location.");
Log.d(LOG_TAG, "Discard fused/network location.");
// only interested in GPS locations
return;
}

View File

@ -28,8 +28,12 @@ public final class LocationBlockList {
}
public void updateBlocks() {
mBlockedLocation = Prefs.getInstance().getGeofenceLocation();
mGeofencingEnabled = Prefs.getInstance().getGeofenceEnabled();
Prefs prefs = Prefs.getInstanceWithoutContext();
if (prefs == null) {
return;
}
mBlockedLocation = prefs.getGeofenceLocation();
mGeofencingEnabled = prefs.getGeofenceEnabled();
}
public boolean contains(Location location) {

View File

@ -74,12 +74,13 @@ public class WifiScanner extends BroadcastReceiver {
public synchronized void start(final ActiveOrPassiveStumbling stumblingMode) {
if (mStarted) {
Prefs prefs = Prefs.getInstanceWithoutContext();
if (mStarted || prefs == null) {
return;
}
mStarted = true;
boolean scanAlways = Prefs.getInstance().getWifiScanAlways();
boolean scanAlways = prefs.getWifiScanAlways();
if (scanAlways || isWifiEnabled()) {
activatePeriodicScan(stumblingMode);

View File

@ -112,10 +112,6 @@ public class AsyncUploader extends AsyncTask<Void, Void, SyncSummary> {
private class Submitter extends AbstractCommunicator {
private static final String SUBMIT_URL = "https://location.services.mozilla.com/v1/submit";
public Submitter() {
super(Prefs.getInstance().getUserAgent());
}
@Override
public String getUrlString() {
return SUBMIT_URL;

View File

@ -48,7 +48,8 @@ public class UploadAlarmReceiver extends BroadcastReceiver {
@Override
protected void onHandleIntent(Intent intent) {
boolean isRepeating = intent.getBooleanExtra(EXTRA_IS_REPEATING, true);
// Default to a repeating alarm, which is what Fennec Stumbler uses
boolean isRepeating = (intent == null)? true : intent.getBooleanExtra(EXTRA_IS_REPEATING, true);
if (DataStorageManager.getInstance() == null) {
DataStorageManager.createGlobalInstance(this, null);
}
@ -77,9 +78,9 @@ public class UploadAlarmReceiver extends BroadcastReceiver {
!AsyncUploader.isUploading()) {
Log.d(LOG_TAG, "Alarm upload(), call AsyncUploader");
AsyncUploader.UploadSettings settings =
new AsyncUploader.UploadSettings(Prefs.getInstance().getWifiScanAlways(), Prefs.getInstance().getUseWifiOnly());
new AsyncUploader.UploadSettings(Prefs.getInstance(this).getWifiScanAlways(), Prefs.getInstance(this).getUseWifiOnly());
AsyncUploader uploader = new AsyncUploader(settings, null);
uploader.setNickname(Prefs.getInstance().getNickname());
uploader.setNickname(Prefs.getInstance(this).getNickname());
uploader.execute();
// we could listen for completion and cancel, instead, cancel on next alarm when db empty
}

View File

@ -61,14 +61,16 @@ public abstract class AbstractCommunicator {
return null;
}
public AbstractCommunicator(String userAgent) {
mUserAgent = userAgent;
public AbstractCommunicator() {
Prefs prefs = Prefs.getInstanceWithoutContext();
mUserAgent = (prefs != null)? prefs.getUserAgent() : "fennec-stumbler-unset-user-agent";
}
private void openConnectionAndSetHeaders() {
try {
if (sMozApiKey == null) {
sMozApiKey = Prefs.getInstance().getMozApiKey();
Prefs prefs = Prefs.getInstanceWithoutContext();
if (sMozApiKey == null || prefs != null) {
sMozApiKey = prefs.getMozApiKey();
}
URL url = new URL(getUrlString() + "?key=" + sMozApiKey);
mHttpURLConnection = (HttpURLConnection) url.openConnection();

View File

@ -15,9 +15,6 @@ Cu.import("resource://gre/modules/Task.jsm");
XPCOMUtils.defineLazyModuleGetter(this, "Services",
"resource://gre/modules/Services.jsm");
XPCOMUtils.defineLazyModuleGetter(this, "BrowserNewTabPreloader",
"resource:///modules/BrowserNewTabPreloader.jsm");
XPCOMUtils.defineLazyModuleGetter(this, "CustomizationTabPreloader",
"resource:///modules/CustomizationTabPreloader.jsm");
@ -504,7 +501,13 @@ Tester.prototype = {
Cu.import("resource://gre/modules/BackgroundPageThumbs.jsm", {});
BackgroundPageThumbs._destroy();
BrowserNewTabPreloader.uninit();
// Destroy preloaded browsers.
if (gBrowser._preloadedBrowser) {
let browser = gBrowser._preloadedBrowser;
gBrowser._preloadedBrowser = null;
gBrowser.getNotificationBox(browser).remove();
}
CustomizationTabPreloader.uninit();
SocialFlyout.unload();
SocialShare.uninit();

View File

@ -684,16 +684,15 @@ AutoRefreshHighlighter.prototype = {
_startRefreshLoop: function() {
let win = this.currentNode.ownerDocument.defaultView;
this.rafID = win.requestAnimationFrame(this._startRefreshLoop.bind(this));
this.rafWin = win;
this.update();
},
_stopRefreshLoop: function() {
if (!this.rafID) {
return;
if (this.rafID && !Cu.isDeadWrapper(this.rafWin)) {
this.rafWin.cancelAnimationFrame(this.rafID);
}
let win = this.currentNode.ownerDocument.defaultView;
win.cancelAnimationFrame(this.rafID);
this.rafID = null;
this.rafID = this.rafWin = null;
},
destroy: function() {