Merge mozilla-central to inbound

This commit is contained in:
arthur.iakab 2018-08-07 18:49:13 +03:00
Родитель d8c8b51305 f0c15db995
Коммит a3f6453363
62 изменённых файлов: 1094 добавлений и 1007 удалений

Просмотреть файл

@ -588,6 +588,7 @@ hbox.urlbar-input-box {
html|input.urlbar-scheme {
position: absolute;
height: 100%;
left: 0;
visibility: hidden;
direction: ltr;
pointer-events: none;

Просмотреть файл

@ -1319,7 +1319,9 @@ var gBrowserInit = {
let mm = window.getGroupMessageManager("browsers");
mm.loadFrameScript("chrome://browser/content/tab-content.js", true);
mm.loadFrameScript("chrome://browser/content/content.js", true);
mm.loadFrameScript("chrome://browser/content/content-UITour.js", true);
mm.loadFrameScript("chrome://global/content/content-HybridContentTelemetry.js", true);
mm.loadFrameScript("chrome://global/content/manifestMessages.js", true);
window.messageManager.addMessageListener("Browser:LoadURI", RedirectLoad);

Просмотреть файл

@ -90,12 +90,6 @@ addMessageListener("MixedContent:ReenableProtection", function() {
XPCOMUtils.defineLazyProxy(this, "LightweightThemeChildHelper",
"resource:///modules/LightweightThemeChildHelper.jsm");
XPCOMUtils.defineLazyProxy(this, "ManifestMessages", () => {
let tmp = {};
ChromeUtils.import("resource://gre/modules/ManifestMessages.jsm", tmp);
return new tmp.ManifestMessages(global);
});
let themeablePagesWhitelist = new Set([
"about:home",
"about:newtab",
@ -523,8 +517,3 @@ addEventListener("MozAfterPaint", function onFirstNonBlankPaint() {
removeEventListener("MozAfterPaint", onFirstNonBlankPaint);
sendAsyncMessage("Browser:FirstNonBlankPaint");
});
addMessageListener("DOM:WebManifest:hasManifestLink", ManifestMessages);
addMessageListener("DOM:ManifestObtainer:Obtain", ManifestMessages);
addMessageListener("DOM:Manifest:FireAppInstalledEvent", ManifestMessages);
addMessageListener("DOM:WebManifest:fetchIcon", ManifestMessages);

Просмотреть файл

@ -464,18 +464,22 @@ window._gBrowser = {
_setFindbarData() {
// Ensure we know what the find bar key is in the content process:
let {sharedData} = Services.ppmm;
if (!sharedData.has("Findbar:Shortcut")) {
let initialProcessData = Services.ppmm.initialProcessData;
if (!initialProcessData.findBarShortcutData) {
let keyEl = document.getElementById("key_find");
let mods = keyEl.getAttribute("modifiers")
.replace(/accel/i, AppConstants.platform == "macosx" ? "meta" : "control");
sharedData.set("Findbar:Shortcut", {
initialProcessData.findBarShortcutData = {
key: keyEl.getAttribute("key"),
shiftKey: mods.includes("shift"),
ctrlKey: mods.includes("control"),
altKey: mods.includes("alt"),
metaKey: mods.includes("meta"),
});
modifiers: {
shiftKey: mods.includes("shift"),
ctrlKey: mods.includes("control"),
altKey: mods.includes("alt"),
metaKey: mods.includes("meta"),
},
};
Services.ppmm.broadcastAsyncMessage("Findbar:ShortcutData",
initialProcessData.findBarShortcutData);
}
},

Просмотреть файл

@ -93,7 +93,7 @@ add_task(async function startup() {
max: 650,
},
"extensions.getAddons.cache.enabled": {
min: 8,
min: 7,
max: 55,
},
};

Просмотреть файл

@ -23,12 +23,18 @@ const whitelist = {
"extension-process-script.js",
]),
modules: new Set([
// From the test harness
"chrome://mochikit/content/ShutdownLeaksCollector.jsm",
"resource://specialpowers/MockColorPicker.jsm",
"resource://specialpowers/MockFilePicker.jsm",
"resource://specialpowers/MockPermissionPrompt.jsm",
// General utilities
"resource://gre/modules/AppConstants.jsm",
"resource://gre/modules/AsyncShutdown.jsm",
"resource://gre/modules/DeferredTask.jsm",
"resource://gre/modules/FileUtils.jsm",
"resource://gre/modules/NetUtil.jsm",
"resource://gre/modules/PromiseUtils.jsm",
"resource://gre/modules/Services.jsm", // bug 1464542
"resource://gre/modules/Timer.jsm",
@ -53,8 +59,6 @@ const whitelist = {
"resource://gre/modules/E10SUtils.jsm",
"resource://gre/modules/PrivateBrowsingUtils.jsm",
"resource://gre/modules/ReaderMode.jsm",
"resource://gre/modules/WebProgressChild.jsm",
"resource://gre/modules/WebNavigationChild.jsm",
// Pocket
"chrome://pocket/content/AboutPocket.jsm",
@ -67,6 +71,12 @@ const whitelist = {
// Extensions
"resource://gre/modules/ExtensionUtils.jsm",
"resource://gre/modules/MessageChannel.jsm",
// Service workers
"resource://gre/modules/ServiceWorkerCleanUp.jsm",
// Shield
"resource://normandy-content/AboutPages.jsm",
]),
};

Просмотреть файл

@ -1805,7 +1805,7 @@ BrowserGlue.prototype = {
_migrateUI: function BG__migrateUI() {
// Use an increasing number to keep track of the current migration state.
// Completely unrelated to the current Firefox release number.
const UI_VERSION = 72;
const UI_VERSION = 73;
const BROWSER_DOCURL = AppConstants.BROWSER_CHROME_URL;
let currentUIVersion;
@ -2142,6 +2142,19 @@ BrowserGlue.prototype = {
Services.prefs.setIntPref(pref, Services.prefs.getIntPref(pref, 1) * 1000);
}
if (currentUIVersion < 73) {
// Remove blocklist JSON local dumps in profile.
OS.File.removeDir(OS.Path.join(OS.Constants.Path.profileDir, "blocklists"),
{ ignoreAbsent: true });
OS.File.removeDir(OS.Path.join(OS.Constants.Path.profileDir, "blocklists-preview"),
{ ignoreAbsent: true });
for (const filename of ["addons.json", "plugins.json", "gfx.json"]) {
// Some old versions used to dump without subfolders. Clean them while we are at it.
const path = OS.Path.join(OS.Constants.Path.profileDir, `blocklists-${filename}`);
OS.File.remove(path, { ignoreAbsent: true });
}
}
// Update the migration version.
Services.prefs.setIntPref("browser.migration.version", UI_VERSION);
},

Просмотреть файл

@ -2,18 +2,14 @@
* 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/. */
var EXPORTED_SYMBOLS = ["UITourListener"];
/* eslint-env mozilla/frame-script */
ChromeUtils.import("resource://gre/modules/Services.jsm");
const PREF_TEST_WHITELIST = "browser.uitour.testingOrigins";
const UITOUR_PERMISSION = "uitour";
class UITourListener {
constructor(mm) {
this.mm = mm;
}
var UITourListener = {
handleEvent(event) {
if (!Services.prefs.getBoolPref("browser.uitour.enabled")) {
return;
@ -21,14 +17,14 @@ class UITourListener {
if (!this.ensureTrustedOrigin()) {
return;
}
this.mm.addMessageListener("UITour:SendPageCallback", this);
this.mm.addMessageListener("UITour:SendPageNotification", this);
this.mm.sendAsyncMessage("UITour:onPageEvent", {
addMessageListener("UITour:SendPageCallback", this);
addMessageListener("UITour:SendPageNotification", this);
sendAsyncMessage("UITour:onPageEvent", {
detail: event.detail,
type: event.type,
pageVisibilityState: this.mm.content.document.visibilityState,
pageVisibilityState: content.document.visibilityState,
});
}
},
isTestingOrigin(aURI) {
if (Services.prefs.getPrefType(PREF_TEST_WHITELIST) != Services.prefs.PREF_STRING) {
@ -47,7 +43,7 @@ class UITourListener {
}
}
return false;
}
},
// This function is copied from UITour.jsm.
isSafeScheme(aURI) {
@ -59,11 +55,9 @@ class UITourListener {
return false;
return true;
}
},
ensureTrustedOrigin() {
let {content} = this.mm;
if (content.top != content)
return false;
@ -80,7 +74,7 @@ class UITourListener {
return true;
return this.isTestingOrigin(uri);
}
},
receiveMessage(aMessage) {
switch (aMessage.name) {
@ -91,19 +85,21 @@ class UITourListener {
this.sendPageEvent("Notification", aMessage.data);
break;
}
}
},
sendPageEvent(type, detail) {
if (!this.ensureTrustedOrigin()) {
return;
}
let win = this.mm.content;
let doc = content.document;
let eventName = "mozUITour" + type;
let event = new win.CustomEvent(eventName, {
let event = new doc.defaultView.CustomEvent(eventName, {
bubbles: true,
detail: Cu.cloneInto(detail, win),
detail: Cu.cloneInto(detail, doc.defaultView)
});
win.document.dispatchEvent(event);
doc.dispatchEvent(event);
}
}
};
addEventListener("mozUITour", UITourListener, false, true);

Просмотреть файл

@ -0,0 +1,6 @@
# 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/.
browser.jar:
content/browser/content-UITour.js

Просмотреть файл

@ -3,10 +3,11 @@
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
EXTRA_JS_MODULES += [
'ContentUITour.jsm',
'UITour.jsm',
]
JAR_MANIFESTS += ['jar.mn']
BROWSER_CHROME_MANIFESTS += [
'test/browser.ini',
]

Просмотреть файл

@ -6,7 +6,6 @@
DIRS += [
'aushelper',
'followonsearch',
'formautofill',
'onboarding',
'pdfjs',

Просмотреть файл

@ -370,10 +370,6 @@
@RESPATH@/components/extension-process-script.js
@RESPATH@/browser/components/extensions-browser.manifest
; [Normandy]
@RESPATH@/components/shield.manifest
@RESPATH@/components/shield-content-process.js
; [PDF Viewer]
@RESPATH@/browser/components/pdfjs.manifest
@RESPATH@/browser/components/pdfjs.js

Просмотреть файл

@ -13,10 +13,13 @@ var EXPORTED_SYMBOLS = [
];
ChromeUtils.import("resource://gre/modules/Services.jsm");
ChromeUtils.import("resource://gre/modules/XPCOMUtils.jsm");
ChromeUtils.defineModuleGetter(this, "PrivateBrowsingUtils",
"resource://gre/modules/PrivateBrowsingUtils.jsm");
XPCOMUtils.defineLazyGlobalGetters(this, ["URLSearchParams"]);
// The upper bound for the count of the visited unique domain names.
const MAX_UNIQUE_VISITED_DOMAINS = 100;
@ -88,7 +91,6 @@ const URLBAR_SELECTED_RESULT_METHODS = {
const MINIMUM_TAB_COUNT_INTERVAL_MS = 5 * 60 * 1000; // 5 minutes, in ms
function getOpenTabsAndWinsCounts() {
let tabCount = 0;
let winCount = 0;
@ -159,6 +161,10 @@ let URICountListener = {
return;
}
// Don't include URI and domain counts when in private mode.
let shouldCountURI = !PrivateBrowsingUtils.isWindowPrivate(browser.ownerGlobal) ||
Services.prefs.getBoolPref("browser.engagement.total_uri_count.pbm", false);
// Track URI loads, even if they're not http(s).
let uriSpec = null;
try {
@ -166,7 +172,9 @@ let URICountListener = {
} catch (e) {
// If we have troubles parsing the spec, still count this as
// an unfiltered URI.
Services.telemetry.scalarAdd(UNFILTERED_URI_COUNT_SCALAR_NAME, 1);
if (shouldCountURI) {
Services.telemetry.scalarAdd(UNFILTERED_URI_COUNT_SCALAR_NAME, 1);
}
return;
}
@ -188,12 +196,42 @@ let URICountListener = {
// The URI wasn't from a restored tab. Count it among the unfiltered URIs.
// If this is an http(s) URI, this also gets counted by the "total_uri_count"
// probe.
Services.telemetry.scalarAdd(UNFILTERED_URI_COUNT_SCALAR_NAME, 1);
if (shouldCountURI) {
Services.telemetry.scalarAdd(UNFILTERED_URI_COUNT_SCALAR_NAME, 1);
}
if (!this.isHttpURI(uri)) {
return;
}
let parseURLResult = Services.search.parseSubmissionURL(uriSpec);
if (parseURLResult.engine) {
this._recordSearchTelemetry(uriSpec, parseURLResult);
} else if (this._urlsQueuedForParsing) {
if (Services.search.isInitialized) {
this._urlsQueuedForParsing = null;
} else {
this._urlsQueuedForParsing.push(uriSpec);
if (this._urlsQueuedForParsing.length == 1) {
Services.search.init(rv => {
if (Components.isSuccessCode(rv)) {
for (let url of this._urlsQueuedForParsing) {
let innerParseURLResult = Services.search.parseSubmissionURL(url);
if (innerParseURLResult.engine) {
this._recordSearchTelemetry(url, innerParseURLResult);
}
}
}
this._urlsQueuedForParsing = null;
});
}
}
}
if (!shouldCountURI) {
return;
}
// Update the URI counts.
Services.telemetry.scalarAdd(TOTAL_URI_COUNT_SCALAR_NAME, 1);
@ -226,6 +264,31 @@ let URICountListener = {
this._domainSet.clear();
},
_urlsQueuedForParsing: [],
_recordSearchTelemetry(url, parseURLResult) {
switch (parseURLResult.engine.identifier) {
case "google":
case "google-2018":
let type;
let queries = new URLSearchParams(url.split("?")[1]);
let code = queries.get("client");
if (code) {
// Detecting follow-on searches for sap is a little tricky.
// There are a few parameters that only show up
// with follow-ons, so we look for those. (oq/ved/ei)
type = queries.has("oq") || queries.has("ved") || queries.has("ei") ? "sap-follow-on" : "sap";
} else {
type = "organic";
}
let payload = `google.in-content.${type}:${code || "none"}`;
let histogram = Services.telemetry.getKeyedHistogramById("SEARCH_COUNTS");
histogram.add(payload);
break;
}
},
QueryInterface: ChromeUtils.generateQI([Ci.nsIWebProgressListener,
Ci.nsISupportsWeakReference]),
};
@ -614,11 +677,6 @@ let BrowserUsageTelemetry = {
win.addEventListener("unload", this);
win.addEventListener("TabOpen", this, true);
// Don't include URI and domain counts when in private mode.
if (PrivateBrowsingUtils.isWindowPrivate(win) &&
!Services.prefs.getBoolPref("browser.engagement.total_uri_count.pbm", false)) {
return;
}
win.gBrowser.tabContainer.addEventListener(TAB_RESTORING_TOPIC, this);
win.gBrowser.addTabsProgressListener(URICountListener);
},
@ -630,11 +688,6 @@ let BrowserUsageTelemetry = {
win.removeEventListener("unload", this);
win.removeEventListener("TabOpen", this, true);
// Don't include URI and domain counts when in private mode.
if (PrivateBrowsingUtils.isWindowPrivate(win.defaultView) &&
!Services.prefs.getBoolPref("browser.engagement.total_uri_count.pbm", false)) {
return;
}
win.defaultView.gBrowser.tabContainer.removeEventListener(TAB_RESTORING_TOPIC, this);
win.defaultView.gBrowser.removeTabsProgressListener(URICountListener);
},

Просмотреть файл

@ -37,6 +37,7 @@ class AnimationListContainer extends PureComponent {
setAnimationsCurrentTime: PropTypes.func.isRequired,
setHighlightedNode: PropTypes.func.isRequired,
setSelectedNode: PropTypes.func.isRequired,
sidebarWidth: PropTypes.number.isRequired,
simulateAnimation: PropTypes.func.isRequired,
timeScale: PropTypes.object.isRequired,
};
@ -55,8 +56,17 @@ class AnimationListContainer extends PureComponent {
this.updateState(this.props);
}
componentWillReceiveProps(nextProps) {
this.updateState(nextProps);
componentDidUpdate(prevProps) {
const {
timeScale,
sidebarWidth
} = this.props;
if (timeScale.getDuration() !== prevProps.timeScale.getDuration() ||
timeScale.zeroPositionTime !== prevProps.timeScale.zeroPositionTime ||
sidebarWidth !== prevProps.sidebarWidth) {
this.updateState(this.props);
}
}
updateState(props) {
@ -79,25 +89,16 @@ class AnimationListContainer extends PureComponent {
// Need to display first graduation since position will be shifted.
if (needToShift) {
const label = timeScale.formatTime(timeScale.distanceToRelativeTime(0));
ticks.push({ position: 0, label });
ticks.push({ position: 0, label, width: shiftWidth });
}
for (let i = 0; i <= tickCount; i++) {
const position = ((i * intervalWidth) + shiftWidth) * 100 / width;
const distance = timeScale.distanceToRelativeTime(position);
let label = isAllDurationInfinity && i === tickCount
? getStr("player.infiniteTimeLabel")
: timeScale.formatTime(distance);
// As result of shifting the label, first shifted label might overlap
// to the most left label. So display empyt label in this case.
// And prevent to skip displaying zero position label.
if (i === 0 &&
needToShift &&
shiftWidth < intervalWidth &&
Math.abs(distance) >= 0.001) {
label = "";
}
ticks.push({ position, label });
const label = isAllDurationInfinity && i === tickCount
? getStr("player.infiniteTimeLabel")
: timeScale.formatTime(distance);
ticks.push({ position, label, width: intervalWidth });
}
this.setState({ ticks });

Просмотреть файл

@ -29,7 +29,10 @@ class TickLabels extends PureComponent {
dom.div(
{
className: "tick-label",
style: { marginInlineStart: `${ tick.position }%` },
style: {
marginInlineStart: `${ tick.position }%`,
maxWidth: `${ tick.width }px`
},
},
tick.label
)

Просмотреть файл

@ -646,6 +646,9 @@ select.playback-rate-selector.devtools-button:not(:empty):not(:disabled):not(.ch
border-inline-start: var(--tick-line-style);
height: 100%;
position: absolute;
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
}
.animated-property-list-container .tick-label:last-child {

Просмотреть файл

@ -307,6 +307,7 @@ class FilterBar extends Component {
return (
dom.div({
className: "webconsole-filteringbar-wrapper",
"aria-live": "off",
ref: node => {
this.wrapperNode = node;
}

Просмотреть файл

@ -19,6 +19,7 @@ const TEST_URI = `data:text/html;charset=utf-8,<script>
window.logStuff = function () {
console.log("simple " + "text message");
function wrapper() {
console.log(new Error("error object"));
console.trace();
}
wrapper();
@ -100,6 +101,17 @@ add_task(async function() {
ok(TRACE_FORMAT.test(lines[1]), "Stacktrace line has the right format:\n" + lines[1]);
ok(TRACE_FORMAT.test(lines[2]), "Stacktrace line has the right format:\n" + lines[2]);
info("Test copy menu item for the error message");
message = await waitFor(() => findMessage(hud, "Error:"));
clipboardText = await copyMessageContent(hud, message);
ok(true, "Clipboard text was found and saved");
lines = clipboardText.split("\n");
is(lines[0], `Error: "error object"`, "Error object first line has expected text");
ok(lines[1].startsWith(`\twrapper data:text/html`),
"Error stacktrace first line starts with expected value");
ok(lines[2].startsWith(`\tlogStuff data:text/html`),
"Error stacktrace second line starts with expected value");
observer.destroy();
Services.prefs.clearUserPref(PREF_MESSAGE_TIMESTAMP);
});

Просмотреть файл

@ -6245,13 +6245,13 @@ nsIDocument::SetTitle(const nsAString& aTitle, ErrorResult& aRv)
}
#endif
// Batch updates so that mutation events don't change "the title
// element" under us
mozAutoDocUpdate updateBatch(this, true);
Maybe<mozAutoDocUpdate> updateBatch;
nsCOMPtr<Element> title = GetTitleElement();
if (rootElement->IsSVGElement(nsGkAtoms::svg)) {
if (!title) {
// Batch updates so that mutation events don't change "the title
// element" under us
updateBatch.emplace(this, true);
RefPtr<mozilla::dom::NodeInfo> titleInfo =
mNodeInfoManager->GetNodeInfo(nsGkAtoms::title, nullptr,
kNameSpaceID_SVG,
@ -6265,6 +6265,9 @@ nsIDocument::SetTitle(const nsAString& aTitle, ErrorResult& aRv)
}
} else if (rootElement->IsHTMLElement()) {
if (!title) {
// Batch updates so that mutation events don't change "the title
// element" under us
updateBatch.emplace(this, true);
Element* head = GetHeadElement();
if (!head) {
return;

Просмотреть файл

@ -144,6 +144,7 @@ support-files = bug1017086_inner.html
[test_bug1017086_enable.html]
support-files = bug1017086_inner.html
[test_bug1079236.html]
[test_bug1127588.html]
[test_bug1145910.html]
[test_bug1150308.html]
skip-if = true # bug 1421545

Просмотреть файл

@ -0,0 +1,61 @@
<!DOCTYPE HTML>
<html>
<!--
https://bugzilla.mozilla.org/show_bug.cgi?id=1127588
-->
<head>
<script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
</head>
<body>
<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=1127588">Mozilla Bug 1127588</a>
<p id="display"></p>
<div id="content" style="display: none">
<script type="application/javascript">
/** Test for Bug 1127588 **/
SimpleTest.waitForExplicitFinish();
window.onload = function () {
let insertedEventCount = 0;
let insertedListener = function() {
insertedEventCount++;
};
let removedEventCount = 0;
let removedListener = function() {
removedEventCount++;
};
// Tests for no title element.
document.addEventListener('DOMNodeRemoved', removedListener);
document.addEventListener('DOMNodeInserted', insertedListener);
document.title = "Test for Bug 1127588";
document.removeEventListener('DOMNodeInserted', insertedListener);
document.removeEventListener('DOMNodeRemoved', removedListener);
// Check result.
is(insertedEventCount, 2, "Should get 'DOMNodeInserted' mutation event");
is(removedEventCount, 0, "Should not get 'DOMNodeRemoved' mutation event");
// Test for updating title element.
insertedEventCount = 0;
removedEventCount = 0;
document.addEventListener('DOMNodeRemoved', removedListener);
document.addEventListener('DOMNodeInserted', insertedListener);
document.title = document.title;
document.removeEventListener('DOMNodeInserted', insertedListener);
document.removeEventListener('DOMNodeRemoved', removedListener);
// Check result.
is(insertedEventCount, 1, "Should get 'DOMNodeInserted' mutation event");
is(removedEventCount, 1, "Should get 'DOMNodeRemoved' mutation event");
SimpleTest.finish();
};
</script>
</body>
</html>

Просмотреть файл

@ -8,3 +8,4 @@ toolkit.jar:
content/global/BrowserElementChild.js (../browser-element/BrowserElementChild.js)
content/global/BrowserElementChildPreload.js (../browser-element/BrowserElementChildPreload.js)
content/global/BrowserElementCopyPaste.js (../browser-element/BrowserElementCopyPaste.js)
content/global/manifestMessages.js (manifestMessages.js)

Просмотреть файл

@ -11,52 +11,54 @@
*
* BUG: https://bugzilla.mozilla.org/show_bug.cgi?id=1083410
*/
/*globals Task, ManifestObtainer, ManifestFinder, content, sendAsyncMessage, addMessageListener, Components*/
"use strict";
var EXPORTED_SYMBOLS = ["ManifestMessages"];
const {
utils: Cu,
} = Components;
ChromeUtils.import("resource://gre/modules/XPCOMUtils.jsm");
ChromeUtils.defineModuleGetter(this, "ManifestObtainer",
"resource://gre/modules/ManifestObtainer.jsm");
"resource://gre/modules/ManifestObtainer.jsm");
ChromeUtils.defineModuleGetter(this, "ManifestFinder",
"resource://gre/modules/ManifestFinder.jsm");
"resource://gre/modules/ManifestFinder.jsm");
ChromeUtils.defineModuleGetter(this, "ManifestIcons",
"resource://gre/modules/ManifestIcons.jsm");
"resource://gre/modules/ManifestIcons.jsm");
class ManifestMessages {
constructor(mm) {
this.mm = mm;
}
receiveMessage(message) {
switch (message.name) {
case "DOM:WebManifest:hasManifestLink":
return this.hasManifestLink(message);
case "DOM:ManifestObtainer:Obtain":
return this.obtainManifest(message);
case "DOM:Manifest:FireAppInstalledEvent":
return this.fireAppInstalledEvent(message);
case "DOM:WebManifest:fetchIcon":
return this.fetchIcon(message);
}
return undefined;
}
const MessageHandler = {
registerListeners() {
addMessageListener(
"DOM:WebManifest:hasManifestLink",
this.hasManifestLink.bind(this)
);
addMessageListener(
"DOM:ManifestObtainer:Obtain",
this.obtainManifest.bind(this)
);
addMessageListener(
"DOM:Manifest:FireAppInstalledEvent",
this.fireAppInstalledEvent.bind(this)
);
addMessageListener(
"DOM:WebManifest:fetchIcon",
this.fetchIcon.bind(this)
);
},
/**
* Check if the this.mm.content document includes a link to a web manifest.
* Check if the content document includes a link to a web manifest.
* @param {Object} aMsg The IPC message, which is destructured to just
* get the id.
*/
hasManifestLink({data: {id}}) {
const response = makeMsgResponse(id);
response.result = ManifestFinder.contentHasManifestLink(this.mm.content);
response.result = ManifestFinder.contentHasManifestLink(content);
response.success = true;
this.mm.sendAsyncMessage("DOM:WebManifest:hasManifestLink", response);
}
sendAsyncMessage("DOM:WebManifest:hasManifestLink", response);
},
/**
* Asynchronously obtains a web manifest from this.mm.content by using the
* Asynchronously obtains a web manifest from content by using the
* ManifestObtainer and messages back the result.
* @param {Object} aMsg The IPC message, which is destructured to just
* get the id.
@ -64,26 +66,26 @@ class ManifestMessages {
async obtainManifest({data: {id}}) {
const response = makeMsgResponse(id);
try {
response.result = await ManifestObtainer.contentObtainManifest(this.mm.content);
response.result = await ManifestObtainer.contentObtainManifest(content);
response.success = true;
} catch (err) {
response.result = serializeError(err);
}
this.mm.sendAsyncMessage("DOM:ManifestObtainer:Obtain", response);
}
sendAsyncMessage("DOM:ManifestObtainer:Obtain", response);
},
fireAppInstalledEvent({data: {id}}) {
fireAppInstalledEvent({data: {id}}){
const ev = new Event("appinstalled");
const response = makeMsgResponse(id);
if (!this.mm.content || this.mm.content.top !== this.mm.content) {
if (!content || content.top !== content) {
const msg = "Can only dispatch install event on top-level browsing contexts.";
response.result = serializeError(new Error(msg));
} else {
response.success = true;
this.mm.content.dispatchEvent(ev);
content.dispatchEvent(ev);
}
this.mm.sendAsyncMessage("DOM:Manifest:FireAppInstalledEvent", response);
}
sendAsyncMessage("DOM:Manifest:FireAppInstalledEvent", response);
},
/**
* Given a manifest and an expected icon size, ask ManifestIcons
@ -93,15 +95,15 @@ class ManifestMessages {
const response = makeMsgResponse(id);
try {
response.result =
await ManifestIcons.contentFetchIcon(this.mm.content, manifest, iconSize);
await ManifestIcons.contentFetchIcon(content, manifest, iconSize);
response.success = true;
} catch (err) {
response.result = serializeError(err);
}
this.mm.sendAsyncMessage("DOM:WebManifest:fetchIcon", response);
}
}
sendAsyncMessage("DOM:WebManifest:fetchIcon", response);
},
};
/**
* Utility function to Serializes an JS Error, so it can be transferred over
* the message channel.
@ -122,9 +124,11 @@ function serializeError(aError) {
}
function makeMsgResponse(aId) {
return {
id: aId,
success: false,
result: undefined
};
}
return {
id: aId,
success: false,
result: undefined
};
}
MessageHandler.registerListeners();

Просмотреть файл

@ -13,10 +13,6 @@ XPIDL_SOURCES += [
XPIDL_MODULE = 'dom'
EXTRA_JS_MODULES += [
'ManifestMessages.jsm',
]
EXPORTS.mozilla.dom.ipc += [
'IdType.h',
'MemMapSnapshot.h',

Просмотреть файл

@ -496,7 +496,7 @@ RestyleManager::ContentRemoved(nsIContent* aOldChild,
* This is called from both Restyle managers.
*/
void
RestyleManager::ContentStateChangedInternal(Element* aElement,
RestyleManager::ContentStateChangedInternal(const Element& aElement,
EventStates aStateMask,
nsChangeHint* aOutChangeHint)
{
@ -510,7 +510,7 @@ RestyleManager::ContentStateChangedInternal(Element* aElement,
// based on content states, so if we already don't have a frame we don't
// need to force a reframe -- if it's needed, the HasStateDependentStyle
// call will handle things.
nsIFrame* primaryFrame = aElement->GetPrimaryFrame();
nsIFrame* primaryFrame = aElement.GetPrimaryFrame();
if (primaryFrame) {
// If it's generated content, ignore LOADING/etc state changes on it.
if (!primaryFrame->IsGeneratedContentFrame() &&
@ -2200,8 +2200,8 @@ ServoRestyleState::TableAwareParentFor(const nsIFrame* aChild)
void
RestyleManager::PostRestyleEvent(Element* aElement,
nsRestyleHint aRestyleHint,
nsChangeHint aMinChangeHint)
nsRestyleHint aRestyleHint,
nsChangeHint aMinChangeHint)
{
MOZ_ASSERT(!(aMinChangeHint & nsChangeHint_NeutralChange),
"Didn't expect explicit change hints to be neutral!");
@ -2945,7 +2945,7 @@ RestyleManager::ClearSnapshots()
}
ServoElementSnapshot&
RestyleManager::SnapshotFor(Element* aElement)
RestyleManager::SnapshotFor(Element& aElement)
{
MOZ_ASSERT(!mInStyleRefresh);
@ -2959,14 +2959,14 @@ RestyleManager::SnapshotFor(Element* aElement)
//
// Can't wait to make ProcessPendingRestyles the only entry-point for styling,
// so this becomes much easier to reason about. Today is not that day though.
MOZ_ASSERT(aElement->HasServoData());
MOZ_ASSERT(!aElement->HasFlag(ELEMENT_HANDLED_SNAPSHOT));
MOZ_ASSERT(aElement.HasServoData());
MOZ_ASSERT(!aElement.HasFlag(ELEMENT_HANDLED_SNAPSHOT));
ServoElementSnapshot* snapshot = mSnapshots.LookupOrAdd(aElement, aElement);
aElement->SetFlags(ELEMENT_HAS_SNAPSHOT);
ServoElementSnapshot* snapshot = mSnapshots.LookupOrAdd(&aElement, aElement);
aElement.SetFlags(ELEMENT_HAS_SNAPSHOT);
// Now that we have a snapshot, make sure a restyle is triggered.
aElement->NoteDirtyForServo();
aElement.NoteDirtyForServo();
return *snapshot;
}
@ -3177,30 +3177,33 @@ RestyleManager::ContentStateChanged(nsIContent* aContent,
return;
}
Element* aElement = aContent->AsElement();
if (!aElement->HasServoData()) {
Element& element = *aContent->AsElement();
if (!element.HasServoData()) {
return;
}
nsChangeHint changeHint;
ContentStateChangedInternal(aElement, aChangedBits, &changeHint);
ContentStateChangedInternal(element, aChangedBits, &changeHint);
// Don't bother taking a snapshot if no rules depend on these state bits.
//
// We always take a snapshot for the LTR/RTL event states, since Servo doesn't
// track those bits in the same way, and we know that :dir() rules are always
// present in UA style sheets.
//
// FIXME(emilio): Doesn't this early-return drop the change hint on the floor?
// Should it?
if (!aChangedBits.HasAtLeastOneOfStates(DIRECTION_STATES) &&
!StyleSet()->HasStateDependency(*aElement, aChangedBits)) {
!StyleSet()->HasStateDependency(element, aChangedBits)) {
return;
}
ServoElementSnapshot& snapshot = SnapshotFor(aElement);
EventStates previousState = aElement->StyleState() ^ aChangedBits;
ServoElementSnapshot& snapshot = SnapshotFor(element);
EventStates previousState = element.StyleState() ^ aChangedBits;
snapshot.AddState(previousState);
if (changeHint) {
Servo_NoteExplicitHints(aElement, nsRestyleHint(0), changeHint);
Servo_NoteExplicitHints(&element, nsRestyleHint(0), changeHint);
}
// Assuming we need to invalidate cached style in getComputedStyle for
@ -3271,30 +3274,30 @@ RestyleManager::AttributeWillChange(Element* aElement,
int32_t aModType,
const nsAttrValue* aNewValue)
{
TakeSnapshotForAttributeChange(aElement, aNameSpaceID, aAttribute);
TakeSnapshotForAttributeChange(*aElement, aNameSpaceID, aAttribute);
}
void
RestyleManager::ClassAttributeWillBeChangedBySMIL(Element* aElement)
{
TakeSnapshotForAttributeChange(aElement, kNameSpaceID_None,
TakeSnapshotForAttributeChange(*aElement, kNameSpaceID_None,
nsGkAtoms::_class);
}
void
RestyleManager::TakeSnapshotForAttributeChange(Element* aElement,
RestyleManager::TakeSnapshotForAttributeChange(Element& aElement,
int32_t aNameSpaceID,
nsAtom* aAttribute)
{
MOZ_ASSERT(!mInStyleRefresh);
if (!aElement->HasServoData()) {
if (!aElement.HasServoData()) {
return;
}
bool influencesOtherPseudoClassState;
if (!NeedToRecordAttrChange(*StyleSet(),
*aElement,
aElement,
aNameSpaceID,
aAttribute,
&influencesOtherPseudoClassState)) {

Просмотреть файл

@ -472,7 +472,9 @@ protected:
void RestyleForEmptyChange(Element* aContainer);
void MaybeRestyleForEdgeChildChange(Element* aContainer, nsIContent* aChangedChild);
void ContentStateChangedInternal(Element* aElement,
// TODO(emilio): there's no good reason this isn't part of ContentStateChanged
// now, or the change hint isn't returned instead of via an out-param, really.
void ContentStateChangedInternal(const Element&,
EventStates aStateMask,
nsChangeHint* aOutChangeHint);
@ -529,8 +531,8 @@ protected:
const SnapshotTable& Snapshots() const { return mSnapshots; }
void ClearSnapshots();
ServoElementSnapshot& SnapshotFor(mozilla::dom::Element* aElement);
void TakeSnapshotForAttributeChange(mozilla::dom::Element* aElement,
ServoElementSnapshot& SnapshotFor(Element&);
void TakeSnapshotForAttributeChange(Element&,
int32_t aNameSpaceID,
nsAtom* aAttribute);

Просмотреть файл

@ -12,7 +12,7 @@
namespace mozilla {
ServoElementSnapshot::ServoElementSnapshot(const Element* aElement)
ServoElementSnapshot::ServoElementSnapshot(const Element& aElement)
: mState(0)
, mContains(Flags(0))
, mIsTableBorderNonzero(false)
@ -22,23 +22,22 @@ ServoElementSnapshot::ServoElementSnapshot(const Element* aElement)
, mOtherAttributeChanged(false)
{
MOZ_COUNT_CTOR(ServoElementSnapshot);
MOZ_ASSERT(NS_IsMainThread());
mIsHTMLElementInHTMLDocument =
aElement->IsHTMLElement() && aElement->IsInHTMLDocument();
mIsInChromeDocument = nsContentUtils::IsChromeDoc(aElement->OwnerDoc());
mSupportsLangAttr = aElement->SupportsLangAttr();
aElement.IsHTMLElement() && aElement.IsInHTMLDocument();
mIsInChromeDocument = nsContentUtils::IsChromeDoc(aElement.OwnerDoc());
mSupportsLangAttr = aElement.SupportsLangAttr();
}
void
ServoElementSnapshot::AddOtherPseudoClassState(Element* aElement)
ServoElementSnapshot::AddOtherPseudoClassState(const Element& aElement)
{
MOZ_ASSERT(aElement);
if (HasOtherPseudoClassState()) {
return;
}
mIsTableBorderNonzero = Gecko_IsTableBorderNonzero(aElement);
mIsMozBrowserFrame = Gecko_IsBrowserFrame(aElement);
mIsTableBorderNonzero = Gecko_IsTableBorderNonzero(&aElement);
mIsMozBrowserFrame = Gecko_IsBrowserFrame(&aElement);
mContains |= Flags::OtherPseudoClassState;
}

Просмотреть файл

@ -67,10 +67,11 @@ class ServoElementSnapshot
public:
typedef ServoElementSnapshotFlags Flags;
explicit ServoElementSnapshot(const Element* aElement);
explicit ServoElementSnapshot(const Element&);
~ServoElementSnapshot()
{
MOZ_ASSERT(NS_IsMainThread());
MOZ_COUNT_DTOR(ServoElementSnapshot);
}
@ -100,13 +101,13 @@ public:
* The attribute name and namespace are used to note which kind of attribute
* has changed.
*/
inline void AddAttrs(Element*, int32_t aNameSpaceID, nsAtom* aAttribute);
inline void AddAttrs(const Element&, int32_t aNameSpaceID, nsAtom* aAttribute);
/**
* Captures some other pseudo-class matching state not included in
* EventStates.
*/
void AddOtherPseudoClassState(Element* aElement);
void AddOtherPseudoClassState(const Element&);
/**
* Needed methods for attribute matching.
@ -194,7 +195,7 @@ private:
inline void
ServoElementSnapshot::AddAttrs(mozilla::dom::Element* aElement,
ServoElementSnapshot::AddAttrs(const Element& aElement,
int32_t aNameSpaceID,
nsAtom* aAttribute)
{
@ -214,20 +215,20 @@ ServoElementSnapshot::AddAttrs(mozilla::dom::Element* aElement,
return;
}
uint32_t attrCount = aElement->GetAttrCount();
uint32_t attrCount = aElement.GetAttrCount();
mAttrs.SetCapacity(attrCount);
for (uint32_t i = 0; i < attrCount; ++i) {
const BorrowedAttrInfo info = aElement->GetAttrInfoAt(i);
const BorrowedAttrInfo info = aElement.GetAttrInfoAt(i);
MOZ_ASSERT(info);
mAttrs.AppendElement(ServoAttrSnapshot { *info.mName, *info.mValue });
}
mContains |= Flags::Attributes;
if (aElement->HasID()) {
if (aElement.HasID()) {
mContains |= Flags::Id;
}
if (const nsAttrValue* classValue = aElement->GetClasses()) {
if (const nsAttrValue* classValue = aElement.GetClasses()) {
// FIXME(emilio): It's pretty unfortunate that this is only relevant for
// SVG, yet it's a somewhat expensive copy. We should be able to do
// better!

Просмотреть файл

@ -103,31 +103,6 @@ async function updatePinningList({ data: { current: records } }) {
}
}
/**
* Write list of records into JSON file, and notify nsBlocklistService.
*
* @param {Object} client RemoteSettingsClient instance
* @param {Object} data Current records in the local db.
*/
async function updateJSONBlocklist(client, { data: { current: records } }) {
// Write JSON dump for synchronous load at startup.
const path = OS.Path.join(OS.Constants.Path.profileDir, client.filename);
const blocklistFolder = OS.Path.dirname(path);
await OS.File.makeDir(blocklistFolder, {from: OS.Constants.Path.profileDir});
const serialized = JSON.stringify({data: records}, null, 2);
try {
await OS.File.writeAtomic(path, serialized, {tmpPath: path + ".tmp"});
// Notify change to `nsBlocklistService`
const eventData = {filename: client.filename};
Services.cpmm.sendAsyncMessage("Blocklist:reload-from-disk", eventData);
} catch (e) {
Cu.reportError(e);
}
}
/**
* This custom filter function is used to limit the entries returned
* by `RemoteSettings("...").get()` depending on the target app information
@ -211,7 +186,6 @@ function initialize() {
signerName: Services.prefs.getCharPref(PREF_BLOCKLIST_ADDONS_SIGNER),
filterFunc: targetAppFilter,
});
AddonBlocklistClient.on("sync", updateJSONBlocklist.bind(null, AddonBlocklistClient));
PluginBlocklistClient = RemoteSettings(Services.prefs.getCharPref(PREF_BLOCKLIST_PLUGINS_COLLECTION), {
bucketName: Services.prefs.getCharPref(PREF_BLOCKLIST_BUCKET),
@ -219,7 +193,6 @@ function initialize() {
signerName: Services.prefs.getCharPref(PREF_BLOCKLIST_PLUGINS_SIGNER),
filterFunc: targetAppFilter,
});
PluginBlocklistClient.on("sync", updateJSONBlocklist.bind(null, PluginBlocklistClient));
GfxBlocklistClient = RemoteSettings(Services.prefs.getCharPref(PREF_BLOCKLIST_GFX_COLLECTION), {
bucketName: Services.prefs.getCharPref(PREF_BLOCKLIST_BUCKET),
@ -227,7 +200,6 @@ function initialize() {
signerName: Services.prefs.getCharPref(PREF_BLOCKLIST_GFX_SIGNER),
filterFunc: targetAppFilter,
});
GfxBlocklistClient.on("sync", updateJSONBlocklist.bind(null, GfxBlocklistClient));
PinningBlocklistClient = RemoteSettings(Services.prefs.getCharPref(PREF_BLOCKLIST_PINNING_COLLECTION), {
bucketName: Services.prefs.getCharPref(PREF_BLOCKLIST_PINNING_BUCKET),

Просмотреть файл

@ -4,7 +4,6 @@ ChromeUtils.import("resource://gre/modules/AppConstants.jsm");
ChromeUtils.import("resource://gre/modules/Services.jsm");
ChromeUtils.import("resource://testing-common/httpd.js");
const { FileUtils } = ChromeUtils.import("resource://gre/modules/FileUtils.jsm", {});
const { OS } = ChromeUtils.import("resource://gre/modules/osfile.jsm", {});
const { RemoteSettings } = ChromeUtils.import("resource://services-settings/remote-settings.js", {});
const BlocklistClients = ChromeUtils.import("resource://services-common/blocklist-clients.js", {});
@ -18,12 +17,6 @@ const IS_ANDROID = AppConstants.platform == "android";
let gBlocklistClients;
let server;
async function readJSON(filepath) {
const binaryData = await OS.File.read(filepath);
const textData = (new TextDecoder()).decode(binaryData);
return Promise.resolve(JSON.parse(textData));
}
async function clear_state() {
for (let {client} of gBlocklistClients) {
// Remove last server times.
@ -32,11 +25,6 @@ async function clear_state() {
// Clear local DB.
const collection = await client.openCollection();
await collection.clear();
// Remove JSON dumps folders in profile dir.
const dumpFile = OS.Path.join(OS.Constants.Path.profileDir, client.filename);
const folder = OS.Path.dirname(dumpFile);
await OS.File.removeDir(folder, { ignoreAbsent: true });
}
}
@ -146,21 +134,6 @@ add_task(async function test_initial_dump_is_loaded_when_using_get_on_empty_coll
});
add_task(clear_state);
add_task(async function test_list_is_written_to_file_in_profile() {
for (let {client, testData} of gBlocklistClients) {
const filePath = OS.Path.join(OS.Constants.Path.profileDir, client.filename);
const profFile = new FileUtils.File(filePath);
strictEqual(profFile.exists(), false);
await client.maybeSync(2000, Date.now(), {loadDump: false});
strictEqual(profFile.exists(), true);
const content = await readJSON(profFile.path);
equal(content.data[0].blockID, testData[testData.length - 1]);
}
});
add_task(clear_state);
add_task(async function test_current_server_time_is_saved_in_pref() {
for (let {client} of gBlocklistClients) {
// The lastCheckTimePref was customized:
@ -174,42 +147,6 @@ add_task(async function test_current_server_time_is_saved_in_pref() {
});
add_task(clear_state);
add_task(async function test_update_json_file_when_addons_has_changes() {
for (let {client, testData} of gBlocklistClients) {
await client.maybeSync(2000, Date.now() - 1000, {loadDump: false});
const filePath = OS.Path.join(OS.Constants.Path.profileDir, client.filename);
const profFile = new FileUtils.File(filePath);
const fileLastModified = profFile.lastModifiedTime = profFile.lastModifiedTime - 1000;
const serverTime = Date.now();
await client.maybeSync(3001, serverTime);
// File was updated.
notEqual(fileLastModified, profFile.lastModifiedTime);
const content = await readJSON(profFile.path);
deepEqual(content.data.map((r) => r.blockID), testData);
// Server time was updated.
const after = Services.prefs.getIntPref(client.lastCheckTimePref);
equal(after, Math.round(serverTime / 1000));
}
});
add_task(clear_state);
add_task(async function test_sends_reload_message_when_blocklist_has_changes() {
for (let {client} of gBlocklistClients) {
let received = await new Promise((resolve, reject) => {
Services.ppmm.addMessageListener("Blocklist:reload-from-disk", {
receiveMessage(aMsg) { resolve(aMsg); }
});
client.maybeSync(2000, Date.now() - 1000, {loadDump: false});
});
equal(received.data.filename, client.filename);
}
});
add_task(clear_state);
add_task(async function test_sync_event_data_is_filtered_for_target() {
// Here we will synchronize 4 times, the first two to initialize the local DB and
// the last two about event filtered data.

Просмотреть файл

@ -192,11 +192,11 @@ async function fetchLatestChanges(url, lastEtag) {
/**
* Load the the JSON file distributed with the release for this collection.
* @param {String} bucket
* @param {String} collection
*/
async function loadDumpFile(filename) {
// Replace OS specific path separator by / for URI.
const { components: folderFile } = OS.Path.split(filename);
const fileURI = `resource://app/defaults/settings/${folderFile.join("/")}`;
async function loadDumpFile(bucket, collection) {
const fileURI = `resource://app/defaults/settings/${bucket}/${collection}.json`;
const response = await fetch(fileURI);
if (!response.ok) {
throw new Error(`Could not read from '${fileURI}'`);
@ -225,12 +225,6 @@ class RemoteSettingsClient {
return `${this.bucketName}/${this.collectionName}`;
}
get filename() {
// Replace slash by OS specific path separator (eg. Windows)
const identifier = OS.Path.join(...this.identifier.split("/"));
return `${identifier}.json`;
}
get lastCheckTimePref() {
return this._lastCheckTimePref || `services.settings.${this.bucketName}.${this.collectionName}.last_check`;
}
@ -302,7 +296,7 @@ class RemoteSettingsClient {
// a packaged JSON dump.
if (timestamp == null) {
try {
const { data } = await loadDumpFile(this.filename);
const { data } = await loadDumpFile(this.bucketName, this.collectionName);
await c.loadDump(data);
} catch (e) {
// Report but return an empty list since there will be no data anyway.
@ -353,7 +347,7 @@ class RemoteSettingsClient {
// cold start.
if (!collectionLastModified && loadDump) {
try {
const initialData = await loadDumpFile(this.filename);
const initialData = await loadDumpFile(this.bucketName, this.collectionName);
await collection.loadDump(initialData.data);
collectionLastModified = await collection.db.getLastModified();
} catch (e) {
@ -586,9 +580,8 @@ async function databaseExists(bucket, collection) {
* @return {bool} Whether it is present or not.
*/
async function hasLocalDump(bucket, collection) {
const filename = OS.Path.join(bucket, `${collection}.json`);
try {
await loadDumpFile(filename);
await loadDumpFile(bucket, collection);
return true;
} catch (e) {
return false;

Просмотреть файл

@ -45,12 +45,6 @@ pub trait Element: Sized + Clone + Debug {
self.parent_element()
}
/// Skips non-element nodes
fn first_child_element(&self) -> Option<Self>;
/// Skips non-element nodes
fn last_child_element(&self) -> Option<Self>;
/// Skips non-element nodes
fn prev_sibling_element(&self) -> Option<Self>;

Просмотреть файл

@ -120,7 +120,6 @@ mod bindings {
let mut file = File::open(&path).unwrap();
let mut content = String::new();
file.read_to_string(&mut content).unwrap();
println!("cargo:rerun-if-changed={}", path.to_str().unwrap());
added_paths.insert(path);
// Find all includes and add them recursively
for cap in INCLUDE_RE.captures_iter(&content) {
@ -286,6 +285,7 @@ mod bindings {
);
},
};
for fixup in fixups.iter() {
result = Regex::new(&fixup.pat)
.unwrap()
@ -602,6 +602,10 @@ mod bindings {
generate_bindings(),
generate_atoms(),
}
for path in ADDED_PATHS.lock().unwrap().iter() {
println!("cargo:rerun-if-changed={}", path.to_str().unwrap());
}
}
}

Просмотреть файл

@ -16,7 +16,6 @@ use selector_parser::{PseudoElement, RestyleDamage, EAGER_PSEUDO_COUNT};
use selectors::NthIndexCache;
use servo_arc::Arc;
use shared_lock::StylesheetGuards;
use smallvec::SmallVec;
use std::fmt;
use std::mem;
use std::ops::{Deref, DerefMut};
@ -273,16 +272,8 @@ impl ElementData {
return InvalidationResult::empty();
}
let mut non_document_styles = SmallVec::<[_; 3]>::new();
let matches_doc_author_rules =
element.each_applicable_non_document_style_rule_data(|data, quirks_mode, host| {
non_document_styles.push((data, quirks_mode, host.map(|h| h.opaque())))
});
let mut processor = StateAndAttrInvalidationProcessor::new(
shared_context,
&non_document_styles,
matches_doc_author_rules,
element,
self,
nth_index_cache,

Просмотреть файл

@ -1957,30 +1957,6 @@ impl<'le> ::selectors::Element for GeckoElement<'le> {
unsafe { Some(GeckoElement(&slot.as_ref()?._base._base._base._base)) }
}
#[inline]
fn first_child_element(&self) -> Option<Self> {
let mut child = self.as_node().first_child();
while let Some(child_node) = child {
if let Some(el) = child_node.as_element() {
return Some(el);
}
child = child_node.next_sibling();
}
None
}
#[inline]
fn last_child_element(&self) -> Option<Self> {
let mut child = self.as_node().last_child();
while let Some(child_node) = child {
if let Some(el) = child_node.as_element() {
return Some(el);
}
child = child_node.prev_sibling();
}
None
}
#[inline]
fn prev_sibling_element(&self) -> Option<Self> {
let mut sibling = self.as_node().prev_sibling();

Просмотреть файл

@ -283,16 +283,6 @@ where
Some(Self::new(host, self.snapshot_map))
}
fn first_child_element(&self) -> Option<Self> {
let child = self.element.first_child_element()?;
Some(Self::new(child, self.snapshot_map))
}
fn last_child_element(&self) -> Option<Self> {
let child = self.element.last_child_element()?;
Some(Self::new(child, self.snapshot_map))
}
fn prev_sibling_element(&self) -> Option<Self> {
let sibling = self.element.prev_sibling_element()?;
Some(Self::new(sibling, self.snapshot_map))

Просмотреть файл

@ -6,7 +6,7 @@
//! changes.
use {Atom, WeakAtom};
use context::{QuirksMode, SharedStyleContext};
use context::SharedStyleContext;
use data::ElementData;
use dom::TElement;
use element_state::ElementState;
@ -18,13 +18,11 @@ use invalidation::element::restyle_hints::RestyleHint;
use selector_map::SelectorMap;
use selector_parser::Snapshot;
use selectors::NthIndexCache;
use selectors::OpaqueElement;
use selectors::attr::CaseSensitivity;
use selectors::matching::{MatchingContext, MatchingMode, VisitedHandlingMode};
use selectors::matching::matches_selector;
use smallvec::SmallVec;
use stylesheets::origin::{Origin, OriginSet};
use stylist::CascadeData;
#[derive(Debug, PartialEq)]
enum VisitedDependent {
@ -56,19 +54,15 @@ where
/// changes.
pub struct StateAndAttrInvalidationProcessor<'a, 'b: 'a, E: TElement> {
shared_context: &'a SharedStyleContext<'b>,
shadow_rule_datas: &'a [(&'b CascadeData, QuirksMode, Option<OpaqueElement>)],
matches_document_author_rules: bool,
element: E,
data: &'a mut ElementData,
matching_context: MatchingContext<'a, E::Impl>,
}
impl<'a, 'b: 'a, E: TElement> StateAndAttrInvalidationProcessor<'a, 'b, E> {
impl<'a, 'b: 'a, E: TElement + 'b> StateAndAttrInvalidationProcessor<'a, 'b, E> {
/// Creates a new StateAndAttrInvalidationProcessor.
pub fn new(
shared_context: &'a SharedStyleContext<'b>,
shadow_rule_datas: &'a [(&'b CascadeData, QuirksMode, Option<OpaqueElement>)],
matches_document_author_rules: bool,
element: E,
data: &'a mut ElementData,
nth_index_cache: &'a mut NthIndexCache,
@ -83,8 +77,6 @@ impl<'a, 'b: 'a, E: TElement> StateAndAttrInvalidationProcessor<'a, 'b, E> {
Self {
shared_context,
shadow_rule_datas,
matches_document_author_rules,
element,
data,
matching_context,
@ -157,6 +149,7 @@ where
descendant_invalidations: &mut DescendantInvalidationLists<'a>,
sibling_invalidations: &mut InvalidationVector<'a>,
) -> bool {
debug_assert_eq!(element, self.element);
debug_assert!(element.has_snapshot(), "Why bothering?");
let wrapper = ElementWrapper::new(element, &*self.shared_context.snapshot_map);
@ -241,6 +234,13 @@ where
element
};
let mut shadow_rule_datas = SmallVec::<[_; 3]>::new();
let matches_document_author_rules =
element.each_applicable_non_document_style_rule_data(|data, quirks_mode, host| {
shadow_rule_datas.push((data, quirks_mode, host.map(|h| h.opaque())))
});
let invalidated_self = {
let mut collector = Collector {
wrapper,
@ -258,7 +258,7 @@ where
invalidates_self: false,
};
let document_origins = if !self.matches_document_author_rules {
let document_origins = if !matches_document_author_rules {
Origin::UserAgent.into()
} else {
OriginSet::all()
@ -271,7 +271,7 @@ where
}
}
for &(ref data, quirks_mode, ref host) in self.shadow_rule_datas {
for &(ref data, quirks_mode, ref host) in &shadow_rule_datas {
// FIXME(emilio): Replace with assert / remove when we figure
// out what to do with the quirks mode mismatches
// (that is, when bug 1406875 is properly fixed).

Просмотреть файл

@ -305,10 +305,10 @@
},
"redo": {
"hashes": [
"sha256:69ea97e4d934806475fe86f93e4f74da2994acab20c2e3cfe0d3ca6380e3f907"
"sha256:080e9eb34c42e2a09dbec48379b876ac1b64fd04483cef0a03af281cc9333bd3"
],
"index": "pypi",
"version": "==1.6"
"version": "==1.7"
},
"requests": {
"hashes": [
@ -366,18 +366,18 @@
},
"taskcluster": {
"hashes": [
"sha256:1c2b36928170ddb73ada7c5548b8ae8c9604d188d9feef79cdcb67eedd9829cc",
"sha256:2574a01171704e71ab9e5b540ca176e6da44b033ba3a396856c24d11ab1e9bfc",
"sha256:5866b8e89905fd75e9467291ee1acfbc81c61b5eda6a45aea5ac63602291ad70"
"sha256:27256511044346ac71a495d3c636f2add95c102b9b09f90d6fb1ea3e9949d311",
"sha256:99dd90bc1c566968868c8b07ede32f8e031cbccd52c7195a61e802679d461447",
"sha256:d0360063c1a3fcaaa514bb31c03954ba573d2b671df40a2ecfdfd9339cc8e93e"
],
"version": "==4.0.0"
"version": "==4.0.1"
},
"urllib3": {
"hashes": [
"sha256:a68ac5e15e76e7e5dd2b8f94007233e01effe3e50e8daddf69acfd81cb686baf",
"sha256:b5725a0bd4ba422ab0e66e89e030c806576753ea3ee08554382c14e685d117b5"
],
"markers": "python_version != '3.1.*' and python_version != '3.2.*' and python_version != '3.3.*' and python_version != '3.0.*' and python_version < '4' and python_version >= '2.6'",
"markers": "python_version != '3.1.*' and python_version != '3.0.*' and python_version < '4' and python_version != '3.2.*' and python_version != '3.3.*' and python_version >= '2.6'",
"version": "==1.23"
},
"virtualenv": {
@ -385,7 +385,7 @@
"sha256:2ce32cd126117ce2c539f0134eb89de91a8413a29baac49cbab3eb50e2026669",
"sha256:ca07b4c0b54e14a91af9f34d0919790b016923d157afda5efdde55c96718f752"
],
"markers": "python_version != '3.1.*' and python_version != '3.2.*' and python_version >= '2.7' and python_version != '3.0.*'",
"markers": "python_version != '3.1.*' and python_version != '3.0.*' and python_version != '3.2.*' and python_version >= '2.7'",
"version": "==16.0.0"
},
"yarl": {
@ -400,6 +400,7 @@
"sha256:f17495e6fe3d377e3faac68121caef6f974fcb9e046bc075bcff40d8e5cc69a4",
"sha256:f85900b9cca0c67767bb61b2b9bd53208aaa7373dae633dbe25d179b4bf38aa7"
],
"markers": "python_version >= '3.4.1'",
"version": "==1.2.6"
}
},

Просмотреть файл

@ -8,8 +8,7 @@ const Cm = Components.manager;
const CONTRACT_ID = "@mozilla.org/filepicker;1";
ChromeUtils.defineModuleGetter(this, "FileUtils",
"resource://gre/modules/FileUtils.jsm");
ChromeUtils.import("resource://gre/modules/FileUtils.jsm");
ChromeUtils.import("resource://gre/modules/Services.jsm");
// Allow stuff from this scope to be accessed from non-privileged scopes. This

Просмотреть файл

@ -12,23 +12,15 @@
var global = this;
ChromeUtils.import("resource://specialpowers/MockFilePicker.jsm");
ChromeUtils.import("resource://specialpowers/MockColorPicker.jsm");
ChromeUtils.import("resource://specialpowers/MockPermissionPrompt.jsm");
ChromeUtils.import("resource://gre/modules/Services.jsm");
ChromeUtils.import("resource://gre/modules/PrivateBrowsingUtils.jsm");
ChromeUtils.import("resource://gre/modules/XPCOMUtils.jsm");
ChromeUtils.defineModuleGetter(this, "MockFilePicker",
"resource://specialpowers/MockFilePicker.jsm");
ChromeUtils.defineModuleGetter(this, "MockColorPicker",
"resource://specialpowers/MockColorPicker.jsm");
ChromeUtils.defineModuleGetter(this, "MockPermissionPrompt",
"resource://specialpowers/MockPermissionPrompt.jsm");
ChromeUtils.defineModuleGetter(this, "PrivateBrowsingUtils",
"resource://gre/modules/PrivateBrowsingUtils.jsm");
ChromeUtils.defineModuleGetter(this, "NetUtil",
"resource://gre/modules/NetUtil.jsm");
ChromeUtils.defineModuleGetter(this, "AppConstants",
"resource://gre/modules/AppConstants.jsm");
ChromeUtils.defineModuleGetter(this, "ServiceWorkerCleanUp",
"resource://gre/modules/ServiceWorkerCleanUp.jsm");
ChromeUtils.import("resource://gre/modules/NetUtil.jsm");
ChromeUtils.import("resource://gre/modules/AppConstants.jsm");
ChromeUtils.import("resource://gre/modules/ServiceWorkerCleanUp.jsm");
ChromeUtils.defineModuleGetter(this, "PerTestCoverageUtils",
"resource://testing-common/PerTestCoverageUtils.jsm");

Просмотреть файл

@ -1784,6 +1784,9 @@ class Extension extends ExtensionData {
// If the extension has to migrate backend, ensure that the data migration
// starts once Firefox is idle after the extension has been started.
this.once("ready", () => ChromeUtils.idleDispatch(() => {
if (this.hasShutdown) {
return;
}
ExtensionStorageIDB.selectBackend({extension: this});
}));
}
@ -1846,6 +1849,17 @@ class Extension extends ExtensionData {
return;
}
if (this.hasPermission("storage") && ExtensionStorageIDB.selectedBackendPromises.has(this)) {
// Wait the data migration to complete.
try {
await ExtensionStorageIDB.selectedBackendPromises.get(this);
} catch (err) {
Cu.reportError(
`Error while waiting for extension data migration on shutdown: ${this.policy.debugName} - ` +
`${err.message}::${err.stack}`);
}
}
if (this.rootURI instanceof Ci.nsIJARURI) {
let file = this.rootURI.JARFile.QueryInterface(Ci.nsIFileURL).file;
Services.ppmm.broadcastAsyncMessage("Extension:FlushJarCache", {path: file.path});

Просмотреть файл

@ -3,6 +3,7 @@
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
"use strict";
const Cm = Components.manager;
ChromeUtils.import("resource://gre/modules/Services.jsm");
ChromeUtils.import("resource://gre/modules/XPCOMUtils.jsm");
@ -20,6 +21,15 @@ var EXPORTED_SYMBOLS = ["AboutPages"];
const SHIELD_LEARN_MORE_URL_PREF = "app.normandy.shieldLearnMoreUrl";
// Due to bug 1051238 frame scripts are cached forever, so we can't update them
// as a restartless add-on. The Math.random() is the work around for this.
const PROCESS_SCRIPT = (
`resource://normandy-content/shield-content-process.js?${Math.random()}`
);
const FRAME_SCRIPT = (
`resource://normandy-content/shield-content-frame.js?${Math.random()}`
);
/**
* Class for managing an about: page that Normandy provides. Adapted from
* browser/extensions/pocket/content/AboutPocket.jsm.
@ -28,10 +38,10 @@ const SHIELD_LEARN_MORE_URL_PREF = "app.normandy.shieldLearnMoreUrl";
* @implements nsIAboutModule
*/
class AboutPage {
constructor({chromeUrl, aboutHost, classID, description, uriFlags}) {
constructor({chromeUrl, aboutHost, classId, description, uriFlags}) {
this.chromeUrl = chromeUrl;
this.aboutHost = aboutHost;
this.classID = Components.ID(classID);
this.classId = Components.ID(classId);
this.description = description;
this.uriFlags = uriFlags;
}
@ -51,6 +61,34 @@ class AboutPage {
}
return channel;
}
createInstance(outer, iid) {
if (outer !== null) {
throw Cr.NS_ERROR_NO_AGGREGATION;
}
return this.QueryInterface(iid);
}
/**
* Register this about: page with XPCOM. This must be called once in each
* process (parent and content) to correctly initialize the page.
*/
register() {
Cm.QueryInterface(Ci.nsIComponentRegistrar).registerFactory(
this.classId,
this.description,
`@mozilla.org/network/protocol/about;1?what=${this.aboutHost}`,
this,
);
}
/**
* Unregister this about: page with XPCOM. This must be called before the
* add-on is cleaned up if the page has been registered.
*/
unregister() {
Cm.QueryInterface(Ci.nsIComponentRegistrar).unregisterFactory(this.classId, this);
}
}
AboutPage.prototype.QueryInterface = ChromeUtils.generateQI([Ci.nsIAboutModule]);
@ -60,17 +98,23 @@ AboutPage.prototype.QueryInterface = ChromeUtils.generateQI([Ci.nsIAboutModule])
var AboutPages = {
async init() {
// Load scripts in content processes and tabs
Services.ppmm.loadProcessScript(PROCESS_SCRIPT, true);
Services.mm.loadFrameScript(FRAME_SCRIPT, true);
// Register about: pages and their listeners
this.aboutStudies.register();
this.aboutStudies.registerParentListeners();
CleanupManager.addCleanupHandler(() => {
// Stop loading processs scripts and notify existing scripts to clean up.
Services.ppmm.removeDelayedProcessScript(PROCESS_SCRIPT);
Services.ppmm.broadcastAsyncMessage("Shield:ShuttingDown");
Services.mm.removeDelayedFrameScript(FRAME_SCRIPT);
Services.mm.broadcastAsyncMessage("Shield:ShuttingDown");
// Clean up about pages
this.aboutStudies.unregisterParentListeners();
this.aboutStudies.unregister();
});
},
};
@ -84,7 +128,7 @@ XPCOMUtils.defineLazyGetter(this.AboutPages, "aboutStudies", () => {
const aboutStudies = new AboutPage({
chromeUrl: "resource://normandy-content/about-studies/about-studies.html",
aboutHost: "studies",
classID: "{6ab96943-a163-482c-9622-4faedc0e827f}",
classId: "{6ab96943-a163-482c-9622-4faedc0e827f}",
description: "Shield Study Listing",
uriFlags: (
Ci.nsIAboutModule.ALLOW_SCRIPT

Просмотреть файл

@ -3,8 +3,6 @@
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
"use strict";
var EXPORTED_SYMBOLS = ["ShieldFrameListener"];
/**
* Listen for DOM events bubbling up from the about:studies page, and perform
* privileged actions in response to them. If we need to do anything that the
@ -15,8 +13,11 @@ var EXPORTED_SYMBOLS = ["ShieldFrameListener"];
* is opened.
*/
/* global content addMessageListener removeMessageListener sendAsyncMessage */
ChromeUtils.import("resource://gre/modules/Services.jsm");
ChromeUtils.import("resource://gre/modules/XPCOMUtils.jsm");
ChromeUtils.import("resource://gre/modules/AppConstants.jsm");
const frameGlobal = {};
ChromeUtils.defineModuleGetter(
@ -37,10 +38,6 @@ XPCOMUtils.defineLazyGetter(this, "gStringBundle", function() {
* @implements EventListener
*/
class ShieldFrameListener {
constructor(mm) {
this.mm = mm;
}
handleEvent(event) {
// Abort if the current page isn't about:studies.
if (!this.ensureTrustedOrigin()) {
@ -49,23 +46,23 @@ class ShieldFrameListener {
// We waited until after we received an event to register message listeners
// in order to save resources for tabs that don't ever load about:studies.
this.mm.addMessageListener("Shield:ShuttingDown", this);
this.mm.addMessageListener("Shield:ReceiveStudyList", this);
this.mm.addMessageListener("Shield:ReceiveStudiesEnabled", this);
addMessageListener("Shield:ShuttingDown", this);
addMessageListener("Shield:ReceiveStudyList", this);
addMessageListener("Shield:ReceiveStudiesEnabled", this);
switch (event.detail.action) {
// Actions that require the parent process
case "GetRemoteValue:StudyList":
this.mm.sendAsyncMessage("Shield:GetStudyList");
sendAsyncMessage("Shield:GetStudyList");
break;
case "RemoveStudy":
this.mm.sendAsyncMessage("Shield:RemoveStudy", event.detail.data);
sendAsyncMessage("Shield:RemoveStudy", event.detail.data);
break;
case "GetRemoteValue:StudiesEnabled":
this.mm.sendAsyncMessage("Shield:GetStudiesEnabled");
sendAsyncMessage("Shield:GetStudiesEnabled");
break;
case "NavigateToDataPreferences":
this.mm.sendAsyncMessage("Shield:OpenDataPreferences");
sendAsyncMessage("Shield:OpenDataPreferences");
break;
// Actions that can be performed in the content process
case "GetRemoteValue:ShieldLearnMoreHref":
@ -97,7 +94,7 @@ class ShieldFrameListener {
* @return {Boolean}
*/
ensureTrustedOrigin() {
return this.mm.content.document.documentURI.startsWith("about:studies");
return content.document.documentURI.startsWith("about:studies");
}
/**
@ -130,8 +127,6 @@ class ShieldFrameListener {
return;
}
let {content} = this.mm;
// Clone details and use the event class from the unprivileged context.
const event = new content.document.defaultView.CustomEvent(type, {
bubbles: true,
@ -141,8 +136,10 @@ class ShieldFrameListener {
}
onShutdown() {
this.mm.removeMessageListener("Shield:SendStudyList", this);
this.mm.removeMessageListener("Shield:ShuttingDown", this);
this.mm.removeEventListener("Shield", this);
removeMessageListener("Shield:SendStudyList", this);
removeMessageListener("Shield:ShuttingDown", this);
removeEventListener("Shield", this);
}
}
addEventListener("ShieldPageEvent", new ShieldFrameListener(), false, true);

Просмотреть файл

@ -0,0 +1,47 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
"use strict";
/**
* Registers about: pages provided by Shield, and listens for a shutdown event
* from the add-on before un-registering them.
*
* This file is loaded as a process script. It is executed once for each
* process, including the parent one.
*/
ChromeUtils.import("resource://gre/modules/XPCOMUtils.jsm");
ChromeUtils.import("resource://gre/modules/Services.jsm");
ChromeUtils.import("resource://normandy-content/AboutPages.jsm");
class ShieldChildListener {
onStartup() {
Services.cpmm.addMessageListener("Shield:ShuttingDown", this, true);
AboutPages.aboutStudies.register();
}
onShutdown() {
AboutPages.aboutStudies.unregister();
Services.cpmm.removeMessageListener("Shield:ShuttingDown", this);
// Unload AboutPages.jsm in case the add-on is reinstalled and we need to
// load a new version of it.
Cu.unload("resource://normandy-content/AboutPages.jsm");
}
receiveMessage(message) {
switch (message.name) {
case "Shield:ShuttingDown":
this.onShutdown();
break;
}
}
}
// Only register in content processes; the parent process handles registration
// separately.
if (Services.appinfo.processType === Services.appinfo.PROCESS_TYPE_CONTENT) {
const listener = new ShieldChildListener();
listener.onStartup();
}

Просмотреть файл

@ -9,11 +9,6 @@ with Files('**'):
JAR_MANIFESTS += ['jar.mn']
EXTRA_COMPONENTS += [
'shield-content-process.js',
'shield.manifest',
]
SPHINX_TREES['normandy'] = 'docs'
BROWSER_CHROME_MANIFESTS += ['test/browser/browser.ini']

Просмотреть файл

@ -1,26 +0,0 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
"use strict";
/**
* Registers about: pages provided by Shield, and listens for a shutdown event
* from the add-on before un-registering them.
*
* This file is loaded as a process script. It is executed once for each
* process, including the parent one.
*/
ChromeUtils.import("resource://gre/modules/XPCOMUtils.jsm");
ChromeUtils.import("resource://normandy-content/AboutPages.jsm");
// generateNSGetFactory only knows how to register factory classes, with
// classID properties on their prototype, and a constructor that returns
// an instance. It can't handle singletons directly. So wrap the
// aboutStudies singleton in a trivial constructor function.
function AboutStudies() {
return AboutStudies.prototype;
}
AboutStudies.prototype = AboutPages.aboutStudies;
var NSGetFactory = XPCOMUtils.generateNSGetFactory([AboutStudies]);

Просмотреть файл

@ -1,3 +0,0 @@
component {6ab96943-a163-482c-9622-4faedc0e827f} shield-content-process.js
contract @mozilla.org/network/protocol/about;1?what=studies {6ab96943-a163-482c-9622-4faedc0e827f}

Просмотреть файл

@ -2352,8 +2352,6 @@ Engine.prototype = {
let responseType = AppConstants.platform == "android" ? this._defaultMobileResponseType :
URLTYPE_SEARCH_HTML;
LOG("getURLParsingInfo: responseType: \"" + responseType + "\"");
let url = this._getURLOfType(responseType);
if (!url || url.method != "GET") {
return null;
@ -4218,7 +4216,6 @@ SearchService.prototype = {
_parseSubmissionMap: null,
_buildParseSubmissionMap: function SRCH_SVC__buildParseSubmissionMap() {
LOG("_buildParseSubmissionMap");
this._parseSubmissionMap = new Map();
// Used only while building the map, indicates which entries do not refer to
@ -4227,16 +4224,12 @@ SearchService.prototype = {
let keysOfAlternates = new Set();
for (let engine of this._sortedEngines) {
LOG("Processing engine: " + engine.name);
if (engine.hidden) {
LOG("Engine is hidden.");
continue;
}
let urlParsingInfo = engine.getURLParsingInfo();
if (!urlParsingInfo) {
LOG("Engine does not support URL parsing.");
continue;
}
@ -4253,17 +4246,12 @@ SearchService.prototype = {
// domains, even if they are found later in the ordered engine list.
let existingEntry = this._parseSubmissionMap.get(key);
if (!existingEntry) {
LOG("Adding new entry: " + key);
if (isAlternate) {
keysOfAlternates.add(key);
}
} else if (!isAlternate && keysOfAlternates.has(key)) {
LOG("Overriding alternate entry: " + key +
" (" + existingEntry.engine.name + ")");
keysOfAlternates.delete(key);
} else {
LOG("Keeping existing entry: " + key +
" (" + existingEntry.engine.name + ")");
return;
}
@ -4331,8 +4319,12 @@ SearchService.prototype = {
},
parseSubmissionURL: function SRCH_SVC_parseSubmissionURL(aURL) {
this._ensureInitialized();
LOG("parseSubmissionURL: Parsing \"" + aURL + "\".");
if (!gInitialized) {
// If search is not initialized, do nothing.
// This allows us to use this function early in telemetry.
// The only other consumer of this (places) uses it much later.
return gEmptyParseSubmissionResult;
}
if (!this._parseSubmissionMap) {
this._buildParseSubmissionMap();
@ -4345,7 +4337,6 @@ SearchService.prototype = {
// Exclude any URL that is not HTTP or HTTPS from the beginning.
if (soughtUrl.scheme != "http" && soughtUrl.scheme != "https") {
LOG("The URL scheme is not HTTP or HTTPS.");
return gEmptyParseSubmissionResult;
}
@ -4354,14 +4345,12 @@ SearchService.prototype = {
soughtQuery = soughtUrl.query;
} catch (ex) {
// Errors while parsing the URL or accessing the properties are not fatal.
LOG("The value does not look like a structured URL.");
return gEmptyParseSubmissionResult;
}
// Look up the domain and path in the map to identify the search engine.
let mapEntry = this._parseSubmissionMap.get(soughtKey);
if (!mapEntry) {
LOG("No engine associated with domain and path: " + soughtKey);
return gEmptyParseSubmissionResult;
}
@ -4378,7 +4367,6 @@ SearchService.prototype = {
}
}
if (encodedTerms === null) {
LOG("Missing terms parameter: " + mapEntry.termsParameterName);
return gEmptyParseSubmissionResult;
}
@ -4407,12 +4395,9 @@ SearchService.prototype = {
encodedTerms.replace(/\+/g, " "));
} catch (ex) {
// Decoding errors will cause this match to be ignored.
LOG("Parameter decoding failed. Charset: " +
mapEntry.engine.queryCharset);
return gEmptyParseSubmissionResult;
}
LOG("Match found. Terms: " + terms);
return new ParseSubmissionResult(mapEntry.engine, terms, offset, length);
},

Просмотреть файл

@ -7795,7 +7795,7 @@
"kind": "count",
"keyed": true,
"releaseChannelCollection": "opt-out",
"description": "Record the search counts for search engines"
"description": "Records search counts for search access points and in content searches. For search access points, the format is: <engine-name>.<search-access-point> For in content searches, the format is <provider>.in-content:[sap|sap-follow-on|organic]:[code|none]"
},
"SEARCH_RESET_RESULT": {
"record_in_processes": ["main", "content"],

Просмотреть файл

@ -1,6 +1,5 @@
[DEFAULT]
support-files =
classifiedAnnotatedPBFrame.html
classifierCommon.js
classifierFrame.html
classifierHelper.js

Просмотреть файл

@ -17,7 +17,7 @@
<script class="testbody" type="text/javascript">
var mainWindow = window.docShell.rootTreeItem.domWindow;
var contentPage = "http://www.itisatrap.org/tests/toolkit/components/url-classifier/tests/mochitest/classifiedAnnotatedPBFrame.html";
var contentPage = "http://www.itisatrap.org/chrome/toolkit/components/url-classifier/tests/mochitest/classifiedAnnotatedPBFrame.html";
ChromeUtils.import("resource://gre/modules/Services.jsm");
ChromeUtils.import("resource://testing-common/UrlClassifierTestUtils.jsm");

Просмотреть файл

@ -4,18 +4,392 @@
/* eslint-env mozilla/frame-script */
ChromeUtils.import("resource://gre/modules/AppConstants.jsm");
ChromeUtils.import("resource://gre/modules/BrowserUtils.jsm");
ChromeUtils.import("resource://gre/modules/Services.jsm");
ChromeUtils.import("resource://gre/modules/XPCOMUtils.jsm");
ChromeUtils.import("resource://gre/modules/Timer.jsm");
ChromeUtils.import("resource://gre/modules/WebNavigationChild.jsm");
ChromeUtils.import("resource://gre/modules/WebProgressChild.jsm");
ChromeUtils.defineModuleGetter(this, "PageThumbUtils",
"resource://gre/modules/PageThumbUtils.jsm");
this.WebProgress = new WebProgressChild(this);
this.WebNavigation = new WebNavigationChild(this);
ChromeUtils.defineModuleGetter(this, "Utils",
"resource://gre/modules/sessionstore/Utils.jsm");
if (AppConstants.MOZ_CRASHREPORTER) {
XPCOMUtils.defineLazyServiceGetter(this, "CrashReporter",
"@mozilla.org/xre/app-info;1",
"nsICrashReporter");
}
var WebProgressListener = {
init() {
this._filter = Cc["@mozilla.org/appshell/component/browser-status-filter;1"]
.createInstance(Ci.nsIWebProgress);
this._filter.addProgressListener(this, Ci.nsIWebProgress.NOTIFY_ALL);
this._filter.target = tabEventTarget;
let webProgress = docShell.QueryInterface(Ci.nsIInterfaceRequestor)
.getInterface(Ci.nsIWebProgress);
webProgress.addProgressListener(this._filter, Ci.nsIWebProgress.NOTIFY_ALL);
this.init = null;
},
uninit() {
let webProgress = docShell.QueryInterface(Ci.nsIInterfaceRequestor)
.getInterface(Ci.nsIWebProgress);
webProgress.removeProgressListener(this._filter);
this._filter.removeProgressListener(this);
this._filter = null;
},
_requestSpec(aRequest, aPropertyName) {
if (!aRequest || !(aRequest instanceof Ci.nsIChannel))
return null;
return aRequest.QueryInterface(Ci.nsIChannel)[aPropertyName].spec;
},
_setupJSON: function setupJSON(aWebProgress, aRequest, aStateFlags) {
// Avoid accessing content.document when being called from onStateChange
// unless if we are in STATE_STOP, because otherwise the getter will
// instantiate an about:blank document for us.
let contentDocument = null;
if (aStateFlags) {
// We're being called from onStateChange
if (aStateFlags & Ci.nsIWebProgressListener.STATE_STOP) {
contentDocument = content.document;
}
} else {
contentDocument = content.document;
}
let innerWindowID = null;
if (aWebProgress) {
let domWindowID = null;
try {
domWindowID = aWebProgress.DOMWindowID;
innerWindowID = aWebProgress.innerDOMWindowID;
} catch (e) {
// The DOM Window ID getters above may throw if the inner or outer
// windows aren't created yet or are destroyed at the time we're making
// this call but that isn't fatal so ignore the exceptions here.
}
aWebProgress = {
isTopLevel: aWebProgress.isTopLevel,
isLoadingDocument: aWebProgress.isLoadingDocument,
loadType: aWebProgress.loadType,
DOMWindowID: domWindowID
};
}
return {
webProgress: aWebProgress || null,
requestURI: this._requestSpec(aRequest, "URI"),
originalRequestURI: this._requestSpec(aRequest, "originalURI"),
documentContentType: contentDocument ? contentDocument.contentType : null,
innerWindowID,
};
},
_setupObjects: function setupObjects(aWebProgress, aRequest) {
let domWindow;
try {
domWindow = aWebProgress && aWebProgress.DOMWindow;
} catch (e) {
// If nsDocShell::Destroy has already been called, then we'll
// get NS_NOINTERFACE when trying to get the DOM window. Ignore
// that here.
domWindow = null;
}
return {
contentWindow: content,
contentDocument: content.document,
// DOMWindow is not necessarily the content-window with subframes.
DOMWindow: domWindow,
webProgress: aWebProgress,
request: aRequest,
};
},
_send(name, data, objects) {
sendAsyncMessage(name, data, objects);
},
onStateChange: function onStateChange(aWebProgress, aRequest, aStateFlags, aStatus) {
let json = this._setupJSON(aWebProgress, aRequest, aStateFlags);
let objects = this._setupObjects(aWebProgress, aRequest);
json.stateFlags = aStateFlags;
json.status = aStatus;
// It's possible that this state change was triggered by
// loading an internal error page, for which the parent
// will want to know some details, so we'll update it with
// the documentURI.
if (aWebProgress && aWebProgress.isTopLevel) {
json.documentURI = content.document.documentURIObject.spec;
json.charset = content.document.characterSet;
json.mayEnableCharacterEncodingMenu = docShell.mayEnableCharacterEncodingMenu;
json.inLoadURI = WebNavigation.inLoadURI;
}
this._send("Content:StateChange", json, objects);
},
// Note: Because the nsBrowserStatusFilter timeout runnable is
// SystemGroup-labeled, this method should not modify content DOM or
// run content JS.
onProgressChange: function onProgressChange(aWebProgress, aRequest, aCurSelf, aMaxSelf, aCurTotal, aMaxTotal) {
let json = this._setupJSON(aWebProgress, aRequest);
let objects = this._setupObjects(aWebProgress, aRequest);
json.curSelf = aCurSelf;
json.maxSelf = aMaxSelf;
json.curTotal = aCurTotal;
json.maxTotal = aMaxTotal;
this._send("Content:ProgressChange", json, objects);
},
onProgressChange64: function onProgressChange(aWebProgress, aRequest, aCurSelf, aMaxSelf, aCurTotal, aMaxTotal) {
this.onProgressChange(aWebProgress, aRequest, aCurSelf, aMaxSelf, aCurTotal, aMaxTotal);
},
onLocationChange: function onLocationChange(aWebProgress, aRequest, aLocationURI, aFlags) {
let json = this._setupJSON(aWebProgress, aRequest);
let objects = this._setupObjects(aWebProgress, aRequest);
json.location = aLocationURI ? aLocationURI.spec : "";
json.flags = aFlags;
// These properties can change even for a sub-frame navigation.
let webNav = docShell.QueryInterface(Ci.nsIWebNavigation);
json.canGoBack = webNav.canGoBack;
json.canGoForward = webNav.canGoForward;
if (aWebProgress && aWebProgress.isTopLevel) {
json.documentURI = content.document.documentURIObject.spec;
json.title = content.document.title;
json.charset = content.document.characterSet;
json.mayEnableCharacterEncodingMenu = docShell.mayEnableCharacterEncodingMenu;
json.principal = content.document.nodePrincipal;
json.synthetic = content.document.mozSyntheticDocument;
json.inLoadURI = WebNavigation.inLoadURI;
json.requestContextID = content.document.documentLoadGroup
? content.document.documentLoadGroup.requestContextID
: null;
if (AppConstants.MOZ_CRASHREPORTER && CrashReporter.enabled) {
let uri = aLocationURI;
try {
// If the current URI contains a username/password, remove it.
uri = uri.mutate()
.setUserPass("")
.finalize();
} catch (ex) { /* Ignore failures on about: URIs. */ }
CrashReporter.annotateCrashReport("URL", uri.spec);
}
}
this._send("Content:LocationChange", json, objects);
},
// Note: Because the nsBrowserStatusFilter timeout runnable is
// SystemGroup-labeled, this method should not modify content DOM or
// run content JS.
onStatusChange: function onStatusChange(aWebProgress, aRequest, aStatus, aMessage) {
let json = this._setupJSON(aWebProgress, aRequest);
let objects = this._setupObjects(aWebProgress, aRequest);
json.status = aStatus;
json.message = aMessage;
this._send("Content:StatusChange", json, objects);
},
onSecurityChange: function onSecurityChange(aWebProgress, aRequest, aState) {
let json = this._setupJSON(aWebProgress, aRequest);
let objects = this._setupObjects(aWebProgress, aRequest);
json.state = aState;
json.secInfo = SecurityUI.getSecInfoAsString();
json.matchedList = null;
if (aRequest && aRequest instanceof Ci.nsIClassifiedChannel) {
json.matchedList = aRequest.matchedList;
}
this._send("Content:SecurityChange", json, objects);
},
onRefreshAttempted: function onRefreshAttempted(aWebProgress, aURI, aDelay, aSameURI) {
return true;
},
sendLoadCallResult() {
sendAsyncMessage("Content:LoadURIResult");
},
QueryInterface: ChromeUtils.generateQI(["nsIWebProgressListener",
"nsIWebProgressListener2",
"nsISupportsWeakReference"]),
};
WebProgressListener.init();
addEventListener("unload", () => {
WebProgressListener.uninit();
});
var WebNavigation = {
init() {
addMessageListener("WebNavigation:GoBack", this);
addMessageListener("WebNavigation:GoForward", this);
addMessageListener("WebNavigation:GotoIndex", this);
addMessageListener("WebNavigation:LoadURI", this);
addMessageListener("WebNavigation:SetOriginAttributes", this);
addMessageListener("WebNavigation:Reload", this);
addMessageListener("WebNavigation:Stop", this);
// This message is used for measuring content process startup performance.
sendAsyncMessage("Content:BrowserChildReady", { time: Services.telemetry.msSystemNow() });
this.init = null;
},
get webNavigation() {
return docShell.QueryInterface(Ci.nsIWebNavigation);
},
_inLoadURI: false,
get inLoadURI() {
return this._inLoadURI;
},
receiveMessage(message) {
switch (message.name) {
case "WebNavigation:GoBack":
this.goBack();
break;
case "WebNavigation:GoForward":
this.goForward();
break;
case "WebNavigation:GotoIndex":
this.gotoIndex(message.data.index);
break;
case "WebNavigation:LoadURI":
let histogram = Services.telemetry.getKeyedHistogramById("FX_TAB_REMOTE_NAVIGATION_DELAY_MS");
histogram.add("WebNavigation:LoadURI",
Services.telemetry.msSystemNow() - message.data.requestTime);
this.loadURI(message.data.uri, message.data.flags,
message.data.referrer, message.data.referrerPolicy,
message.data.postData, message.data.headers,
message.data.baseURI, message.data.triggeringPrincipal);
break;
case "WebNavigation:SetOriginAttributes":
this.setOriginAttributes(message.data.originAttributes);
break;
case "WebNavigation:Reload":
this.reload(message.data.flags);
break;
case "WebNavigation:Stop":
this.stop(message.data.flags);
break;
}
},
_wrapURIChangeCall(fn) {
this._inLoadURI = true;
try {
fn();
} finally {
this._inLoadURI = false;
WebProgressListener.sendLoadCallResult();
}
},
goBack() {
if (this.webNavigation.canGoBack) {
this._wrapURIChangeCall(() => this.webNavigation.goBack());
}
},
goForward() {
if (this.webNavigation.canGoForward) {
this._wrapURIChangeCall(() => this.webNavigation.goForward());
}
},
gotoIndex(index) {
this._wrapURIChangeCall(() => this.webNavigation.gotoIndex(index));
},
loadURI(uri, flags, referrer, referrerPolicy, postData, headers, baseURI, triggeringPrincipal) {
if (AppConstants.MOZ_CRASHREPORTER && CrashReporter.enabled) {
let annotation = uri;
try {
let url = Services.io.newURI(uri);
// If the current URI contains a username/password, remove it.
url = url.mutate()
.setUserPass("")
.finalize();
annotation = url.spec;
} catch (ex) { /* Ignore failures to parse and failures
on about: URIs. */ }
CrashReporter.annotateCrashReport("URL", annotation);
}
if (referrer)
referrer = Services.io.newURI(referrer);
if (postData)
postData = Utils.makeInputStream(postData);
if (headers)
headers = Utils.makeInputStream(headers);
if (baseURI)
baseURI = Services.io.newURI(baseURI);
if (triggeringPrincipal)
triggeringPrincipal = Utils.deserializePrincipal(triggeringPrincipal);
this._wrapURIChangeCall(() => {
return this.webNavigation.loadURIWithOptions(uri, flags, referrer, referrerPolicy,
postData, headers, baseURI, triggeringPrincipal);
});
},
setOriginAttributes(originAttributes) {
if (originAttributes) {
this.webNavigation.setOriginAttributesBeforeLoading(originAttributes);
}
},
reload(flags) {
this.webNavigation.reload(flags);
},
stop(flags) {
this.webNavigation.stop(flags);
}
};
WebNavigation.init();
var SecurityUI = {
getSecInfoAsString() {
let secInfo = docShell.securityUI.secInfo;
if (secInfo) {
if (secInfo) {
let helper = Cc["@mozilla.org/network/serialization-helper;1"]
.getService(Ci.nsISerializationHelper);
secInfo.QueryInterface(Ci.nsISerializable);
return helper.serializeToString(secInfo);
}
}
return null;
}
};
var ControllerCommands = {
init() {

Просмотреть файл

@ -37,18 +37,6 @@ XPCOMUtils.defineLazyProxy(this, "PopupBlocking", () => {
return new tmp.PopupBlocking(global);
});
XPCOMUtils.defineLazyProxy(this, "ShieldFrameListener", () => {
let tmp = {};
ChromeUtils.import("resource://normandy-content/ShieldFrameListener.jsm", tmp);
return new tmp.ShieldFrameListener(global);
});
XPCOMUtils.defineLazyProxy(this, "UITourListener", () => {
let tmp = {};
ChromeUtils.import("resource:///modules/ContentUITour.jsm", tmp);
return new tmp.UITourListener(global);
});
XPCOMUtils.defineLazyProxy(this, "SelectionSourceContent",
"resource://gre/modules/SelectionSourceContent.jsm");
@ -61,12 +49,6 @@ XPCOMUtils.defineLazyProxy(this, "DateTimePickerContent", () => {
return new tmp.DateTimePickerContent(this);
});
XPCOMUtils.defineLazyProxy(this, "FindBarChild", () => {
let tmp = {};
ChromeUtils.import("resource://gre/modules/FindBarChild.jsm", tmp);
return new tmp.FindBarChild(this);
}, {inQuickFind: false, inPassThrough: false});
// Lazily load the finder code
addMessageListener("Finder:Initialize", function() {
@ -135,6 +117,13 @@ addMessageListener("SwitchDocumentDirection", () => {
});
var FindBar = {
/* Please keep in sync with toolkit/content/widgets/findbar.xml */
FIND_NORMAL: 0,
FIND_TYPEAHEAD: 1,
FIND_LINKS: 2,
_findMode: 0,
/**
* _findKey and _findModifiers are used to determine whether a keypress
* is a user attempting to use the find shortcut, after which we'll
@ -142,59 +131,159 @@ var FindBar = {
* there. To do this, we need shortcut data from the parent.
*/
_findKey: null,
_findModifiers: null,
init() {
Services.els.addSystemEventListener(global, "keypress",
this.onKeypress.bind(this), false);
addMessageListener("Findbar:UpdateState", this);
Services.els.addSystemEventListener(global, "keypress", this, false);
Services.els.addSystemEventListener(global, "mouseup", this, false);
this._initShortcutData();
this.init = null;
},
receiveMessage(msg) {
switch (msg.name) {
case "Findbar:UpdateState":
this._findMode = msg.data.findMode;
this._quickFindTimeout = msg.data.hasQuickFindTimeout;
if (msg.data.isOpenAndFocused) {
this._keepPassingUntilToldOtherwise = false;
}
break;
case "Findbar:ShortcutData":
// Set us up to never need this again for the lifetime of this process,
// and remove the listener.
Services.cpmm.initialProcessData.findBarShortcutData = msg.data;
Services.cpmm.removeMessageListener("Findbar:ShortcutData", this);
this._initShortcutData(msg.data);
break;
}
},
handleEvent(event) {
switch (event.type) {
case "keypress":
this._onKeypress(event);
break;
case "mouseup":
this._onMouseup(event);
break;
}
},
/**
* Use initial process data for find key/modifier data if we have it.
* Otherwise, add a listener so we get the data when the parent process has
* it.
*/
_initShortcutData(data = Services.cpmm.initialProcessData.findBarShortcutData) {
if (data) {
this._findKey = data.key;
this._findModifiers = data.modifiers;
} else {
Services.cpmm.addMessageListener("Findbar:ShortcutData", this);
}
},
/**
* Check whether this key event will start the findbar in the parent,
* in which case we should pass any further key events to the parent to avoid
* them being lost.
* @param aEvent the key event to check.
*/
eventMatchesFindShortcut(aEvent) {
if (!this._findKey) {
this._findKey = Services.cpmm.sharedData.get("Findbar:Shortcut");
if (!this._findKey) {
return false;
}
_eventMatchesFindShortcut(aEvent) {
let modifiers = this._findModifiers;
if (!modifiers) {
return false;
}
for (let k in this._findKey) {
if (this._findKey[k] != aEvent[k]) {
return false;
}
}
return true;
return aEvent.ctrlKey == modifiers.ctrlKey && aEvent.altKey == modifiers.altKey &&
aEvent.shiftKey == modifiers.shiftKey && aEvent.metaKey == modifiers.metaKey &&
aEvent.key == this._findKey;
},
onKeypress(event) {
if (!FindBarChild.inPassThrough &&
this.eventMatchesFindShortcut(event)) {
return FindBarChild.start(event);
/**
* Returns whether FAYT can be used for the given event in
* the current content state.
*/
_canAndShouldFastFind() {
let should = false;
let can = BrowserUtils.canFastFind(content);
if (can) {
// XXXgijs: why all these shenanigans? Why not use the event's target?
let focusedWindow = {};
let elt = Services.focus.getFocusedElementForWindow(content, true, focusedWindow);
let win = focusedWindow.value;
should = BrowserUtils.shouldFastFind(elt, win);
}
return { can, should };
},
_onKeypress(event) {
const FAYT_LINKS_KEY = "'";
const FAYT_TEXT_KEY = "/";
if (this._eventMatchesFindShortcut(event)) {
this._keepPassingUntilToldOtherwise = true;
}
// Useless keys:
if (event.ctrlKey || event.altKey || event.metaKey || event.defaultPrevented) {
return;
}
if (event.ctrlKey || event.altKey || event.metaKey || event.defaultPrevented ||
!BrowserUtils.canFastFind(content)) {
return null;
// Check the focused element etc.
let fastFind = this._canAndShouldFastFind();
// Can we even use find in this page at all?
if (!fastFind.can) {
return;
}
if (this._keepPassingUntilToldOtherwise) {
this._passKeyToParent(event);
return;
}
if (!fastFind.should) {
return;
}
if (FindBarChild.inPassThrough || FindBarChild.inQuickFind) {
return FindBarChild.onKeypress(event);
}
if (event.charCode && BrowserUtils.shouldFastFind(event.target)) {
let key = String.fromCharCode(event.charCode);
if ((key == "/" || key == "'") && RemoteFinder._manualFAYT) {
return FindBarChild.startQuickFind(event);
}
if (key != " " && RemoteFinder._findAsYouType) {
return FindBarChild.startQuickFind(event, true);
let charCode = event.charCode;
// If the find bar is open and quick find is on, send the key to the parent.
if (this._findMode != this.FIND_NORMAL && this._quickFindTimeout) {
if (!charCode)
return;
this._passKeyToParent(event);
} else {
let key = charCode ? String.fromCharCode(charCode) : null;
let manualstartFAYT = (key == FAYT_LINKS_KEY || key == FAYT_TEXT_KEY) && RemoteFinder._manualFAYT;
let autostartFAYT = !manualstartFAYT && RemoteFinder._findAsYouType && key && key != " ";
if (manualstartFAYT || autostartFAYT) {
let mode = (key == FAYT_LINKS_KEY || (autostartFAYT && RemoteFinder._typeAheadLinksOnly)) ?
this.FIND_LINKS : this.FIND_TYPEAHEAD;
// Set _findMode immediately (without waiting for child->parent->child roundtrip)
// to ensure we pass any further keypresses, too.
this._findMode = mode;
this._passKeyToParent(event);
}
}
return null;
},
_passKeyToParent(event) {
event.preventDefault();
// These are the properties required to dispatch another 'real' event
// to the findbar in the parent in _dispatchKeypressEvent in findbar.xml .
// If you make changes here, verify that that method can still do its job.
const kRequiredProps = [
"type", "bubbles", "cancelable", "ctrlKey", "altKey", "shiftKey",
"metaKey", "keyCode", "charCode",
];
let fakeEvent = {};
for (let prop of kRequiredProps) {
fakeEvent[prop] = event[prop];
}
sendAsyncMessage("Findbar:Keypress", fakeEvent);
},
_onMouseup(event) {
if (this._findMode != this.FIND_NORMAL)
sendAsyncMessage("Findbar:Mouseup");
},
};
FindBar.init();
@ -445,7 +534,3 @@ let ExtFind = {
};
ExtFind.init();
addEventListener("ShieldPageEvent", ShieldFrameListener, false, true);
addEventListener("mozUITour", UITourListener, false, true);

Просмотреть файл

@ -220,7 +220,7 @@
</content>
<implementation>
<!-- Please keep in sync with toolkit/modules/FindBarChild.jsm -->
<!-- Please keep in sync with toolkit/content/browser-content.js -->
<field name="FIND_NORMAL">0</field>
<field name="FIND_TYPEAHEAD">1</field>
<field name="FIND_LINKS">2</field>

Просмотреть файл

@ -290,10 +290,12 @@ var BrowserUtils = {
*
* @param elt
* The element that is focused
* @param win
* The window that is focused
*
*/
shouldFastFind(elt) {
shouldFastFind(elt, win) {
if (elt) {
let win = elt.ownerGlobal;
if (elt instanceof win.HTMLInputElement && elt.mozIsTextField(false))
return false;

Просмотреть файл

@ -1,99 +0,0 @@
// vim: set ts=2 sw=2 sts=2 tw=80:
// This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0. If a copy of the MPL was not distributed with this
// file, You can obtain one at http://mozilla.org/MPL/2.0/.
"use strict";
var EXPORTED_SYMBOLS = ["FindBarChild"];
ChromeUtils.defineModuleGetter(this, "RemoteFinder",
"resource://gre/modules/RemoteFinder.jsm");
ChromeUtils.defineModuleGetter(this, "Services",
"resource://gre/modules/Services.jsm");
/* Please keep in sync with toolkit/this.mm.content/widgets/findbar.xml */
const FIND_NORMAL = 0;
const FIND_TYPEAHEAD = 1;
const FIND_LINKS = 2;
class FindBarChild {
constructor(mm) {
this.mm = mm;
this.findMode = 0;
this.inQuickFind = false;
this.mm.addMessageListener("Findbar:UpdateState", this);
Services.els.addSystemEventListener(this.mm, "mouseup", this, false);
}
start(event) {
this.inPassThrough = true;
}
startQuickFind(event, autostart = false) {
let mode = FIND_TYPEAHEAD;
if (event.charCode == "'".charAt(0) ||
autostart && RemoteFinder._typeAheadLinksOnly) {
mode = FIND_LINKS;
}
// Set findMode immediately (without waiting for child->parent->child roundtrip)
// to ensure we pass any further keypresses, too.
this.findMode = mode;
this.passKeyToParent(event);
}
receiveMessage(msg) {
switch (msg.name) {
case "Findbar:UpdateState":
this.findMode = msg.data.findMode;
this.inQuickFind = msg.data.hasQuickFindTimeout;
if (msg.data.isOpenAndFocused) {
this.inPassThrough = false;
}
break;
}
}
handleEvent(event) {
switch (event.type) {
case "keypress":
this.onKeypress(event);
break;
case "mouseup":
this.onMouseup(event);
break;
}
}
onKeypress(event) {
if (this.inPassThrough) {
this.passKeyToParent(event);
} else if (this.findMode != FIND_NORMAL && this.inQuickFind && event.charCode) {
this.passKeyToParent(event);
}
}
passKeyToParent(event) {
event.preventDefault();
// These are the properties required to dispatch another 'real' event
// to the findbar in the parent in _dispatchKeypressEvent in findbar.xml .
// If you make changes here, verify that that method can still do its job.
const kRequiredProps = [
"type", "bubbles", "cancelable", "ctrlKey", "altKey", "shiftKey",
"metaKey", "keyCode", "charCode",
];
let fakeEvent = {};
for (let prop of kRequiredProps) {
fakeEvent[prop] = event[prop];
}
this.mm.sendAsyncMessage("Findbar:Keypress", fakeEvent);
}
onMouseup(event) {
if (this.findMode != FIND_NORMAL)
this.mm.sendAsyncMessage("Findbar:Mouseup");
}
}

Просмотреть файл

@ -1,144 +0,0 @@
/* -*- indent-tabs-mode: nil; js-indent-level: 2 -*- */
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
"use strict";
var EXPORTED_SYMBOLS = ["WebNavigationChild"];
ChromeUtils.import("resource://gre/modules/Services.jsm");
ChromeUtils.import("resource://gre/modules/XPCOMUtils.jsm");
ChromeUtils.defineModuleGetter(this, "AppConstants",
"resource://gre/modules/AppConstants.jsm");
ChromeUtils.defineModuleGetter(this, "Utils",
"resource://gre/modules/sessionstore/Utils.jsm");
XPCOMUtils.defineLazyServiceGetter(this, "CrashReporter",
"@mozilla.org/xre/app-info;1",
"nsICrashReporter");
class WebNavigationChild {
constructor(mm) {
this.mm = mm;
this.mm.addMessageListener("WebNavigation:GoBack", this);
this.mm.addMessageListener("WebNavigation:GoForward", this);
this.mm.addMessageListener("WebNavigation:GotoIndex", this);
this.mm.addMessageListener("WebNavigation:LoadURI", this);
this.mm.addMessageListener("WebNavigation:SetOriginAttributes", this);
this.mm.addMessageListener("WebNavigation:Reload", this);
this.mm.addMessageListener("WebNavigation:Stop", this);
// This message is used for measuring this.mm.content process startup performance.
this.mm.sendAsyncMessage("Content:BrowserChildReady", { time: Services.telemetry.msSystemNow() });
this.inLoadURI = false;
}
get webNavigation() {
return this.mm.docShell.QueryInterface(Ci.nsIWebNavigation);
}
receiveMessage(message) {
switch (message.name) {
case "WebNavigation:GoBack":
this.goBack();
break;
case "WebNavigation:GoForward":
this.goForward();
break;
case "WebNavigation:GotoIndex":
this.gotoIndex(message.data.index);
break;
case "WebNavigation:LoadURI":
let histogram = Services.telemetry.getKeyedHistogramById("FX_TAB_REMOTE_NAVIGATION_DELAY_MS");
histogram.add("WebNavigation:LoadURI",
Services.telemetry.msSystemNow() - message.data.requestTime);
this.loadURI(message.data.uri, message.data.flags,
message.data.referrer, message.data.referrerPolicy,
message.data.postData, message.data.headers,
message.data.baseURI, message.data.triggeringPrincipal);
break;
case "WebNavigation:SetOriginAttributes":
this.setOriginAttributes(message.data.originAttributes);
break;
case "WebNavigation:Reload":
this.reload(message.data.flags);
break;
case "WebNavigation:Stop":
this.stop(message.data.flags);
break;
}
}
_wrapURIChangeCall(fn) {
this.inLoadURI = true;
try {
fn();
} finally {
this.inLoadURI = false;
this.mm.WebProgress.sendLoadCallResult();
}
}
goBack() {
if (this.webNavigation.canGoBack) {
this._wrapURIChangeCall(() => this.webNavigation.goBack());
}
}
goForward() {
if (this.webNavigation.canGoForward) {
this._wrapURIChangeCall(() => this.webNavigation.goForward());
}
}
gotoIndex(index) {
this._wrapURIChangeCall(() => this.webNavigation.gotoIndex(index));
}
loadURI(uri, flags, referrer, referrerPolicy, postData, headers, baseURI, triggeringPrincipal) {
if (AppConstants.MOZ_CRASHREPORTER && CrashReporter.enabled) {
let annotation = uri;
try {
let url = Services.io.newURI(uri);
// If the current URI contains a username/password, remove it.
url = url.mutate()
.setUserPass("")
.finalize();
annotation = url.spec;
} catch (ex) { /* Ignore failures to parse and failures
on about: URIs. */ }
CrashReporter.annotateCrashReport("URL", annotation);
}
if (referrer)
referrer = Services.io.newURI(referrer);
if (postData)
postData = Utils.makeInputStream(postData);
if (headers)
headers = Utils.makeInputStream(headers);
if (baseURI)
baseURI = Services.io.newURI(baseURI);
if (triggeringPrincipal)
triggeringPrincipal = Utils.deserializePrincipal(triggeringPrincipal);
this._wrapURIChangeCall(() => {
return this.webNavigation.loadURIWithOptions(uri, flags, referrer, referrerPolicy,
postData, headers, baseURI, triggeringPrincipal);
});
}
setOriginAttributes(originAttributes) {
if (originAttributes) {
this.webNavigation.setOriginAttributesBeforeLoading(originAttributes);
}
}
reload(flags) {
this.webNavigation.reload(flags);
}
stop(flags) {
this.webNavigation.stop(flags);
}
}

Просмотреть файл

@ -1,237 +0,0 @@
/* -*- indent-tabs-mode: nil; js-indent-level: 2 -*- */
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
"use strict";
var EXPORTED_SYMBOLS = ["WebProgressChild"];
ChromeUtils.import("resource://gre/modules/XPCOMUtils.jsm");
ChromeUtils.defineModuleGetter(this, "AppConstants",
"resource://gre/modules/AppConstants.jsm");
XPCOMUtils.defineLazyServiceGetter(this, "CrashReporter",
"@mozilla.org/xre/app-info;1",
"nsICrashReporter");
XPCOMUtils.defineLazyServiceGetter(this, "serializationHelper",
"@mozilla.org/network/serialization-helper;1",
"nsISerializationHelper");
class WebProgressChild {
constructor(mm) {
this.mm = mm;
this._filter = Cc["@mozilla.org/appshell/component/browser-status-filter;1"]
.createInstance(Ci.nsIWebProgress);
this._filter.addProgressListener(this, Ci.nsIWebProgress.NOTIFY_ALL);
this._filter.target = this.mm.tabEventTarget;
let webProgress = this.mm.docShell.QueryInterface(Ci.nsIInterfaceRequestor)
.getInterface(Ci.nsIWebProgress);
webProgress.addProgressListener(this._filter, Ci.nsIWebProgress.NOTIFY_ALL);
}
_requestSpec(aRequest, aPropertyName) {
if (!aRequest || !(aRequest instanceof Ci.nsIChannel))
return null;
return aRequest[aPropertyName].spec;
}
_setupJSON(aWebProgress, aRequest, aStateFlags) {
// Avoid accessing this.mm.content.document when being called from onStateChange
// unless if we are in STATE_STOP, because otherwise the getter will
// instantiate an about:blank document for us.
let contentDocument = null;
if (aStateFlags) {
// We're being called from onStateChange
if (aStateFlags & Ci.nsIWebProgressListener.STATE_STOP) {
contentDocument = this.mm.content.document;
}
} else {
contentDocument = this.mm.content.document;
}
let innerWindowID = null;
if (aWebProgress) {
let domWindowID = null;
try {
domWindowID = aWebProgress.DOMWindowID;
innerWindowID = aWebProgress.innerDOMWindowID;
} catch (e) {
// The DOM Window ID getters above may throw if the inner or outer
// windows aren't created yet or are destroyed at the time we're making
// this call but that isn't fatal so ignore the exceptions here.
}
aWebProgress = {
isTopLevel: aWebProgress.isTopLevel,
isLoadingDocument: aWebProgress.isLoadingDocument,
loadType: aWebProgress.loadType,
DOMWindowID: domWindowID
};
}
return {
webProgress: aWebProgress || null,
requestURI: this._requestSpec(aRequest, "URI"),
originalRequestURI: this._requestSpec(aRequest, "originalURI"),
documentContentType: contentDocument ? contentDocument.contentType : null,
innerWindowID,
};
}
_setupObjects(aWebProgress, aRequest) {
let domWindow;
try {
domWindow = aWebProgress && aWebProgress.DOMWindow;
} catch (e) {
// If nsDocShell::Destroy has already been called, then we'll
// get NS_NOINTERFACE when trying to get the DOM window. Ignore
// that here.
domWindow = null;
}
return {
contentWindow: this.mm.content,
contentDocument: this.mm.content.document,
// DOMWindow is not necessarily the this.mm.content-window with subframes.
DOMWindow: domWindow,
webProgress: aWebProgress,
request: aRequest,
};
}
_send(name, data, objects) {
this.mm.sendAsyncMessage(name, data, objects);
}
onStateChange(aWebProgress, aRequest, aStateFlags, aStatus) {
let json = this._setupJSON(aWebProgress, aRequest, aStateFlags);
let objects = this._setupObjects(aWebProgress, aRequest);
json.stateFlags = aStateFlags;
json.status = aStatus;
// It's possible that this state change was triggered by
// loading an internal error page, for which the parent
// will want to know some details, so we'll update it with
// the documentURI.
if (aWebProgress && aWebProgress.isTopLevel) {
json.documentURI = this.mm.content.document.documentURIObject.spec;
json.charset = this.mm.content.document.characterSet;
json.mayEnableCharacterEncodingMenu = this.mm.docShell.mayEnableCharacterEncodingMenu;
json.inLoadURI = this.mm.WebNavigation.inLoadURI;
}
this._send("Content:StateChange", json, objects);
}
// Note: Because the nsBrowserStatusFilter timeout runnable is
// SystemGroup-labeled, this method should not modify this.mm.content DOM or
// run this.mm.content JS.
onProgressChange(aWebProgress, aRequest, aCurSelf, aMaxSelf, aCurTotal, aMaxTotal) {
let json = this._setupJSON(aWebProgress, aRequest);
let objects = this._setupObjects(aWebProgress, aRequest);
json.curSelf = aCurSelf;
json.maxSelf = aMaxSelf;
json.curTotal = aCurTotal;
json.maxTotal = aMaxTotal;
this._send("Content:ProgressChange", json, objects);
}
onProgressChange64(aWebProgress, aRequest, aCurSelf, aMaxSelf, aCurTotal, aMaxTotal) {
this.onProgressChange(aWebProgress, aRequest, aCurSelf, aMaxSelf, aCurTotal, aMaxTotal);
}
onLocationChange(aWebProgress, aRequest, aLocationURI, aFlags) {
let json = this._setupJSON(aWebProgress, aRequest);
let objects = this._setupObjects(aWebProgress, aRequest);
json.location = aLocationURI ? aLocationURI.spec : "";
json.flags = aFlags;
// These properties can change even for a sub-frame navigation.
let webNav = this.mm.docShell.QueryInterface(Ci.nsIWebNavigation);
json.canGoBack = webNav.canGoBack;
json.canGoForward = webNav.canGoForward;
if (aWebProgress && aWebProgress.isTopLevel) {
json.documentURI = this.mm.content.document.documentURIObject.spec;
json.title = this.mm.content.document.title;
json.charset = this.mm.content.document.characterSet;
json.mayEnableCharacterEncodingMenu = this.mm.docShell.mayEnableCharacterEncodingMenu;
json.principal = this.mm.content.document.nodePrincipal;
json.synthetic = this.mm.content.document.mozSyntheticDocument;
json.inLoadURI = this.mm.WebNavigation.inLoadURI;
json.requestContextID = this.mm.content.document.documentLoadGroup
? this.mm.content.document.documentLoadGroup.requestContextID
: null;
if (AppConstants.MOZ_CRASHREPORTER && CrashReporter.enabled) {
let uri = aLocationURI;
try {
// If the current URI contains a username/password, remove it.
uri = uri.mutate()
.setUserPass("")
.finalize();
} catch (ex) { /* Ignore failures on about: URIs. */ }
CrashReporter.annotateCrashReport("URL", uri.spec);
}
}
this._send("Content:LocationChange", json, objects);
}
// Note: Because the nsBrowserStatusFilter timeout runnable is
// SystemGroup-labeled, this method should not modify this.mm.content DOM or
// run this.mm.content JS.
onStatusChange(aWebProgress, aRequest, aStatus, aMessage) {
let json = this._setupJSON(aWebProgress, aRequest);
let objects = this._setupObjects(aWebProgress, aRequest);
json.status = aStatus;
json.message = aMessage;
this._send("Content:StatusChange", json, objects);
}
getSecInfoAsString() {
let secInfo = this.mm.docShell.securityUI.secInfo;
if (secInfo) {
return serializationHelper.serializeToString(secInfo);
}
return null;
}
onSecurityChange(aWebProgress, aRequest, aState) {
let json = this._setupJSON(aWebProgress, aRequest);
let objects = this._setupObjects(aWebProgress, aRequest);
json.state = aState;
json.secInfo = this.getSecInfoAsString();
json.matchedList = null;
if (aRequest && aRequest instanceof Ci.nsIClassifiedChannel) {
json.matchedList = aRequest.matchedList;
}
this._send("Content:SecurityChange", json, objects);
}
onRefreshAttempted(aWebProgress, aURI, aDelay, aSameURI) {
return true;
}
sendLoadCallResult() {
this.mm.sendAsyncMessage("Content:LoadURIResult");
}
}
WebProgressChild.prototype.QueryInterface =
ChromeUtils.generateQI(["nsIWebProgressListener",
"nsIWebProgressListener2",
"nsISupportsWeakReference"]);

Просмотреть файл

@ -200,7 +200,6 @@ EXTRA_JS_MODULES += [
'E10SUtils.jsm',
'EventEmitter.jsm',
'FileUtils.jsm',
'FindBarChild.jsm',
'Finder.jsm',
'FinderHighlighter.jsm',
'FinderIterator.jsm',
@ -254,8 +253,6 @@ EXTRA_JS_MODULES += [
'UpdateUtils.jsm',
'WebChannel.jsm',
'WebChannelContent.jsm',
'WebNavigationChild.jsm',
'WebProgressChild.jsm',
'WindowDraggingUtils.jsm',
'ZipUtils.jsm',
]

Просмотреть файл

@ -46,8 +46,16 @@ struct ManifestDirective
const char* directive;
int argc;
// Binary components are only allowed for APP locations.
bool apponly;
// Some directives should only be delivered for APP or EXTENSION locations.
bool componentonly;
bool ischrome;
bool allowbootstrap;
// The contentaccessible flags only apply to content/resource directives.
bool contentflags;
@ -59,44 +67,50 @@ struct ManifestDirective
void (nsChromeRegistry::*regfunc)(
nsChromeRegistry::ManifestProcessingContext& aCx,
int aLineNo, char* const* aArgv, int aFlags);
bool isContract;
};
static const ManifestDirective kParsingTable[] = {
{
"manifest", 1, true, false,
"manifest", 1, false, false, true, true, false,
&nsComponentManagerImpl::ManifestManifest, nullptr,
},
{
"component", 2, false, false,
"binary-component", 1, true, true, false, false, false,
&nsComponentManagerImpl::ManifestBinaryComponent, nullptr,
},
{
"component", 2, false, true, false, false, false,
&nsComponentManagerImpl::ManifestComponent, nullptr,
},
{
"contract", 2, false, false,
"contract", 2, false, true, false, false, false,
&nsComponentManagerImpl::ManifestContract, nullptr,
},
{
"category", 3, false, false,
"category", 3, false, true, false, false, false,
&nsComponentManagerImpl::ManifestCategory, nullptr,
},
{
"content", 2, true, true,
"content", 2, false, true, true, true, true,
nullptr, &nsChromeRegistry::ManifestContent,
},
{
"locale", 3, true, false,
"locale", 3, false, true, true, true, false,
nullptr, &nsChromeRegistry::ManifestLocale,
},
{
"skin", 3, true, false,
"skin", 3, false, false, true, true, false,
nullptr, &nsChromeRegistry::ManifestSkin,
},
{
// NB: note that while skin manifests can use this, they are only allowed
// to use it for chrome://../skin/ URLs
"override", 2, true, false,
"override", 2, false, false, true, true, false,
nullptr, &nsChromeRegistry::ManifestOverride,
},
{
"resource", 2, false, true,
"resource", 2, false, true, true, false, true,
nullptr, &nsChromeRegistry::ManifestResource,
}
};
@ -571,13 +585,28 @@ ParseManifest(NSLocationType aType, FileLocation& aFile, char* aBuf,
continue;
}
if (!directive->ischrome && NS_BOOTSTRAPPED_LOCATION == aType) {
if (!directive->allowbootstrap && NS_BOOTSTRAPPED_LOCATION == aType) {
LogMessageWithContext(aFile, line,
"Bootstrapped manifest not allowed to use '%s' directive.",
token);
continue;
}
#ifndef MOZ_BINARY_EXTENSIONS
if (directive->apponly && NS_APP_LOCATION != aType) {
LogMessageWithContext(aFile, line,
"Only application manifests may use the '%s' directive.", token);
continue;
}
#endif
if (directive->componentonly && NS_SKIN_LOCATION == aType) {
LogMessageWithContext(aFile, line,
"Skin manifest not allowed to use '%s' directive.",
token);
continue;
}
NS_ASSERTION(directive->argc < 4, "Need to reset argv array length");
char* argv[4];
for (int i = 0; i < directive->argc; ++i) {
@ -692,8 +721,15 @@ ParseManifest(NSLocationType aType, FileLocation& aFile, char* aBuf,
(nsChromeRegistry::gChromeRegistry->*(directive->regfunc))(
chromecx, line, argv, flags);
} else if (directive->ischrome || !aChromeOnly) {
(nsComponentManagerImpl::gComponentManager->*(directive->mgrfunc))(
mgrcx, line, argv);
if (directive->isContract) {
CachedDirective* cd = contracts.AppendElement();
cd->lineno = line;
cd->argv[0] = argv[0];
cd->argv[1] = argv[1];
} else {
(nsComponentManagerImpl::gComponentManager->*(directive->mgrfunc))(
mgrcx, line, argv);
}
}
}

Просмотреть файл

@ -665,6 +665,15 @@ nsComponentManagerImpl::ManifestManifest(ManifestProcessingContext& aCx,
RegisterManifest(aCx.mType, f, aCx.mChromeOnly);
}
void
nsComponentManagerImpl::ManifestBinaryComponent(ManifestProcessingContext& aCx,
int aLineNo,
char* const* aArgv)
{
LogMessageWithContext(aCx.mFile, aLineNo,
"Binary XPCOM components are no longer supported.");
}
void
nsComponentManagerImpl::ManifestComponent(ManifestProcessingContext& aCx,
int aLineNo, char* const* aArgv)

Просмотреть файл

@ -287,6 +287,8 @@ public:
void ManifestManifest(ManifestProcessingContext& aCx, int aLineNo,
char* const* aArgv);
void ManifestBinaryComponent(ManifestProcessingContext& aCx, int aLineNo,
char* const* aArgv);
void ManifestComponent(ManifestProcessingContext& aCx, int aLineNo,
char* const* aArgv);
void ManifestContract(ManifestProcessingContext& aCx, int aLineNo,