Merge m-c to b2g-inbound.

This commit is contained in:
Ryan VanderMeulen 2013-11-05 15:37:26 -05:00
commit 47a001ba82
245 changed files with 5879 additions and 8393 deletions

View File

@ -213,9 +213,6 @@ AccGroupInfo::IsConceptualParent(role aRole, role aParentRole)
if ((aParentRole == roles::TABLE || aParentRole == roles::TREE_TABLE) &&
aRole == roles::ROW)
return true;
if (aParentRole == roles::ROW &&
(aRole == roles::CELL || aRole == roles::GRID_CELL))
return true;
if (aParentRole == roles::LIST && aRole == roles::LISTITEM)
return true;
if (aParentRole == roles::COMBOBOX_LIST && aRole == roles::COMBOBOX_OPTION)

View File

@ -41,7 +41,6 @@ public:
{
mozilla::a11y::role role = aAccessible->Role();
if (role != mozilla::a11y::roles::ROW &&
role != mozilla::a11y::roles::GRID_CELL &&
role != mozilla::a11y::roles::OUTLINEITEM &&
role != mozilla::a11y::roles::OPTION &&
role != mozilla::a11y::roles::LISTITEM &&

View File

@ -140,26 +140,26 @@
//////////////////////////////////////////////////////////////////////////
// ARIA grid
testGroupAttrs("grid_row1", 1, 2);
testGroupAttrs("grid_cell1", 1, 2);
testGroupAttrs("grid_cell2", 2, 2);
testAbsentAttrs("grid_cell1", {"posinset":"", "setsize":""});
testAbsentAttrs("grid_cell2", {"posinset":"", "setsize":""});
testGroupAttrs("grid_row2", 2, 2);
testGroupAttrs("grid_cell3", 1, 2);
testGroupAttrs("grid_cell4", 2, 2);
testAbsentAttrs("grid_cell3", {"posinset":"", "setsize":""});
testAbsentAttrs("grid_cell4", {"posinset":"", "setsize":""});
//////////////////////////////////////////////////////////////////////////
// ARIA treegrid
testGroupAttrs("treegrid_row1", 1, 2, 1);
testGroupAttrs("treegrid_cell1", 1, 2);
testGroupAttrs("treegrid_cell2", 2, 2);
testAbsentAttrs("treegrid_cell1", {"posinset":"", "setsize":""});
testAbsentAttrs("treegrid_cell2", {"posinset":"", "setsize":""});
testGroupAttrs("treegrid_row2", 1, 1, 2);
testGroupAttrs("treegrid_cell3", 1, 2);
testGroupAttrs("treegrid_cell4", 2, 2);
testAbsentAttrs("treegrid_cell3", {"posinset":"", "setsize":""});
testAbsentAttrs("treegrid_cell4", {"posinset":"", "setsize":""});
testGroupAttrs("treegrid_row3", 2, 2, 1);
testGroupAttrs("treegrid_cell5", 1, 2);
testGroupAttrs("treegrid_cell6", 2, 2);
testAbsentAttrs("treegrid_cell5", {"posinset":"", "setsize":""});
testAbsentAttrs("treegrid_cell6", {"posinset":"", "setsize":""});
//////////////////////////////////////////////////////////////////////////
// HTML headings

View File

@ -150,7 +150,7 @@ XRE_SetupDllBlocklistType XRE_SetupDllBlocklist;
XRE_TelemetryAccumulateType XRE_TelemetryAccumulate;
XRE_StartupTimelineRecordType XRE_StartupTimelineRecord;
XRE_mainType XRE_main;
XRE_DisableWritePoisoningType XRE_DisableWritePoisoning;
XRE_StopLateWriteChecksType XRE_StopLateWriteChecks;
static const nsDynamicFunctionLoad kXULFuncs[] = {
{ "XRE_GetFileFromPath", (NSFuncPtr*) &XRE_GetFileFromPath },
@ -162,7 +162,7 @@ static const nsDynamicFunctionLoad kXULFuncs[] = {
{ "XRE_TelemetryAccumulate", (NSFuncPtr*) &XRE_TelemetryAccumulate },
{ "XRE_StartupTimelineRecord", (NSFuncPtr*) &XRE_StartupTimelineRecord },
{ "XRE_main", (NSFuncPtr*) &XRE_main },
{ "XRE_DisableWritePoisoning", (NSFuncPtr*) &XRE_DisableWritePoisoning },
{ "XRE_StopLateWriteChecks", (NSFuncPtr*) &XRE_StopLateWriteChecks },
{ nullptr, nullptr }
};
@ -642,7 +642,7 @@ int main(int argc, char* argv[])
// at least one such write that we don't control (see bug 826029). For
// now we enable writes again and early exits will have to use exit instead
// of _exit.
XRE_DisableWritePoisoning();
XRE_StopLateWriteChecks();
#endif
return result;

View File

@ -244,6 +244,7 @@ pref("lightweightThemes.update.enabled", true);
// UI tour experience.
pref("browser.uitour.enabled", true);
pref("browser.uitour.requireSecure", true);
pref("browser.uitour.themeOrigin", "https://addons.mozilla.org/%LOCALE%/firefox/themes/");
pref("browser.uitour.pinnedTabUrl", "https://support.mozilla.org/%LOCALE%/kb/pinned-tabs-keep-favorite-websites-open");
pref("browser.uitour.whitelist.add.260", "www.mozilla.org,support.mozilla.org");

View File

@ -146,7 +146,8 @@ let gPage = {
handleEvent: function Page_handleEvent(aEvent) {
switch (aEvent.type) {
case "unload":
this._mutationObserver.disconnect();
if (this._mutationObserver)
this._mutationObserver.disconnect();
gAllPages.unregister(this);
break;
case "click":

View File

@ -15,24 +15,20 @@ function test() {
// Verify that about:preferences tab is displayed when
// browser.preferences.inContent is set to true
Services.prefs.setBoolPref("browser.preferences.inContent", true);
gBrowser.tabContainer.addEventListener("TabOpen", function(aEvent) {
gBrowser.tabContainer.removeEventListener("TabOpen", arguments.callee, true);
let browser = aEvent.originalTarget.linkedBrowser;
browser.addEventListener("load", function(aEvent) {
browser.removeEventListener("load", arguments.callee, true);
is(Services.prefs.getBoolPref("browser.preferences.inContent"), true, "In-content prefs are enabled");
is(browser.contentWindow.location.href, "about:preferences", "Checking if the preferences tab was opened");
gBrowser.removeCurrentTab();
Services.prefs.setBoolPref("browser.preferences.inContent", false);
openPreferences();
}, true);
}, true);
// Open a new tab.
whenNewTabLoaded(window, testPreferences);
}
function testPreferences() {
whenTabLoaded(gBrowser.selectedTab, function () {
is(Services.prefs.getBoolPref("browser.preferences.inContent"), true, "In-content prefs are enabled");
is(content.location.href, "about:preferences", "Checking if the preferences tab was opened");
gBrowser.removeCurrentTab();
Services.prefs.setBoolPref("browser.preferences.inContent", false);
openPreferences();
});
let observer = {
observe: function(aSubject, aTopic, aData) {

View File

@ -237,9 +237,14 @@ function whenNewTabLoaded(aWindow, aCallback) {
return;
}
whenTabLoaded(aWindow.gBrowser.selectedTab, aCallback);
}
function whenTabLoaded(aTab, aCallback) {
let browser = aTab.linkedBrowser;
browser.addEventListener("load", function onLoad() {
browser.removeEventListener("load", onLoad, true);
aCallback();
executeSoon(aCallback);
}, true);
}

View File

@ -473,8 +473,37 @@ function openAboutDialog() {
function openPreferences(paneID, extraArgs)
{
if (Services.prefs.getBoolPref("browser.preferences.inContent")) {
openUILinkIn("about:preferences", "tab");
function switchToAdvancedSubPane(doc) {
if (extraArgs && extraArgs["advancedTab"]) {
let advancedPaneTabs = doc.getElementById("advancedPrefs");
advancedPaneTabs.selectedTab = doc.getElementById(extraArgs["advancedTab"]);
}
}
if (getBoolPref("browser.preferences.inContent")) {
let win = Services.wm.getMostRecentWindow("navigator:browser");
if (!win) {
return;
}
let newLoad = !win.switchToTabHavingURI("about:preferences", true);
let browser = win.gBrowser.selectedBrowser;
function switchToPane() {
if (paneID) {
browser.contentWindow.selectCategory(paneID);
}
switchToAdvancedSubPane(browser.contentDocument);
}
if (newLoad) {
browser.addEventListener("load", function onload() {
browser.removeEventListener("load", onload, true);
switchToPane();
}, true);
} else {
switchToPane();
}
} else {
var instantApply = getBoolPref("browser.preferences.instantApply", false);
var features = "chrome,titlebar,toolbar,centerscreen" + (instantApply ? ",dialog=no" : ",modal");
@ -487,16 +516,11 @@ function openPreferences(paneID, extraArgs)
win.document.documentElement.showPane(pane);
}
if (extraArgs && extraArgs["advancedTab"]) {
var advancedPaneTabs = win.document.getElementById("advancedPrefs");
advancedPaneTabs.selectedTab = win.document.getElementById(extraArgs["advancedTab"]);
}
return;
switchToAdvancedSubPane(win.document);
} else {
openDialog("chrome://browser/content/preferences/preferences.xul",
"Preferences", features, paneID, extraArgs);
}
openDialog("chrome://browser/content/preferences/preferences.xul",
"Preferences", features, paneID, extraArgs);
}
}

View File

@ -452,8 +452,10 @@ nsBrowserContentHandler.prototype = {
var chromeParam = cmdLine.handleFlagWithParam("chrome", false);
if (chromeParam) {
// Handle the old preference dialog URL separately (bug 285416)
if (chromeParam == "chrome://browser/content/pref/pref.xul") {
// Handle old preference dialog URLs.
if (chromeParam == "chrome://browser/content/pref/pref.xul" ||
(Services.prefs.getBoolPref("browser.preferences.inContent") &&
chromeParam == "chrome://browser/content/preferences/preferences.xul")) {
openPreferences();
cmdLine.preventDefault = true;
} else try {

View File

@ -2,11 +2,11 @@
* 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/. */
richlistitem {
#handlersView > richlistitem {
-moz-binding: url("chrome://browser/content/preferences/handlers.xml#handler");
}
richlistitem[selected="true"] {
#handlersView > richlistitem[selected="true"] {
-moz-binding: url("chrome://browser/content/preferences/handlers.xml#handler-selected");
}

View File

@ -128,11 +128,6 @@
#endif
<stringbundle id="bundlePreferences" src="chrome://browser/locale/preferences/preferences.properties"/>
<hbox class="heading" data-category="paneAdvanced" hidden="true">
<image class="preference-icon" type="advanced"/>
<html:h1>&paneAdvanced.title;</html:h1>
</hbox>
<tabbox id="advancedPrefs" flex="1"
data-category="paneAdvanced" hidden="true"
onselect="gAdvancedPane.tabSelectionChanged();">

View File

@ -55,11 +55,6 @@
<key key="&focusSearch2.key;" modifiers="accel" oncommand="gApplicationsPane.focusFilterBox();"/>
</keyset>
<hbox class="heading" data-category="paneApplications" hidden="true">
<image class="preference-icon" type="applications"/>
<html:h1>&paneApplications.title;</html:h1>
</hbox>
<vbox data-category="paneApplications" hidden="true" flex="1">
<hbox>
<textbox id="filter" flex="1"

View File

@ -21,12 +21,9 @@
<script type="application/javascript"
src="chrome://browser/content/preferences/in-content/content.js"/>
<hbox class="heading" data-category="paneContent" hidden="true">
<image class="preference-icon" type="content"/>
<html:h1>&paneContent.title;</html:h1>
</hbox>
<groupbox id="miscGroup" data-category="paneContent" hidden="true">
<caption label="&popups.label;"/>
<grid id="contentGrid">
<columns>
<column flex="1"/>

View File

@ -4,7 +4,6 @@
browser.jar:
content/browser/preferences/in-content/preferences.js
content/browser/preferences/in-content/landing.xul
* content/browser/preferences/in-content/preferences.xul
* content/browser/preferences/in-content/main.xul
* content/browser/preferences/in-content/main.js

View File

@ -1,55 +0,0 @@
<!-- This Source Code Form is subject to the terms of the Mozilla Public
- License, v. 2.0. If a copy of the MPL was not distributed with this file,
- You can obtain one at http://mozilla.org/MPL/2.0/. -->
<vbox data-category="landing">
<html:h1 class="indent-small">&brandShortName;</html:h1>
<hbox id="preferences-home" flex="1">
<button label="&paneGeneral.title;" class="landingButton"
oncommand="gotoPref('paneGeneral');">
<image class="landingButton-icon" type="general"/>
<label class="landingButton-label">&paneGeneral.title;</label>
</button>
<button label="&paneContent.title;" class="landingButton"
oncommand="gotoPref('paneContent');">
<image class="landingButton-icon" type="content"/>
<label class="landingButton-label">&paneContent.title;</label>
</button>
<button label="&paneApplications.title;" class="landingButton"
oncommand="gotoPref('paneApplications');">
<image class="landingButton-icon" type="applications"/>
<label class="landingButton-label">&paneApplications.title;</label>
</button>
<button label="&panePrivacy.title;" class="landingButton"
oncommand="gotoPref('panePrivacy');">
<image class="landingButton-icon" type="privacy"/>
<label class="landingButton-label">&panePrivacy.title;</label>
</button>
<button label="&paneSecurity.title;" class="landingButton"
oncommand="gotoPref('paneSecurity');">
<image class="landingButton-icon" type="security"/>
<label class="landingButton-label">&paneSecurity.title;</label>
</button>
<button label="&paneSync.title;" class="landingButton"
oncommand="gotoPref('paneSync');">
<image class="landingButton-icon" type="sync"/>
<label class="landingButton-label">&paneSync.title;</label>
</button>
<button label="&paneAdvanced.title;" class="landingButton"
oncommand="gotoPref('paneAdvanced');">
<image class="landingButton-icon" type="advanced"/>
<label class="landingButton-label">&paneAdvanced.title;</label>
</button>
</hbox>
</vbox>

View File

@ -85,13 +85,8 @@
#endif
</preferences>
<hbox class="heading" data-category="paneGeneral" hidden="true">
<image class="preference-icon" type="general"/>
<html:h1>&paneGeneral.title;</html:h1>
</hbox>
<!-- Startup -->
<groupbox id="startupGroup" data-category="paneGeneral" hidden="true">
<groupbox id="startupGroup" data-category="paneGeneral">
<caption label="&startup.label;"/>
<hbox align="center">
@ -150,7 +145,7 @@
</groupbox>
<!-- Downloads -->
<groupbox id="downloadsGroup" data-category="paneGeneral" hidden="true">
<groupbox id="downloadsGroup" data-category="paneGeneral">
<caption label="&downloads.label;"/>
<radiogroup id="saveWhere"
@ -189,7 +184,7 @@
</groupbox>
<!-- Tab preferences -->
<groupbox data-category="paneGeneral" hidden="true">
<groupbox data-category="paneGeneral">
<caption label="&tabsGroup.label;"/>
<checkbox id="linkTargeting" label="&newWindowsAsTabs.label;"
accesskey="&newWindowsAsTabs.accesskey;"

View File

@ -12,11 +12,13 @@ const Cr = Components.results;
Cu.import("resource://gre/modules/XPCOMUtils.jsm");
Cu.import("resource://gre/modules/Services.jsm");
addEventListener("DOMContentLoaded", function onLoad() {
removeEventListener("DOMContentLoaded", onLoad);
init_all();
});
function init_all() {
document.documentElement.instantApply = true;
window.history.replaceState("landing", document.title);
window.addEventListener("popstate", onStatePopped, true);
updateCommands();
gMainPane.init();
gPrivacyPane.init();
gAdvancedPane.init();
@ -27,12 +29,32 @@ function init_all() {
var initFinished = document.createEvent("Event");
initFinished.initEvent("Initialized", true, true);
document.dispatchEvent(initFinished);
let categories = document.getElementById("categories");
categories.addEventListener("select", event => gotoPref(event.target.value));
window.addEventListener("popstate", event => selectCategory(event.state));
if (history.length > 1 && history.state) {
updateCommands();
selectCategory(history.state);
} else {
history.replaceState("paneGeneral", document.title);
}
}
function selectCategory(name) {
let categories = document.getElementById("categories");
let item = categories.querySelector(".category[value=" + name + "]");
categories.selectedItem = item;
}
function gotoPref(page) {
search(page, "data-category");
window.history.pushState(page, document.title);
if (history.state != page) {
window.history.pushState(page, document.title);
}
updateCommands();
search(page, "data-category");
}
function cmd_back() {
@ -43,11 +65,6 @@ function cmd_forward() {
window.history.forward();
}
function onStatePopped(aEvent) {
updateCommands();
search(aEvent.state, "data-category");
}
function updateCommands() {
document.getElementById("back-btn").disabled = !canGoBack();
document.getElementById("forward-btn").disabled = !canGoForward();

View File

@ -54,8 +54,7 @@
#define USE_WIN_TITLE_STYLE
#endif
<page onload="init_all();"
xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
<page xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
xmlns:html="http://www.w3.org/1999/xhtml"
#ifdef USE_WIN_TITLE_STYLE
title="&prefWindow.titleWin;">
@ -86,10 +85,58 @@
oncommand="cmd_forward()" tooltiptext="&buttonForward.tooltip;"
disabled="true"/>
</hbox>
<hbox class="main-content" flex="1">
<prefpane flex="1" id="mainPrefPane">
#include landing.xul
<hbox flex="1">
<!-- category list -->
<richlistbox id="categories">
<richlistitem id="category-general" class="category" align="center"
value="paneGeneral" tooltiptext="&paneGeneral.title;">
<image class="category-icon"/>
<label class="category-name" flex="1" value="&paneGeneral.title;"/>
</richlistitem>
<richlistitem id="category-content" class="category" align="center"
value="paneContent" tooltiptext="&paneContent.title;">
<image class="category-icon"/>
<label class="category-name" flex="1" value="&paneContent.title;"/>
</richlistitem>
<richlistitem id="category-application" class="category" align="center"
value="paneApplications" tooltiptext="&paneApplications.title;">
<image class="category-icon"/>
<label class="category-name" flex="1" value="&paneApplications.title;"/>
</richlistitem>
<richlistitem id="category-privacy" class="category" align="center"
value="panePrivacy" tooltiptext="&panePrivacy.title;">
<image class="category-icon"/>
<label class="category-name" flex="1" value="&panePrivacy.title;"/>
</richlistitem>
<richlistitem id="category-security" class="category" align="center"
value="paneSecurity" tooltiptext="&paneSecurity.title;">
<image class="category-icon"/>
<label class="category-name" flex="1" value="&paneSecurity.title;"/>
</richlistitem>
#ifdef MOZ_SERVICES_SYNC
<richlistitem id="category-sync" class="category" align="center"
value="paneSync" tooltiptext="&paneSync.title;">
<image class="category-icon"/>
<label class="category-name" flex="1" value="&paneSync.title;"/>
</richlistitem>
#endif
<richlistitem id="category-advanced" class="category" align="center"
value="paneAdvanced" tooltiptext="&paneAdvanced.title;">
<image class="category-icon"/>
<label class="category-name" flex="1" value="&paneAdvanced.title;"/>
</richlistitem>
</richlistbox>
<box class="main-content" flex="1">
<prefpane flex="1" id="mainPrefPane">
#include main.xul
#include privacy.xul
#include advanced.xul
@ -99,7 +146,8 @@
#ifdef MOZ_SERVICES_SYNC
#include sync.xul
#endif
</prefpane>
</prefpane>
</box>
</hbox>
</page>

View File

@ -65,11 +65,6 @@
</preferences>
<hbox class="heading" data-category="panePrivacy" hidden="true">
<image class="preference-icon" type="privacy"/>
<html:h1>&panePrivacy.title;</html:h1>
</hbox>
<!-- Tracking -->
<groupbox id="trackingGroup" data-category="panePrivacy" hidden="true" align="start">
<caption label="&tracking.label;"/>

View File

@ -30,13 +30,10 @@
</preferences>
<hbox class="heading" data-category="paneSecurity" hidden="true">
<image class="preference-icon" type="security"/>
<html:h1>&paneSecurity.title;</html:h1>
</hbox>
<!-- addons, forgery (phishing) UI -->
<groupbox id="addonsPhishingGroup" data-category="paneSecurity" hidden="true">
<caption label="&general.label;"/>
<hbox id="addonInstallBox">
<checkbox id="warnAddonInstall" flex="1"
label="&warnAddonInstall.label;"

View File

@ -28,11 +28,6 @@
<script type="application/javascript"
src="chrome://browser/content/sync/utils.js"/>
<hbox class="heading" data-category="paneSync" hidden="true">
<image class="preference-icon" type="sync"/>
<html:h1>&paneSync.title;</html:h1>
</hbox>
<deck id="weavePrefsDeck" data-category="paneSync" hidden="true">
<vbox id="noAccount" align="center">
<spacer flex="1"/>

View File

@ -149,7 +149,7 @@ AppValidator.prototype.validateLaunchPath = function (manifest) {
try {
indexURL = Services.io.newURI(path, null, Services.io.newURI(origin, null, null)).spec;
} catch(e) {
this.error(strings.formatStringFromName("validator.invalidLaunchPath", [origin + path], 1));
this.error(strings.formatStringFromName("validator.accessFailedLaunchPath", [origin + path], 1));
deferred.resolve();
return deferred.promise;
}
@ -158,25 +158,25 @@ AppValidator.prototype.validateLaunchPath = function (manifest) {
try {
req.open("HEAD", indexURL, true);
} catch(e) {
this.error(strings.formatStringFromName("validator.invalidLaunchPath", [indexURL], 1));
this.error(strings.formatStringFromName("validator.accessFailedLaunchPath", [indexURL], 1));
deferred.resolve();
return deferred.promise;
}
req.channel.loadFlags |= Ci.nsIRequest.LOAD_BYPASS_CACHE | Ci.nsIRequest.INHIBIT_CACHING;
req.onload = () => {
if (req.status >= 400)
this.error(strings.formatStringFromName("validator.invalidLaunchPathBadHttpCode", [indexURL, req.status], 2));
this.error(strings.formatStringFromName("validator.accessFailedLaunchPathBadHttpCode", [indexURL, req.status], 2));
deferred.resolve();
};
req.onerror = () => {
this.error(strings.formatStringFromName("validator.invalidLaunchPath", [indexURL], 1));
this.error(strings.formatStringFromName("validator.accessFailedLaunchPath", [indexURL], 1));
deferred.resolve();
};
try {
req.send(null);
} catch(e) {
this.error(strings.formatStringFromName("validator.invalidLaunchPath", [indexURL], 1));
this.error(strings.formatStringFromName("validator.accessFailedLaunchPath", [indexURL], 1));
deferred.resolve();
}

View File

@ -99,7 +99,7 @@
let validator = createHosted("wrong-launch-path");
validator.validate().then(() => {
is(validator.errors.length, 1, "app with non-existant launch path got an error");
is(validator.errors[0], strings.formatStringFromName("validator.invalidLaunchPathBadHttpCode", [origin + "wrong-path.html", 404], 2),
is(validator.errors[0], strings.formatStringFromName("validator.accessFailedLaunchPathBadHttpCode", [origin + "wrong-path.html", 404], 2),
"with the right error message");
is(validator.warnings.length, 0, "but no warning");
next();
@ -112,7 +112,7 @@
let file = nsFile(validator.project.location);
file.append("wrong-path.html");
let url = Services.io.newFileURI(file);
is(validator.errors[0], strings.formatStringFromName("validator.invalidLaunchPath", [url.spec], 1),
is(validator.errors[0], strings.formatStringFromName("validator.accessFailedLaunchPath", [url.spec], 1),
"with the expected message");
is(validator.warnings.length, 0, "but no warning");

View File

@ -358,6 +358,9 @@ InspectorPanel.prototype = {
this._initMarkup();
this.once("markuploaded", () => {
if (this._destroyPromise) {
return;
}
this.markup.expandNode(this.selection.nodeFront);
this.setupSearchBox();
this.emit("new-root");

View File

@ -14,6 +14,7 @@ const COLLAPSE_ATTRIBUTE_LENGTH = 120;
const COLLAPSE_DATA_URL_REGEX = /^data.+base64/;
const COLLAPSE_DATA_URL_LENGTH = 60;
const CONTAINER_FLASHING_DURATION = 500;
const IMAGE_PREVIEW_MAX_DIM = 400;
const {UndoStack} = require("devtools/shared/undo");
const {editableField, InplaceEditor} = require("devtools/shared/inplace-editor");
@ -99,6 +100,10 @@ function MarkupView(aInspector, aFrame, aControllerWindow) {
gDevTools.on("pref-changed", this._handlePrefChange);
this._initPreview();
this.tooltip = new Tooltip(this._inspector.panelDoc);
this.tooltip.startTogglingOnHover(this._elt,
this._buildTooltipContent.bind(this));
}
exports.MarkupView = MarkupView;
@ -148,6 +153,25 @@ MarkupView.prototype = {
updateChildren(documentElement);
},
_buildTooltipContent: function(target) {
// From the target passed here, let's find the parent MarkupContainer
// and ask it if the tooltip should be shown
let parent = target, container;
while (parent !== this.doc.body) {
if (parent.container) {
container = parent.container;
break;
}
parent = parent.parentNode;
}
if (container) {
// With the newly found container, delegate the tooltip content creation
// and decision to show or not the tooltip
return container._buildTooltipContent(target, this.tooltip);
}
},
/**
* Highlight the inspector selected node.
*/
@ -954,6 +978,9 @@ MarkupView.prototype = {
container.destroy();
}
delete this._containers;
this.tooltip.destroy();
delete this.tooltip;
},
/**
@ -1099,8 +1126,8 @@ function MarkupContainer(aMarkupView, aNode, aInspector) {
this._onMouseDown = this._onMouseDown.bind(this);
this.elt.addEventListener("mousedown", this._onMouseDown, false);
this.tooltip = null;
this._attachTooltipIfNeeded();
// Prepare the image preview tooltip data if any
this._prepareImagePreview();
}
MarkupContainer.prototype = {
@ -1108,36 +1135,43 @@ MarkupContainer.prototype = {
return "[MarkupContainer for " + this.node + "]";
},
_attachTooltipIfNeeded: function() {
_prepareImagePreview: function() {
if (this.node.tagName) {
let tagName = this.node.tagName.toLowerCase();
let isImage = tagName === "img" &&
this.editor.getAttributeElement("src");
let isCanvas = tagName && tagName === "canvas";
let srcAttr = this.editor.getAttributeElement("src");
let isImage = tagName === "img" && srcAttr;
let isCanvas = tagName === "canvas";
// Get the image data for later so that when the user actually hovers over
// the element, the tooltip does contain the image
if (isImage || isCanvas) {
this.tooltip = new Tooltip(this._inspector.panelDoc);
let def = promise.defer();
this.node.getImageData().then(data => {
this.tooltipData = {
target: isImage ? srcAttr : this.editor.tag,
data: def.promise
};
this.node.getImageData(IMAGE_PREVIEW_MAX_DIM).then(data => {
if (data) {
data.string().then(str => {
this.tooltip.setImageContent(str);
data.data.string().then(str => {
// Resolving the data promise and, to always keep tooltipData.data
// as a promise, create a new one that resolves immediately
def.resolve(str, data.size);
this.tooltipData.data = promise.resolve(str, data.size);
});
}
});
}
}
},
// If it's an image, show the tooltip on the src attribute
if (isImage) {
this.tooltip.startTogglingOnHover(this.editor.getAttributeElement("src"));
}
// If it's a canvas, show it on the tag
if (isCanvas) {
this.tooltip.startTogglingOnHover(this.editor.tag);
}
_buildTooltipContent: function(target, tooltip) {
if (this.tooltipData && target === this.tooltipData.target) {
this.tooltipData.data.then((data, size) => {
tooltip.setImageContent(data, size);
});
return true;
}
},
@ -1375,12 +1409,6 @@ MarkupContainer.prototype = {
// Destroy my editor
this.editor.destroy();
// Destroy the tooltip if any
if (this.tooltip) {
this.tooltip.destroy();
this.tooltip = null;
}
}
};

View File

@ -88,14 +88,14 @@ function testImageTooltip(index) {
target = container.editor.getAttributeElement("src");
}
assertTooltipShownOn(container.tooltip, target, () => {
let images = container.tooltip.panel.getElementsByTagName("image");
assertTooltipShownOn(target, () => {
let images = markup.tooltip.panel.getElementsByTagName("image");
is(images.length, 1, "Tooltip for [" + TEST_NODES[index] + "] contains an image");
if (isImg) {
compareImageData(node, images[0].src);
}
container.tooltip.hide();
markup.tooltip.hide();
testImageTooltip(index + 1);
});
@ -115,17 +115,17 @@ function compareImageData(img, imgData) {
is(data, imgData, "Tooltip image has the right content");
}
function assertTooltipShownOn(tooltip, element, cb) {
function assertTooltipShownOn(element, cb) {
// If there is indeed a show-on-hover on element, the xul panel will be shown
tooltip.panel.addEventListener("popupshown", function shown() {
tooltip.panel.removeEventListener("popupshown", shown, true);
markup.tooltip.panel.addEventListener("popupshown", function shown() {
markup.tooltip.panel.removeEventListener("popupshown", shown, true);
// Poll until the image gets loaded in the tooltip. This is required because
// markup containers only load images in their associated tooltips when
// the image data comes back from the server. However, this test is executed
// synchronously as soon as "inspector-updated" is fired, which is before
// the data for images is known.
let hasImage = () => tooltip.panel.getElementsByTagName("image").length;
let hasImage = () => markup.tooltip.panel.getElementsByTagName("image").length;
let poll = setInterval(() => {
if (hasImage()) {
clearInterval(poll);
@ -133,5 +133,5 @@ function assertTooltipShownOn(tooltip, element, cb) {
}
}, 200);
}, true);
tooltip._showOnHover(element);
markup.tooltip._showOnHover(element);
}

View File

@ -159,7 +159,7 @@ var Scratchpad = {
{
this._dirty = aValue;
if (!aValue && this.editor)
this.editor.markClean();
this.editor.setClean();
this._updateTitle();
},

View File

@ -15,6 +15,7 @@ Cu.import("resource:///modules/devtools/ViewHelpers.jsm");
const require = Cu.import("resource://gre/modules/devtools/Loader.jsm", {}).devtools.require;
const promise = require("sdk/core/promise");
const EventEmitter = require("devtools/shared/event-emitter");
const {Tooltip} = require("devtools/shared/widgets/Tooltip");
const Editor = require("devtools/sourceeditor/editor");
// The panel's window global is an EventEmitter firing the following events:
@ -31,12 +32,14 @@ const EVENTS = {
};
const STRINGS_URI = "chrome://browser/locale/devtools/shadereditor.properties"
const HIGHLIGHT_COLOR = [1, 0, 0, 1];
const BLACKBOX_COLOR = [0, 0, 0, 0];
const TYPING_MAX_DELAY = 500;
const HIGHLIGHT_COLOR = [1, 0, 0, 1]; // rgba
const TYPING_MAX_DELAY = 500; // ms
const SHADERS_AUTOGROW_ITEMS = 4;
const GUTTER_ERROR_PANEL_OFFSET_X = 7; // px
const GUTTER_ERROR_PANEL_DELAY = 100; // ms
const DEFAULT_EDITOR_CONFIG = {
mode: Editor.modes.text,
gutters: ["errors"],
lineNumbers: true,
showAnnotationRuler: true
};
@ -174,25 +177,25 @@ let ShadersListView = Heritage.extend(WidgetMethods, {
showItemCheckboxes: true
});
this._onShaderSelect = this._onShaderSelect.bind(this);
this._onShaderCheck = this._onShaderCheck.bind(this);
this._onShaderMouseEnter = this._onShaderMouseEnter.bind(this);
this._onShaderMouseLeave = this._onShaderMouseLeave.bind(this);
this._onProgramSelect = this._onProgramSelect.bind(this);
this._onProgramCheck = this._onProgramCheck.bind(this);
this._onProgramMouseEnter = this._onProgramMouseEnter.bind(this);
this._onProgramMouseLeave = this._onProgramMouseLeave.bind(this);
this.widget.addEventListener("select", this._onShaderSelect, false);
this.widget.addEventListener("check", this._onShaderCheck, false);
this.widget.addEventListener("mouseenter", this._onShaderMouseEnter, true);
this.widget.addEventListener("mouseleave", this._onShaderMouseLeave, true);
this.widget.addEventListener("select", this._onProgramSelect, false);
this.widget.addEventListener("check", this._onProgramCheck, false);
this.widget.addEventListener("mouseenter", this._onProgramMouseEnter, true);
this.widget.addEventListener("mouseleave", this._onProgramMouseLeave, true);
},
/**
* Destruction function, called when the tool is closed.
*/
destroy: function() {
this.widget.removeEventListener("select", this._onShaderSelect, false);
this.widget.removeEventListener("check", this._onShaderCheck, false);
this.widget.removeEventListener("mouseenter", this._onShaderMouseEnter, true);
this.widget.removeEventListener("mouseleave", this._onShaderMouseLeave, true);
this.widget.removeEventListener("select", this._onProgramSelect, false);
this.widget.removeEventListener("check", this._onProgramCheck, false);
this.widget.removeEventListener("mouseenter", this._onProgramMouseEnter, true);
this.widget.removeEventListener("mouseleave", this._onProgramMouseLeave, true);
},
/**
@ -248,9 +251,9 @@ let ShadersListView = Heritage.extend(WidgetMethods, {
},
/**
* The select listener for the sources container.
* The select listener for the programs container.
*/
_onShaderSelect: function({ detail: sourceItem }) {
_onProgramSelect: function({ detail: sourceItem }) {
if (!sourceItem) {
return;
}
@ -280,19 +283,19 @@ let ShadersListView = Heritage.extend(WidgetMethods, {
},
/**
* The check listener for the sources container.
* The check listener for the programs container.
*/
_onShaderCheck: function({ detail: { checked }, target }) {
_onProgramCheck: function({ detail: { checked }, target }) {
let sourceItem = this.getItemForElement(target);
let attachment = sourceItem.attachment;
attachment.isBlackBoxed = !checked;
attachment.programActor[checked ? "unhighlight" : "highlight"](BLACKBOX_COLOR);
attachment.programActor[checked ? "unblackbox" : "blackbox"]();
},
/**
* The mouseenter listener for the sources container.
* The mouseenter listener for the programs container.
*/
_onShaderMouseEnter: function(e) {
_onProgramMouseEnter: function(e) {
let sourceItem = this.getItemForElement(e.target, { noSiblings: true });
if (sourceItem && !sourceItem.attachment.isBlackBoxed) {
sourceItem.attachment.programActor.highlight(HIGHLIGHT_COLOR);
@ -305,9 +308,9 @@ let ShadersListView = Heritage.extend(WidgetMethods, {
},
/**
* The mouseleave listener for the sources container.
* The mouseleave listener for the programs container.
*/
_onShaderMouseLeave: function(e) {
_onProgramMouseLeave: function(e) {
let sourceItem = this.getItemForElement(e.target, { noSiblings: true });
if (sourceItem && !sourceItem.attachment.isBlackBoxed) {
sourceItem.attachment.programActor.unhighlight();
@ -427,6 +430,9 @@ let ShadersEditorsView = {
*/
_onChanged: function(type) {
setNamedTimeout("gl-typed", TYPING_MAX_DELAY, () => this._doCompile(type));
// Remove all the gutter markers and line classes from the editor.
this._cleanEditor(type);
},
/**
@ -443,13 +449,117 @@ let ShadersEditorsView = {
try {
yield shaderActor.compile(editor.getText());
window.emit(EVENTS.SHADER_COMPILED, null);
// TODO: remove error gutter markers, after bug 919709 lands.
} catch (error) {
window.emit(EVENTS.SHADER_COMPILED, error);
// TODO: add error gutter markers, after bug 919709 lands.
this._onSuccessfulCompilation();
} catch (e) {
this._onFailedCompilation(type, editor, e);
}
}.bind(this));
},
/**
* Called uppon a successful shader compilation.
*/
_onSuccessfulCompilation: function() {
// Signal that the shader was compiled successfully.
window.emit(EVENTS.SHADER_COMPILED, null);
},
/**
* Called uppon an unsuccessful shader compilation.
*/
_onFailedCompilation: function(type, editor, errors) {
let lineCount = editor.lineCount();
let currentLine = editor.getCursor().line;
let listeners = { mouseenter: this._onMarkerMouseEnter };
function matchLinesAndMessages(string) {
return {
// First number that is not equal to 0.
lineMatch: string.match(/\d{2,}|[1-9]/),
// The string after all the numbers, semicolons and spaces.
textMatch: string.match(/[^\s\d:][^\r\n|]*/)
};
}
function discardInvalidMatches(e) {
// Discard empty line and text matches.
return e.lineMatch && e.textMatch;
}
function sanitizeValidMatches(e) {
return {
// Drivers might yield retarded line numbers under some obscure
// circumstances. Don't throw the errors away in those cases,
// just display them on the currently edited line.
line: e.lineMatch[0] > lineCount ? currentLine : e.lineMatch[0] - 1,
// Trim whitespace from the beginning and the end of the message,
// and replace all other occurences of double spaces to a single space.
text: e.textMatch[0].trim().replace(/\s{2,}/g, " ")
};
}
function sortByLine(first, second) {
// Sort all the errors ascending by their corresponding line number.
return first.line > second.line ? 1 : -1;
}
function groupSameLineMessages(accumulator, current) {
// Group errors corresponding to the same line number to a single object.
let previous = accumulator[accumulator.length - 1];
if (!previous || previous.line != current.line) {
return [...accumulator, {
line: current.line,
messages: [current.text]
}];
} else {
previous.messages.push(current.text);
return accumulator;
}
}
function displayErrors({ line, messages }) {
// Add gutter markers and line classes for every error in the source.
editor.addMarker(line, "errors", "error");
editor.setMarkerListeners(line, "errors", "error", listeners, messages);
editor.addLineClass(line, "error-line");
}
(this._errors[type] = errors.link
.split("ERROR")
.map(matchLinesAndMessages)
.filter(discardInvalidMatches)
.map(sanitizeValidMatches)
.sort(sortByLine)
.reduce(groupSameLineMessages, []))
.forEach(displayErrors);
// Signal that the shader wasn't compiled successfully.
window.emit(EVENTS.SHADER_COMPILED, errors);
},
/**
* Event listener for the 'mouseenter' event on a marker in the editor gutter.
*/
_onMarkerMouseEnter: function(line, node, messages) {
if (node._markerErrorsTooltip) {
return;
}
let tooltip = node._markerErrorsTooltip = new Tooltip(document);
tooltip.defaultOffsetX = GUTTER_ERROR_PANEL_OFFSET_X;
tooltip.setTextContent.apply(tooltip, messages);
tooltip.startTogglingOnHover(node, () => true, GUTTER_ERROR_PANEL_DELAY);
},
/**
* Removes all the gutter markers and line classes from the editor.
*/
_cleanEditor: function(type) {
this._getEditor(type).then(editor => {
editor.removeAllMarkers("errors");
this._errors[type].forEach(e => editor.removeLineClass(e.line));
this._errors[type].length = 0;
});
},
_errors: {
vs: [],
fs: []
}
};

View File

@ -1,6 +1,7 @@
[DEFAULT]
support-files =
doc_multiple-contexts.html
doc_overlapping-geometry.html
doc_shader-order.html
doc_simple-canvas.html
head.js
@ -8,6 +9,8 @@ support-files =
[browser_se_aaa_run_first_leaktest.js]
[browser_se_bfcache.js]
[browser_se_editors-contents.js]
[browser_se_editors-error-gutter.js]
[browser_se_editors-error-tooltip.js]
[browser_se_editors-lazy-init.js]
[browser_se_first-run.js]
[browser_se_navigation.js]
@ -34,3 +37,4 @@ support-files =
[browser_webgl-actor-test-14.js]
[browser_webgl-actor-test-15.js]
[browser_webgl-actor-test-16.js]
[browser_webgl-actor-test-17.js]

View File

@ -0,0 +1,156 @@
/* Any copyright is dedicated to the Public Domain.
http://creativecommons.org/publicdomain/zero/1.0/ */
/**
* Tests if error indicators are shown in the editor's gutter and text area
* when there's a shader compilation error.
*/
function ifWebGLSupported() {
let [target, debuggee, panel] = yield initShaderEditor(SIMPLE_CANVAS_URL);
let { gFront, EVENTS, ShadersEditorsView } = panel.panelWin;
reload(target);
yield once(gFront, "program-linked");
let vsEditor = yield ShadersEditorsView._getEditor("vs");
let fsEditor = yield ShadersEditorsView._getEditor("fs");
vsEditor.replaceText("vec3", { line: 7, ch: 22 }, { line: 7, ch: 26 });
let vertError = yield once(panel.panelWin, EVENTS.SHADER_COMPILED);
checkHasVertFirstError(true, vertError);
checkHasVertSecondError(false, vertError);
info("Error marks added in the vertex shader editor.");
vsEditor.insertText(" ", { line: 1, ch: 0 });
is(vsEditor.getText(1), " precision lowp float;", "Typed space.");
checkHasVertFirstError(false, vertError);
checkHasVertSecondError(false, vertError);
info("Error marks removed while typing in the vertex shader editor.");
let vertError = yield once(panel.panelWin, EVENTS.SHADER_COMPILED);
checkHasVertFirstError(true, vertError);
checkHasVertSecondError(false, vertError);
info("Error marks were re-added after recompiling the vertex shader.");
fsEditor.replaceText("vec4", { line: 2, ch: 14 }, { line: 2, ch: 18 });
let fragError = yield once(panel.panelWin, EVENTS.SHADER_COMPILED);
checkHasVertFirstError(true, vertError);
checkHasVertSecondError(false, vertError);
checkHasFragError(true, fragError);
info("Error marks added in the fragment shader editor.");
fsEditor.insertText(" ", { line: 1, ch: 0 });
is(fsEditor.getText(1), " precision lowp float;", "Typed space.");
checkHasVertFirstError(true, vertError);
checkHasVertSecondError(false, vertError);
checkHasFragError(false, fragError);
info("Error marks removed while typing in the fragment shader editor.");
let fragError = yield once(panel.panelWin, EVENTS.SHADER_COMPILED);
checkHasVertFirstError(true, vertError);
checkHasVertSecondError(false, vertError);
checkHasFragError(true, fragError);
info("Error marks were re-added after recompiling the fragment shader.");
vsEditor.replaceText("2", { line: 3, ch: 19 }, { line: 3, ch: 20 });
checkHasVertFirstError(false, vertError);
checkHasVertSecondError(false, vertError);
checkHasFragError(true, fragError);
info("Error marks removed while typing in the vertex shader editor again.");
let vertError = yield once(panel.panelWin, EVENTS.SHADER_COMPILED);
checkHasVertFirstError(true, vertError);
checkHasVertSecondError(true, vertError);
checkHasFragError(true, fragError);
info("Error marks were re-added after recompiling the fragment shader again.");
yield teardown(panel);
finish();
function checkHasVertFirstError(bool, error) {
ok(error, "Vertex shader compiled with errors.");
isnot(error.link, "", "The linkage status should not be empty.");
let line = 7;
info("Checking first vertex shader error on line " + line + "...");
is(vsEditor.hasMarker(line, "errors", "error"), bool,
"Error is " + (bool ? "" : "not ") + "shown in the editor's gutter.");
is(vsEditor.hasLineClass(line, "error-line"), bool,
"Error style is " + (bool ? "" : "not ") + "applied to the faulty line.");
let parsed = ShadersEditorsView._errors.vs;
is(parsed.length >= 1, bool,
"There's " + (bool ? ">= 1" : "< 1") + " parsed vertex shader error(s).");
if (bool) {
is(parsed[0].line, line,
"The correct line was parsed.");
is(parsed[0].messages.length, 2,
"There are 2 parsed messages.");
ok(parsed[0].messages[0].contains("'constructor' : too many arguments"),
"The correct first message was parsed.");
ok(parsed[0].messages[1].contains("'assign' : cannot convert from"),
"The correct second message was parsed.");
}
}
function checkHasVertSecondError(bool, error) {
ok(error, "Vertex shader compiled with errors.");
isnot(error.link, "", "The linkage status should not be empty.");
let line = 8;
info("Checking second vertex shader error on line " + line + "...");
is(vsEditor.hasMarker(line, "errors", "error"), bool,
"Error is " + (bool ? "" : "not ") + "shown in the editor's gutter.");
is(vsEditor.hasLineClass(line, "error-line"), bool,
"Error style is " + (bool ? "" : "not ") + "applied to the faulty line.");
let parsed = ShadersEditorsView._errors.vs;
is(parsed.length >= 2, bool,
"There's " + (bool ? ">= 2" : "< 2") + " parsed vertex shader error(s).");
if (bool) {
is(parsed[1].line, line,
"The correct line was parsed.");
is(parsed[1].messages.length, 1,
"There is 1 parsed message.");
ok(parsed[1].messages[0].contains("'assign' : cannot convert from"),
"The correct message was parsed.");
}
}
function checkHasFragError(bool, error) {
ok(error, "Fragment shader compiled with errors.");
isnot(error.link, "", "The linkage status should not be empty.");
let line = 5;
info("Checking first vertex shader error on line " + line + "...");
is(fsEditor.hasMarker(line, "errors", "error"), bool,
"Error is " + (bool ? "" : "not ") + "shown in the editor's gutter.");
is(fsEditor.hasLineClass(line, "error-line"), bool,
"Error style is " + (bool ? "" : "not ") + "applied to the faulty line.");
let parsed = ShadersEditorsView._errors.fs;
is(parsed.length >= 1, bool,
"There's " + (bool ? ">= 2" : "< 1") + " parsed fragment shader error(s).");
if (bool) {
is(parsed[0].line, line,
"The correct line was parsed.");
is(parsed[0].messages.length, 1,
"There is 1 parsed message.");
ok(parsed[0].messages[0].contains("'constructor' : too many arguments"),
"The correct message was parsed.");
}
}
}
function once(aTarget, aEvent) {
let deferred = promise.defer();
aTarget.once(aEvent, (aName, aData) => deferred.resolve(aData));
return deferred.promise;
}

View File

@ -0,0 +1,59 @@
/* Any copyright is dedicated to the Public Domain.
http://creativecommons.org/publicdomain/zero/1.0/ */
/**
* Tests if error tooltips can be opened from the editor's gutter when there's
* a shader compilation error.
*/
function ifWebGLSupported() {
let [target, debuggee, panel] = yield initShaderEditor(SIMPLE_CANVAS_URL);
let { gFront, EVENTS, ShadersEditorsView } = panel.panelWin;
reload(target);
yield once(gFront, "program-linked");
let vsEditor = yield ShadersEditorsView._getEditor("vs");
let fsEditor = yield ShadersEditorsView._getEditor("fs");
vsEditor.replaceText("vec3", { line: 7, ch: 22 }, { line: 7, ch: 26 });
yield once(panel.panelWin, EVENTS.SHADER_COMPILED);
// Synthesizing 'mouseenter' events doesn't work, hack around this by
// manually calling the event listener with the expected arguments.
let editorDocument = vsEditor.container.contentDocument;
let marker = editorDocument.querySelector(".error");
let parsed = ShadersEditorsView._errors.vs[0].messages;
ShadersEditorsView._onMarkerMouseEnter(7, marker, parsed);
let tooltip = marker._markerErrorsTooltip;
ok(tooltip, "A tooltip was created successfully.");
let content = tooltip.content;
ok(tooltip.content,
"Some tooltip's content was set.");
is(tooltip.content.className, "devtools-tooltip-simple-text-container",
"The tooltip's content container was created correctly.");
let messages = content.childNodes;
is(messages.length, 2,
"There are two messages displayed in the tooltip.");
is(messages[0].className, "devtools-tooltip-simple-text",
"The first message was created correctly.");
is(messages[1].className, "devtools-tooltip-simple-text",
"The second message was created correctly.");
ok(messages[0].textContent.contains("'constructor' : too many arguments"),
"The first message contains the correct text.");
ok(messages[1].textContent.contains("'assign' : cannot convert"),
"The second message contains the correct text.");
yield teardown(panel);
finish();
}
function once(aTarget, aEvent) {
let deferred = promise.defer();
aTarget.once(aEvent, (aName, aData) => deferred.resolve(aData));
return deferred.promise;
}

View File

@ -55,9 +55,9 @@ function ifWebGLSupported() {
is(getBlackBoxCheckbox(panel, 1).checked, true,
"The second blackbox checkbox should still be checked.");
yield ensurePixelIs(debuggee, { x: 0, y: 0 }, { r: 0, g: 0, b: 0, a: 0 }, true, "#canvas1");
yield ensurePixelIs(debuggee, { x: 0, y: 0 }, { r: 0, g: 0, b: 0, a: 255 }, true, "#canvas1");
yield ensurePixelIs(debuggee, { x: 0, y: 0 }, { r: 0, g: 255, b: 255, a: 255 }, true, "#canvas2");
yield ensurePixelIs(debuggee, { x: 127, y: 127 }, { r: 0, g: 0, b: 0, a: 0 }, true, "#canvas1");
yield ensurePixelIs(debuggee, { x: 127, y: 127 }, { r: 0, g: 0, b: 0, a: 255 }, true, "#canvas1");
yield ensurePixelIs(debuggee, { x: 127, y: 127 }, { r: 0, g: 255, b: 255, a: 255 }, true, "#canvas2");
ok(true, "The first program was correctly blackboxed.");
@ -72,35 +72,35 @@ function ifWebGLSupported() {
is(getBlackBoxCheckbox(panel, 1).checked, false,
"The second blackbox checkbox should now be unchecked.");
yield ensurePixelIs(debuggee, { x: 0, y: 0 }, { r: 0, g: 0, b: 0, a: 0 }, true, "#canvas1");
yield ensurePixelIs(debuggee, { x: 0, y: 0 }, { r: 0, g: 0, b: 0, a: 0 }, true, "#canvas2");
yield ensurePixelIs(debuggee, { x: 127, y: 127 }, { r: 0, g: 0, b: 0, a: 0 }, true, "#canvas1");
yield ensurePixelIs(debuggee, { x: 127, y: 127 }, { r: 0, g: 0, b: 0, a: 0 }, true, "#canvas2");
yield ensurePixelIs(debuggee, { x: 0, y: 0 }, { r: 0, g: 0, b: 0, a: 255 }, true, "#canvas1");
yield ensurePixelIs(debuggee, { x: 0, y: 0 }, { r: 0, g: 0, b: 0, a: 255 }, true, "#canvas2");
yield ensurePixelIs(debuggee, { x: 127, y: 127 }, { r: 0, g: 0, b: 0, a: 255 }, true, "#canvas1");
yield ensurePixelIs(debuggee, { x: 127, y: 127 }, { r: 0, g: 0, b: 0, a: 255 }, true, "#canvas2");
ok(true, "The second program was correctly blackboxed.");
ShadersListView._onShaderMouseEnter({ target: getItemLabel(panel, 0) });
ShadersListView._onProgramMouseEnter({ target: getItemLabel(panel, 0) });
yield ensurePixelIs(debuggee, { x: 0, y: 0 }, { r: 0, g: 0, b: 0, a: 0 }, true, "#canvas1");
yield ensurePixelIs(debuggee, { x: 0, y: 0 }, { r: 0, g: 0, b: 0, a: 0 }, true, "#canvas2");
yield ensurePixelIs(debuggee, { x: 127, y: 127 }, { r: 0, g: 0, b: 0, a: 0 }, true, "#canvas1");
yield ensurePixelIs(debuggee, { x: 127, y: 127 }, { r: 0, g: 0, b: 0, a: 0 }, true, "#canvas2");
yield ensurePixelIs(debuggee, { x: 0, y: 0 }, { r: 0, g: 0, b: 0, a: 255 }, true, "#canvas1");
yield ensurePixelIs(debuggee, { x: 0, y: 0 }, { r: 0, g: 0, b: 0, a: 255 }, true, "#canvas2");
yield ensurePixelIs(debuggee, { x: 127, y: 127 }, { r: 0, g: 0, b: 0, a: 255 }, true, "#canvas1");
yield ensurePixelIs(debuggee, { x: 127, y: 127 }, { r: 0, g: 0, b: 0, a: 255 }, true, "#canvas2");
ok(true, "Highlighting didn't work while blackboxed (1).");
ShadersListView._onShaderMouseLeave({ target: getItemLabel(panel, 0) });
ShadersListView._onShaderMouseEnter({ target: getItemLabel(panel, 1) });
ShadersListView._onProgramMouseLeave({ target: getItemLabel(panel, 0) });
ShadersListView._onProgramMouseEnter({ target: getItemLabel(panel, 1) });
yield ensurePixelIs(debuggee, { x: 0, y: 0 }, { r: 0, g: 0, b: 0, a: 0 }, true, "#canvas1");
yield ensurePixelIs(debuggee, { x: 0, y: 0 }, { r: 0, g: 0, b: 0, a: 0 }, true, "#canvas2");
yield ensurePixelIs(debuggee, { x: 127, y: 127 }, { r: 0, g: 0, b: 0, a: 0 }, true, "#canvas1");
yield ensurePixelIs(debuggee, { x: 127, y: 127 }, { r: 0, g: 0, b: 0, a: 0 }, true, "#canvas2");
yield ensurePixelIs(debuggee, { x: 0, y: 0 }, { r: 0, g: 0, b: 0, a: 255 }, true, "#canvas1");
yield ensurePixelIs(debuggee, { x: 0, y: 0 }, { r: 0, g: 0, b: 0, a: 255 }, true, "#canvas2");
yield ensurePixelIs(debuggee, { x: 127, y: 127 }, { r: 0, g: 0, b: 0, a: 255 }, true, "#canvas1");
yield ensurePixelIs(debuggee, { x: 127, y: 127 }, { r: 0, g: 0, b: 0, a: 255 }, true, "#canvas2");
ok(true, "Highlighting didn't work while blackboxed (2).");
ShadersListView._onShaderMouseLeave({ target: getItemLabel(panel, 1) });
ShadersListView._onProgramMouseLeave({ target: getItemLabel(panel, 1) });
yield ensurePixelIs(debuggee, { x: 0, y: 0 }, { r: 0, g: 0, b: 0, a: 0 }, true, "#canvas1");
yield ensurePixelIs(debuggee, { x: 0, y: 0 }, { r: 0, g: 0, b: 0, a: 0 }, true, "#canvas2");
yield ensurePixelIs(debuggee, { x: 127, y: 127 }, { r: 0, g: 0, b: 0, a: 0 }, true, "#canvas1");
yield ensurePixelIs(debuggee, { x: 127, y: 127 }, { r: 0, g: 0, b: 0, a: 0 }, true, "#canvas2");
yield ensurePixelIs(debuggee, { x: 0, y: 0 }, { r: 0, g: 0, b: 0, a: 255 }, true, "#canvas1");
yield ensurePixelIs(debuggee, { x: 0, y: 0 }, { r: 0, g: 0, b: 0, a: 255 }, true, "#canvas2");
yield ensurePixelIs(debuggee, { x: 127, y: 127 }, { r: 0, g: 0, b: 0, a: 255 }, true, "#canvas1");
yield ensurePixelIs(debuggee, { x: 127, y: 127 }, { r: 0, g: 0, b: 0, a: 255 }, true, "#canvas2");
ok(true, "Highlighting didn't work while blackboxed (3).");
getBlackBoxCheckbox(panel, 0).click();
@ -121,7 +121,7 @@ function ifWebGLSupported() {
yield ensurePixelIs(debuggee, { x: 127, y: 127 }, { r: 0, g: 255, b: 255, a: 255 }, true, "#canvas2");
ok(true, "The two programs were correctly unblackboxed.");
ShadersListView._onShaderMouseEnter({ target: getItemLabel(panel, 0) });
ShadersListView._onProgramMouseEnter({ target: getItemLabel(panel, 0) });
yield ensurePixelIs(debuggee, { x: 0, y: 0 }, { r: 255, g: 0, b: 0, a: 255 }, true, "#canvas1");
yield ensurePixelIs(debuggee, { x: 0, y: 0 }, { r: 0, g: 255, b: 255, a: 255 }, true, "#canvas2");
@ -129,8 +129,8 @@ function ifWebGLSupported() {
yield ensurePixelIs(debuggee, { x: 127, y: 127 }, { r: 0, g: 255, b: 255, a: 255 }, true, "#canvas2");
ok(true, "The first program was correctly highlighted.");
ShadersListView._onShaderMouseLeave({ target: getItemLabel(panel, 0) });
ShadersListView._onShaderMouseEnter({ target: getItemLabel(panel, 1) });
ShadersListView._onProgramMouseLeave({ target: getItemLabel(panel, 0) });
ShadersListView._onProgramMouseEnter({ target: getItemLabel(panel, 1) });
yield ensurePixelIs(debuggee, { x: 0, y: 0 }, { r: 255, g: 255, b: 0, a: 255 }, true, "#canvas1");
yield ensurePixelIs(debuggee, { x: 0, y: 0 }, { r: 255, g: 0, b: 0, a: 255 }, true, "#canvas2");
@ -138,7 +138,7 @@ function ifWebGLSupported() {
yield ensurePixelIs(debuggee, { x: 127, y: 127 }, { r: 255, g: 0, b: 0, a: 255 }, true, "#canvas2");
ok(true, "The second program was correctly highlighted.");
ShadersListView._onShaderMouseLeave({ target: getItemLabel(panel, 1) });
ShadersListView._onProgramMouseLeave({ target: getItemLabel(panel, 1) });
yield ensurePixelIs(debuggee, { x: 0, y: 0 }, { r: 255, g: 255, b: 0, a: 255 }, true, "#canvas1");
yield ensurePixelIs(debuggee, { x: 0, y: 0 }, { r: 0, g: 255, b: 255, a: 255 }, true, "#canvas2");

View File

@ -35,7 +35,7 @@ function ifWebGLSupported() {
yield ensurePixelIs(debuggee, { x: 127, y: 127 }, { r: 255, g: 255, b: 0, a: 255 }, true, "#canvas1");
yield ensurePixelIs(debuggee, { x: 127, y: 127 }, { r: 0, g: 255, b: 255, a: 255 }, true, "#canvas2");
ShadersListView._onShaderMouseEnter({ target: getItemLabel(panel, 0) });
ShadersListView._onProgramMouseEnter({ target: getItemLabel(panel, 0) });
yield ensurePixelIs(debuggee, { x: 0, y: 0 }, { r: 255, g: 0, b: 0, a: 255 }, true, "#canvas1");
yield ensurePixelIs(debuggee, { x: 0, y: 0 }, { r: 0, g: 255, b: 255, a: 255 }, true, "#canvas2");
@ -43,8 +43,8 @@ function ifWebGLSupported() {
yield ensurePixelIs(debuggee, { x: 127, y: 127 }, { r: 0, g: 255, b: 255, a: 255 }, true, "#canvas2");
ok(true, "The first program was correctly highlighted.");
ShadersListView._onShaderMouseLeave({ target: getItemLabel(panel, 0) });
ShadersListView._onShaderMouseEnter({ target: getItemLabel(panel, 1) });
ShadersListView._onProgramMouseLeave({ target: getItemLabel(panel, 0) });
ShadersListView._onProgramMouseEnter({ target: getItemLabel(panel, 1) });
yield ensurePixelIs(debuggee, { x: 0, y: 0 }, { r: 255, g: 255, b: 0, a: 255 }, true, "#canvas1");
yield ensurePixelIs(debuggee, { x: 0, y: 0 }, { r: 255, g: 0, b: 0, a: 255 }, true, "#canvas2");
@ -52,7 +52,7 @@ function ifWebGLSupported() {
yield ensurePixelIs(debuggee, { x: 127, y: 127 }, { r: 255, g: 0, b: 0, a: 255 }, true, "#canvas2");
ok(true, "The second program was correctly highlighted.");
ShadersListView._onShaderMouseLeave({ target: getItemLabel(panel, 1) });
ShadersListView._onProgramMouseLeave({ target: getItemLabel(panel, 1) });
yield ensurePixelIs(debuggee, { x: 0, y: 0 }, { r: 255, g: 255, b: 0, a: 255 }, true, "#canvas1");
yield ensurePixelIs(debuggee, { x: 0, y: 0 }, { r: 0, g: 255, b: 255, a: 255 }, true, "#canvas2");
@ -60,7 +60,7 @@ function ifWebGLSupported() {
yield ensurePixelIs(debuggee, { x: 127, y: 127 }, { r: 0, g: 255, b: 255, a: 255 }, true, "#canvas2");
ok(true, "The two programs were correctly unhighlighted.");
ShadersListView._onShaderMouseEnter({ target: getBlackBoxCheckbox(panel, 0) });
ShadersListView._onProgramMouseEnter({ target: getBlackBoxCheckbox(panel, 0) });
yield ensurePixelIs(debuggee, { x: 0, y: 0 }, { r: 255, g: 255, b: 0, a: 255 }, true, "#canvas1");
yield ensurePixelIs(debuggee, { x: 0, y: 0 }, { r: 0, g: 255, b: 255, a: 255 }, true, "#canvas2");
@ -68,7 +68,7 @@ function ifWebGLSupported() {
yield ensurePixelIs(debuggee, { x: 127, y: 127 }, { r: 0, g: 255, b: 255, a: 255 }, true, "#canvas2");
ok(true, "The two programs were left unchanged after hovering a blackbox checkbox.");
ShadersListView._onShaderMouseLeave({ target: getBlackBoxCheckbox(panel, 0) });
ShadersListView._onProgramMouseLeave({ target: getBlackBoxCheckbox(panel, 0) });
yield ensurePixelIs(debuggee, { x: 0, y: 0 }, { r: 255, g: 255, b: 0, a: 255 }, true, "#canvas1");
yield ensurePixelIs(debuggee, { x: 0, y: 0 }, { r: 0, g: 255, b: 255, a: 255 }, true, "#canvas2");

View File

@ -2,7 +2,8 @@
http://creativecommons.org/publicdomain/zero/1.0/ */
/**
* Tests if editing a vertex and a fragment shader works properly.
* Tests if editing a vertex and a fragment shader would permanently store
* their new source on the backend and reshow it in the frontend when required.
*/
function ifWebGLSupported() {

View File

@ -2,8 +2,8 @@
http://creativecommons.org/publicdomain/zero/1.0/ */
/**
* Tests that the highlight/unhighlight operations on program actors
* work as expected.
* Tests that the highlight/unhighlight and blackbox/unblackbox operations on
* program actors work as expected.
*/
function ifWebGLSupported() {
@ -17,19 +17,31 @@ function ifWebGLSupported() {
yield ensurePixelIs(debuggee, { x: 0, y: 0 }, { r: 255, g: 0, b: 0, a: 255 }, true);
yield ensurePixelIs(debuggee, { x: 511, y: 511 }, { r: 0, g: 255, b: 0, a: 255 }, true);
yield checkShaderSource("The shader sources are correct before highlighting.");
ok(true, "The top left pixel color was correct before highlighting.");
ok(true, "The corner pixel colors are correct before highlighting.");
yield programActor.highlight([0, 0, 1, 1]);
yield ensurePixelIs(debuggee, { x: 0, y: 0 }, { r: 0, g: 0, b: 255, a: 255 }, true);
yield ensurePixelIs(debuggee, { x: 511, y: 511 }, { r: 0, g: 0, b: 255, a: 255 }, true);
yield checkShaderSource("The shader sources are preserved after highlighting.");
ok(true, "The top left pixel color is correct after highlighting.");
ok(true, "The corner pixel colors are correct after highlighting.");
yield programActor.unhighlight();
yield ensurePixelIs(debuggee, { x: 0, y: 0 }, { r: 255, g: 0, b: 0, a: 255 }, true);
yield ensurePixelIs(debuggee, { x: 511, y: 511 }, { r: 0, g: 255, b: 0, a: 255 }, true);
yield checkShaderSource("The shader sources are correct after unhighlighting.");
ok(true, "The top left pixel color is correct after unhighlighting.");
ok(true, "The corner pixel colors are correct after unhighlighting.");
yield programActor.blackbox();
yield ensurePixelIs(debuggee, { x: 0, y: 0 }, { r: 0, g: 0, b: 0, a: 255 }, true);
yield ensurePixelIs(debuggee, { x: 511, y: 511 }, { r: 0, g: 0, b: 0, a: 255 }, true);
yield checkShaderSource("The shader sources are preserved after blackboxing.");
ok(true, "The corner pixel colors are correct after blackboxing.");
yield programActor.unblackbox();
yield ensurePixelIs(debuggee, { x: 0, y: 0 }, { r: 255, g: 0, b: 0, a: 255 }, true);
yield ensurePixelIs(debuggee, { x: 511, y: 511 }, { r: 0, g: 255, b: 0, a: 255 }, true);
yield checkShaderSource("The shader sources are correct after unblackboxing.");
ok(true, "The corner pixel colors are correct after unblackboxing.");
function checkShaderSource(aMessage) {
return Task.spawn(function() {

View File

@ -0,0 +1,47 @@
/* Any copyright is dedicated to the Public Domain.
http://creativecommons.org/publicdomain/zero/1.0/ */
/**
* Tests that the blackbox/unblackbox operations work as expected with
* overlapping geometry.
*/
function ifWebGLSupported() {
let [target, debuggee, front] = yield initBackend(OVERLAPPING_GEOMETRY_CANVAS_URL);
front.setup({ reload: true });
let firstProgramActor = yield once(front, "program-linked");
let secondProgramActor = yield once(front, "program-linked");
yield ensurePixelIs(debuggee, { x: 0, y: 0 }, { r: 255, g: 255, b: 0, a: 255 }, true);
yield ensurePixelIs(debuggee, { x: 64, y: 64 }, { r: 0, g: 255, b: 255, a: 255 }, true);
yield ensurePixelIs(debuggee, { x: 127, y: 127 }, { r: 255, g: 255, b: 0, a: 255 }, true);
ok(true, "The corner vs. center pixel colors are correct before blackboxing.");
yield firstProgramActor.blackbox();
yield ensurePixelIs(debuggee, { x: 0, y: 0 }, { r: 0, g: 0, b: 0, a: 255 }, true);
yield ensurePixelIs(debuggee, { x: 64, y: 64 }, { r: 0, g: 255, b: 255, a: 255 }, true);
yield ensurePixelIs(debuggee, { x: 127, y: 127 }, { r: 0, g: 0, b: 0, a: 255 }, true);
ok(true, "The corner vs. center pixel colors are correct after blackboxing (1).");
yield firstProgramActor.unblackbox();
yield ensurePixelIs(debuggee, { x: 0, y: 0 }, { r: 255, g: 255, b: 0, a: 255 }, true);
yield ensurePixelIs(debuggee, { x: 64, y: 64 }, { r: 0, g: 255, b: 255, a: 255 }, true);
yield ensurePixelIs(debuggee, { x: 127, y: 127 }, { r: 255, g: 255, b: 0, a: 255 }, true);
ok(true, "The corner vs. center pixel colors are correct after unblackboxing (1).");
yield secondProgramActor.blackbox();
yield ensurePixelIs(debuggee, { x: 0, y: 0 }, { r: 255, g: 255, b: 0, a: 255 }, true);
yield ensurePixelIs(debuggee, { x: 64, y: 64 }, { r: 255, g: 255, b: 0, a: 255 }, true);
yield ensurePixelIs(debuggee, { x: 127, y: 127 }, { r: 255, g: 255, b: 0, a: 255 }, true);
ok(true, "The corner vs. center pixel colors are correct after blackboxing (2).");
yield secondProgramActor.unblackbox();
yield ensurePixelIs(debuggee, { x: 0, y: 0 }, { r: 255, g: 255, b: 0, a: 255 }, true);
yield ensurePixelIs(debuggee, { x: 64, y: 64 }, { r: 0, g: 255, b: 255, a: 255 }, true);
yield ensurePixelIs(debuggee, { x: 127, y: 127 }, { r: 255, g: 255, b: 0, a: 255 }, true);
ok(true, "The corner vs. center pixel colors are correct after unblackboxing (2).");
yield removeTab(target.tab);
finish();
}

View File

@ -0,0 +1,120 @@
<!-- Any copyright is dedicated to the Public Domain.
http://creativecommons.org/publicdomain/zero/1.0/ -->
<!doctype html>
<html>
<head>
<meta charset="utf-8"/>
<title>WebGL editor test page</title>
<script id="shader-vs" type="x-shader/x-vertex">
precision lowp float;
attribute vec3 aVertexPosition;
uniform float uDepth;
void main(void) {
gl_Position = vec4(aVertexPosition, uDepth);
}
</script>
<script id="shader-fs-0" type="x-shader/x-fragment">
precision lowp float;
void main(void) {
gl_FragColor = vec4(1.0, 1.0, 0.0, 1.0);
}
</script>
<script id="shader-fs-1" type="x-shader/x-fragment">
precision lowp float;
void main(void) {
gl_FragColor = vec4(0.0, 1.0, 1.0, 1.0);
}
</script>
</head>
<body>
<canvas id="canvas" width="128" height="128"></canvas>
<script type="text/javascript;version=1.8">
"use strict";
let canvas, gl;
let program = [];
let squareVerticesPositionBuffer;
let vertexPositionAttribute = [];
let depthUniform = [];
window.onload = function() {
canvas = document.querySelector("canvas");
gl = canvas.getContext("webgl");
gl.clearColor(0.0, 0.0, 0.0, 1.0);
initProgram(0);
initProgram(1);
initBuffers();
drawScene();
}
function initProgram(i) {
let vertexShader = getShader("shader-vs");
let fragmentShader = getShader("shader-fs-" + i);
program[i] = gl.createProgram();
gl.attachShader(program[i], vertexShader);
gl.attachShader(program[i], fragmentShader);
gl.linkProgram(program[i]);
vertexPositionAttribute[i] = gl.getAttribLocation(program[i], "aVertexPosition");
gl.enableVertexAttribArray(vertexPositionAttribute[i]);
depthUniform[i] = gl.getUniformLocation(program[i], "uDepth");
}
function getShader(id) {
let script = document.getElementById(id);
let source = script.textContent;
let shader;
if (script.type == "x-shader/x-fragment") {
shader = gl.createShader(gl.FRAGMENT_SHADER);
} else if (script.type == "x-shader/x-vertex") {
shader = gl.createShader(gl.VERTEX_SHADER);
}
gl.shaderSource(shader, source);
gl.compileShader(shader);
return shader;
}
function initBuffers() {
squareVerticesPositionBuffer = gl.createBuffer();
gl.bindBuffer(gl.ARRAY_BUFFER, squareVerticesPositionBuffer);
gl.bufferData(gl.ARRAY_BUFFER, new Float32Array([
1.0, 1.0, 0.0,
-1.0, 1.0, 0.0,
1.0, -1.0, 0.0,
-1.0, -1.0, 0.0
]), gl.STATIC_DRAW);
}
function drawScene() {
gl.clear(gl.COLOR_BUFFER_BIT);
for (let i = 0; i < 2; i++) {
gl.bindBuffer(gl.ARRAY_BUFFER, squareVerticesPositionBuffer);
gl.vertexAttribPointer(vertexPositionAttribute[i], 3, gl.FLOAT, false, 0, 0);
gl.useProgram(program[i]);
gl.uniform1f(depthUniform[i], i + 1);
gl.drawArrays(gl.TRIANGLE_STRIP, 0, 4);
}
window.requestAnimationFrame(drawScene);
}
</script>
</body>
</html>

View File

@ -27,6 +27,7 @@ const EXAMPLE_URL = "http://example.com/browser/browser/devtools/shadereditor/te
const SIMPLE_CANVAS_URL = EXAMPLE_URL + "doc_simple-canvas.html";
const SHADER_ORDER_URL = EXAMPLE_URL + "doc_shader-order.html";
const MULTIPLE_CONTEXTS_URL = EXAMPLE_URL + "doc_multiple-contexts.html";
const OVERLAPPING_GEOMETRY_CANVAS_URL = EXAMPLE_URL + "doc_overlapping-geometry.html";
// All tests are asynchronous.
waitForExplicitFinish();

View File

@ -95,6 +95,10 @@ function Tooltip(doc) {
module.exports.Tooltip = Tooltip;
Tooltip.prototype = {
defaultPosition: "before_start",
defaultOffsetX: 0,
defaultOffsetY: 0,
/**
* Show the tooltip. It might be wise to append some content first if you
* don't want the tooltip to be empty. You may access the content of the
@ -105,9 +109,12 @@ Tooltip.prototype = {
* https://developer.mozilla.org/en-US/docs/XUL/PopupGuide/Positioning
* Defaults to before_start
*/
show: function(anchor, position="before_start") {
show: function(anchor,
position = this.defaultPosition,
x = this.defaultOffsetX,
y = this.defaultOffsetY) {
this.panel.hidden = false;
this.panel.openPopup(anchor, position);
this.panel.openPopup(anchor, position, x, y);
},
/**
@ -258,11 +265,44 @@ Tooltip.prototype = {
},
/**
* Fill the tooltip with an image, displayed over a tiled background useful
* for transparent images.
* Also adds the image dimension as a label at the bottom.
* Sets some text as the content of this tooltip.
*
* @param string[] messages
* A list of text messages.
*/
setImageContent: function(imageUrl, maxDim=400) {
setTextContent: function(...messages) {
let vbox = this.doc.createElement("vbox");
vbox.className = "devtools-tooltip-simple-text-container";
vbox.setAttribute("flex", "1");
for (let text of messages) {
let description = this.doc.createElement("description");
description.setAttribute("flex", "1");
description.className = "devtools-tooltip-simple-text";
description.textContent = text;
vbox.appendChild(description);
}
this.content = vbox;
},
/**
* Fill the tooltip with an image, displayed over a tiled background useful
* for transparent images. Also adds the image dimension as a label at the
* bottom.
* @param {string} imageUrl
* The url to load the image from
* @param {Object} options
* The following options are supported:
* - resized : whether or not the image identified by imageUrl has been
* resized before this function was called.
* - naturalWidth/naturalHeight : the original size of the image before
* it was resized, if if was resized before this function was called.
* If not provided, will be measured on the loaded image.
* - maxDim : if the image should be resized before being shown, pass
* a number here
*/
setImageContent: function(imageUrl, options={}) {
// Main container
let vbox = this.doc.createElement("vbox");
vbox.setAttribute("align", "center")
@ -279,9 +319,9 @@ Tooltip.prototype = {
// Display the image
let image = this.doc.createElement("image");
image.setAttribute("src", imageUrl);
if (maxDim) {
image.style.maxWidth = maxDim + "px";
image.style.maxHeight = maxDim + "px";
if (options.maxDim) {
image.style.maxWidth = options.maxDim + "px";
image.style.maxHeight = options.maxDim + "px";
}
tiles.appendChild(image);
@ -294,11 +334,9 @@ Tooltip.prototype = {
imgObj.onload = null;
// Display dimensions
label.textContent = imgObj.naturalWidth + " x " + imgObj.naturalHeight;
if (imgObj.naturalWidth > maxDim ||
imgObj.naturalHeight > maxDim) {
label.textContent += " *";
}
let w = options.naturalWidth || imgObj.naturalWidth;
let h = options.naturalHeight || imgObj.naturalHeight;
label.textContent = w + " x " + h;
}
},
@ -309,7 +347,9 @@ Tooltip.prototype = {
setCssBackgroundImageContent: function(cssBackground, sheetHref, maxDim=400) {
let uri = getBackgroundImageUri(cssBackground, sheetHref);
if (uri) {
this.setImageContent(uri, maxDim);
this.setImageContent(uri, {
maxDim: maxDim
});
}
},

View File

@ -1,15 +1,25 @@
/* 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/. */
.errors,
.breakpoints {
width: 16px;
}
.breakpoint, .debugLocation, .breakpoint-debugLocation {
.error, .breakpoint, .debugLocation, .breakpoint-debugLocation {
display: inline-block;
margin-left: 5px;
width: 14px;
height: 14px;
width: 12px;
height: 12px;
background-repeat: no-repeat;
background-position: center center;
background-size: 12px;
background-position: center;
background-size: contain;
}
.error {
background-image: url("chrome://browser/skin/devtools/orion-error.png");
opacity: 0.75;
}
.breakpoint {
@ -23,4 +33,8 @@
.breakpoint.debugLocation {
background-image: url("chrome://browser/skin/devtools/orion-debug-location.png"),
url("chrome://browser/skin/devtools/orion-breakpoint.png");
}
}
.error-line {
background: rgba(255,0,0,0.2);
}

View File

@ -6,38 +6,6 @@
const dbginfo = new WeakMap();
// Private functions
/**
* Adds a marker to the breakpoints gutter.
* Type should be either a 'breakpoint' or a 'debugLocation'.
*/
function addMarker(cm, line, type) {
let info = cm.lineInfo(line);
if (info.gutterMarkers)
return void info.gutterMarkers.breakpoints.classList.add(type);
let mark = cm.getWrapperElement().ownerDocument.createElement("div");
mark.className = type;
mark.innerHTML = "";
cm.setGutterMarker(info.line, "breakpoints", mark);
}
/**
* Removes a marker from the breakpoints gutter.
* Type should be either a 'breakpoint' or a 'debugLocation'.
*/
function removeMarker(cm, line, type) {
let info = cm.lineInfo(line);
if (!info || !info.gutterMarkers)
return;
info.gutterMarkers.breakpoints.classList.remove(type);
}
// These functions implement search within the debugger. Since
// search in the debugger is different from other components,
// we can't use search.js CodeMirror addon. This is a slightly
@ -155,7 +123,7 @@ function addBreakpoint(ctx, line, cond) {
let meta = dbginfo.get(ed);
let info = cm.lineInfo(line);
addMarker(cm, line, "breakpoint");
ed.addMarker(line, "breakpoints", "breakpoint");
meta.breakpoints[line] = { condition: cond };
info.handle.on("delete", function onDelete() {
@ -179,7 +147,7 @@ function removeBreakpoint(ctx, line) {
let info = cm.lineInfo(line);
meta.breakpoints[info.line] = null;
removeMarker(cm, info.line, "breakpoint");
ed.removeMarker(info.line, "breakpoints", "breakpoint");
ed.emit("breakpointRemoved", line);
}
@ -203,11 +171,11 @@ function getBreakpoints(ctx) {
* display the line on which the Debugger is currently paused.
*/
function setDebugLocation(ctx, line) {
let { ed, cm } = ctx;
let { ed } = ctx;
let meta = dbginfo.get(ed);
meta.debugLocation = line;
addMarker(cm, line, "debugLocation");
ed.addMarker(line, "breakpoints", "debugLocation");
}
/**
@ -226,11 +194,11 @@ function getDebugLocation(ctx) {
* also removes a visual anchor from the breakpoints gutter.
*/
function clearDebugLocation(ctx) {
let { ed, cm } = ctx;
let { ed } = ctx;
let meta = dbginfo.get(ed);
if (meta.debugLocation != null) {
removeMarker(cm, meta.debugLocation, "debugLocation");
ed.removeMarker(meta.debugLocation, "breakpoints", "debugLocation");
meta.debugLocation = null;
}
}

View File

@ -340,7 +340,7 @@ Editor.prototype = {
* Replaces contents of a text area within the from/to {line, ch}
* range. If neither from nor to arguments are provided works
* exactly like setText. If only from object is provided, inserts
* text at that point.
* text at that point, *overwriting* as many characters as needed.
*/
replaceText: function (value, from, to) {
let cm = editors.get(this);
@ -356,6 +356,15 @@ Editor.prototype = {
cm.replaceRange(value, from, to);
},
/**
* Inserts text at the specified {line, ch} position, shifting existing
* contents as necessary.
*/
insertText: function (value, at) {
let cm = editors.get(this);
cm.replaceRange(value, at, at);
},
/**
* Deselects contents of the text area.
*/
@ -370,7 +379,7 @@ Editor.prototype = {
* Marks the contents as clean and returns the current
* version number.
*/
markClean: function () {
setClean: function () {
let cm = editors.get(this);
this.version = cm.changeGeneration();
return this.version;
@ -519,6 +528,120 @@ Editor.prototype = {
this.setFirstVisibleLine(topLine);
},
/**
* Returns whether a marker of a specified class exists in a line's gutter.
*/
hasMarker: function (line, gutterName, markerClass) {
let cm = editors.get(this);
let info = cm.lineInfo(line);
if (!info)
return false;
let gutterMarkers = info.gutterMarkers;
if (!gutterMarkers)
return false;
let marker = gutterMarkers[gutterName];
if (!marker)
return false;
return marker.classList.contains(markerClass);
},
/**
* Adds a marker with a specified class to a line's gutter. If another marker
* exists on that line, the new marker class is added to its class list.
*/
addMarker: function (line, gutterName, markerClass) {
let cm = editors.get(this);
let info = cm.lineInfo(line);
if (!info)
return;
let gutterMarkers = info.gutterMarkers;
if (gutterMarkers) {
let marker = gutterMarkers[gutterName];
if (marker) {
marker.classList.add(markerClass);
return;
}
}
let marker = cm.getWrapperElement().ownerDocument.createElement("div");
marker.className = markerClass;
cm.setGutterMarker(info.line, gutterName, marker);
},
/**
* The reverse of addMarker. Removes a marker of a specified class from a
* line's gutter.
*/
removeMarker: function (line, gutterName, markerClass) {
if (!this.hasMarker(line, gutterName, markerClass))
return;
let cm = editors.get(this);
cm.lineInfo(line).gutterMarkers[gutterName].classList.remove(markerClass);
},
/**
* Remove all gutter markers in the gutter with the given name.
*/
removeAllMarkers: function (gutterName) {
let cm = editors.get(this);
cm.clearGutter(gutterName);
},
/**
* Handles attaching a set of events listeners on a marker. They should
* be passed as an object literal with keys as event names and values as
* function listeners. The line number, marker node and optional data
* will be passed as arguments to the function listener.
*
* You don't need to worry about removing these event listeners.
* They're automatically orphaned when clearing markers.
*/
setMarkerListeners: function(line, gutterName, markerClass, events, data) {
if (!this.hasMarker(line, gutterName, markerClass))
return;
let cm = editors.get(this);
let marker = cm.lineInfo(line).gutterMarkers[gutterName];
for (let name in events) {
let listener = events[name].bind(this, line, marker, data);
marker.addEventListener(name, listener);
}
},
/**
* Returns whether a line is decorated using the specified class name.
*/
hasLineClass: function (line, className) {
let cm = editors.get(this);
let info = cm.lineInfo(line);
if (!info)
return false;
return info.wrapClass == className;
},
/**
* Set a CSS class name for the given line, including the text and gutter.
*/
addLineClass: function (line, className) {
let cm = editors.get(this);
cm.addLineClass(line, "wrap", className);
},
/**
* The reverse of addLineClass.
*/
removeLineClass: function (line, className) {
let cm = editors.get(this);
cm.removeLineClass(line, "wrap", className);
},
destroy: function () {
this.container = null;
this.config = null;

View File

@ -376,7 +376,7 @@ StyleSheetEditor.prototype = {
if (callback) {
callback(returnFile);
}
this.sourceEditor.markClean();
this.sourceEditor.setClean();
}.bind(this));
};

View File

@ -6,6 +6,8 @@
const TEST_URI = "http://example.com/browser/browser/devtools/webconsole/test/test-bug-632347-iterators-generators.html";
function test() {
requestLongerTimeout(4);
addTab(TEST_URI);
browser.addEventListener("load", function onLoad() {
browser.removeEventListener("load", onLoad, true);

View File

@ -34,8 +34,8 @@ validator.invalidAppType=Unknown app type: '%S'.
validator.invalidHostedPriviledges=Hosted App can't be type '%S'.
validator.noCertifiedSupport='certified' apps are not fully supported on the App manager.
validator.nonAbsoluteLaunchPath=Launch path has to be an absolute path starting with '/': '%S'
validator.invalidLaunchPath=Unable to access to app starting document '%S'
# LOCALIZATION NOTE (validator.invalidLaunchPathBadHttpCode): %1$S is the URI of
validator.accessFailedLaunchPath=Unable to access the app starting document '%S'
# LOCALIZATION NOTE (validator.accessFailedLaunchPathBadHttpCode): %1$S is the URI of
# the launch document, %2$S is the http error code.
validator.invalidLaunchPathBadHttpCode=Unable to access to app starting document '%1$S', got HTTP code %2$S
validator.accessFailedLaunchPathBadHttpCode=Unable to access the app starting document '%1$S', got HTTP code %2$S

View File

@ -2,6 +2,8 @@
- 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/. -->
<!ENTITY popups.label "Pop-ups">
<!ENTITY blockPopups.label "Block pop-up windows">
<!ENTITY blockPopups.accesskey "B">
<!ENTITY popupExceptions.label "Exceptions…">

View File

@ -2,6 +2,8 @@
- 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/. -->
<!ENTITY general.label "General">
<!ENTITY warnAddonInstall.label "Warn me when sites try to install add-ons">
<!ENTITY warnAddonInstall.accesskey "W">

View File

@ -255,7 +255,11 @@ this.UITour = {
if (uri.schemeIs("chrome"))
return true;
if (!uri.schemeIs("https"))
let allowedSchemes = new Set(["https"]);
if (!Services.prefs.getBoolPref("browser.uitour.requireSecure"))
allowedSchemes.add("http");
if (!allowedSchemes.has(uri.scheme))
return false;
this.importPermissions();

View File

@ -32,13 +32,12 @@ function is_element_hidden(element, msg) {
ok(is_hidden(element), msg);
}
function loadTestPage(callback, untrustedHost = false) {
function loadTestPage(callback, host = "https://example.com/") {
if (gTestTab)
gBrowser.removeTab(gTestTab);
let url = getRootDirectory(gTestPath) + "uitour.html";
if (untrustedHost)
url = url.replace("chrome://mochitests/content/", "http://example.com/");
url = url.replace("chrome://mochitests/content/", host);
gTestTab = gBrowser.addTab(url);
gBrowser.selectedTab = gTestTab;
@ -55,6 +54,8 @@ function loadTestPage(callback, untrustedHost = false) {
function test() {
Services.prefs.setBoolPref("browser.uitour.enabled", true);
let testUri = Services.io.newURI("http://example.com", null, null);
Services.perms.add(testUri, "uitour", Services.perms.ALLOW_ACTION);
waitForExplicitFinish();
@ -65,6 +66,7 @@ function test() {
gBrowser.removeTab(gTestTab);
delete window.gTestTab;
Services.prefs.clearUserPref("browser.uitour.enabled", true);
Services.perms.remove("example.com", "uitour");
});
function done() {
@ -98,6 +100,41 @@ function test() {
}
let tests = [
function test_untrusted_host(done) {
loadTestPage(function() {
let highlight = document.getElementById("UITourHighlight");
is_element_hidden(highlight, "Highlight should initially be hidden");
gContentAPI.showHighlight("urlbar");
is_element_hidden(highlight, "Highlight should not be shown on a untrusted host");
done();
}, "http://mochi.test:8888/");
},
function test_unsecure_host(done) {
loadTestPage(function() {
let highlight = document.getElementById("UITourHighlight");
is_element_hidden(highlight, "Highlight should initially be hidden");
gContentAPI.showHighlight("urlbar");
is_element_hidden(highlight, "Highlight should not be shown on a unsecure host");
done();
}, "http://example.com/");
},
function test_unsecure_host_override(done) {
Services.prefs.setBoolPref("browser.uitour.requireSecure", false);
loadTestPage(function() {
let highlight = document.getElementById("UITourHighlight");
is_element_hidden(highlight, "Highlight should initially be hidden");
gContentAPI.showHighlight("urlbar");
is_element_visible(highlight, "Highlight should be shown on a unsecure host when override pref is set");
Services.prefs.setBoolPref("browser.uitour.requireSecure", true);
done();
}, "http://example.com/");
},
function test_disabled(done) {
Services.prefs.setBoolPref("browser.uitour.enabled", false);
@ -110,17 +147,6 @@ let tests = [
Services.prefs.setBoolPref("browser.uitour.enabled", true);
done();
},
function test_untrusted_host(done) {
loadTestPage(function() {
let highlight = document.getElementById("UITourHighlight");
is_element_hidden(highlight, "Highlight should initially be hidden");
gContentAPI.showHighlight("urlbar");
is_element_hidden(highlight, "Highlight should not be shown on a untrusted domain");
done();
}, true);
},
function test_highlight(done) {
let highlight = document.getElementById("UITourHighlight");
is_element_hidden(highlight, "Highlight should initially be hidden");

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.7 KiB

View File

@ -105,7 +105,7 @@ browser.jar:
skin/classic/browser/preferences/Options-sync.png (preferences/Options-sync.png)
#endif
* skin/classic/browser/preferences/preferences.css (preferences/preferences.css)
skin/classic/browser/preferences/in-content/preferences.css (preferences/in-content/preferences.css)
* skin/classic/browser/preferences/in-content/preferences.css (preferences/in-content/preferences.css)
skin/classic/browser/preferences/applications.css (preferences/applications.css)
skin/classic/browser/preferences/aboutPermissions.css (preferences/aboutPermissions.css)
skin/classic/browser/social/services-16.png (social/services-16.png)
@ -143,6 +143,7 @@ browser.jar:
skin/classic/browser/devtools/orion.css (devtools/orion.css)
skin/classic/browser/devtools/orion-container.css (devtools/orion-container.css)
skin/classic/browser/devtools/orion-task.png (devtools/orion-task.png)
skin/classic/browser/devtools/orion-error.png (devtools/orion-error.png)
skin/classic/browser/devtools/orion-breakpoint.png (devtools/orion-breakpoint.png)
skin/classic/browser/devtools/orion-debug-location.png (devtools/orion-debug-location.png)
skin/classic/browser/devtools/breadcrumbs-scrollbutton.png (devtools/breadcrumbs-scrollbutton.png)

View File

@ -21,12 +21,12 @@
-moz-margin-end: 3px;
}
richlistitem label {
#handlersView > richlistitem label {
-moz-margin-start: 1px;
margin-top: 2px;
}
richlistitem {
#handlersView > richlistitem {
min-height: 25px;
}

View File

@ -6,95 +6,115 @@
@namespace html "http://www.w3.org/1999/xhtml";
#preferences-home {
display: block;
}
#header {
margin-bottom: 18px;
}
.landingButton {
-moz-box-align: center;
-moz-box-orient: vertical;
}
.landingButton:hover {
cursor: pointer;
}
.landingButton-label {
margin-top: 4px;
}
.landingButton-icon {
display: block;
width: 32px;
height: 32px;
background-image: url("chrome://browser/skin/preferences/Options.png");
background-repeat: no-repeat;
}
.preference-icon {
display: block;
width: 32px;
height: 32px;
background-image: url("chrome://browser/skin/preferences/Options.png");
background-repeat: no-repeat;
margin: 0 20px;
}
.preference-icon[type="general"],
.landingButton-icon[type="general"] {
background-position: 0 0;
}
.preference-icon[type="content"],
.landingButton-icon[type="content"] {
background-position: -64px 0;
}
.preference-icon[type="applications"],
.landingButton-icon[type="applications"] {
background-position: -96px 0;
}
.preference-icon[type="privacy"],
.landingButton-icon[type="privacy"] {
background-position: -128px 0;
}
.preference-icon[type="security"],
.landingButton-icon[type="security"] {
background-position: -160px 0;
}
.preference-icon[type="advanced"],
.landingButton-icon[type="advanced"] {
background-position: -192px 0;
}
.preference-icon[type="sync"],
.landingButton-icon[type="sync"] {
background-image: url("chrome://browser/skin/preferences/Options-sync.png");
}
caption {
font-size: 20px;
font-size: 1.667rem;
}
.heading {
height: 50px;
background-color: rgba(192,199,210,0.7);
border-radius: 5px 5px 0 0;
margin-bottom: 15px;
-moz-box-align: center;
.main-content {
max-width: 800px;
}
prefpane > .content-box {
overflow: auto;
}
/* Category List */
#categories {
-moz-appearance: none;
border: none;
-moz-margin-end: -1px;
background-color: transparent;
position: relative;
margin-top: 41px;
}
.category {
-moz-appearance: none;
border-width: 1px;
-moz-border-end-width: 0;
border-style: solid;
border-color: transparent;
padding: 9px 4px 10px;
-moz-padding-end: 8px;
-moz-box-align: center;
overflow: hidden;
min-height: 0;
color: WindowText;
height: 52px;
}
.category:-moz-locale-dir(ltr) {
border-top-left-radius: 5px;
border-bottom-left-radius: 5px;
}
.category:-moz-locale-dir(rtl) {
border-top-right-radius: 5px;
border-bottom-right-radius: 5px;
}
.category[selected] {
background-color: -moz-Field;
color: -moz-FieldText;
border-color: ThreeDShadow;
}
.category-name {
font-size: 1.5rem;
-moz-padding-end: 24px;
}
/* Maximize the size of the viewport when the window is small */
@media (max-width: 800px) {
.category-name {
display: none;
}
}
.category-icon {
width: 32px;
height: 32px;
margin: 0 6px;
-moz-margin-start: 6px;
-moz-margin-end: 5px;
list-style-image: url("chrome://browser/skin/preferences/Options.png");
}
#category-general > .category-icon {
-moz-image-region: rect(0, 32px, 32px, 0);
}
#category-content > .category-icon {
-moz-image-region: rect(0, 96px, 32px, 64px)
}
#category-application > .category-icon {
-moz-image-region: rect(0, 128px, 32px, 96px)
}
#category-privacy > .category-icon {
-moz-image-region: rect(0, 160px, 32px, 128px)
}
#category-security > .category-icon {
-moz-image-region: rect(0, 192px, 32px, 160px)
}
#category-advanced > .category-icon {
-moz-image-region: rect(0, 224px, 32px, 192px)
}
%ifdef MOZ_SERVICES_SYNC
#category-sync > .category-icon {
list-style-image: url("chrome://browser/skin/preferences/Options-sync.png");
}
%endif
/* Applications Pane Styles */
#applications-content {

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.7 KiB

View File

@ -169,7 +169,7 @@ browser.jar:
#endif
skin/classic/browser/preferences/saveFile.png (preferences/saveFile.png)
* skin/classic/browser/preferences/preferences.css (preferences/preferences.css)
skin/classic/browser/preferences/in-content/preferences.css (preferences/in-content/preferences.css)
* skin/classic/browser/preferences/in-content/preferences.css (preferences/in-content/preferences.css)
skin/classic/browser/preferences/applications.css (preferences/applications.css)
skin/classic/browser/preferences/aboutPermissions.css (preferences/aboutPermissions.css)
skin/classic/browser/social/services-16.png (social/services-16.png)
@ -232,6 +232,7 @@ browser.jar:
skin/classic/browser/devtools/orion.css (devtools/orion.css)
skin/classic/browser/devtools/orion-container.css (devtools/orion-container.css)
skin/classic/browser/devtools/orion-task.png (devtools/orion-task.png)
skin/classic/browser/devtools/orion-error.png (devtools/orion-error.png)
skin/classic/browser/devtools/orion-breakpoint.png (devtools/orion-breakpoint.png)
skin/classic/browser/devtools/orion-debug-location.png (devtools/orion-debug-location.png)
* skin/classic/browser/devtools/webconsole.css (devtools/webconsole.css)

View File

@ -14,12 +14,12 @@
margin-bottom: -1px;
}
richlistitem label {
#handlersView > richlistitem label {
-moz-margin-start: 3px;
margin-top: 2px;
}
richlistitem {
#handlersView > richlistitem {
min-height: 22px;
}

View File

@ -2,102 +2,119 @@
- 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/. */
%include ../../shared.inc
@import url("chrome://global/skin/inContentUI.css");
@namespace html "http://www.w3.org/1999/xhtml";
#preferences-home {
display: block;
}
#header {
margin-bottom: 18px;
}
.landingButton {
-moz-box-align: center;
-moz-box-orient: vertical;
border: none;
background: none;
box-shadow: none;
}
.landingButton:hover {
cursor: pointer;
}
.landingButton-label {
margin-top: 4px;
}
.landingButton-icon {
display: block;
width: 32px;
height: 32px;
background-image: url("chrome://browser/skin/preferences/Options.png");
background-repeat: no-repeat;
}
.preference-icon {
display: block;
width: 32px;
height: 32px;
background-image: url("chrome://browser/skin/preferences/Options.png");
background-repeat: no-repeat;
margin: 0 20px;
}
.preference-icon[type="general"],
.landingButton-icon[type="general"] {
background-position: 0 0;
}
.preference-icon[type="content"],
.landingButton-icon[type="content"] {
background-position: -64px 0;
}
.preference-icon[type="applications"],
.landingButton-icon[type="applications"] {
background-position: -96px 0;
}
.preference-icon[type="privacy"],
.landingButton-icon[type="privacy"] {
background-position: -128px 0;
}
.preference-icon[type="security"],
.landingButton-icon[type="security"] {
background-position: -160px 0;
}
.preference-icon[type="advanced"],
.landingButton-icon[type="advanced"] {
background-position: -192px 0;
}
.preference-icon[type="sync"],
.landingButton-icon[type="sync"] {
background-image: url("chrome://browser/skin/preferences/Options-sync.png");
}
caption {
font-size: 20px;
font-size: 1.667rem;
}
.heading {
height: 50px;
background-color: rgba(192,199,210,0.7);
border-radius: 5px 5px 0 0;
margin-bottom: 15px;
-moz-box-align: center;
.main-content {
max-width: 800px;
}
prefpane > .content-box {
overflow: auto;
}
/* Category List */
#categories {
-moz-appearance: none;
border: none;
-moz-margin-end: -1px;
background-color: transparent;
position: relative;
margin-top: 31px;
}
.category {
-moz-appearance: none;
color: #252F3B;
border-width: 1px;
border-style: solid;
border-color: transparent;
padding: 10px 4px;
-moz-padding-end: 8px;
-moz-box-align: center;
overflow: hidden;
min-height: 0;
height: 52px;
}
.category:-moz-locale-dir(ltr) {
border-top-left-radius: 5px;
border-bottom-left-radius: 5px;
}
.category:-moz-locale-dir(rtl) {
border-top-right-radius: 5px;
border-bottom-right-radius: 5px;
}
.category[selected] {
background-color: rgba(255, 255, 255, 0.35);
color: -moz-dialogtext;
border-color: rgba(50, 65, 92, 0.4);
-moz-border-end-color: #C9CFD7;
}
.category-name {
font-size: 1.5rem;
-moz-padding-end: 24px;
}
/* Maximize the size of the viewport when the window is small */
@media (max-width: 800px) {
.category-name {
display: none;
}
}
.category-icon {
width: 32px;
height: 32px;
-moz-margin-start: 6px;
list-style-image: url("chrome://browser/skin/preferences/Options.png");
}
#category-general > .category-icon {
-moz-image-region: rect(0, 32px, 32px, 0);
}
#category-content > .category-icon {
-moz-image-region: rect(0, 96px, 32px, 64px)
}
#category-application > .category-icon {
-moz-image-region: rect(0, 128px, 32px, 96px)
}
#category-privacy > .category-icon {
-moz-image-region: rect(0, 160px, 32px, 128px)
}
#category-security > .category-icon {
-moz-image-region: rect(0, 192px, 32px, 160px)
}
#category-advanced > .category-icon {
-moz-image-region: rect(0, 224px, 32px, 192px)
}
%ifdef MOZ_SERVICES_SYNC
#category-sync > .category-icon {
list-style-image: url("chrome://browser/skin/preferences/Options-sync.png");
}
%endif
/* Applications Pane Styles */
#applications-content {

View File

@ -121,11 +121,29 @@
background: #eee;
border-radius: 3px;
}
.devtools-tooltip.devtools-tooltip-panel .panel-arrowcontent {
/* If the tooltip uses a <panel> XUL element instead */
padding: 4px;
}
.devtools-tooltip-simple-text {
background: linear-gradient(1deg, transparent 0%, rgba(94,136,176,0.1) 100%);
max-width: 400px;
margin: 0 -4px; /* Compensate for the .panel-arrowcontent padding. */
padding: 8px 12px;
text-shadow: 0 1px 0 #fff;
white-space: pre-wrap;
}
.devtools-tooltip-simple-text:first-child {
margin-top: -4px;
}
.devtools-tooltip-simple-text:last-child {
margin-bottom: -4px;
}
.devtools-tooltip-tiles {
background-color: #eee;
background-image: linear-gradient(45deg, #ccc 25%, transparent 25%, transparent 75%, #ccc 75%, #ccc),

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.7 KiB

View File

@ -125,7 +125,7 @@ browser.jar:
#endif
skin/classic/browser/preferences/saveFile.png (preferences/saveFile.png)
* skin/classic/browser/preferences/preferences.css (preferences/preferences.css)
skin/classic/browser/preferences/in-content/preferences.css (preferences/in-content/preferences.css)
* skin/classic/browser/preferences/in-content/preferences.css (preferences/in-content/preferences.css)
skin/classic/browser/preferences/applications.css (preferences/applications.css)
skin/classic/browser/preferences/aboutPermissions.css (preferences/aboutPermissions.css)
skin/classic/browser/social/services-16.png (social/services-16.png)
@ -167,6 +167,7 @@ browser.jar:
skin/classic/browser/devtools/orion.css (devtools/orion.css)
skin/classic/browser/devtools/orion-container.css (devtools/orion-container.css)
skin/classic/browser/devtools/orion-task.png (devtools/orion-task.png)
skin/classic/browser/devtools/orion-error.png (devtools/orion-error.png)
skin/classic/browser/devtools/orion-breakpoint.png (devtools/orion-breakpoint.png)
skin/classic/browser/devtools/orion-debug-location.png (devtools/orion-debug-location.png)
* skin/classic/browser/devtools/webconsole.css (devtools/webconsole.css)
@ -402,7 +403,7 @@ browser.jar:
#endif
skin/classic/aero/browser/preferences/saveFile.png (preferences/saveFile-aero.png)
* skin/classic/aero/browser/preferences/preferences.css (preferences/preferences.css)
skin/classic/aero/browser/preferences/in-content/preferences.css (preferences/in-content/preferences.css)
* skin/classic/aero/browser/preferences/in-content/preferences.css (preferences/in-content/preferences.css)
skin/classic/aero/browser/preferences/applications.css (preferences/applications.css)
skin/classic/aero/browser/preferences/aboutPermissions.css (preferences/aboutPermissions.css)
skin/classic/aero/browser/social/services-16.png (social/services-16.png)
@ -444,6 +445,7 @@ browser.jar:
skin/classic/aero/browser/devtools/orion.css (devtools/orion.css)
skin/classic/aero/browser/devtools/orion-container.css (devtools/orion-container.css)
skin/classic/aero/browser/devtools/orion-task.png (devtools/orion-task.png)
skin/classic/aero/browser/devtools/orion-error.png (devtools/orion-error.png)
skin/classic/aero/browser/devtools/orion-breakpoint.png (devtools/orion-breakpoint.png)
skin/classic/aero/browser/devtools/orion-debug-location.png (devtools/orion-debug-location.png)
* skin/classic/aero/browser/devtools/webconsole.css (devtools/webconsole.css)

View File

@ -21,12 +21,12 @@
-moz-margin-end: 3px;
}
richlistitem label {
#handlersView > richlistitem label {
-moz-margin-start: 1px;
margin-top: 2px;
}
richlistitem {
#handlersView > richlistitem {
min-height: 22px;
}

View File

@ -6,98 +6,116 @@
@namespace html "http://www.w3.org/1999/xhtml";
#preferences-home {
display: block;
}
#header {
margin-bottom: 18px;
}
.landingButton {
-moz-box-align: center;
-moz-box-orient: vertical;
border: none;
background: none;
box-shadow: none;
}
.landingButton:hover {
cursor: pointer;
}
.landingButton-label {
margin-top: 4px;
}
.landingButton-icon {
display: block;
width: 32px;
height: 32px;
background-image: url("chrome://browser/skin/preferences/Options.png");
background-repeat: no-repeat;
}
.preference-icon {
display: block;
width: 32px;
height: 32px;
background-image: url("chrome://browser/skin/preferences/Options.png");
background-repeat: no-repeat;
margin: 0 20px;
}
.preference-icon[type="general"],
.landingButton-icon[type="general"] {
background-position: 0 0;
}
.preference-icon[type="content"],
.landingButton-icon[type="content"] {
background-position: -64px 0;
}
.preference-icon[type="applications"],
.landingButton-icon[type="applications"] {
background-position: -96px 0;
}
.preference-icon[type="privacy"],
.landingButton-icon[type="privacy"] {
background-position: -128px 0;
}
.preference-icon[type="security"],
.landingButton-icon[type="security"] {
background-position: -160px 0;
}
.preference-icon[type="advanced"],
.landingButton-icon[type="advanced"] {
background-position: -192px 0;
}
.preference-icon[type="sync"],
.landingButton-icon[type="sync"] {
background-image: url("chrome://browser/skin/preferences/Options-sync.png");
}
caption {
font-size: 20px;
font-size: 1.667rem;
}
.heading {
height: 50px;
background-color: rgba(192,199,210,0.7);
border-radius: 5px 5px 0 0;
margin-bottom: 15px;
-moz-box-align: center;
.main-content {
max-width: 800px;
}
prefpane > .content-box {
overflow: auto;
}
/* Category List */
#categories {
-moz-appearance: none;
border: none;
-moz-margin-end: -1px;
background-color: transparent;
position: relative;
margin-top: 31px;
}
.category {
-moz-appearance: none;
background-color: transparent;
color: #252F3B;
padding: 10px 4px;
border-width: 1px;
border-style: solid;
border-color: transparent;
-moz-padding-end: 8px;
-moz-box-align: center;
overflow: hidden;
min-height: 0;
height: 52px;
}
.category:-moz-locale-dir(ltr) {
border-top-left-radius: 5px;
border-bottom-left-radius: 5px;
}
.category:-moz-locale-dir(rtl) {
border-top-right-radius: 5px;
border-bottom-right-radius: 5px;
}
.category[selected] {
background-color: rgba(255, 255, 255, 0.4);
color: #252F3B;
border-color: #C3CEDF;
-moz-border-end-color: #E2E9F2;
}
.category-name {
font-size: 1.5rem;
-moz-padding-end: 24px;
}
/* Maximize the size of the viewport when the window is small */
@media (max-width: 800px) {
.category-name {
display: none;
}
}
.category-icon {
width: 32px;
height: 32px;
margin: 0 6px;
-moz-margin-start: 6px;
-moz-margin-end: 5px;
list-style-image: url("chrome://browser/skin/preferences/Options.png");
}
#category-general > .category-icon {
-moz-image-region: rect(0, 32px, 32px, 0);
}
#category-content > .category-icon {
-moz-image-region: rect(0, 96px, 32px, 64px)
}
#category-application > .category-icon {
-moz-image-region: rect(0, 128px, 32px, 96px)
}
#category-privacy > .category-icon {
-moz-image-region: rect(0, 160px, 32px, 128px)
}
#category-security > .category-icon {
-moz-image-region: rect(0, 192px, 32px, 160px)
}
#category-advanced > .category-icon {
-moz-image-region: rect(0, 224px, 32px, 192px)
}
%ifdef MOZ_SERVICES_SYNC
#category-sync > .category-icon {
list-style-image: url("chrome://browser/skin/preferences/Options-sync.png");
}
%endif
/* Applications Pane Styles */
#applications-content {

View File

@ -107,6 +107,8 @@ public class DoCommand {
String ffxProvider = "org.mozilla.ffxcp";
String fenProvider = "org.mozilla.fencp";
private static final int DEFAULT_STARTPRG_TIMEOUT_SECONDS = 300;
private final String prgVersion = "SUTAgentAndroid Version 1.19";
public enum Command
@ -116,6 +118,7 @@ public class DoCommand {
EXECSU ("execsu"),
EXECCWD ("execcwd"),
EXECCWDSU ("execcwdsu"),
EXECEXT ("execext"),
ENVRUN ("envrun"),
KILL ("kill"),
PS ("ps"),
@ -723,7 +726,7 @@ public class DoCommand {
theArgs[lcv - 1] = Argv[lcv];
}
strReturn = StartPrg2(theArgs, cmdOut, null, false);
strReturn = StartPrg2(theArgs, cmdOut, null, false, DEFAULT_STARTPRG_TIMEOUT_SECONDS);
}
else
{
@ -741,7 +744,7 @@ public class DoCommand {
theArgs[lcv - 1] = Argv[lcv];
}
strReturn = StartPrg2(theArgs, cmdOut, null, true);
strReturn = StartPrg2(theArgs, cmdOut, null, true, DEFAULT_STARTPRG_TIMEOUT_SECONDS);
}
else
{
@ -759,7 +762,7 @@ public class DoCommand {
theArgs[lcv - 2] = Argv[lcv];
}
strReturn = StartPrg2(theArgs, cmdOut, Argv[1], false);
strReturn = StartPrg2(theArgs, cmdOut, Argv[1], false, DEFAULT_STARTPRG_TIMEOUT_SECONDS);
}
else
{
@ -777,7 +780,7 @@ public class DoCommand {
theArgs[lcv - 2] = Argv[lcv];
}
strReturn = StartPrg2(theArgs, cmdOut, Argv[1], true);
strReturn = StartPrg2(theArgs, cmdOut, Argv[1], true, DEFAULT_STARTPRG_TIMEOUT_SECONDS);
}
else
{
@ -796,7 +799,7 @@ public class DoCommand {
}
if (Argv[1].contains("/") || Argv[1].contains("\\") || !Argv[1].contains("."))
strReturn = StartPrg(theArgs, cmdOut, false);
strReturn = StartPrg(theArgs, cmdOut, false, DEFAULT_STARTPRG_TIMEOUT_SECONDS);
else
strReturn = StartJavaPrg(theArgs, null);
}
@ -806,6 +809,62 @@ public class DoCommand {
}
break;
case EXECEXT:
// An "extended" exec command with format:
// execext [su] [cwd=<path>] [t=<timeout in seconds>] arg1 ...
if (Argc >= 2)
{
boolean su = false;
String cwd = null;
int timeout = DEFAULT_STARTPRG_TIMEOUT_SECONDS;
int extra;
for (extra = 1; extra < Argc; extra++)
{
if (Argv[extra].equals("su"))
{
su = true;
}
else if (Argv[extra].startsWith("cwd="))
{
cwd = Argv[extra].substring(4);
}
else if (Argv[extra].startsWith("t="))
{
timeout = Integer.parseInt(Argv[extra].substring(2));
if (timeout < 1 || timeout > 4*60*60)
{
Log.e("SUTAgentAndroid",
"invalid execext timeout "+Argv[extra].substring(2)+"; using default instead");
timeout = DEFAULT_STARTPRG_TIMEOUT_SECONDS;
}
}
else
{
break;
}
}
if (extra < Argc)
{
String [] theArgs = new String [Argc - extra];
for (int lcv = extra; lcv < Argc; lcv++)
{
theArgs[lcv - extra] = Argv[lcv];
}
strReturn = StartPrg2(theArgs, cmdOut, cwd, su, timeout);
}
else
{
strReturn = sErrorPrefix + "No regular arguments for " + Argv[0] + " command!";
}
}
else
{
strReturn = sErrorPrefix + "Wrong number of arguments for " + Argv[0] + " command!";
}
break;
case KILL:
if (Argc == 2)
strReturn = KillProcess(Argv[1], cmdOut);
@ -3594,7 +3653,7 @@ private void CancelNotification()
return (sRet);
}
public String StartPrg(String [] progArray, OutputStream out, boolean startAsRoot)
public String StartPrg(String [] progArray, OutputStream out, boolean startAsRoot, int timeoutSeconds)
{
String sRet = "";
int lcv = 0;
@ -3625,16 +3684,12 @@ private void CancelNotification()
}
RedirOutputThread outThrd = new RedirOutputThread(pProc, out);
outThrd.start();
while (lcv < 30) {
try {
outThrd.join(10000);
int nRetCode = pProc.exitValue();
sRet = "return code [" + nRetCode + "]";
break;
}
catch (IllegalThreadStateException itse) {
lcv++;
}
try {
outThrd.join(timeoutSeconds * 1000);
int nRetCode = pProc.exitValue();
sRet = "return code [" + nRetCode + "]";
}
catch (IllegalThreadStateException itse) {
}
outThrd.stopRedirect();
}
@ -3651,7 +3706,7 @@ private void CancelNotification()
return (sRet);
}
public String StartPrg2(String [] progArray, OutputStream out, String cwd, boolean startAsRoot)
public String StartPrg2(String [] progArray, OutputStream out, String cwd, boolean startAsRoot, int timeoutSeconds)
{
String sRet = "";
@ -3665,7 +3720,7 @@ private void CancelNotification()
if (!sEnvString.contains("=") && (sEnvString.length() > 0))
{
if (sEnvString.contains("/") || sEnvString.contains("\\") || !sEnvString.contains("."))
sRet = StartPrg(progArray, out, startAsRoot);
sRet = StartPrg(progArray, out, startAsRoot, timeoutSeconds);
else
sRet = StartJavaPrg(progArray, null);
return(sRet);
@ -3754,18 +3809,12 @@ private void CancelNotification()
RedirOutputThread outThrd = new RedirOutputThread(pProc, out);
outThrd.start();
lcv = 0;
while (lcv < 30) {
try {
outThrd.join(10000);
int nRetCode = pProc.exitValue();
sRet = "return code [" + nRetCode + "]";
lcv = 30;
}
catch (IllegalThreadStateException itse) {
lcv++;
}
try {
outThrd.join(timeoutSeconds * 1000);
int nRetCode = pProc.exitValue();
sRet = "return code [" + nRetCode + "]";
}
catch (IllegalThreadStateException itse) {
}
outThrd.stopRedirect();
}
@ -3898,9 +3947,10 @@ private void CancelNotification()
"run [cmdline] - start program no wait\n" +
"exec [env pairs] [cmdline] - start program no wait optionally pass env\n" +
" key=value pairs (comma separated)\n" +
"execcwd [env pairs] [cmdline] - start program from specified directory\n" +
"execcwd <dir> [env pairs] [cmdline] - start program from specified directory\n" +
"execsu [env pairs] [cmdline] - start program as privileged user\n" +
"execcwdsu [env pairs] [cmdline] - start program from specified directory as privileged user\n" +
"execcwdsu <dir> [env pairs] [cmdline] - start program from specified directory as privileged user\n" +
"execext [su] [cwd=<dir>] [t=<timeout>] [env pairs] [cmdline] - start program with extended options\n" +
"kill [program name] - kill program no path\n" +
"killall - kill all processes started\n" +
"ps - list of running processes\n" +
@ -3915,7 +3965,6 @@ private void CancelNotification()
" [memory] - physical, free, available, storage memory\n" +
" for device\n" +
" [processes] - list of running processes see 'ps'\n" +
"deadman timeout - set the duration for the deadman timer\n" +
"alrt [on/off] - start or stop sysalert behavior\n" +
"disk [arg] - prints disk space info\n" +
"cp file1 file2 - copy file1 to file2\n" +

View File

@ -1777,7 +1777,7 @@ fi
AC_DEFINE_UNQUOTED(MOZILLA_VERSION,"$MOZILLA_VERSION")
AC_DEFINE_UNQUOTED(MOZILLA_VERSION_U,$MOZILLA_VERSION)
AC_DEFINE_UNQUOTED(MOZILLA_UAVERSION,"$MOZILLA_UAVERSION")
AC_DEFINE_UNQUOTED(MOZILLA_SYMBOLVERSION,"$MOZILLA_SYMBOLVERSION")
AC_SUBST(MOZILLA_SYMBOLVERSION)
MOZ_DOING_LTO(lto_is_enabled)

View File

@ -538,6 +538,8 @@ protected:
}
public:
bool HasAttrs() const { return mAttrsAndChildren.HasAttrs(); }
inline bool GetAttr(const nsAString& aName, DOMString& aResult) const
{
MOZ_ASSERT(aResult.HasStringBuffer() && aResult.StringBufferLength() == 0,
@ -1190,7 +1192,7 @@ inline const mozilla::dom::Element* nsINode::AsElement() const
inline bool nsINode::HasAttributes() const
{
return IsElement() && AsElement()->GetAttrCount() > 0;
return IsElement() && AsElement()->HasAttrs();
}
/**

View File

@ -2171,9 +2171,6 @@ public:
virtual nsHTMLDocument* AsHTMLDocument() { return nullptr; }
virtual JSObject* WrapObject(JSContext *aCx,
JS::Handle<JSObject*> aScope) MOZ_OVERRIDE;
private:
uint64_t mWarnedAbout;
SelectorCache mSelectorCache;

View File

@ -71,6 +71,11 @@ public:
already_AddRefed<nsIContent> TakeChildAt(uint32_t aPos);
int32_t IndexOfChild(const nsINode* aPossibleChild) const;
bool HasAttrs() const
{
return MappedAttrCount() || (AttrSlotCount() && AttrSlotIsTaken(0));
}
uint32_t AttrCount() const;
const nsAttrValue* GetAttr(nsIAtom* aLocalName,
int32_t aNamespaceID = kNameSpaceID_None) const;

View File

@ -11325,57 +11325,6 @@ nsDocument::Evaluate(const nsAString& aExpression, nsIDOMNode* aContextNode,
aInResult, aResult);
}
// This is just a hack around the fact that window.document is not
// [Unforgeable] yet.
JSObject*
nsIDocument::WrapObject(JSContext *aCx, JS::Handle<JSObject*> aScope)
{
MOZ_ASSERT(IsDOMBinding());
JS::Rooted<JSObject*> obj(aCx, nsINode::WrapObject(aCx, aScope));
if (!obj) {
return nullptr;
}
nsCOMPtr<nsPIDOMWindow> win = do_QueryInterface(GetInnerWindow());
if (!win) {
// No window, nothing else to do here
return obj;
}
if (this != win->GetExtantDoc()) {
// We're not the current document; we're also done here
return obj;
}
JSAutoCompartment ac(aCx, obj);
JS::Rooted<JS::Value> winVal(aCx);
nsCOMPtr<nsIXPConnectJSObjectHolder> holder;
nsresult rv = nsContentUtils::WrapNative(aCx, obj, win,
&NS_GET_IID(nsIDOMWindow),
&winVal,
getter_AddRefs(holder),
false);
if (NS_FAILED(rv)) {
Throw(aCx, rv);
return nullptr;
}
NS_NAMED_LITERAL_STRING(doc_str, "document");
if (!JS_DefineUCProperty(aCx, JSVAL_TO_OBJECT(winVal),
reinterpret_cast<const jschar *>
(doc_str.get()),
doc_str.Length(), JS::ObjectValue(*obj),
JS_PropertyStub, JS_StrictPropertyStub,
JSPROP_READONLY | JSPROP_ENUMERATE)) {
return nullptr;
}
return obj;
}
XPathEvaluator*
nsIDocument::XPathEvaluator()
{

View File

@ -53,7 +53,7 @@ using namespace mozilla::dom::ipc;
static PLDHashOperator
CycleCollectorTraverseListeners(const nsAString& aKey,
nsTArray<nsMessageListenerInfo>* aListeners,
nsAutoTObserverArray<nsMessageListenerInfo, 1>* aListeners,
void* aCb)
{
nsCycleCollectionTraversalCallback* cb =
@ -61,7 +61,7 @@ CycleCollectorTraverseListeners(const nsAString& aKey,
uint32_t count = aListeners->Length();
for (uint32_t i = 0; i < count; ++i) {
NS_CYCLE_COLLECTION_NOTE_EDGE_NAME(*cb, "listeners[i] mStrongListener");
cb->NoteXPCOMChild((*aListeners)[i].mStrongListener.get());
cb->NoteXPCOMChild(aListeners->ElementAt(i).mStrongListener.get());
}
return PL_DHASH_NEXT;
}
@ -258,14 +258,15 @@ NS_IMETHODIMP
nsFrameMessageManager::AddMessageListener(const nsAString& aMessage,
nsIMessageListener* aListener)
{
nsTArray<nsMessageListenerInfo>* listeners = mListeners.Get(aMessage);
nsAutoTObserverArray<nsMessageListenerInfo, 1>* listeners =
mListeners.Get(aMessage);
if (!listeners) {
listeners = new nsTArray<nsMessageListenerInfo>();
listeners = new nsAutoTObserverArray<nsMessageListenerInfo, 1>();
mListeners.Put(aMessage, listeners);
} else {
uint32_t len = listeners->Length();
for (uint32_t i = 0; i < len; ++i) {
if ((*listeners)[i].mStrongListener == aListener) {
if (listeners->ElementAt(i).mStrongListener == aListener) {
return NS_OK;
}
}
@ -281,14 +282,15 @@ NS_IMETHODIMP
nsFrameMessageManager::RemoveMessageListener(const nsAString& aMessage,
nsIMessageListener* aListener)
{
nsTArray<nsMessageListenerInfo>* listeners = mListeners.Get(aMessage);
nsAutoTObserverArray<nsMessageListenerInfo, 1>* listeners =
mListeners.Get(aMessage);
if (!listeners) {
return NS_OK;
}
uint32_t len = listeners->Length();
for (uint32_t i = 0; i < len; ++i) {
if ((*listeners)[i].mStrongListener == aListener) {
if (listeners->ElementAt(i).mStrongListener == aListener) {
listeners->RemoveElementAt(i);
return NS_OK;
}
@ -305,7 +307,7 @@ typedef struct
static PLDHashOperator
CanonicalChecker(const nsAString& aKey,
nsTArray<nsMessageListenerInfo>* aListeners,
nsAutoTObserverArray<nsMessageListenerInfo, 1>* aListeners,
void* aParams)
{
CanonicalCheckerParams* params =
@ -313,13 +315,13 @@ CanonicalChecker(const nsAString& aKey,
uint32_t count = aListeners->Length();
for (uint32_t i = 0; i < count; i++) {
if (!(*aListeners)[i].mWeakListener) {
if (!aListeners->ElementAt(i).mWeakListener) {
continue;
}
nsCOMPtr<nsISupports> otherCanonical =
do_QueryReferent((*aListeners)[i].mWeakListener);
do_QueryReferent(aListeners->ElementAt(i).mWeakListener);
MOZ_ASSERT((params->mCanonical == otherCanonical) ==
(params->mWeak == (*aListeners)[i].mWeakListener));
(params->mWeak == aListeners->ElementAt(i).mWeakListener));
}
return PL_DHASH_NEXT;
}
@ -344,14 +346,15 @@ nsFrameMessageManager::AddWeakMessageListener(const nsAString& aMessage,
mListeners.EnumerateRead(CanonicalChecker, (void*)&params);
#endif
nsTArray<nsMessageListenerInfo>* listeners = mListeners.Get(aMessage);
nsAutoTObserverArray<nsMessageListenerInfo, 1>* listeners =
mListeners.Get(aMessage);
if (!listeners) {
listeners = new nsTArray<nsMessageListenerInfo>();
listeners = new nsAutoTObserverArray<nsMessageListenerInfo, 1>();
mListeners.Put(aMessage, listeners);
} else {
uint32_t len = listeners->Length();
for (uint32_t i = 0; i < len; ++i) {
if ((*listeners)[i].mWeakListener == weak) {
if (listeners->ElementAt(i).mWeakListener == weak) {
return NS_OK;
}
}
@ -369,14 +372,15 @@ nsFrameMessageManager::RemoveWeakMessageListener(const nsAString& aMessage,
nsWeakPtr weak = do_GetWeakReference(aListener);
NS_ENSURE_TRUE(weak, NS_OK);
nsTArray<nsMessageListenerInfo>* listeners = mListeners.Get(aMessage);
nsAutoTObserverArray<nsMessageListenerInfo, 1>* listeners =
mListeners.Get(aMessage);
if (!listeners) {
return NS_OK;
}
uint32_t len = listeners->Length();
for (uint32_t i = 0; i < len; ++i) {
if ((*listeners)[i].mWeakListener == weak) {
if (listeners->ElementAt(i).mWeakListener == weak) {
listeners->RemoveElementAt(i);
return NS_OK;
}
@ -840,18 +844,22 @@ nsFrameMessageManager::ReceiveMessage(nsISupports* aTarget,
InfallibleTArray<nsString>* aJSONRetVal)
{
AutoSafeJSContext ctx;
nsTArray<nsMessageListenerInfo>* listeners = mListeners.Get(aMessage);
nsAutoTObserverArray<nsMessageListenerInfo, 1>* listeners =
mListeners.Get(aMessage);
if (listeners) {
MMListenerRemover lr(this);
for (uint32_t i = 0; i < listeners->Length(); ++i) {
nsAutoTObserverArray<nsMessageListenerInfo, 1>::EndLimitedIterator
iter(*listeners);
while(iter.HasMore()) {
nsMessageListenerInfo& listener = iter.GetNext();
// Remove mListeners[i] if it's an expired weak listener.
nsCOMPtr<nsISupports> weakListener;
if ((*listeners)[i].mWeakListener) {
weakListener = do_QueryReferent((*listeners)[i].mWeakListener);
if (listener.mWeakListener) {
weakListener = do_QueryReferent(listener.mWeakListener);
if (!weakListener) {
listeners->RemoveElementAt(i--);
listeners->RemoveElement(listener);
continue;
}
}
@ -860,7 +868,7 @@ nsFrameMessageManager::ReceiveMessage(nsISupports* aTarget,
if (weakListener) {
wrappedJS = do_QueryInterface(weakListener);
} else {
wrappedJS = do_QueryInterface((*listeners)[i].mStrongListener);
wrappedJS = do_QueryInterface(listener.mStrongListener);
}
if (!wrappedJS) {
@ -1088,7 +1096,7 @@ NS_IMPL_ISUPPORTS1(MessageManagerReporter, nsIMemoryReporter)
static PLDHashOperator
CollectMessageListenerData(const nsAString& aKey,
nsTArray<nsMessageListenerInfo>* aListeners,
nsAutoTObserverArray<nsMessageListenerInfo, 1>* aListeners,
void* aData)
{
MessageManagerReferentCount* referentCount =
@ -1112,7 +1120,8 @@ CollectMessageListenerData(const nsAString& aKey,
}
for (uint32_t i = 0; i < listenerCount; ++i) {
const nsMessageListenerInfo& listenerInfo = (*aListeners)[i];
const nsMessageListenerInfo& listenerInfo =
aListeners->ElementAt(i);
if (listenerInfo.mWeakListener) {
nsCOMPtr<nsISupports> referent =
do_QueryReferent(listenerInfo.mWeakListener);
@ -1779,13 +1788,13 @@ NS_NewChildProcessMessageManager(nsISyncMessageSender** aResult)
static PLDHashOperator
CycleCollectorMarkListeners(const nsAString& aKey,
nsTArray<nsMessageListenerInfo>* aListeners,
nsAutoTObserverArray<nsMessageListenerInfo, 1>* aListeners,
void* aData)
{
uint32_t count = aListeners->Length();
for (uint32_t i = 0; i < count; i++) {
if ((*aListeners)[i].mStrongListener) {
xpc_TryUnmarkWrappedGrayObject((*aListeners)[i].mStrongListener);
if (aListeners->ElementAt(i).mStrongListener) {
xpc_TryUnmarkWrappedGrayObject(aListeners->ElementAt(i).mStrongListener);
}
}
return PL_DHASH_NEXT;

View File

@ -25,6 +25,7 @@
#include "nsWeakPtr.h"
#include "mozilla/Attributes.h"
#include "js/RootingAPI.h"
#include "nsTObserverArray.h"
namespace mozilla {
namespace dom {
@ -114,6 +115,11 @@ class nsAXPCNativeCallContext;
struct nsMessageListenerInfo
{
bool operator==(const nsMessageListenerInfo& aOther) const
{
return &aOther == this;
}
// Exactly one of mStrongListener and mWeakListener must be non-null.
nsCOMPtr<nsIMessageListener> mStrongListener;
nsWeakPtr mWeakListener;
@ -270,7 +276,8 @@ protected:
friend class MMListenerRemover;
// We keep the message listeners as arrays in a hastable indexed by the
// message name. That gives us fast lookups in ReceiveMessage().
nsClassHashtable<nsStringHashKey, nsTArray<nsMessageListenerInfo>> mListeners;
nsClassHashtable<nsStringHashKey,
nsAutoTObserverArray<nsMessageListenerInfo, 1>> mListeners;
nsCOMArray<nsIContentFrameMessageManager> mChildManagers;
bool mChrome; // true if we're in the chrome process
bool mGlobal; // true if we're the global frame message manager

View File

@ -665,6 +665,7 @@ GK_ATOM(oncomplete, "oncomplete")
GK_ATOM(oncompositionend, "oncompositionend")
GK_ATOM(oncompositionstart, "oncompositionstart")
GK_ATOM(oncompositionupdate, "oncompositionupdate")
GK_ATOM(onconnect, "onconnect")
GK_ATOM(onconnected, "onconnected")
GK_ATOM(onconnecting, "onconnecting")
GK_ATOM(oncontextmenu, "oncontextmenu")

View File

@ -4,6 +4,7 @@
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#include "nsDOMMessageEvent.h"
#include "mozilla/dom/MessageEventBinding.h"
#include "mozilla/dom/MessagePort.h"
#include "mozilla/dom/MessagePortBinding.h"
#include "mozilla/dom/MessagePortList.h"
@ -55,6 +56,12 @@ nsDOMMessageEvent::~nsDOMMessageEvent()
mozilla::DropJSObjects(this);
}
JSObject*
nsDOMMessageEvent::WrapObject(JSContext* aCx, JS::Handle<JSObject*> aScope)
{
return mozilla::dom::MessageEventBinding::Wrap(aCx, aScope, this);
}
NS_IMETHODIMP
nsDOMMessageEvent::GetData(JSContext* aCx, JS::Value* aData)
{
@ -148,7 +155,7 @@ nsDOMMessageEvent::Constructor(const mozilla::dom::GlobalObject& aGlobal,
}
if (!event->mWindowSource) {
MessagePort* port = nullptr;
MessagePortBase* port = nullptr;
nsresult rv = UNWRAP_OBJECT(MessagePort, aCx, aParam.mSource, port);
if (NS_FAILED(rv)) {
aRv.Throw(NS_ERROR_INVALID_ARG);
@ -160,7 +167,7 @@ nsDOMMessageEvent::Constructor(const mozilla::dom::GlobalObject& aGlobal,
}
if (aParam.mPorts.WasPassed() && !aParam.mPorts.Value().IsNull()) {
nsTArray<nsRefPtr<MessagePort> > ports;
nsTArray<nsRefPtr<MessagePortBase>> ports;
for (uint32_t i = 0, len = aParam.mPorts.Value().Value().Length(); i < len; ++i) {
ports.AppendElement(aParam.mPorts.Value().Value()[i].get());
}
@ -193,6 +200,13 @@ nsDOMMessageEvent::InitMessageEvent(const nsAString& aType,
return NS_OK;
}
void
nsDOMMessageEvent::SetPorts(mozilla::dom::MessagePortList* aPorts)
{
MOZ_ASSERT(!mPorts && aPorts);
mPorts = aPorts;
}
nsresult
NS_NewDOMMessageEvent(nsIDOMEvent** aInstancePtrResult,
mozilla::dom::EventTarget* aOwner,

View File

@ -9,10 +9,12 @@
#include "nsIDOMMessageEvent.h"
#include "nsDOMEvent.h"
#include "nsCycleCollectionParticipant.h"
#include "mozilla/dom/MessageEventBinding.h"
namespace mozilla {
namespace dom {
class MessageEventInit;
class MessagePort;
class MessagePortBase;
class MessagePortList;
class OwningWindowProxyOrMessagePort;
}
@ -44,10 +46,7 @@ public:
NS_FORWARD_TO_NSDOMEVENT
virtual JSObject* WrapObject(JSContext* aCx,
JS::Handle<JSObject*> aScope) MOZ_OVERRIDE
{
return mozilla::dom::MessageEventBinding::Wrap(aCx, aScope, this);
}
JS::Handle<JSObject*> aScope) MOZ_OVERRIDE;
JS::Value GetData(JSContext* aCx, mozilla::ErrorResult& aRv);
@ -58,6 +57,8 @@ public:
return mPorts;
}
void SetPorts(mozilla::dom::MessagePortList* aPorts);
static already_AddRefed<nsDOMMessageEvent>
Constructor(const mozilla::dom::GlobalObject& aGlobal, JSContext* aCx,
const nsAString& aType,
@ -69,7 +70,7 @@ private:
nsString mOrigin;
nsString mLastEventId;
nsCOMPtr<nsIDOMWindow> mWindowSource;
nsCOMPtr<mozilla::dom::MessagePort> mPortSource;
nsCOMPtr<mozilla::dom::MessagePortBase> mPortSource;
nsRefPtr<mozilla::dom::MessagePortList> mPorts;
};

View File

@ -525,7 +525,8 @@ nsEventListenerManager::ListenerCanHandle(nsListenerStruct* aLs,
}
return aLs->mTypeString.Equals(aEvent->typeString);
}
MOZ_ASSERT(mIsMainThreadELM);
MOZ_ASSERT_IF(aEvent->eventStructType != NS_SCRIPT_ERROR_EVENT,
mIsMainThreadELM);
return aLs->mEventType == aEvent->message;
}
@ -596,6 +597,10 @@ nsEventListenerManager::SetEventHandlerInternal(nsIScriptContext *aContext,
NS_NewJSEventListener(aContext, aScopeObject, mTarget, aName,
aHandler, getter_AddRefs(scriptListener));
if (!aName && aTypeString.EqualsLiteral("error")) {
eventType = NS_LOAD_ERROR;
}
EventListenerHolder holder(scriptListener);
AddEventListenerInternal(holder, eventType, aName, aTypeString, flags,
true);
@ -981,7 +986,11 @@ nsEventListenerManager::HandleEventInternal(nsPresContext* aPresContext,
}
nsAutoTObserverArray<nsListenerStruct, 2>::EndLimitedIterator iter(mListeners);
nsAutoPopupStatePusher popupStatePusher(nsDOMEvent::GetEventPopupControlState(aEvent));
Maybe<nsAutoPopupStatePusher> popupStatePusher;
if (mIsMainThreadELM) {
popupStatePusher.construct(nsDOMEvent::GetEventPopupControlState(aEvent));
}
bool hasListener = false;
while (iter.HasMore()) {
if (aEvent->mFlags.mImmediatePropagationStopped) {
@ -1241,17 +1250,28 @@ nsEventListenerManager::SetEventHandler(nsIAtom* aEventName,
void
nsEventListenerManager::SetEventHandler(OnErrorEventHandlerNonNull* aHandler)
{
if (!aHandler) {
RemoveEventHandler(nsGkAtoms::onerror, EmptyString());
return;
}
if (mIsMainThreadELM) {
if (!aHandler) {
RemoveEventHandler(nsGkAtoms::onerror, EmptyString());
return;
}
// Untrusted events are always permitted for non-chrome script
// handlers.
SetEventHandlerInternal(nullptr, JS::NullPtr(), nsGkAtoms::onerror,
EmptyString(), nsEventHandler(aHandler),
!mIsMainThreadELM ||
!nsContentUtils::IsCallerChrome());
// Untrusted events are always permitted for non-chrome script
// handlers.
SetEventHandlerInternal(nullptr, JS::NullPtr(), nsGkAtoms::onerror,
EmptyString(), nsEventHandler(aHandler),
!nsContentUtils::IsCallerChrome());
} else {
if (!aHandler) {
RemoveEventHandler(nullptr, NS_LITERAL_STRING("error"));
return;
}
// Untrusted events are always permitted.
SetEventHandlerInternal(nullptr, JS::NullPtr(), nullptr,
NS_LITERAL_STRING("error"),
nsEventHandler(aHandler), true);
}
}
void

View File

@ -485,8 +485,12 @@ public:
}
mozilla::dom::OnErrorEventHandlerNonNull* GetOnErrorEventHandler()
{
const nsEventHandler* handler =
GetEventHandlerInternal(nsGkAtoms::onerror, EmptyString());
const nsEventHandler* handler;
if (mIsMainThreadELM) {
handler = GetEventHandlerInternal(nsGkAtoms::onerror, EmptyString());
} else {
handler = GetEventHandlerInternal(nullptr, NS_LITERAL_STRING("onerror"));
}
return handler ? handler->OnErrorEventHandler() : nullptr;
}
mozilla::dom::OnBeforeUnloadEventHandlerNonNull* GetOnBeforeUnloadEventHandler()

View File

@ -62,8 +62,8 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=737851
<pre id="test">
<script type="text/javascript">
var frameElement = document.getElementById("frame");
var frame = frameElement.contentWindow;
var frameElem = document.getElementById("frame");
var frame = frameElem.contentWindow;
/* -- Main test run -- */
@ -73,7 +73,7 @@ SimpleTest.waitForExplicitFinish();
addLoadEvent(function() {
shuffle();
fill();
frameElement.addEventListener("load", function() {
frameElem.addEventListener("load", function() {
shuffle();
checkAllFields();
SimpleTest.finish();

View File

@ -143,9 +143,7 @@ public:
private:
int32_t ObjectAt(int32_t aIndex) {
void* v = nsDeque::ObjectAt(aIndex);
// Ugly hack to work around "casting 64bit void* to 32bit int loses precision"
// error on 64bit Linux.
return *(reinterpret_cast<int32_t*>(&v));
return reinterpret_cast<uintptr_t>(v);
}
};

View File

@ -190,10 +190,14 @@ PostMessageWriteStructuredClone(JSContext* cx,
}
}
MessagePort* port = nullptr;
MessagePortBase* port = nullptr;
nsresult rv = UNWRAP_OBJECT(MessagePort, cx, obj, port);
if (NS_SUCCEEDED(rv)) {
nsRefPtr<MessagePort> newPort = port->Clone();
nsRefPtr<MessagePortBase> newPort = port->Clone();
if (!newPort) {
return false;
}
return JS_WriteUint32Pair(writer, SCTAG_DOM_MESSAGEPORT, 0) &&
JS_WriteBytes(writer, &newPort, sizeof(newPort)) &&
@ -282,6 +286,17 @@ PostMessageRunnable::Run()
return status ? NS_OK : NS_ERROR_FAILURE;
}
MessagePortBase::MessagePortBase(nsPIDOMWindow* aWindow)
: nsDOMEventTargetHelper(aWindow)
{
// SetIsDOMBinding() is called by nsDOMEventTargetHelper's ctor.
}
MessagePortBase::MessagePortBase()
{
SetIsDOMBinding();
}
NS_IMPL_CYCLE_COLLECTION_CLASS(MessagePort)
NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN_INHERITED(MessagePort,
@ -326,16 +341,14 @@ NS_IMPL_ADDREF_INHERITED(MessagePort, nsDOMEventTargetHelper)
NS_IMPL_RELEASE_INHERITED(MessagePort, nsDOMEventTargetHelper)
MessagePort::MessagePort(nsPIDOMWindow* aWindow)
: nsDOMEventTargetHelper(aWindow)
: MessagePortBase(aWindow)
, mMessageQueueEnabled(false)
{
MOZ_COUNT_CTOR(MessagePort);
SetIsDOMBinding();
}
MessagePort::~MessagePort()
{
MOZ_COUNT_DTOR(MessagePort);
Close();
}
@ -346,9 +359,9 @@ MessagePort::WrapObject(JSContext* aCx, JS::Handle<JSObject*> aScope)
}
void
MessagePort::PostMessage(JSContext* aCx, JS::Handle<JS::Value> aMessage,
const Optional<JS::Handle<JS::Value> >& aTransfer,
ErrorResult& aRv)
MessagePort::PostMessageMoz(JSContext* aCx, JS::Handle<JS::Value> aMessage,
const Optional<Sequence<JS::Value>>& aTransferable,
ErrorResult& aRv)
{
nsRefPtr<PostMessageRunnable> event = new PostMessageRunnable();
@ -359,9 +372,18 @@ MessagePort::PostMessage(JSContext* aCx, JS::Handle<JS::Value> aMessage,
scInfo.mEvent = event;
scInfo.mPort = this;
JS::Handle<JS::Value> transferable = aTransfer.WasPassed()
? aTransfer.Value()
: JS::UndefinedHandleValue;
JS::Rooted<JS::Value> transferable(aCx, JS::UndefinedValue());
if (aTransferable.WasPassed()) {
const Sequence<JS::Value>& realTransferable = aTransferable.Value();
JSObject* array =
JS_NewArrayObject(aCx, realTransferable.Length(),
const_cast<JS::Value*>(realTransferable.Elements()));
if (!array) {
aRv.Throw(NS_ERROR_OUT_OF_MEMORY);
return;
}
transferable.setObject(*array);
}
if (!buffer.write(aCx, aMessage, transferable, &kPostMessageCallbacks,
&scInfo)) {
@ -454,7 +476,7 @@ MessagePort::Entangle(MessagePort* aMessagePort)
mEntangledPort = aMessagePort;
}
already_AddRefed<MessagePort>
already_AddRefed<MessagePortBase>
MessagePort::Clone()
{
nsRefPtr<MessagePort> newPort = new MessagePort(nullptr);

View File

@ -7,7 +7,6 @@
#define mozilla_dom_MessagePort_h
#include "mozilla/Attributes.h"
#include "mozilla/ErrorResult.h"
#include "nsDOMEventTargetHelper.h"
class nsPIDOMWindow;
@ -18,14 +17,47 @@ namespace dom {
class DispatchEventRunnable;
class PostMessageRunnable;
class MessagePort MOZ_FINAL : public nsDOMEventTargetHelper
class MessagePortBase : public nsDOMEventTargetHelper
{
protected:
MessagePortBase(nsPIDOMWindow* aWindow);
MessagePortBase();
public:
virtual void
PostMessageMoz(JSContext* aCx, JS::Handle<JS::Value> aMessage,
const Optional<Sequence<JS::Value>>& aTransferable,
ErrorResult& aRv) = 0;
virtual void
Start() = 0;
virtual void
Close() = 0;
// The 'message' event handler has to call |Start()| method, so we
// cannot use IMPL_EVENT_HANDLER macro here.
virtual EventHandlerNonNull*
GetOnmessage() = 0;
virtual void
SetOnmessage(EventHandlerNonNull* aCallback) = 0;
// Duplicate this message port. This method is used by the Structured Clone
// Algorithm and makes the new MessagePort active with the entangled
// MessagePort of this object.
virtual already_AddRefed<MessagePortBase>
Clone() = 0;
};
class MessagePort MOZ_FINAL : public MessagePortBase
{
friend class DispatchEventRunnable;
friend class PostMessageRunnable;
public:
NS_DECL_ISUPPORTS_INHERITED
NS_REALLY_FORWARD_NSIDOMEVENTTARGET(nsDOMEventTargetHelper)
NS_DECL_CYCLE_COLLECTION_CLASS_INHERITED(MessagePort,
nsDOMEventTargetHelper)
@ -35,24 +67,22 @@ public:
virtual JSObject*
WrapObject(JSContext* aCx, JS::Handle<JSObject*> aScope) MOZ_OVERRIDE;
void
PostMessage(JSContext* aCx, JS::Handle<JS::Value> aMessage,
const Optional<JS::Handle<JS::Value> >& aTransfer,
ErrorResult& aRv);
virtual void
PostMessageMoz(JSContext* aCx, JS::Handle<JS::Value> aMessage,
const Optional<Sequence<JS::Value>>& aTransferable,
ErrorResult& aRv) MOZ_OVERRIDE;
void
Start();
virtual void
Start() MOZ_OVERRIDE;
void
Close();
virtual void
Close() MOZ_OVERRIDE;
// The 'message' event handler has to call |Start()| method, so we
// cannot use IMPL_EVENT_HANDLER macro here.
EventHandlerNonNull*
GetOnmessage();
virtual EventHandlerNonNull*
GetOnmessage() MOZ_OVERRIDE;
void
SetOnmessage(EventHandlerNonNull* aCallback);
virtual void
SetOnmessage(EventHandlerNonNull* aCallback) MOZ_OVERRIDE;
// Non WebIDL methods
@ -62,11 +92,8 @@ public:
void
Entangle(MessagePort* aMessagePort);
// Duplicate this message port. This method is used by the Structured Clone
// Algorithm and makes the new MessagePort active with the entangled
// MessagePort of this object.
already_AddRefed<MessagePort>
Clone();
virtual already_AddRefed<MessagePortBase>
Clone() MOZ_OVERRIDE;
private:
// Dispatch events from the Message Queue using a nsRunnable.

View File

@ -26,7 +26,7 @@ public:
NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_CLASS(MessagePortList)
public:
MessagePortList(nsISupports* aOwner, nsTArray<nsRefPtr<MessagePort> >& aPorts)
MessagePortList(nsISupports* aOwner, nsTArray<nsRefPtr<MessagePortBase>>& aPorts)
: mOwner(aOwner)
, mPorts(aPorts)
{
@ -48,13 +48,13 @@ public:
return mPorts.Length();
}
MessagePort*
MessagePortBase*
Item(uint32_t aIndex)
{
return mPorts.SafeElementAt(aIndex);
}
MessagePort*
MessagePortBase*
IndexedGetter(uint32_t aIndex, bool &aFound)
{
aFound = aIndex < mPorts.Length();
@ -66,7 +66,7 @@ public:
public:
nsCOMPtr<nsISupports> mOwner;
nsTArray<nsRefPtr<MessagePort> > mPorts;
nsTArray<nsRefPtr<MessagePortBase>> mPorts;
};
} // namespace dom

View File

@ -141,9 +141,6 @@
// Drag and drop
#include "nsIDOMDataTransfer.h"
// Workers
#include "mozilla/dom/workers/Workers.h"
#include "nsIDOMFile.h"
#include "nsDOMBlobBuilder.h" // nsDOMMultipartFile
@ -187,6 +184,8 @@
#include "mozilla/Likely.h"
#include "WindowNamedPropertiesHandler.h"
#include "nsIInterfaceInfoManager.h"
#include "mozilla/dom/EventTargetBinding.h"
#include "mozilla/dom/WindowBinding.h"
#ifdef MOZ_TIME_MANAGER
#include "TimeManager.h"
@ -194,7 +193,6 @@
using namespace mozilla;
using namespace mozilla::dom;
using mozilla::dom::workers::ResolveWorkerClasses;
static NS_DEFINE_CID(kDOMSOF_CID, NS_DOM_SCRIPT_OBJECT_FACTORY_CID);
@ -203,6 +201,7 @@ static NS_DEFINE_CID(kDOMSOF_CID, NS_DOM_SCRIPT_OBJECT_FACTORY_CID);
#define WINDOW_SCRIPTABLE_FLAGS \
(nsIXPCScriptable::WANT_PRECREATE | \
nsIXPCScriptable::WANT_POSTCREATE | \
nsIXPCScriptable::WANT_FINALIZE | \
nsIXPCScriptable::WANT_ENUMERATE | \
nsIXPCScriptable::DONT_ENUM_QUERY_INTERFACE | \
@ -585,30 +584,15 @@ nsIScriptSecurityManager *nsDOMClassInfo::sSecMan = nullptr;
bool nsDOMClassInfo::sIsInitialized = false;
jsid nsDOMClassInfo::sParent_id = JSID_VOID;
jsid nsDOMClassInfo::sScrollbars_id = JSID_VOID;
jsid nsDOMClassInfo::sLocation_id = JSID_VOID;
jsid nsDOMClassInfo::sConstructor_id = JSID_VOID;
jsid nsDOMClassInfo::s_content_id = JSID_VOID;
jsid nsDOMClassInfo::sContent_id = JSID_VOID;
jsid nsDOMClassInfo::sMenubar_id = JSID_VOID;
jsid nsDOMClassInfo::sToolbar_id = JSID_VOID;
jsid nsDOMClassInfo::sLocationbar_id = JSID_VOID;
jsid nsDOMClassInfo::sPersonalbar_id = JSID_VOID;
jsid nsDOMClassInfo::sStatusbar_id = JSID_VOID;
jsid nsDOMClassInfo::sControllers_id = JSID_VOID;
jsid nsDOMClassInfo::sLength_id = JSID_VOID;
jsid nsDOMClassInfo::sScrollX_id = JSID_VOID;
jsid nsDOMClassInfo::sScrollY_id = JSID_VOID;
jsid nsDOMClassInfo::sScrollMaxX_id = JSID_VOID;
jsid nsDOMClassInfo::sScrollMaxY_id = JSID_VOID;
jsid nsDOMClassInfo::sItem_id = JSID_VOID;
jsid nsDOMClassInfo::sNamedItem_id = JSID_VOID;
jsid nsDOMClassInfo::sEnumerate_id = JSID_VOID;
jsid nsDOMClassInfo::sTop_id = JSID_VOID;
jsid nsDOMClassInfo::sDocument_id = JSID_VOID;
jsid nsDOMClassInfo::sFrames_id = JSID_VOID;
jsid nsDOMClassInfo::sSelf_id = JSID_VOID;
jsid nsDOMClassInfo::sWrappedJSObject_id = JSID_VOID;
static const JSClass *sObjectClass = nullptr;
@ -733,30 +717,15 @@ nsDOMClassInfo::DefineStaticJSVals(JSContext *cx)
else \
return NS_ERROR_OUT_OF_MEMORY;
SET_JSID_TO_STRING(sParent_id, cx, "parent");
SET_JSID_TO_STRING(sScrollbars_id, cx, "scrollbars");
SET_JSID_TO_STRING(sLocation_id, cx, "location");
SET_JSID_TO_STRING(sConstructor_id, cx, "constructor");
SET_JSID_TO_STRING(s_content_id, cx, "_content");
SET_JSID_TO_STRING(sContent_id, cx, "content");
SET_JSID_TO_STRING(sMenubar_id, cx, "menubar");
SET_JSID_TO_STRING(sToolbar_id, cx, "toolbar");
SET_JSID_TO_STRING(sLocationbar_id, cx, "locationbar");
SET_JSID_TO_STRING(sPersonalbar_id, cx, "personalbar");
SET_JSID_TO_STRING(sStatusbar_id, cx, "statusbar");
SET_JSID_TO_STRING(sControllers_id, cx, "controllers");
SET_JSID_TO_STRING(sLength_id, cx, "length");
SET_JSID_TO_STRING(sScrollX_id, cx, "scrollX");
SET_JSID_TO_STRING(sScrollY_id, cx, "scrollY");
SET_JSID_TO_STRING(sScrollMaxX_id, cx, "scrollMaxX");
SET_JSID_TO_STRING(sScrollMaxY_id, cx, "scrollMaxY");
SET_JSID_TO_STRING(sItem_id, cx, "item");
SET_JSID_TO_STRING(sNamedItem_id, cx, "namedItem");
SET_JSID_TO_STRING(sEnumerate_id, cx, "enumerateProperties");
SET_JSID_TO_STRING(sTop_id, cx, "top");
SET_JSID_TO_STRING(sDocument_id, cx, "document");
SET_JSID_TO_STRING(sFrames_id, cx, "frames");
SET_JSID_TO_STRING(sSelf_id, cx, "self");
SET_JSID_TO_STRING(sWrappedJSObject_id, cx, "wrappedJSObject");
return NS_OK;
@ -2001,29 +1970,14 @@ nsDOMClassInfo::ShutDown()
}
}
sParent_id = JSID_VOID;
sScrollbars_id = JSID_VOID;
sLocation_id = JSID_VOID;
sConstructor_id = JSID_VOID;
s_content_id = JSID_VOID;
sContent_id = JSID_VOID;
sMenubar_id = JSID_VOID;
sToolbar_id = JSID_VOID;
sLocationbar_id = JSID_VOID;
sPersonalbar_id = JSID_VOID;
sStatusbar_id = JSID_VOID;
sControllers_id = JSID_VOID;
sLength_id = JSID_VOID;
sScrollX_id = JSID_VOID;
sScrollY_id = JSID_VOID;
sScrollMaxX_id = JSID_VOID;
sScrollMaxY_id = JSID_VOID;
sItem_id = JSID_VOID;
sEnumerate_id = JSID_VOID;
sTop_id = JSID_VOID;
sDocument_id = JSID_VOID;
sFrames_id = JSID_VOID;
sSelf_id = JSID_VOID;
sWrappedJSObject_id = JSID_VOID;
NS_IF_RELEASE(sXPConnect);
@ -2080,6 +2034,28 @@ nsWindowSH::PostCreatePrototype(JSContext* aCx, JSObject* aProto)
return NS_OK;
}
NS_IMETHODIMP
nsWindowSH::PostCreate(nsIXPConnectWrappedNative *wrapper,
JSContext *cx, JSObject *obj)
{
#ifdef DEBUG
nsCOMPtr<nsIScriptGlobalObject> sgo(do_QueryWrappedNative(wrapper));
NS_ASSERTION(sgo && sgo->GetGlobalJSObject() == nullptr,
"Multiple wrappers created for global object!");
#endif
const NativeProperties* windowProperties =
WindowBinding::sNativePropertyHooks->mNativeProperties.regular;
const NativeProperties* eventTargetProperties =
EventTargetBinding::sNativePropertyHooks->mNativeProperties.regular;
JS::Rooted<JSObject*> window(cx, obj);
return DefineWebIDLBindingPropertiesOnXPCObject(cx, window, windowProperties, true) &&
DefineWebIDLBindingPropertiesOnXPCObject(cx, window, eventTargetProperties, true) ?
NS_OK : NS_ERROR_FAILURE;
}
static nsHTMLDocument*
GetDocument(JSObject *obj)
{
@ -3605,21 +3581,6 @@ nsWindowSH::NewResolve(nsIXPConnectWrappedNative *wrapper, JSContext *cx,
return NS_OK;
}
// Handle resolving if id refers to a name resolved by DOM worker code.
JS::Rooted<JSObject*> tmp(cx, nullptr);
if (!ResolveWorkerClasses(cx, obj, id, flags, &tmp)) {
return NS_ERROR_FAILURE;
}
if (tmp) {
*objp = tmp;
return NS_OK;
}
// Check for names managed by the script namespace manager. Call
// GlobalResolve() after we call FindChildWithName() so that named child
// frames will override external properties which have been registered with
// the script namespace manager -- pages must be able to depend on frame
// names working no matter how Gecko's been configured.
bool did_resolve = false;
nsresult rv = GlobalResolve(win, cx, obj, id, &did_resolve);
NS_ENSURE_SUCCESS(rv, rv);
@ -3658,23 +3619,8 @@ nsWindowSH::NewResolve(nsIXPConnectWrappedNative *wrapper, JSContext *cx,
return NS_OK;
}
if (flags & JSRESOLVE_ASSIGNING) {
if (IsReadonlyReplaceable(id)) {
// A readonly "replaceable" property is being set. Define the property
// on obj with the value undefined to override the predefined property.
// This isn't quite what WebIDL requires for [Replaceable] properties,
// but it'll do until we move Window over to the new DOM bindings.
if (!::JS_DefinePropertyById(cx, obj, id, JSVAL_VOID, JS_PropertyStub,
JS_StrictPropertyStub, JSPROP_ENUMERATE)) {
return NS_ERROR_FAILURE;
}
*objp = obj;
return NS_OK;
}
} else {
if (sDocument_id == id) {
if (!(flags & JSRESOLVE_ASSIGNING) && sDocument_id == id) {
if (xpc::WrapperFactory::IsXrayWrapper(obj)) {
nsCOMPtr<nsIDocument> document = win->GetDoc();
JS::Rooted<JS::Value> v(cx);
nsCOMPtr<nsIXPConnectJSObjectHolder> holder;
@ -3683,26 +3629,18 @@ nsWindowSH::NewResolve(nsIXPConnectWrappedNative *wrapper, JSContext *cx,
false);
NS_ENSURE_SUCCESS(rv, rv);
// The PostCreate hook for the document will handle defining the
// property
*objp = obj;
// NB: We need to do this for any Xray wrapper.
if (xpc::WrapperFactory::IsXrayWrapper(obj)) {
// Unless our object is a native wrapper, in which case we have to
// define it ourselves.
*_retval = JS_WrapValue(cx, &v) &&
JS_DefineProperty(cx, obj, "document", v,
JS_PropertyStub, JS_StrictPropertyStub,
JSPROP_READONLY | JSPROP_ENUMERATE);
if (!*_retval) {
return NS_ERROR_UNEXPECTED;
}
*_retval = JS_WrapValue(cx, &v) &&
JS_DefineProperty(cx, obj, "document", v,
JS_PropertyStub, JS_StrictPropertyStub,
JSPROP_READONLY | JSPROP_ENUMERATE);
if (!*_retval) {
return NS_ERROR_UNEXPECTED;
}
return NS_OK;
}
return NS_OK;
}
return nsDOMGenericSH::NewResolve(wrapper, cx, obj, id, flags, objp,

View File

@ -154,26 +154,6 @@ protected:
static int32_t GetArrayIndexFromId(JSContext *cx, JS::Handle<jsid> id,
bool *aIsNumber = nullptr);
static inline bool IsReadonlyReplaceable(jsid id)
{
return (id == sParent_id ||
id == sScrollbars_id ||
id == sContent_id ||
id == sMenubar_id ||
id == sToolbar_id ||
id == sLocationbar_id ||
id == sPersonalbar_id ||
id == sStatusbar_id ||
id == sControllers_id ||
id == sScrollX_id ||
id == sScrollY_id ||
id == sScrollMaxX_id ||
id == sScrollMaxY_id ||
id == sLength_id ||
id == sFrames_id ||
id == sSelf_id);
}
static nsIXPConnect *sXPConnect;
static nsIScriptSecurityManager *sSecMan;
@ -183,31 +163,15 @@ protected:
static bool sIsInitialized;
public:
static jsid sParent_id;
static jsid sScrollbars_id;
static jsid sLocation_id;
static jsid sConstructor_id;
static jsid s_content_id;
static jsid sContent_id;
static jsid sMenubar_id;
static jsid sToolbar_id;
static jsid sLocationbar_id;
static jsid sPersonalbar_id;
static jsid sStatusbar_id;
static jsid sControllers_id;
static jsid sLength_id;
static jsid sScrollX_id;
static jsid sScrollY_id;
static jsid sScrollMaxX_id;
static jsid sScrollMaxY_id;
static jsid sItem_id;
static jsid sNamedItem_id;
static jsid sEnumerate_id;
static jsid sTop_id;
static jsid sDocument_id;
static jsid sFrames_id;
static jsid sSelf_id;
static jsid sJava_id;
static jsid sWrappedJSObject_id;
};
@ -299,23 +263,8 @@ public:
NS_IMETHOD PreCreate(nsISupports *nativeObj, JSContext *cx,
JSObject *globalObj, JSObject **parentObj) MOZ_OVERRIDE;
NS_IMETHOD PostCreatePrototype(JSContext * cx, JSObject * proto) MOZ_OVERRIDE;
#ifdef DEBUG
NS_IMETHOD PostCreate(nsIXPConnectWrappedNative *wrapper, JSContext *cx,
JSObject *obj) MOZ_OVERRIDE
{
nsCOMPtr<nsIScriptGlobalObject> sgo(do_QueryWrappedNative(wrapper));
NS_ASSERTION(!sgo || sgo->GetGlobalJSObject() == nullptr,
"Multiple wrappers created for global object!");
return NS_OK;
}
virtual uint32_t GetScriptableFlags() MOZ_OVERRIDE
{
return nsDOMGenericSH::GetScriptableFlags() |
nsIXPCScriptable::WANT_POSTCREATE;
}
#endif
JSObject *obj) MOZ_OVERRIDE;
NS_IMETHOD Enumerate(nsIXPConnectWrappedNative *wrapper, JSContext *cx,
JSObject *obj, bool *_retval) MOZ_OVERRIDE;
NS_IMETHOD NewResolve(nsIXPConnectWrappedNative *wrapper, JSContext *cx,

View File

@ -56,6 +56,7 @@
#include "mozilla/dom/workers/Workers.h"
#include "nsJSPrincipals.h"
#include "mozilla/Attributes.h"
#include "mozilla/Debug.h"
#include "mozilla/MouseEvents.h"
// Interfaces Needed
@ -64,19 +65,7 @@
#include "nsIWidget.h"
#include "nsIWidgetListener.h"
#include "nsIBaseWindow.h"
#include "nsDeviceSensors.h"
#ifdef XP_WIN
// Thanks so much, Microsoft and the people who pull in windows.h via
// random silly headers! :(
#ifdef GetClassName
#undef GetClassName
#endif // GetClassName
#ifdef CreateEvent
#undef CreateEvent
#endif
#endif // XP_WIN
#include "nsIDeviceSensors.h"
#include "nsIContent.h"
#include "nsIDocShell.h"
#include "nsIDocCharset.h"
@ -183,7 +172,6 @@
#include "GeneratedEvents.h"
#include "GeneratedEventClasses.h"
#include "mozIThirdPartyUtil.h"
#ifdef MOZ_LOGGING
// so we can get logging even in release builds
#define FORCE_PR_LOG 1
@ -219,7 +207,7 @@
#include "mozilla/dom/BrowserElementDictionariesBinding.h"
#include "mozilla/dom/FunctionBinding.h"
#include "mozilla/dom/WindowBinding.h"
#include "mozilla/dom/TabChild.h"
#include "nsITabChild.h"
#include "nsIDOMMediaQueryList.h"
#ifdef MOZ_WEBSPEECH
@ -1509,7 +1497,6 @@ nsGlobalWindow::FreeInnerObjects()
}
// Remove our reference to the document and the document principal.
mDoc = nullptr;
mFocusedNode = nullptr;
if (mApplicationCache) {
@ -1958,6 +1945,8 @@ nsGlobalWindow::SetInitialPrincipalToSubject()
PopupControlState
PushPopupControlState(PopupControlState aState, bool aForce)
{
MOZ_ASSERT(NS_IsMainThread());
PopupControlState oldState = gPopupControlState;
if (aState < gPopupControlState || aForce) {
@ -1970,6 +1959,8 @@ PushPopupControlState(PopupControlState aState, bool aForce)
void
PopPopupControlState(PopupControlState aState)
{
MOZ_ASSERT(NS_IsMainThread());
gPopupControlState = aState;
}
@ -1989,6 +1980,7 @@ nsGlobalWindow::PopPopupControlState(PopupControlState aState) const
PopupControlState
nsGlobalWindow::GetPopupControlState() const
{
MOZ_ASSERT(NS_IsMainThread());
return gPopupControlState;
}
@ -5680,9 +5672,7 @@ nsGlobalWindow::Dump(const nsAString& aStr)
if (cstr) {
#ifdef XP_WIN
if (IsDebuggerPresent()) {
OutputDebugStringA(cstr);
}
PrintToDebugger(cstr);
#endif
#ifdef ANDROID
__android_log_write(ANDROID_LOG_INFO, "GeckoDump", cstr);
@ -6229,7 +6219,7 @@ nsGlobalWindow::Focus(ErrorResult& aError)
}
return;
}
if (TabChild *child = TabChild::GetFrom(this)) {
if (nsCOMPtr<nsITabChild> child = do_GetInterface(mDocShell)) {
child->SendRequestFocus(canFocus);
return;
}
@ -7486,7 +7476,7 @@ PostMessageReadStructuredClone(JSContext* cx,
if (MessageChannel::PrefEnabled() && tag == SCTAG_DOM_MESSAGEPORT) {
NS_ASSERTION(!data, "Data should be empty");
MessagePort* port;
MessagePortBase* port;
if (JS_ReadBytes(reader, &port, sizeof(port))) {
JS::Rooted<JSObject*> global(cx, JS::CurrentGlobalOrNull(cx));
if (global) {
@ -7540,10 +7530,14 @@ PostMessageWriteStructuredClone(JSContext* cx,
}
if (MessageChannel::PrefEnabled()) {
MessagePort* port = nullptr;
MessagePortBase* port = nullptr;
nsresult rv = UNWRAP_OBJECT(MessagePort, cx, obj, port);
if (NS_SUCCEEDED(rv) && scInfo->subsumes) {
nsRefPtr<MessagePort> newPort = port->Clone();
nsRefPtr<MessagePortBase> newPort = port->Clone();
if (!newPort) {
return false;
}
return JS_WriteUint32Pair(writer, SCTAG_DOM_MESSAGEPORT, 0) &&
JS_WriteBytes(writer, &newPort, sizeof(newPort)) &&
@ -8911,6 +8905,9 @@ NS_IMPL_REMOVE_SYSTEM_EVENT_LISTENER(nsGlobalWindow)
NS_IMETHODIMP
nsGlobalWindow::DispatchEvent(nsIDOMEvent* aEvent, bool* aRetVal)
{
MOZ_ASSERT(!IsInnerWindow() || IsCurrentInnerWindow(),
"We should only fire events on the current inner window.");
FORWARD_TO_INNER(DispatchEvent, (aEvent, aRetVal), NS_OK);
if (!mDoc) {
@ -9040,10 +9037,7 @@ nsIScriptContext*
nsGlobalWindow::GetContextForEventHandlers(nsresult* aRv)
{
*aRv = NS_ERROR_UNEXPECTED;
if (IsInnerWindow()) {
nsPIDOMWindow* outer = GetOuterWindow();
NS_ENSURE_TRUE(outer && outer->GetCurrentInnerWindow() == this, nullptr);
}
NS_ENSURE_TRUE(!IsInnerWindow() || IsCurrentInnerWindow(), nullptr);
nsIScriptContext* scx;
if ((scx = GetContext())) {
@ -9563,7 +9557,7 @@ nsGlobalWindow::FireHashchange(const nsAString &aOldURL,
return NS_OK;
// Get a presentation shell for use in creating the hashchange event.
NS_ENSURE_STATE(mDoc);
NS_ENSURE_STATE(IsCurrentInnerWindow());
nsIPresShell *shell = mDoc->GetShell();
nsRefPtr<nsPresContext> presContext;
@ -10120,7 +10114,7 @@ nsGlobalWindow::GetInterface(const nsIID & aIID, void **aSink)
void
nsGlobalWindow::FireOfflineStatusEvent()
{
if (!mDoc)
if (!IsCurrentInnerWindow())
return;
nsAutoString name;
if (NS_IsOffline()) {
@ -10699,7 +10693,7 @@ nsGlobalWindow::Observe(nsISupports* aSubject, const char* aTopic,
// need to fire only one idle event while the window is frozen.
mNotifyIdleObserversIdleOnThaw = true;
mNotifyIdleObserversActiveOnThaw = false;
} else if (mOuterWindow && mOuterWindow->GetCurrentInnerWindow() == this) {
} else if (IsCurrentInnerWindow()) {
HandleIdleActiveEvent();
}
return NS_OK;
@ -10710,13 +10704,17 @@ nsGlobalWindow::Observe(nsISupports* aSubject, const char* aTopic,
if (IsFrozen()) {
mNotifyIdleObserversActiveOnThaw = true;
mNotifyIdleObserversIdleOnThaw = false;
} else if (mOuterWindow && mOuterWindow->GetCurrentInnerWindow() == this) {
} else if (IsCurrentInnerWindow()) {
ScheduleActiveTimerCallback();
}
return NS_OK;
}
if (IsInnerWindow() && !nsCRT::strcmp(aTopic, "dom-storage2-changed")) {
if (!nsCRT::strcmp(aTopic, "dom-storage2-changed")) {
if (!IsInnerWindow() || !IsCurrentInnerWindow()) {
return NS_OK;
}
nsIPrincipal *principal;
nsresult rv;
@ -10838,6 +10836,11 @@ nsGlobalWindow::Observe(nsISupports* aSubject, const char* aTopic,
#ifdef MOZ_B2G
if (!nsCRT::strcmp(aTopic, NS_NETWORK_ACTIVITY_BLIP_UPLOAD_TOPIC) ||
!nsCRT::strcmp(aTopic, NS_NETWORK_ACTIVITY_BLIP_DOWNLOAD_TOPIC)) {
MOZ_ASSERT(IsInnerWindow());
if (!IsCurrentInnerWindow()) {
return NS_OK;
}
nsCOMPtr<nsIDOMEvent> event;
NS_NewDOMEvent(getter_AddRefs(event), this, nullptr, nullptr);
nsresult rv = event->InitEvent(
@ -12556,13 +12559,13 @@ nsGlobalWindow::SetHasGamepadEventListener(bool aHasGamepad/* = true*/)
void
nsGlobalWindow::EnableTimeChangeNotifications()
{
nsSystemTimeChangeObserver::AddWindowListener(this);
mozilla::time::AddWindowListener(this);
}
void
nsGlobalWindow::DisableTimeChangeNotifications()
{
nsSystemTimeChangeObserver::RemoveWindowListener(this);
mozilla::time::RemoveWindowListener(this);
}
static PLDHashOperator
@ -13204,3 +13207,7 @@ nsGlobalWindow::DisableNetworkEvent(uint32_t aType)
#undef BEFOREUNLOAD_EVENT
#undef ERROR_EVENT
#undef EVENT
#ifdef _WINDOWS_
#error "Never include windows.h in this file!"
#endif

View File

@ -327,6 +327,15 @@ public:
return mIsInnerWindow;
}
// Returns true if this object has an outer window and it is the current inner
// window of that outer. Only call this on inner windows.
bool IsCurrentInnerWindow() const
{
MOZ_ASSERT(IsInnerWindow(),
"It doesn't make sense to call this on outer windows.");
return mOuterWindow && mOuterWindow->GetCurrentInnerWindow() == this;
}
bool IsOuterWindow() const
{
return !IsInnerWindow();

View File

@ -15,16 +15,6 @@
struct JSTracer;
class XPCWrappedNativeScope;
namespace mozilla {
namespace dom {
namespace workers {
class DOMBindingBase;
} // namespace workers
} // namespace dom
} // namespace mozilla
#define NS_WRAPPERCACHE_IID \
{ 0x6f3179a1, 0x36f7, 0x4a5c, \
{ 0x8c, 0xf1, 0xad, 0xc8, 0x7c, 0xde, 0x3e, 0x87 } }
@ -60,8 +50,6 @@ class DOMBindingBase;
*/
class nsWrapperCache
{
friend class mozilla::dom::workers::DOMBindingBase;
public:
NS_DECLARE_STATIC_IID_ACCESSOR(NS_WRAPPERCACHE_IID)

View File

@ -24,12 +24,6 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=677638
} catch(e) {
ok(!what, "Should MessageChannel exist?");
}
try {
status = MessagePort;
ok(what, "Should MessagePort exist?");
} catch(e) {
ok(!what, "Should MessagePort exist?");
}
}
SimpleTest.waitForExplicitFinish();

View File

@ -532,17 +532,23 @@ CreateInterfaceObject(JSContext* cx, JS::Handle<JSObject*> global,
}
bool
DefineWebIDLBindingPropertiesOnXPCProto(JSContext* cx,
JS::Handle<JSObject*> proto,
const NativeProperties* properties)
DefineWebIDLBindingPropertiesOnXPCObject(JSContext* cx,
JS::Handle<JSObject*> obj,
const NativeProperties* properties,
bool defineUnforgeableAttributes)
{
if (properties->methods &&
!DefinePrefable(cx, proto, properties->methods)) {
!DefinePrefable(cx, obj, properties->methods)) {
return false;
}
if (properties->attributes &&
!DefinePrefable(cx, proto, properties->attributes)) {
!DefinePrefable(cx, obj, properties->attributes)) {
return false;
}
if (defineUnforgeableAttributes && properties->unforgeableAttributes &&
!DefinePrefable(cx, obj, properties->unforgeableAttributes)) {
return false;
}
@ -2147,11 +2153,39 @@ ConvertJSValueToByteString(JSContext* cx, JS::Handle<JS::Value> v,
}
bool
ThreadsafeCheckIsChrome(JSContext* aCx, JSObject* aObj) {
ThreadsafeCheckIsChrome(JSContext* aCx, JSObject* aObj)
{
using mozilla::dom::workers::GetWorkerPrivateFromContext;
return NS_IsMainThread() ? xpc::AccessCheck::isChrome(aObj):
GetWorkerPrivateFromContext(aCx)->IsChromeWorker();
}
void
TraceGlobal(JSTracer* aTrc, JSObject* aObj)
{
MOZ_ASSERT(js::GetObjectClass(aObj)->flags & JSCLASS_DOM_GLOBAL);
mozilla::dom::TraceProtoAndIfaceCache(aTrc, aObj);
}
bool
ResolveGlobal(JSContext* aCx, JS::Handle<JSObject*> aObj,
JS::MutableHandle<jsid> aId, unsigned aFlags,
JS::MutableHandle<JSObject*> aObjp)
{
bool resolved;
if (!JS_ResolveStandardClass(aCx, aObj, aId, &resolved)) {
return false;
}
aObjp.set(resolved ? aObj.get() : nullptr);
return true;
}
bool
EnumerateGlobal(JSContext* aCx, JS::Handle<JSObject*> aObj)
{
return JS_EnumerateStandardClasses(aCx, aObj);
}
} // namespace dom
} // namespace mozilla

View File

@ -401,9 +401,10 @@ DefineUnforgeableAttributes(JSContext* cx, JS::Handle<JSObject*> obj,
const Prefable<const JSPropertySpec>* props);
bool
DefineWebIDLBindingPropertiesOnXPCProto(JSContext* cx,
JS::Handle<JSObject*> proto,
const NativeProperties* properties);
DefineWebIDLBindingPropertiesOnXPCObject(JSContext* cx,
JS::Handle<JSObject*> obj,
const NativeProperties* properties,
bool defineUnforgeableAttributes);
#ifdef _MSC_VER
#define HAS_MEMBER_CHECK(_name) \
@ -2269,6 +2270,62 @@ public:
bool
ThreadsafeCheckIsChrome(JSContext* aCx, JSObject* aObj);
void
TraceGlobal(JSTracer* aTrc, JSObject* aObj);
bool
ResolveGlobal(JSContext* aCx, JS::Handle<JSObject*> aObj,
JS::MutableHandle<jsid> aId, unsigned aFlags,
JS::MutableHandle<JSObject*> aObjp);
bool
EnumerateGlobal(JSContext* aCx, JS::Handle<JSObject*> aObj);
template <class T, JS::Handle<JSObject*> (*ProtoGetter)(JSContext*,
JS::Handle<JSObject*>)>
JSObject*
CreateGlobal(JSContext* aCx, T* aObject, nsWrapperCache* aCache,
const JSClass* aClass, JS::CompartmentOptions& aOptions,
JSPrincipals* aPrincipal)
{
MOZ_ASSERT(!NS_IsMainThread());
JS::Rooted<JSObject*> global(aCx,
JS_NewGlobalObject(aCx, aClass, aPrincipal, JS::DontFireOnNewGlobalHook,
aOptions));
if (!global) {
NS_WARNING("Failed to create global");
return nullptr;
}
JSAutoCompartment ac(aCx, global);
dom::AllocateProtoAndIfaceCache(global);
js::SetReservedSlot(global, DOM_OBJECT_SLOT, PRIVATE_TO_JSVAL(aObject));
NS_ADDREF(aObject);
aCache->SetIsDOMBinding();
aCache->SetWrapper(global);
/* Intl API is broken and makes this fail intermittently, see bug 934889.
if (!JS_InitStandardClasses(aCx, global)) {
NS_WARNING("Failed to init standard classes");
return nullptr;
}
*/
JS::Handle<JSObject*> proto = ProtoGetter(aCx, global);
NS_ENSURE_TRUE(proto, nullptr);
if (!JS_SetPrototype(aCx, global, proto)) {
NS_WARNING("Failed to set proto");
return nullptr;
}
return global;
}
} // namespace dom
} // namespace mozilla

View File

@ -29,6 +29,9 @@
# will not be made available on the main thread.
# * customFinalize - The native class will use a custom finalize hook
# (defaults to true for workers, false otherwise).
# * customWrapperManagement - The native class will be responsible for
# preserving its own wrapper (no AddProperty
# hook will be generated, defaults to false).
# * notflattened - The native type does not have nsIClassInfo, so when
# wrapping it the right IID needs to be passed in.
# * register - True if this binding should be registered. Defaults to true.
@ -201,6 +204,13 @@ DOMInterfaces = {
'concrete': False
},
'ChromeWorker': {
'headerFile': 'mozilla/dom/WorkerPrivate.h',
'nativeType': 'mozilla::dom::workers::ChromeWorkerPrivate',
'customFinalize': True,
'customWrapperManagement': True,
},
'DOMRectList': {
'headerFile': 'mozilla/dom/DOMRect.h',
'resultNotAddRefed': [ 'item' ]
@ -270,6 +280,11 @@ DOMInterfaces = {
'nativeType': 'nsDOMDataContainerEvent',
},
'DedicatedWorkerGlobalScope': {
'headerFile': 'mozilla/dom/WorkerScope.h',
'workers': True,
},
'DelayNode': [
{
'resultNotAddRefed': [ 'delayTime' ],
@ -355,38 +370,15 @@ DOMInterfaces = {
]
},
'Event': [
{
'Event': {
'nativeType': 'nsDOMEvent',
},
{
'nativeType': 'JSObject',
'workers': True,
'skipGen': True
}],
'EventListener': [
{
'workers': True,
}],
'EventTarget': [
{
'EventTarget': {
'hasXPConnectImpls': True,
'concrete': False,
'jsImplParent': 'nsDOMEventTargetHelper'
},
{
'workers': True,
'nativeOwnership': 'worker',
'concrete': False,
# XXXkhuey ownerGlobal returns WindowProxy? which boils down to a JSObject*
# on a worker, and nsRefPtr<JSObject> fails in the expected way. This is
# ugly but it's all going away soon anyways.
'resultNotAddRefed': [
'ownerGlobal'
]
}],
'Exception': {
'headerFile': 'mozilla/dom/DOMException.h',
@ -735,6 +727,14 @@ DOMInterfaces = {
'nativeType': 'nsDOMMessageEvent',
},
'MessagePort': {
'nativeType': 'mozilla::dom::MessagePortBase',
'headerFile': 'mozilla/dom/MessagePort.h',
'binaryNames': {
'postMessage': 'postMessageMoz',
},
},
'MimeType': {
'headerFile' : 'nsMimeTypeArray.h',
'nativeType': 'nsMimeType',
@ -944,6 +944,11 @@ DOMInterfaces = {
'implicitJSContext': [ 'constructor' ],
},
'SharedWorkerGlobalScope': {
'headerFile': 'mozilla/dom/WorkerScope.h',
'workers': True,
},
'SimpleGestureEvent': {
'nativeType': 'nsDOMSimpleGestureEvent',
},
@ -1244,12 +1249,12 @@ DOMInterfaces = {
},
'URL' : [{
'wrapperCache' : False,
'nativeOwnership': 'refcounted',
'wrapperCache': False,
},
{
'workers': True,
'nativeOwnership': 'worker',
'wrapperCache': False,
'nativeOwnership': 'owned',
}],
'VTTCue': {
@ -1443,29 +1448,30 @@ DOMInterfaces = {
'workers': True
}],
'Worker': {
'headerFile': 'mozilla/dom/WorkerPrivate.h',
'nativeType': 'mozilla::dom::workers::WorkerPrivate',
'implicitJSContext': [
'terminate',
],
'customFinalize': True,
'customWrapperManagement': True,
},
'WorkerGlobalScope': {
'headerFile': 'mozilla/dom/WorkerScope.h',
'workers': True,
'concrete': False,
'implicitJSContext': [
'close', 'importScripts',
],
},
'WorkerLocation': {
'headerFile': 'mozilla/dom/workers/bindings/Location.h',
'workers': True,
},
'WorkerMessagePort': [{
'nativeType': 'mozilla::dom::workers::MessagePort',
'headerFile': 'mozilla/dom/workers/bindings/MessagePort.h',
'implicitJSContext': [ 'postMessage' ],
'binaryNames': {
'postMessage': 'postMessageMoz',
},
},
{
'nativeType': 'mozilla::dom::workers::WorkerMessagePort',
'headerFile': 'mozilla/dom/workers/bindings/WorkerMessagePort.h',
'workers': True,
'nativeOwnership': 'worker',
'binaryNames': {
'postMessage': 'postMessageMoz',
},
}],
'WorkerNavigator': {
'headerFile': 'mozilla/dom/workers/bindings/Navigator.h',
'workers': True,
@ -1479,7 +1485,6 @@ DOMInterfaces = {
},
{
'workers': True,
'nativeOwnership': 'worker',
# XXXkhuey responseXML returns Document? which boils down to a JSObject*
# on a worker, and nsRefPtr<JSObject> fails in the expected way. channel is
# similar. This is ugly but it's all going away soon anyways.
@ -1488,17 +1493,11 @@ DOMInterfaces = {
]
}],
'XMLHttpRequestEventTarget': [
{
'XMLHttpRequestEventTarget': {
'nativeType': 'nsXHREventTarget',
'headerFile': 'nsXMLHttpRequest.h',
'concrete': False
},
{
'workers': True,
'nativeOwnership': 'worker',
'concrete': False,
}],
'XMLHttpRequestUpload': [
{
@ -1507,7 +1506,6 @@ DOMInterfaces = {
},
{
'workers': True,
'nativeOwnership': 'worker',
}],
'XMLSerializer': {

View File

@ -61,6 +61,11 @@ def isTypeCopyConstructible(type):
(type.isDictionary() and
CGDictionary.isDictionaryCopyConstructible(type.inner)))
def wantsAddProperty(desc):
return desc.concrete and not desc.nativeOwnership == 'worker' and \
desc.wrapperCache and not desc.customWrapperManagement and \
not desc.interface.getExtendedAttribute("Global")
class CGThing():
"""
Abstract base class for things that spit out code.
@ -148,19 +153,22 @@ def NativePropertyHooks(descriptor):
return "&sWorkerNativePropertyHooks" if descriptor.workers else "sNativePropertyHooks"
def DOMClass(descriptor):
protoList = ['prototypes::id::' + proto for proto in descriptor.prototypeChain]
# Pad out the list to the right length with _ID_Count so we
# guarantee that all the lists are the same length. _ID_Count
# is never the ID of any prototype, so it's safe to use as
# padding.
protoList.extend(['prototypes::id::_ID_Count'] * (descriptor.config.maxProtoChainLength - len(protoList)))
prototypeChainString = ', '.join(protoList)
if descriptor.nativeOwnership == 'worker':
participant = "nullptr"
else:
participant = "GetCCParticipant<%s>::Get()" % descriptor.nativeType
getParentObject = "GetParentObject<%s>::Get" % descriptor.nativeType
return """{
def make_name(d):
return "%s%s" % (d.interface.identifier.name, '_workers' if d.workers else '')
protoList = ['prototypes::id::' + make_name(descriptor.getDescriptor(proto)) for proto in descriptor.prototypeChain]
# Pad out the list to the right length with _ID_Count so we
# guarantee that all the lists are the same length. _ID_Count
# is never the ID of any prototype, so it's safe to use as
# padding.
protoList.extend(['prototypes::id::_ID_Count'] * (descriptor.config.maxProtoChainLength - len(protoList)))
prototypeChainString = ', '.join(protoList)
if descriptor.nativeOwnership == 'worker':
participant = "nullptr"
else:
participant = "GetCCParticipant<%s>::Get()" % descriptor.nativeType
getParentObject = "GetParentObject<%s>::Get" % descriptor.nativeType
return """{
{ %s },
IsBaseOf<nsISupports, %s >::value,
%s,
@ -184,11 +192,20 @@ class CGDOMJSClass(CGThing):
def define(self):
traceHook = TRACE_HOOK_NAME if self.descriptor.customTrace else 'nullptr'
callHook = LEGACYCALLER_HOOK_NAME if self.descriptor.operations["LegacyCaller"] else 'nullptr'
classFlags = "JSCLASS_IS_DOMJSCLASS | JSCLASS_HAS_RESERVED_SLOTS(3)"
classFlags = "JSCLASS_IS_DOMJSCLASS | "
if self.descriptor.interface.getExtendedAttribute("Global"):
classFlags += "JSCLASS_DOM_GLOBAL | JSCLASS_GLOBAL_FLAGS_WITH_SLOTS(DOM_GLOBAL_SLOTS) | JSCLASS_IMPLEMENTS_BARRIERS"
traceHook = "mozilla::dom::TraceGlobal"
else:
classFlags += "JSCLASS_HAS_RESERVED_SLOTS(3)"
if self.descriptor.interface.getExtendedAttribute("NeedNewResolve"):
newResolveHook = "(JSResolveOp)" + NEWRESOLVE_HOOK_NAME
classFlags += " | JSCLASS_NEW_RESOLVE"
enumerateHook = ENUMERATE_HOOK_NAME
elif self.descriptor.interface.getExtendedAttribute("Global"):
newResolveHook = "(JSResolveOp) mozilla::dom::ResolveGlobal"
classFlags += " | JSCLASS_NEW_RESOLVE"
enumerateHook = "mozilla::dom::EnumerateGlobal"
else:
newResolveHook = "JS_ResolveStub"
enumerateHook = "JS_EnumerateStub"
@ -215,7 +232,7 @@ static const DOMJSClass Class = {
};
""" % (self.descriptor.interface.identifier.name,
classFlags,
ADDPROPERTY_HOOK_NAME if self.descriptor.concrete and not self.descriptor.nativeOwnership == 'worker' and self.descriptor.wrapperCache else 'JS_PropertyStub',
ADDPROPERTY_HOOK_NAME if wantsAddProperty(self.descriptor) else 'JS_PropertyStub',
enumerateHook, newResolveHook, FINALIZE_HOOK_NAME, callHook, traceHook,
CGIndenter(CGGeneric(DOMClass(self.descriptor))).define())
@ -707,9 +724,16 @@ class CGHeaders(CGWrapper):
if desc.interface.isExternal():
continue
def addHeaderForFunc(func):
if func is None:
return
# Include the right class header, which we can only do
# if this is a class member function.
if func is not None and "::" in func:
if not desc.headerIsDefault:
# An explicit header file was provided, assume that we know
# what we're doing.
return
if "::" in func:
# Strip out the function name and convert "::" to "/"
bindingHeaders.add("/".join(func.split("::")[:-1]) + ".h")
for m in desc.interface.members:
@ -1779,8 +1803,7 @@ class CGCreateInterfaceObjectsMethod(CGAbstractMethod):
CGAbstractMethod.__init__(self, descriptor, 'CreateInterfaceObjects', 'void', args)
self.properties = properties
def definition_body(self):
protoChain = self.descriptor.prototypeChain
if len(protoChain) == 1:
if len(self.descriptor.prototypeChain) == 1:
parentProtoType = "Rooted"
if self.descriptor.interface.getExtendedAttribute("ArrayClass"):
getParentProto = "aCx, JS_GetArrayPrototype(aCx, aGlobal)"
@ -1788,6 +1811,9 @@ class CGCreateInterfaceObjectsMethod(CGAbstractMethod):
getParentProto = "aCx, JS_GetObjectPrototype(aCx, aGlobal)"
else:
parentProtoName = self.descriptor.prototypeChain[-2]
parentDesc = self.descriptor.getDescriptor(parentProtoName)
if parentDesc.workers:
parentProtoName += '_workers'
getParentProto = ("%s::GetProtoObject(aCx, aGlobal)" %
toBindingNamespace(parentProtoName))
parentProtoType = "Handle"
@ -1798,7 +1824,8 @@ class CGCreateInterfaceObjectsMethod(CGAbstractMethod):
parentWithInterfaceObject = parentWithInterfaceObject.parent
if parentWithInterfaceObject:
parentIfaceName = parentWithInterfaceObject.identifier.name
if self.descriptor.workers:
parentDesc = self.descriptor.getDescriptor(parentIfaceName)
if parentDesc.workers:
parentIfaceName += "_workers"
getConstructorProto = ("%s::GetConstructorObject(aCx, aGlobal)" %
toBindingNamespace(parentIfaceName))
@ -2354,6 +2381,47 @@ class CGWrapNonWrapperCacheMethod(CGAbstractMethod):
"global"),
InitUnforgeableProperties(self.descriptor, self.properties))
class CGWrapGlobalMethod(CGAbstractMethod):
"""
Create a wrapper JSObject for a global. The global must implement
nsWrapperCache.
properties should be a PropertyArrays instance.
"""
def __init__(self, descriptor, properties):
assert descriptor.interface.hasInterfacePrototypeObject()
args = [Argument('JSContext*', 'aCx'),
Argument('JS::Handle<JSObject*>', 'aScope'),
Argument(descriptor.nativeType + '*', 'aObject'),
Argument('nsWrapperCache*', 'aCache'),
Argument('JS::CompartmentOptions&', 'aOptions'),
Argument('JSPrincipals*', 'aPrincipal')]
CGAbstractMethod.__init__(self, descriptor, 'Wrap', 'JSObject*', args)
self.descriptor = descriptor
self.properties = properties
def definition_body(self):
return """%s
MOZ_ASSERT(ToSupportsIsOnPrimaryInheritanceChain(aObject, aCache),
"nsISupports must be on our primary inheritance chain");
JS::Rooted<JSObject*> obj(aCx);
obj = CreateGlobal<%s, GetProtoObject>(aCx,
aObject,
aCache,
&Class.mBase,
aOptions,
aPrincipal);
%s
// XXXkhuey can't do this yet until workers can lazy resolve.
// JS_FireOnNewGlobalObject(aCx, obj);
return obj;""" % (AssertInheritanceChain(self.descriptor),
self.descriptor.nativeType,
InitUnforgeableProperties(self.descriptor, self.properties))
builtinNames = {
IDLType.Tags.bool: 'bool',
IDLType.Tags.int8: 'int8_t',
@ -5617,10 +5685,11 @@ class CGLegacyCallHook(CGAbstractBindingMethod):
class CGNewResolveHook(CGAbstractBindingMethod):
"""
NewResolve hook for our object
NewResolve hook for objects with custom hooks.
"""
def __init__(self, descriptor):
assert descriptor.interface.getExtendedAttribute("NeedNewResolve")
args = [Argument('JSContext*', 'cx'), Argument('JS::Handle<JSObject*>', 'obj'),
Argument('JS::Handle<jsid>', 'id'), Argument('unsigned', 'flags'),
Argument('JS::MutableHandle<JSObject*>', 'objp')]
@ -5646,10 +5715,11 @@ class CGNewResolveHook(CGAbstractBindingMethod):
class CGEnumerateHook(CGAbstractBindingMethod):
"""
Enumerate hook for our object
Enumerate hook for objects with custom hooks.
"""
def __init__(self, descriptor):
assert descriptor.interface.getExtendedAttribute("NeedNewResolve")
args = [Argument('JSContext*', 'cx'),
Argument('JS::Handle<JSObject*>', 'obj')]
# Our "self" is actually the "obj" argument in this case, not the thisval.
@ -8144,7 +8214,7 @@ class CGDescriptor(CGThing):
cgThings.append(CGConstructNavigatorObject(descriptor))
if descriptor.concrete and not descriptor.proxy:
if not descriptor.nativeOwnership == 'worker' and descriptor.wrapperCache:
if wantsAddProperty(descriptor):
cgThings.append(CGAddPropertyHook(descriptor))
# Always have a finalize hook, regardless of whether the class
@ -8235,7 +8305,10 @@ class CGDescriptor(CGThing):
cgThings.append(CGDOMJSClass(descriptor))
cgThings.append(CGGetJSClassMethod(descriptor))
if descriptor.wrapperCache:
if descriptor.interface.getExtendedAttribute("Global"):
assert descriptor.wrapperCache
cgThings.append(CGWrapGlobalMethod(descriptor, properties))
elif descriptor.wrapperCache:
cgThings.append(CGWrapWithCacheMethod(descriptor, properties))
cgThings.append(CGWrapMethod(descriptor))
else:

View File

@ -165,6 +165,10 @@ class Configuration:
if d.workers == workers:
return d
if workers:
for d in self.descriptorsByName[interfaceName]:
return d
raise NoSuchDescriptorError("For " + interfaceName + " found no matches");
def getDescriptorProvider(self, workers):
"""
@ -238,6 +242,7 @@ class Descriptor(DescriptorProvider):
headerDefault = self.nativeType
headerDefault = headerDefault.replace("::", "/") + ".h"
self.headerFile = desc.get('headerFile', headerDefault)
self.headerIsDefault = self.headerFile == headerDefault
if self.jsImplParent == self.nativeType:
self.jsImplParentHeader = self.headerFile
else:
@ -356,12 +361,17 @@ class Descriptor(DescriptorProvider):
(self.interface.identifier.name, self.nativeOwnership))
self.customTrace = (self.nativeOwnership == 'worker')
self.customFinalize = desc.get('customFinalize', self.nativeOwnership == 'worker')
self.customWrapperManagement = desc.get('customWrapperManagement', False)
if desc.get('wantsQI', None) != None:
self._wantsQI = desc.get('wantsQI', None)
self.wrapperCache = (not self.interface.isCallback() and
(self.nativeOwnership == 'worker' or
(self.nativeOwnership != 'owned' and
desc.get('wrapperCache', True))))
if self.customWrapperManagement and not self.wrapperCache:
raise TypeError("Descriptor for %s has customWrapperManagement "
"but is not wrapperCached." %
(self.interface.identifier.name))
def make_name(name):
return name + "_workers" if self.workers else name
@ -408,7 +418,7 @@ class Descriptor(DescriptorProvider):
self.prototypeChain = []
parent = interface
while parent:
self.prototypeChain.insert(0, make_name(parent.identifier.name))
self.prototypeChain.insert(0, parent.identifier.name)
parent = parent.parent
config.maxProtoChainLength = max(config.maxProtoChainLength,
len(self.prototypeChain))

View File

@ -13,6 +13,7 @@
#include "mozilla/dom/UnionTypes.h"
#include "mozilla/ErrorResult.h"
#include "nsCOMPtr.h"
#include "nsGenericHTMLElement.h"
#include "nsWrapperCache.h"
// Forward declare this before we include TestCodeGenBinding.h, because that header relies on including

View File

@ -209,7 +209,7 @@ GamepadService::NewButtonEvent(uint32_t aIndex, uint32_t aButton, bool aPressed,
--i;
// Only send events to non-background windows
if (!listeners[i]->GetOuterWindow() ||
if (!listeners[i]->IsCurrentInnerWindow() ||
listeners[i]->GetOuterWindow()->IsBackground()) {
continue;
}
@ -274,7 +274,7 @@ GamepadService::NewAxisMoveEvent(uint32_t aIndex, uint32_t aAxis, double aValue)
--i;
// Only send events to non-background windows
if (!listeners[i]->GetOuterWindow() ||
if (!listeners[i]->IsCurrentInnerWindow() ||
listeners[i]->GetOuterWindow()->IsBackground()) {
continue;
}
@ -340,7 +340,7 @@ GamepadService::NewConnectionEvent(uint32_t aIndex, bool aConnected)
--i;
// Only send events to non-background windows
if (!listeners[i]->GetOuterWindow() ||
if (!listeners[i]->IsCurrentInnerWindow() ||
listeners[i]->GetOuterWindow()->IsBackground()) {
continue;
}
@ -525,6 +525,7 @@ GamepadServiceTest::CreateService()
GamepadServiceTest::GamepadServiceTest()
{
/* member initializers and constructor code */
nsRefPtr<GamepadService> service = GamepadService::GetService();
}
/* uint32_t addGamepad (in string id, in unsigned long mapping, in unsigned long numButtons, in unsigned long numAxes); */

View File

@ -2,6 +2,29 @@
"EventTarget method: addEventListener": true,
"EventTarget method: removeEventListener": true,
"EventTarget method: dispatchEvent": true,
"Window method: close": true,
"Window method: stop": true,
"Window method: focus": true,
"Window method: blur": true,
"Window method: open": true,
"Window method: alert": true,
"Window method: confirm": true,
"Window method: prompt": true,
"Window method: print": true,
"Window method: showModalDialog": true,
"Window method: postMessage": true,
"Window method: btoa": true,
"Window method: atob": true,
"Window method: setTimeout": true,
"Window method: clearTimeout": true,
"Window method: setInterval": true,
"Window method: clearInterval": true,
"Window method: getSelection": true,
"Window method: getComputedStyle": true,
"Window method: matchMedia": true,
"Window method: scroll": true,
"Window method: scrollTo": true,
"Window method: scrollBy": true,
"Window readonly attribute: history": true,
"Window readonly attribute: parent": true,
"Window readonly attribute: frameElement": true,
@ -21,14 +44,93 @@
"Window readonly attribute: screenY": true,
"Window readonly attribute: outerWidth": true,
"Window readonly attribute: outerHeight": true,
"Window attribute: name": true,
"Window attribute: status": true,
"Window attribute: opener": true,
"Window attribute: onabort": true,
"Window attribute: onafterprint": true,
"Window attribute: onbeforeprint": true,
"Window attribute: onbeforeunload": true,
"Window attribute: onblur": true,
"Window attribute: oncancel": true,
"Window attribute: oncanplay": true,
"Window attribute: oncanplaythrough": true,
"Window attribute: onchange": true,
"Window attribute: onclick": true,
"Window attribute: onclose": true,
"Window attribute: oncontextmenu": true,
"Window attribute: oncuechange": true,
"Window attribute: ondblclick": true,
"Window attribute: ondrag": true,
"Window attribute: ondragend": true,
"Window attribute: ondragenter": true,
"Window attribute: ondragleave": true,
"Window attribute: ondragover": true,
"Window attribute: ondragstart": true,
"Window attribute: ondrop": true,
"Window attribute: ondurationchange": true,
"Window attribute: onemptied": true,
"Window attribute: onended": true,
"Window attribute: onerror": true,
"Window attribute: onfocus": true,
"Window attribute: onhashchange": true,
"Window attribute: oninput": true,
"Window attribute: oninvalid": true,
"Window attribute: onkeydown": true,
"Window attribute: onkeypress": true,
"Window attribute: onkeyup": true,
"Window attribute: oncancel": true,
"Window attribute: onclose": true,
"Window attribute: oncuechange": true,
"Window attribute: onmousewheel": true,
"Window attribute: onload": true,
"Window attribute: onloadeddata": true,
"Window attribute: onloadedmetadata": true,
"Window attribute: onloadstart": true,
"Window attribute: onmessage": true,
"Window attribute: onmousedown": true,
"Window attribute: onmousemove": true,
"Window attribute: onmouseout": true,
"Window attribute: onmouseover": true,
"Window attribute: onmouseup": true,
"Window attribute: onmousewheel": true,
"Window attribute: onoffline": true,
"Window attribute: ononline": true,
"Window attribute: onpause": true,
"Window attribute: onplay": true,
"Window attribute: onplaying": true,
"Window attribute: onpagehide": true,
"Window attribute: onpageshow": true,
"Window attribute: onpopstate": true,
"Window attribute: onprogress": true,
"Window attribute: onratechange": true,
"Window attribute: onreset": true,
"Window attribute: onresize": true,
"Window attribute: onscroll": true,
"Window attribute: onseeked": true,
"Window attribute: onseeking": true,
"Window attribute: onselect": true,
"Window attribute: onshow": true,
"Window attribute: onstalled": true,
"Window attribute: onstorage": true,
"Window attribute: onsubmit": true,
"Window attribute: onsuspend": true,
"Window attribute: ontimeupdate": true,
"Window attribute: onunload": true,
"Window attribute: onvolumechange": true,
"Window attribute: onwaiting": true,
"Window unforgeable attribute: window": true,
"Window unforgeable attribute: document": true,
"Window unforgeable attribute: location": true,
"Window unforgeable attribute: top": true,
"Window replaceable attribute: self": true,
"Window replaceable attribute: locationbar": true,
"Window replaceable attribute: menubar": true,
"Window replaceable attribute: personalbar": true,
"Window replaceable attribute: scrollbars": true,
"Window replaceable attribute: statusbar": true,
"Window replaceable attribute: toolbar": true,
"Window replaceable attribute: frames": true,
"Window replaceable attribute: length": true,
"constructor": true
}

View File

@ -251,7 +251,7 @@ test(function() {
var EventTargetProto = EventTarget.prototype;
assert_true(id in window, id + " in window");
assert_equals(window[id], EventTargetProto[id]);
assert_data_propdesc(Object.getOwnPropertyDescriptor(EventTargetProto, id),
assert_data_propdesc(Object.getOwnPropertyDescriptor(window, id),
true, true, true);
}, "EventTarget method: " + id);
});
@ -262,9 +262,8 @@ test(function() {
test(function() {
var WindowProto = Window.prototype;
assert_true(id in window, id + " in window");
assert_true(id in WindowProto, id + " in Window.prototype");
assert_equals(window[id], WindowProto[id]);
assert_data_propdesc(Object.getOwnPropertyDescriptor(WindowProto, id),
assert_false(id in WindowProto, id + " in Window.prototype");
assert_data_propdesc(Object.getOwnPropertyDescriptor(window, id),
true, true, true);
}, "Window method: " + id);
});
@ -272,8 +271,8 @@ test(function() {
test(function() {
var WindowProto = Window.prototype;
assert_true(id in window, id + " in window");
assert_true(id in WindowProto, id + " in Window.prototype");
assert_accessor_propdesc(Object.getOwnPropertyDescriptor(WindowProto, id),
assert_false(id in WindowProto, id + " in Window.prototype");
assert_accessor_propdesc(Object.getOwnPropertyDescriptor(window, id),
false, true, true);
}, "Window readonly attribute: " + id);
});
@ -281,8 +280,8 @@ test(function() {
test(function() {
var WindowProto = Window.prototype;
assert_true(id in window, id + " in window");
assert_true(id in WindowProto, id + " in Window.prototype");
assert_accessor_propdesc(Object.getOwnPropertyDescriptor(WindowProto, id),
assert_false(id in WindowProto, id + " in Window.prototype");
assert_accessor_propdesc(Object.getOwnPropertyDescriptor(window, id),
true, true, true);
}, "Window attribute: " + id);
});
@ -290,18 +289,18 @@ test(function() {
test(function() {
var WindowProto = Window.prototype;
assert_true(id in window, id + " in window");
assert_false(id in WindowProto, id + " in Window.prototype");
// location has a [PutForwards] extended attribute.
assert_accessor_propdesc(Object.getOwnPropertyDescriptor(window, id),
id === "location", true, false);
assert_false(id in WindowProto, id + " in Window.prototype");
}, "Window unforgeable attribute: " + id);
});
replacableAttributes.forEach(function(id) {
test(function() {
var WindowProto = Window.prototype;
assert_true(id in window, id + " in window");
assert_true(id in WindowProto, id + " in Window.prototype");
assert_accessor_propdesc(Object.getOwnPropertyDescriptor(WindowProto, id),
assert_false(id in WindowProto, id + " in Window.prototype");
assert_accessor_propdesc(Object.getOwnPropertyDescriptor(window, id),
true, true, true);
}, "Window replaceable attribute: " + id);
});

View File

@ -6,10 +6,11 @@
#include "domstubs.idl"
interface nsIContentFrameMessageManager;
// Sole purpose is to be able to identify the concrete class nsTabChild
[uuid(bf1eddf9-731b-4a4b-bd65-9a712a892832)]
[uuid( 60146bc6-31d8-450b-a9eb-4000b6403d5c)]
interface nsITabChild : nsISupports
{
readonly attribute nsIContentFrameMessageManager messageManager;
[notxpcom] void sendRequestFocus(in boolean canFocus);
};

View File

@ -71,6 +71,10 @@
#include "nsILoadContext.h"
#include "ipc/nsGUIEventIPC.h"
#ifdef DEBUG
#include "PCOMContentPermissionRequestChild.h"
#endif /* DEBUG */
#define BROWSER_ELEMENT_CHILD_SCRIPT \
NS_LITERAL_STRING("chrome://global/content/BrowserElementChild.js")
@ -1141,6 +1145,20 @@ TabChild::ArraysToParams(const InfallibleTArray<int>& aIntParams,
}
}
#ifdef DEBUG
PContentPermissionRequestChild*
TabChild:: SendPContentPermissionRequestConstructor(PContentPermissionRequestChild* aActor,
const nsCString& aType,
const nsCString& aAccess,
const IPC::Principal& aPrincipal)
{
PCOMContentPermissionRequestChild* child = static_cast<PCOMContentPermissionRequestChild*>(aActor);
PContentPermissionRequestChild* request = PBrowserChild::SendPContentPermissionRequestConstructor(aActor, aType, aAccess, aPrincipal);
child->mIPCOpen = true;
return request;
}
#endif /* DEBUG */
void
TabChild::DestroyWindow()
{
@ -2360,6 +2378,12 @@ TabChild::GetMessageManager(nsIContentFrameMessageManager** aResult)
return NS_ERROR_FAILURE;
}
void
TabChild::SendRequestFocus(bool aCanFocus)
{
PBrowserChild::SendRequestFocus(aCanFocus);
}
PIndexedDBChild*
TabChild::AllocPIndexedDBChild(
const nsCString& aGroup,

View File

@ -8,9 +8,6 @@
#define mozilla_dom_TabChild_h
#include "mozilla/dom/PBrowserChild.h"
#ifdef DEBUG
#include "PCOMContentPermissionRequestChild.h"
#endif /* DEBUG */
#include "nsIWebNavigation.h"
#include "nsCOMPtr.h"
#include "nsAutoPtr.h"
@ -270,15 +267,10 @@ public:
nsIDialogParamBlock* aParams);
#ifdef DEBUG
virtual PContentPermissionRequestChild* SendPContentPermissionRequestConstructor(PContentPermissionRequestChild* aActor,
const InfallibleTArray<PermissionRequest>& aRequests,
const IPC::Principal& aPrincipal)
{
PCOMContentPermissionRequestChild* child = static_cast<PCOMContentPermissionRequestChild*>(aActor);
PContentPermissionRequestChild* request = PBrowserChild::SendPContentPermissionRequestConstructor(aActor, aRequests, aPrincipal);
child->mIPCOpen = true;
return request;
}
virtual PContentPermissionRequestChild*
SendPContentPermissionRequestConstructor(PContentPermissionRequestChild* aActor,
const InfallibleTArray<PermissionRequest>& aRequests,
const IPC::Principal& aPrincipal);
#endif /* DEBUG */
virtual PContentPermissionRequestChild* AllocPContentPermissionRequestChild(const InfallibleTArray<PermissionRequest>& aRequests,

View File

@ -167,7 +167,7 @@ nsJSEventListener::HandleEvent(nsIDOMEvent* aEvent)
return NS_ERROR_FAILURE;
if (mHandler.Type() == nsEventHandler::eOnError) {
MOZ_ASSERT(mEventName == nsGkAtoms::onerror);
MOZ_ASSERT_IF(mEventName, mEventName == nsGkAtoms::onerror);
nsString errorMsg, file;
EventOrString msgOrEvent;

Some files were not shown because too many files have changed in this diff Show More