Merge m-c to m-i

This commit is contained in:
Phil Ringnalda 2015-02-22 15:17:42 -08:00
commit af3d786890
26 changed files with 671 additions and 29 deletions

View File

@ -15,6 +15,25 @@
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>
@ -174,6 +193,12 @@
var accTree = {
role: ROLE_APP_ROOT,
children: [
{
role: ROLE_CHROME_WINDOW
},
{
role: ROLE_CHROME_WINDOW
},
{
role: ROLE_CHROME_WINDOW
},

View File

@ -15,7 +15,7 @@
<project name="platform_build" path="build" remote="b2g" revision="ef937d1aca7c4cf89ecb5cc43ae8c21c2000a9db">
<copyfile dest="Makefile" src="core/root.mk"/>
</project>
<project name="gaia" path="gaia" remote="mozillaorg" revision="76f26cf0e552d972c9822657f0b72e78842b6582"/>
<project name="gaia" path="gaia" remote="mozillaorg" revision="a6881205deae450757a8d1e1ed65e5e5be0ec633"/>
<project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="3905180d9e2dbe03d7ce3b3a6debe4d4adc938d1"/>
<project name="librecovery" path="librecovery" remote="b2g" revision="1b3591a50ed352fc6ddb77462b7b35d0bfa555a3"/>

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="76f26cf0e552d972c9822657f0b72e78842b6582"/>
<project name="gaia.git" path="gaia" remote="mozillaorg" revision="a6881205deae450757a8d1e1ed65e5e5be0ec633"/>
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="3905180d9e2dbe03d7ce3b3a6debe4d4adc938d1"/>
<project name="rilproxy" path="rilproxy" remote="b2g" revision="5ef30994f4778b4052e58a4383dbe7890048c87e"/>
<project name="platform_hardware_ril" path="hardware/ril" remote="b2g" revision="93f9ba577f68d772093987c2f1c0a4ae293e1802"/>

View File

@ -17,7 +17,7 @@
</project>
<project name="rilproxy" path="rilproxy" remote="b2g" revision="5ef30994f4778b4052e58a4383dbe7890048c87e"/>
<project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
<project name="gaia" path="gaia" remote="mozillaorg" revision="76f26cf0e552d972c9822657f0b72e78842b6582"/>
<project name="gaia" path="gaia" remote="mozillaorg" revision="a6881205deae450757a8d1e1ed65e5e5be0ec633"/>
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="3905180d9e2dbe03d7ce3b3a6debe4d4adc938d1"/>
<project name="moztt" path="external/moztt" remote="b2g" revision="c42985975f2bbc42859b9136ed348186d989b93d"/>
<project name="apitrace" path="external/apitrace" remote="apitrace" revision="a1ddea3133e0807350326cee5dcf0d06fad00c08"/>

View File

@ -15,7 +15,7 @@
<project name="platform_build" path="build" remote="b2g" revision="ef937d1aca7c4cf89ecb5cc43ae8c21c2000a9db">
<copyfile dest="Makefile" src="core/root.mk"/>
</project>
<project name="gaia" path="gaia" remote="mozillaorg" revision="76f26cf0e552d972c9822657f0b72e78842b6582"/>
<project name="gaia" path="gaia" remote="mozillaorg" revision="a6881205deae450757a8d1e1ed65e5e5be0ec633"/>
<project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="3905180d9e2dbe03d7ce3b3a6debe4d4adc938d1"/>
<project name="librecovery" path="librecovery" remote="b2g" revision="1b3591a50ed352fc6ddb77462b7b35d0bfa555a3"/>

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="76f26cf0e552d972c9822657f0b72e78842b6582"/>
<project name="gaia.git" path="gaia" remote="mozillaorg" revision="a6881205deae450757a8d1e1ed65e5e5be0ec633"/>
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="3905180d9e2dbe03d7ce3b3a6debe4d4adc938d1"/>
<project name="rilproxy" path="rilproxy" remote="b2g" revision="5ef30994f4778b4052e58a4383dbe7890048c87e"/>
<project name="platform_hardware_ril" path="hardware/ril" remote="b2g" revision="93f9ba577f68d772093987c2f1c0a4ae293e1802"/>

View File

@ -15,7 +15,7 @@
<project name="platform_build" path="build" remote="b2g" revision="ef937d1aca7c4cf89ecb5cc43ae8c21c2000a9db">
<copyfile dest="Makefile" src="core/root.mk"/>
</project>
<project name="gaia" path="gaia" remote="mozillaorg" revision="76f26cf0e552d972c9822657f0b72e78842b6582"/>
<project name="gaia" path="gaia" remote="mozillaorg" revision="a6881205deae450757a8d1e1ed65e5e5be0ec633"/>
<project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="3905180d9e2dbe03d7ce3b3a6debe4d4adc938d1"/>
<project name="librecovery" path="librecovery" remote="b2g" revision="1b3591a50ed352fc6ddb77462b7b35d0bfa555a3"/>

View File

@ -17,7 +17,7 @@
</project>
<project name="librecovery" path="librecovery" remote="b2g" revision="1b3591a50ed352fc6ddb77462b7b35d0bfa555a3"/>
<project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
<project name="gaia" path="gaia" remote="mozillaorg" revision="76f26cf0e552d972c9822657f0b72e78842b6582"/>
<project name="gaia" path="gaia" remote="mozillaorg" revision="a6881205deae450757a8d1e1ed65e5e5be0ec633"/>
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="3905180d9e2dbe03d7ce3b3a6debe4d4adc938d1"/>
<project name="moztt" path="external/moztt" remote="b2g" revision="c42985975f2bbc42859b9136ed348186d989b93d"/>
<project name="apitrace" path="external/apitrace" remote="apitrace" revision="a1ddea3133e0807350326cee5dcf0d06fad00c08"/>

View File

@ -1,9 +1,9 @@
{
"git": {
"git_revision": "76f26cf0e552d972c9822657f0b72e78842b6582",
"git_revision": "a6881205deae450757a8d1e1ed65e5e5be0ec633",
"remote": "https://git.mozilla.org/releases/gaia.git",
"branch": ""
},
"revision": "8cbe026f420c66f7ea675c1b1cff6e39435f5a93",
"revision": "1438a6024d8aeb50a5a93a3844127908dc94acef",
"repo_path": "integration/gaia-central"
}

View File

@ -17,7 +17,7 @@
</project>
<project name="rilproxy" path="rilproxy" remote="b2g" revision="5ef30994f4778b4052e58a4383dbe7890048c87e"/>
<project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
<project name="gaia" path="gaia" remote="mozillaorg" revision="76f26cf0e552d972c9822657f0b72e78842b6582"/>
<project name="gaia" path="gaia" remote="mozillaorg" revision="a6881205deae450757a8d1e1ed65e5e5be0ec633"/>
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="3905180d9e2dbe03d7ce3b3a6debe4d4adc938d1"/>
<project name="moztt" path="external/moztt" remote="b2g" revision="c42985975f2bbc42859b9136ed348186d989b93d"/>
<project name="apitrace" path="external/apitrace" remote="apitrace" revision="a1ddea3133e0807350326cee5dcf0d06fad00c08"/>

View File

@ -15,7 +15,7 @@
<project name="platform_build" path="build" remote="b2g" revision="52775e03a2d8532429dff579cb2cd56718e488c3">
<copyfile dest="Makefile" src="core/root.mk"/>
</project>
<project name="gaia" path="gaia" remote="mozillaorg" revision="76f26cf0e552d972c9822657f0b72e78842b6582"/>
<project name="gaia" path="gaia" remote="mozillaorg" revision="a6881205deae450757a8d1e1ed65e5e5be0ec633"/>
<project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="3905180d9e2dbe03d7ce3b3a6debe4d4adc938d1"/>
<project name="librecovery" path="librecovery" remote="b2g" revision="1b3591a50ed352fc6ddb77462b7b35d0bfa555a3"/>

View File

@ -860,11 +860,7 @@ pref("browser.preferences.instantApply", true);
#endif
// Toggles between the two Preferences implementations, pop-up window and in-content
#ifdef EARLY_BETA_OR_EARLIER
pref("browser.preferences.inContent", true);
#else
pref("browser.preferences.inContent", false);
#endif
pref("browser.download.show_plugins_in_list", true);
pref("browser.download.hide_plugins_without_extensions", true);
@ -1032,6 +1028,8 @@ pref("browser.rights.3.shown", false);
pref("browser.rights.override", true);
#endif
pref("browser.selfsupport.url", "http://self-repair.mozilla.org/%LOCALE%/repair");
pref("browser.sessionstore.resume_from_crash", true);
pref("browser.sessionstore.resume_session_once", false);

View File

@ -25,15 +25,6 @@ let gEMEHandler = {
return "<label class='text-link' href='" + baseURL + "drm-content'>" +
text + "</label>";
},
getDRMLabel: function(keySystem) {
if (keySystem.startsWith("com.adobe")) {
return "Adobe Primetime";
}
if (keySystem == "org.w3.clearkey") {
return "ClearKey";
}
return gNavigatorBundle.getString("emeNotifications.unknownDRMSoftware");
},
onDontAskAgain: function(menuPopupItem) {
let button = menuPopupItem.parentNode.anchorNode;
let bar = button.parentNode;
@ -158,12 +149,11 @@ let gEMEHandler = {
}
let msgPrefix = "emeNotifications.drmContentPlaying.";
let msgId = msgPrefix + "message";
let msgId = msgPrefix + "message2";
let btnLabelId = msgPrefix + "button.label";
let btnAccessKeyId = msgPrefix + "button.accesskey";
let drmProvider = this.getDRMLabel(keySystem);
let message = gNavigatorBundle.getFormattedString(msgId, [drmProvider, this._brandShortName]);
let message = gNavigatorBundle.getFormattedString(msgId, [this._brandShortName]);
let anchorId = "eme-notification-icon";
let mainAction = {

View File

@ -91,6 +91,9 @@ XPCOMUtils.defineLazyModuleGetter(this, "RemotePrompt",
XPCOMUtils.defineLazyModuleGetter(this, "ContentPrefServiceParent",
"resource://gre/modules/ContentPrefServiceParent.jsm");
XPCOMUtils.defineLazyModuleGetter(this, "SelfSupportBackend",
"resource:///modules/SelfSupportBackend.jsm");
XPCOMUtils.defineLazyModuleGetter(this, "SessionStore",
"resource:///modules/sessionstore/SessionStore.jsm");
@ -627,6 +630,8 @@ BrowserGlue.prototype = {
LoginManagerParent.init();
ReaderParent.init();
SelfSupportBackend.init();
#ifdef NIGHTLY_BUILD
Services.prefs.addObserver(POLARIS_ENABLED, this, false);
#endif
@ -888,6 +893,8 @@ BrowserGlue.prototype = {
Cu.reportError("Could not end startup crash tracking in quit-application-granted: " + e);
}
SelfSupportBackend.uninit();
CustomizationTabPreloader.uninit();
WebappManager.uninit();
#ifdef NIGHTLY_BUILD

View File

@ -344,6 +344,15 @@ this.UITour = {
onPageEvent: function(aMessage, aEvent) {
let browser = aMessage.target;
let window = browser.ownerDocument.defaultView;
// Does the window have tabs? We need to make sure since windowless browsers do
// not have tabs.
if (!window.gBrowser) {
// When using windowless browsers we don't have a valid |window|. If that's the case,
// use the most recent window as a target for UITour functions (see Bug 1111022).
window = Services.wm.getMostRecentWindow("navigator:browser");
}
let tab = window.gBrowser.getTabForBrowser(browser);
let messageManager = browser.messageManager;

View File

@ -5,6 +5,7 @@ support-files =
uitour.html
../UITour-lib.js
[browser_no_tabs.js]
[browser_UITour.js]
skip-if = os == "linux" || e10s # Intermittent failures, bug 951965
[browser_UITour2.js]

View File

@ -0,0 +1,110 @@
/* Any copyright is dedicated to the Public Domain.
* http://creativecommons.org/publicdomain/zero/1.0/ */
"use strict";
const HTML_NS = "http://www.w3.org/1999/xhtml";
const XUL_NS = "http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul";
/**
* Create a frame in the |hiddenDOMWindow| to host a |browser|, then load the URL in the
* latter.
*
* @param aURL
* The URL to open in the browser.
**/
function createHiddenBrowser(aURL) {
let deferred = Promise.defer();
let hiddenDoc = Services.appShell.hiddenDOMWindow.document;
// Create a HTML iframe with a chrome URL, then this can host the browser.
let iframe = hiddenDoc.createElementNS(HTML_NS, "iframe");
iframe.setAttribute("src", "chrome://global/content/mozilla.xhtml");
iframe.addEventListener("load", function onLoad() {
iframe.removeEventListener("load", onLoad, true);
let browser = iframe.contentDocument.createElementNS(XUL_NS, "browser");
browser.setAttribute("type", "content");
browser.setAttribute("disableglobalhistory", "true");
browser.setAttribute("src", aURL);
iframe.contentDocument.documentElement.appendChild(browser);
deferred.resolve({frame: iframe, browser: browser});
}, true);
hiddenDoc.documentElement.appendChild(iframe);
return deferred.promise;
};
/**
* Remove the browser and the iframe.
*
* @param aFrame
* The iframe to dismiss.
* @param aBrowser
* The browser to dismiss.
*/
function destroyHiddenBrowser(aFrame, aBrowser) {
// Dispose of the hidden browser.
aBrowser.remove();
// Take care of the frame holding our invisible browser.
if (!Cu.isDeadWrapper(aFrame)) {
aFrame.remove();
}
};
/**
* Test that UITour works when called when no tabs are available (e.g., when using windowless
* browsers).
*/
add_task(function* test_windowless_UITour(){
// Get the URL for the test page.
let pageURL = getRootDirectory(gTestPath) + "uitour.html";
// Allow the URL to use the UITour.
info("Adding UITour permission to the test page.");
let pageURI = Services.io.newURI(pageURL, null, null);
Services.perms.add(pageURI, "uitour", Services.perms.ALLOW_ACTION);
// UITour's ping will resolve this promise.
let deferredPing = Promise.defer();
// Create a windowless browser and test that UITour works in it.
let browserPromise = createHiddenBrowser(pageURL);
browserPromise.then(frameInfo => {
isnot(frameInfo.browser, null, "The browser must exist and not be null.");
// Load UITour frame script.
frameInfo.browser.messageManager.loadFrameScript(
"chrome://browser/content/content-UITour.js", false);
// When the page loads, try to use UITour API.
frameInfo.browser.addEventListener("load", function loadListener() {
info("The test page was correctly loaded.");
frameInfo.browser.removeEventListener("load", loadListener, true);
// Get a reference to the UITour API.
info("Testing access to the UITour API.");
let contentWindow = Cu.waiveXrays(frameInfo.browser.contentDocument.defaultView);
isnot(contentWindow, null, "The content window must exist and not be null.");
let uitourAPI = contentWindow.Mozilla.UITour;
// Test the UITour API with a ping.
uitourAPI.ping(function() {
info("Ping response received from the UITour API.");
// Make sure to clean up.
destroyHiddenBrowser(frameInfo.frame, frameInfo.browser);
// Resolve our promise.
deferredPing.resolve();
});
}, true);
});
// Wait for the UITour ping to complete.
yield deferredPing.promise;
});

View File

@ -591,8 +591,8 @@ getUserMedia.sharingMenuMicrophoneWindow = %S (microphone and window)
# origin for the sharing menu if no readable origin could be deduced from the URL.
getUserMedia.sharingMenuUnknownHost = Unknown origin
# LOCALIZATION NOTE(emeNotifications.drmContentPlaying.message): %1$S is the vendor name of the DRM that's in use, %2$S is brandShortName.
emeNotifications.drmContentPlaying.message = Some audio or video on this site uses %1$S DRM software, which may limit what %2$S can let you do with it.
# LOCALIZATION NOTE(emeNotifications.drmContentPlaying.message2): %S is brandShortName.
emeNotifications.drmContentPlaying.message2 = Some audio or video on this site uses DRM software, which may limit what %S can let you do with it.
emeNotifications.drmContentPlaying.button.label = Configure…
emeNotifications.drmContentPlaying.button.accesskey = C
@ -614,6 +614,11 @@ emeNotifications.drmContentCDMInsufficientVersion.message = %S is installing upd
# LOCALIZATION NOTE(emeNotifications.drmContentCDMInstalling.message): NB: inserted via innerHTML, so please don't use <, > or & in this string. %S is brandShortName
emeNotifications.drmContentCDMInstalling.message = %S is installing components needed to play the audio or video on this page. Please try again later.
# LOCALIZATION NOTE(emeNotifications.drmContentCDMNotSupported.64bit.message): NB: inserted via innerHTML, so please don't use <, > or & in this string. %1$S is brandShortName, %2$S will be the 'learn more' link
emeNotifications.drmContentCDMNotSupported.64bit.message = The audio or video on this page requires DRM software that this 64-bit build of %1$S does not support. %2$S
# LOCALIZATION NOTE(emeNotifications.drmContentCDMNotSupported.unsupportedOS.message): NB: inserted via innerHTML, so please don't use <, > or & in this string. %1$S is brandShortName, %2$S is the name of the user's OS (Windows, Linux, Mac OS X), %3$S will be the 'learn more' link
emeNotifications.drmContentCDMNotSupported.unsupportedOS.message = The audio or video on this page requires DRM software that %1$S does not support on %2$S. %3$S
emeNotifications.optionsButton.label = Options
emeNotifications.optionsButton.accesskey = O

View File

@ -0,0 +1,323 @@
/* 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 = ["SelfSupportBackend"];
const Cu = Components.utils;
const Cc = Components.classes;
const Ci = Components.interfaces;
Cu.import("resource://gre/modules/Log.jsm");
Cu.import("resource://gre/modules/Preferences.jsm");
Cu.import("resource://gre/modules/Services.jsm");
Cu.import("resource://gre/modules/Timer.jsm");
Cu.import("resource://gre/modules/XPCOMUtils.jsm");
XPCOMUtils.defineLazyModuleGetter(this, "HiddenFrame",
"resource:///modules/HiddenFrame.jsm");
// Enables or disables the Self Support.
const PREF_ENABLED = "browser.selfsupport.enabled";
// Url to open in the Self Support browser, in the urlFormatter service format.
const PREF_URL = "browser.selfsupport.url";
// FHR status.
const PREF_FHR_ENABLED = "datareporting.healthreport.service.enabled";
// UITour status.
const PREF_UITOUR_ENABLED = "browser.uitour.enabled";
// Controls the interval at which the self support page tries to reload in case of
// errors.
const RETRY_INTERVAL_MS = 30000;
// Maximum number of SelfSupport page load attempts in case of failure.
const MAX_RETRIES = 5;
// The delay after which to load the self-support, at startup.
const STARTUP_DELAY_MS = 5000;
const LOGGER_NAME = "Browser.SelfSupportBackend";
const PREF_BRANCH_LOG = "browser.selfsupport.log.";
const PREF_LOG_LEVEL = PREF_BRANCH_LOG + "level";
const PREF_LOG_DUMP = PREF_BRANCH_LOG + "dump";
const HTML_NS = "http://www.w3.org/1999/xhtml";
const XUL_NS = "http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul";
const UITOUR_FRAME_SCRIPT = "chrome://browser/content/content-UITour.js";
let gLogAppenderDump = null;
this.SelfSupportBackend = Object.freeze({
init: function () {
SelfSupportBackendInternal.init();
},
uninit: function () {
SelfSupportBackendInternal.uninit();
},
});
let SelfSupportBackendInternal = {
// The browser element that will load the SelfSupport page.
_browser: null,
// The Id of the timer triggering delayed SelfSupport page load.
_delayedLoadTimerId: null,
// The HiddenFrame holding the _browser element.
_frame: null,
_log: null,
_progressListener: null,
/**
* Initializes the self support backend.
*/
init: function () {
this._configureLogging();
this._log.trace("init");
Preferences.observe(PREF_BRANCH_LOG, this._configureLogging, this);
// Only allow to use SelfSupport if FHR is enabled.
let fhrEnabled = Preferences.get(PREF_FHR_ENABLED, false);
if (!fhrEnabled) {
this._log.config("init - Disabling SelfSupport because Health Report is disabled.");
return;
}
// Make sure UITour is enabled.
let uiTourEnabled = Preferences.get(PREF_UITOUR_ENABLED, false);
if (!uiTourEnabled) {
this._log.config("init - Disabling SelfSupport because UITour is disabled.");
return;
}
// Check the preferences to see if we want this to be active.
if (!Preferences.get(PREF_ENABLED, true)) {
this._log.config("init - SelfSupport is disabled.");
return;
}
Services.obs.addObserver(this, "sessionstore-windows-restored", false);
},
/**
* Shut down the self support backend, if active.
*/
uninit: function () {
this._log.trace("uninit");
Preferences.ignore(PREF_BRANCH_LOG, this._configureLogging, this);
// Cancel delayed loading, if still active, when shutting down.
clearTimeout(this._delayedLoadTimerId);
// Dispose of the hidden browser.
if (this._browser !== null) {
if (this._browser.contentWindow) {
this._browser.contentWindow.removeEventListener("DOMWindowClose", this, true);
}
if (this._progressListener) {
this._browser.removeProgressListener(this._progressListener);
this._progressListener.destroy();
this._progressListener = null;
}
this._browser.remove();
this._browser = null;
}
if (this._frame) {
this._frame.destroy();
this._frame = null;
}
},
/**
* Handle notifications. Once all windows are created, we wait a little bit more
* since tabs might still be loading. Then, we open the self support.
*/
observe: function (aSubject, aTopic, aData) {
this._log.trace("observe - Topic " + aTopic);
if (aTopic === "sessionstore-windows-restored") {
Services.obs.removeObserver(this, "sessionstore-windows-restored");
this._delayedLoadTimerId = setTimeout(this._loadSelfSupport.bind(this), STARTUP_DELAY_MS);
}
},
/**
* Configure the logger based on the preferences.
*/
_configureLogging: function() {
if (!this._log) {
this._log = Log.repository.getLogger(LOGGER_NAME);
// Log messages need to go to the browser console.
let consoleAppender = new Log.ConsoleAppender(new Log.BasicFormatter());
this._log.addAppender(consoleAppender);
}
// Make sure the logger keeps up with the logging level preference.
this._log.level = Log.Level[Preferences.get(PREF_LOG_LEVEL, "Warn")];
// If enabled in the preferences, add a dump appender.
let logDumping = Preferences.get(PREF_LOG_DUMP, false);
if (logDumping != !!gLogAppenderDump) {
if (logDumping) {
gLogAppenderDump = new Log.DumpAppender(new Log.BasicFormatter());
this._log.addAppender(gLogAppenderDump);
} else {
this._log.removeAppender(gLogAppenderDump);
gLogAppenderDump = null;
}
}
},
/**
* Create an hidden frame to host our |browser|, then load the SelfSupport page in it.
* @param aURL The URL to load in the browser.
*/
_makeHiddenBrowser: function(aURL) {
this._frame = new HiddenFrame();
return this._frame.get().then(aFrame => {
let doc = aFrame.document;
this._browser = doc.createElementNS(XUL_NS, "browser");
this._browser.setAttribute("type", "content");
this._browser.setAttribute("disableglobalhistory", "true");
this._browser.setAttribute("src", aURL);
doc.documentElement.appendChild(this._browser);
});
},
handleEvent: function(aEvent) {
this._log.trace("handleEvent - aEvent.type " + aEvent.type + ", Trusted " + aEvent.isTrusted);
if (aEvent.type === "DOMWindowClose") {
let window = this._browser.contentDocument.defaultView;
let target = aEvent.target;
if (target == window) {
// preventDefault stops the default window.close(). We need to do that to prevent
// Services.appShell.hiddenDOMWindow from being destroyed.
aEvent.preventDefault();
this.uninit();
}
}
},
/**
* Called when the self support page correctly loads.
*/
_pageSuccessCallback: function() {
this._log.debug("_pageSuccessCallback - Page correctly loaded.");
this._browser.removeProgressListener(this._progressListener);
this._progressListener.destroy();
this._progressListener = null;
// Allow SelfSupportBackend to catch |window.close()| issued by the content.
this._browser.contentWindow.addEventListener("DOMWindowClose", this, true);
},
/**
* Called when the self support page fails to load.
*/
_pageLoadErrorCallback: function() {
this._log.info("_pageLoadErrorCallback - Too many failed load attempts. Giving up.");
this.uninit();
},
/**
* Create a browser and attach it to an hidden window. The browser will contain the
* self support page and attempt to load the page content. If loading fails, try again
* after an interval.
*/
_loadSelfSupport: function() {
// Fetch the Self Support URL from the preferences.
let unformattedURL = Preferences.get(PREF_URL, null);
let url = Services.urlFormatter.formatURL(unformattedURL);
this._log.config("_loadSelfSupport - URL " + url);
// Create the hidden browser.
this._makeHiddenBrowser(url).then(() => {
// Load UITour frame script.
this._browser.messageManager.loadFrameScript(UITOUR_FRAME_SCRIPT, true);
// We need to watch for load errors as well and, in case, try to reload
// the self support page.
const webFlags = Ci.nsIWebProgress.NOTIFY_STATE_WINDOW |
Ci.nsIWebProgress.NOTIFY_STATE_REQUEST |
Ci.nsIWebProgress.NOTIFY_LOCATION;
this._progressListener = new ProgressListener(() => this._pageLoadErrorCallback(),
() => this._pageSuccessCallback());
this._browser.addProgressListener(this._progressListener, webFlags);
});
}
};
/**
* A progress listener object which notifies of page load error and load success
* through callbacks. When the page fails to load, the progress listener tries to
* reload it up to MAX_RETRIES times. The page is not loaded again immediately, but
* after a timeout.
*
* @param aLoadErrorCallback Called when a page failed to load MAX_RETRIES times.
* @param aLoadSuccessCallback Called when a page correctly loads.
*/
function ProgressListener(aLoadErrorCallback, aLoadSuccessCallback) {
this._loadErrorCallback = aLoadErrorCallback;
this._loadSuccessCallback = aLoadSuccessCallback;
// The number of page loads attempted.
this._loadAttempts = 0;
this._log = Log.repository.getLogger(LOGGER_NAME);
// The Id of the timer which triggers page load again in case of errors.
this._reloadTimerId = null;
}
ProgressListener.prototype = {
onLocationChange: function(aWebProgress, aRequest, aLocation, aFlags) {
if (aFlags & Ci.nsIWebProgressListener.LOCATION_CHANGE_ERROR_PAGE) {
this._log.warn("onLocationChange - There was a problem fetching the SelfSupport URL (attempt " +
this._loadAttempts + ").");
// Increase the number of attempts and bail out if we failed too many times.
this._loadAttempts++;
if (this._loadAttempts > MAX_RETRIES) {
this._loadErrorCallback();
return;
}
// Reload the page after the retry interval expires. The interval is multiplied
// by the number of attempted loads, so that it takes a bit more to try to reload
// when frequently failing.
this._reloadTimerId = setTimeout(() => {
this._log.debug("onLocationChange - Reloading SelfSupport URL in the hidden browser.");
aWebProgress.DOMWindow.location.reload();
}, RETRY_INTERVAL_MS * this._loadAttempts);
}
},
onStateChange: function (aWebProgress, aRequest, aFlags, aStatus) {
if (aFlags & Ci.nsIWebProgressListener.STATE_STOP &&
aFlags & Ci.nsIWebProgressListener.STATE_IS_NETWORK &&
aFlags & Ci.nsIWebProgressListener.STATE_IS_WINDOW &&
Components.isSuccessCode(aStatus)) {
this._loadSuccessCallback();
}
},
destroy: function () {
// Make sure we don't try to reload self support when shutting down.
clearTimeout(this._reloadTimerId);
},
QueryInterface: XPCOMUtils.generateQI([Ci.nsIWebProgressListener,
Ci.nsISupportsWeakReference]),
};

View File

@ -32,6 +32,7 @@ EXTRA_JS_MODULES += [
'ProcessHangMonitor.jsm',
'ReaderParent.jsm',
'RemotePrompt.jsm',
'SelfSupportBackend.jsm',
'SitePermissions.jsm',
'Social.jsm',
'TabCrashReporter.jsm',

View File

@ -12,6 +12,10 @@ support-files =
contentSearchSuggestions.xml
[browser_NetworkPrioritizer.js]
skip-if = e10s # Bug 666804 - Support NetworkPrioritizer in e10s
[browser_SelfSupportBackend.js]
support-files =
../../components/uitour/test/uitour.html
../../components/uitour/UITour-lib.js
[browser_SignInToWebsite.js]
skip-if = e10s # Bug 941426 - SignIntoWebsite.jsm not e10s friendly
[browser_taskbar_preview.js]

View File

@ -0,0 +1,158 @@
/* 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";
// Pass an empty scope object to the import to prevent "leaked window property"
// errors in tests.
let Preferences = Cu.import("resource://gre/modules/Preferences.jsm", {}).Preferences;
let PromiseUtils = Cu.import("resource://gre/modules/PromiseUtils.jsm", {}).PromiseUtils;
let SelfSupportBackend =
Cu.import("resource:///modules/SelfSupportBackend.jsm", {}).SelfSupportBackend;
const PREF_SELFSUPPORT_ENABLED = "browser.selfsupport.enabled";
const PREF_SELFSUPPORT_URL = "browser.selfsupport.url";
const PREF_UITOUR_ENABLED = "browser.uitour.enabled";
const TEST_WAIT_RETRIES = 60;
const TEST_PAGE_URL = getRootDirectory(gTestPath) + "uitour.html";
/**
* Find a browser, with an IFRAME as parent, who has aURL as the source attribute.
*
* @param aURL The URL to look for to identify the browser.
*
* @returns {Object} The browser element or null on failure.
*/
function findSelfSupportBrowser(aURL) {
let frames = Services.appShell.hiddenDOMWindow.document.querySelectorAll('iframe');
for (let frame of frames) {
try {
let browser = frame.contentDocument.getElementById("win").querySelectorAll('browser')[0];
let url = browser.getAttribute("src");
if (url == aURL) {
return browser;
}
} catch (e) {
continue;
}
}
return null;
}
/**
* Wait for self support page to load.
*
* @param aURL The URL to look for to identify the browser.
*
* @returns {Promise} Return a promise which is resolved when SelfSupport page is fully
* loaded.
*/
function promiseSelfSupportLoad(aURL) {
return new Promise((resolve, reject) => {
// Find the SelfSupport browser.
let browserPromise = waitForConditionPromise(() => !!findSelfSupportBrowser(aURL),
"SelfSupport browser not found.",
TEST_WAIT_RETRIES);
// Once found, append a "load" listener to catch page loads.
browserPromise.then(() => {
let browser = findSelfSupportBrowser(aURL);
if (browser.contentDocument.readyState === "complete") {
resolve(browser);
} else {
let handler = () => {
browser.removeEventListener("load", handler, true);
resolve(browser);
};
browser.addEventListener("load", handler, true);
}
}, reject);
});
}
/**
* Wait for self support to close.
*
* @param aURL The URL to look for to identify the browser.
*
* @returns {Promise} Return a promise which is resolved when SelfSupport browser cannot
* be found anymore.
*/
function promiseSelfSupportClose(aURL) {
return waitForConditionPromise(() => !findSelfSupportBrowser(aURL),
"SelfSupport browser is still open.", TEST_WAIT_RETRIES);
}
/**
* Prepare the test environment.
*/
add_task(function* setupEnvironment() {
// We always run the SelfSupportBackend in tests to check for weird behaviours.
// Disable it to test its start-up.
SelfSupportBackend.uninit();
// Testing prefs are set via |user_pref|, so we need to get their value in order
// to restore them.
let selfSupportEnabled = Preferences.get(PREF_SELFSUPPORT_ENABLED, true);
let uitourEnabled = Preferences.get(PREF_UITOUR_ENABLED, false);
let selfSupportURL = Preferences.get(PREF_SELFSUPPORT_URL, "");
// Enable the SelfSupport backend and set the page URL. We also make sure UITour
// is enabled.
Preferences.set(PREF_SELFSUPPORT_ENABLED, true);
Preferences.set(PREF_UITOUR_ENABLED, true);
Preferences.set(PREF_SELFSUPPORT_URL, TEST_PAGE_URL);
registerCleanupFunction(() => {
Preferences.set(PREF_SELFSUPPORT_ENABLED, selfSupportEnabled);
Preferences.set(PREF_UITOUR_ENABLED, uitourEnabled);
Preferences.set(PREF_SELFSUPPORT_URL, selfSupportURL);
});
});
/**
* Test that the self support page can use the UITour API and close itself.
*/
add_task(function* test_selfSupport() {
// Initialise the SelfSupport backend and trigger the load.
SelfSupportBackend.init();
// SelfSupportBackend waits for "sessionstore-windows-restored" to start loading. Send it.
info("Sending sessionstore-windows-restored");
Services.obs.notifyObservers(null, "sessionstore-windows-restored", null);
// Wait for the SelfSupport page to load.
info("Waiting for the SelfSupport local page to load.");
let selfSupportBrowser = yield promiseSelfSupportLoad(TEST_PAGE_URL);
Assert.ok(!!selfSupportBrowser, "SelfSupport browser must exist.");
// Get a reference to the UITour API.
info("Testing access to the UITour API.");
let contentWindow =
Cu.waiveXrays(selfSupportBrowser.contentDocument.defaultView);
let uitourAPI = contentWindow.Mozilla.UITour;
// Test the UITour API with a ping.
let pingPromise = new Promise((resolve) => {
uitourAPI.ping(resolve);
});
yield pingPromise;
// Close SelfSupport from content.
contentWindow.close();
// Wait until SelfSupport closes.
info("Waiting for the SelfSupport to close.");
yield promiseSelfSupportClose(TEST_PAGE_URL);
// Find the SelfSupport browser, again. We don't expect to find it.
selfSupportBrowser = findSelfSupportBrowser(TEST_PAGE_URL);
Assert.ok(!selfSupportBrowser, "SelfSupport browser must not exist.");
// We shouldn't need this, but let's keep it to make sure closing SelfSupport twice
// doesn't create any problem.
SelfSupportBackend.uninit();
});

View File

@ -58,3 +58,6 @@
// desired side-effect of preventing our geoip lookup.
branch.setBoolPref("browser.search.isUS", true);
branch.setCharPref("browser.search.countryCode", "US");
// Make sure SelfSupport doesn't hit the network.
branch.setCharPref("browser.selfsupport.url", "https://%(server)s/selfsupport-dummy/");

View File

@ -25,6 +25,9 @@ XPCOMUtils.defineLazyModuleGetter(this, "CustomizationTabPreloader",
XPCOMUtils.defineLazyModuleGetter(this, "ContentSearch",
"resource:///modules/ContentSearch.jsm");
XPCOMUtils.defineLazyModuleGetter(this, "SelfSupportBackend",
"resource:///modules/SelfSupportBackend.jsm");
const SIMPLETEST_OVERRIDES =
["ok", "is", "isnot", "ise", "todo", "todo_is", "todo_isnot", "info", "expectAssertions", "requestCompleteLog"];
@ -523,6 +526,7 @@ Tester.prototype = {
gBrowser.getNotificationBox(browser).remove();
}
SelfSupportBackend.uninit();
CustomizationTabPreloader.uninit();
SocialFlyout.unload();
SocialShare.uninit();

View File

@ -281,6 +281,9 @@ user_pref("browser.uitour.url", "http://%(server)s/uitour-dummy/tour");
user_pref("browser.search.isUS", true);
user_pref("browser.search.countryCode", "US");
// Make sure the self support tab doesn't hit the network.
user_pref("browser.selfsupport.url", "https://%(server)s/selfsupport-dummy/");
user_pref("media.eme.enabled", true);
user_pref("media.eme.apiVisible", true);

View File

@ -1417,5 +1417,6 @@ try {
.getService(Components.interfaces.nsIPrefBranch);
prefs.setCharPref("media.gmp-manager.url.override", "http://%(server)s/dummy-gmp-manager.xml");
prefs.setCharPref("browser.selfsupport.url", "https://%(server)s/selfsupport-dummy/");
}
} catch (e) { }