Merge m-c to b2g-inbound. a=merge
2
.gdbinit
@ -177,5 +177,5 @@ def js
|
||||
end
|
||||
|
||||
def ft
|
||||
call nsFrame::DumpFrameTree($arg0)
|
||||
call $arg0->DumpFrameTree()
|
||||
end
|
||||
|
@ -21,7 +21,10 @@ class TableAccessible;
|
||||
class xpcAccessibleTable
|
||||
{
|
||||
public:
|
||||
explicit xpcAccessibleTable(mozilla::a11y::TableAccessible* aTable) : mTable(aTable) { }
|
||||
explicit xpcAccessibleTable(TableAccessible* aTable) :
|
||||
mTable(aTable)
|
||||
{
|
||||
}
|
||||
|
||||
nsresult GetCaption(nsIAccessible** aCaption);
|
||||
nsresult GetSummary(nsAString& aSummary);
|
||||
|
@ -25,8 +25,10 @@ class TableCellAccessible;
|
||||
class xpcAccessibleTableCell
|
||||
{
|
||||
public:
|
||||
explicit xpcAccessibleTableCell(mozilla::a11y::TableCellAccessible* aTableCell) :
|
||||
mTableCell(aTableCell) { }
|
||||
explicit xpcAccessibleTableCell(TableCellAccessible* aTableCell) :
|
||||
mTableCell(aTableCell)
|
||||
{
|
||||
}
|
||||
|
||||
nsresult GetTable(nsIAccessibleTable** aTable);
|
||||
nsresult GetColumnIndex(int32_t* aColIdx);
|
||||
|
@ -7,22 +7,27 @@ module.metadata = {
|
||||
};
|
||||
|
||||
const { Cc, Ci, Cu } = require('chrome');
|
||||
const { isNative } = require('@loader/options');
|
||||
const { rootURI, metadata, isNative } = require('@loader/options');
|
||||
const { id, loadReason } = require('../self');
|
||||
const { descriptor, Sandbox, evaluate, main, resolveURI } = require('toolkit/loader');
|
||||
const { once } = require('../system/events');
|
||||
const { exit, env, staticArgs } = require('../system');
|
||||
const { when: unload } = require('../system/unload');
|
||||
const { loadReason } = require('../self');
|
||||
const { rootURI, metadata } = require("@loader/options");
|
||||
const globals = require('../system/globals');
|
||||
const xulApp = require('../system/xul-app');
|
||||
const { id } = require('sdk/self');
|
||||
const { get } = require('../preferences/service');
|
||||
const appShellService = Cc['@mozilla.org/appshell/appShellService;1'].
|
||||
getService(Ci.nsIAppShellService);
|
||||
const { preferences } = metadata;
|
||||
|
||||
const Startup = Cu.import("resource://gre/modules/sdk/system/Startup.js", {}).exports;
|
||||
|
||||
Cu.import("resource://gre/modules/XPCOMUtils.jsm");
|
||||
XPCOMUtils.defineLazyGetter(this, "BrowserToolboxProcess", function () {
|
||||
return Cu.import("resource:///modules/devtools/ToolboxProcess.jsm", {}).
|
||||
BrowserToolboxProcess;
|
||||
});
|
||||
|
||||
// Initializes default preferences
|
||||
function setDefaultPrefs(prefsURI) {
|
||||
const prefs = Cc['@mozilla.org/preferences-service;1'].
|
||||
@ -102,7 +107,9 @@ function run(options) {
|
||||
// native-options does stuff directly with preferences key from package.json
|
||||
if (preferences && preferences.length > 0) {
|
||||
try {
|
||||
require('../preferences/native-options').enable({ preferences: preferences, id: id });
|
||||
require('../preferences/native-options').
|
||||
enable({ preferences: preferences, id: id }).
|
||||
catch(console.exception);
|
||||
}
|
||||
catch (error) {
|
||||
console.exception(error);
|
||||
@ -141,7 +148,6 @@ function run(options) {
|
||||
unload(program.onUnload);
|
||||
|
||||
if (typeof(program.main) === 'function') {
|
||||
|
||||
program.main({
|
||||
loadReason: loadReason,
|
||||
staticArgs: staticArgs
|
||||
@ -150,6 +156,10 @@ function run(options) {
|
||||
quit: exit
|
||||
});
|
||||
}
|
||||
|
||||
if (get("extensions." + id + ".sdk.debug.show", false)) {
|
||||
BrowserToolboxProcess.init({ addonID: id });
|
||||
}
|
||||
} catch (error) {
|
||||
console.exception(error);
|
||||
throw error;
|
||||
|
@ -55,6 +55,10 @@ DEFAULT_NO_CONNECTIONS_PREFS = {
|
||||
# Disable app update
|
||||
'app.update.enabled' : False,
|
||||
|
||||
# Disable about:newtab content fetch and ping
|
||||
'browser.newtabpage.directory.source': 'data:application/json,{"jetpack":1}',
|
||||
'browser.newtabpage.directory.ping': '',
|
||||
|
||||
# Point update checks to a nonexistent local URL for fast failures.
|
||||
'extensions.update.url' : 'http://localhost/extensions-dummy/updateURL',
|
||||
'extensions.blocklist.url' : 'http://localhost/extensions-dummy/blocklistURL',
|
||||
|
17
addon-sdk/source/test/addons/author-email/main.js
Normal file
@ -0,0 +1,17 @@
|
||||
/* 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';
|
||||
|
||||
const { Cu } = require('chrome');
|
||||
const self = require('sdk/self');
|
||||
const { AddonManager } = Cu.import('resource://gre/modules/AddonManager.jsm', {});
|
||||
|
||||
exports.testContributors = function(assert, done) {
|
||||
AddonManager.getAddonByID(self.id, (addon) => {
|
||||
assert.equal(addon.creator.name, 'test <test@mozilla.com>', '< and > characters work');
|
||||
done();
|
||||
});
|
||||
}
|
||||
|
||||
require('sdk/test/runner').runTestsFromModule(module);
|
4
addon-sdk/source/test/addons/author-email/package.json
Normal file
@ -0,0 +1,4 @@
|
||||
{
|
||||
"id": "test-addon-author-email@jetpack",
|
||||
"author": "test <test@mozilla.com>"
|
||||
}
|
@ -76,7 +76,7 @@ exports['test `load` events'] = function(assert, done) {
|
||||
});
|
||||
};
|
||||
|
||||
exports['test removeing listeners'] = function(assert, done) {
|
||||
exports['test removing listeners'] = function(assert, done) {
|
||||
Loader({
|
||||
onLoad: function(window) {
|
||||
assert.equal(window, this._window, 'windows should match');
|
||||
|
@ -7,7 +7,6 @@ support-files =
|
||||
invalid.json
|
||||
[browser_sdk_loader_sdk_modules.js]
|
||||
[browser_sdk_loader_sdk_gui_modules.js]
|
||||
skip-if = e10s # Bug ?????? - test times out.
|
||||
[browser_sdk_loader_jsm_modules.js]
|
||||
[browser_sdk_loader_js_modules.js]
|
||||
[browser_sdk_loader_json.js]
|
||||
|
@ -293,6 +293,7 @@
|
||||
@BINPATH@/components/spellchecker.xpt
|
||||
@BINPATH@/components/storage.xpt
|
||||
@BINPATH@/components/telemetry.xpt
|
||||
@BINPATH@/components/toolkit_filewatcher.xpt
|
||||
@BINPATH@/components/toolkit_finalizationwitness.xpt
|
||||
@BINPATH@/components/toolkit_formautofill.xpt
|
||||
@BINPATH@/components/toolkit_osfile.xpt
|
||||
|
@ -10,18 +10,6 @@
|
||||
* Tab previews utility, produces thumbnails
|
||||
*/
|
||||
var tabPreviews = {
|
||||
aspectRatio: 0.5625, // 16:9
|
||||
|
||||
get width() {
|
||||
delete this.width;
|
||||
return this.width = Math.ceil(screen.availWidth / 5.75);
|
||||
},
|
||||
|
||||
get height() {
|
||||
delete this.height;
|
||||
return this.height = Math.round(this.width * this.aspectRatio);
|
||||
},
|
||||
|
||||
init: function tabPreviews_init() {
|
||||
if (this._selectedTab)
|
||||
return;
|
||||
@ -29,6 +17,12 @@ var tabPreviews = {
|
||||
|
||||
gBrowser.tabContainer.addEventListener("TabSelect", this, false);
|
||||
gBrowser.tabContainer.addEventListener("SSTabRestored", this, false);
|
||||
|
||||
let screenManager = Cc["@mozilla.org/gfx/screenmanager;1"]
|
||||
.getService(Ci.nsIScreenManager);
|
||||
let left = {}, top = {}, width = {}, height = {};
|
||||
screenManager.primaryScreen.GetRectDisplayPix(left, top, width, height);
|
||||
this.aspectRatio = height.value / width.value;
|
||||
},
|
||||
|
||||
get: function tabPreviews_get(aTab) {
|
||||
@ -52,31 +46,35 @@ var tabPreviews = {
|
||||
return this.capture(aTab, !aTab.hasAttribute("busy"));
|
||||
},
|
||||
|
||||
capture: function tabPreviews_capture(aTab, aStore) {
|
||||
var thumbnail = document.createElementNS("http://www.w3.org/1999/xhtml", "canvas");
|
||||
thumbnail.mozOpaque = true;
|
||||
thumbnail.height = this.height;
|
||||
thumbnail.width = this.width;
|
||||
capture: function tabPreviews_capture(aTab, aShouldCache) {
|
||||
let browser = aTab.linkedBrowser;
|
||||
let uri = browser.currentURI.spec;
|
||||
|
||||
// drawWindow doesn't yet work with e10s (bug 698371)
|
||||
if (gMultiProcessBrowser)
|
||||
return thumbnail;
|
||||
// FIXME: The gBrowserThumbnails._shouldCapture determines whether
|
||||
// thumbnails should be written to disk. This should somehow be part
|
||||
// of the PageThumbs API. (bug 1062414)
|
||||
if (aShouldCache &&
|
||||
gBrowserThumbnails._shouldCapture(browser)) {
|
||||
let img = new Image;
|
||||
|
||||
var ctx = thumbnail.getContext("2d");
|
||||
var win = aTab.linkedBrowser.contentWindow;
|
||||
var snippetWidth = win.innerWidth * .6;
|
||||
var scale = this.width / snippetWidth;
|
||||
ctx.scale(scale, scale);
|
||||
ctx.drawWindow(win, win.scrollX, win.scrollY,
|
||||
snippetWidth, snippetWidth * this.aspectRatio, "rgb(255,255,255)");
|
||||
PageThumbs.captureAndStore(browser, function () {
|
||||
img.src = PageThumbs.getThumbnailURL(uri);
|
||||
});
|
||||
|
||||
if (aStore &&
|
||||
aTab.linkedBrowser /* bug 795608: the tab may got removed while drawing the thumbnail */) {
|
||||
aTab.__thumbnail = thumbnail;
|
||||
aTab.__thumbnail_lastURI = aTab.linkedBrowser.currentURI.spec;
|
||||
aTab.__thumbnail = img;
|
||||
aTab.__thumbnail_lastURI = uri;
|
||||
return img;
|
||||
}
|
||||
|
||||
return thumbnail;
|
||||
let canvas = PageThumbs.createCanvas(window);
|
||||
|
||||
if (aShouldCache) {
|
||||
aTab.__thumbnail = canvas;
|
||||
aTab.__thumbnail_lastURI = uri;
|
||||
}
|
||||
|
||||
PageThumbs.captureToCanvas(aTab.linkedBrowser.contentWindow, canvas);
|
||||
return canvas;
|
||||
},
|
||||
|
||||
handleEvent: function tabPreviews_handleEvent(event) {
|
||||
@ -182,8 +180,7 @@ var ctrlTab = {
|
||||
get isOpen () this.panel.state == "open" || this.panel.state == "showing" || this._timer,
|
||||
get tabCount () this.tabList.length,
|
||||
get tabPreviewCount () Math.min(this.previews.length - 1, this.tabCount),
|
||||
get canvasWidth () Math.min(tabPreviews.width,
|
||||
Math.ceil(screen.availWidth * .85 / this.tabPreviewCount)),
|
||||
get canvasWidth () Math.ceil(screen.availWidth * .85 / this.tabPreviewCount),
|
||||
get canvasHeight () Math.round(this.canvasWidth * tabPreviews.aspectRatio),
|
||||
|
||||
get tabList () {
|
||||
@ -505,6 +502,15 @@ var ctrlTab = {
|
||||
}
|
||||
},
|
||||
|
||||
filterForThumbnailExpiration: function (aCallback) {
|
||||
let urls = [];
|
||||
let previewCount = this.tabPreviewCount;
|
||||
for (let i = 0; i < previewCount; i++)
|
||||
urls.push(this.tabList[i].linkedBrowser.currentURI.spec);
|
||||
|
||||
aCallback(urls);
|
||||
},
|
||||
|
||||
_initRecentlyUsedTabs: function () {
|
||||
this._recentlyUsedTabs =
|
||||
Array.filter(gBrowser.tabs, tab => !tab.closing)
|
||||
@ -525,6 +531,11 @@ var ctrlTab = {
|
||||
document[toggleEventListener]("keypress", this, false);
|
||||
gBrowser.mTabBox.handleCtrlTab = !enable;
|
||||
|
||||
if (enable)
|
||||
PageThumbs.addExpirationFilter(this);
|
||||
else
|
||||
PageThumbs.removeExpirationFilter(this);
|
||||
|
||||
// If we're not running, hide the "Show All Tabs" menu item,
|
||||
// as Shift+Ctrl+Tab will be handled by the tab bar.
|
||||
document.getElementById("menu_showAllTabs").hidden = !enable;
|
||||
|
@ -103,7 +103,9 @@ let gBrowserThumbnails = {
|
||||
},
|
||||
|
||||
_capture: function Thumbnails_capture(aBrowser) {
|
||||
if (this._shouldCapture(aBrowser))
|
||||
// Only capture about:newtab top sites.
|
||||
if (this._topSiteURLs.indexOf(aBrowser.currentURI.spec) >= 0 &&
|
||||
this._shouldCapture(aBrowser))
|
||||
PageThumbs.captureAndStoreIfStale(aBrowser);
|
||||
},
|
||||
|
||||
@ -121,15 +123,12 @@ let gBrowserThumbnails = {
|
||||
this._timeouts.set(aBrowser, timeout);
|
||||
},
|
||||
|
||||
// FIXME: This should be part of the PageThumbs API. (bug 1062414)
|
||||
_shouldCapture: function Thumbnails_shouldCapture(aBrowser) {
|
||||
// Capture only if it's the currently selected tab.
|
||||
if (aBrowser != gBrowser.selectedBrowser)
|
||||
return false;
|
||||
|
||||
// Only capture about:newtab top sites.
|
||||
if (this._topSiteURLs.indexOf(aBrowser.currentURI.spec) < 0)
|
||||
return false;
|
||||
|
||||
// Don't capture in per-window private browsing mode.
|
||||
if (PrivateBrowsingUtils.isWindowPrivate(window))
|
||||
return false;
|
||||
|
@ -672,33 +672,17 @@ var gPopupBlockerObserver = {
|
||||
}
|
||||
};
|
||||
|
||||
function gKeywordURIFixup(fixupInfo, topic, data) {
|
||||
fixupInfo.QueryInterface(Ci.nsIURIFixupInfo);
|
||||
function gKeywordURIFixup({ target: browser, data: fixupInfo }) {
|
||||
let deserializeURI = (spec) => spec ? makeURI(spec) : null;
|
||||
|
||||
// We get called irrespective of whether we did a keyword search, or
|
||||
// whether the original input would be vaguely interpretable as a URL,
|
||||
// so figure that out first.
|
||||
let alternativeURI = fixupInfo.fixedURI;
|
||||
let alternativeURI = deserializeURI(fixupInfo.fixedURI);
|
||||
if (!fixupInfo.fixupUsedKeyword || !alternativeURI) {
|
||||
return;
|
||||
}
|
||||
|
||||
// We should have a document loader...
|
||||
let docshellRef = fixupInfo.consumer;
|
||||
try {
|
||||
docshellRef.QueryInterface(Ci.nsIDocumentLoader);
|
||||
} catch (ex) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (!docshellRef.document)
|
||||
return;
|
||||
|
||||
// ... from which we can deduce the browser
|
||||
let browser = gBrowser.getBrowserForDocument(docshellRef.document);
|
||||
if (!browser)
|
||||
return;
|
||||
|
||||
// At this point we're still only just about to load this URI.
|
||||
// When the async DNS lookup comes back, we may be in any of these states:
|
||||
// 1) still on the previous URI, waiting for the preferredURI (keyword
|
||||
@ -708,6 +692,7 @@ function gKeywordURIFixup(fixupInfo, topic, data) {
|
||||
// We keep track of the currentURI to detect case (1) in the DNS lookup
|
||||
// callback.
|
||||
let previousURI = browser.currentURI;
|
||||
let preferredURI = deserializeURI(fixupInfo.preferredURI);
|
||||
|
||||
// now swap for a weak ref so we don't hang on to browser needlessly
|
||||
// even if the DNS query takes forever
|
||||
@ -738,7 +723,7 @@ function gKeywordURIFixup(fixupInfo, topic, data) {
|
||||
let currentURI = browser.currentURI;
|
||||
// If we're in case (3) (see above), don't show an info bar.
|
||||
if (!currentURI.equals(previousURI) &&
|
||||
!currentURI.equals(fixupInfo.preferredURI)) {
|
||||
!currentURI.equals(preferredURI)) {
|
||||
return;
|
||||
}
|
||||
|
||||
@ -1025,15 +1010,12 @@ var gBrowserInit = {
|
||||
|
||||
// This pageshow listener needs to be registered before we may call
|
||||
// swapBrowsersAndCloseOther() to receive pageshow events fired by that.
|
||||
if (!gMultiProcessBrowser) {
|
||||
// pageshow handlers are being migrated to
|
||||
// content.js. Eventually this code should be removed.
|
||||
gBrowser.addEventListener("pageshow", function(event) {
|
||||
// Filter out events that are not about the document load we are interested in
|
||||
if (content && event.target == content.document)
|
||||
setTimeout(pageShowEventHandlers, 0, event.persisted);
|
||||
}, true);
|
||||
}
|
||||
let mm = window.messageManager;
|
||||
mm.addMessageListener("PageVisibility:Show", function(message) {
|
||||
if (message.target == gBrowser.selectedBrowser) {
|
||||
setTimeout(pageShowEventHandlers, 0, message.data.persisted);
|
||||
}
|
||||
});
|
||||
|
||||
if (uriToLoad && uriToLoad != "about:blank") {
|
||||
if (uriToLoad instanceof Ci.nsISupportsArray) {
|
||||
@ -1087,7 +1069,7 @@ var gBrowserInit = {
|
||||
Services.obs.addObserver(gXPInstallObserver, "addon-install-blocked", false);
|
||||
Services.obs.addObserver(gXPInstallObserver, "addon-install-failed", false);
|
||||
Services.obs.addObserver(gXPInstallObserver, "addon-install-complete", false);
|
||||
Services.obs.addObserver(gKeywordURIFixup, "keyword-uri-fixup", false);
|
||||
window.messageManager.addMessageListener("Browser:URIFixup", gKeywordURIFixup);
|
||||
|
||||
BrowserOffline.init();
|
||||
OfflineApps.init();
|
||||
@ -1393,7 +1375,7 @@ var gBrowserInit = {
|
||||
Services.obs.removeObserver(gXPInstallObserver, "addon-install-blocked");
|
||||
Services.obs.removeObserver(gXPInstallObserver, "addon-install-failed");
|
||||
Services.obs.removeObserver(gXPInstallObserver, "addon-install-complete");
|
||||
Services.obs.removeObserver(gKeywordURIFixup, "keyword-uri-fixup");
|
||||
window.messageManager.removeMessageListener("Browser:URIFixup", gKeywordURIFixup);
|
||||
|
||||
try {
|
||||
gPrefService.removeObserver(gHomeButton.prefDomain, gHomeButton);
|
||||
@ -3561,42 +3543,11 @@ var XULBrowserWindow = {
|
||||
|
||||
// Called before links are navigated to to allow us to retarget them if needed.
|
||||
onBeforeLinkTraversal: function(originalTarget, linkURI, linkNode, isAppTab) {
|
||||
let target = this._onBeforeLinkTraversal(originalTarget, linkURI, linkNode, isAppTab);
|
||||
let target = BrowserUtils.onBeforeLinkTraversal(originalTarget, linkURI, linkNode, isAppTab);
|
||||
SocialUI.closeSocialPanelForLinkTraversal(target, linkNode);
|
||||
return target;
|
||||
},
|
||||
|
||||
_onBeforeLinkTraversal: function(originalTarget, linkURI, linkNode, isAppTab) {
|
||||
// Don't modify non-default targets or targets that aren't in top-level app
|
||||
// tab docshells (isAppTab will be false for app tab subframes).
|
||||
if (originalTarget != "" || !isAppTab)
|
||||
return originalTarget;
|
||||
|
||||
// External links from within app tabs should always open in new tabs
|
||||
// instead of replacing the app tab's page (Bug 575561)
|
||||
let linkHost;
|
||||
let docHost;
|
||||
try {
|
||||
linkHost = linkURI.host;
|
||||
docHost = linkNode.ownerDocument.documentURIObject.host;
|
||||
} catch(e) {
|
||||
// nsIURI.host can throw for non-nsStandardURL nsIURIs.
|
||||
// If we fail to get either host, just return originalTarget.
|
||||
return originalTarget;
|
||||
}
|
||||
|
||||
if (docHost == linkHost)
|
||||
return originalTarget;
|
||||
|
||||
// Special case: ignore "www" prefix if it is part of host string
|
||||
let [longHost, shortHost] =
|
||||
linkHost.length > docHost.length ? [linkHost, docHost] : [docHost, linkHost];
|
||||
if (longHost == "www." + shortHost)
|
||||
return originalTarget;
|
||||
|
||||
return "_blank";
|
||||
},
|
||||
|
||||
onProgressChange: function (aWebProgress, aRequest,
|
||||
aCurSelfProgress, aMaxSelfProgress,
|
||||
aCurTotalProgress, aMaxTotalProgress) {
|
||||
@ -7367,9 +7318,17 @@ let ToolbarIconColor = {
|
||||
toolbarSelector += ":not([type=menubar])";
|
||||
#endif
|
||||
|
||||
// The getComputedStyle calls and setting the brighttext are separated in
|
||||
// two loops to avoid flushing layout and making it dirty repeatedly.
|
||||
|
||||
let luminances = new Map;
|
||||
for (let toolbar of document.querySelectorAll(toolbarSelector)) {
|
||||
let [r, g, b] = parseRGB(getComputedStyle(toolbar).color);
|
||||
let luminance = 0.2125 * r + 0.7154 * g + 0.0721 * b;
|
||||
luminances.set(toolbar, luminance);
|
||||
}
|
||||
|
||||
for (let [toolbar, luminance] of luminances) {
|
||||
if (luminance <= 110)
|
||||
toolbar.removeAttribute("brighttext");
|
||||
else
|
||||
|
@ -633,3 +633,54 @@ let DOMFullscreenHandler = {
|
||||
}
|
||||
};
|
||||
DOMFullscreenHandler.init();
|
||||
|
||||
function gKeywordURIFixup(fixupInfo) {
|
||||
fixupInfo.QueryInterface(Ci.nsIURIFixupInfo);
|
||||
|
||||
// Ignore info from other docshells
|
||||
let parent = fixupInfo.consumer.QueryInterface(Ci.nsIDocShellTreeItem).sameTypeRootTreeItem;
|
||||
if (parent != docShell)
|
||||
return;
|
||||
|
||||
let data = {};
|
||||
for (let f of Object.keys(fixupInfo)) {
|
||||
if (f == "consumer" || typeof fixupInfo[f] == "function")
|
||||
continue;
|
||||
|
||||
if (fixupInfo[f] && fixupInfo[f] instanceof Ci.nsIURI) {
|
||||
data[f] = fixupInfo[f].spec;
|
||||
} else {
|
||||
data[f] = fixupInfo[f];
|
||||
}
|
||||
}
|
||||
|
||||
sendAsyncMessage("Browser:URIFixup", data);
|
||||
}
|
||||
Services.obs.addObserver(gKeywordURIFixup, "keyword-uri-fixup", false);
|
||||
addEventListener("unload", () => {
|
||||
Services.obs.removeObserver(gKeywordURIFixup, "keyword-uri-fixup");
|
||||
}, false);
|
||||
|
||||
addMessageListener("Browser:AppTab", function(message) {
|
||||
docShell.isAppTab = message.data.isAppTab;
|
||||
});
|
||||
|
||||
let WebBrowserChrome = {
|
||||
onBeforeLinkTraversal: function(originalTarget, linkURI, linkNode, isAppTab) {
|
||||
return BrowserUtils.onBeforeLinkTraversal(originalTarget, linkURI, linkNode, isAppTab);
|
||||
},
|
||||
};
|
||||
|
||||
if (Services.appinfo.processType == Services.appinfo.PROCESS_TYPE_CONTENT) {
|
||||
let tabchild = docShell.QueryInterface(Ci.nsIInterfaceRequestor)
|
||||
.getInterface(Ci.nsITabChild);
|
||||
tabchild.webBrowserChrome = WebBrowserChrome;
|
||||
}
|
||||
|
||||
addEventListener("pageshow", function(event) {
|
||||
if (event.target == content.document) {
|
||||
sendAsyncMessage("PageVisibility:Show", {
|
||||
persisted: event.persisted,
|
||||
});
|
||||
}
|
||||
});
|
||||
|
@ -289,9 +289,7 @@
|
||||
this.tabContainer._positionPinnedTabs();
|
||||
this.tabContainer.adjustTabstrip();
|
||||
|
||||
// Bug 961867 - [e10s] Implement the logic for app tabs
|
||||
if (!gMultiProcessBrowser)
|
||||
this.getBrowserForTab(aTab).docShell.isAppTab = true;
|
||||
this.getBrowserForTab(aTab).messageManager.sendAsyncMessage("Browser:AppTab", { isAppTab: true })
|
||||
|
||||
if (aTab.selected)
|
||||
this._setCloseKeyState(false);
|
||||
@ -315,9 +313,7 @@
|
||||
this.tabContainer._positionPinnedTabs();
|
||||
this.tabContainer.adjustTabstrip();
|
||||
|
||||
// Bug 961867 - [e10s] Implement the logic for app tabs
|
||||
if (!gMultiProcessBrowser)
|
||||
this.getBrowserForTab(aTab).docShell.isAppTab = false;
|
||||
this.getBrowserForTab(aTab).messageManager.sendAsyncMessage("Browser:AppTab", { isAppTab: false })
|
||||
|
||||
if (aTab.selected)
|
||||
this._setCloseKeyState(true);
|
||||
@ -5330,7 +5326,8 @@
|
||||
let switchPromise = gBrowser._prepareForTabSwitch(toTab, fromTab);
|
||||
|
||||
var panel = this._selectedPanel;
|
||||
this._selectedPanel = this.childNodes[val];
|
||||
var newPanel = this.childNodes[val];
|
||||
this._selectedPanel = newPanel;
|
||||
if (this._selectedPanel != panel) {
|
||||
var event = document.createEvent("Events");
|
||||
event.initEvent("select", true, true);
|
||||
@ -5340,8 +5337,16 @@
|
||||
this._selectedIndex = val;
|
||||
|
||||
switchPromise.then(() => {
|
||||
this.setAttribute("selectedIndex", val);
|
||||
gBrowser._finalizeTabSwitch(toTab, fromTab);
|
||||
// If we cannot find the tabpanel that we were trying to switch to, then
|
||||
// it must have been removed before our Promise could be resolved. In
|
||||
// that case, we just cancel the tab switch.
|
||||
var updatedTabIndex = Array.indexOf(this.childNodes, newPanel);
|
||||
if (updatedTabIndex == -1) {
|
||||
gBrowser._cancelTabSwitch(toTab);
|
||||
} else {
|
||||
this.setAttribute("selectedIndex", updatedTabIndex);
|
||||
gBrowser._finalizeTabSwitch(toTab, fromTab);
|
||||
}
|
||||
}, () => {
|
||||
// If the promise rejected, that means we don't want to actually
|
||||
// flip the deck, so we cancel the tab switch.
|
||||
|
@ -1,5 +1,5 @@
|
||||
[DEFAULT]
|
||||
skip-if = buildapp == 'mulet'
|
||||
skip-if = buildapp == 'mulet' || e10s
|
||||
support-files =
|
||||
head.js
|
||||
chat.html
|
||||
|
@ -102,6 +102,7 @@ skip-if = os == "linux" # Bug 924307
|
||||
skip-if = e10s # Bug ?????? - no about:home support yet
|
||||
[browser_aboutSyncProgress.js]
|
||||
[browser_addKeywordSearch.js]
|
||||
skip-if = e10s
|
||||
[browser_alltabslistener.js]
|
||||
skip-if = os == "linux" || e10s # Linux: Intermittent failures, bug 951680; e10s: Bug ?????? - notifications don't work correctly.
|
||||
[browser_backButtonFitts.js]
|
||||
@ -110,10 +111,13 @@ skip-if = os != "win" || e10s # The Fitts Law back button is only supported on W
|
||||
[browser_bookmark_titles.js]
|
||||
skip-if = buildapp == 'mulet' || toolkit == "windows" || e10s # Disabled on Windows due to frequent failures (bugs 825739, 841341) / e10s - Bug ?????? test checks event.target on load event, which our e10s utils don't support
|
||||
[browser_bug304198.js]
|
||||
skip-if = e10s
|
||||
[browser_bug321000.js]
|
||||
skip-if = true # browser_bug321000.js is disabled because newline handling is shaky (bug 592528)
|
||||
[browser_bug329212.js]
|
||||
skip-if = e10s
|
||||
[browser_bug331772_xul_tooltiptext_in_html.js]
|
||||
skip-if = e10s
|
||||
[browser_bug356571.js]
|
||||
[browser_bug380960.js]
|
||||
[browser_bug386835.js]
|
||||
@ -121,8 +125,8 @@ skip-if = e10s # Bug 691614 - no e10s zoom support yet
|
||||
[browser_bug405137.js]
|
||||
[browser_bug406216.js]
|
||||
[browser_bug409481.js]
|
||||
skip-if = e10s # Bug 921952 - Content:Click event issues (test simulated middle-click on a link and checks the value pastes - it doesn't)
|
||||
[browser_bug409624.js]
|
||||
skip-if = e10s
|
||||
[browser_bug413915.js]
|
||||
[browser_bug416661.js]
|
||||
skip-if = e10s # Bug 691614 - no e10s zoom support yet
|
||||
@ -146,6 +150,7 @@ skip-if = buildapp == 'mulet' || e10s # Bug ?????? - test directly manipulates c
|
||||
[browser_bug441778.js]
|
||||
skip-if = buildapp == 'mulet' || e10s # Bug 691614 - no e10s zoom support yet
|
||||
[browser_bug455852.js]
|
||||
skip-if = e10s
|
||||
[browser_bug460146.js]
|
||||
skip-if = e10s # Bug 866413 - PageInfo doesn't work in e10s
|
||||
[browser_bug462289.js]
|
||||
@ -159,6 +164,7 @@ skip-if = buildapp == 'mulet' || e10s # Bug 918663 - DOMLinkAdded events don't m
|
||||
[browser_bug481560.js]
|
||||
skip-if = e10s # Bug ????? - This bug attached an event listener directly to the content
|
||||
[browser_bug484315.js]
|
||||
skip-if = e10s
|
||||
[browser_bug491431.js]
|
||||
skip-if = buildapp == 'mulet' || e10s # Bug 918634 - swapFrameLoaders (and thus replaceTabWithWindow) not implemented for e10s
|
||||
[browser_bug495058.js]
|
||||
@ -188,27 +194,26 @@ skip-if = e10s # Bug 932651 - getClipboardData in specialpowersAPI.js not e10s f
|
||||
[browser_bug559991.js]
|
||||
skip-if = e10s # Bug 691614 - no e10s zoom support yet
|
||||
[browser_bug561623.js]
|
||||
skip-if = e10s
|
||||
[browser_bug561636.js]
|
||||
skip-if = e10s # Bug 691601 - no form submit observers
|
||||
[browser_bug562649.js]
|
||||
skip-if = e10s # Bug 940195 - XULBrowserWindow.isBusy is false as a remote tab starts loading
|
||||
[browser_bug563588.js]
|
||||
[browser_bug565575.js]
|
||||
skip-if = e10s
|
||||
[browser_bug565667.js]
|
||||
run-if = toolkit == "cocoa"
|
||||
[browser_bug567306.js]
|
||||
skip-if = e10s
|
||||
[browser_bug575561.js]
|
||||
skip-if = e10s # Bug 921905 - pinTab/unpinTab fail in e10s
|
||||
[browser_bug575830.js]
|
||||
skip-if = e10s # Bug 691614 - no e10s zoom support yet
|
||||
[browser_bug577121.js]
|
||||
skip-if = e10s # Bug 921905 - pinTab/unpinTab fail in e10s
|
||||
[browser_bug578534.js]
|
||||
skip-if = e10s # Bug ?????? - test directly manipulates content
|
||||
[browser_bug579872.js]
|
||||
skip-if = e10s # Bug 921905 - pinTab/unpinTab fail in e10s
|
||||
[browser_bug580638.js]
|
||||
skip-if = e10s # Bug 921905 - pinTab/unpinTab fail in e10s
|
||||
[browser_bug580956.js]
|
||||
skip-if = e10s # Bug 516755 - SessionStore disabled for e10s
|
||||
[browser_bug581242.js]
|
||||
@ -216,20 +221,18 @@ skip-if = e10s # Bug 930863 - pageshow issues ("TypeError: charset is undefined"
|
||||
[browser_bug581253.js]
|
||||
skip-if = e10s # Bug 930863 - pageshow issues ("TypeError: charset is undefined" in pageshow listener, as document is null)
|
||||
[browser_bug581947.js]
|
||||
skip-if = e10s
|
||||
[browser_bug585558.js]
|
||||
skip-if = e10s # Bug 921905 - pinTab/unpinTab fail in e10s
|
||||
[browser_bug585785.js]
|
||||
[browser_bug585830.js]
|
||||
[browser_bug590206.js]
|
||||
[browser_bug592338.js]
|
||||
skip-if = e10s # Bug 653065 - Make the lightweight theme web installer ready for e10s
|
||||
[browser_bug594131.js]
|
||||
skip-if = e10s # Bug 921905 - pinTab/unpinTab fail in e10s
|
||||
[browser_bug595507.js]
|
||||
skip-if = e10s # Bug 691601 - no form submit observers
|
||||
[browser_bug596687.js]
|
||||
[browser_bug597218.js]
|
||||
skip-if = e10s # Bug 921905 - pinTab/unpinTab fail in e10s
|
||||
[browser_bug609700.js]
|
||||
skip-if = e10s # Bug 516755 - SessionStore disabled for e10s (calls duplicateTabIn, which uses SessionStore)
|
||||
[browser_bug623155.js]
|
||||
@ -242,6 +245,7 @@ skip-if = e10s # Bug ?????? - test directly manipulates content (eg, var expertD
|
||||
[browser_bug647886.js]
|
||||
skip-if = buildapp == 'mulet' || e10s # Bug 916974 - Session history doesn't work in e10s
|
||||
[browser_bug655584.js]
|
||||
skip-if = e10s
|
||||
[browser_bug664672.js]
|
||||
[browser_bug676619.js]
|
||||
skip-if = buildapp == 'mulet' || os == "mac" || e10s # mac: Intermittent failures, bug 925225; e10s: Bug ?????? - test directly manipulates content (event.target.location)
|
||||
@ -258,6 +262,7 @@ skip-if = e10s # Bug ?????? - test directly manipulates content
|
||||
[browser_bug749738.js]
|
||||
skip-if = e10s # Bug 921935 - focusmanager issues with e10s
|
||||
[browser_bug763468_perwindowpb.js]
|
||||
skip-if = e10s
|
||||
[browser_bug767836_perwindowpb.js]
|
||||
skip-if = e10s # Bug ?????? - test reports a leaked nsGlobalWindow with e10s enabled.
|
||||
[browser_bug771331.js]
|
||||
@ -273,6 +278,7 @@ skip-if = e10s # Bug 916974 - Session history doesn't work in e10s
|
||||
[browser_bug880101.js]
|
||||
[browser_bug882977.js]
|
||||
[browser_bug902156.js]
|
||||
skip-if = e10s
|
||||
[browser_bug906190.js]
|
||||
skip-if = buildapp == "mulet" || e10s # Bug ?????? - test directly manipulates content (strange - gets an element from a child which it tries to treat as a string, but that fails)
|
||||
[browser_bug970746.js]
|
||||
@ -282,11 +288,13 @@ skip-if = os == 'win' || e10s # Bug 1056146 - FullZoomHelper uses promiseTabLoad
|
||||
[browser_canonizeURL.js]
|
||||
skip-if = e10s # Bug ?????? - [JavaScript Error: "Error in AboutHome.sendAboutHomeData TypeError: target.messageManager is undefined" {file: "resource:///modules/AboutHome.jsm" line: 208}]
|
||||
[browser_contentAreaClick.js]
|
||||
skip-if = e10s
|
||||
[browser_contextSearchTabPosition.js]
|
||||
skip-if = os == "mac" # bug 967013, bug 926729
|
||||
skip-if = os == "mac" || e10s # bug 967013, bug 926729
|
||||
[browser_ctrlTab.js]
|
||||
skip-if = e10s # Bug ????? - thumbnail captures need e10s love (tabPreviews_capture fails with Argument 1 of CanvasRenderingContext2D.drawWindow does not implement interface Window.)
|
||||
[browser_customize_popupNotification.js]
|
||||
skip-if = e10s
|
||||
[browser_datareporting_notification.js]
|
||||
run-if = datareporting
|
||||
[browser_devices_get_user_media.js]
|
||||
@ -299,11 +307,13 @@ skip-if = e10s # Bug 918663 - DOMLinkAdded events don't make their way to chrome
|
||||
[browser_drag.js]
|
||||
skip-if = true # browser_drag.js is disabled, as it needs to be updated for the new behavior from bug 320638.
|
||||
[browser_favicon_change.js]
|
||||
skip-if = e10s
|
||||
[browser_findbarClose.js]
|
||||
skip-if = e10s # Bug ?????? - test directly manipulates content (tries to grab an iframe directly from content)
|
||||
[browser_fullscreen-window-open.js]
|
||||
skip-if = buildapp == 'mulet' || e10s || os == "linux" # Bug 933103 - mochitest's EventUtils.synthesizeMouse functions not e10s friendly. Linux: Intermittent failures - bug 941575.
|
||||
[browser_fxa_oauth.js]
|
||||
skip-if = e10s
|
||||
[browser_gestureSupport.js]
|
||||
skip-if = e10s # Bug 863514 - no gesture support.
|
||||
[browser_getshortcutoruri.js]
|
||||
@ -323,6 +333,7 @@ skip-if = toolkit == "windows" # Disabled on Windows due to frequent failures (b
|
||||
[browser_locationBarCommand.js]
|
||||
skip-if = os == "linux" || e10s # Linux: Intermittent failures, bug 917535; e10s: Bug ?????? - Focus issues (There should be no focused element - Got [object XULElement], expected null)
|
||||
[browser_locationBarExternalLoad.js]
|
||||
skip-if = e10s
|
||||
[browser_menuButtonFitts.js]
|
||||
skip-if = os != "win" || e10s # The Fitts Law menu button is only supported on Windows (bug 969376); # Bug ?????? - URL bar issues ("There should be no focused element - Got [object XULElement], expected null")
|
||||
[browser_middleMouse_noJSPaste.js]
|
||||
@ -336,18 +347,17 @@ skip-if = buildapp == 'mulet' || e10s # Bug ?????? - uncaught exception - Error:
|
||||
[browser_offlineQuotaNotification.js]
|
||||
skip-if = buildapp == 'mulet' || e10s # Bug ?????? - test directly manipulates content (gBrowser.selectedBrowser.contentWindow.applicationCache.oncached = function() {...})
|
||||
[browser_overflowScroll.js]
|
||||
skip-if = e10s # Bug 921905 - pinTab/unpinTab fail in e10s
|
||||
[browser_pageInfo.js]
|
||||
skip-if = buildapp == 'mulet' || e10s # Bug 866413 - PageInfo doesn't work in e10s
|
||||
[browser_page_style_menu.js]
|
||||
skip-if = e10s # Bug ?????? - test directly manipulates content
|
||||
|
||||
[browser_parsable_css.js]
|
||||
skip-if = e10s
|
||||
[browser_parsable_script.js]
|
||||
skip-if = debug || asan # Times out on debug/asan, and we are less picky about our JS there
|
||||
|
||||
[browser_pinnedTabs.js]
|
||||
skip-if = e10s # Bug 921905 - pinTab/unpinTab fail in e10s
|
||||
[browser_plainTextLinks.js]
|
||||
skip-if = e10s # Bug ?????? - test directly manipulates content (creates and fetches elements directly from content document)
|
||||
[browser_popupUI.js]
|
||||
@ -360,8 +370,8 @@ skip-if = buildapp == 'mulet'
|
||||
skip-if = buildapp == 'mulet'
|
||||
[browser_relatedTabs.js]
|
||||
[browser_removeTabsToTheEnd.js]
|
||||
skip-if = e10s # Bug 921905 - pinTab/unpinTab fail in e10s
|
||||
[browser_removeUnsafeProtocolsFromURLBarPaste.js]
|
||||
skip-if = e10s
|
||||
[browser_sanitize-download-history.js]
|
||||
skip-if = true # bug 432425
|
||||
[browser_sanitize-passwordDisabledHosts.js]
|
||||
@ -382,6 +392,7 @@ skip-if = buildapp == 'mulet' || e10s # e10s: Bug 933103 - mochitest's EventUtil
|
||||
skip-if = buildapp == 'mulet' || e10s # Bug ?????? - test directly manipulates content (event.target)
|
||||
[browser_scope.js]
|
||||
[browser_searchSuggestionUI.js]
|
||||
skip-if = e10s
|
||||
support-files =
|
||||
searchSuggestionUI.html
|
||||
searchSuggestionUI.js
|
||||
@ -391,7 +402,7 @@ skip-if = e10s # Bug ?????? - no idea! "Accel+9 selects expected tab - Got 0, ex
|
||||
skip-if = e10s # Bug ?????? - timeout after logging "Error: Channel closing: too late to send/recv, messages will be lost"
|
||||
[browser_subframe_favicons_not_used.js]
|
||||
[browser_tabDrop.js]
|
||||
skip-if = buildapp == 'mulet'
|
||||
skip-if = buildapp == 'mulet' || e10s
|
||||
[browser_tabMatchesInAwesomebar_perwindowpb.js]
|
||||
skip-if = e10s # Bug 918634 - swapFrameLoaders not implemented for e10s (test uses gBrowser.swapBrowsersAndCloseOther)
|
||||
[browser_tab_drag_drop_perwindow.js]
|
||||
@ -399,19 +410,21 @@ skip-if = buildapp == 'mulet'
|
||||
[browser_tab_dragdrop.js]
|
||||
skip-if = buildapp == 'mulet' || e10s # Bug 918634 - swapFrameLoaders not implemented for e10s (test uses gBrowser.swapBrowsersAndCloseOther)
|
||||
[browser_tab_dragdrop2.js]
|
||||
skip-if = buildapp == 'mulet'
|
||||
skip-if = buildapp == 'mulet' || e10s
|
||||
[browser_tabbar_big_widgets.js]
|
||||
skip-if = os == "linux" || os == "mac" # No tabs in titlebar on linux
|
||||
# Disabled on OS X because of bug 967917
|
||||
[browser_tabfocus.js]
|
||||
skip-if = e10s # Bug 921935 - focusmanager issues with e10s (test calls getFocusedElementForWindow with a content window)
|
||||
[browser_tabkeynavigation.js]
|
||||
skip-if = e10s
|
||||
[browser_tabopen_reflows.js]
|
||||
skip-if = e10s # Bug ?????? - test needs to be updated for e10s (captures a stack that isn't correct in e10s)
|
||||
[browser_tabs_isActive.js]
|
||||
skip-if = e10s # Bug ?????? - test directly manipulates content (tries to get/set attributes directly on content docshell)
|
||||
[browser_tabs_owner.js]
|
||||
[browser_trackingUI.js]
|
||||
skip-if = e10s
|
||||
support-files =
|
||||
trackingPage.html
|
||||
benignPage.html
|
||||
@ -420,7 +433,9 @@ skip-if = buildapp == 'mulet' || e10s # Bug 921935 - focusmanager issues with e1
|
||||
[browser_unloaddialogs.js]
|
||||
skip-if = e10s # Bug ?????? - test uses chrome windowMediator to try and see alert() from content
|
||||
[browser_urlHighlight.js]
|
||||
skip-if = e10s
|
||||
[browser_urlbarAutoFillTrimURLs.js]
|
||||
skip-if = e10s
|
||||
[browser_urlbarCopying.js]
|
||||
skip-if = e10s # Bug 932651 - getClipboardData in specialpowersAPI.js not e10s friendly
|
||||
[browser_urlbarEnter.js]
|
||||
@ -428,9 +443,11 @@ skip-if = e10s # Bug ?????? - obscure non-windows child process crashes on try
|
||||
[browser_urlbarRevert.js]
|
||||
skip-if = e10s # Bug ?????? - ESC reverted the location bar value - Got foobar, expected example.com
|
||||
[browser_urlbarSearchSingleWordNotification.js]
|
||||
skip-if = e10s
|
||||
[browser_urlbarStop.js]
|
||||
skip-if = e10s # Bug ????? - test calls gBrowser.contentWindow.stop
|
||||
[browser_urlbarTrimURLs.js]
|
||||
skip-if = e10s
|
||||
[browser_urlbar_search_healthreport.js]
|
||||
skip-if = e10s # Bug ?????? - FHR tests failing (either with "no data for today" or "2 records for today")
|
||||
[browser_utilityOverlay.js]
|
||||
@ -438,13 +455,10 @@ skip-if = e10s # Bug ?????? - FHR tests failing (either with "no data for today"
|
||||
skip-if = e10s # Bug ?????? - test directly manipulates content
|
||||
[browser_visibleLabel.js]
|
||||
[browser_visibleTabs.js]
|
||||
skip-if = e10s # Bug 921905 - pinTab/unpinTab fail in e10s
|
||||
[browser_visibleTabs_bookmarkAllPages.js]
|
||||
skip-if = true # Bug 1005420 - fails intermittently. also with e10s enabled: bizarre problem with hidden tab having _mouseenter called, via _setPositionalAttributes, and tab not being found resulting in 'candidate is undefined'
|
||||
[browser_visibleTabs_bookmarkAllTabs.js]
|
||||
skip-if = e10s # Bug 921905 - pinTab/unpinTab fail in e10s
|
||||
[browser_visibleTabs_contextMenu.js]
|
||||
skip-if = e10s # Bug 921905 - pinTab/unpinTab fail in e10s
|
||||
[browser_visibleTabs_tabPreview.js]
|
||||
skip-if = (os == "win" && !debug) || e10s # Bug 1007418 / Bug 698371 - thumbnail captures need e10s love (tabPreviews_capture fails with Argument 1 of CanvasRenderingContext2D.drawWindow does not implement interface Window.)
|
||||
[browser_web_channel.js]
|
||||
@ -459,8 +473,11 @@ skip-if = e10s # Bug 940206 - nsIWebContentHandlerRegistrar::registerProtocolHan
|
||||
[browser_no_mcb_on_http_site.js]
|
||||
skip-if = e10s # Bug 516755 - SessionStore disabled for e10s
|
||||
[browser_bug1003461-switchtab-override.js]
|
||||
skip-if = e10s
|
||||
[browser_bug1024133-switchtab-override-keynav.js]
|
||||
skip-if = e10s
|
||||
[browser_bug1025195_switchToTabHavingURI_ignoreFragment.js]
|
||||
[browser_addCertException.js]
|
||||
skip-if = e10s # Bug ?????? - test directly manipulates content (content.document.getElementById)
|
||||
[browser_bug1045809.js]
|
||||
skip-if = e10s
|
||||
|
@ -43,16 +43,8 @@ function testLink(aLinkIndex, pinTab, expectNewTab, nextTest, testSubFrame) {
|
||||
if (pinTab)
|
||||
gBrowser.pinTab(appTab);
|
||||
gBrowser.selectedTab = appTab;
|
||||
appTab.linkedBrowser.addEventListener("load", onLoad, true);
|
||||
|
||||
let loadCount = 0;
|
||||
function onLoad() {
|
||||
loadCount++;
|
||||
if (loadCount < 2)
|
||||
return;
|
||||
|
||||
appTab.linkedBrowser.removeEventListener("load", onLoad, true);
|
||||
|
||||
waitForDocLoadComplete(appTab.linkedBrowser).then(function() {
|
||||
let browser = gBrowser.getBrowserForTab(appTab);
|
||||
if (testSubFrame)
|
||||
browser = browser.contentDocument.getElementsByTagName("iframe")[0];
|
||||
@ -62,7 +54,7 @@ function testLink(aLinkIndex, pinTab, expectNewTab, nextTest, testSubFrame) {
|
||||
if (expectNewTab)
|
||||
gBrowser.tabContainer.addEventListener("TabOpen", onTabOpen, true);
|
||||
else
|
||||
browser.addEventListener("load", onPageLoad, true);
|
||||
waitForDocLoadComplete(appTab.linkedBrowser).then(onPageLoad);
|
||||
|
||||
info("Clicking " + links[aLinkIndex].textContent);
|
||||
EventUtils.sendMouseEvent({type:"click"}, links[aLinkIndex], browser.contentWindow);
|
||||
@ -80,11 +72,13 @@ function testLink(aLinkIndex, pinTab, expectNewTab, nextTest, testSubFrame) {
|
||||
function onTabOpen(event) {
|
||||
gBrowser.tabContainer.removeEventListener("TabOpen", onTabOpen, true);
|
||||
ok(true, "Link should open a new tab");
|
||||
executeSoon(function(){
|
||||
gBrowser.removeTab(appTab);
|
||||
gBrowser.removeCurrentTab();
|
||||
nextTest();
|
||||
waitForDocLoadComplete(event.target.linkedBrowser).then(function() {
|
||||
executeSoon(function(){
|
||||
gBrowser.removeTab(appTab);
|
||||
gBrowser.removeCurrentTab();
|
||||
nextTest();
|
||||
});
|
||||
});
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
@ -49,14 +49,6 @@ const EXPECTED_REFLOWS = [
|
||||
"ssi_updateWindowFeatures/<@resource:///modules/sessionstore/SessionStore.jsm|" +
|
||||
"ssi_updateWindowFeatures@resource:///modules/sessionstore/SessionStore.jsm|" +
|
||||
"ssi_collectWindowData@resource:///modules/sessionstore/SessionStore.jsm|",
|
||||
|
||||
// tabPreviews.capture()
|
||||
"tabPreviews_capture@chrome://browser/content/browser.js|" +
|
||||
"tabPreviews_handleEvent/<@chrome://browser/content/browser.js|",
|
||||
|
||||
// tabPreviews.capture()
|
||||
"tabPreviews_capture@chrome://browser/content/browser.js|" +
|
||||
"@chrome://browser/content/browser.js|"
|
||||
];
|
||||
|
||||
const PREF_PRELOAD = "browser.newtab.preload";
|
||||
|
@ -15,8 +15,10 @@ function promiseNotificationForTab(aBrowser, value, expected, tab=aBrowser.selec
|
||||
let deferred = Promise.defer();
|
||||
let notificationBox = aBrowser.getNotificationBox(tab.linkedBrowser);
|
||||
if (expected) {
|
||||
info("Waiting for " + value + " notification");
|
||||
let checkForNotification = function() {
|
||||
if (notificationBox.getNotificationWithValue(value)) {
|
||||
info("Saw the notification");
|
||||
notificationObserver.disconnect();
|
||||
notificationObserver = null;
|
||||
deferred.resolve();
|
||||
@ -48,12 +50,13 @@ function* runURLBarSearchTest(valueToOpen, expectSearch, expectNotification, aWi
|
||||
expectedURI = Services.search.defaultEngine.getSubmission(valueToOpen, null, "keyword").uri.spec;
|
||||
}
|
||||
aWindow.gURLBar.focus();
|
||||
let docLoadPromise = waitForDocLoadAndStopIt(expectedURI, aWindow.gBrowser);
|
||||
let docLoadPromise = waitForDocLoadAndStopIt(expectedURI, aWindow.gBrowser.selectedBrowser);
|
||||
EventUtils.synthesizeKey("VK_RETURN", {}, aWindow);
|
||||
|
||||
yield docLoadPromise;
|
||||
|
||||
yield promiseNotificationForTab(aWindow.gBrowser, "keyword-uri-fixup", expectNotification);
|
||||
yield Promise.all([
|
||||
docLoadPromise,
|
||||
promiseNotificationForTab(aWindow.gBrowser, "keyword-uri-fixup", expectNotification)
|
||||
]);
|
||||
}
|
||||
|
||||
add_task(function* test_navigate_full_domain() {
|
||||
@ -88,7 +91,7 @@ function get_test_function_for_localhost_with_hostname(hostName, isPrivate) {
|
||||
|
||||
let notificationBox = browser.getNotificationBox(tab.linkedBrowser);
|
||||
let notification = notificationBox.getNotificationWithValue("keyword-uri-fixup");
|
||||
let docLoadPromise = waitForDocLoadAndStopIt("http://" + hostName + "/", browser);
|
||||
let docLoadPromise = waitForDocLoadAndStopIt("http://" + hostName + "/", tab.linkedBrowser);
|
||||
notification.querySelector(".notification-button-default").click();
|
||||
|
||||
// check pref value
|
||||
|
@ -394,26 +394,66 @@ function promiseClearHistory() {
|
||||
* The URL of the document that is expected to load.
|
||||
* @return promise
|
||||
*/
|
||||
function waitForDocLoadAndStopIt(aExpectedURL, aBrowser=gBrowser) {
|
||||
function waitForDocLoadAndStopIt(aExpectedURL, aBrowser=gBrowser.selectedBrowser) {
|
||||
function content_script() {
|
||||
let { interfaces: Ci, utils: Cu } = Components;
|
||||
Components.utils.import("resource://gre/modules/XPCOMUtils.jsm");
|
||||
let wp = docShell.QueryInterface(Ci.nsIWebProgress);
|
||||
|
||||
let progressListener = {
|
||||
onStateChange: function (webProgress, req, flags, status) {
|
||||
dump("waitForDocLoadAndStopIt: onStateChange " + flags.toString(16) + ": " + req.name + "\n");
|
||||
let docStart = Ci.nsIWebProgressListener.STATE_IS_DOCUMENT |
|
||||
Ci.nsIWebProgressListener.STATE_START;
|
||||
if (((flags & docStart) == docStart) && webProgress.isTopLevel) {
|
||||
dump("waitForDocLoadAndStopIt: Document start: " +
|
||||
req.QueryInterface(Ci.nsIChannel).URI.spec + "\n");
|
||||
req.cancel(Components.results.NS_ERROR_FAILURE);
|
||||
wp.removeProgressListener(progressListener);
|
||||
sendAsyncMessage("Test:WaitForDocLoadAndStopIt", { uri: req.originalURI.spec });
|
||||
}
|
||||
},
|
||||
QueryInterface: XPCOMUtils.generateQI(["nsISupportsWeakReference"])
|
||||
};
|
||||
wp.addProgressListener(progressListener, wp.NOTIFY_ALL);
|
||||
}
|
||||
|
||||
return new Promise((resolve, reject) => {
|
||||
function complete({ data }) {
|
||||
is(data.uri, aExpectedURL, "waitForDocLoadAndStopIt: The expected URL was loaded");
|
||||
mm.removeMessageListener("Test:WaitForDocLoadAndStopIt", complete);
|
||||
resolve();
|
||||
}
|
||||
|
||||
let mm = aBrowser.messageManager;
|
||||
mm.loadFrameScript("data:,(" + content_script.toString() + ")();", true);
|
||||
mm.addMessageListener("Test:WaitForDocLoadAndStopIt", complete);
|
||||
info("waitForDocLoadAndStopIt: Waiting for URL: " + aExpectedURL);
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Waits for the next load to complete in the current browser.
|
||||
*
|
||||
* @return promise
|
||||
*/
|
||||
function waitForDocLoadComplete(aBrowser=gBrowser) {
|
||||
let deferred = Promise.defer();
|
||||
let progressListener = {
|
||||
onStateChange: function (webProgress, req, flags, status) {
|
||||
info("waitForDocLoadAndStopIt: onStateChange: " + req.name);
|
||||
let docStart = Ci.nsIWebProgressListener.STATE_IS_DOCUMENT |
|
||||
Ci.nsIWebProgressListener.STATE_START;
|
||||
if ((flags & docStart) && webProgress.isTopLevel) {
|
||||
info("waitForDocLoadAndStopIt: Document start: " +
|
||||
req.QueryInterface(Ci.nsIChannel).URI.spec);
|
||||
is(req.originalURI.spec, aExpectedURL,
|
||||
"waitForDocLoadAndStopIt: The expected URL was loaded");
|
||||
req.cancel(Components.results.NS_ERROR_FAILURE);
|
||||
let docStart = Ci.nsIWebProgressListener.STATE_IS_NETWORK |
|
||||
Ci.nsIWebProgressListener.STATE_STOP;
|
||||
if ((flags & docStart) == docStart) {
|
||||
aBrowser.removeProgressListener(progressListener);
|
||||
info("Browser loaded");
|
||||
deferred.resolve();
|
||||
}
|
||||
},
|
||||
QueryInterface: XPCOMUtils.generateQI([Ci.nsIWebProgressListener,
|
||||
Ci.nsISupportsWeakReference])
|
||||
};
|
||||
aBrowser.addProgressListener(progressListener);
|
||||
info("waitForDocLoadAndStopIt: Waiting for URL: " + aExpectedURL);
|
||||
info("Waiting for browser load");
|
||||
return deferred.promise;
|
||||
}
|
||||
|
||||
|
@ -1,5 +1,5 @@
|
||||
[DEFAULT]
|
||||
skip-if = buildapp == "mulet"
|
||||
skip-if = buildapp == "mulet" || e10s
|
||||
support-files =
|
||||
head.js
|
||||
support/test_967000_charEncoding_page.html
|
||||
|
@ -2,7 +2,7 @@
|
||||
support-files = head.js
|
||||
|
||||
[browser_basic_functionality.js]
|
||||
skip-if = buildapp == "mulet"
|
||||
skip-if = buildapp == "mulet" || e10s
|
||||
[browser_first_download_panel.js]
|
||||
skip-if = os == "linux" # Bug 949434
|
||||
[browser_overflow_anchor.js]
|
||||
|
@ -21,7 +21,7 @@ XPCOMUtils.defineLazyModuleGetter(this, "console",
|
||||
*/
|
||||
let MozLoopPushHandler = {
|
||||
// This is the uri of the push server.
|
||||
pushServerUri: Services.prefs.getCharPref("services.push.serverURL"),
|
||||
pushServerUri: undefined,
|
||||
// This is the channel id we're using for notifications
|
||||
channelID: "8b1081ce-9b35-42b5-b8f5-3ff8cb813a50",
|
||||
// This is the UserAgent UUID assigned by the PushServer
|
||||
@ -211,8 +211,51 @@ let MozLoopPushHandler = {
|
||||
}
|
||||
|
||||
this._websocket.protocol = "push-notification";
|
||||
let uri = Services.io.newURI(this.pushServerUri, null, null);
|
||||
this._websocket.asyncOpen(uri, this.pushServerUri, this, null);
|
||||
|
||||
let performOpen = () => {
|
||||
let uri = Services.io.newURI(this.pushServerUri, null, null);
|
||||
this._websocket.asyncOpen(uri, this.pushServerUri, this, null);
|
||||
}
|
||||
|
||||
let pushServerURLFetchError = () => {
|
||||
console.warn("MozLoopPushHandler - Could not retrieve push server URL from Loop server; using default");
|
||||
this.pushServerUri = Services.prefs.getCharPref("services.push.serverURL");
|
||||
performOpen();
|
||||
}
|
||||
|
||||
if (!this.pushServerUri) {
|
||||
// Get push server to use from the Loop server
|
||||
let pushUrlEndpoint = Services.prefs.getCharPref("loop.server") + "/push-server-config";
|
||||
let req = Cc["@mozilla.org/xmlextras/xmlhttprequest;1"].
|
||||
createInstance(Ci.nsIXMLHttpRequest);
|
||||
req.open("GET", pushUrlEndpoint);
|
||||
req.onload = () => {
|
||||
if (req.status >= 200 && req.status < 300) {
|
||||
let pushServerConfig;
|
||||
try {
|
||||
pushServerConfig = JSON.parse(req.responseText);
|
||||
} catch (e) {
|
||||
console.warn("MozLoopPushHandler - Error parsing JSON response for push server URL");
|
||||
pushServerURLFetchError();
|
||||
}
|
||||
if (pushServerConfig.pushServerURI) {
|
||||
this.pushServerUri = pushServerConfig.pushServerURI;
|
||||
performOpen();
|
||||
} else {
|
||||
console.warn("MozLoopPushHandler - push server URL config lacks pushServerURI parameter");
|
||||
pushServerURLFetchError();
|
||||
}
|
||||
} else {
|
||||
console.warn("MozLoopPushHandler - push server URL retrieve error: " + req.status);
|
||||
pushServerURLFetchError();
|
||||
}
|
||||
};
|
||||
req.onerror = pushServerURLFetchError;
|
||||
req.send();
|
||||
} else {
|
||||
// this.pushServerUri already set -- just open the channel
|
||||
performOpen();
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
|
@ -6,7 +6,7 @@ support-files =
|
||||
|
||||
[browser_CardDavImporter.js]
|
||||
[browser_fxa_login.js]
|
||||
skip-if = !debug
|
||||
skip-if = !debug || e10s
|
||||
[browser_loop_fxa_server.js]
|
||||
[browser_LoopContacts.js]
|
||||
[browser_mozLoop_appVersionInfo.js]
|
||||
|
@ -57,9 +57,17 @@ function loadLoopPanel() {
|
||||
Services.prefs.setCharPref("services.push.serverURL", "ws://localhost/");
|
||||
Services.prefs.setCharPref("loop.server", "http://localhost/");
|
||||
|
||||
// Turn off the network for loop tests, so that we don't
|
||||
// try to access the remote servers. If we want to turn this
|
||||
// back on in future, be careful to check for intermittent
|
||||
// failures.
|
||||
let wasOffline = Services.io.offline;
|
||||
Services.io.offline = true;
|
||||
|
||||
registerCleanupFunction(function() {
|
||||
Services.prefs.clearUserPref("services.push.serverURL");
|
||||
Services.prefs.clearUserPref("loop.server");
|
||||
Services.io.offline = wasOffline;
|
||||
});
|
||||
|
||||
// Turn off animations to make tests quicker.
|
||||
|
@ -54,6 +54,8 @@
|
||||
});
|
||||
|
||||
function run_test() {
|
||||
setupFakeLoopServer();
|
||||
|
||||
Services.prefs.setCharPref("services.push.serverURL", kServerPushUrl);
|
||||
Services.prefs.setIntPref("loop.retry_delay.start", 10); // 10 ms
|
||||
Services.prefs.setIntPref("loop.retry_delay.limit", 20); // 20 ms
|
||||
|
@ -7,6 +7,8 @@ function expiryTimePref() {
|
||||
|
||||
function run_test()
|
||||
{
|
||||
setupFakeLoopServer();
|
||||
|
||||
Services.prefs.setIntPref("loop.urlsExpiryTimeSeconds", 0);
|
||||
|
||||
MozLoopService.noteCallUrlExpiry(1000);
|
||||
|
@ -50,6 +50,8 @@ add_task(function test_initialize_starts_timer() {
|
||||
|
||||
function run_test()
|
||||
{
|
||||
setupFakeLoopServer();
|
||||
|
||||
// Override MozLoopService's initializeTimer, so that we can verify the timeout is called
|
||||
// correctly.
|
||||
MozLoopService.initializeTimerFunc = function() {
|
||||
|
@ -22,6 +22,8 @@ function test_getStrings() {
|
||||
|
||||
function run_test()
|
||||
{
|
||||
setupFakeLoopServer();
|
||||
|
||||
test_locale();
|
||||
test_getStrings();
|
||||
}
|
||||
|
@ -89,6 +89,8 @@ function test_getLoopBoolPref_not_found()
|
||||
|
||||
function run_test()
|
||||
{
|
||||
setupFakeLoopServer();
|
||||
|
||||
test_getLoopCharPref();
|
||||
test_getLoopCharPref_not_found();
|
||||
test_getLoopCharPref_non_coercible_type();
|
||||
|
@ -15,6 +15,7 @@ support-files =
|
||||
[browser_library_left_pane_fixnames.js]
|
||||
[browser_425884.js]
|
||||
[browser_475045.js]
|
||||
skip-if = e10s
|
||||
[browser_423515.js]
|
||||
[browser_410196_paste_into_tags.js]
|
||||
skip-if = e10s # Bug ?????? - clipboard operations don't seem to work in this test?
|
||||
@ -24,6 +25,7 @@ skip-if = e10s # Bug ?????? - clipboard operations don't seem to work in this te
|
||||
[browser_library_search.js]
|
||||
[browser_history_sidebar_search.js]
|
||||
[browser_bookmarksProperties.js]
|
||||
skip-if = e10s
|
||||
|
||||
[browser_forgetthissite_single.js]
|
||||
# disabled for very frequent oranges - bug 551540
|
||||
@ -46,10 +48,13 @@ skip-if = e10s # Bug 933103 - mochitest's EventUtils.synthesizeMouse functions n
|
||||
[browser_toolbar_migration.js]
|
||||
[browser_library_batch_delete.js]
|
||||
[browser_555547.js]
|
||||
skip-if = e10s
|
||||
[browser_416459_cut.js]
|
||||
skip-if = e10s # Bug ?????? - clipboard operations don't seem to work in this test?
|
||||
[browser_library_downloads.js]
|
||||
[browser_library_left_pane_select_hierarchy.js]
|
||||
[browser_435851_copy_query.js]
|
||||
skip-if = e10s
|
||||
[browser_toolbarbutton_menu_context.js]
|
||||
skip-if = e10s
|
||||
[browser_library_openFlatContainer.js]
|
||||
|
@ -62,8 +62,8 @@ var gAdvancedPane = {
|
||||
gAdvancedPane.clearOfflineAppCache);
|
||||
setEventListener("offlineNotifyExceptions", "command",
|
||||
gAdvancedPane.showOfflineExceptions);
|
||||
setEventListener("offlineNotifyExceptions", "command", function (event) {
|
||||
gAdvancedPane.offlineAppSelected(event); })
|
||||
setEventListener("offlineAppsList", "select",
|
||||
gAdvancedPane.offlineAppSelected);
|
||||
let bundlePrefs = document.getElementById("bundlePreferences");
|
||||
document.getElementById("offlineAppsList")
|
||||
.style.height = bundlePrefs.getString("offlineAppsList.height");
|
||||
@ -72,9 +72,9 @@ var gAdvancedPane = {
|
||||
#ifdef MOZ_UPDATER
|
||||
setEventListener("updateRadioGroup", "command",
|
||||
gAdvancedPane.updateWritePrefs);
|
||||
#endif
|
||||
setEventListener("showUpdateHistory", "command",
|
||||
gAdvancedPane.showUpdates);
|
||||
#endif
|
||||
setEventListener("viewCertificatesButton", "command",
|
||||
gAdvancedPane.showCertificates);
|
||||
setEventListener("viewSecurityDevicesButton", "command",
|
||||
|
@ -1,5 +1,5 @@
|
||||
[DEFAULT]
|
||||
skip-if = buildapp == "mulet"
|
||||
skip-if = buildapp == "mulet" || e10s
|
||||
support-files =
|
||||
head.js
|
||||
privacypane_tests_perwindow.js
|
||||
@ -17,5 +17,7 @@ skip-if = !healthreport || (os == 'linux' && debug)
|
||||
[browser_privacypane_1.js]
|
||||
[browser_privacypane_3.js]
|
||||
[browser_privacypane_4.js]
|
||||
skip-if = e10s # leaks windows
|
||||
[browser_privacypane_5.js]
|
||||
skip-if = e10s # leaks windows
|
||||
[browser_privacypane_8.js]
|
||||
|
@ -1,5 +1,5 @@
|
||||
[DEFAULT]
|
||||
skip-if = buildapp == "mulet"
|
||||
skip-if = buildapp == "mulet" || e10s
|
||||
support-files =
|
||||
browser_privatebrowsing_concurrent_page.html
|
||||
browser_privatebrowsing_cookieacceptdialog.html
|
||||
@ -17,19 +17,14 @@ support-files =
|
||||
|
||||
[browser_privatebrowsing_DownloadLastDirWithCPS.js]
|
||||
[browser_privatebrowsing_aboutHomeButtonAfterWindowClose.js]
|
||||
skip-if = e10s # Bug ?????? - test directly manipulates content (win.getComputedStyle(win.gBrowser.contentDocument.getElementById("restorePreviousSession")))
|
||||
[browser_privatebrowsing_aboutSessionRestore.js]
|
||||
skip-if = e10s # Bug ?????? - "leaked until shutdown [nsGlobalWindow...]"
|
||||
[browser_privatebrowsing_cache.js]
|
||||
[browser_privatebrowsing_certexceptionsui.js]
|
||||
[browser_privatebrowsing_concurrent.js]
|
||||
skip-if = e10s # Bug ?????? - test directly manipulates content (private_tab.docShell.QueryInterface...)
|
||||
[browser_privatebrowsing_cookieacceptdialog.js]
|
||||
[browser_privatebrowsing_crh.js]
|
||||
[browser_privatebrowsing_downloadLastDir.js]
|
||||
skip-if = e10s # Bug ?????? MockFilePicker cleanup failing ( nsresult: "0x80040154 (NS_ERROR_FACTORY_NOT_REGISTERED)" location: "JS frame :: resource://specialpowers/MockFilePicker.jsm :: this.MockFilePicker.cleanup :: line 84")
|
||||
[browser_privatebrowsing_downloadLastDir_c.js]
|
||||
skip-if = e10s # Bug ?????? MockFilePicker cleanup failing ( nsresult: "0x80040154 (NS_ERROR_FACTORY_NOT_REGISTERED)" location: "JS frame :: resource://specialpowers/MockFilePicker.jsm :: this.MockFilePicker.cleanup :: line 84")
|
||||
[browser_privatebrowsing_downloadLastDir_toggle.js]
|
||||
[browser_privatebrowsing_geoprompt.js]
|
||||
[browser_privatebrowsing_lastpbcontextexited.js]
|
||||
@ -47,8 +42,5 @@ skip-if = e10s # Bug ?????? MockFilePicker cleanup failing ( nsresult: "0x800401
|
||||
[browser_privatebrowsing_ui.js]
|
||||
[browser_privatebrowsing_urlbarfocus.js]
|
||||
[browser_privatebrowsing_windowtitle.js]
|
||||
skip-if = e10s # Bug 918634 - swapFrameLoaders
|
||||
[browser_privatebrowsing_zoom.js]
|
||||
skip-if = e10s # Bug 691614 - e10s support for content zooming
|
||||
[browser_privatebrowsing_zoomrestore.js]
|
||||
skip-if = e10s # Bug 691614 - e10s support for content zooming
|
||||
|
@ -2,6 +2,7 @@
|
||||
support-files = head.js
|
||||
|
||||
[browser_bug400731.js]
|
||||
skip-if = e10s
|
||||
[browser_bug415846.js]
|
||||
skip-if = true
|
||||
# Disabled because it seems to now touch network resources
|
||||
|
@ -6,5 +6,6 @@ support-files =
|
||||
|
||||
[browser_translation_bing.js]
|
||||
[browser_translation_fhr.js]
|
||||
skip-if = e10s
|
||||
[browser_translation_infobar.js]
|
||||
[browser_translation_exceptions.js]
|
||||
|
@ -1,3 +1,4 @@
|
||||
. "$topsrcdir/build/mozconfig.win-common"
|
||||
. "$topsrcdir/browser/config/mozconfigs/win64/common-win64"
|
||||
. "$topsrcdir/browser/config/mozconfigs/win64/common-opt"
|
||||
|
||||
|
@ -1,5 +1,6 @@
|
||||
# This make file should be identical to the beta mozconfig, apart from the
|
||||
# safeguard below
|
||||
. "$topsrcdir/build/mozconfig.win-common"
|
||||
. "$topsrcdir/browser/config/mozconfigs/win64/common-win64"
|
||||
. "$topsrcdir/browser/config/mozconfigs/win64/common-opt"
|
||||
|
||||
|
@ -76,6 +76,9 @@ const TEST_DATA = [
|
||||
" var handler9 = function divKeyDown() {\n" +
|
||||
" alert(9);\n" +
|
||||
" };\n" +
|
||||
" var handler10 = function divDragOut() {\n" +
|
||||
" alert(10);\n" +
|
||||
" };\n" +
|
||||
"\n" +
|
||||
" if ($(\"#livediv\").live) {\n" +
|
||||
" $(\"#livediv\").live(\"dblclick\", handler1);\n" +
|
||||
@ -90,6 +93,7 @@ const TEST_DATA = [
|
||||
" if ($(\"#livediv\").on) {\n" +
|
||||
" $(document).on(\"drop\", \"#livediv\", handler5);\n" +
|
||||
" $(document).on(\"dragover\", \"#livediv\", handler6);\n" +
|
||||
" $(document).on(\"dragout\", \"#livediv:xxxxx\", handler10);\n" +
|
||||
" }\n" +
|
||||
"\n" +
|
||||
" var div = $(\"div\")[0];\n" +
|
||||
|
@ -80,6 +80,9 @@ const TEST_DATA = [
|
||||
" var handler9 = function divKeyDown() {\n" +
|
||||
" alert(9);\n" +
|
||||
" };\n" +
|
||||
" var handler10 = function divDragOut() {\n" +
|
||||
" alert(10);\n" +
|
||||
" };\n" +
|
||||
"\n" +
|
||||
" if ($(\"#livediv\").live) {\n" +
|
||||
" $(\"#livediv\").live(\"dblclick\", handler1);\n" +
|
||||
@ -94,6 +97,7 @@ const TEST_DATA = [
|
||||
" if ($(\"#livediv\").on) {\n" +
|
||||
" $(document).on(\"drop\", \"#livediv\", handler5);\n" +
|
||||
" $(document).on(\"dragover\", \"#livediv\", handler6);\n" +
|
||||
" $(document).on(\"dragout\", \"#livediv:xxxxx\", handler10);\n" +
|
||||
" }\n" +
|
||||
"\n" +
|
||||
" var div = $(\"div\")[0];\n" +
|
||||
|
@ -51,6 +51,9 @@ const TEST_DATA = [
|
||||
" var handler9 = function divKeyDown() {\n" +
|
||||
" alert(9);\n" +
|
||||
" };\n" +
|
||||
" var handler10 = function divDragOut() {\n" +
|
||||
" alert(10);\n" +
|
||||
" };\n" +
|
||||
"\n" +
|
||||
" if ($(\"#livediv\").live) {\n" +
|
||||
" $(\"#livediv\").live(\"dblclick\", handler1);\n" +
|
||||
@ -65,6 +68,7 @@ const TEST_DATA = [
|
||||
" if ($(\"#livediv\").on) {\n" +
|
||||
" $(document).on(\"drop\", \"#livediv\", handler5);\n" +
|
||||
" $(document).on(\"dragover\", \"#livediv\", handler6);\n" +
|
||||
" $(document).on(\"dragout\", \"#livediv:xxxxx\", handler10);\n" +
|
||||
" }\n" +
|
||||
"\n" +
|
||||
" var div = $(\"div\")[0];\n" +
|
||||
|
@ -51,6 +51,9 @@ const TEST_DATA = [
|
||||
" var handler9 = function divKeyDown() {\n" +
|
||||
" alert(9);\n" +
|
||||
" };\n" +
|
||||
" var handler10 = function divDragOut() {\n" +
|
||||
" alert(10);\n" +
|
||||
" };\n" +
|
||||
"\n" +
|
||||
" if ($(\"#livediv\").live) {\n" +
|
||||
" $(\"#livediv\").live(\"dblclick\", handler1);\n" +
|
||||
@ -65,6 +68,7 @@ const TEST_DATA = [
|
||||
" if ($(\"#livediv\").on) {\n" +
|
||||
" $(document).on(\"drop\", \"#livediv\", handler5);\n" +
|
||||
" $(document).on(\"dragover\", \"#livediv\", handler6);\n" +
|
||||
" $(document).on(\"dragout\", \"#livediv:xxxxx\", handler10);\n" +
|
||||
" }\n" +
|
||||
"\n" +
|
||||
" var div = $(\"div\")[0];\n" +
|
||||
|
@ -81,6 +81,9 @@ const TEST_DATA = [
|
||||
" var handler9 = function divKeyDown() {\n" +
|
||||
" alert(9);\n" +
|
||||
" };\n" +
|
||||
" var handler10 = function divDragOut() {\n" +
|
||||
" alert(10);\n" +
|
||||
" };\n" +
|
||||
"\n" +
|
||||
" if ($(\"#livediv\").live) {\n" +
|
||||
" $(\"#livediv\").live(\"dblclick\", handler1);\n" +
|
||||
@ -95,6 +98,7 @@ const TEST_DATA = [
|
||||
" if ($(\"#livediv\").on) {\n" +
|
||||
" $(document).on(\"drop\", \"#livediv\", handler5);\n" +
|
||||
" $(document).on(\"dragover\", \"#livediv\", handler6);\n" +
|
||||
" $(document).on(\"dragout\", \"#livediv:xxxxx\", handler10);\n" +
|
||||
" }\n" +
|
||||
"\n" +
|
||||
" var div = $(\"div\")[0];\n" +
|
||||
|
@ -51,6 +51,9 @@ const TEST_DATA = [
|
||||
" var handler9 = function divKeyDown() {\n" +
|
||||
" alert(9);\n" +
|
||||
" };\n" +
|
||||
" var handler10 = function divDragOut() {\n" +
|
||||
" alert(10);\n" +
|
||||
" };\n" +
|
||||
"\n" +
|
||||
" if ($(\"#livediv\").live) {\n" +
|
||||
" $(\"#livediv\").live(\"dblclick\", handler1);\n" +
|
||||
@ -65,6 +68,7 @@ const TEST_DATA = [
|
||||
" if ($(\"#livediv\").on) {\n" +
|
||||
" $(document).on(\"drop\", \"#livediv\", handler5);\n" +
|
||||
" $(document).on(\"dragover\", \"#livediv\", handler6);\n" +
|
||||
" $(document).on(\"dragout\", \"#livediv:xxxxx\", handler10);\n" +
|
||||
" }\n" +
|
||||
"\n" +
|
||||
" var div = $(\"div\")[0];\n" +
|
||||
|
@ -51,6 +51,9 @@ const TEST_DATA = [
|
||||
" var handler9 = function divKeyDown() {\n" +
|
||||
" alert(9);\n" +
|
||||
" };\n" +
|
||||
" var handler10 = function divDragOut() {\n" +
|
||||
" alert(10);\n" +
|
||||
" };\n" +
|
||||
"\n" +
|
||||
" if ($(\"#livediv\").live) {\n" +
|
||||
" $(\"#livediv\").live(\"dblclick\", handler1);\n" +
|
||||
@ -65,6 +68,7 @@ const TEST_DATA = [
|
||||
" if ($(\"#livediv\").on) {\n" +
|
||||
" $(document).on(\"drop\", \"#livediv\", handler5);\n" +
|
||||
" $(document).on(\"dragover\", \"#livediv\", handler6);\n" +
|
||||
" $(document).on(\"dragout\", \"#livediv:xxxxx\", handler10);\n" +
|
||||
" }\n" +
|
||||
"\n" +
|
||||
" var div = $(\"div\")[0];\n" +
|
||||
|
@ -51,6 +51,9 @@ const TEST_DATA = [
|
||||
" var handler9 = function divKeyDown() {\n" +
|
||||
" alert(9);\n" +
|
||||
" };\n" +
|
||||
" var handler10 = function divDragOut() {\n" +
|
||||
" alert(10);\n" +
|
||||
" };\n" +
|
||||
"\n" +
|
||||
" if ($(\"#livediv\").live) {\n" +
|
||||
" $(\"#livediv\").live(\"dblclick\", handler1);\n" +
|
||||
@ -65,6 +68,7 @@ const TEST_DATA = [
|
||||
" if ($(\"#livediv\").on) {\n" +
|
||||
" $(document).on(\"drop\", \"#livediv\", handler5);\n" +
|
||||
" $(document).on(\"dragover\", \"#livediv\", handler6);\n" +
|
||||
" $(document).on(\"dragout\", \"#livediv:xxxxx\", handler10);\n" +
|
||||
" }\n" +
|
||||
"\n" +
|
||||
" var div = $(\"div\")[0];\n" +
|
||||
|
@ -51,6 +51,9 @@ const TEST_DATA = [
|
||||
" var handler9 = function divKeyDown() {\n" +
|
||||
" alert(9);\n" +
|
||||
" };\n" +
|
||||
" var handler10 = function divDragOut() {\n" +
|
||||
" alert(10);\n" +
|
||||
" };\n" +
|
||||
"\n" +
|
||||
" if ($(\"#livediv\").live) {\n" +
|
||||
" $(\"#livediv\").live(\"dblclick\", handler1);\n" +
|
||||
@ -65,6 +68,7 @@ const TEST_DATA = [
|
||||
" if ($(\"#livediv\").on) {\n" +
|
||||
" $(document).on(\"drop\", \"#livediv\", handler5);\n" +
|
||||
" $(document).on(\"dragover\", \"#livediv\", handler6);\n" +
|
||||
" $(document).on(\"dragout\", \"#livediv:xxxxx\", handler10);\n" +
|
||||
" }\n" +
|
||||
"\n" +
|
||||
" var div = $(\"div\")[0];\n" +
|
||||
|
@ -34,6 +34,7 @@
|
||||
var handler7 = function divClick1() { alert(7); };
|
||||
var handler8 = function divClick2() { alert(8); };
|
||||
var handler9 = function divKeyDown() { alert(9); };
|
||||
var handler10 = function divDragOut() { alert(10); };
|
||||
|
||||
if ($("#livediv").live) {
|
||||
$("#livediv").live( "dblclick", handler1);
|
||||
@ -48,6 +49,7 @@
|
||||
if ($("#livediv").on) {
|
||||
$(document).on( "drop", "#livediv", handler5);
|
||||
$(document).on( "dragover", "#livediv", handler6);
|
||||
$(document).on( "dragout", "#livediv:xxxxx", handler10);
|
||||
}
|
||||
|
||||
var div = $("div")[0];
|
||||
|
@ -324,38 +324,83 @@ CssHtmlTree.prototype = {
|
||||
* returns null of the node isn't anything we care about
|
||||
*/
|
||||
getNodeInfo: function(node) {
|
||||
let type, value;
|
||||
if (!node) {
|
||||
return null;
|
||||
}
|
||||
|
||||
let classes = node.classList;
|
||||
|
||||
if (classes.contains("property-name") ||
|
||||
classes.contains("property-value") ||
|
||||
(classes.contains("theme-link") && !classes.contains("link"))) {
|
||||
// Go up to the common parent to find the property and value
|
||||
let parent = node.parentNode;
|
||||
while (!parent.classList.contains("property-view")) {
|
||||
parent = parent.parentNode;
|
||||
// Check if the node isn't a selector first since this doesn't require
|
||||
// walking the DOM
|
||||
if (classes.contains("matched") ||
|
||||
classes.contains("bestmatch") ||
|
||||
classes.contains("parentmatch")) {
|
||||
let selectorText = "";
|
||||
for (let child of node.childNodes) {
|
||||
if (child.nodeType === node.TEXT_NODE) {
|
||||
selectorText += child.textContent;
|
||||
}
|
||||
}
|
||||
return {
|
||||
type: overlays.VIEW_NODE_SELECTOR_TYPE,
|
||||
value: selectorText.trim()
|
||||
}
|
||||
}
|
||||
|
||||
// Walk up the nodes to find out where node is
|
||||
let propertyView;
|
||||
let propertyContent;
|
||||
let parent = node;
|
||||
while (parent.parentNode) {
|
||||
if (parent.classList.contains("property-view")) {
|
||||
propertyView = parent;
|
||||
break;
|
||||
}
|
||||
if (parent.classList.contains("property-content")) {
|
||||
propertyContent = parent;
|
||||
break;
|
||||
}
|
||||
parent = parent.parentNode;
|
||||
}
|
||||
if (!propertyView && !propertyContent) {
|
||||
return null;
|
||||
}
|
||||
|
||||
let value, type;
|
||||
|
||||
// Get the property and value for a node that's a property name or value
|
||||
let isHref = classes.contains("theme-link") && !classes.contains("link");
|
||||
if (propertyView && (classes.contains("property-name") ||
|
||||
classes.contains("property-value") ||
|
||||
isHref)) {
|
||||
value = {
|
||||
property: parent.querySelector(".property-name").textContent,
|
||||
value: parent.querySelector(".property-value").textContent
|
||||
};
|
||||
}
|
||||
if (propertyContent && (classes.contains("other-property-value") ||
|
||||
isHref)) {
|
||||
let view = propertyContent.previousSibling;
|
||||
value = {
|
||||
property: view.querySelector(".property-name").textContent,
|
||||
value: node.textContent
|
||||
};
|
||||
}
|
||||
|
||||
// Get the type
|
||||
if (classes.contains("property-name")) {
|
||||
type = overlays.VIEW_NODE_PROPERTY_TYPE;
|
||||
} else if (classes.contains("property-value")) {
|
||||
} else if (classes.contains("property-value") ||
|
||||
classes.contains("other-property-value")) {
|
||||
type = overlays.VIEW_NODE_VALUE_TYPE;
|
||||
} else if (classes.contains("theme-link")) {
|
||||
} else if (isHref) {
|
||||
type = overlays.VIEW_NODE_IMAGE_URL_TYPE;
|
||||
value.url = node.href;
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
|
||||
return {
|
||||
type: type,
|
||||
value: value
|
||||
};
|
||||
return {type, value};
|
||||
},
|
||||
|
||||
_createPropertyViews: function()
|
||||
|
@ -1248,6 +1248,10 @@ CssRuleView.prototype = {
|
||||
* returns null of the node isn't anything we care about
|
||||
*/
|
||||
getNodeInfo: function(node) {
|
||||
if (!node) {
|
||||
return null;
|
||||
}
|
||||
|
||||
let type, value;
|
||||
let classes = node.classList;
|
||||
let prop = getParentTextProperty(node);
|
||||
|
@ -25,6 +25,7 @@ support-files =
|
||||
head.js
|
||||
|
||||
[browser_computedview_browser-styles.js]
|
||||
[browser_computedview_getNodeInfo.js]
|
||||
[browser_computedview_keybindings_01.js]
|
||||
[browser_computedview_keybindings_02.js]
|
||||
[browser_computedview_matched-selectors-toggle.js]
|
||||
|
@ -0,0 +1,177 @@
|
||||
/* vim: set ft=javascript ts=2 et sw=2 tw=80: */
|
||||
/* Any copyright is dedicated to the Public Domain.
|
||||
http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
|
||||
"use strict";
|
||||
|
||||
// Test various output of the computed-view's getNodeInfo method.
|
||||
// This method is used by the style-inspector-overlay on mouseover to decide
|
||||
// which tooltip or highlighter to show when hovering over a value/name/selector
|
||||
// if any.
|
||||
// For instance, browser_ruleview_selector-highlighter_01.js and
|
||||
// browser_ruleview_selector-highlighter_02.js test that the selector
|
||||
// highlighter appear when hovering over a selector in the rule-view.
|
||||
// Since the code to make this work for the computed-view is 90% the same, there
|
||||
// is no need for testing it again here.
|
||||
// This test however serves as a unit test for getNodeInfo.
|
||||
|
||||
const {
|
||||
VIEW_NODE_SELECTOR_TYPE,
|
||||
VIEW_NODE_PROPERTY_TYPE,
|
||||
VIEW_NODE_VALUE_TYPE,
|
||||
VIEW_NODE_IMAGE_URL_TYPE
|
||||
} = devtools.require("devtools/styleinspector/style-inspector-overlays");
|
||||
|
||||
const PAGE_CONTENT = [
|
||||
'<style type="text/css">',
|
||||
' body {',
|
||||
' background: red;',
|
||||
' color: white;',
|
||||
' }',
|
||||
' div {',
|
||||
' background: green;',
|
||||
' }',
|
||||
' div div {',
|
||||
' background-color: yellow;',
|
||||
' background-image: url(chrome://global/skin/icons/warning-64.png);',
|
||||
' color: red;',
|
||||
' }',
|
||||
'</style>',
|
||||
'<div><div id="testElement">Test element</div></div>'
|
||||
].join("\n");
|
||||
|
||||
// Each item in this array must have the following properties:
|
||||
// - desc {String} will be logged for information
|
||||
// - getHoveredNode {Generator Function} received the computed-view instance as
|
||||
// argument and must return the node to be tested
|
||||
// - assertNodeInfo {Function} should check the validity of the nodeInfo
|
||||
// argument it receives
|
||||
const TEST_DATA = [
|
||||
{
|
||||
desc: "Testing a null node",
|
||||
getHoveredNode: function*() {
|
||||
return null;
|
||||
},
|
||||
assertNodeInfo: function(nodeInfo) {
|
||||
is(nodeInfo, null);
|
||||
}
|
||||
},
|
||||
{
|
||||
desc: "Testing a useless node",
|
||||
getHoveredNode: function*(view) {
|
||||
return view.element;
|
||||
},
|
||||
assertNodeInfo: function(nodeInfo) {
|
||||
is(nodeInfo, null);
|
||||
}
|
||||
},
|
||||
{
|
||||
desc: "Testing a property name",
|
||||
getHoveredNode: function*(view) {
|
||||
return getComputedViewProperty(view, "color").nameSpan;
|
||||
},
|
||||
assertNodeInfo: function(nodeInfo) {
|
||||
is(nodeInfo.type, VIEW_NODE_PROPERTY_TYPE);
|
||||
ok("property" in nodeInfo.value);
|
||||
ok("value" in nodeInfo.value);
|
||||
is(nodeInfo.value.property, "color");
|
||||
is(nodeInfo.value.value, "#F00");
|
||||
}
|
||||
},
|
||||
{
|
||||
desc: "Testing a property value",
|
||||
getHoveredNode: function*(view) {
|
||||
return getComputedViewProperty(view, "color").valueSpan;
|
||||
},
|
||||
assertNodeInfo: function(nodeInfo) {
|
||||
is(nodeInfo.type, VIEW_NODE_VALUE_TYPE);
|
||||
ok("property" in nodeInfo.value);
|
||||
ok("value" in nodeInfo.value);
|
||||
is(nodeInfo.value.property, "color");
|
||||
is(nodeInfo.value.value, "#F00");
|
||||
}
|
||||
},
|
||||
{
|
||||
desc: "Testing an image url",
|
||||
getHoveredNode: function*(view) {
|
||||
let {valueSpan} = getComputedViewProperty(view, "background-image");
|
||||
return valueSpan.querySelector(".theme-link");
|
||||
},
|
||||
assertNodeInfo: function(nodeInfo) {
|
||||
is(nodeInfo.type, VIEW_NODE_IMAGE_URL_TYPE);
|
||||
ok("property" in nodeInfo.value);
|
||||
ok("value" in nodeInfo.value);
|
||||
is(nodeInfo.value.property, "background-image");
|
||||
is(nodeInfo.value.value, "url(\"chrome://global/skin/icons/warning-64.png\")");
|
||||
is(nodeInfo.value.url, "chrome://global/skin/icons/warning-64.png");
|
||||
}
|
||||
},
|
||||
{
|
||||
desc: "Testing a matched rule selector (bestmatch)",
|
||||
getHoveredNode: function*(view) {
|
||||
let content = yield getComputedViewMatchedRules(view, "background-color");
|
||||
return content.querySelector(".bestmatch");
|
||||
},
|
||||
assertNodeInfo: function(nodeInfo) {
|
||||
is(nodeInfo.type, VIEW_NODE_SELECTOR_TYPE);
|
||||
is(nodeInfo.value, "div div");
|
||||
}
|
||||
},
|
||||
{
|
||||
desc: "Testing a matched rule selector (matched)",
|
||||
getHoveredNode: function*(view) {
|
||||
let content = yield getComputedViewMatchedRules(view, "background-color");
|
||||
return content.querySelector(".matched");
|
||||
},
|
||||
assertNodeInfo: function(nodeInfo) {
|
||||
is(nodeInfo.type, VIEW_NODE_SELECTOR_TYPE);
|
||||
is(nodeInfo.value, "div");
|
||||
}
|
||||
},
|
||||
{
|
||||
desc: "Testing a matched rule selector (parentmatch)",
|
||||
getHoveredNode: function*(view) {
|
||||
let content = yield getComputedViewMatchedRules(view, "color");
|
||||
return content.querySelector(".parentmatch");
|
||||
},
|
||||
assertNodeInfo: function(nodeInfo) {
|
||||
is(nodeInfo.type, VIEW_NODE_SELECTOR_TYPE);
|
||||
is(nodeInfo.value, "body");
|
||||
}
|
||||
},
|
||||
{
|
||||
desc: "Testing a matched rule value",
|
||||
getHoveredNode: function*(view) {
|
||||
let content = yield getComputedViewMatchedRules(view, "color");
|
||||
return content.querySelector(".other-property-value");
|
||||
},
|
||||
assertNodeInfo: function(nodeInfo) {
|
||||
is(nodeInfo.type, VIEW_NODE_VALUE_TYPE);
|
||||
is(nodeInfo.value.property, "color");
|
||||
is(nodeInfo.value.value, "#F00");
|
||||
}
|
||||
},
|
||||
{
|
||||
desc: "Testing a matched rule stylesheet link",
|
||||
getHoveredNode: function*(view) {
|
||||
let content = yield getComputedViewMatchedRules(view, "color");
|
||||
return content.querySelector(".rule-link .theme-link");
|
||||
},
|
||||
assertNodeInfo: function(nodeInfo) {
|
||||
is(nodeInfo, null);
|
||||
}
|
||||
}
|
||||
];
|
||||
|
||||
let test = asyncTest(function*() {
|
||||
yield addTab("data:text/html;charset=utf-8," + PAGE_CONTENT);
|
||||
|
||||
let {inspector, view} = yield openComputedView();
|
||||
yield selectNode("#testElement", inspector);
|
||||
|
||||
for (let {desc, getHoveredNode, assertNodeInfo} of TEST_DATA) {
|
||||
info(desc);
|
||||
let nodeInfo = view.getNodeInfo(yield getHoveredNode(view));
|
||||
assertNodeInfo(nodeInfo);
|
||||
}
|
||||
});
|
@ -23,7 +23,7 @@ let test = asyncTest(function*() {
|
||||
yield selectNode("div", inspector);
|
||||
|
||||
info("Expanding the first property");
|
||||
yield expandComputedViewPropertyByIndex(view, inspector, 0);
|
||||
yield expandComputedViewPropertyByIndex(view, 0);
|
||||
|
||||
info("Verifying the link text");
|
||||
yield verifyLinkText(view, SCSS_LOC);
|
||||
|
@ -61,7 +61,7 @@ let test = asyncTest(function*() {
|
||||
function* testInlineStyle(view, inspector) {
|
||||
info("Testing inline style");
|
||||
|
||||
yield expandComputedViewPropertyByIndex(view, inspector, 0);
|
||||
yield expandComputedViewPropertyByIndex(view, 0);
|
||||
|
||||
let onWindow = waitForWindow();
|
||||
info("Clicking on the first rule-link in the computed-view");
|
||||
|
@ -35,6 +35,8 @@ let test = asyncTest(function*() {
|
||||
let {toolbox, inspector, view} = yield openComputedView();
|
||||
|
||||
yield testComputedView(view, inspector.selection.nodeFront);
|
||||
|
||||
yield testExpandedComputedViewProperty(view, inspector.selection.nodeFront);
|
||||
});
|
||||
|
||||
function* testRuleView(ruleView, nodeFront) {
|
||||
@ -77,3 +79,39 @@ function* testComputedView(computedView, nodeFront) {
|
||||
let dataURL = yield getFontFamilyDataURL(valueSpan.textContent, nodeFront);
|
||||
is(images[0].getAttribute("src"), dataURL, "Tooltip contains the correct data-uri image");
|
||||
}
|
||||
|
||||
function* testExpandedComputedViewProperty(computedView, nodeFront) {
|
||||
info("Testing font-family tooltips in expanded properties of the computed view");
|
||||
|
||||
info("Expanding the font-family property to reveal matched selectors");
|
||||
let propertyView = getPropertyView(computedView, "font-family");
|
||||
propertyView.matchedExpanded = true;
|
||||
yield propertyView.refreshMatchedSelectors();
|
||||
|
||||
let valueSpan = propertyView.matchedSelectorsContainer
|
||||
.querySelector(".bestmatch .other-property-value");
|
||||
|
||||
let tooltip = computedView.tooltips.previewTooltip;
|
||||
let panel = tooltip.panel;
|
||||
|
||||
yield assertHoverTooltipOn(tooltip, valueSpan);
|
||||
|
||||
let images = panel.getElementsByTagName("image");
|
||||
is(images.length, 1, "Tooltip contains an image");
|
||||
ok(images[0].getAttribute("src").startsWith("data:"), "Tooltip contains a data-uri image as expected");
|
||||
|
||||
let dataURL = yield getFontFamilyDataURL(valueSpan.textContent, nodeFront);
|
||||
is(images[0].getAttribute("src"), dataURL, "Tooltip contains the correct data-uri image");
|
||||
}
|
||||
|
||||
function getPropertyView(computedView, name) {
|
||||
let propertyView = null;
|
||||
computedView.propertyViews.some(function(view) {
|
||||
if (view.name == name) {
|
||||
propertyView = view;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
});
|
||||
return propertyView;
|
||||
}
|
||||
|
@ -28,11 +28,6 @@ let test = asyncTest(function*() {
|
||||
yield selectNode("#testElement", inspector);
|
||||
|
||||
yield testRuleView(view, inspector.selection.nodeFront);
|
||||
|
||||
info("Opening the computed view");
|
||||
let {toolbox, inspector, view} = yield openComputedView();
|
||||
|
||||
yield testComputedView(view, inspector.selection.nodeFront);
|
||||
});
|
||||
|
||||
function* testRuleView(ruleView, nodeFront) {
|
||||
@ -63,21 +58,3 @@ function* testRuleView(ruleView, nodeFront) {
|
||||
let dataURL = yield getFontFamilyDataURL(valueSpan.textContent, nodeFront);
|
||||
is(images[0].getAttribute("src"), dataURL, "Tooltip contains the correct data-uri image");
|
||||
}
|
||||
|
||||
function* testComputedView(computedView, nodeFront) {
|
||||
info("Testing font-family tooltips in the computed view");
|
||||
|
||||
let tooltip = computedView.tooltips.previewTooltip;
|
||||
let panel = tooltip.panel;
|
||||
|
||||
let {valueSpan} = getComputedViewProperty(computedView, "font-family");
|
||||
|
||||
yield assertHoverTooltipOn(tooltip, valueSpan);
|
||||
|
||||
let images = panel.getElementsByTagName("image");
|
||||
is(images.length, 1, "Tooltip contains an image");
|
||||
ok(images[0].getAttribute("src").startsWith("data:"), "Tooltip contains a data-uri image as expected");
|
||||
|
||||
let dataURL = yield getFontFamilyDataURL(valueSpan.textContent, nodeFront);
|
||||
is(images[0].getAttribute("src"), dataURL, "Tooltip contains the correct data-uri image");
|
||||
}
|
||||
|
@ -752,32 +752,6 @@ let createNewRuleViewProperty = Task.async(function*(ruleEditor, inputValue) {
|
||||
yield onFocus;
|
||||
});
|
||||
|
||||
// TO BE UNCOMMENTED WHEN THE EYEDROPPER FINALLY LANDS
|
||||
// /**
|
||||
// * Given a color swatch in the ruleview, click on it to open the color picker
|
||||
// * and then click on the eyedropper button to start the eyedropper tool
|
||||
// * @param {CssRuleView} view The instance of the rule-view panel
|
||||
// * @param {DOMNode} swatch The color swatch to be clicked on
|
||||
// * @return A promise that resolves when the dropper is opened
|
||||
// */
|
||||
// let openRuleViewEyeDropper = Task.async(function*(view, swatch) {
|
||||
// info("Opening the colorpicker tooltip on a colorswatch");
|
||||
// let tooltip = view.colorPicker.tooltip;
|
||||
// let onTooltipShown = tooltip.once("shown");
|
||||
// swatch.click();
|
||||
// yield onTooltipShown;
|
||||
|
||||
// info("Finding the eyedropper icon in the colorpicker document");
|
||||
// let tooltipDoc = tooltip.content.contentDocument;
|
||||
// let dropperButton = tooltipDoc.querySelector("#eyedropper-button");
|
||||
// ok(dropperButton, "Found the eyedropper icon");
|
||||
|
||||
// info("Opening the eyedropper");
|
||||
// let onOpen = tooltip.once("eyedropper-opened");
|
||||
// dropperButton.click();
|
||||
// return yield onOpen;
|
||||
// });
|
||||
|
||||
/* *********************************************
|
||||
* COMPUTED-VIEW
|
||||
* *********************************************
|
||||
@ -806,6 +780,40 @@ function getComputedViewProperty(view, name) {
|
||||
return prop;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a reference to the property-content element for a given property name in
|
||||
* the computed-view.
|
||||
* A property-content element always follows (nextSibling) the property itself
|
||||
* and is only shown when the twisty icon is expanded on the property.
|
||||
* A property-content element contains matched rules, with selectors, properties,
|
||||
* values and stylesheet links
|
||||
* @param {CssHtmlTree} view The instance of the computed view panel
|
||||
* @param {String} name The name of the property to retrieve
|
||||
* @return {Promise} A promise that resolves to the property matched rules
|
||||
* container
|
||||
*/
|
||||
let getComputedViewMatchedRules = Task.async(function*(view, name) {
|
||||
let expander;
|
||||
let propertyContent;
|
||||
for (let property of view.styleDocument.querySelectorAll(".property-view")) {
|
||||
let nameSpan = property.querySelector(".property-name");
|
||||
if (nameSpan.textContent === name) {
|
||||
expander = property.querySelector(".expandable");
|
||||
propertyContent = property.nextSibling;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!expander.hasAttribute("open")) {
|
||||
// Need to expand the property
|
||||
let onExpand = view.inspector.once("computed-view-property-expanded");
|
||||
expander.click();
|
||||
yield onExpand;
|
||||
}
|
||||
|
||||
return propertyContent;
|
||||
});
|
||||
|
||||
/**
|
||||
* Get the text value of the property corresponding to a given name in the
|
||||
* computed-view
|
||||
@ -813,8 +821,8 @@ function getComputedViewProperty(view, name) {
|
||||
* @param {String} name The name of the property to retrieve
|
||||
* @return {String} The property value
|
||||
*/
|
||||
function getComputedViewPropertyValue(view, selectorText, propertyName) {
|
||||
return getComputedViewProperty(view, selectorText, propertyName)
|
||||
function getComputedViewPropertyValue(view, name, propertyName) {
|
||||
return getComputedViewProperty(view, name, propertyName)
|
||||
.valueSpan.textContent;
|
||||
}
|
||||
|
||||
@ -822,19 +830,18 @@ function getComputedViewPropertyValue(view, selectorText, propertyName) {
|
||||
* Expand a given property, given its index in the current property list of
|
||||
* the computed view
|
||||
* @param {CssHtmlTree} view The instance of the computed view panel
|
||||
* @param {InspectorPanel} inspector The instance of the inspector panel
|
||||
* @param {Number} index The index of the property to be expanded
|
||||
* @return a promise that resolves when the property has been expanded, or
|
||||
* rejects if the property was not found
|
||||
*/
|
||||
function expandComputedViewPropertyByIndex(view, inspector, index) {
|
||||
function expandComputedViewPropertyByIndex(view, index) {
|
||||
info("Expanding property " + index + " in the computed view");
|
||||
let expandos = view.styleDocument.querySelectorAll(".expandable");
|
||||
if (!expandos.length || !expandos[index]) {
|
||||
return promise.reject();
|
||||
}
|
||||
|
||||
let onExpand = inspector.once("computed-view-property-expanded");
|
||||
let onExpand = view.inspector.once("computed-view-property-expanded");
|
||||
expandos[index].click();
|
||||
return onExpand;
|
||||
}
|
||||
|
@ -147,13 +147,18 @@ const HISTORY_FORWARD = 1;
|
||||
const GROUP_INDENT = 12;
|
||||
|
||||
// The number of messages to display in a single display update. If we display
|
||||
// too many messages at once we slow the Firefox UI too much.
|
||||
// too many messages at once we slow down the Firefox UI too much.
|
||||
const MESSAGES_IN_INTERVAL = DEFAULT_LOG_LIMIT;
|
||||
|
||||
// The delay between display updates - tells how often we should *try* to push
|
||||
// new messages to screen. This value is optimistic, updates won't always
|
||||
// happen. Keep this low so the Web Console output feels live.
|
||||
const OUTPUT_INTERVAL = 50; // milliseconds
|
||||
const OUTPUT_INTERVAL = 20; // milliseconds
|
||||
|
||||
// The maximum amount of time that can be spent doing cleanup inside of the
|
||||
// flush output callback. If things don't get cleaned up in this time,
|
||||
// then it will start again the next time it is called.
|
||||
const MAX_CLEANUP_TIME = 10; // milliseconds
|
||||
|
||||
// When the output queue has more than MESSAGES_IN_INTERVAL items we throttle
|
||||
// output updates to this number of milliseconds. So during a lot of output we
|
||||
@ -190,6 +195,7 @@ function WebConsoleFrame(aWebConsoleOwner)
|
||||
|
||||
this._repeatNodes = {};
|
||||
this._outputQueue = [];
|
||||
this._itemDestroyQueue = [];
|
||||
this._pruneCategoriesQueue = {};
|
||||
this._networkRequests = {};
|
||||
this.filterPrefs = {};
|
||||
@ -2048,9 +2054,7 @@ WebConsoleFrame.prototype = {
|
||||
|
||||
this._outputQueue.push([aCategory, aMethodOrNode, aArguments]);
|
||||
|
||||
if (!this._outputTimerInitialized) {
|
||||
this._initOutputTimer();
|
||||
}
|
||||
this._initOutputTimer();
|
||||
},
|
||||
|
||||
/**
|
||||
@ -2062,21 +2066,31 @@ WebConsoleFrame.prototype = {
|
||||
*/
|
||||
_flushMessageQueue: function WCF__flushMessageQueue()
|
||||
{
|
||||
this._outputTimerInitialized = false;
|
||||
if (!this._outputTimer) {
|
||||
return;
|
||||
}
|
||||
|
||||
let timeSinceFlush = Date.now() - this._lastOutputFlush;
|
||||
if (this._outputQueue.length > MESSAGES_IN_INTERVAL &&
|
||||
timeSinceFlush < THROTTLE_UPDATES) {
|
||||
this._initOutputTimer();
|
||||
return;
|
||||
}
|
||||
let startTime = Date.now();
|
||||
let timeSinceFlush = startTime - this._lastOutputFlush;
|
||||
let shouldThrottle = this._outputQueue.length > MESSAGES_IN_INTERVAL &&
|
||||
timeSinceFlush < THROTTLE_UPDATES;
|
||||
|
||||
// Determine how many messages we can display now.
|
||||
let toDisplay = Math.min(this._outputQueue.length, MESSAGES_IN_INTERVAL);
|
||||
if (toDisplay < 1) {
|
||||
this._outputTimerInitialized = false;
|
||||
|
||||
// If there aren't any messages to display (because of throttling or an
|
||||
// empty queue), then take care of some cleanup. Destroy items that were
|
||||
// pruned from the outputQueue before being displayed.
|
||||
if (shouldThrottle || toDisplay < 1) {
|
||||
while (this._itemDestroyQueue.length) {
|
||||
if ((Date.now() - startTime) > MAX_CLEANUP_TIME) {
|
||||
break;
|
||||
}
|
||||
this._destroyItem(this._itemDestroyQueue.pop());
|
||||
}
|
||||
|
||||
this._initOutputTimer();
|
||||
return;
|
||||
}
|
||||
|
||||
@ -2088,21 +2102,22 @@ WebConsoleFrame.prototype = {
|
||||
}
|
||||
|
||||
let batch = this._outputQueue.splice(0, toDisplay);
|
||||
if (!batch.length) {
|
||||
this._outputTimerInitialized = false;
|
||||
return;
|
||||
}
|
||||
|
||||
let outputNode = this.outputNode;
|
||||
let lastVisibleNode = null;
|
||||
let scrollNode = outputNode.parentNode;
|
||||
let scrolledToBottom = Utils.isOutputScrolledToBottom(outputNode);
|
||||
let hudIdSupportsString = WebConsoleUtils.supportsString(this.hudId);
|
||||
|
||||
// We won't bother to try to restore scroll position if this is showing
|
||||
// a lot of messages at once (and there are still items in the queue).
|
||||
// It is going to purge whatever you were looking at anyway.
|
||||
let scrolledToBottom = shouldPrune ||
|
||||
Utils.isOutputScrolledToBottom(outputNode);
|
||||
|
||||
// Output the current batch of messages.
|
||||
let newMessages = new Set();
|
||||
let updatedMessages = new Set();
|
||||
for (let item of batch) {
|
||||
for (let i = 0; i < batch.length; i++) {
|
||||
let item = batch[i];
|
||||
let result = this._outputMessageFromQueue(hudIdSupportsString, item);
|
||||
if (result) {
|
||||
if (result.isRepeated) {
|
||||
@ -2118,12 +2133,15 @@ WebConsoleFrame.prototype = {
|
||||
}
|
||||
|
||||
let oldScrollHeight = 0;
|
||||
|
||||
// Prune messages if needed. We do not do this for every flush call to
|
||||
// improve performance.
|
||||
let removedNodes = 0;
|
||||
|
||||
// Prune messages from the DOM, but only if needed.
|
||||
if (shouldPrune || !this._outputQueue.length) {
|
||||
oldScrollHeight = scrollNode.scrollHeight;
|
||||
// Only bother measuring the scrollHeight if not scrolled to bottom,
|
||||
// since the oldScrollHeight will not be used if it is.
|
||||
if (!scrolledToBottom) {
|
||||
oldScrollHeight = scrollNode.scrollHeight;
|
||||
}
|
||||
|
||||
let categories = Object.keys(this._pruneCategoriesQueue);
|
||||
categories.forEach(function _pruneOutput(aCategory) {
|
||||
@ -2156,17 +2174,15 @@ WebConsoleFrame.prototype = {
|
||||
this.emit("messages-updated", updatedMessages);
|
||||
}
|
||||
|
||||
// If the queue is not empty, schedule another flush.
|
||||
if (this._outputQueue.length > 0) {
|
||||
this._initOutputTimer();
|
||||
}
|
||||
else {
|
||||
this._outputTimerInitialized = false;
|
||||
if (this._flushCallback && this._flushCallback() === false) {
|
||||
// If the output queue is empty, then run _flushCallback.
|
||||
if (this._outputQueue.length === 0 && this._flushCallback) {
|
||||
if (this._flushCallback() === false) {
|
||||
this._flushCallback = null;
|
||||
}
|
||||
}
|
||||
|
||||
this._initOutputTimer();
|
||||
|
||||
this._lastOutputFlush = Date.now();
|
||||
},
|
||||
|
||||
@ -2176,7 +2192,13 @@ WebConsoleFrame.prototype = {
|
||||
*/
|
||||
_initOutputTimer: function WCF__initOutputTimer()
|
||||
{
|
||||
if (!this._outputTimer) {
|
||||
let panelIsDestroyed = !this._outputTimer;
|
||||
let alreadyScheduled = this._outputTimerInitialized;
|
||||
let nothingToDo = !this._itemDestroyQueue.length &&
|
||||
!this._outputQueue.length;
|
||||
|
||||
// Don't schedule a callback in the following cases:
|
||||
if (panelIsDestroyed || alreadyScheduled || nothingToDo) {
|
||||
return;
|
||||
}
|
||||
|
||||
@ -2274,7 +2296,7 @@ WebConsoleFrame.prototype = {
|
||||
let n = Math.max(0, indexes.length - limit);
|
||||
pruned += n;
|
||||
for (let i = n - 1; i >= 0; i--) {
|
||||
this._pruneItemFromQueue(this._outputQueue[indexes[i]]);
|
||||
this._itemDestroyQueue.push(this._outputQueue[indexes[i]]);
|
||||
this._outputQueue.splice(indexes[i], 1);
|
||||
}
|
||||
}
|
||||
@ -2284,17 +2306,18 @@ WebConsoleFrame.prototype = {
|
||||
},
|
||||
|
||||
/**
|
||||
* Prune an item from the output queue.
|
||||
* Destroy an item that was once in the outputQueue but isn't needed
|
||||
* after all.
|
||||
*
|
||||
* @private
|
||||
* @param array aItem
|
||||
* The item you want to remove from the output queue.
|
||||
* The item you want to destroy. Does not remove it from the output
|
||||
* queue.
|
||||
*/
|
||||
_pruneItemFromQueue: function WCF__pruneItemFromQueue(aItem)
|
||||
_destroyItem: function WCF__destroyItem(aItem)
|
||||
{
|
||||
// TODO: handle object releasing in a more elegant way once all console
|
||||
// messages use the new API - bug 778766.
|
||||
|
||||
let [category, methodOrNode, args] = aItem;
|
||||
if (typeof methodOrNode != "function" && methodOrNode._objectActors) {
|
||||
for (let actor of methodOrNode._objectActors) {
|
||||
@ -2370,9 +2393,7 @@ WebConsoleFrame.prototype = {
|
||||
let messageNodes = this.outputNode.querySelectorAll(".message[category=" +
|
||||
CATEGORY_CLASS_FRAGMENTS[aCategory] + "]");
|
||||
let n = Math.max(0, messageNodes.length - logLimit);
|
||||
let toRemove = Array.prototype.slice.call(messageNodes, 0, n);
|
||||
toRemove.forEach(this.removeOutputMessage, this);
|
||||
|
||||
[...messageNodes].slice(0, n).forEach(this.removeOutputMessage, this);
|
||||
return n;
|
||||
},
|
||||
|
||||
@ -2415,9 +2436,7 @@ WebConsoleFrame.prototype = {
|
||||
aNode._variablesView = null;
|
||||
}
|
||||
|
||||
if (aNode.parentNode) {
|
||||
aNode.parentNode.removeChild(aNode);
|
||||
}
|
||||
aNode.remove();
|
||||
},
|
||||
|
||||
/**
|
||||
@ -2897,7 +2916,10 @@ WebConsoleFrame.prototype = {
|
||||
gDevTools.off("pref-changed", this._onToolboxPrefChanged);
|
||||
|
||||
this._repeatNodes = {};
|
||||
this._outputQueue.forEach(this._destroyItem, this);
|
||||
this._outputQueue = [];
|
||||
this._itemDestroyQueue.forEach(this._destroyItem, this);
|
||||
this._itemDestroyQueue = [];
|
||||
this._pruneCategoriesQueue = {};
|
||||
this._networkRequests = {};
|
||||
|
||||
@ -2906,7 +2928,6 @@ WebConsoleFrame.prototype = {
|
||||
this._outputTimer.cancel();
|
||||
}
|
||||
this._outputTimer = null;
|
||||
|
||||
if (this.jsterm) {
|
||||
this.jsterm.destroy();
|
||||
this.jsterm = null;
|
||||
@ -3787,7 +3808,7 @@ JSTerm.prototype = {
|
||||
}
|
||||
|
||||
hud.groupDepth = 0;
|
||||
hud._outputQueue.forEach(hud._pruneItemFromQueue, hud);
|
||||
hud._outputQueue.forEach(hud._destroyItem, hud);
|
||||
hud._outputQueue = [];
|
||||
hud._networkRequests = {};
|
||||
hud._repeatNodes = {};
|
||||
|
@ -89,6 +89,7 @@ SimulatorRuntime.prototype = {
|
||||
return promise.reject("Can't find simulator: " + this.getName());
|
||||
}
|
||||
return simulator.launch({port: port}).then(() => {
|
||||
connection.host = "localhost";
|
||||
connection.port = port;
|
||||
connection.keepConnecting = true;
|
||||
connection.once(Connection.Events.DISCONNECTED, simulator.close);
|
||||
@ -109,8 +110,8 @@ let gLocalRuntime = {
|
||||
DebuggerServer.init();
|
||||
DebuggerServer.addBrowserActors();
|
||||
}
|
||||
connection.port = null;
|
||||
connection.host = null; // Force Pipe transport
|
||||
connection.port = null;
|
||||
connection.connect();
|
||||
return promise.resolve();
|
||||
},
|
||||
|
@ -300,6 +300,7 @@
|
||||
@BINPATH@/components/shistory.xpt
|
||||
@BINPATH@/components/spellchecker.xpt
|
||||
@BINPATH@/components/storage.xpt
|
||||
@BINPATH@/components/toolkit_filewatcher.xpt
|
||||
@BINPATH@/components/toolkit_finalizationwitness.xpt
|
||||
@BINPATH@/components/toolkit_formautofill.xpt
|
||||
@BINPATH@/components/toolkit_osfile.xpt
|
||||
|
@ -6,6 +6,7 @@ support-files =
|
||||
|
||||
[browser_BrowserUITelemetry_buckets.js]
|
||||
[browser_ContentSearch.js]
|
||||
skip-if = e10s
|
||||
support-files =
|
||||
contentSearch.js
|
||||
contentSearchBadImage.xml
|
||||
|
Before Width: | Height: | Size: 883 B After Width: | Height: | Size: 874 B |
Before Width: | Height: | Size: 811 B After Width: | Height: | Size: 742 B |
Before Width: | Height: | Size: 1.6 KiB After Width: | Height: | Size: 1.6 KiB |
Before Width: | Height: | Size: 1.5 KiB After Width: | Height: | Size: 1.9 KiB |
Before Width: | Height: | Size: 3.4 KiB After Width: | Height: | Size: 4.4 KiB |
Before Width: | Height: | Size: 2.5 KiB After Width: | Height: | Size: 2.0 KiB |
Before Width: | Height: | Size: 6.0 KiB After Width: | Height: | Size: 5.2 KiB |
@ -4,7 +4,7 @@ export LIB=/d/msvs10/vc/lib:/d/msvs10/vc/atlmfc/lib:/d/sdks/v7.0/lib:/d/msvs8/VC
|
||||
export PATH="/d/msvs10/VSTSDB/Deploy:/d/msvs10/Common7/IDE/:/d/msvs10/VC/BIN:/d/msvs10/Common7/Tools:/d/msvs10/VC/VCPackages:${PATH}"
|
||||
export WIN32_REDIST_DIR=/d/msvs10/VC/redist/x86/Microsoft.VC100.CRT
|
||||
|
||||
. $topsrcdir/build/mozconfig.vs2010-common
|
||||
. $topsrcdir/build/mozconfig.vs-common
|
||||
|
||||
mk_export_correct_style LIB
|
||||
mk_export_correct_style LIBPATH
|
||||
|
@ -25,7 +25,7 @@ export PATH="/c/Program Files (x86)/Windows Kits/8.0/bin/x86:${_VSPATH}/Common7/
|
||||
## WindowsSDKDir ##
|
||||
export WINDOWSSDKDIR="/c/Program Files (x86)/Windows Kits/8.0/"
|
||||
|
||||
. $topsrcdir/build/mozconfig.vs2010-common
|
||||
. $topsrcdir/build/mozconfig.vs-common
|
||||
|
||||
mk_export_correct_style LIB
|
||||
mk_export_correct_style LIBPATH
|
||||
|
28
build/win32/mozconfig.vs2013-win64
Normal file
@ -0,0 +1,28 @@
|
||||
_VSPATH="/c/tools/vs2013"
|
||||
export WIN32_REDIST_DIR=${_VSPATH}/VC/redist/x86/Microsoft.VC120.CRT
|
||||
|
||||
## moz tools location for 64-bit builders ##
|
||||
export MOZ_TOOLS=C:/mozilla-build/moztools
|
||||
|
||||
## includes: win8 sdk includes, winrt headers for metro, msvc std library, directx sdk for d3d9 ##
|
||||
export INCLUDE=/c/Program\ Files\ \(x86\)/Windows\ Kits/8.0/include/shared:/c/Program\ Files\ \(x86\)/Windows\ Kits/8.0/include/um:/c/Program\ Files\ \(x86\)/Windows\ Kits/8.0/include/winrt:/c/Program\ Files\ \(x86\)/Windows\ Kits/8.0/include/winrt/wrl:/c/Program\ Files\ \(x86\)/Windows\ Kits/8.0/include/winrt/wrl/wrappers:${_VSPATH}/vc/include:${_VSPATH}/vc/atlmfc/include:/c/tools/sdks/dx10/include
|
||||
|
||||
## libs: win8 sdk x86 (32-bit) libs, msvc (32-bit) std library, msvc atl libs, directx sdk (32-bit) for d3d9 ##
|
||||
export LIBPATH=/c/Program\ Files\ \(x86\)/Windows\ Kits/8.0/Lib/win8/um/x86:${_VSPATH}/vc/lib:${_VSPATH}/vc/atlmfc/lib:/c/tools/sdks/dx10/lib
|
||||
export LIB=/c/Program\ Files\ \(x86\)/Windows\ Kits/8.0/Lib/win8/um/x86:${_VSPATH}/vc/lib:${_VSPATH}/vc/atlmfc/lib:/c/tools/sdks/dx10/lib
|
||||
|
||||
## paths: win8 sdk x86 (32-bit) tools, msvc (64-bit compiling 32-bit) build toolchain, moz tools ##
|
||||
export PATH="/c/Program Files (x86)/Windows Kits/8.0/bin/x86:${_VSPATH}/Common7/IDE:${_VSPATH}/VC/BIN/amd64_x86:${_VSPATH}/VC/BIN/amd64:${_VSPATH}/Common7/Tools:${_VSPATH}/VC/VCPackages:/c/mozilla-build/moztools:${PATH}"
|
||||
|
||||
## WindowsSDKDir ##
|
||||
export WINDOWSSDKDIR="/c/Program Files (x86)/Windows Kits/8.0/"
|
||||
|
||||
. $topsrcdir/build/mozconfig.vs-common
|
||||
|
||||
mk_export_correct_style LIB
|
||||
mk_export_correct_style LIBPATH
|
||||
mk_export_correct_style PATH
|
||||
mk_export_correct_style INCLUDE
|
||||
mk_export_correct_style WIN32_REDIST_DIR
|
||||
|
||||
mk_add_options "export MOZ_TOOLS=$MOZ_TOOLS"
|
@ -31,7 +31,7 @@ else
|
||||
export LD=c:/tools/msvs10/VC/BIN/x86_amd64/link.exe
|
||||
fi
|
||||
|
||||
. $topsrcdir/build/mozconfig.vs2010-common
|
||||
. $topsrcdir/build/mozconfig.vs-common
|
||||
|
||||
mk_export_correct_style LIB
|
||||
mk_export_correct_style LIBPATH
|
||||
|
23
build/win64/mozconfig.vs2013
Normal file
@ -0,0 +1,23 @@
|
||||
_VSPATH="/c/tools/vs2013"
|
||||
export WIN32_REDIST_DIR=${_VSPATH}/VC/redist/x64/Microsoft.VC120.CRT
|
||||
|
||||
## includes: win8 sdk includes, winrt headers for metro, msvc 10 std library, directx sdk for d3d9 ##
|
||||
export INCLUDE=/c/Program\ Files\ \(x86\)/Windows\ Kits/8.0/include/shared:/c/Program\ Files\ \(x86\)/Windows\ Kits/8.0/include/um:/c/Program\ Files\ \(x86\)/Windows\ Kits/8.0/include/winrt:/c/Program\ Files\ \(x86\)/Windows\ Kits/8.0/include/winrt/wrl:/c/Program\ Files\ \(x86\)/Windows\ Kits/8.0/include/winrt/wrl/wrappers:${_VSPATH}/vc/include:${_VSPATH}/vc/atlmfc/include:/c/tools/sdks/dx10/include
|
||||
|
||||
## libs: win8 sdk x64 (64-bit) libs, msvc 10 (64-bit) std library, msvc 10 atl libs, directx sdk (64-bit) for d3d9 ##
|
||||
export LIBPATH=/c/Program\ Files\ \(x86\)/Windows\ Kits/8.0/Lib/win8/um/x64:${_VSPATH}/vc/lib/amd64:${_VSPATH}/vc/atlmfc/lib/amd64:/c/tools/sdks/dx10/lib/x64
|
||||
export LIB=/c/Program\ Files\ \(x86\)/Windows\ Kits/8.0/Lib/win8/um/x64:${_VSPATH}/vc/lib/amd64:${_VSPATH}/vc/atlmfc/lib/amd64:/c/tools/sdks/dx10/lib/x64
|
||||
|
||||
## paths: win8 sdk x64 (64-bit) tools, msvc 10 (64-bit) build toolchain, moz tools ##
|
||||
export PATH="/c/Program Files (x86)/Windows Kits/8.0/bin/x64:${_VSPATH}/Common7/IDE:${_VSPATH}/VC/BIN/amd64:${_VSPATH}/VC/BIN/x86_amd64:${_VSPATH}/VC/BIN:${_VSPATH}/Common7/Tools:${_VSPATH}/VC/VCPackages:${PATH}"
|
||||
|
||||
## WindowsSDKDir ##
|
||||
export WINDOWSSDKDIR="/c/Program Files (x86)/Windows Kits/8.0/"
|
||||
|
||||
. $topsrcdir/build/mozconfig.vs-common
|
||||
|
||||
mk_export_correct_style LIB
|
||||
mk_export_correct_style LIBPATH
|
||||
mk_export_correct_style PATH
|
||||
mk_export_correct_style INCLUDE
|
||||
mk_export_correct_style WIN32_REDIST_DIR
|
@ -34,7 +34,7 @@ public:
|
||||
virtual size_t SizeOfExcludingThis(mozilla::MallocSizeOf aMallocSizeOf) const;
|
||||
virtual size_t SizeOfIncludingThis(mozilla::MallocSizeOf aMallocSizeOf) const;
|
||||
|
||||
nsNullPrincipalURI(const nsCString &aSpec);
|
||||
explicit nsNullPrincipalURI(const nsCString &aSpec);
|
||||
|
||||
private:
|
||||
~nsNullPrincipalURI() {}
|
||||
|
@ -123,7 +123,7 @@ protected:
|
||||
class nsExpandedPrincipal : public nsIExpandedPrincipal, public nsBasePrincipal
|
||||
{
|
||||
public:
|
||||
nsExpandedPrincipal(nsTArray< nsCOMPtr<nsIPrincipal> > &aWhiteList);
|
||||
explicit nsExpandedPrincipal(nsTArray< nsCOMPtr<nsIPrincipal> > &aWhiteList);
|
||||
|
||||
protected:
|
||||
virtual ~nsExpandedPrincipal();
|
||||
|
@ -127,7 +127,7 @@ class nsChromeRegistryChrome : public nsChromeRegistry
|
||||
typedef nsURIHashKey::KeyType KeyType;
|
||||
typedef nsURIHashKey::KeyTypePointer KeyTypePointer;
|
||||
|
||||
OverlayListEntry(KeyTypePointer aKey) : nsURIHashKey(aKey) { }
|
||||
explicit OverlayListEntry(KeyTypePointer aKey) : nsURIHashKey(aKey) { }
|
||||
OverlayListEntry(OverlayListEntry&& toMove) : nsURIHashKey(mozilla::Move(toMove)),
|
||||
mArray(mozilla::Move(toMove.mArray)) { }
|
||||
~OverlayListEntry() { }
|
||||
|
@ -359,19 +359,25 @@ JAVA_GEN_DIR = _javagen
|
||||
JAVA_DIST_DIR = $(DEPTH)/$(JAVA_GEN_DIR)
|
||||
JAVA_IFACES_PKG_NAME = org/mozilla/interfaces
|
||||
|
||||
OS_INCLUDES += $(MOZ_JPEG_CFLAGS) $(MOZ_PNG_CFLAGS) $(MOZ_ZLIB_CFLAGS) $(MOZ_PIXMAN_CFLAGS)
|
||||
|
||||
# NSPR_CFLAGS and NSS_CFLAGS must appear ahead of OS_INCLUDES to avoid Linux
|
||||
# builds wrongly picking up system NSPR/NSS header files.
|
||||
INCLUDES = \
|
||||
-I$(srcdir) \
|
||||
-I. \
|
||||
$(LOCAL_INCLUDES) \
|
||||
-I$(DIST)/include \
|
||||
$(NULL)
|
||||
|
||||
ifndef IS_GYP_DIR
|
||||
# NSPR_CFLAGS and NSS_CFLAGS must appear ahead of the other flags to avoid Linux
|
||||
# builds wrongly picking up system NSPR/NSS header files.
|
||||
OS_INCLUDES := \
|
||||
$(if $(LIBXUL_SDK),-I$(LIBXUL_SDK)/include) \
|
||||
$(NSPR_CFLAGS) $(NSS_CFLAGS) \
|
||||
$(OS_INCLUDES) \
|
||||
$(MOZ_JPEG_CFLAGS) \
|
||||
$(MOZ_PNG_CFLAGS) \
|
||||
$(MOZ_ZLIB_CFLAGS) \
|
||||
$(MOZ_PIXMAN_CFLAGS) \
|
||||
$(NULL)
|
||||
endif
|
||||
|
||||
include $(topsrcdir)/config/static-checking-config.mk
|
||||
|
||||
@ -483,8 +489,8 @@ OS_COMPILE_CMMFLAGS += -fobjc-abi-version=2 -fobjc-legacy-dispatch
|
||||
endif
|
||||
endif
|
||||
|
||||
COMPILE_CFLAGS = $(VISIBILITY_FLAGS) $(DEFINES) $(INCLUDES) $(DSO_CFLAGS) $(DSO_PIC_CFLAGS) $(RTL_FLAGS) $(OS_CPPFLAGS) $(OS_COMPILE_CFLAGS) $(CFLAGS) $(MOZBUILD_CFLAGS) $(EXTRA_COMPILE_FLAGS)
|
||||
COMPILE_CXXFLAGS = $(if $(DISABLE_STL_WRAPPING),,$(STL_FLAGS)) $(VISIBILITY_FLAGS) $(DEFINES) $(INCLUDES) $(DSO_CFLAGS) $(DSO_PIC_CFLAGS) $(RTL_FLAGS) $(OS_CPPFLAGS) $(OS_COMPILE_CXXFLAGS) $(CXXFLAGS) $(MOZBUILD_CXXFLAGS) $(EXTRA_COMPILE_FLAGS)
|
||||
COMPILE_CFLAGS = $(VISIBILITY_FLAGS) $(DEFINES) $(INCLUDES) $(OS_INCLUDES) $(DSO_CFLAGS) $(DSO_PIC_CFLAGS) $(RTL_FLAGS) $(OS_CPPFLAGS) $(OS_COMPILE_CFLAGS) $(CFLAGS) $(MOZBUILD_CFLAGS) $(EXTRA_COMPILE_FLAGS)
|
||||
COMPILE_CXXFLAGS = $(if $(DISABLE_STL_WRAPPING),,$(STL_FLAGS)) $(VISIBILITY_FLAGS) $(DEFINES) $(INCLUDES) $(OS_INCLUDES) $(DSO_CFLAGS) $(DSO_PIC_CFLAGS) $(RTL_FLAGS) $(OS_CPPFLAGS) $(OS_COMPILE_CXXFLAGS) $(CXXFLAGS) $(MOZBUILD_CXXFLAGS) $(EXTRA_COMPILE_FLAGS)
|
||||
COMPILE_CMFLAGS = $(OS_COMPILE_CMFLAGS) $(MOZBUILD_CMFLAGS) $(EXTRA_COMPILE_FLAGS)
|
||||
COMPILE_CMMFLAGS = $(OS_COMPILE_CMMFLAGS) $(MOZBUILD_CMMFLAGS) $(EXTRA_COMPILE_FLAGS)
|
||||
ASFLAGS += $(EXTRA_ASSEMBLER_FLAGS)
|
||||
@ -750,22 +756,5 @@ export NONASCII
|
||||
|
||||
DEFINES += -DNO_NSPR_10_SUPPORT
|
||||
|
||||
ifdef IS_GYP_DIR
|
||||
LOCAL_INCLUDES += \
|
||||
-I$(topsrcdir)/ipc/chromium/src \
|
||||
-I$(topsrcdir)/ipc/glue \
|
||||
-I$(DEPTH)/ipc/ipdl/_ipdlheaders \
|
||||
$(NULL)
|
||||
|
||||
ifeq (WINNT,$(OS_TARGET))
|
||||
# These get set via VC project file settings for normal GYP builds.
|
||||
DEFINES += -DUNICODE -D_UNICODE
|
||||
endif
|
||||
|
||||
DISABLE_STL_WRAPPING := 1
|
||||
# Skip most Mozilla-specific include locations.
|
||||
INCLUDES = -I. $(LOCAL_INCLUDES) -I$(DEPTH)/dist/include
|
||||
endif
|
||||
|
||||
# Freeze the values specified by moz.build to catch them if they fail.
|
||||
$(foreach var,$(_MOZBUILD_EXTERNAL_VARIABLES) $(_DEPRECATED_VARIABLES),$(eval $(var)_FROZEN := '$($(var))'))
|
||||
|
@ -142,6 +142,9 @@ public:
|
||||
|
||||
protected:
|
||||
double mX, mY, mWidth, mHeight;
|
||||
|
||||
private:
|
||||
~DOMRect() {};
|
||||
};
|
||||
|
||||
class DOMRectList MOZ_FINAL : public nsIDOMClientRectList,
|
||||
@ -210,12 +213,6 @@ protected:
|
||||
|
||||
}
|
||||
|
||||
template<>
|
||||
struct HasDangerousPublicDestructor<dom::DOMRect>
|
||||
{
|
||||
static const bool value = true;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif /*MOZILLA_DOMRECT_H_*/
|
||||
|
@ -1601,6 +1601,12 @@ nsDocument::~nsDocument()
|
||||
|
||||
NS_ASSERTION(!mIsShowing, "Destroying a currently-showing document");
|
||||
|
||||
// Note: This assert is only non-fatal because mochitest-bc triggers
|
||||
// it... as well as the preceding assert about !mIsShowing.
|
||||
NS_ASSERTION(!mObservingAppThemeChanged,
|
||||
"Document leaked to shutdown, then the observer service dropped "
|
||||
"its ref to us so we were able to go away.");
|
||||
|
||||
if (IsTopLevelContentDocument()) {
|
||||
//don't report for about: pages
|
||||
nsCOMPtr<nsIPrincipal> principal = GetPrincipal();
|
||||
@ -8873,7 +8879,10 @@ nsDocument::OnPageShow(bool aPersisted,
|
||||
"chrome-page-shown" :
|
||||
"content-page-shown",
|
||||
nullptr);
|
||||
os->AddObserver(this, "app-theme-changed", /* ownsWeak */ false);
|
||||
if (!mObservingAppThemeChanged) {
|
||||
os->AddObserver(this, "app-theme-changed", /* ownsWeak */ false);
|
||||
mObservingAppThemeChanged = true;
|
||||
}
|
||||
|
||||
DispatchPageTransition(target, NS_LITERAL_STRING("pageshow"), aPersisted);
|
||||
}
|
||||
@ -8949,6 +8958,7 @@ nsDocument::OnPageHide(bool aPersisted,
|
||||
nullptr);
|
||||
|
||||
os->RemoveObserver(this, "app-theme-changed");
|
||||
mObservingAppThemeChanged = false;
|
||||
}
|
||||
|
||||
DispatchPageTransition(target, NS_LITERAL_STRING("pagehide"), aPersisted);
|
||||
|
@ -1598,6 +1598,12 @@ public:
|
||||
|
||||
bool mAsyncFullscreenPending:1;
|
||||
|
||||
// Whether we're observing the "app-theme-changed" observer service
|
||||
// notification. We need to keep track of this because we might get multiple
|
||||
// OnPageShow notifications in a row without an OnPageHide in between, if
|
||||
// we're getting document.open()/close() called on us.
|
||||
bool mObservingAppThemeChanged:1;
|
||||
|
||||
// Keeps track of whether we have a pending
|
||||
// 'style-sheet-applicable-state-changed' notification.
|
||||
bool mSSApplicableStateNotificationPending:1;
|
||||
|
@ -26,10 +26,10 @@ class GlobalObject;
|
||||
} // namespace dom
|
||||
} // namespace mozilla
|
||||
|
||||
class nsFormData : public nsIDOMFormData,
|
||||
public nsIXHRSendable,
|
||||
public nsFormSubmission,
|
||||
public nsWrapperCache
|
||||
class nsFormData MOZ_FINAL : public nsIDOMFormData,
|
||||
public nsIXHRSendable,
|
||||
public nsFormSubmission,
|
||||
public nsWrapperCache
|
||||
{
|
||||
~nsFormData() {}
|
||||
|
||||
|
@ -1051,6 +1051,9 @@ nsFrameLoader::SwapWithOtherLoader(nsFrameLoader* aOther,
|
||||
nsCOMPtr<EventTarget> otherChromeEventHandler =
|
||||
do_QueryInterface(otherWindow->GetChromeEventHandler());
|
||||
|
||||
nsCOMPtr<EventTarget> ourEventTarget = ourWindow->GetParentTarget();
|
||||
nsCOMPtr<EventTarget> otherEventTarget = otherWindow->GetParentTarget();
|
||||
|
||||
NS_ASSERTION(SameCOMIdentity(ourFrameElement, ourContent) &&
|
||||
SameCOMIdentity(otherFrameElement, otherContent) &&
|
||||
SameCOMIdentity(ourChromeEventHandler, ourContent) &&
|
||||
@ -1100,25 +1103,25 @@ nsFrameLoader::SwapWithOtherLoader(nsFrameLoader* aOther,
|
||||
// Fire pageshow events on still-loading pages, and then fire pagehide
|
||||
// events. Note that we do NOT fire these in the normal way, but just fire
|
||||
// them on the chrome event handlers.
|
||||
FirePageShowEvent(ourDocshell, ourChromeEventHandler, false);
|
||||
FirePageShowEvent(otherDocshell, otherChromeEventHandler, false);
|
||||
FirePageHideEvent(ourDocshell, ourChromeEventHandler);
|
||||
FirePageHideEvent(otherDocshell, otherChromeEventHandler);
|
||||
FirePageShowEvent(ourDocshell, ourEventTarget, false);
|
||||
FirePageShowEvent(otherDocshell, otherEventTarget, false);
|
||||
FirePageHideEvent(ourDocshell, ourEventTarget);
|
||||
FirePageHideEvent(otherDocshell, otherEventTarget);
|
||||
|
||||
nsIFrame* ourFrame = ourContent->GetPrimaryFrame();
|
||||
nsIFrame* otherFrame = otherContent->GetPrimaryFrame();
|
||||
if (!ourFrame || !otherFrame) {
|
||||
mInSwap = aOther->mInSwap = false;
|
||||
FirePageShowEvent(ourDocshell, ourChromeEventHandler, true);
|
||||
FirePageShowEvent(otherDocshell, otherChromeEventHandler, true);
|
||||
FirePageShowEvent(ourDocshell, ourEventTarget, true);
|
||||
FirePageShowEvent(otherDocshell, otherEventTarget, true);
|
||||
return NS_ERROR_NOT_IMPLEMENTED;
|
||||
}
|
||||
|
||||
nsSubDocumentFrame* ourFrameFrame = do_QueryFrame(ourFrame);
|
||||
if (!ourFrameFrame) {
|
||||
mInSwap = aOther->mInSwap = false;
|
||||
FirePageShowEvent(ourDocshell, ourChromeEventHandler, true);
|
||||
FirePageShowEvent(otherDocshell, otherChromeEventHandler, true);
|
||||
FirePageShowEvent(ourDocshell, ourEventTarget, true);
|
||||
FirePageShowEvent(otherDocshell, otherEventTarget, true);
|
||||
return NS_ERROR_NOT_IMPLEMENTED;
|
||||
}
|
||||
|
||||
@ -1126,8 +1129,8 @@ nsFrameLoader::SwapWithOtherLoader(nsFrameLoader* aOther,
|
||||
rv = ourFrameFrame->BeginSwapDocShells(otherFrame);
|
||||
if (NS_FAILED(rv)) {
|
||||
mInSwap = aOther->mInSwap = false;
|
||||
FirePageShowEvent(ourDocshell, ourChromeEventHandler, true);
|
||||
FirePageShowEvent(otherDocshell, otherChromeEventHandler, true);
|
||||
FirePageShowEvent(ourDocshell, ourEventTarget, true);
|
||||
FirePageShowEvent(otherDocshell, otherEventTarget, true);
|
||||
return rv;
|
||||
}
|
||||
|
||||
@ -1230,8 +1233,8 @@ nsFrameLoader::SwapWithOtherLoader(nsFrameLoader* aOther,
|
||||
ourParentDocument->FlushPendingNotifications(Flush_Layout);
|
||||
otherParentDocument->FlushPendingNotifications(Flush_Layout);
|
||||
|
||||
FirePageShowEvent(ourDocshell, otherChromeEventHandler, true);
|
||||
FirePageShowEvent(otherDocshell, ourChromeEventHandler, true);
|
||||
FirePageShowEvent(ourDocshell, ourEventTarget, true);
|
||||
FirePageShowEvent(otherDocshell, otherEventTarget, true);
|
||||
|
||||
mInSwap = aOther->mInSwap = false;
|
||||
return NS_OK;
|
||||
|
@ -1035,6 +1035,16 @@ nsObjectLoadingContent::BuildParametersArray()
|
||||
}
|
||||
|
||||
nsAdoptingCString wmodeOverride = Preferences::GetCString("plugins.force.wmode");
|
||||
#if defined(XP_WIN) || defined(XP_LINUX)
|
||||
// Bug 923745 (/Bug 1061995) - Until we support windowed mode plugins in
|
||||
// content processes, force flash to use a windowless rendering mode. This
|
||||
// hack should go away when bug 923746 lands. (OS X plugins always use some
|
||||
// native widgets, so unfortunately this does not help there)
|
||||
if (wmodeOverride.IsEmpty() &&
|
||||
XRE_GetProcessType() == GeckoProcessType_Content) {
|
||||
wmodeOverride.AssignLiteral("transparent");
|
||||
}
|
||||
#endif
|
||||
|
||||
for (uint32_t i = 0; i < mCachedAttributes.Length(); i++) {
|
||||
if (!wmodeOverride.IsEmpty() && mCachedAttributes[i].mName.EqualsIgnoreCase("wmode")) {
|
||||
|
@ -35,7 +35,7 @@ class AutoJSAPI;
|
||||
// Script loader implementation
|
||||
//////////////////////////////////////////////////////////////
|
||||
|
||||
class nsScriptLoader : public nsIStreamLoaderObserver
|
||||
class nsScriptLoader MOZ_FINAL : public nsIStreamLoaderObserver
|
||||
{
|
||||
class MOZ_STACK_CLASS AutoCurrentScriptUpdater
|
||||
{
|
||||
|
@ -7,3 +7,5 @@ skip-if = e10s # Bug ?????? - test e10s utils don't support load events from ifr
|
||||
[browser_state_notifications.js]
|
||||
# skip-if = e10s # Bug ?????? - content-document-* notifications come while document's URI is still about:blank, but test expects real URL.
|
||||
skip-if = true # Intermittent failures - bug 987493. Restore the skip-if above once fixed
|
||||
[browser_bug1058164.js]
|
||||
skip-if = e10s # We need bug 918634 to land before this can be tested with e10s.
|
||||
|
106
content/base/test/browser_bug1058164.js
Normal file
@ -0,0 +1,106 @@
|
||||
/* 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";
|
||||
|
||||
const kTimeout = 5000; // ms
|
||||
|
||||
/**
|
||||
* Frame script injected in the test browser that sends
|
||||
* messages when it sees the pagehide and pageshow events
|
||||
* with the persisted property set to true.
|
||||
*/
|
||||
function frame_script() {
|
||||
addEventListener("pageshow", (event) => {
|
||||
if (event.persisted) {
|
||||
sendAsyncMessage("test:pageshow");
|
||||
}
|
||||
});
|
||||
addEventListener("pagehide", (event) => {
|
||||
if (event.persisted) {
|
||||
sendAsyncMessage("test:pagehide");
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Return a Promise that resolves when the browser's frame
|
||||
* script sees an event of type eventType. eventType can be
|
||||
* either "pagehide" or "pageshow". Times out after kTimeout
|
||||
* milliseconds if the event is never seen.
|
||||
*/
|
||||
function prepareForPageEvent(browser, eventType) {
|
||||
return new Promise((resolve, reject) => {
|
||||
let mm = browser.messageManager;
|
||||
|
||||
let timeoutId = setTimeout(() => {
|
||||
ok(false, "Timed out waiting for " + eventType)
|
||||
reject();
|
||||
}, kTimeout);
|
||||
|
||||
mm.addMessageListener("test:" + eventType, function onSawEvent(message) {
|
||||
mm.removeMessageListener("test:" + eventType, onSawEvent);
|
||||
ok(true, "Saw " + eventType + " event in frame script.");
|
||||
clearTimeout(timeoutId);
|
||||
resolve();
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a Promise that resolves when both the pagehide
|
||||
* and pageshow events have been seen from the frame script.
|
||||
*/
|
||||
function prepareForPageHideAndShow(browser) {
|
||||
return Promise.all([prepareForPageEvent(browser, "pagehide"),
|
||||
prepareForPageEvent(browser, "pageshow")]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a Promise that resolves when the load event for
|
||||
* aWindow fires during the capture phase.
|
||||
*/
|
||||
function waitForLoad(aWindow) {
|
||||
return new Promise((resolve, reject) => {
|
||||
aWindow.addEventListener("load", function onLoad(aEvent) {
|
||||
aWindow.removeEventListener("load", onLoad, true);
|
||||
resolve();
|
||||
}, true);
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests that frame scripts get pageshow / pagehide events when
|
||||
* swapping browser frameloaders (which occurs when moving a tab
|
||||
* into a different window).
|
||||
*/
|
||||
add_task(function* test_swap_frameloader_pagevisibility_events() {
|
||||
// Inject our frame script into a new browser.
|
||||
let tab = gBrowser.addTab();
|
||||
gBrowser.selectedTab = tab;
|
||||
let mm = window.getGroupMessageManager("browsers");
|
||||
mm.loadFrameScript("data:,(" + frame_script.toString() + ")();", true);
|
||||
let browser = gBrowser.selectedBrowser;
|
||||
|
||||
// Swap the browser out to a new window
|
||||
let newWindow = gBrowser.replaceTabWithWindow(tab);
|
||||
// We have to wait for the window to load so we can get the selected browser
|
||||
// to listen to.
|
||||
yield waitForLoad(newWindow);
|
||||
let pageHideAndShowPromise = prepareForPageHideAndShow(newWindow.gBrowser.selectedBrowser);
|
||||
// Yield waiting for the pagehide and pageshow events.
|
||||
yield pageHideAndShowPromise;
|
||||
|
||||
// Send the browser back to its original window
|
||||
let newTab = gBrowser.addTab();
|
||||
gBrowser.selectedTab = newTab;
|
||||
browser = newWindow.gBrowser.selectedBrowser;
|
||||
pageHideAndShowPromise = prepareForPageHideAndShow(gBrowser.selectedBrowser);
|
||||
gBrowser.swapBrowsersAndCloseOther(newTab, newWindow.gBrowser.selectedTab);
|
||||
|
||||
// Yield waiting for the pagehide and pageshow events.
|
||||
yield pageHideAndShowPromise;
|
||||
|
||||
gBrowser.removeTab(gBrowser.selectedTab);
|
||||
});
|
@ -48,9 +48,9 @@ protected:
|
||||
nsRefPtr<HTMLPropertiesCollection> mCollection;
|
||||
};
|
||||
|
||||
class HTMLPropertiesCollection : public nsIHTMLCollection,
|
||||
public nsStubMutationObserver,
|
||||
public nsWrapperCache
|
||||
class HTMLPropertiesCollection MOZ_FINAL : public nsIHTMLCollection,
|
||||
public nsStubMutationObserver,
|
||||
public nsWrapperCache
|
||||
{
|
||||
friend class PropertyNodeList;
|
||||
friend class PropertyStringList;
|
||||
|
@ -65,11 +65,6 @@ public:
|
||||
// Can be called on any thread.
|
||||
virtual void NotifyDecodedFrames(uint32_t aParsed, uint32_t aDecoded) = 0;
|
||||
|
||||
// Returns the end time of the last sample in the media. Note that a media
|
||||
// can have a non-zero start time, so the end time may not necessarily be
|
||||
// the same as the duration (i.e. duration is (end_time - start_time)).
|
||||
virtual int64_t GetEndMediaTime() const = 0;
|
||||
|
||||
// Return the duration of the media in microseconds.
|
||||
virtual int64_t GetMediaDuration() = 0;
|
||||
|
||||
|
@ -17,6 +17,20 @@ extern PRLogModuleInfo* gMediaStreamGraphLog;
|
||||
#define STREAM_LOG(type, msg)
|
||||
#endif
|
||||
|
||||
// We don't use NSPR log here because we want this interleaved with adb logcat
|
||||
// on Android/B2G
|
||||
// #define ENABLE_LIFECYCLE_LOG
|
||||
#ifdef ENABLE_LIFECYCLE_LOG
|
||||
#ifdef ANDROID
|
||||
#include "android/log.h"
|
||||
#define LIFECYCLE_LOG(args...) __android_log_print(ANDROID_LOG_INFO, "Gecko - MSG" , ## __VA_ARGS__); printf(__VA_ARGS__);printf("\n");
|
||||
#else
|
||||
#define LIFECYCLE_LOG(...) printf(__VA_ARGS__);printf("\n");
|
||||
#endif
|
||||
#else
|
||||
#define LIFECYCLE_LOG(...)
|
||||
#endif
|
||||
|
||||
namespace mozilla {
|
||||
|
||||
struct AutoProfilerUnregisterThread
|
||||
@ -68,10 +82,12 @@ void GraphDriver::SetGraphTime(GraphDriver* aPreviousDriver,
|
||||
void GraphDriver::SwitchAtNextIteration(GraphDriver* aNextDriver)
|
||||
{
|
||||
|
||||
STREAM_LOG(PR_LOG_DEBUG, ("Switching to new driver: %p (%s)", aNextDriver, aNextDriver->AsAudioCallbackDriver() ? "AudioCallbackDriver" : "SystemClockDriver"));
|
||||
LIFECYCLE_LOG("Switching to new driver: %p (%s)",
|
||||
aNextDriver, aNextDriver->AsAudioCallbackDriver() ?
|
||||
"AudioCallbackDriver" : "SystemClockDriver");
|
||||
// Sometimes we switch twice to a new driver per iteration, this is probably a
|
||||
// bug.
|
||||
MOZ_ASSERT(!mNextDriver || !mNextDriver->AsAudioCallbackDriver());
|
||||
MOZ_ASSERT(!mNextDriver || mNextDriver->AsAudioCallbackDriver());
|
||||
mNextDriver = aNextDriver;
|
||||
}
|
||||
|
||||
@ -115,6 +131,47 @@ void GraphDriver::EnsureNextIterationLocked()
|
||||
mNeedAnotherIteration = true;
|
||||
}
|
||||
|
||||
class MediaStreamGraphShutdownThreadRunnable : public nsRunnable {
|
||||
public:
|
||||
explicit MediaStreamGraphShutdownThreadRunnable(GraphDriver* aDriver)
|
||||
: mDriver(aDriver)
|
||||
{
|
||||
}
|
||||
NS_IMETHOD Run()
|
||||
{
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
|
||||
LIFECYCLE_LOG("MediaStreamGraphShutdownThreadRunnable for graph %p",
|
||||
mDriver->GraphImpl());
|
||||
// We can't release an audio driver on the main thread, because it can be
|
||||
// blocking.
|
||||
if (mDriver->AsAudioCallbackDriver()) {
|
||||
LIFECYCLE_LOG("Releasing audio driver off main thread.");
|
||||
nsRefPtr<AsyncCubebTask> releaseEvent =
|
||||
new AsyncCubebTask(mDriver->AsAudioCallbackDriver(),
|
||||
AsyncCubebTask::SHUTDOWN);
|
||||
mDriver = nullptr;
|
||||
releaseEvent->Dispatch();
|
||||
} else {
|
||||
LIFECYCLE_LOG("Dropping driver reference for SystemClockDriver.");
|
||||
mDriver = nullptr;
|
||||
}
|
||||
return NS_OK;
|
||||
}
|
||||
private:
|
||||
nsRefPtr<GraphDriver> mDriver;
|
||||
};
|
||||
|
||||
void GraphDriver::Shutdown()
|
||||
{
|
||||
if (AsAudioCallbackDriver()) {
|
||||
LIFECYCLE_LOG("Releasing audio driver off main thread (GraphDriver::Shutdown).\n");
|
||||
nsRefPtr<AsyncCubebTask> releaseEvent =
|
||||
new AsyncCubebTask(AsAudioCallbackDriver(), AsyncCubebTask::SHUTDOWN);
|
||||
releaseEvent->Dispatch();
|
||||
}
|
||||
}
|
||||
|
||||
ThreadedDriver::ThreadedDriver(MediaStreamGraphImpl* aGraphImpl)
|
||||
: GraphDriver(aGraphImpl)
|
||||
{ }
|
||||
@ -125,33 +182,6 @@ ThreadedDriver::~ThreadedDriver()
|
||||
mThread->Shutdown();
|
||||
}
|
||||
}
|
||||
|
||||
class MediaStreamGraphShutdownThreadRunnable : public nsRunnable {
|
||||
public:
|
||||
explicit MediaStreamGraphShutdownThreadRunnable(GraphDriver* aDriver)
|
||||
: mDriver(aDriver)
|
||||
{
|
||||
}
|
||||
NS_IMETHOD Run()
|
||||
{
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
// We can't release an audio driver on the main thread, because it can be
|
||||
// blocking.
|
||||
if (mDriver->AsAudioCallbackDriver()) {
|
||||
STREAM_LOG(PR_LOG_DEBUG, ("Releasing audio driver off main thread.\n"));
|
||||
nsRefPtr<AsyncCubebTask> releaseEvent =
|
||||
new AsyncCubebTask(mDriver->AsAudioCallbackDriver(), AsyncCubebTask::SHUTDOWN);
|
||||
mDriver = nullptr;
|
||||
releaseEvent->Dispatch();
|
||||
} else {
|
||||
mDriver = nullptr;
|
||||
}
|
||||
return NS_OK;
|
||||
}
|
||||
private:
|
||||
nsRefPtr<GraphDriver> mDriver;
|
||||
};
|
||||
|
||||
class MediaStreamGraphInitThreadRunnable : public nsRunnable {
|
||||
public:
|
||||
explicit MediaStreamGraphInitThreadRunnable(ThreadedDriver* aDriver)
|
||||
@ -163,7 +193,13 @@ public:
|
||||
char aLocal;
|
||||
STREAM_LOG(PR_LOG_DEBUG, ("Starting system thread"));
|
||||
profiler_register_thread("MediaStreamGraph", &aLocal);
|
||||
LIFECYCLE_LOG("Starting a new system driver for graph %p\n",
|
||||
mDriver->mGraphImpl);
|
||||
if (mDriver->mPreviousDriver) {
|
||||
LIFECYCLE_LOG("%p releasing an AudioCallbackDriver(%p), for graph %p\n",
|
||||
mDriver,
|
||||
mDriver->mPreviousDriver.get(),
|
||||
mDriver->GraphImpl());
|
||||
MOZ_ASSERT(!mDriver->AsAudioCallbackDriver());
|
||||
// Stop and release the previous driver off-main-thread.
|
||||
nsRefPtr<AsyncCubebTask> releaseEvent =
|
||||
@ -185,6 +221,7 @@ private:
|
||||
void
|
||||
ThreadedDriver::Start()
|
||||
{
|
||||
LIFECYCLE_LOG("Starting thread for a SystemClockDriver %p\n", mGraphImpl);
|
||||
nsCOMPtr<nsIRunnable> event = new MediaStreamGraphInitThreadRunnable(this);
|
||||
NS_NewNamedThread("MediaStreamGrph", getter_AddRefs(mThread), event);
|
||||
}
|
||||
@ -413,6 +450,17 @@ OfflineClockDriver::WakeUp()
|
||||
MOZ_ASSERT(false, "An offline graph should not have to wake up.");
|
||||
}
|
||||
|
||||
AsyncCubebTask::AsyncCubebTask(AudioCallbackDriver* aDriver, AsyncCubebOperation aOperation)
|
||||
: mDriver(aDriver),
|
||||
mOperation(aOperation),
|
||||
mShutdownGrip(aDriver->GraphImpl())
|
||||
{
|
||||
MOZ_ASSERT(mDriver->mAudioStream || aOperation == INIT, "No audio stream !");
|
||||
}
|
||||
|
||||
AsyncCubebTask::~AsyncCubebTask()
|
||||
{
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
AsyncCubebTask::Run()
|
||||
@ -432,14 +480,18 @@ AsyncCubebTask::Run()
|
||||
|
||||
switch(mOperation) {
|
||||
case AsyncCubebOperation::INIT:
|
||||
LIFECYCLE_LOG("AsyncCubebOperation::INIT\n");
|
||||
mDriver->Init();
|
||||
break;
|
||||
case AsyncCubebOperation::SHUTDOWN:
|
||||
LIFECYCLE_LOG("AsyncCubebOperation::SHUTDOWN\n");
|
||||
mDriver->Stop();
|
||||
mDriver = nullptr;
|
||||
mShutdownGrip = nullptr;
|
||||
break;
|
||||
case AsyncCubebOperation::SLEEP: {
|
||||
{
|
||||
LIFECYCLE_LOG("AsyncCubebOperation::SLEEP\n");
|
||||
MonitorAutoLock mon(mDriver->mGraphImpl->GetMonitor());
|
||||
// We might just have been awoken
|
||||
if (mDriver->mNeedAnotherIteration) {
|
||||
@ -797,7 +849,7 @@ AudioCallbackDriver::DataCallback(AudioDataValue* aBuffer, long aFrames)
|
||||
}
|
||||
|
||||
if (!stillProcessing) {
|
||||
STREAM_LOG(PR_LOG_DEBUG, ("Stopping audio thread for MediaStreamGraph %p", this));
|
||||
LIFECYCLE_LOG("Stopping audio thread for MediaStreamGraph %p", this);
|
||||
return aFrames - 1;
|
||||
}
|
||||
return aFrames;
|
||||
|
@ -96,6 +96,7 @@ public:
|
||||
virtual void Resume() = 0;
|
||||
/* Revive this driver, as more messages just arrived. */
|
||||
virtual void Revive() = 0;
|
||||
void Shutdown();
|
||||
/* Rate at which the GraphDriver runs, in ms. This can either be user
|
||||
* controlled (because we are using a {System,Offline}ClockDriver, and decide
|
||||
* how often we want to wakeup/how much we want to process per iteration), or
|
||||
@ -187,6 +188,10 @@ public:
|
||||
*/
|
||||
void EnsureNextIterationLocked();
|
||||
|
||||
MediaStreamGraphImpl* GraphImpl() {
|
||||
return mGraphImpl;
|
||||
}
|
||||
|
||||
protected:
|
||||
// Time of the start of this graph iteration.
|
||||
GraphTime mIterationStart;
|
||||
@ -460,12 +465,7 @@ public:
|
||||
};
|
||||
|
||||
|
||||
AsyncCubebTask(AudioCallbackDriver* aDriver, AsyncCubebOperation aOperation)
|
||||
: mDriver(aDriver),
|
||||
mOperation(aOperation)
|
||||
{
|
||||
MOZ_ASSERT(mDriver->mAudioStream || aOperation == INIT, "No audio stream !");
|
||||
}
|
||||
AsyncCubebTask(AudioCallbackDriver* aDriver, AsyncCubebOperation aOperation);
|
||||
|
||||
nsresult Dispatch()
|
||||
{
|
||||
@ -479,13 +479,14 @@ public:
|
||||
}
|
||||
|
||||
protected:
|
||||
virtual ~AsyncCubebTask() {};
|
||||
virtual ~AsyncCubebTask();
|
||||
|
||||
private:
|
||||
NS_IMETHOD Run() MOZ_OVERRIDE MOZ_FINAL;
|
||||
nsCOMPtr<nsIThread> mThread;
|
||||
nsRefPtr<AudioCallbackDriver> mDriver;
|
||||
AsyncCubebOperation mOperation;
|
||||
nsRefPtr<MediaStreamGraphImpl> mShutdownGrip;
|
||||
};
|
||||
|
||||
}
|
||||
|
@ -130,12 +130,10 @@ void MediaDecoder::SetDormantIfNecessary(bool aDormant)
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
ReentrantMonitorAutoEnter mon(GetReentrantMonitor());
|
||||
|
||||
if (!mDecoderStateMachine || !mDecoderStateMachine->IsDormantNeeded() || (mPlayState == PLAY_STATE_SHUTDOWN)) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (mIsDormant == aDormant) {
|
||||
// no change to dormant state
|
||||
if (!mDecoderStateMachine ||
|
||||
!mDecoderStateMachine->IsDormantNeeded() ||
|
||||
mPlayState == PLAY_STATE_SHUTDOWN ||
|
||||
mIsDormant == aDormant) {
|
||||
return;
|
||||
}
|
||||
|
||||
@ -149,16 +147,11 @@ void MediaDecoder::SetDormantIfNecessary(bool aDormant)
|
||||
SecondsToUsecs(mCurrentTime, timeUsecs);
|
||||
mRequestedSeekTarget = SeekTarget(timeUsecs, SeekTarget::Accurate);
|
||||
|
||||
if (mPlayState == PLAY_STATE_PLAYING){
|
||||
mNextState = PLAY_STATE_PLAYING;
|
||||
} else {
|
||||
mNextState = PLAY_STATE_PAUSED;
|
||||
}
|
||||
mNextState = mPlayState;
|
||||
mIsDormant = true;
|
||||
mIsExitingDormant = false;
|
||||
ChangeState(PLAY_STATE_LOADING);
|
||||
} else if ((aDormant != true) && (mPlayState == PLAY_STATE_LOADING)) {
|
||||
} else if (!aDormant && mPlayState == PLAY_STATE_LOADING) {
|
||||
// exit dormant state
|
||||
// trigger to state machine.
|
||||
mDecoderStateMachine->SetDormant(false);
|
||||
@ -170,7 +163,9 @@ void MediaDecoder::Pause()
|
||||
{
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
ReentrantMonitorAutoEnter mon(GetReentrantMonitor());
|
||||
if ((mPlayState == PLAY_STATE_LOADING && mIsDormant) || mPlayState == PLAY_STATE_SEEKING || mPlayState == PLAY_STATE_ENDED) {
|
||||
if ((mPlayState == PLAY_STATE_LOADING && mIsDormant) ||
|
||||
mPlayState == PLAY_STATE_SEEKING ||
|
||||
mPlayState == PLAY_STATE_ENDED) {
|
||||
mNextState = PLAY_STATE_PAUSED;
|
||||
return;
|
||||
}
|
||||
@ -869,8 +864,11 @@ void MediaDecoder::PlaybackEnded()
|
||||
{
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
|
||||
if (mShuttingDown || mPlayState == MediaDecoder::PLAY_STATE_SEEKING)
|
||||
if (mShuttingDown ||
|
||||
mPlayState == PLAY_STATE_SEEKING ||
|
||||
(mPlayState == PLAY_STATE_LOADING && mIsDormant)) {
|
||||
return;
|
||||
}
|
||||
|
||||
{
|
||||
ReentrantMonitorAutoEnter mon(GetReentrantMonitor());
|
||||
@ -1554,11 +1552,6 @@ bool MediaDecoder::IsShutdown() const {
|
||||
return GetStateMachine()->IsShutdown();
|
||||
}
|
||||
|
||||
int64_t MediaDecoder::GetEndMediaTime() const {
|
||||
NS_ENSURE_TRUE(GetStateMachine(), -1);
|
||||
return GetStateMachine()->GetEndMediaTime();
|
||||
}
|
||||
|
||||
// Drop reference to state machine. Only called during shutdown dance.
|
||||
void MediaDecoder::BreakCycles() {
|
||||
mDecoderStateMachine = nullptr;
|
||||
|
@ -581,8 +581,6 @@ public:
|
||||
// by the MediaResource read functions.
|
||||
void NotifyBytesConsumed(int64_t aBytes, int64_t aOffset) MOZ_FINAL MOZ_OVERRIDE;
|
||||
|
||||
int64_t GetEndMediaTime() const MOZ_FINAL MOZ_OVERRIDE;
|
||||
|
||||
// Return true if we are currently seeking in the media resource.
|
||||
// Call on the main thread only.
|
||||
virtual bool IsSeeking() const;
|
||||
|
@ -1450,6 +1450,7 @@ void MediaDecoderStateMachine::Play()
|
||||
|
||||
void MediaDecoderStateMachine::ResetPlayback()
|
||||
{
|
||||
AssertCurrentThreadInMonitor();
|
||||
MOZ_ASSERT(mState == DECODER_STATE_SEEKING ||
|
||||
mState == DECODER_STATE_SHUTDOWN ||
|
||||
mState == DECODER_STATE_DORMANT);
|
||||
@ -2485,7 +2486,7 @@ MediaDecoderStateMachine::FlushDecoding()
|
||||
{
|
||||
NS_ASSERTION(OnStateMachineThread() || OnDecodeThread(),
|
||||
"Should be on state machine or decode thread.");
|
||||
mDecoder->GetReentrantMonitor().AssertNotCurrentThreadIn();
|
||||
AssertCurrentThreadInMonitor();
|
||||
|
||||
{
|
||||
// Put a task in the decode queue to abort any decoding operations.
|
||||
|
@ -275,11 +275,6 @@ public:
|
||||
|
||||
void NotifyDataArrived(const char* aBuffer, uint32_t aLength, int64_t aOffset);
|
||||
|
||||
int64_t GetEndMediaTime() const {
|
||||
AssertCurrentThreadInMonitor();
|
||||
return mEndTime;
|
||||
}
|
||||
|
||||
// Returns the shared state machine thread.
|
||||
nsIEventTarget* GetStateMachineThread() const;
|
||||
|
||||
|
@ -936,6 +936,7 @@ ChannelMediaResource::RecreateChannel()
|
||||
loadGroup,
|
||||
nullptr,
|
||||
loadFlags);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
// We have cached the Content-Type, which should not change. Give a hint to
|
||||
// the channel to avoid a sniffing failure, which would be expected because we
|
||||
@ -1034,8 +1035,7 @@ ChannelMediaResource::CacheClientSeek(int64_t aOffset, bool aResume)
|
||||
}
|
||||
|
||||
nsresult rv = RecreateChannel();
|
||||
if (NS_FAILED(rv))
|
||||
return rv;
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
return OpenChannel(nullptr);
|
||||
}
|
||||
|
@ -45,6 +45,21 @@ PRLogModuleInfo* gMediaStreamGraphLog;
|
||||
#define STREAM_LOG(type, msg)
|
||||
#endif
|
||||
|
||||
// #define ENABLE_LIFECYCLE_LOG
|
||||
|
||||
// We don't use NSPR log here because we want this interleaved with adb logcat
|
||||
// on Android/B2G
|
||||
#ifdef ENABLE_LIFECYCLE_LOG
|
||||
# ifdef ANDROID
|
||||
# include "android/log.h"
|
||||
# define LIFECYCLE_LOG(...) __android_log_print(ANDROID_LOG_INFO, "Gecko - MSG", ## __VA_ARGS__); printf(__VA_ARGS__);printf("\n");
|
||||
# else
|
||||
# define LIFECYCLE_LOG(...) printf(__VA_ARGS__);printf("\n");
|
||||
# endif
|
||||
#else
|
||||
# define LIFECYCLE_LOG(...)
|
||||
#endif
|
||||
|
||||
/**
|
||||
* The singleton graph instance.
|
||||
*/
|
||||
@ -55,6 +70,7 @@ MediaStreamGraphImpl::~MediaStreamGraphImpl()
|
||||
NS_ASSERTION(IsEmpty(),
|
||||
"All streams should have been destroyed by messages from the main thread");
|
||||
STREAM_LOG(PR_LOG_DEBUG, ("MediaStreamGraph %p destroyed", this));
|
||||
LIFECYCLE_LOG("MediaStreamGraphImpl::~MediaStreamGraphImpl\n");
|
||||
}
|
||||
|
||||
|
||||
@ -526,8 +542,11 @@ MediaStreamGraphImpl::UpdateStreamOrder()
|
||||
started = CurrentDriver()->AsAudioCallbackDriver()->IsStarted();
|
||||
}
|
||||
if (started) {
|
||||
SystemClockDriver* driver = new SystemClockDriver(this);
|
||||
CurrentDriver()->SwitchAtNextIteration(driver);
|
||||
MonitorAutoLock mon(mMonitor);
|
||||
if (mLifecycleState == LIFECYCLE_RUNNING) {
|
||||
SystemClockDriver* driver = new SystemClockDriver(this);
|
||||
CurrentDriver()->SwitchAtNextIteration(driver);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -905,9 +924,12 @@ MediaStreamGraphImpl::CreateOrDestroyAudioStreams(GraphTime aAudioOutputStartTim
|
||||
|
||||
if (!CurrentDriver()->AsAudioCallbackDriver() &&
|
||||
!CurrentDriver()->Switching()) {
|
||||
AudioCallbackDriver* driver = new AudioCallbackDriver(this);
|
||||
mMixer.AddCallback(driver);
|
||||
CurrentDriver()->SwitchAtNextIteration(driver);
|
||||
MonitorAutoLock mon(mMonitor);
|
||||
if (mLifecycleState == LIFECYCLE_RUNNING) {
|
||||
AudioCallbackDriver* driver = new AudioCallbackDriver(this);
|
||||
mMixer.AddCallback(driver);
|
||||
CurrentDriver()->SwitchAtNextIteration(driver);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1456,13 +1478,13 @@ public:
|
||||
NS_ASSERTION(mGraph->mDetectedNotRunning,
|
||||
"We should know the graph thread control loop isn't running!");
|
||||
|
||||
STREAM_LOG(PR_LOG_DEBUG, ("Shutting down graph %p", mGraph.get()));
|
||||
LIFECYCLE_LOG("Shutting down graph %p", mGraph.get());
|
||||
|
||||
if (mGraph->CurrentDriver()->AsAudioCallbackDriver()) {
|
||||
MOZ_ASSERT(!mGraph->CurrentDriver()->AsAudioCallbackDriver()->InCallback());
|
||||
}
|
||||
|
||||
mGraph->CurrentDriver()->Stop();
|
||||
mGraph->CurrentDriver()->Shutdown();
|
||||
|
||||
// mGraph's thread is not running so it's OK to do whatever here
|
||||
if (mGraph->IsEmpty()) {
|
||||
@ -1559,6 +1581,23 @@ MediaStreamGraphImpl::RunInStableState(bool aSourceIsMSG)
|
||||
mPostedRunInStableStateEvent = false;
|
||||
}
|
||||
|
||||
#ifdef ENABLE_LIFECYCLE_LOG
|
||||
// This should be kept in sync with the LifecycleState enum in
|
||||
// MediaStreamGraphImpl.h
|
||||
const char * LifecycleState_str[] = {
|
||||
"LIFECYCLE_THREAD_NOT_STARTED",
|
||||
"LIFECYCLE_RUNNING",
|
||||
"LIFECYCLE_WAITING_FOR_MAIN_THREAD_CLEANUP",
|
||||
"LIFECYCLE_WAITING_FOR_THREAD_SHUTDOWN",
|
||||
"LIFECYCLE_WAITING_FOR_STREAM_DESTRUCTION"
|
||||
};
|
||||
|
||||
if (mLifecycleState != LIFECYCLE_RUNNING) {
|
||||
LIFECYCLE_LOG("Running %p in stable state. Current state: %s\n",
|
||||
this, LifecycleState_str[mLifecycleState]);
|
||||
}
|
||||
#endif
|
||||
|
||||
runnables.SwapElements(mUpdateRunnables);
|
||||
for (uint32_t i = 0; i < mStreamUpdates.Length(); ++i) {
|
||||
StreamUpdate* update = &mStreamUpdates[i];
|
||||
@ -1572,17 +1611,19 @@ MediaStreamGraphImpl::RunInStableState(bool aSourceIsMSG)
|
||||
if (mLifecycleState == LIFECYCLE_WAITING_FOR_MAIN_THREAD_CLEANUP && IsEmpty()) {
|
||||
// Complete shutdown. First, ensure that this graph is no longer used.
|
||||
// A new graph graph will be created if one is needed.
|
||||
STREAM_LOG(PR_LOG_DEBUG, ("Disconnecting MediaStreamGraph %p", this));
|
||||
if (this == gGraph) {
|
||||
// null out gGraph if that's the graph being shut down
|
||||
gGraph = nullptr;
|
||||
}
|
||||
// Asynchronously clean up old graph. We don't want to do this
|
||||
// synchronously because it spins the event loop waiting for threads
|
||||
// to shut down, and we don't want to do that in a stable state handler.
|
||||
mLifecycleState = LIFECYCLE_WAITING_FOR_THREAD_SHUTDOWN;
|
||||
LIFECYCLE_LOG("Sending MediaStreamGraphShutDownRunnable %p", this);
|
||||
nsCOMPtr<nsIRunnable> event = new MediaStreamGraphShutDownRunnable(this );
|
||||
NS_DispatchToMainThread(event);
|
||||
|
||||
LIFECYCLE_LOG("Disconnecting MediaStreamGraph %p", this);
|
||||
if (this == gGraph) {
|
||||
// null out gGraph if that's the graph being shut down
|
||||
gGraph = nullptr;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if (mLifecycleState <= LIFECYCLE_WAITING_FOR_MAIN_THREAD_CLEANUP) {
|
||||
@ -1605,6 +1646,9 @@ MediaStreamGraphImpl::RunInStableState(bool aSourceIsMSG)
|
||||
// or it might exit immediately.
|
||||
{
|
||||
MonitorAutoUnlock unlock(mMonitor);
|
||||
LIFECYCLE_LOG("Reviving a graph (%p) ! %s\n",
|
||||
this, CurrentDriver()->AsAudioCallbackDriver() ? "AudioDriver" :
|
||||
"SystemDriver");
|
||||
CurrentDriver()->Revive();
|
||||
}
|
||||
}
|
||||
@ -1622,7 +1666,10 @@ MediaStreamGraphImpl::RunInStableState(bool aSourceIsMSG)
|
||||
// We should exit the monitor for now, because starting a stream might
|
||||
// take locks, and we don't want to deadlock.
|
||||
MonitorAutoUnlock unlock(mMonitor);
|
||||
STREAM_LOG(PR_LOG_DEBUG, ("Starting a graph ! %s\n", CurrentDriver()->AsAudioCallbackDriver() ? "AudioDriver" : "SystemDriver"));
|
||||
LIFECYCLE_LOG("Starting a graph (%p) ! %s\n",
|
||||
this,
|
||||
CurrentDriver()->AsAudioCallbackDriver() ? "AudioDriver" :
|
||||
"SystemDriver");
|
||||
CurrentDriver()->Start();
|
||||
}
|
||||
}
|
||||
|
@ -688,7 +688,8 @@ public:
|
||||
mMutex("mozilla::media::SourceMediaStream"),
|
||||
mUpdateKnownTracksTime(0),
|
||||
mPullEnabled(false),
|
||||
mUpdateFinished(false)
|
||||
mUpdateFinished(false),
|
||||
mNeedsMixing(false)
|
||||
{}
|
||||
|
||||
virtual SourceMediaStream* AsSourceStream() { return this; }
|
||||
|
@ -520,6 +520,9 @@ public:
|
||||
* is not deleted. New messages for the graph are processed synchronously on
|
||||
* the main thread if necessary. When the last stream is destroyed, the
|
||||
* graph object is deleted.
|
||||
*
|
||||
* This should be kept in sync with the LifecycleState_str array in
|
||||
* MediaStreamGraph.cpp
|
||||
*/
|
||||
enum LifecycleState {
|
||||
// The graph thread hasn't started yet.
|
||||
|