зеркало из https://github.com/mozilla/gecko-dev.git
Merge m-c to inbound, a=merge
MozReview-Commit-ID: HDHJC8X9xWG
This commit is contained in:
Коммит
29443ed98c
|
@ -460,6 +460,7 @@ const gStoragePressureObserver = {
|
|||
let buttons = [];
|
||||
let usage = parseInt(data);
|
||||
let prefStrBundle = document.getElementById("bundle_preferences");
|
||||
let brandShortName = document.getElementById("bundle_brand").getString("brandShortName");
|
||||
let notificationBox = document.getElementById("high-priority-global-notificationbox");
|
||||
buttons.push({
|
||||
label: prefStrBundle.getString("spaceAlert.learnMoreButton.label"),
|
||||
|
@ -474,7 +475,7 @@ const gStoragePressureObserver = {
|
|||
// This is because this usage is small and not the main cause for space issue.
|
||||
// In order to avoid the bad and wrong impression among users that
|
||||
// firefox eats disk space a lot, indicate users to clean up other disk space.
|
||||
msg = prefStrBundle.getString("spaceAlert.under5GB.description");
|
||||
msg = prefStrBundle.getFormattedString("spaceAlert.under5GB.message", [brandShortName]);
|
||||
buttons.push({
|
||||
label: prefStrBundle.getString("spaceAlert.under5GB.okButton.label"),
|
||||
accessKey: prefStrBundle.getString("spaceAlert.under5GB.okButton.accesskey"),
|
||||
|
@ -483,15 +484,15 @@ const gStoragePressureObserver = {
|
|||
} else {
|
||||
// The firefox-used space >= 5GB, then guide users to about:preferences
|
||||
// to clear some data stored on firefox by websites.
|
||||
let descriptionStringID = "spaceAlert.over5GB.description";
|
||||
let descriptionStringID = "spaceAlert.over5GB.message";
|
||||
let prefButtonLabelStringID = "spaceAlert.over5GB.prefButton.label";
|
||||
let prefButtonAccesskeyStringID = "spaceAlert.over5GB.prefButton.accesskey";
|
||||
if (AppConstants.platform == "win") {
|
||||
descriptionStringID = "spaceAlert.over5GB.descriptionWin";
|
||||
descriptionStringID = "spaceAlert.over5GB.messageWin";
|
||||
prefButtonLabelStringID = "spaceAlert.over5GB.prefButtonWin.label";
|
||||
prefButtonAccesskeyStringID = "spaceAlert.over5GB.prefButtonWin.accesskey";
|
||||
}
|
||||
msg = prefStrBundle.getString(descriptionStringID);
|
||||
msg = prefStrBundle.getFormattedString(descriptionStringID, [brandShortName]);
|
||||
buttons.push({
|
||||
label: prefStrBundle.getString(prefButtonLabelStringID),
|
||||
accessKey: prefStrBundle.getString(prefButtonAccesskeyStringID),
|
||||
|
@ -3435,7 +3436,7 @@ var PrintPreviewListener = {
|
|||
let browser = gBrowser.selectedBrowser;
|
||||
let preferredRemoteType = browser.remoteType;
|
||||
this._tabBeforePrintPreview = gBrowser.selectedTab;
|
||||
this._printPreviewTab = gBrowser.loadOneTab("about:blank", {
|
||||
this._printPreviewTab = gBrowser.loadOneTab("about:printpreview", {
|
||||
inBackground: false,
|
||||
preferredRemoteType,
|
||||
sameProcessAsFrameLoader: browser.frameLoader
|
||||
|
@ -3446,7 +3447,7 @@ var PrintPreviewListener = {
|
|||
},
|
||||
createSimplifiedBrowser() {
|
||||
let browser = this._tabBeforePrintPreview.linkedBrowser;
|
||||
this._simplifyPageTab = gBrowser.loadOneTab("about:blank", {
|
||||
this._simplifyPageTab = gBrowser.loadOneTab("about:printpreview", {
|
||||
inBackground: true,
|
||||
sameProcessAsFrameLoader: browser.frameLoader
|
||||
});
|
||||
|
|
|
@ -388,7 +388,7 @@ this.SessionStore = {
|
|||
let win = aState.windows[i];
|
||||
for (let j = win.tabs.length - 1; j >= 0; j--) {
|
||||
let tab = win.tabs[j];
|
||||
if (!SessionStoreInternal._shouldSaveTabState(tab)) {
|
||||
if (!SessionStoreInternal._shouldSaveTab(tab)) {
|
||||
win.tabs.splice(j, 1);
|
||||
if (win.selected > j) {
|
||||
win.selected--;
|
||||
|
@ -4198,10 +4198,29 @@ var SessionStoreInternal = {
|
|||
!(aTabState.entries.length == 1 &&
|
||||
(aTabState.entries[0].url == "about:blank" ||
|
||||
aTabState.entries[0].url == "about:newtab" ||
|
||||
aTabState.entries[0].url == "about:printpreview" ||
|
||||
aTabState.entries[0].url == "about:privatebrowsing") &&
|
||||
!aTabState.userTypedValue);
|
||||
},
|
||||
|
||||
/**
|
||||
* Determine if the tab state we're passed is something we should keep to be
|
||||
* reopened at session restore. This is used when we are saving the current
|
||||
* session state to disk. This method is very similar to _shouldSaveTabState,
|
||||
* however, "about:blank" and "about:newtab" tabs will still be saved to disk.
|
||||
*
|
||||
* @param aTabState
|
||||
* The current tab state
|
||||
* @returns boolean
|
||||
*/
|
||||
_shouldSaveTab: function ssi_shouldSaveTab(aTabState) {
|
||||
// If the tab has one of the following transient about: history entry,
|
||||
// then we don't actually want to write this tab's data to disk.
|
||||
return aTabState.entries.length &&
|
||||
!(aTabState.entries[0].url == "about:printpreview" ||
|
||||
aTabState.entries[0].url == "about:privatebrowsing");
|
||||
},
|
||||
|
||||
/**
|
||||
* This is going to take a state as provided at startup (via
|
||||
* nsISessionStartup.state) and split it into 2 parts. The first part
|
||||
|
|
|
@ -271,9 +271,10 @@ var FormAutofillContent = {
|
|||
ProfileAutocomplete.ensureUnregistered();
|
||||
}
|
||||
});
|
||||
Services.cpmm.sendAsyncMessage("FormAutofill:getEnabledStatus");
|
||||
// TODO: use initialProcessData:
|
||||
// Services.cpmm.initialProcessData.autofillEnabled
|
||||
|
||||
if (Services.cpmm.initialProcessData.autofillEnabled) {
|
||||
ProfileAutocomplete.ensureRegistered();
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
|
|
|
@ -80,11 +80,10 @@ FormAutofillParent.prototype = {
|
|||
// Observing the pref and storage changes
|
||||
Services.prefs.addObserver(ENABLED_PREF, this, false);
|
||||
Services.obs.addObserver(this, "formautofill-storage-changed", false);
|
||||
this._enabled = this._getStatus();
|
||||
|
||||
// Force to trigger the onStatusChanged function for setting listeners properly
|
||||
// while initizlization
|
||||
this._onStatusChanged();
|
||||
Services.ppmm.addMessageListener("FormAutofill:getEnabledStatus", this);
|
||||
this._setStatus(this._getStatus());
|
||||
},
|
||||
|
||||
observe(subject, topic, data) {
|
||||
|
@ -104,8 +103,7 @@ FormAutofillParent.prototype = {
|
|||
// Observe pref changes and update _enabled cache if status is changed.
|
||||
let currentStatus = this._getStatus();
|
||||
if (currentStatus !== this._enabled) {
|
||||
this._enabled = currentStatus;
|
||||
this._onStatusChanged();
|
||||
this._setStatus(currentStatus);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
@ -118,8 +116,7 @@ FormAutofillParent.prototype = {
|
|||
|
||||
let currentStatus = this._getStatus();
|
||||
if (currentStatus !== this._enabled) {
|
||||
this._enabled = currentStatus;
|
||||
this._onStatusChanged();
|
||||
this._setStatus(currentStatus);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
@ -143,6 +140,9 @@ FormAutofillParent.prototype = {
|
|||
}
|
||||
|
||||
Services.ppmm.broadcastAsyncMessage("FormAutofill:enabledStatus", this._enabled);
|
||||
// Sync process data autofillEnabled to make sure the value up to date
|
||||
// no matter when the new content process is initialized.
|
||||
Services.ppmm.initialProcessData.autofillEnabled = this._enabled;
|
||||
},
|
||||
|
||||
/**
|
||||
|
@ -159,6 +159,16 @@ FormAutofillParent.prototype = {
|
|||
return this._profileStore.getAll().length > 0;
|
||||
},
|
||||
|
||||
/**
|
||||
* Set status and trigger _onStatusChanged.
|
||||
*
|
||||
* @param {boolean} newStatus The latest status we want to set for _enabled
|
||||
*/
|
||||
_setStatus(newStatus) {
|
||||
this._enabled = newStatus;
|
||||
this._onStatusChanged();
|
||||
},
|
||||
|
||||
/**
|
||||
* Handles the message coming from FormAutofillContent.
|
||||
*
|
||||
|
@ -171,10 +181,6 @@ FormAutofillParent.prototype = {
|
|||
case "FormAutofill:GetProfiles":
|
||||
this._getProfiles(data, target);
|
||||
break;
|
||||
case "FormAutofill:getEnabledStatus":
|
||||
Services.ppmm.broadcastAsyncMessage("FormAutofill:enabledStatus",
|
||||
this._enabled);
|
||||
break;
|
||||
}
|
||||
},
|
||||
|
||||
|
|
|
@ -69,11 +69,11 @@ ProfileAutoCompleteResult.prototype = {
|
|||
* @returns {number} The number of results
|
||||
*/
|
||||
get matchCount() {
|
||||
return this._matchingProfiles.length;
|
||||
return this._popupLabels.length;
|
||||
},
|
||||
|
||||
_checkIndexBounds(index) {
|
||||
if (index < 0 || index >= this._matchingProfiles.length) {
|
||||
if (index < 0 || index >= this._popupLabels.length) {
|
||||
throw Components.Exception("Index out of range.", Cr.NS_ERROR_ILLEGAL_VALUE);
|
||||
}
|
||||
},
|
||||
|
@ -123,7 +123,10 @@ ProfileAutoCompleteResult.prototype = {
|
|||
},
|
||||
|
||||
_generateLabels(focusedFieldName, allFieldNames, profiles) {
|
||||
return profiles.map(profile => {
|
||||
// Skip results without a primary label.
|
||||
return profiles.filter(profile => {
|
||||
return !!profile[focusedFieldName];
|
||||
}).map(profile => {
|
||||
return {
|
||||
primary: profile[focusedFieldName],
|
||||
secondary: this._getSecondaryLabel(focusedFieldName,
|
||||
|
|
|
@ -8,13 +8,15 @@ Cu.import("resource://formautofill/FormAutofillParent.jsm");
|
|||
|
||||
add_task(function* test_enabledStatus_init() {
|
||||
let formAutofillParent = new FormAutofillParent();
|
||||
sinon.spy(formAutofillParent, "_onStatusChanged");
|
||||
sinon.spy(formAutofillParent, "_setStatus");
|
||||
|
||||
// Default status is false before initialization
|
||||
do_check_eq(formAutofillParent._enabled, false);
|
||||
do_check_eq(Services.ppmm.initialProcessData.autofillEnabled, undefined);
|
||||
|
||||
formAutofillParent.init();
|
||||
do_check_eq(formAutofillParent._onStatusChanged.called, true);
|
||||
do_check_eq(formAutofillParent._setStatus.called, true);
|
||||
do_check_eq(Services.ppmm.initialProcessData.autofillEnabled, false);
|
||||
|
||||
formAutofillParent._uninit();
|
||||
});
|
||||
|
@ -22,36 +24,36 @@ add_task(function* test_enabledStatus_init() {
|
|||
add_task(function* test_enabledStatus_observe() {
|
||||
let formAutofillParent = new FormAutofillParent();
|
||||
sinon.stub(formAutofillParent, "_getStatus");
|
||||
sinon.spy(formAutofillParent, "_onStatusChanged");
|
||||
sinon.spy(formAutofillParent, "_setStatus");
|
||||
|
||||
// _enabled = _getStatus() => No need to trigger onStatusChanged
|
||||
formAutofillParent._enabled = true;
|
||||
formAutofillParent._getStatus.returns(true);
|
||||
formAutofillParent.observe(null, "nsPref:changed", "browser.formautofill.enabled");
|
||||
do_check_eq(formAutofillParent._onStatusChanged.called, false);
|
||||
do_check_eq(formAutofillParent._setStatus.called, false);
|
||||
|
||||
// _enabled != _getStatus() => Need to trigger onStatusChanged
|
||||
formAutofillParent._getStatus.returns(false);
|
||||
formAutofillParent.observe(null, "nsPref:changed", "browser.formautofill.enabled");
|
||||
do_check_eq(formAutofillParent._onStatusChanged.called, true);
|
||||
do_check_eq(formAutofillParent._setStatus.called, true);
|
||||
|
||||
// profile added => Need to trigger onStatusChanged
|
||||
formAutofillParent._getStatus.returns(!formAutofillParent._enabled);
|
||||
formAutofillParent._onStatusChanged.reset();
|
||||
formAutofillParent._setStatus.reset();
|
||||
formAutofillParent.observe(null, "formautofill-storage-changed", "add");
|
||||
do_check_eq(formAutofillParent._onStatusChanged.called, true);
|
||||
do_check_eq(formAutofillParent._setStatus.called, true);
|
||||
|
||||
// profile removed => Need to trigger onStatusChanged
|
||||
formAutofillParent._getStatus.returns(!formAutofillParent._enabled);
|
||||
formAutofillParent._onStatusChanged.reset();
|
||||
formAutofillParent._setStatus.reset();
|
||||
formAutofillParent.observe(null, "formautofill-storage-changed", "remove");
|
||||
do_check_eq(formAutofillParent._onStatusChanged.called, true);
|
||||
do_check_eq(formAutofillParent._setStatus.called, true);
|
||||
|
||||
// profile updated => no need to trigger onStatusChanged
|
||||
formAutofillParent._getStatus.returns(!formAutofillParent._enabled);
|
||||
formAutofillParent._onStatusChanged.reset();
|
||||
formAutofillParent._setStatus.reset();
|
||||
formAutofillParent.observe(null, "formautofill-storage-changed", "update");
|
||||
do_check_eq(formAutofillParent._onStatusChanged.called, false);
|
||||
do_check_eq(formAutofillParent._setStatus.called, false);
|
||||
});
|
||||
|
||||
add_task(function* test_enabledStatus_getStatus() {
|
||||
|
@ -82,3 +84,19 @@ add_task(function* test_enabledStatus_getStatus() {
|
|||
Services.prefs.setBoolPref("browser.formautofill.enabled", false);
|
||||
do_check_eq(formAutofillParent._getStatus(), false);
|
||||
});
|
||||
|
||||
add_task(function* test_enabledStatus_setStatus() {
|
||||
let formAutofillParent = new FormAutofillParent();
|
||||
sinon.spy(formAutofillParent, "_onStatusChanged");
|
||||
|
||||
formAutofillParent._setStatus(true);
|
||||
do_check_eq(formAutofillParent._enabled, true);
|
||||
do_check_eq(Services.ppmm.initialProcessData.autofillEnabled, true);
|
||||
do_check_eq(formAutofillParent._onStatusChanged.called, true);
|
||||
|
||||
formAutofillParent._onStatusChanged.reset();
|
||||
formAutofillParent._setStatus(false);
|
||||
do_check_eq(formAutofillParent._enabled, false);
|
||||
do_check_eq(Services.ppmm.initialProcessData.autofillEnabled, false);
|
||||
do_check_eq(formAutofillParent._onStatusChanged.called, true);
|
||||
});
|
||||
|
|
|
@ -12,11 +12,17 @@ let matchingProfiles = [{
|
|||
organization: "Mozilla",
|
||||
"street-address": "331 E. Evelyn Avenue",
|
||||
tel: "1-650-903-0800",
|
||||
}, {
|
||||
guid: "test-guid-3",
|
||||
organization: "",
|
||||
"street-address": "321, No Name St.",
|
||||
tel: "1-000-000-0000",
|
||||
}];
|
||||
|
||||
let allFieldNames = ["street-address", "organization", "tel"];
|
||||
|
||||
let testCases = [{
|
||||
description: "Focus on an `organization` field",
|
||||
options: {},
|
||||
matchingProfiles,
|
||||
allFieldNames,
|
||||
|
@ -46,6 +52,7 @@ let testCases = [{
|
|||
}],
|
||||
},
|
||||
}, {
|
||||
description: "Focus on an `tel` field",
|
||||
options: {},
|
||||
matchingProfiles,
|
||||
allFieldNames,
|
||||
|
@ -72,9 +79,19 @@ let testCases = [{
|
|||
secondary: "331 E. Evelyn Avenue",
|
||||
}),
|
||||
image: "",
|
||||
}, {
|
||||
value: "1-000-000-0000",
|
||||
style: "autofill-profile",
|
||||
comment: JSON.stringify(matchingProfiles[2]),
|
||||
label: JSON.stringify({
|
||||
primary: "1-000-000-0000",
|
||||
secondary: "321, No Name St.",
|
||||
}),
|
||||
image: "",
|
||||
}],
|
||||
},
|
||||
}, {
|
||||
description: "Focus on an `street-address` field",
|
||||
options: {},
|
||||
matchingProfiles,
|
||||
allFieldNames,
|
||||
|
@ -101,9 +118,19 @@ let testCases = [{
|
|||
secondary: "Mozilla",
|
||||
}),
|
||||
image: "",
|
||||
}, {
|
||||
value: "321, No Name St.",
|
||||
style: "autofill-profile",
|
||||
comment: JSON.stringify(matchingProfiles[2]),
|
||||
label: JSON.stringify({
|
||||
primary: "321, No Name St.",
|
||||
secondary: "1-000-000-0000",
|
||||
}),
|
||||
image: "",
|
||||
}],
|
||||
},
|
||||
}, {
|
||||
description: "No matching profiles",
|
||||
options: {},
|
||||
matchingProfiles: [],
|
||||
allFieldNames,
|
||||
|
@ -115,6 +142,7 @@ let testCases = [{
|
|||
items: [],
|
||||
},
|
||||
}, {
|
||||
description: "Search with failure",
|
||||
options: {resultCode: Ci.nsIAutoCompleteResult.RESULT_FAILURE},
|
||||
matchingProfiles: [],
|
||||
allFieldNames,
|
||||
|
@ -128,13 +156,14 @@ let testCases = [{
|
|||
}];
|
||||
|
||||
add_task(function* test_all_patterns() {
|
||||
testCases.forEach(pattern => {
|
||||
let actual = new ProfileAutoCompleteResult(pattern.searchString,
|
||||
pattern.fieldName,
|
||||
pattern.allFieldNames,
|
||||
pattern.matchingProfiles,
|
||||
pattern.options);
|
||||
let expectedValue = pattern.expected;
|
||||
testCases.forEach(testCase => {
|
||||
do_print("Starting testcase: " + testCase.description);
|
||||
let actual = new ProfileAutoCompleteResult(testCase.searchString,
|
||||
testCase.fieldName,
|
||||
testCase.allFieldNames,
|
||||
testCase.matchingProfiles,
|
||||
testCase.options);
|
||||
let expectedValue = testCase.expected;
|
||||
equal(actual.searchResult, expectedValue.searchResult);
|
||||
equal(actual.defaultIndex, expectedValue.defaultIndex);
|
||||
equal(actual.matchCount, expectedValue.items.length);
|
||||
|
|
|
@ -636,6 +636,7 @@
|
|||
@RESPATH@/greprefs.js
|
||||
@RESPATH@/defaults/autoconfig/prefcalls.js
|
||||
@RESPATH@/browser/defaults/permissions
|
||||
@RESPATH@/browser/defaults/blocklists
|
||||
|
||||
; Warning: changing the path to channel-prefs.js can cause bugs (Bug 756325)
|
||||
; Technically this is an app pref file, but we are keeping it in the original
|
||||
|
|
|
@ -207,12 +207,16 @@ spaceAlert.over5GB.prefButton.accesskey=O
|
|||
# LOCALIZATION NOTE (spaceAlert.over5GB.prefButtonWin.label): On Windows Preferences is called Options
|
||||
spaceAlert.over5GB.prefButtonWin.label=Open Options
|
||||
spaceAlert.over5GB.prefButtonWin.accesskey=O
|
||||
spaceAlert.over5GB.description=Firefox is running out of disk space. Website contents may not display properly. You can clear stored site data in Preferences > Advanced > Site Data.
|
||||
# LOCALIZATION NOTE (spaceAlert.over5GB.descriptionWin): On Windows Preferences is called Options
|
||||
spaceAlert.over5GB.descriptionWin=Firefox is running out of disk space. Website contents may not display properly. You can clear stored site data in Options > Advanced > Site Data.
|
||||
# LOCALIZATION NOTE (spaceAlert.over5GB.message): %S = brandShortName
|
||||
spaceAlert.over5GB.message=%S is running out of disk space. Website contents may not display properly. You can clear stored site data in Preferences > Advanced > Site Data.
|
||||
# LOCALIZATION NOTE (spaceAlert.over5GB.messageWin):
|
||||
# - On Windows Preferences is called Options
|
||||
# - %S = brandShortName
|
||||
spaceAlert.over5GB.messageWin=%S is running out of disk space. Website contents may not display properly. You can clear stored site data in Options > Advanced > Site Data.
|
||||
spaceAlert.under5GB.okButton.label=OK, Got it
|
||||
spaceAlert.under5GB.okButton.accesskey=K
|
||||
spaceAlert.under5GB.description=Firefox is running out of disk space. Website contents may not display properly. Visit “Learn More” to optimize your disk usage for better browsing experience.
|
||||
# LOCALIZATION NOTE (spaceAlert.under5GB.message): %S = brandShortName
|
||||
spaceAlert.under5GB.message=%S is running out of disk space. Website contents may not display properly. Visit “Learn More” to optimize your disk usage for better browsing experience.
|
||||
|
||||
# LOCALIZATION NOTE (featureEnableRequiresRestart, featureDisableRequiresRestart, restartTitle): %S = brandShortName
|
||||
featureEnableRequiresRestart=%S must restart to enable this feature.
|
||||
|
|
|
@ -4,8 +4,6 @@
|
|||
|
||||
"use strict";
|
||||
|
||||
const { Cu, Ci } = require("chrome");
|
||||
|
||||
const { TargetFactory } = require("devtools/client/framework/target");
|
||||
const { DebuggerServer } = require("devtools/server/main");
|
||||
const { DebuggerClient } = require("devtools/shared/client/main");
|
||||
|
@ -21,20 +19,25 @@ const { Task } = require("devtools/shared/task");
|
|||
* ws:
|
||||
* {Boolean} If true, connect via websocket instread of regular TCP connection.
|
||||
*
|
||||
* type: tab, process
|
||||
* {String} The type of target to connect to. Currently tabs and processes are supported types.
|
||||
* type: tab, process, window
|
||||
* {String} The type of target to connect to.
|
||||
*
|
||||
* If type="tab":
|
||||
* If type == "tab":
|
||||
* id:
|
||||
* {Number} the tab outerWindowID
|
||||
* chrome: Optional
|
||||
* {Boolean} Force the creation of a chrome target. Gives more privileges to the tab
|
||||
* actor. Allows chrome execution in the webconsole and see chrome files in
|
||||
* the debugger. (handy when contributing to firefox)
|
||||
* {Boolean} Force the creation of a chrome target. Gives more privileges to
|
||||
* the tab actor. Allows chrome execution in the webconsole and see chrome
|
||||
* files in the debugger. (handy when contributing to firefox)
|
||||
*
|
||||
* If type="process":
|
||||
* If type == "process":
|
||||
* id:
|
||||
* {Number} the process id to debug. Default to 0, which is the parent process.
|
||||
* {Number} the process id to debug. Default to 0, which is the parent
|
||||
* process.
|
||||
*
|
||||
* If type == "window":
|
||||
* id:
|
||||
* {Number} the window outerWindowID
|
||||
*
|
||||
* @param {URL} url
|
||||
* The url to fetch query params from.
|
||||
|
@ -93,6 +96,26 @@ exports.targetFromURL = Task.async(function* (url) {
|
|||
}
|
||||
throw ex;
|
||||
}
|
||||
} else if (type == "window") {
|
||||
// Fetch target for a remote window actor
|
||||
DebuggerServer.allowChromeProcess = true;
|
||||
try {
|
||||
id = parseInt(id, 10);
|
||||
if (isNaN(id)) {
|
||||
throw new Error("targetFromURL, window requires id parameter");
|
||||
}
|
||||
let response = yield client.mainRoot.getWindow({
|
||||
outerWindowID: id,
|
||||
});
|
||||
form = response.window;
|
||||
chrome = true;
|
||||
} catch (ex) {
|
||||
if (ex.error == "notFound") {
|
||||
throw new Error(`targetFromURL, window with id:'${id}' ` +
|
||||
"doesn't exist");
|
||||
}
|
||||
throw ex;
|
||||
}
|
||||
} else {
|
||||
throw new Error("targetFromURL, unsupported type='" + type + "' parameter");
|
||||
}
|
||||
|
|
|
@ -36,8 +36,19 @@ add_task(function* () {
|
|||
is(e.message, "targetFromURL, unsupported type='x' parameter");
|
||||
}
|
||||
|
||||
info("Test browser window");
|
||||
let windowId = window.QueryInterface(Ci.nsIInterfaceRequestor)
|
||||
.getInterface(Ci.nsIDOMWindowUtils)
|
||||
.outerWindowID;
|
||||
target = yield targetFromURL(new URL("http://foo?type=window&id=" + windowId));
|
||||
is(target.url, window.location.href);
|
||||
is(target.isLocalTab, false);
|
||||
is(target.chrome, true);
|
||||
is(target.isTabActor, true);
|
||||
is(target.isRemote, true);
|
||||
|
||||
info("Test tab");
|
||||
let windowId = browser.outerWindowID;
|
||||
windowId = browser.outerWindowID;
|
||||
target = yield targetFromURL(new URL("http://foo?type=tab&id=" + windowId));
|
||||
assertIsTabTarget(target, TEST_URI);
|
||||
|
||||
|
|
|
@ -2,6 +2,8 @@
|
|||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
/* eslint-env browser */
|
||||
|
||||
"use strict";
|
||||
|
||||
// URL constructor doesn't support about: scheme
|
||||
|
@ -26,6 +28,23 @@ if (url.search.length > 1) {
|
|||
.getInterface(Ci.nsIDOMWindowUtils)
|
||||
.containerElement;
|
||||
|
||||
// If there's no containerElement (which happens when loading about:devtools-toolbox as
|
||||
// a top level document), use the current window.
|
||||
if (!host) {
|
||||
host = {
|
||||
contentWindow: window,
|
||||
contentDocument: document,
|
||||
// toolbox-host-manager.js wants to set attributes on the frame that contains it,
|
||||
// but that is fine to skip and doesn't make sense when using the current window.
|
||||
setAttribute() {},
|
||||
ownerDocument: document,
|
||||
// toolbox-host-manager.js wants to listen for unload events from outside the frame,
|
||||
// but this is fine to skip since the toolbox code listens inside the frame as well,
|
||||
// and there is no outer document in this case.
|
||||
addEventListener() {},
|
||||
};
|
||||
}
|
||||
|
||||
// Specify the default tool to open
|
||||
let tool = url.searchParams.get("tool");
|
||||
|
||||
|
|
|
@ -5,12 +5,29 @@
|
|||
"use strict";
|
||||
|
||||
const {
|
||||
UPDATE_GRID_COLOR,
|
||||
UPDATE_GRID_HIGHLIGHTED,
|
||||
UPDATE_GRIDS,
|
||||
} = require("./index");
|
||||
|
||||
module.exports = {
|
||||
|
||||
/**
|
||||
* Update the color used for the grid's highlighter.
|
||||
*
|
||||
* @param {NodeFront} nodeFront
|
||||
* The NodeFront of the DOM node to toggle the grid highlighter.
|
||||
* @param {String} color
|
||||
* The color to use for thie nodeFront's grid highlighter.
|
||||
*/
|
||||
updateGridColor(nodeFront, color) {
|
||||
return {
|
||||
type: UPDATE_GRID_COLOR,
|
||||
color,
|
||||
nodeFront,
|
||||
};
|
||||
},
|
||||
|
||||
/**
|
||||
* Update the grid highlighted state.
|
||||
*
|
||||
|
@ -22,8 +39,8 @@ module.exports = {
|
|||
updateGridHighlighted(nodeFront, highlighted) {
|
||||
return {
|
||||
type: UPDATE_GRID_HIGHLIGHTED,
|
||||
nodeFront,
|
||||
highlighted,
|
||||
nodeFront,
|
||||
};
|
||||
},
|
||||
|
||||
|
|
|
@ -8,6 +8,9 @@ const { createEnum } = require("devtools/client/shared/enum");
|
|||
|
||||
createEnum([
|
||||
|
||||
// Update the color used for the overlay of a grid.
|
||||
"UPDATE_GRID_COLOR",
|
||||
|
||||
// Update the grid highlighted state.
|
||||
"UPDATE_GRID_HIGHLIGHTED",
|
||||
|
||||
|
|
|
@ -26,11 +26,13 @@ const App = createClass({
|
|||
|
||||
propTypes: {
|
||||
boxModel: PropTypes.shape(Types.boxModel).isRequired,
|
||||
getSwatchColorPickerTooltip: PropTypes.func.isRequired,
|
||||
grids: PropTypes.arrayOf(PropTypes.shape(Types.grid)).isRequired,
|
||||
highlighterSettings: PropTypes.shape(Types.highlighterSettings).isRequired,
|
||||
showBoxModelProperties: PropTypes.bool.isRequired,
|
||||
onShowBoxModelEditor: PropTypes.func.isRequired,
|
||||
onHideBoxModelHighlighter: PropTypes.func.isRequired,
|
||||
onSetGridOverlayColor: PropTypes.func.isRequired,
|
||||
onShowBoxModelEditor: PropTypes.func.isRequired,
|
||||
onShowBoxModelHighlighter: PropTypes.func.isRequired,
|
||||
onToggleGridHighlighter: PropTypes.func.isRequired,
|
||||
onToggleShowGridLineNumbers: PropTypes.func.isRequired,
|
||||
|
|
|
@ -18,8 +18,10 @@ module.exports = createClass({
|
|||
displayName: "Grid",
|
||||
|
||||
propTypes: {
|
||||
getSwatchColorPickerTooltip: PropTypes.func.isRequired,
|
||||
grids: PropTypes.arrayOf(PropTypes.shape(Types.grid)).isRequired,
|
||||
highlighterSettings: PropTypes.shape(Types.highlighterSettings).isRequired,
|
||||
onSetGridOverlayColor: PropTypes.func.isRequired,
|
||||
onToggleGridHighlighter: PropTypes.func.isRequired,
|
||||
onToggleShowGridLineNumbers: PropTypes.func.isRequired,
|
||||
onToggleShowInfiniteLines: PropTypes.func.isRequired,
|
||||
|
@ -29,8 +31,10 @@ module.exports = createClass({
|
|||
|
||||
render() {
|
||||
let {
|
||||
getSwatchColorPickerTooltip,
|
||||
grids,
|
||||
highlighterSettings,
|
||||
onSetGridOverlayColor,
|
||||
onToggleGridHighlighter,
|
||||
onToggleShowGridLineNumbers,
|
||||
onToggleShowInfiniteLines,
|
||||
|
@ -42,7 +46,9 @@ module.exports = createClass({
|
|||
id: "layout-grid-container",
|
||||
},
|
||||
GridList({
|
||||
getSwatchColorPickerTooltip,
|
||||
grids,
|
||||
onSetGridOverlayColor,
|
||||
onToggleGridHighlighter,
|
||||
}),
|
||||
GridDisplaySettings({
|
||||
|
|
|
@ -0,0 +1,118 @@
|
|||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
"use strict";
|
||||
|
||||
const { addons, createClass, DOM: dom, PropTypes } = require("devtools/client/shared/vendor/react");
|
||||
const { findDOMNode } = require("devtools/client/shared/vendor/react-dom");
|
||||
|
||||
const Types = require("../types");
|
||||
|
||||
module.exports = createClass({
|
||||
|
||||
displayName: "GridItem",
|
||||
|
||||
propTypes: {
|
||||
getSwatchColorPickerTooltip: PropTypes.func.isRequired,
|
||||
grid: PropTypes.shape(Types.grid).isRequired,
|
||||
onSetGridOverlayColor: PropTypes.func.isRequired,
|
||||
onToggleGridHighlighter: PropTypes.func.isRequired,
|
||||
},
|
||||
|
||||
mixins: [ addons.PureRenderMixin ],
|
||||
|
||||
componentDidMount() {
|
||||
let tooltip = this.props.getSwatchColorPickerTooltip();
|
||||
let swatchEl = findDOMNode(this).querySelector(".grid-color-swatch");
|
||||
|
||||
let previousColor;
|
||||
tooltip.addSwatch(swatchEl, {
|
||||
onCommit: this.setGridColor,
|
||||
onPreview: this.setGridColor,
|
||||
onRevert: () => {
|
||||
this.props.onSetGridOverlayColor(this.props.grid.nodeFront, previousColor);
|
||||
},
|
||||
onShow: () => {
|
||||
previousColor = this.props.grid.color;
|
||||
},
|
||||
});
|
||||
},
|
||||
|
||||
componentWillUnmount() {
|
||||
let tooltip = this.props.getSwatchColorPickerTooltip();
|
||||
let swatchEl = findDOMNode(this).querySelector(".grid-color-swatch");
|
||||
tooltip.removeSwatch(swatchEl);
|
||||
},
|
||||
|
||||
setGridColor() {
|
||||
let color = findDOMNode(this).querySelector(".grid-color-value").textContent;
|
||||
this.props.onSetGridOverlayColor(this.props.grid.nodeFront, color);
|
||||
},
|
||||
|
||||
onGridCheckboxClick() {
|
||||
let {
|
||||
grid,
|
||||
onToggleGridHighlighter,
|
||||
} = this.props;
|
||||
|
||||
onToggleGridHighlighter(grid.nodeFront);
|
||||
},
|
||||
|
||||
render() {
|
||||
let { grid } = this.props;
|
||||
let { nodeFront } = grid;
|
||||
let { displayName, attributes } = nodeFront;
|
||||
|
||||
let gridName = displayName;
|
||||
|
||||
let idIndex = attributes.findIndex(({ name }) => name === "id");
|
||||
if (idIndex > -1 && attributes[idIndex].value) {
|
||||
gridName += "#" + attributes[idIndex].value;
|
||||
}
|
||||
|
||||
let classIndex = attributes.findIndex(({name}) => name === "class");
|
||||
if (classIndex > -1 && attributes[classIndex].value) {
|
||||
gridName += "." + attributes[classIndex].value.split(" ").join(".");
|
||||
}
|
||||
|
||||
return dom.li(
|
||||
{
|
||||
key: grid.id,
|
||||
className: "grid-item",
|
||||
},
|
||||
dom.label(
|
||||
{},
|
||||
dom.input(
|
||||
{
|
||||
type: "checkbox",
|
||||
value: grid.id,
|
||||
checked: grid.highlighted,
|
||||
onChange: this.onGridCheckboxClick,
|
||||
}
|
||||
),
|
||||
gridName
|
||||
),
|
||||
dom.div(
|
||||
{
|
||||
className: "grid-color-swatch",
|
||||
style: {
|
||||
backgroundColor: grid.color,
|
||||
},
|
||||
title: grid.color,
|
||||
}
|
||||
),
|
||||
// The SwatchColorPicker relies on the nextSibling of the swatch element to apply
|
||||
// the selected color. This is why we use a span in display: none for now.
|
||||
// Ideally we should modify the SwatchColorPickerTooltip to bypass this requirement.
|
||||
// See https://bugzilla.mozilla.org/show_bug.cgi?id=1341578
|
||||
dom.span(
|
||||
{
|
||||
className: "grid-color-value"
|
||||
},
|
||||
grid.color
|
||||
)
|
||||
);
|
||||
},
|
||||
|
||||
});
|
|
@ -4,9 +4,11 @@
|
|||
|
||||
"use strict";
|
||||
|
||||
const { addons, createClass, DOM: dom, PropTypes } =
|
||||
const { addons, createClass, createFactory, DOM: dom, PropTypes } =
|
||||
require("devtools/client/shared/vendor/react");
|
||||
|
||||
const GridItem = createFactory(require("./GridItem"));
|
||||
|
||||
const Types = require("../types");
|
||||
const { getStr } = require("../utils/l10n");
|
||||
|
||||
|
@ -15,24 +17,20 @@ module.exports = createClass({
|
|||
displayName: "GridList",
|
||||
|
||||
propTypes: {
|
||||
getSwatchColorPickerTooltip: PropTypes.func.isRequired,
|
||||
grids: PropTypes.arrayOf(PropTypes.shape(Types.grid)).isRequired,
|
||||
onSetGridOverlayColor: PropTypes.func.isRequired,
|
||||
onToggleGridHighlighter: PropTypes.func.isRequired,
|
||||
},
|
||||
|
||||
mixins: [ addons.PureRenderMixin ],
|
||||
|
||||
onGridCheckboxClick({ target }) {
|
||||
let {
|
||||
grids,
|
||||
onToggleGridHighlighter,
|
||||
} = this.props;
|
||||
|
||||
onToggleGridHighlighter(grids[target.value].nodeFront);
|
||||
},
|
||||
|
||||
render() {
|
||||
let {
|
||||
getSwatchColorPickerTooltip,
|
||||
grids,
|
||||
onSetGridOverlayColor,
|
||||
onToggleGridHighlighter,
|
||||
} = this.props;
|
||||
|
||||
return dom.div(
|
||||
|
@ -45,43 +43,14 @@ module.exports = createClass({
|
|||
),
|
||||
dom.ul(
|
||||
{},
|
||||
grids.map(grid => {
|
||||
let { nodeFront } = grid;
|
||||
let { displayName, attributes } = nodeFront;
|
||||
|
||||
let gridName = displayName;
|
||||
|
||||
let idIndex = attributes.findIndex(({ name }) => name === "id");
|
||||
if (idIndex > -1 && attributes[idIndex].value) {
|
||||
gridName += "#" + attributes[idIndex].value;
|
||||
}
|
||||
|
||||
let classIndex = attributes.findIndex(({name}) => name === "class");
|
||||
if (classIndex > -1 && attributes[classIndex].value) {
|
||||
gridName += "." + attributes[classIndex].value.split(" ").join(".");
|
||||
}
|
||||
|
||||
return dom.li(
|
||||
{
|
||||
key: grid.id,
|
||||
},
|
||||
dom.label(
|
||||
{},
|
||||
dom.input(
|
||||
{
|
||||
type: "checkbox",
|
||||
value: grid.id,
|
||||
checked: grid.highlighted,
|
||||
onChange: this.onGridCheckboxClick,
|
||||
}
|
||||
),
|
||||
gridName
|
||||
)
|
||||
);
|
||||
})
|
||||
grids.map(grid => GridItem({
|
||||
getSwatchColorPickerTooltip,
|
||||
grid,
|
||||
onSetGridOverlayColor,
|
||||
onToggleGridHighlighter,
|
||||
}))
|
||||
)
|
||||
);
|
||||
},
|
||||
|
||||
});
|
||||
|
||||
|
|
|
@ -16,5 +16,6 @@ DevToolsModules(
|
|||
'ComputedProperty.js',
|
||||
'Grid.js',
|
||||
'GridDisplaySettings.js',
|
||||
'GridItem.js',
|
||||
'GridList.js',
|
||||
)
|
||||
|
|
|
@ -13,10 +13,13 @@ const { InplaceEditor } = require("devtools/client/shared/inplace-editor");
|
|||
const { createFactory, createElement } = require("devtools/client/shared/vendor/react");
|
||||
const { Provider } = require("devtools/client/shared/vendor/react-redux");
|
||||
|
||||
const SwatchColorPickerTooltip = require("devtools/client/shared/widgets/tooltip/SwatchColorPickerTooltip");
|
||||
|
||||
const {
|
||||
updateLayout,
|
||||
} = require("./actions/box-model");
|
||||
const {
|
||||
updateGridColor,
|
||||
updateGridHighlighted,
|
||||
updateGrids,
|
||||
} = require("./actions/grids");
|
||||
|
@ -37,6 +40,18 @@ const NUMERIC = /^-?[\d\.]+$/;
|
|||
const SHOW_GRID_LINE_NUMBERS = "devtools.gridinspector.showGridLineNumbers";
|
||||
const SHOW_INFINITE_LINES_PREF = "devtools.gridinspector.showInfiniteLines";
|
||||
|
||||
// Default grid colors.
|
||||
const GRID_COLORS = [
|
||||
"#05E4EE",
|
||||
"#BB9DFF",
|
||||
"#FFB53B",
|
||||
"#71F362",
|
||||
"#FF90FF",
|
||||
"#FF90FF",
|
||||
"#1B80FF",
|
||||
"#FF2647"
|
||||
];
|
||||
|
||||
function LayoutView(inspector, window) {
|
||||
this.document = window.document;
|
||||
this.highlighters = inspector.highlighters;
|
||||
|
@ -74,7 +89,23 @@ LayoutView.prototype = {
|
|||
|
||||
this.loadHighlighterSettings();
|
||||
|
||||
// Create a shared SwatchColorPicker instance to be reused by all GridItem components.
|
||||
this.swatchColorPickerTooltip = new SwatchColorPickerTooltip(
|
||||
this.inspector.toolbox.doc,
|
||||
this.inspector,
|
||||
{
|
||||
supportsCssColor4ColorFunction: () => false
|
||||
}
|
||||
);
|
||||
|
||||
let app = App({
|
||||
/**
|
||||
* Retrieve the shared SwatchColorPicker instance.
|
||||
*/
|
||||
getSwatchColorPickerTooltip: () => {
|
||||
return this.swatchColorPickerTooltip;
|
||||
},
|
||||
|
||||
/**
|
||||
* Shows the box model properties under the box model if true, otherwise, hidden by
|
||||
* default.
|
||||
|
@ -89,6 +120,29 @@ LayoutView.prototype = {
|
|||
toolbox.highlighterUtils.unhighlight();
|
||||
},
|
||||
|
||||
/**
|
||||
* Handler for a change in the grid overlay color picker for a grid container.
|
||||
*
|
||||
* @param {NodeFront} node
|
||||
* The NodeFront of the grid container element for which the grid color is
|
||||
* being updated.
|
||||
* @param {String} color
|
||||
* A hex string representing the color to use.
|
||||
*/
|
||||
onSetGridOverlayColor: (node, color) => {
|
||||
this.store.dispatch(updateGridColor(node, color));
|
||||
let { grids } = this.store.getState();
|
||||
|
||||
// If the grid for which the color was updated currently has a highlighter, update
|
||||
// the color.
|
||||
for (let grid of grids) {
|
||||
if (grid.nodeFront === node && grid.highlighted) {
|
||||
let highlighterSettings = this.getGridHighlighterSettings(node);
|
||||
this.highlighters.showGridHighlighter(node, highlighterSettings);
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* Shows the inplace editor when a box model editable value is clicked on the
|
||||
* box model panel.
|
||||
|
@ -180,13 +234,13 @@ LayoutView.prototype = {
|
|||
* highlighter is toggled on/off for.
|
||||
*/
|
||||
onToggleGridHighlighter: node => {
|
||||
let { highlighterSettings } = this.store.getState();
|
||||
let highlighterSettings = this.getGridHighlighterSettings(node);
|
||||
this.highlighters.toggleGridHighlighter(node, highlighterSettings);
|
||||
},
|
||||
|
||||
/**
|
||||
* Handler for a change in the show grid line numbers checkbox in the
|
||||
* GridDisplaySettings component. TOggles on/off the option to show the grid line
|
||||
* GridDisplaySettings component. Toggles on/off the option to show the grid line
|
||||
* numbers in the grid highlighter. Refreshes the shown grid highlighter for the
|
||||
* grids currently highlighted.
|
||||
*
|
||||
|
@ -197,10 +251,11 @@ LayoutView.prototype = {
|
|||
this.store.dispatch(updateShowGridLineNumbers(enabled));
|
||||
Services.prefs.setBoolPref(SHOW_GRID_LINE_NUMBERS, enabled);
|
||||
|
||||
let { grids, highlighterSettings } = this.store.getState();
|
||||
let { grids } = this.store.getState();
|
||||
|
||||
for (let grid of grids) {
|
||||
if (grid.highlighted) {
|
||||
let highlighterSettings = this.getGridHighlighterSettings(grid.nodeFront);
|
||||
this.highlighters.showGridHighlighter(grid.nodeFront, highlighterSettings);
|
||||
}
|
||||
}
|
||||
|
@ -219,14 +274,15 @@ LayoutView.prototype = {
|
|||
this.store.dispatch(updateShowInfiniteLines(enabled));
|
||||
Services.prefs.setBoolPref(SHOW_INFINITE_LINES_PREF, enabled);
|
||||
|
||||
let { grids, highlighterSettings } = this.store.getState();
|
||||
let { grids } = this.store.getState();
|
||||
|
||||
for (let grid of grids) {
|
||||
if (grid.highlighted) {
|
||||
let highlighterSettings = this.getGridHighlighterSettings(grid.nodeFront);
|
||||
this.highlighters.showGridHighlighter(grid.nodeFront, highlighterSettings);
|
||||
}
|
||||
}
|
||||
},
|
||||
}
|
||||
});
|
||||
|
||||
let provider = createElement(Provider, {
|
||||
|
@ -270,6 +326,43 @@ LayoutView.prototype = {
|
|||
this.walker = null;
|
||||
},
|
||||
|
||||
/**
|
||||
* Returns the color set for the grid highlighter associated with the provided
|
||||
* nodeFront.
|
||||
*
|
||||
* @param {NodeFront} nodeFront
|
||||
* The NodeFront for which we need the color.
|
||||
*/
|
||||
getGridColorForNodeFront(nodeFront) {
|
||||
let { grids } = this.store.getState();
|
||||
|
||||
for (let grid of grids) {
|
||||
if (grid.nodeFront === nodeFront) {
|
||||
return grid.color;
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
},
|
||||
|
||||
/**
|
||||
* Create a highlighter settings object for the provided nodeFront.
|
||||
*
|
||||
* @param {NodeFront} nodeFront
|
||||
* The NodeFront for which we need highlighter settings.
|
||||
*/
|
||||
getGridHighlighterSettings(nodeFront) {
|
||||
let { highlighterSettings } = this.store.getState();
|
||||
|
||||
// Get the grid color for the provided nodeFront.
|
||||
let color = this.getGridColorForNodeFront(nodeFront);
|
||||
|
||||
// Merge the grid color to the generic highlighter settings.
|
||||
return Object.assign({}, highlighterSettings, {
|
||||
color
|
||||
});
|
||||
},
|
||||
|
||||
/**
|
||||
* Returns true if the layout panel is visible, and false otherwise.
|
||||
*/
|
||||
|
@ -391,8 +484,12 @@ LayoutView.prototype = {
|
|||
let grid = gridFronts[i];
|
||||
let nodeFront = yield this.walker.getNodeFromActor(grid.actorID, ["containerEl"]);
|
||||
|
||||
let fallbackColor = GRID_COLORS[i % GRID_COLORS.length];
|
||||
let color = this.getGridColorForNodeFront(nodeFront) || fallbackColor;
|
||||
|
||||
grids.push({
|
||||
id: i,
|
||||
color,
|
||||
gridFragments: grid.gridFragments,
|
||||
highlighted: nodeFront == this.highlighters.gridHighlighterShown,
|
||||
nodeFront,
|
||||
|
|
|
@ -5,6 +5,7 @@
|
|||
"use strict";
|
||||
|
||||
const {
|
||||
UPDATE_GRID_COLOR,
|
||||
UPDATE_GRID_HIGHLIGHTED,
|
||||
UPDATE_GRIDS,
|
||||
} = require("../actions/index");
|
||||
|
@ -13,12 +14,10 @@ const INITIAL_GRIDS = [];
|
|||
|
||||
let reducers = {
|
||||
|
||||
[UPDATE_GRID_HIGHLIGHTED](grids, { nodeFront, highlighted }) {
|
||||
[UPDATE_GRID_COLOR](grids, { nodeFront, color }) {
|
||||
let newGrids = grids.map(g => {
|
||||
if (g.nodeFront == nodeFront) {
|
||||
g.highlighted = highlighted;
|
||||
} else {
|
||||
g.highlighted = false;
|
||||
g.color = color;
|
||||
}
|
||||
|
||||
return g;
|
||||
|
@ -27,6 +26,14 @@ let reducers = {
|
|||
return newGrids;
|
||||
},
|
||||
|
||||
[UPDATE_GRID_HIGHLIGHTED](grids, { nodeFront, highlighted }) {
|
||||
return grids.map(g => {
|
||||
return Object.assign({}, g, {
|
||||
highlighted: g.nodeFront === nodeFront ? highlighted : false
|
||||
});
|
||||
});
|
||||
},
|
||||
|
||||
[UPDATE_GRIDS](_, { grids }) {
|
||||
return grids;
|
||||
},
|
||||
|
|
|
@ -24,6 +24,9 @@ exports.grid = {
|
|||
// The id of the grid
|
||||
id: PropTypes.number,
|
||||
|
||||
// The color for the grid overlay highlighter
|
||||
color: PropTypes.string,
|
||||
|
||||
// The grid fragment object of the grid container
|
||||
gridFragments: PropTypes.array,
|
||||
|
||||
|
|
|
@ -52,3 +52,29 @@
|
|||
text-align: center;
|
||||
padding: 0.5em;
|
||||
}
|
||||
|
||||
/**
|
||||
* Grid Item
|
||||
*/
|
||||
|
||||
.grid-item {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.grid-item input {
|
||||
margin: 0 5px;
|
||||
}
|
||||
|
||||
.grid-color-swatch {
|
||||
width: 12px;
|
||||
height: 12px;
|
||||
margin-left: 5px;
|
||||
border: 1px solid var(--theme-highlight-gray);
|
||||
border-radius: 50%;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.grid-color-value {
|
||||
display: none;
|
||||
}
|
||||
|
|
|
@ -21,20 +21,22 @@ const {
|
|||
const { stringifyGridFragments } = require("devtools/server/actors/utils/css-grid-utils");
|
||||
|
||||
const CSS_GRID_ENABLED_PREF = "layout.css.grid.enabled";
|
||||
const DEFAULT_GRID_COLOR = "#4B0082";
|
||||
const ROWS = "rows";
|
||||
const COLUMNS = "cols";
|
||||
|
||||
const GRID_LINES_PROPERTIES = {
|
||||
"edge": {
|
||||
lineDash: [0, 0],
|
||||
strokeStyle: "#4B0082"
|
||||
alpha: 1,
|
||||
},
|
||||
"explicit": {
|
||||
lineDash: [5, 3],
|
||||
strokeStyle: "#8A2BE2"
|
||||
alpha: 0.75,
|
||||
},
|
||||
"implicit": {
|
||||
lineDash: [2, 2],
|
||||
strokeStyle: "#9370DB"
|
||||
alpha: 0.5,
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -42,7 +44,7 @@ const GRID_LINES_PROPERTIES = {
|
|||
const GRID_GAP_PATTERN_WIDTH = 14;
|
||||
const GRID_GAP_PATTERN_HEIGHT = 14;
|
||||
const GRID_GAP_PATTERN_LINE_DASH = [5, 3];
|
||||
const GRID_GAP_PATTERN_STROKE_STYLE = "#9370DB";
|
||||
const GRID_GAP_ALPHA = 0.5;
|
||||
|
||||
/**
|
||||
* Cached used by `CssGridHighlighter.getGridGapPattern`.
|
||||
|
@ -64,6 +66,9 @@ const COLUMN_KEY = {};
|
|||
* h.destroy();
|
||||
*
|
||||
* Available Options:
|
||||
* - color(colorValue)
|
||||
* @param {String} colorValue
|
||||
* The color that should be used to draw the highlighter for this grid.
|
||||
* - showGridArea(areaName)
|
||||
* @param {String} areaName
|
||||
* Shows the grid area highlight for the given area name.
|
||||
|
@ -251,6 +256,10 @@ CssGridHighlighter.prototype = extend(AutoRefreshHighlighter.prototype, {
|
|||
return this.getElement("canvas");
|
||||
},
|
||||
|
||||
get color() {
|
||||
return this.options.color || DEFAULT_GRID_COLOR;
|
||||
},
|
||||
|
||||
/**
|
||||
* Gets the grid gap pattern used to render the gap regions.
|
||||
*
|
||||
|
@ -270,6 +279,7 @@ CssGridHighlighter.prototype = extend(AutoRefreshHighlighter.prototype, {
|
|||
canvas.height = GRID_GAP_PATTERN_HEIGHT;
|
||||
|
||||
let ctx = canvas.getContext("2d");
|
||||
ctx.save();
|
||||
ctx.setLineDash(GRID_GAP_PATTERN_LINE_DASH);
|
||||
ctx.beginPath();
|
||||
ctx.translate(.5, .5);
|
||||
|
@ -282,8 +292,10 @@ CssGridHighlighter.prototype = extend(AutoRefreshHighlighter.prototype, {
|
|||
ctx.lineTo(0, GRID_GAP_PATTERN_HEIGHT);
|
||||
}
|
||||
|
||||
ctx.strokeStyle = GRID_GAP_PATTERN_STROKE_STYLE;
|
||||
ctx.strokeStyle = this.color;
|
||||
ctx.globalAlpha = GRID_GAP_ALPHA;
|
||||
ctx.stroke();
|
||||
ctx.restore();
|
||||
|
||||
let pattern = ctx.createPattern(canvas, "repeat");
|
||||
gCachedGridPattern.set(dimension, pattern);
|
||||
|
@ -295,8 +307,7 @@ CssGridHighlighter.prototype = extend(AutoRefreshHighlighter.prototype, {
|
|||
* using DeadWrapper objects as gap patterns the next time.
|
||||
*/
|
||||
onNavigate() {
|
||||
gCachedGridPattern.delete(ROW_KEY);
|
||||
gCachedGridPattern.delete(COLUMN_KEY);
|
||||
this._clearCache();
|
||||
},
|
||||
|
||||
onWillNavigate({ isTopLevel }) {
|
||||
|
@ -311,9 +322,17 @@ CssGridHighlighter.prototype = extend(AutoRefreshHighlighter.prototype, {
|
|||
return false;
|
||||
}
|
||||
|
||||
// The grid pattern cache should be cleared in case the color changed.
|
||||
this._clearCache();
|
||||
|
||||
return this._update();
|
||||
},
|
||||
|
||||
_clearCache() {
|
||||
gCachedGridPattern.delete(ROW_KEY);
|
||||
gCachedGridPattern.delete(COLUMN_KEY);
|
||||
},
|
||||
|
||||
/**
|
||||
* Shows the grid area highlight for the given area name.
|
||||
*
|
||||
|
@ -610,7 +629,9 @@ CssGridHighlighter.prototype = extend(AutoRefreshHighlighter.prototype, {
|
|||
this.ctx.lineTo(endPos, linePos);
|
||||
}
|
||||
|
||||
this.ctx.strokeStyle = GRID_LINES_PROPERTIES[lineType].strokeStyle;
|
||||
this.ctx.strokeStyle = this.color;
|
||||
this.ctx.globalAlpha = GRID_LINES_PROPERTIES[lineType].alpha;
|
||||
|
||||
this.ctx.stroke();
|
||||
this.ctx.restore();
|
||||
},
|
||||
|
@ -631,11 +652,16 @@ CssGridHighlighter.prototype = extend(AutoRefreshHighlighter.prototype, {
|
|||
renderGridLineNumber(lineNumber, linePos, startPos, dimensionType) {
|
||||
this.ctx.save();
|
||||
|
||||
let textWidth = this.ctx.measureText(lineNumber).width;
|
||||
// Guess the font height based on the measured width
|
||||
let textHeight = textWidth * 2;
|
||||
|
||||
if (dimensionType === COLUMNS) {
|
||||
this.ctx.fillText(lineNumber, linePos, startPos);
|
||||
let yPos = Math.max(startPos, textHeight);
|
||||
this.ctx.fillText(lineNumber, linePos, yPos);
|
||||
} else {
|
||||
let textWidth = this.ctx.measureText(lineNumber).width;
|
||||
this.ctx.fillText(lineNumber, startPos - textWidth, linePos);
|
||||
let xPos = Math.max(startPos, textWidth);
|
||||
this.ctx.fillText(lineNumber, xPos - textWidth, linePos);
|
||||
}
|
||||
|
||||
this.ctx.restore();
|
||||
|
|
|
@ -66,6 +66,7 @@ DevToolsModules(
|
|||
'webextension-inspected-window.js',
|
||||
'webextension.js',
|
||||
'webgl.js',
|
||||
'window.js',
|
||||
'worker-list.js',
|
||||
'worker.js',
|
||||
)
|
||||
|
|
|
@ -7,6 +7,7 @@
|
|||
"use strict";
|
||||
|
||||
const { Cc, Ci, Cu } = require("chrome");
|
||||
const Services = require("Services");
|
||||
const { ActorPool, appendExtraActors, createExtraActors } = require("devtools/server/actors/common");
|
||||
const { DebuggerServer } = require("devtools/server/main");
|
||||
|
||||
|
@ -14,6 +15,8 @@ loader.lazyGetter(this, "ppmm", () => {
|
|||
return Cc["@mozilla.org/parentprocessmessagemanager;1"].getService(
|
||||
Ci.nsIMessageBroadcaster);
|
||||
});
|
||||
loader.lazyRequireGetter(this, "WindowActor",
|
||||
"devtools/server/actors/window", true);
|
||||
|
||||
/* Root actor for the remote debugging protocol. */
|
||||
|
||||
|
@ -167,12 +170,15 @@ RootActor.prototype = {
|
|||
// Added in Firefox 40. Indicates that the backend supports registering custom
|
||||
// commands through the WebConsoleCommands API.
|
||||
webConsoleCommands: true,
|
||||
// Whether root actor exposes tab actors
|
||||
// if allowChromeProcess is true, you can fetch a ChromeActor instance
|
||||
// to debug chrome and any non-content ressource via getProcess request
|
||||
// if allocChromeProcess is defined, but not true, it means that root actor
|
||||
// no longer expose tab actors, but also that getProcess forbids
|
||||
// exposing actors for security reasons
|
||||
// Whether root actor exposes tab actors and access to any window.
|
||||
// If allowChromeProcess is true, you can:
|
||||
// * get a ChromeActor instance to debug chrome and any non-content
|
||||
// resource via getProcess requests
|
||||
// * get a WindowActor instance to debug windows which could be chrome,
|
||||
// like browser windows via getWindow requests
|
||||
// If allowChromeProcess is defined, but not true, it means that root actor
|
||||
// no longer expose tab actors, but also that the above requests are
|
||||
// forbidden for security reasons.
|
||||
get allowChromeProcess() {
|
||||
return DebuggerServer.allowChromeProcess;
|
||||
},
|
||||
|
@ -232,6 +238,7 @@ RootActor.prototype = {
|
|||
this.conn = null;
|
||||
this._tabActorPool = null;
|
||||
this._globalActorPool = null;
|
||||
this._windowActorPool = null;
|
||||
this._parameters = null;
|
||||
this._chromeActor = null;
|
||||
this._processActors.clear();
|
||||
|
@ -338,6 +345,38 @@ RootActor.prototype = {
|
|||
});
|
||||
},
|
||||
|
||||
onGetWindow: function ({ outerWindowID }) {
|
||||
if (!DebuggerServer.allowChromeProcess) {
|
||||
return {
|
||||
from: this.actorID,
|
||||
error: "forbidden",
|
||||
message: "You are not allowed to debug windows."
|
||||
};
|
||||
}
|
||||
let window = Services.wm.getOuterWindowWithId(outerWindowID);
|
||||
if (!window) {
|
||||
return {
|
||||
from: this.actorID,
|
||||
error: "notFound",
|
||||
message: `No window found with outerWindowID ${outerWindowID}`,
|
||||
};
|
||||
}
|
||||
|
||||
if (!this._windowActorPool) {
|
||||
this._windowActorPool = new ActorPool(this.conn);
|
||||
this.conn.addActorPool(this._windowActorPool);
|
||||
}
|
||||
|
||||
let actor = new WindowActor(this.conn, window);
|
||||
actor.parentID = this.actorID;
|
||||
this._windowActorPool.addActor(actor);
|
||||
|
||||
return {
|
||||
from: this.actorID,
|
||||
window: actor.form(),
|
||||
};
|
||||
},
|
||||
|
||||
onTabListChanged: function () {
|
||||
this.conn.send({ from: this.actorID, type: "tabListChanged" });
|
||||
/* It's a one-shot notification; no need to watch any more. */
|
||||
|
@ -539,6 +578,7 @@ RootActor.prototype = {
|
|||
RootActor.prototype.requestTypes = {
|
||||
"listTabs": RootActor.prototype.onListTabs,
|
||||
"getTab": RootActor.prototype.onGetTab,
|
||||
"getWindow": RootActor.prototype.onGetWindow,
|
||||
"listAddons": RootActor.prototype.onListAddons,
|
||||
"listWorkers": RootActor.prototype.onListWorkers,
|
||||
"listServiceWorkerRegistrations": RootActor.prototype.onListServiceWorkerRegistrations,
|
||||
|
|
|
@ -0,0 +1,83 @@
|
|||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
"use strict";
|
||||
|
||||
const { Ci } = require("chrome");
|
||||
const Services = require("Services");
|
||||
const { TabActor } = require("./tab");
|
||||
|
||||
/**
|
||||
* Creates a WindowActor for debugging a single window, like a browser window in Firefox,
|
||||
* but it can be used to reach any window in the process. (Currently this is parent
|
||||
* process only because the root actor's `onGetWindow` doesn't try to cross process
|
||||
* boundaries.) Both chrome and content windows are supported.
|
||||
*
|
||||
* Most of the implementation is inherited from TabActor. WindowActor exposes all tab
|
||||
* actors via its form() request, like TabActor.
|
||||
*
|
||||
* You can request a specific window's actor via RootActor.getWindow().
|
||||
*
|
||||
* @param connection DebuggerServerConnection
|
||||
* The connection to the client.
|
||||
* @param window DOMWindow
|
||||
* The window.
|
||||
*/
|
||||
function WindowActor(connection, window) {
|
||||
TabActor.call(this, connection);
|
||||
|
||||
let docShell = window.QueryInterface(Ci.nsIInterfaceRequestor)
|
||||
.getInterface(Ci.nsIDocShell);
|
||||
Object.defineProperty(this, "docShell", {
|
||||
value: docShell,
|
||||
configurable: true
|
||||
});
|
||||
}
|
||||
|
||||
WindowActor.prototype = Object.create(TabActor.prototype);
|
||||
|
||||
// Bug 1266561: This setting is mysteriously named, we should split up the
|
||||
// functionality that is triggered by it.
|
||||
WindowActor.prototype.isRootActor = true;
|
||||
|
||||
WindowActor.prototype.observe = function (subject, topic, data) {
|
||||
TabActor.prototype.observe.call(this, subject, topic, data);
|
||||
if (!this.attached) {
|
||||
return;
|
||||
}
|
||||
if (topic == "chrome-webnavigation-destroy") {
|
||||
this._onDocShellDestroy(subject);
|
||||
}
|
||||
};
|
||||
|
||||
WindowActor.prototype._attach = function () {
|
||||
if (this.attached) {
|
||||
return false;
|
||||
}
|
||||
|
||||
TabActor.prototype._attach.call(this);
|
||||
|
||||
// Listen for chrome docshells in addition to content docshells
|
||||
if (this.docShell.itemType == Ci.nsIDocShellTreeItem.typeChrome) {
|
||||
Services.obs.addObserver(this, "chrome-webnavigation-destroy", false);
|
||||
}
|
||||
|
||||
return true;
|
||||
};
|
||||
|
||||
WindowActor.prototype._detach = function () {
|
||||
if (!this.attached) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (this.docShell.itemType == Ci.nsIDocShellTreeItem.typeChrome) {
|
||||
Services.obs.removeObserver(this, "chrome-webnavigation-destroy");
|
||||
}
|
||||
|
||||
TabActor.prototype._detach.call(this);
|
||||
|
||||
return true;
|
||||
};
|
||||
|
||||
exports.WindowActor = WindowActor;
|
|
@ -7,7 +7,8 @@ once a parent is removed from the pool, its children are removed as well.
|
|||
|
||||
The overall hierarchy of actors looks like this:
|
||||
|
||||
RootActor: First one, automatically instantiated when we start connecting.
|
||||
```
|
||||
RootActor: First one, automatically instantiated when we start connecting.
|
||||
| Mostly meant to instantiate new actors.
|
||||
|
|
||||
|--> Global-scoped actors:
|
||||
|
@ -27,6 +28,7 @@ The overall hierarchy of actors looks like this:
|
|||
worker). Examples include the console and inspector actors.
|
||||
These actors may extend this hierarchy by having their
|
||||
own children, like LongStringActor, WalkerActor, etc.
|
||||
```
|
||||
|
||||
## RootActor
|
||||
|
||||
|
@ -36,7 +38,8 @@ All other actors have an `actorID` which is computed dynamically,
|
|||
so that you need to ask an existing actor to create an Actor
|
||||
and returns its `actorID`. That's the main role of RootActor.
|
||||
|
||||
RootActor (root.js)
|
||||
```
|
||||
RootActor (root.js)
|
||||
|
|
||||
|-- BrowserTabActor (webbrowser.js)
|
||||
| Targets tabs living in the parent or child process. Note that this is
|
||||
|
@ -60,6 +63,11 @@ and returns its `actorID`. That's the main role of RootActor.
|
|||
| Returned by "listWorkers" request to a ChildProcessActor to get workers
|
||||
| for the chrome of the child process.
|
||||
|
|
||||
|-- WindowActor (window.js)
|
||||
| Targets a single window, such as a browser window in Firefox, but it can
|
||||
| be used to reach any window in the parent process.
|
||||
| Returned by "getWindow" request to the root actor.
|
||||
|
|
||||
|-- ChromeActor (chrome.js)
|
||||
| Targets all resources in the parent process of firefox
|
||||
| (chrome documents, JSM, JS XPCOM, etc.).
|
||||
|
@ -73,6 +81,7 @@ and returns its `actorID`. That's the main role of RootActor.
|
|||
\-- BrowserAddonActor (addon.js)
|
||||
Targets the javascript of add-ons.
|
||||
Returned by "listAddons" request.
|
||||
```
|
||||
|
||||
## "TabActor"
|
||||
|
||||
|
|
|
@ -12,8 +12,8 @@
|
|||
.simple-animation {
|
||||
display: inline-block;
|
||||
|
||||
width: 50px;
|
||||
height: 50px;
|
||||
width: 64px;
|
||||
height: 64px;
|
||||
border-radius: 50%;
|
||||
background: red;
|
||||
|
||||
|
|
|
@ -1741,6 +1741,27 @@ RootClient.prototype = {
|
|||
return this.request(packet);
|
||||
},
|
||||
|
||||
/**
|
||||
* Fetch the WindowActor for a specific window, like a browser window in
|
||||
* Firefox, but it can be used to reach any window in the process.
|
||||
*
|
||||
* @param number outerWindowID
|
||||
* The outerWindowID of the top level window you are looking for.
|
||||
*/
|
||||
getWindow: function ({ outerWindowID }) {
|
||||
if (!outerWindowID) {
|
||||
throw new Error("Must specify outerWindowID");
|
||||
}
|
||||
|
||||
let packet = {
|
||||
to: this.actor,
|
||||
type: "getWindow",
|
||||
outerWindowID,
|
||||
};
|
||||
|
||||
return this.request(packet);
|
||||
},
|
||||
|
||||
/**
|
||||
* Description of protocol's actors and methods.
|
||||
*
|
||||
|
|
|
@ -138,6 +138,12 @@ static const RedirEntry kRedirMap[] = {
|
|||
{
|
||||
"webrtc", "chrome://global/content/aboutwebrtc/aboutWebrtc.html",
|
||||
nsIAboutModule::ALLOW_SCRIPT
|
||||
},
|
||||
{
|
||||
"printpreview", "about:blank",
|
||||
nsIAboutModule::URI_SAFE_FOR_UNTRUSTED_CONTENT |
|
||||
nsIAboutModule::HIDE_FROM_ABOUTABOUT |
|
||||
nsIAboutModule::URI_CAN_LOAD_IN_CHILD
|
||||
}
|
||||
};
|
||||
static const int kRedirTotal = mozilla::ArrayLength(kRedirMap);
|
||||
|
@ -173,9 +179,11 @@ nsAboutRedirector::NewChannel(nsIURI* aURI,
|
|||
&isUIResource);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
nsLoadFlags loadFlags =
|
||||
isUIResource ? static_cast<nsLoadFlags>(nsIChannel::LOAD_NORMAL)
|
||||
: static_cast<nsLoadFlags>(nsIChannel::LOAD_REPLACE);
|
||||
bool isAboutBlank = NS_IsAboutBlank(tempURI);
|
||||
|
||||
nsLoadFlags loadFlags = isUIResource || isAboutBlank
|
||||
? static_cast<nsLoadFlags>(nsIChannel::LOAD_NORMAL)
|
||||
: static_cast<nsLoadFlags>(nsIChannel::LOAD_REPLACE);
|
||||
|
||||
rv = NS_NewChannelInternal(getter_AddRefs(tempChannel),
|
||||
tempURI,
|
||||
|
|
|
@ -14364,10 +14364,19 @@ nsDocShell::GetPrintPreview(nsIWebBrowserPrint** aPrintPreview)
|
|||
#if NS_PRINT_PREVIEW
|
||||
nsCOMPtr<nsIDocumentViewerPrint> print = do_QueryInterface(mContentViewer);
|
||||
if (!print || !print->IsInitializedForPrintPreview()) {
|
||||
// XXX: Creating a brand new content viewer to host preview every
|
||||
// time we enter here seems overwork. We could skip ahead to where
|
||||
// we QI the mContentViewer if the current URI is either about:blank
|
||||
// or about:printpreview.
|
||||
Stop(nsIWebNavigation::STOP_ALL);
|
||||
nsCOMPtr<nsIPrincipal> principal = nsNullPrincipal::CreateWithInheritedAttributes(this);
|
||||
nsresult rv = CreateAboutBlankContentViewer(principal, nullptr);
|
||||
nsCOMPtr<nsIURI> uri;
|
||||
NS_NewURI(getter_AddRefs(uri), NS_LITERAL_CSTRING("about:printpreview"));
|
||||
nsresult rv = CreateAboutBlankContentViewer(principal, uri);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
// Here we manually set current URI since we have just created a
|
||||
// brand new content viewer (about:blank) to host preview.
|
||||
SetCurrentURI(uri, nullptr, true, 0);
|
||||
print = do_QueryInterface(mContentViewer);
|
||||
NS_ENSURE_STATE(print);
|
||||
print->InitializeForPrintPreview();
|
||||
|
|
|
@ -189,6 +189,7 @@ const mozilla::Module::ContractIDEntry kDocShellContracts[] = {
|
|||
{ NS_ABOUT_MODULE_CONTRACTID_PREFIX "support", &kNS_ABOUT_REDIRECTOR_MODULE_CID },
|
||||
{ NS_ABOUT_MODULE_CONTRACTID_PREFIX "telemetry", &kNS_ABOUT_REDIRECTOR_MODULE_CID },
|
||||
{ NS_ABOUT_MODULE_CONTRACTID_PREFIX "webrtc", &kNS_ABOUT_REDIRECTOR_MODULE_CID },
|
||||
{ NS_ABOUT_MODULE_CONTRACTID_PREFIX "printpreview", &kNS_ABOUT_REDIRECTOR_MODULE_CID },
|
||||
{ NS_URI_LOADER_CONTRACTID, &kNS_URI_LOADER_CID },
|
||||
{ NS_DOCUMENTLOADER_SERVICE_CONTRACTID, &kNS_DOCUMENTLOADER_SERVICE_CID },
|
||||
{ NS_HANDLERSERVICE_CONTRACTID, &kNS_CONTENTHANDLERSERVICE_CID, mozilla::Module::CONTENT_PROCESS_ONLY },
|
||||
|
|
|
@ -33,13 +33,6 @@ AnimationPerformanceWarning::ToLocalizedString(
|
|||
const char* key = nullptr;
|
||||
|
||||
switch (mType) {
|
||||
case Type::ContentTooSmall:
|
||||
MOZ_ASSERT(mParams && mParams->Length() == 2,
|
||||
"Parameter's length should be 2 for ContentTooSmall");
|
||||
|
||||
return NS_SUCCEEDED(
|
||||
ToLocalizedStringWithIntParams<2>(
|
||||
"CompositorAnimationWarningContentTooSmall", aLocalizedString));
|
||||
case Type::ContentTooLarge:
|
||||
MOZ_ASSERT(mParams && mParams->Length() == 6,
|
||||
"Parameter's length should be 6 for ContentTooLarge");
|
||||
|
|
|
@ -20,7 +20,6 @@ namespace mozilla {
|
|||
struct AnimationPerformanceWarning
|
||||
{
|
||||
enum class Type : uint8_t {
|
||||
ContentTooSmall,
|
||||
ContentTooLarge,
|
||||
TransformBackfaceVisibilityHidden,
|
||||
TransformPreserve3D,
|
||||
|
|
|
@ -840,7 +840,7 @@ function testMultipleAnimationsWithGeometricAnimations() {
|
|||
function testSmallElements() {
|
||||
[
|
||||
{
|
||||
desc: 'opacity on too small element',
|
||||
desc: 'opacity on small element',
|
||||
frames: {
|
||||
opacity: [0, 1]
|
||||
},
|
||||
|
@ -855,13 +855,12 @@ function testSmallElements() {
|
|||
expected: [
|
||||
{
|
||||
property: 'opacity',
|
||||
runningOnCompositor: false,
|
||||
warning: /Animation cannot be run on the compositor because frame size \(8, 8\) is smaller than \(16, 16\)/
|
||||
runningOnCompositor: true
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
desc: 'transform on too small element',
|
||||
desc: 'transform on small element',
|
||||
frames: {
|
||||
transform: ['translate(0px)', 'translate(100px)']
|
||||
},
|
||||
|
@ -869,8 +868,7 @@ function testSmallElements() {
|
|||
expected: [
|
||||
{
|
||||
property: 'transform',
|
||||
runningOnCompositor: false,
|
||||
warning: /Animation cannot be run on the compositor because frame size \(8, 8\) is smaller than \(16, 16\)/
|
||||
runningOnCompositor: true
|
||||
}
|
||||
]
|
||||
},
|
||||
|
|
|
@ -11,9 +11,6 @@ ImageMapPolyOddNumberOfCoords=The “coords” attribute of the <area shape="pol
|
|||
TablePartRelPosWarning=Relative positioning of table rows and row groups is now supported. This site may need to be updated because it may depend on this feature having no effect.
|
||||
ScrollLinkedEffectFound2=This site appears to use a scroll-linked positioning effect. This may not work well with asynchronous panning; see https://developer.mozilla.org/docs/Mozilla/Performance/ScrollLinkedEffects for further details and to join the discussion on related tools and features!
|
||||
|
||||
## LOCALIZATION NOTE(CompositorAnimationWarningContentTooSmall):
|
||||
## (%1$S, %2$S) is a pair of integer values of the frame size
|
||||
CompositorAnimationWarningContentTooSmall=Animation cannot be run on the compositor because frame size (%1$S, %2$S) is smaller than (16, 16)
|
||||
## LOCALIZATION NOTE(CompositorAnimationWarningContentTooLarge2):
|
||||
## (%1$S, %2$S) is a pair of integer values of the frame size
|
||||
## (%3$S, %4$S) is a pair of integer values of a limit based on the viewport size
|
||||
|
|
|
@ -90,10 +90,11 @@ private:
|
|||
DECL_MEDIA_PREF("accessibility.monoaudio.enable", MonoAudio, bool, false);
|
||||
DECL_MEDIA_PREF("media.resampling.enabled", AudioSinkResampling, bool, false);
|
||||
DECL_MEDIA_PREF("media.resampling.rate", AudioSinkResampleRate, uint32_t, 48000);
|
||||
#if defined(ANDROID)
|
||||
DECL_MEDIA_PREF("media.forcestereo.enabled", AudioSinkForceStereo, bool, true);
|
||||
#else
|
||||
#if defined(XP_WIN) || defined(XP_DARWIN) || defined(MOZ_PULSEAUDIO)
|
||||
// libcubeb backend implement .get_preferred_channel_layout
|
||||
DECL_MEDIA_PREF("media.forcestereo.enabled", AudioSinkForceStereo, bool, false);
|
||||
#else
|
||||
DECL_MEDIA_PREF("media.forcestereo.enabled", AudioSinkForceStereo, bool, true);
|
||||
#endif
|
||||
// VideoSink
|
||||
DECL_MEDIA_PREF("media.ruin-av-sync.enabled", RuinAvSync, bool, false);
|
||||
|
|
|
@ -556,6 +556,7 @@ private:
|
|||
DECL_GFX_PREF(Live, "layout.display-list.dump-content", LayoutDumpDisplayListContent, bool, false);
|
||||
DECL_GFX_PREF(Live, "layout.event-regions.enabled", LayoutEventRegionsEnabledDoNotUseDirectly, bool, false);
|
||||
DECL_GFX_PREF(Once, "layout.frame_rate", LayoutFrameRate, int32_t, -1);
|
||||
DECL_GFX_PREF(Live, "layout.min-active-layer-size", LayoutMinActiveLayerSize, int, 64);
|
||||
DECL_GFX_PREF(Once, "layout.paint_rects_separately", LayoutPaintRectsSeparately, bool, true);
|
||||
|
||||
// This and code dependent on it should be removed once containerless scrolling looks stable.
|
||||
|
|
|
@ -0,0 +1,53 @@
|
|||
// |jit-test| --no-threads
|
||||
|
||||
function t1() {
|
||||
let x = [];
|
||||
|
||||
for (let k = 0; k < 100; ++k)
|
||||
x[k] = () => k; // Lexical capture
|
||||
|
||||
try {
|
||||
eval("k");
|
||||
throw false;
|
||||
}
|
||||
catch (e) {
|
||||
if (!(e instanceof ReferenceError))
|
||||
throw "Loop index escaped block";
|
||||
}
|
||||
|
||||
for (var i = 0; i < 100; ++i)
|
||||
if (x[i]() != i)
|
||||
throw "Bad let capture";
|
||||
}
|
||||
t1();
|
||||
t1();
|
||||
t1();
|
||||
t1();
|
||||
|
||||
function t2() {
|
||||
let x = [];
|
||||
let y = {};
|
||||
|
||||
for (var i = 0; i < 100; ++i)
|
||||
x[i] = i;
|
||||
|
||||
for (const k of x)
|
||||
y[k] = () => k; // Lexical capture
|
||||
|
||||
try {
|
||||
eval("k");
|
||||
throw false;
|
||||
}
|
||||
catch (e) {
|
||||
if (!(e instanceof ReferenceError))
|
||||
throw "Loop index escaped block";
|
||||
}
|
||||
|
||||
for (var i = 0; i < 100; ++i)
|
||||
if (y[i]() != i)
|
||||
throw "Bad const capture";
|
||||
}
|
||||
t2();
|
||||
t2();
|
||||
t2();
|
||||
t2();
|
|
@ -0,0 +1,46 @@
|
|||
// |jit-test| --no-threads
|
||||
|
||||
function t1() {
|
||||
let x = [];
|
||||
|
||||
try
|
||||
{
|
||||
for (let k = 0; k < 100; ++k)
|
||||
{
|
||||
let w = () => k; // Lexical capture
|
||||
|
||||
if (w() > 10)
|
||||
{
|
||||
throw () => w; // Lexical capture
|
||||
}
|
||||
|
||||
x[k] = w;
|
||||
}
|
||||
}
|
||||
catch (e)
|
||||
{
|
||||
// 'w' and 'k' should leave scope as exception unwinds
|
||||
|
||||
try {
|
||||
eval("k");
|
||||
throw false;
|
||||
}
|
||||
catch (e) {
|
||||
if (!(e instanceof ReferenceError))
|
||||
throw "Loop index escaped block";
|
||||
}
|
||||
|
||||
try {
|
||||
eval("w");
|
||||
throw false;
|
||||
}
|
||||
catch (e) {
|
||||
if (!(e instanceof ReferenceError))
|
||||
throw "Local name escaped block";
|
||||
}
|
||||
}
|
||||
}
|
||||
t1();
|
||||
t1();
|
||||
t1();
|
||||
t1();
|
|
@ -137,6 +137,8 @@ struct BaselineStackBuilder
|
|||
header_->resumeFramePtr = nullptr;
|
||||
header_->resumeAddr = nullptr;
|
||||
header_->resumePC = nullptr;
|
||||
header_->tryPC = nullptr;
|
||||
header_->faultPC = nullptr;
|
||||
header_->monitorStub = nullptr;
|
||||
header_->numFrames = 0;
|
||||
header_->checkGlobalDeclarationConflicts = false;
|
||||
|
@ -729,14 +731,12 @@ InitFromBailout(JSContext* cx, HandleScript caller, jsbytecode* callerPC,
|
|||
Value v = iter.read();
|
||||
if (v.isObject()) {
|
||||
envChain = &v.toObject();
|
||||
if (fun &&
|
||||
((fun->needsCallObject() && envChain->is<CallObject>()) ||
|
||||
(fun->needsNamedLambdaEnvironment() &&
|
||||
!fun->needsCallObject() &&
|
||||
envChain->is<LexicalEnvironmentObject>() &&
|
||||
&envChain->as<LexicalEnvironmentObject>().scope() ==
|
||||
script->maybeNamedLambdaScope())))
|
||||
{
|
||||
|
||||
// If Ion has updated env slot from UndefinedValue, it will be the
|
||||
// complete initial environment, so we can set the HAS_INITIAL_ENV
|
||||
// flag if needed.
|
||||
if (fun && fun->needsFunctionEnvironmentObjects()) {
|
||||
MOZ_ASSERT(fun->nonLazyScript()->initialEnvironmentShape());
|
||||
MOZ_ASSERT(!fun->needsExtraBodyVarEnvironment());
|
||||
flags |= BaselineFrame::HAS_INITIAL_ENV;
|
||||
}
|
||||
|
@ -1822,6 +1822,8 @@ jit::FinishBailoutToBaseline(BaselineBailoutInfo* bailoutInfo)
|
|||
BaselineFrame* topFrame = GetTopBaselineFrame(cx);
|
||||
topFrame->setOverridePc(bailoutInfo->resumePC);
|
||||
|
||||
jsbytecode* faultPC = bailoutInfo->faultPC;
|
||||
jsbytecode* tryPC = bailoutInfo->tryPC;
|
||||
uint32_t numFrames = bailoutInfo->numFrames;
|
||||
MOZ_ASSERT(numFrames > 0);
|
||||
BailoutKind bailoutKind = bailoutInfo->bailoutKind;
|
||||
|
@ -1939,6 +1941,13 @@ jit::FinishBailoutToBaseline(BaselineBailoutInfo* bailoutInfo)
|
|||
return false;
|
||||
}
|
||||
|
||||
// If we are catching an exception, we need to unwind scopes.
|
||||
// See |SettleOnTryNote|
|
||||
if (cx->isExceptionPending() && faultPC) {
|
||||
EnvironmentIter ei(cx, topFrame, faultPC);
|
||||
UnwindEnvironment(cx, ei, tryPC);
|
||||
}
|
||||
|
||||
JitSpew(JitSpew_BaselineBailouts,
|
||||
" Restored outerScript=(%s:%" PRIuSIZE ",%u) innerScript=(%s:%" PRIuSIZE ",%u) (bailoutKind=%u)",
|
||||
outerScript->filename(), outerScript->lineno(), outerScript->getWarmUpCount(),
|
||||
|
|
|
@ -592,6 +592,10 @@ struct BaselineBailoutInfo
|
|||
// The bytecode pc where we will resume.
|
||||
jsbytecode* resumePC;
|
||||
|
||||
// The bytecode pc of try block and fault block.
|
||||
jsbytecode* tryPC;
|
||||
jsbytecode* faultPC;
|
||||
|
||||
// If resuming into a TypeMonitor IC chain, this field holds the
|
||||
// address of the first stub in that chain. If this field is
|
||||
// set, then the actual jitcode resumed into is the jitcode for
|
||||
|
|
|
@ -168,6 +168,8 @@ BytecodeAnalysis::init(TempAllocator& alloc, GSNCache& gsn)
|
|||
case JSOP_LAMBDA_ARROW:
|
||||
case JSOP_DEFFUN:
|
||||
case JSOP_DEFVAR:
|
||||
case JSOP_PUSHLEXICALENV:
|
||||
case JSOP_POPLEXICALENV:
|
||||
usesEnvironmentChain_ = true;
|
||||
break;
|
||||
|
||||
|
|
|
@ -3433,6 +3433,35 @@ CodeGenerator::visitFunctionEnvironment(LFunctionEnvironment* lir)
|
|||
masm.loadPtr(environment, ToRegister(lir->output()));
|
||||
}
|
||||
|
||||
typedef LexicalEnvironmentObject* (*NewLexicalEnvironmentObjectFn)(JSContext*,
|
||||
Handle<LexicalScope*>,
|
||||
HandleObject, gc::InitialHeap);
|
||||
static const VMFunction NewLexicalEnvironmentObjectInfo =
|
||||
FunctionInfo<NewLexicalEnvironmentObjectFn>(LexicalEnvironmentObject::create,
|
||||
"LexicalEnvironmentObject::create");
|
||||
|
||||
void
|
||||
CodeGenerator::visitNewLexicalEnvironmentObject(LNewLexicalEnvironmentObject* lir)
|
||||
{
|
||||
pushArg(Imm32(gc::DefaultHeap));
|
||||
pushArg(ToRegister(lir->enclosing()));
|
||||
pushArg(ImmGCPtr(lir->mir()->scope()));
|
||||
callVM(NewLexicalEnvironmentObjectInfo, lir);
|
||||
}
|
||||
|
||||
typedef JSObject* (*CopyLexicalEnvironmentObjectFn)(JSContext*, HandleObject, bool);
|
||||
static const VMFunction CopyLexicalEnvironmentObjectInfo =
|
||||
FunctionInfo<CopyLexicalEnvironmentObjectFn>(js::jit::CopyLexicalEnvironmentObject,
|
||||
"js::jit::CopyLexicalEnvironmentObject");
|
||||
|
||||
void
|
||||
CodeGenerator::visitCopyLexicalEnvironmentObject(LCopyLexicalEnvironmentObject* lir)
|
||||
{
|
||||
pushArg(Imm32(lir->mir()->copySlots()));
|
||||
pushArg(ToRegister(lir->env()));
|
||||
callVM(CopyLexicalEnvironmentObjectInfo, lir);
|
||||
}
|
||||
|
||||
void
|
||||
CodeGenerator::visitGuardObjectIdentity(LGuardObjectIdentity* guard)
|
||||
{
|
||||
|
|
|
@ -287,6 +287,8 @@ class CodeGenerator final : public CodeGeneratorSpecific
|
|||
void visitSinCos(LSinCos *lir);
|
||||
void visitStringSplit(LStringSplit* lir);
|
||||
void visitFunctionEnvironment(LFunctionEnvironment* lir);
|
||||
void visitNewLexicalEnvironmentObject(LNewLexicalEnvironmentObject* lir);
|
||||
void visitCopyLexicalEnvironmentObject(LCopyLexicalEnvironmentObject* lir);
|
||||
void visitCallGetProperty(LCallGetProperty* lir);
|
||||
void visitCallGetElement(LCallGetElement* lir);
|
||||
void visitCallSetElement(LCallSetElement* lir);
|
||||
|
|
|
@ -1175,6 +1175,9 @@ IonBuilder::initEnvironmentChain(MDefinition* callee)
|
|||
env = constant(ObjectValue(script()->global().lexicalEnvironment()));
|
||||
}
|
||||
|
||||
// Update the environment slot from UndefinedValue only after initial
|
||||
// environment is created so that bailout doesn't see a partial env.
|
||||
// See: |InitFromBailout|
|
||||
current->setEnvironmentChain(env);
|
||||
return Ok();
|
||||
}
|
||||
|
@ -2207,6 +2210,19 @@ IonBuilder::inspectOpcode(JSOp op)
|
|||
case JSOP_SETFUNNAME:
|
||||
return jsop_setfunname(GET_UINT8(pc));
|
||||
|
||||
case JSOP_PUSHLEXICALENV:
|
||||
return jsop_pushlexicalenv(GET_UINT32_INDEX(pc));
|
||||
|
||||
case JSOP_POPLEXICALENV:
|
||||
current->setEnvironmentChain(walkEnvironmentChain(1));
|
||||
return Ok();
|
||||
|
||||
case JSOP_FRESHENLEXICALENV:
|
||||
return jsop_copylexicalenv(true);
|
||||
|
||||
case JSOP_RECREATELEXICALENV:
|
||||
return jsop_copylexicalenv(false);
|
||||
|
||||
case JSOP_ITER:
|
||||
return jsop_iter(GET_INT8(pc));
|
||||
|
||||
|
@ -2269,18 +2285,6 @@ IonBuilder::inspectOpcode(JSOp op)
|
|||
pushConstant(MagicValue(JS_IS_CONSTRUCTING));
|
||||
return Ok();
|
||||
|
||||
#ifdef DEBUG
|
||||
case JSOP_PUSHLEXICALENV:
|
||||
case JSOP_FRESHENLEXICALENV:
|
||||
case JSOP_RECREATELEXICALENV:
|
||||
case JSOP_POPLEXICALENV:
|
||||
// These opcodes are currently unhandled by Ion, but in principle
|
||||
// there's no reason they couldn't be. Whenever this happens, OSR
|
||||
// will have to consider that JSOP_{FRESHEN,RECREATE}LEXICALENV
|
||||
// mutates the env chain -- right now MBasicBlock::environmentChain()
|
||||
// caches the env chain. JSOP_{FRESHEN,RECREATE}LEXICALENV must
|
||||
// update that stale value.
|
||||
#endif
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
@ -11849,6 +11853,35 @@ IonBuilder::jsop_setfunname(uint8_t prefixKind)
|
|||
return resumeAfter(ins);
|
||||
}
|
||||
|
||||
AbortReasonOr<Ok>
|
||||
IonBuilder::jsop_pushlexicalenv(uint32_t index)
|
||||
{
|
||||
MOZ_ASSERT(analysis().usesEnvironmentChain());
|
||||
|
||||
LexicalScope* scope = &script()->getScope(index)->as<LexicalScope>();
|
||||
MNewLexicalEnvironmentObject* ins =
|
||||
MNewLexicalEnvironmentObject::New(alloc(), current->environmentChain(), scope);
|
||||
|
||||
current->add(ins);
|
||||
current->setEnvironmentChain(ins);
|
||||
|
||||
return resumeAfter(ins);
|
||||
}
|
||||
|
||||
AbortReasonOr<Ok>
|
||||
IonBuilder::jsop_copylexicalenv(bool copySlots)
|
||||
{
|
||||
MOZ_ASSERT(analysis().usesEnvironmentChain());
|
||||
|
||||
MCopyLexicalEnvironmentObject* ins =
|
||||
MCopyLexicalEnvironmentObject::New(alloc(), current->environmentChain(), copySlots);
|
||||
|
||||
current->add(ins);
|
||||
current->setEnvironmentChain(ins);
|
||||
|
||||
return resumeAfter(ins);
|
||||
}
|
||||
|
||||
AbortReasonOr<Ok>
|
||||
IonBuilder::jsop_setarg(uint32_t arg)
|
||||
{
|
||||
|
|
|
@ -561,6 +561,8 @@ class IonBuilder
|
|||
AbortReasonOr<Ok> jsop_lambda(JSFunction* fun);
|
||||
AbortReasonOr<Ok> jsop_lambda_arrow(JSFunction* fun);
|
||||
AbortReasonOr<Ok> jsop_setfunname(uint8_t prefixKind);
|
||||
AbortReasonOr<Ok> jsop_pushlexicalenv(uint32_t index);
|
||||
AbortReasonOr<Ok> jsop_copylexicalenv(bool copySlots);
|
||||
AbortReasonOr<Ok> jsop_functionthis();
|
||||
AbortReasonOr<Ok> jsop_globalthis();
|
||||
AbortReasonOr<Ok> jsop_typeof();
|
||||
|
|
|
@ -464,8 +464,14 @@ HandleExceptionIon(JSContext* cx, const InlineFrameIterator& frame, ResumeFromEx
|
|||
jsbytecode* catchPC = script->main() + tn->start + tn->length;
|
||||
ExceptionBailoutInfo excInfo(frame.frameNo(), catchPC, tn->stackDepth);
|
||||
uint32_t retval = ExceptionHandlerBailout(cx, frame, rfe, excInfo, overrecursed);
|
||||
if (retval == BAILOUT_RETURN_OK)
|
||||
if (retval == BAILOUT_RETURN_OK) {
|
||||
// Record exception locations to allow scope unwinding in
|
||||
// |FinishBailoutToBaseline|
|
||||
MOZ_ASSERT(cx->isExceptionPending());
|
||||
rfe->bailoutInfo->tryPC = UnwindEnvironmentToTryPc(frame.script(), tn);
|
||||
rfe->bailoutInfo->faultPC = frame.pc();
|
||||
return;
|
||||
}
|
||||
|
||||
// Error on bailout clears pending exception.
|
||||
MOZ_ASSERT(!cx->isExceptionPending());
|
||||
|
|
|
@ -2517,6 +2517,32 @@ LIRGenerator::visitSetFunName(MSetFunName* ins)
|
|||
assignSafepoint(lir, ins);
|
||||
}
|
||||
|
||||
void
|
||||
LIRGenerator::visitNewLexicalEnvironmentObject(MNewLexicalEnvironmentObject* ins)
|
||||
{
|
||||
MDefinition* enclosing = ins->enclosing();
|
||||
MOZ_ASSERT(enclosing->type() == MIRType::Object);
|
||||
|
||||
LNewLexicalEnvironmentObject* lir =
|
||||
new(alloc()) LNewLexicalEnvironmentObject(useRegisterAtStart(enclosing));
|
||||
|
||||
defineReturn(lir, ins);
|
||||
assignSafepoint(lir, ins);
|
||||
}
|
||||
|
||||
void
|
||||
LIRGenerator::visitCopyLexicalEnvironmentObject(MCopyLexicalEnvironmentObject* ins)
|
||||
{
|
||||
MDefinition* env = ins->env();
|
||||
MOZ_ASSERT(env->type() == MIRType::Object);
|
||||
|
||||
LCopyLexicalEnvironmentObject* lir =
|
||||
new(alloc()) LCopyLexicalEnvironmentObject(useRegisterAtStart(env));
|
||||
|
||||
defineReturn(lir, ins);
|
||||
assignSafepoint(lir, ins);
|
||||
}
|
||||
|
||||
void
|
||||
LIRGenerator::visitKeepAliveObject(MKeepAliveObject* ins)
|
||||
{
|
||||
|
|
|
@ -186,6 +186,8 @@ class LIRGenerator : public LIRGeneratorSpecific
|
|||
void visitLambda(MLambda* ins);
|
||||
void visitLambdaArrow(MLambdaArrow* ins);
|
||||
void visitSetFunName(MSetFunName* ins);
|
||||
void visitNewLexicalEnvironmentObject(MNewLexicalEnvironmentObject* ins);
|
||||
void visitCopyLexicalEnvironmentObject(MCopyLexicalEnvironmentObject* ins);
|
||||
void visitKeepAliveObject(MKeepAliveObject* ins);
|
||||
void visitSlots(MSlots* ins);
|
||||
void visitElements(MElements* ins);
|
||||
|
|
|
@ -11530,6 +11530,63 @@ class MFunctionEnvironment
|
|||
}
|
||||
};
|
||||
|
||||
// Allocate a new LexicalEnvironmentObject.
|
||||
class MNewLexicalEnvironmentObject
|
||||
: public MUnaryInstruction,
|
||||
public SingleObjectPolicy::Data
|
||||
{
|
||||
CompilerGCPointer<LexicalScope*> scope_;
|
||||
|
||||
MNewLexicalEnvironmentObject(MDefinition* enclosing, LexicalScope* scope)
|
||||
: MUnaryInstruction(enclosing),
|
||||
scope_(scope)
|
||||
{
|
||||
setResultType(MIRType::Object);
|
||||
}
|
||||
|
||||
public:
|
||||
INSTRUCTION_HEADER(NewLexicalEnvironmentObject)
|
||||
TRIVIAL_NEW_WRAPPERS
|
||||
NAMED_OPERANDS((0, enclosing))
|
||||
|
||||
LexicalScope* scope() const {
|
||||
return scope_;
|
||||
}
|
||||
bool possiblyCalls() const override {
|
||||
return true;
|
||||
}
|
||||
bool appendRoots(MRootList& roots) const override {
|
||||
return roots.append(scope_);
|
||||
}
|
||||
};
|
||||
|
||||
// Allocate a new LexicalEnvironmentObject from existing one
|
||||
class MCopyLexicalEnvironmentObject
|
||||
: public MUnaryInstruction,
|
||||
public SingleObjectPolicy::Data
|
||||
{
|
||||
bool copySlots_;
|
||||
|
||||
MCopyLexicalEnvironmentObject(MDefinition* env, bool copySlots)
|
||||
: MUnaryInstruction(env),
|
||||
copySlots_(copySlots)
|
||||
{
|
||||
setResultType(MIRType::Object);
|
||||
}
|
||||
|
||||
public:
|
||||
INSTRUCTION_HEADER(CopyLexicalEnvironmentObject)
|
||||
TRIVIAL_NEW_WRAPPERS
|
||||
NAMED_OPERANDS((0, env))
|
||||
|
||||
bool copySlots() const {
|
||||
return copySlots_;
|
||||
}
|
||||
bool possiblyCalls() const override {
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
// Store to vp[slot] (slots that are not inline in an object).
|
||||
class MStoreSlot
|
||||
: public MBinaryInstruction,
|
||||
|
|
|
@ -172,6 +172,8 @@ namespace jit {
|
|||
_(LoadSlot) \
|
||||
_(StoreSlot) \
|
||||
_(FunctionEnvironment) \
|
||||
_(NewLexicalEnvironmentObject) \
|
||||
_(CopyLexicalEnvironmentObject) \
|
||||
_(FilterTypeSet) \
|
||||
_(TypeBarrier) \
|
||||
_(MonitorTypes) \
|
||||
|
|
|
@ -956,6 +956,17 @@ NewArgumentsObject(JSContext* cx, BaselineFrame* frame, MutableHandleValue res)
|
|||
return true;
|
||||
}
|
||||
|
||||
JSObject*
|
||||
CopyLexicalEnvironmentObject(JSContext* cx, HandleObject env, bool copySlots)
|
||||
{
|
||||
Handle<LexicalEnvironmentObject*> lexicalEnv = env.as<LexicalEnvironmentObject>();
|
||||
|
||||
if (copySlots)
|
||||
return LexicalEnvironmentObject::clone(cx, lexicalEnv);
|
||||
|
||||
return LexicalEnvironmentObject::recreate(cx, lexicalEnv);
|
||||
}
|
||||
|
||||
JSObject*
|
||||
InitRestParameter(JSContext* cx, uint32_t length, Value* rest, HandleObject templateObj,
|
||||
HandleObject objRes)
|
||||
|
|
|
@ -278,6 +278,7 @@ template <> struct TypeToDataType<NativeObject*> { static const DataType result
|
|||
template <> struct TypeToDataType<PlainObject*> { static const DataType result = Type_Object; };
|
||||
template <> struct TypeToDataType<InlineTypedObject*> { static const DataType result = Type_Object; };
|
||||
template <> struct TypeToDataType<NamedLambdaObject*> { static const DataType result = Type_Object; };
|
||||
template <> struct TypeToDataType<LexicalEnvironmentObject*> { static const DataType result = Type_Object; };
|
||||
template <> struct TypeToDataType<ArrayObject*> { static const DataType result = Type_Object; };
|
||||
template <> struct TypeToDataType<TypedArrayObject*> { static const DataType result = Type_Object; };
|
||||
template <> struct TypeToDataType<JSString*> { static const DataType result = Type_Object; };
|
||||
|
@ -715,6 +716,8 @@ InitFunctionEnvironmentObjects(JSContext* cx, BaselineFrame* frame);
|
|||
MOZ_MUST_USE bool
|
||||
NewArgumentsObject(JSContext* cx, BaselineFrame* frame, MutableHandleValue res);
|
||||
|
||||
JSObject* CopyLexicalEnvironmentObject(JSContext* cx, HandleObject env, bool copySlots);
|
||||
|
||||
JSObject* InitRestParameter(JSContext* cx, uint32_t length, Value* rest, HandleObject templateObj,
|
||||
HandleObject res);
|
||||
|
||||
|
|
|
@ -7050,6 +7050,42 @@ class LFunctionEnvironment : public LInstructionHelper<1, 1, 0>
|
|||
}
|
||||
};
|
||||
|
||||
// Allocate a new LexicalEnvironmentObject.
|
||||
class LNewLexicalEnvironmentObject : public LCallInstructionHelper<1, 1, 0>
|
||||
{
|
||||
public:
|
||||
LIR_HEADER(NewLexicalEnvironmentObject)
|
||||
|
||||
explicit LNewLexicalEnvironmentObject(const LAllocation& enclosing) {
|
||||
setOperand(0, enclosing);
|
||||
}
|
||||
const LAllocation* enclosing() {
|
||||
return getOperand(0);
|
||||
}
|
||||
|
||||
MNewLexicalEnvironmentObject* mir() const {
|
||||
return mir_->toNewLexicalEnvironmentObject();
|
||||
}
|
||||
};
|
||||
|
||||
// Copy a LexicalEnvironmentObject.
|
||||
class LCopyLexicalEnvironmentObject : public LCallInstructionHelper<1, 1, 0>
|
||||
{
|
||||
public:
|
||||
LIR_HEADER(CopyLexicalEnvironmentObject)
|
||||
|
||||
explicit LCopyLexicalEnvironmentObject(const LAllocation& env) {
|
||||
setOperand(0, env);
|
||||
}
|
||||
const LAllocation* env() {
|
||||
return getOperand(0);
|
||||
}
|
||||
|
||||
MCopyLexicalEnvironmentObject* mir() const {
|
||||
return mir_->toCopyLexicalEnvironmentObject();
|
||||
}
|
||||
};
|
||||
|
||||
class LCallGetProperty : public LCallInstructionHelper<BOX_PIECES, BOX_PIECES, 0>
|
||||
{
|
||||
public:
|
||||
|
|
|
@ -319,6 +319,8 @@
|
|||
_(StoreFixedSlotV) \
|
||||
_(StoreFixedSlotT) \
|
||||
_(FunctionEnvironment) \
|
||||
_(NewLexicalEnvironmentObject) \
|
||||
_(CopyLexicalEnvironmentObject) \
|
||||
_(GetPropertyCacheV) \
|
||||
_(GetPropertyCacheT) \
|
||||
_(GetPropertyPolymorphicV) \
|
||||
|
|
|
@ -889,8 +889,8 @@ LexicalEnvironmentObject::createTemplateObject(JSContext* cx, HandleShape shape,
|
|||
}
|
||||
|
||||
/* static */ LexicalEnvironmentObject*
|
||||
LexicalEnvironmentObject::createTemplateObject(JSContext* cx, Handle<LexicalScope*> scope,
|
||||
HandleObject enclosing, gc::InitialHeap heap)
|
||||
LexicalEnvironmentObject::create(JSContext* cx, Handle<LexicalScope*> scope,
|
||||
HandleObject enclosing, gc::InitialHeap heap)
|
||||
{
|
||||
assertSameCompartment(cx, enclosing);
|
||||
MOZ_ASSERT(scope->hasEnvironment());
|
||||
|
@ -915,7 +915,7 @@ LexicalEnvironmentObject::create(JSContext* cx, Handle<LexicalScope*> scope,
|
|||
AbstractFramePtr frame)
|
||||
{
|
||||
RootedObject enclosing(cx, frame.environmentChain());
|
||||
return createTemplateObject(cx, scope, enclosing, gc::DefaultHeap);
|
||||
return create(cx, scope, enclosing, gc::DefaultHeap);
|
||||
}
|
||||
|
||||
/* static */ LexicalEnvironmentObject*
|
||||
|
@ -997,8 +997,7 @@ LexicalEnvironmentObject::clone(JSContext* cx, Handle<LexicalEnvironmentObject*>
|
|||
{
|
||||
Rooted<LexicalScope*> scope(cx, &env->scope());
|
||||
RootedObject enclosing(cx, &env->enclosingEnvironment());
|
||||
Rooted<LexicalEnvironmentObject*> copy(cx, createTemplateObject(cx, scope, enclosing,
|
||||
gc::TenuredHeap));
|
||||
Rooted<LexicalEnvironmentObject*> copy(cx, create(cx, scope, enclosing, gc::TenuredHeap));
|
||||
if (!copy)
|
||||
return nullptr;
|
||||
|
||||
|
@ -1016,7 +1015,7 @@ LexicalEnvironmentObject::recreate(JSContext* cx, Handle<LexicalEnvironmentObjec
|
|||
{
|
||||
Rooted<LexicalScope*> scope(cx, &env->scope());
|
||||
RootedObject enclosing(cx, &env->enclosingEnvironment());
|
||||
return createTemplateObject(cx, scope, enclosing, gc::TenuredHeap);
|
||||
return create(cx, scope, enclosing, gc::TenuredHeap);
|
||||
}
|
||||
|
||||
bool
|
||||
|
@ -1071,8 +1070,7 @@ NamedLambdaObject::create(JSContext* cx, HandleFunction callee,
|
|||
#endif
|
||||
|
||||
LexicalEnvironmentObject* obj =
|
||||
LexicalEnvironmentObject::createTemplateObject(cx, scope.as<LexicalScope>(),
|
||||
enclosing, heap);
|
||||
LexicalEnvironmentObject::create(cx, scope.as<LexicalScope>(), enclosing, heap);
|
||||
if (!obj)
|
||||
return nullptr;
|
||||
|
||||
|
|
|
@ -477,11 +477,8 @@ class LexicalEnvironmentObject : public EnvironmentObject
|
|||
}
|
||||
|
||||
public:
|
||||
static LexicalEnvironmentObject* createTemplateObject(JSContext* cx,
|
||||
Handle<LexicalScope*> scope,
|
||||
HandleObject enclosing,
|
||||
gc::InitialHeap heap);
|
||||
|
||||
static LexicalEnvironmentObject* create(JSContext* cx, Handle<LexicalScope*> scope,
|
||||
HandleObject enclosing, gc::InitialHeap heap);
|
||||
static LexicalEnvironmentObject* create(JSContext* cx, Handle<LexicalScope*> scope,
|
||||
AbstractFramePtr frame);
|
||||
static LexicalEnvironmentObject* createGlobal(JSContext* cx, Handle<GlobalObject*> global);
|
||||
|
|
|
@ -5212,43 +5212,20 @@ IsItemTooSmallForActiveLayer(nsIFrame* aFrame)
|
|||
{
|
||||
nsIntRect visibleDevPixels = aFrame->GetVisualOverflowRectRelativeToSelf().ToOutsidePixels(
|
||||
aFrame->PresContext()->AppUnitsPerDevPixel());
|
||||
static const int MIN_ACTIVE_LAYER_SIZE_DEV_PIXELS = 16;
|
||||
return visibleDevPixels.Size() <
|
||||
nsIntSize(MIN_ACTIVE_LAYER_SIZE_DEV_PIXELS, MIN_ACTIVE_LAYER_SIZE_DEV_PIXELS);
|
||||
}
|
||||
|
||||
static void
|
||||
SetAnimationPerformanceWarningForTooSmallItem(nsIFrame* aFrame,
|
||||
nsCSSPropertyID aProperty)
|
||||
{
|
||||
// We use ToNearestPixels() here since ToOutsidePixels causes some sort of
|
||||
// errors. See https://bugzilla.mozilla.org/show_bug.cgi?id=1258904#c19
|
||||
nsIntRect visibleDevPixels = aFrame->GetVisualOverflowRectRelativeToSelf().ToNearestPixels(
|
||||
aFrame->PresContext()->AppUnitsPerDevPixel());
|
||||
|
||||
// Set performance warning only if the visible dev pixels is not empty
|
||||
// because dev pixels is empty if the frame has 'preserve-3d' style.
|
||||
if (visibleDevPixels.IsEmpty()) {
|
||||
return;
|
||||
}
|
||||
|
||||
EffectCompositor::SetPerformanceWarning(aFrame, aProperty,
|
||||
AnimationPerformanceWarning(
|
||||
AnimationPerformanceWarning::Type::ContentTooSmall,
|
||||
{ visibleDevPixels.Width(), visibleDevPixels.Height() }));
|
||||
nsIntSize(gfxPrefs::LayoutMinActiveLayerSize(),
|
||||
gfxPrefs::LayoutMinActiveLayerSize());
|
||||
}
|
||||
|
||||
/* static */ bool
|
||||
nsDisplayOpacity::NeedsActiveLayer(nsDisplayListBuilder* aBuilder, nsIFrame* aFrame)
|
||||
{
|
||||
if (ActiveLayerTracker::IsStyleAnimated(aBuilder, aFrame,
|
||||
eCSSProperty_opacity) ||
|
||||
EffectCompositor::HasAnimationsForCompositor(aFrame,
|
||||
eCSSProperty_opacity)) {
|
||||
if (!IsItemTooSmallForActiveLayer(aFrame)) {
|
||||
return true;
|
||||
}
|
||||
SetAnimationPerformanceWarningForTooSmallItem(aFrame, eCSSProperty_opacity);
|
||||
if (EffectCompositor::HasAnimationsForCompositor(aFrame,
|
||||
eCSSProperty_opacity) ||
|
||||
(ActiveLayerTracker::IsStyleAnimated(aBuilder, aFrame,
|
||||
eCSSProperty_opacity) &&
|
||||
!IsItemTooSmallForActiveLayer(aFrame))) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
@ -6881,17 +6858,20 @@ already_AddRefed<Layer> nsDisplayTransform::BuildLayer(nsDisplayListBuilder *aBu
|
|||
bool
|
||||
nsDisplayTransform::MayBeAnimated(nsDisplayListBuilder* aBuilder)
|
||||
{
|
||||
// Here we check if the *post-transform* bounds of this item are big enough
|
||||
// to justify an active layer.
|
||||
if (ActiveLayerTracker::IsStyleAnimated(aBuilder,
|
||||
mFrame,
|
||||
eCSSProperty_transform) ||
|
||||
EffectCompositor::HasAnimationsForCompositor(mFrame,
|
||||
eCSSProperty_transform)) {
|
||||
if (!IsItemTooSmallForActiveLayer(mFrame)) {
|
||||
return true;
|
||||
}
|
||||
SetAnimationPerformanceWarningForTooSmallItem(mFrame, eCSSProperty_transform);
|
||||
// If EffectCompositor::HasAnimationsForCompositor() is true then we can
|
||||
// completely bypass the main thread for this animation, so it is always
|
||||
// worthwhile.
|
||||
// For ActiveLayerTracker::IsStyleAnimated() cases the main thread is
|
||||
// already involved so there is less to be gained.
|
||||
// Therefore we check that the *post-transform* bounds of this item are
|
||||
// big enough to justify an active layer.
|
||||
if (EffectCompositor::HasAnimationsForCompositor(mFrame,
|
||||
eCSSProperty_transform) ||
|
||||
(ActiveLayerTracker::IsStyleAnimated(aBuilder,
|
||||
mFrame,
|
||||
eCSSProperty_transform) &&
|
||||
!IsItemTooSmallForActiveLayer(mFrame))) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
|
|
@ -55,12 +55,10 @@ public:
|
|||
*/
|
||||
PreEffectsVisualOverflowCollector(nsIFrame* aFirstContinuation,
|
||||
nsIFrame* aCurrentFrame,
|
||||
const nsRect& aCurrentFrameOverflowArea,
|
||||
bool aCheckPreEffectsBBoxPropCache)
|
||||
const nsRect& aCurrentFrameOverflowArea)
|
||||
: mFirstContinuation(aFirstContinuation)
|
||||
, mCurrentFrame(aCurrentFrame)
|
||||
, mCurrentFrameOverflowArea(aCurrentFrameOverflowArea)
|
||||
, mCheckPreEffectsBBoxPropCache(aCheckPreEffectsBBoxPropCache)
|
||||
{
|
||||
NS_ASSERTION(!mFirstContinuation->GetPrevContinuation(),
|
||||
"We want the first continuation here");
|
||||
|
@ -69,7 +67,7 @@ public:
|
|||
virtual void AddBox(nsIFrame* aFrame) override {
|
||||
nsRect overflow = (aFrame == mCurrentFrame)
|
||||
? mCurrentFrameOverflowArea
|
||||
: GetPreEffectsVisualOverflowRect(aFrame, mCheckPreEffectsBBoxPropCache);
|
||||
: GetPreEffectsVisualOverflowRect(aFrame);
|
||||
mResult.UnionRect(mResult, overflow + aFrame->GetOffsetTo(mFirstContinuation));
|
||||
}
|
||||
|
||||
|
@ -79,72 +77,25 @@ public:
|
|||
|
||||
private:
|
||||
|
||||
static nsRect GetPreEffectsVisualOverflowRect(nsIFrame* aFrame,
|
||||
bool aCheckPropCache) {
|
||||
static nsRect GetPreEffectsVisualOverflowRect(nsIFrame* aFrame) {
|
||||
nsRect* r = aFrame->Properties().Get(nsIFrame::PreEffectsBBoxProperty());
|
||||
if (r) {
|
||||
return *r;
|
||||
}
|
||||
// Despite the fact that we're invoked for frames with SVG effects applied,
|
||||
// we can actually get here. All continuations and IB split siblings of a
|
||||
// frame with SVG effects applied will have the PreEffectsBBoxProperty
|
||||
// property set on them. Therefore, the frames that are passed to us will
|
||||
// always have that property set...well, with one exception. If the frames
|
||||
// for an element with SVG effects applied have been subject to an "IB
|
||||
// split", then the block frame(s) that caused the split will have been
|
||||
// wrapped in anonymous, inline-block, nsBlockFrames of pseudo-type
|
||||
// nsCSSAnonBoxes::mozAnonymousBlock. These "IB split sibling" anonymous
|
||||
// blocks will have the PreEffectsBBoxProperty property set on them, but
|
||||
// they will never be passed to us. Instead, we'll be passed the block
|
||||
// children that they wrap, which don't have the PreEffectsBBoxProperty
|
||||
// property set on them. This is actually okay. What we care about is
|
||||
// collecting the _pre_ effects visual overflow rects of the frames to
|
||||
// which the SVG effects have been applied. Since the IB split results in
|
||||
// any overflow rect adjustments for transforms, effects, etc. taking
|
||||
// place on the anonymous block wrappers, the wrapped children are left
|
||||
// with their overflow rects unaffected. In other words, calling
|
||||
// GetVisualOverflowRect() on the children will return their pre-effects
|
||||
// visual overflow rects, just as we need.
|
||||
//
|
||||
// A couple of tests that demonstrate the IB split and cause us to get here
|
||||
// are:
|
||||
//
|
||||
// * reftests/svg/svg-integration/clipPath-html-06.xhtml
|
||||
// * reftests/svg/svg-integration/clipPath-html-06-extref.xhtml
|
||||
//
|
||||
// If we ever got passed a frame with the PreTransformOverflowAreasProperty
|
||||
// property set, that would be bad, since then our GetVisualOverflowRect()
|
||||
// call would give us the post-effects, and post-transform, overflow rect.
|
||||
//
|
||||
// There is one more exceptions, in
|
||||
// nsStyleImageLayers::Layer::CalcDifference, we do not add
|
||||
// nsChangeHint_UpdateOverflow hint when image mask(not SVG mask) property
|
||||
// value changed, since replace image mask does not cause layout change.
|
||||
// So even if we apply a new mask image to this frame,
|
||||
// PreEffectsBBoxProperty might still left empty.
|
||||
|
||||
#ifdef DEBUG
|
||||
if (aCheckPropCache) {
|
||||
nsIFrame* firstFrame =
|
||||
nsLayoutUtils::FirstContinuationOrIBSplitSibling(aFrame);
|
||||
bool mightHaveNoneSVGMask =
|
||||
nsSVGEffects::GetEffectProperties(firstFrame).MightHaveNoneSVGMask();
|
||||
// Having PreTransformOverflowAreasProperty cached means
|
||||
// GetVisualOverflowRect() will return post-effect rect, which is not what
|
||||
// we want. This function intentional reports pre-effect rect. But it does
|
||||
// not matter if there is no SVG effect on this frame, since no effect
|
||||
// means post-effect rect matches pre-effect rect.
|
||||
if (nsSVGIntegrationUtils::UsingEffectsForFrame(aFrame)) {
|
||||
nsOverflowAreas* preTransformOverflows =
|
||||
aFrame->Properties().Get(aFrame->PreTransformOverflowAreasProperty());
|
||||
|
||||
NS_ASSERTION(mightHaveNoneSVGMask ||
|
||||
aFrame->GetParent()->StyleContext()->GetPseudo() ==
|
||||
nsCSSAnonBoxes::mozAnonymousBlock,
|
||||
"How did we getting here, then?");
|
||||
MOZ_ASSERT(!preTransformOverflows,
|
||||
"GetVisualOverflowRect() won't return the pre-effects rect!");
|
||||
}
|
||||
|
||||
bool hasEffect = nsSVGIntegrationUtils::UsingEffectsForFrame(aFrame);
|
||||
nsOverflowAreas* preTransformOverflows =
|
||||
aFrame->Properties().Get(aFrame->PreTransformOverflowAreasProperty());
|
||||
// Having PreTransformOverflowAreasProperty means GetVisualOverflowRect()
|
||||
// will return post-effect rect, which is not what we want, this function
|
||||
// intentional reports pre-effect rect. But it does not matter if there is
|
||||
// no SVG effect on this frame, since no effect means post-effect rect
|
||||
// matches pre-effect rect.
|
||||
MOZ_ASSERT(!hasEffect || !preTransformOverflows,
|
||||
"GetVisualOverflowRect() won't return the pre-effects rect!");
|
||||
#endif
|
||||
return aFrame->GetVisualOverflowRect();
|
||||
}
|
||||
|
@ -153,7 +104,6 @@ private:
|
|||
nsIFrame* mCurrentFrame;
|
||||
const nsRect& mCurrentFrameOverflowArea;
|
||||
nsRect mResult;
|
||||
bool mCheckPreEffectsBBoxPropCache;
|
||||
};
|
||||
|
||||
/**
|
||||
|
@ -164,15 +114,13 @@ static nsRect
|
|||
GetPreEffectsVisualOverflowUnion(nsIFrame* aFirstContinuation,
|
||||
nsIFrame* aCurrentFrame,
|
||||
const nsRect& aCurrentFramePreEffectsOverflow,
|
||||
const nsPoint& aFirstContinuationToUserSpace,
|
||||
bool aCheckPreEffectsBBoxPropCache)
|
||||
const nsPoint& aFirstContinuationToUserSpace)
|
||||
{
|
||||
NS_ASSERTION(!aFirstContinuation->GetPrevContinuation(),
|
||||
"Need first continuation here");
|
||||
PreEffectsVisualOverflowCollector collector(aFirstContinuation,
|
||||
aCurrentFrame,
|
||||
aCurrentFramePreEffectsOverflow,
|
||||
aCheckPreEffectsBBoxPropCache);
|
||||
aCurrentFramePreEffectsOverflow);
|
||||
// Compute union of all overflow areas relative to aFirstContinuation:
|
||||
nsLayoutUtils::GetAllInFlowBoxes(aFirstContinuation, &collector);
|
||||
// Return the result in user space:
|
||||
|
@ -250,8 +198,7 @@ nsSVGIntegrationUtils::GetSVGBBoxForNonSVGFrame(nsIFrame* aNonSVGFrame)
|
|||
nsLayoutUtils::FirstContinuationOrIBSplitSibling(aNonSVGFrame);
|
||||
// 'r' is in "user space":
|
||||
nsRect r = GetPreEffectsVisualOverflowUnion(firstFrame, nullptr, nsRect(),
|
||||
GetOffsetToBoundingBox(firstFrame),
|
||||
true);
|
||||
GetOffsetToBoundingBox(firstFrame));
|
||||
return nsLayoutUtils::RectToGfxRect(r,
|
||||
aNonSVGFrame->PresContext()->AppUnitsPerCSSPixel());
|
||||
}
|
||||
|
@ -313,11 +260,7 @@ nsRect
|
|||
nsLayoutUtils::RectToGfxRect(
|
||||
GetPreEffectsVisualOverflowUnion(firstFrame, aFrame,
|
||||
aPreEffectsOverflowRect,
|
||||
firstFrameToBoundingBox,
|
||||
false /* See the beginning of the
|
||||
comment above this function to
|
||||
know why we skip this
|
||||
checking. */),
|
||||
firstFrameToBoundingBox),
|
||||
aFrame->PresContext()->AppUnitsPerCSSPixel());
|
||||
overrideBBox.RoundOut();
|
||||
|
||||
|
|
|
@ -471,10 +471,6 @@ public class FxAccountStatusFragment
|
|||
accountProfileInformationReceiver = new FxAccountProfileInformationReceiver();
|
||||
LocalBroadcastManager.getInstance(getActivity()).registerReceiver(accountProfileInformationReceiver, intentFilter);
|
||||
|
||||
// profilePreference is set during onCreate, so it's definitely not null here.
|
||||
final float cornerRadius = getResources().getDimension(R.dimen.fxaccount_profile_image_width) / 2;
|
||||
profileAvatarTarget = new PicassoPreferenceIconTarget(getResources(), profilePreference, cornerRadius);
|
||||
|
||||
refresh();
|
||||
}
|
||||
|
||||
|
@ -518,6 +514,10 @@ public class FxAccountStatusFragment
|
|||
throw new IllegalArgumentException("fxAccount must not be null");
|
||||
}
|
||||
|
||||
// profilePreference is set during onCreate, so it's definitely not null here.
|
||||
final float cornerRadius = getResources().getDimension(R.dimen.fxaccount_profile_image_width) / 2;
|
||||
profileAvatarTarget = new PicassoPreferenceIconTarget(getResources(), profilePreference, cornerRadius);
|
||||
|
||||
updateProfileInformation();
|
||||
updateAuthServerPreference();
|
||||
updateSyncServerPreference();
|
||||
|
|
|
@ -1283,6 +1283,7 @@ GatherTelemetryForSingleSCT(const ct::VerifiedSCT& verifiedSct)
|
|||
|
||||
void
|
||||
GatherCertificateTransparencyTelemetry(const UniqueCERTCertList& certList,
|
||||
bool isEV,
|
||||
const CertificateTransparencyInfo& info)
|
||||
{
|
||||
if (!info.enabled) {
|
||||
|
@ -1306,6 +1307,59 @@ GatherCertificateTransparencyTelemetry(const UniqueCERTCertList& certList,
|
|||
// Note that sctsCount can also be 0 in case we've received SCT binary data,
|
||||
// but it failed to parse (e.g. due to unsupported CT protocol version).
|
||||
Telemetry::Accumulate(Telemetry::SSL_SCTS_PER_CONNECTION, sctsCount);
|
||||
|
||||
// Report CT Policy compliance of EV certificates.
|
||||
if (isEV) {
|
||||
uint32_t evCompliance = 0;
|
||||
switch (info.policyCompliance) {
|
||||
case ct::CTPolicyCompliance::Compliant:
|
||||
evCompliance = 1;
|
||||
break;
|
||||
case ct::CTPolicyCompliance::NotEnoughScts:
|
||||
evCompliance = 2;
|
||||
break;
|
||||
case ct::CTPolicyCompliance::NotDiverseScts:
|
||||
evCompliance = 3;
|
||||
break;
|
||||
case ct::CTPolicyCompliance::Unknown:
|
||||
default:
|
||||
MOZ_ASSERT_UNREACHABLE("Unexpected CTPolicyCompliance type");
|
||||
}
|
||||
Telemetry::Accumulate(Telemetry::SSL_CT_POLICY_COMPLIANCE_OF_EV_CERTS,
|
||||
evCompliance);
|
||||
}
|
||||
|
||||
// Get the root cert.
|
||||
CERTCertListNode* rootNode = CERT_LIST_TAIL(certList);
|
||||
MOZ_ASSERT(rootNode);
|
||||
if (!rootNode) {
|
||||
return;
|
||||
}
|
||||
MOZ_ASSERT(!CERT_LIST_END(rootNode, certList));
|
||||
if (CERT_LIST_END(rootNode, certList)) {
|
||||
return;
|
||||
}
|
||||
CERTCertificate* rootCert = rootNode->cert;
|
||||
MOZ_ASSERT(rootCert);
|
||||
if (!rootCert) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Report CT Policy compliance by CA.
|
||||
switch (info.policyCompliance) {
|
||||
case ct::CTPolicyCompliance::Compliant:
|
||||
AccumulateTelemetryForRootCA(
|
||||
Telemetry::SSL_CT_POLICY_COMPLIANT_CONNECTIONS_BY_CA, rootCert);
|
||||
break;
|
||||
case ct::CTPolicyCompliance::NotEnoughScts:
|
||||
case ct::CTPolicyCompliance::NotDiverseScts:
|
||||
AccumulateTelemetryForRootCA(
|
||||
Telemetry::SSL_CT_POLICY_NON_COMPLIANT_CONNECTIONS_BY_CA, rootCert);
|
||||
break;
|
||||
case ct::CTPolicyCompliance::Unknown:
|
||||
default:
|
||||
MOZ_ASSERT_UNREACHABLE("Unexpected CTPolicyCompliance type");
|
||||
}
|
||||
}
|
||||
|
||||
// Note: Takes ownership of |peerCertChain| if SECSuccess is not returned.
|
||||
|
@ -1390,6 +1444,7 @@ AuthCertificate(CertVerifier& certVerifier,
|
|||
SECSuccess);
|
||||
GatherSuccessfulValidationTelemetry(certList);
|
||||
GatherCertificateTransparencyTelemetry(certList,
|
||||
/*isEV*/ evOidPolicy != SEC_OID_UNKNOWN,
|
||||
certificateTransparencyInfo);
|
||||
|
||||
// The connection may get terminated, for example, if the server requires
|
||||
|
|
|
@ -1157,4 +1157,4 @@ static const TransportSecurityPreload kPublicKeyPinningPreloadList[] = {
|
|||
|
||||
static const int32_t kUnknownId = -1;
|
||||
|
||||
static const PRTime kPreloadPKPinsExpirationTime = INT64_C(1496157927859000);
|
||||
static const PRTime kPreloadPKPinsExpirationTime = INT64_C(1496246555187000);
|
||||
|
|
|
@ -16,7 +16,7 @@
|
|||
123plons.nl: [Exception... "Component returned failure code: 0x80004005 (NS_ERROR_FAILURE) [nsISiteSecurityService.processHeader]" nsresult: "0x80004005 (NS_ERROR_FAILURE)" location: "JS frame :: /builds/slave/m-cen-l64-periodicupdate-00000/getHSTSPreloadList.js :: processStsHeader :: line 121" data: no]
|
||||
123test.de: did not receive HSTS header
|
||||
126ium.moe: could not connect to host
|
||||
127011-networks.ch: could not connect to host
|
||||
127011-networks.ch: did not receive HSTS header
|
||||
12vpnchina.com: could not connect to host
|
||||
16packets.com: could not connect to host
|
||||
1a-jva.de: did not receive HSTS header
|
||||
|
@ -157,7 +157,7 @@ ajmahal.com: could not connect to host
|
|||
akclinics.org: did not receive HSTS header
|
||||
akombakom.net: did not receive HSTS header
|
||||
akselimedia.fi: did not receive HSTS header
|
||||
akutun.cl: did not receive HSTS header
|
||||
akutun.cl: could not connect to host
|
||||
al-shami.net: could not connect to host
|
||||
aladdin.ie: did not receive HSTS header
|
||||
alainwolf.net: could not connect to host
|
||||
|
@ -197,6 +197,7 @@ altmv.com: max-age too low: 7776000
|
|||
amaforums.org: could not connect to host
|
||||
amandaonishi.com: could not connect to host
|
||||
amavis.org: did not receive HSTS header
|
||||
amazingfloridagulfhomes.com: could not connect to host
|
||||
ameho.me: [Exception... "Component returned failure code: 0x80004005 (NS_ERROR_FAILURE) [nsISiteSecurityService.processHeader]" nsresult: "0x80004005 (NS_ERROR_FAILURE)" location: "JS frame :: /builds/slave/m-cen-l64-periodicupdate-00000/getHSTSPreloadList.js :: processStsHeader :: line 121" data: no]
|
||||
american-truck-simulator.de: could not connect to host
|
||||
american-truck-simulator.net: could not connect to host
|
||||
|
@ -263,7 +264,7 @@ apmg-certified.com: did not receive HSTS header
|
|||
apmg-cyber.com: did not receive HSTS header
|
||||
apnakliyat.com: did not receive HSTS header
|
||||
aponkralsunucu.com: could not connect to host
|
||||
app.lookout.com: could not connect to host
|
||||
app.lookout.com: did not receive HSTS header
|
||||
app.manilla.com: could not connect to host
|
||||
appart.ninja: could not connect to host
|
||||
appengine.google.com: did not receive HSTS header (error ignored - included regardless)
|
||||
|
@ -279,6 +280,7 @@ appson.co.uk: did not receive HSTS header
|
|||
arabdigitalexpression.org: did not receive HSTS header
|
||||
aradulconteaza.ro: could not connect to host
|
||||
aran.me.uk: could not connect to host
|
||||
arbeitskreis-asyl-eningen.de: [Exception... "Component returned failure code: 0x80004005 (NS_ERROR_FAILURE) [nsISiteSecurityService.processHeader]" nsresult: "0x80004005 (NS_ERROR_FAILURE)" location: "JS frame :: /builds/slave/m-cen-l64-periodicupdate-00000/getHSTSPreloadList.js :: processStsHeader :: line 121" data: no]
|
||||
arboineuropa.nl: did not receive HSTS header
|
||||
arbu.eu: could not connect to host
|
||||
arlen.se: could not connect to host
|
||||
|
@ -325,6 +327,7 @@ athaliasoft.com: did not receive HSTS header
|
|||
athenelive.com: could not connect to host
|
||||
athul.xyz: did not receive HSTS header
|
||||
atlex.nl: did not receive HSTS header
|
||||
atlseccon.com: did not receive HSTS header
|
||||
atomik.pro: could not connect to host
|
||||
atop.io: could not connect to host
|
||||
attimidesigns.com: did not receive HSTS header
|
||||
|
@ -333,6 +336,7 @@ aubiosales.com: did not receive HSTS header
|
|||
aucubin.moe: could not connect to host
|
||||
audiovisualdevices.com.au: did not receive HSTS header
|
||||
aufmerksamkeitsstudie.com: could not connect to host
|
||||
augiero.it: could not connect to host
|
||||
aujapan.ru: could not connect to host
|
||||
aurainfosec.com: did not receive HSTS header
|
||||
aurainfosec.com.au: could not connect to host
|
||||
|
@ -347,6 +351,7 @@ authentication.io: could not connect to host
|
|||
authoritynutrition.com: did not receive HSTS header
|
||||
auto-serwis.zgorzelec.pl: did not receive HSTS header
|
||||
auto4trade.nl: could not connect to host
|
||||
autodeploy.it: could not connect to host
|
||||
autoepc.ro: did not receive HSTS header
|
||||
autojuhos.sk: could not connect to host
|
||||
autokovrik-diskont.ru: did not receive HSTS header
|
||||
|
@ -372,6 +377,7 @@ azuxul.fr: could not connect to host
|
|||
b303.me: did not receive HSTS header
|
||||
b3orion.com: max-age too low: 0
|
||||
b64.club: could not connect to host
|
||||
babelfisch.eu: could not connect to host
|
||||
baby-click.de: did not receive HSTS header
|
||||
babybic.hu: did not receive HSTS header
|
||||
babyhouse.xyz: could not connect to host
|
||||
|
@ -403,6 +409,7 @@ baumstark.ca: could not connect to host
|
|||
baysse.eu: could not connect to host
|
||||
bazarstupava.sk: could not connect to host
|
||||
bcbsmagentprofile.com: could not connect to host
|
||||
bcchack.com: could not connect to host
|
||||
bccx.com: could not connect to host
|
||||
bckp.de: did not receive HSTS header
|
||||
bcm.com.au: max-age too low: 0
|
||||
|
@ -497,6 +504,7 @@ bizcms.com: did not receive HSTS header
|
|||
bizon.sk: did not receive HSTS header
|
||||
black-armada.com.pl: could not connect to host
|
||||
black-armada.pl: could not connect to host
|
||||
black-octopus.ru: could not connect to host
|
||||
blackburn.link: could not connect to host
|
||||
blacklane.com: did not receive HSTS header
|
||||
blackly.uk: max-age too low: 0
|
||||
|
@ -540,7 +548,7 @@ bonigo.de: [Exception... "Component returned failure code: 0x80004005 (NS_ERROR_
|
|||
bonitabrazilian.co.nz: did not receive HSTS header
|
||||
bookcelerator.com: did not receive HSTS header
|
||||
booked.holiday: could not connect to host
|
||||
bookourdjs.com: [Exception... "Component returned failure code: 0x80004005 (NS_ERROR_FAILURE) [nsISiteSecurityService.processHeader]" nsresult: "0x80004005 (NS_ERROR_FAILURE)" location: "JS frame :: /builds/slave/m-cen-l64-periodicupdate-00000/getHSTSPreloadList.js :: processStsHeader :: line 121" data: no]
|
||||
bookourdjs.com: could not connect to host
|
||||
boomerang.com: could not connect to host
|
||||
boosterlearnpro.com: did not receive HSTS header
|
||||
bootjp.me: did not receive HSTS header
|
||||
|
@ -554,7 +562,6 @@ boxcryptor.com: did not receive HSTS header
|
|||
br3in.nl: [Exception... "Component returned failure code: 0x80004005 (NS_ERROR_FAILURE) [nsISiteSecurityService.processHeader]" nsresult: "0x80004005 (NS_ERROR_FAILURE)" location: "JS frame :: /builds/slave/m-cen-l64-periodicupdate-00000/getHSTSPreloadList.js :: processStsHeader :: line 121" data: no]
|
||||
braineet.com: did not receive HSTS header
|
||||
brainfork.ml: could not connect to host
|
||||
brainster.co: could not connect to host
|
||||
braintreegateway.com: did not receive HSTS header
|
||||
braintreepayments.com: did not receive HSTS header
|
||||
brainvation.de: did not receive HSTS header
|
||||
|
@ -609,6 +616,7 @@ buttercoin.com: could not connect to host
|
|||
butterfieldstraining.com: did not receive HSTS header
|
||||
buybaby.eu: did not receive HSTS header
|
||||
buyfox.de: did not receive HSTS header
|
||||
buzzconcert.com: could not connect to host
|
||||
bws16.de: did not receive HSTS header
|
||||
by4cqb.cn: could not connect to host
|
||||
bypassed.press: could not connect to host
|
||||
|
@ -634,6 +642,7 @@ cake.care: could not connect to host
|
|||
calendarr.com: did not receive HSTS header
|
||||
calgaryconstructionjobs.com: did not receive HSTS header
|
||||
calix.com: max-age too low: 0
|
||||
call.me: did not receive HSTS header
|
||||
calltrackingreports.com: could not connect to host
|
||||
calvin.me: max-age too low: 2592000
|
||||
calvinallen.net: did not receive HSTS header
|
||||
|
@ -725,6 +734,7 @@ cheesetart.my: could not connect to host
|
|||
cheetah85.de: could not connect to host
|
||||
chejianer.cn: did not receive HSTS header
|
||||
chensir.net: could not connect to host
|
||||
chepaofen.com: could not connect to host
|
||||
cherysunzhang.com: max-age too low: 7776000
|
||||
chihiro.xyz: could not connect to host
|
||||
chijiokeindustries.co.uk: could not connect to host
|
||||
|
@ -738,7 +748,6 @@ chopperforums.com: did not receive HSTS header
|
|||
chotu.net: could not connect to host
|
||||
chris-web.info: could not connect to host
|
||||
chrisandsarahinasia.com: did not receive HSTS header
|
||||
chrisbrown.id.au: could not connect to host
|
||||
chrisfaber.com: could not connect to host
|
||||
chriskyrouac.com: could not connect to host
|
||||
christiaandruif.nl: could not connect to host
|
||||
|
@ -778,6 +787,7 @@ clemovementlaw.com: could not connect to host
|
|||
clerkendweller.uk: could not connect to host
|
||||
clickandgo.com: did not receive HSTS header
|
||||
clickandshoot.nl: did not receive HSTS header
|
||||
clickgram.biz: could not connect to host
|
||||
clientsecure.me: could not connect to host
|
||||
clint.id.au: max-age too low: 0
|
||||
clintonbloodworth.com: could not connect to host
|
||||
|
@ -791,6 +801,7 @@ cloudcy.net: could not connect to host
|
|||
clouddesktop.co.nz: could not connect to host
|
||||
cloudey.net: did not receive HSTS header
|
||||
cloudflare.com: did not receive HSTS header
|
||||
cloudily.com: could not connect to host
|
||||
cloudimag.es: could not connect to host
|
||||
cloudlink.club: could not connect to host
|
||||
cloudns.com.au: could not connect to host
|
||||
|
@ -813,8 +824,6 @@ cmsbattle.com: could not connect to host
|
|||
cmscafe.ru: did not receive HSTS header
|
||||
cn.search.yahoo.com: did not receive HSTS header
|
||||
cni-certing.it: max-age too low: 0
|
||||
cnwage.com: could not connect to host
|
||||
cnwarn.com: could not connect to host
|
||||
co50.com: did not receive HSTS header
|
||||
cocaine-import.agency: could not connect to host
|
||||
cocktailfuture.fr: could not connect to host
|
||||
|
@ -828,6 +837,7 @@ codeforce.io: could not connect to host
|
|||
codelayer.ca: could not connect to host
|
||||
codemonkeyrawks.net: did not receive HSTS header
|
||||
codepoet.de: could not connect to host
|
||||
codepult.com: could not connect to host
|
||||
codepx.com: did not receive HSTS header
|
||||
codewiththepros.org: could not connect to host
|
||||
codiva.io: max-age too low: 2592000
|
||||
|
@ -866,6 +876,7 @@ consciousandglamorous.com: could not connect to host
|
|||
console.python.org: did not receive HSTS header
|
||||
constructionjobs.com: did not receive HSTS header
|
||||
contactbig.com: did not receive HSTS header
|
||||
containerstatistics.com: could not connect to host
|
||||
contarkos.xyz: could not connect to host
|
||||
content-api-dev.azurewebsites.net: could not connect to host
|
||||
continuumgaming.com: could not connect to host
|
||||
|
@ -878,7 +889,8 @@ cordial-restaurant.com: did not receive HSTS header
|
|||
core.mx: could not connect to host
|
||||
core4system.de: could not connect to host
|
||||
corenetworking.de: could not connect to host
|
||||
corgicloud.com: could not connect to host
|
||||
corgicloud.com: did not receive HSTS header
|
||||
cormactagging.ie: could not connect to host
|
||||
cormilu.com.br: did not receive HSTS header
|
||||
correctpaardbatterijnietje.nl: did not receive HSTS header
|
||||
corruption-mc.net: could not connect to host
|
||||
|
@ -888,7 +900,6 @@ count.sh: could not connect to host
|
|||
couragewhispers.ca: did not receive HSTS header
|
||||
coursdeprogrammation.com: could not connect to host
|
||||
coursella.com: did not receive HSTS header
|
||||
cousincouples.com: did not receive HSTS header
|
||||
covenantbank.net: could not connect to host
|
||||
coverduck.ru: could not connect to host
|
||||
cpuvinf.eu.org: could not connect to host
|
||||
|
@ -937,8 +948,10 @@ csgodicegame.com: did not receive HSTS header
|
|||
csgoelemental.com: could not connect to host
|
||||
csgokings.eu: could not connect to host
|
||||
csohack.tk: could not connect to host
|
||||
csokolade.hu: could not connect to host
|
||||
cspbuilder.info: could not connect to host
|
||||
cspvalidator.org: did not receive HSTS header
|
||||
csru.net: could not connect to host
|
||||
csvape.com: did not receive HSTS header
|
||||
ct-status.org: could not connect to host
|
||||
ct.search.yahoo.com: did not receive HSTS header
|
||||
|
@ -1081,6 +1094,7 @@ diamante.ro: could not connect to host
|
|||
diarbag.us: did not receive HSTS header
|
||||
diasp.cz: [Exception... "Component returned failure code: 0x80004005 (NS_ERROR_FAILURE) [nsISiteSecurityService.processHeader]" nsresult: "0x80004005 (NS_ERROR_FAILURE)" location: "JS frame :: /builds/slave/m-cen-l64-periodicupdate-00000/getHSTSPreloadList.js :: processStsHeader :: line 121" data: no]
|
||||
dick.red: could not connect to host
|
||||
die-partei-reutlingen.de: [Exception... "Component returned failure code: 0x80004005 (NS_ERROR_FAILURE) [nsISiteSecurityService.processHeader]" nsresult: "0x80004005 (NS_ERROR_FAILURE)" location: "JS frame :: /builds/slave/m-cen-l64-periodicupdate-00000/getHSTSPreloadList.js :: processStsHeader :: line 121" data: no]
|
||||
diedrich.co: did not receive HSTS header
|
||||
digidroom.be: did not receive HSTS header
|
||||
digioccumss.ddns.net: could not connect to host
|
||||
|
@ -1161,26 +1175,30 @@ drtroyhendrickson.com: could not connect to host
|
|||
drumbandesperanto.nl: could not connect to host
|
||||
ds-christiansen.de: did not receive HSTS header
|
||||
dshiv.io: could not connect to host
|
||||
dubrovskiy.net: could not connect to host
|
||||
dubrovskiy.pro: could not connect to host
|
||||
duesee.org: could not connect to host
|
||||
dullsir.com: did not receive HSTS header
|
||||
duria.de: max-age too low: 3600
|
||||
dustri.org: did not receive HSTS header
|
||||
dutchessuganda.com: did not receive HSTS header
|
||||
dutchrank.com: could not connect to host
|
||||
dwhd.org: [Exception... "Component returned failure code: 0x80004005 (NS_ERROR_FAILURE) [nsISiteSecurityService.processHeader]" nsresult: "0x80004005 (NS_ERROR_FAILURE)" location: "JS frame :: /builds/slave/m-cen-l64-periodicupdate-00000/getHSTSPreloadList.js :: processStsHeader :: line 121" data: no]
|
||||
dworzak.ch: could not connect to host
|
||||
dycontrol.de: could not connect to host
|
||||
dylanscott.com.au: did not receive HSTS header
|
||||
dymersion.com: did not receive HSTS header
|
||||
dynamic-innovations.net: could not connect to host
|
||||
dzimejl.sk: did not receive HSTS header
|
||||
dzlibs.io: could not connect to host
|
||||
dzndk.net: could not connect to host
|
||||
dzndk.org: could not connect to host
|
||||
e-aut.net: did not receive HSTS header
|
||||
e-deca2.org: did not receive HSTS header
|
||||
e-sa.com: did not receive HSTS header
|
||||
e3amn2l.com: could not connect to host
|
||||
earlybirdsnacks.com: could not connect to host
|
||||
earthrise16.com: could not connect to host
|
||||
easez.net: did not receive HSTS header
|
||||
eason-yang.com: could not connect to host
|
||||
easychiller.org: could not connect to host
|
||||
easyhaul.com: did not receive HSTS header
|
||||
eatlowcarb.de: did not receive HSTS header
|
||||
|
@ -1260,6 +1278,7 @@ encode.space: did not receive HSTS header
|
|||
encoder.pw: could not connect to host
|
||||
encontrebarato.com.br: did not receive HSTS header
|
||||
encrypted.google.com: did not receive HSTS header (error ignored - included regardless)
|
||||
encryptedaudience.com: could not connect to host
|
||||
end.pp.ua: could not connect to host
|
||||
endlessdark.net: max-age too low: 600
|
||||
endlessdiy.ca: could not connect to host
|
||||
|
@ -1293,6 +1312,7 @@ equilibre-yoga-jennifer-will.com: could not connect to host
|
|||
erawanarifnugroho.com: did not receive HSTS header
|
||||
eressea.xyz: could not connect to host
|
||||
eridanus.uk: could not connect to host
|
||||
erikhubers.nl: could not connect to host
|
||||
ernaehrungsberatung-rapperswil.ch: [Exception... "Component returned failure code: 0x80004005 (NS_ERROR_FAILURE) [nsISiteSecurityService.processHeader]" nsresult: "0x80004005 (NS_ERROR_FAILURE)" location: "JS frame :: /builds/slave/m-cen-l64-periodicupdate-00000/getHSTSPreloadList.js :: processStsHeader :: line 121" data: no]
|
||||
ernaehrungsberatung-zurich.ch: could not connect to host
|
||||
ernesto.at: could not connect to host
|
||||
|
@ -1341,6 +1361,7 @@ exfiles.cz: did not receive HSTS header
|
|||
exgravitus.com: could not connect to host
|
||||
exitus.jp: max-age too low: 0
|
||||
exno.co: could not connect to host
|
||||
expatads.com: could not connect to host
|
||||
expertmile.com: did not receive HSTS header
|
||||
expoundite.net: did not receive HSTS header
|
||||
expressfinance.co.za: did not receive HSTS header
|
||||
|
@ -1384,8 +1405,6 @@ fatgeekflix.net: could not connect to host
|
|||
fatherhood.gov: did not receive HSTS header
|
||||
fatlossguide.xyz: could not connect to host
|
||||
fatox.de: could not connect to host
|
||||
fatzebra.com.au: could not connect to host
|
||||
fawkex.me: could not connect to host
|
||||
fayolle.info: [Exception... "Component returned failure code: 0x80004005 (NS_ERROR_FAILURE) [nsISiteSecurityService.processHeader]" nsresult: "0x80004005 (NS_ERROR_FAILURE)" location: "JS frame :: /builds/slave/m-cen-l64-periodicupdate-00000/getHSTSPreloadList.js :: processStsHeader :: line 121" data: no]
|
||||
fbox.li: could not connect to host
|
||||
fdj.im: could not connect to host
|
||||
|
@ -1406,13 +1425,14 @@ fexmen.com: could not connect to host
|
|||
ffmradio.de: did not receive HSTS header
|
||||
fhdhelp.de: could not connect to host
|
||||
fhdhilft.de: could not connect to host
|
||||
fierman.net: [Exception... "Component returned failure code: 0x80004005 (NS_ERROR_FAILURE) [nsISiteSecurityService.processHeader]" nsresult: "0x80004005 (NS_ERROR_FAILURE)" location: "JS frame :: /builds/slave/m-cen-l64-periodicupdate-00000/getHSTSPreloadList.js :: processStsHeader :: line 121" data: no]
|
||||
fifieldtech.com: could not connect to host
|
||||
fiftyshadesofluca.ml: could not connect to host
|
||||
fig.co: did not receive HSTS header
|
||||
fightr.co: could not connect to host
|
||||
fikt.space: could not connect to host
|
||||
filmipop.com: max-age too low: 0
|
||||
finalgear.com: could not connect to host
|
||||
finalgear.com: did not receive HSTS header
|
||||
financieringsportaal.nl: did not receive HSTS header
|
||||
finanzkontor.net: could not connect to host
|
||||
findtutorsnearme.com: did not receive HSTS header
|
||||
|
@ -1452,6 +1472,7 @@ florianlillpopp.de: max-age too low: 10
|
|||
floridaescapes.co.uk: did not receive HSTS header
|
||||
flouartistique.ch: could not connect to host
|
||||
flow.pe: could not connect to host
|
||||
flow.su: could not connect to host
|
||||
flowersandclouds.com: could not connect to host
|
||||
flowlo.me: could not connect to host
|
||||
flushstudios.com: did not receive HSTS header
|
||||
|
@ -1465,6 +1486,7 @@ foodievenues.com: could not connect to host
|
|||
footballmapped.com: could not connect to host
|
||||
foraje-profesionale.ro: did not receive HSTS header
|
||||
forbook.net: could not connect to host
|
||||
fordbydesign.com: could not connect to host
|
||||
foreignexchangeresource.com: did not receive HSTS header
|
||||
foreveralone.io: could not connect to host
|
||||
forex-dan.com: did not receive HSTS header
|
||||
|
@ -1520,7 +1542,6 @@ ftctele.com: did not receive HSTS header
|
|||
fuckbilibili.com: did not receive HSTS header
|
||||
fuckgfw233.org: could not connect to host
|
||||
fukushima-web.com: did not receive HSTS header
|
||||
fumo.se: could not connect to host
|
||||
fundacionhijosdelsol.org: could not connect to host
|
||||
funkyweddingideas.com.au: could not connect to host
|
||||
funnyang.com: could not connect to host
|
||||
|
@ -1624,7 +1645,6 @@ gh16.com.ar: could not connect to host
|
|||
gheorghesarcov.ga: could not connect to host
|
||||
gheorghesarcov.tk: could not connect to host
|
||||
gietvloergarant.nl: did not receive HSTS header
|
||||
gifzilla.net: could not connect to host
|
||||
gigacloud.org: max-age too low: 0
|
||||
gilgaz.com: did not receive HSTS header
|
||||
gilly.berlin: did not receive HSTS header
|
||||
|
@ -1693,6 +1713,7 @@ gpsfix.cz: could not connect to host
|
|||
gpstuner.com: did not receive HSTS header
|
||||
gracesofgrief.com: max-age too low: 86400
|
||||
gradienthosting.co.uk: did not receive HSTS header
|
||||
graffen.dk: did not receive HSTS header
|
||||
grandmascookieblog.com: did not receive HSTS header
|
||||
grantedby.me: could not connect to host
|
||||
graph.no: did not receive HSTS header
|
||||
|
@ -1749,6 +1770,7 @@ gyboche.science: could not connect to host
|
|||
gycis.me: could not connect to host
|
||||
gypthecat.com: max-age too low: 604800
|
||||
gyz.io: could not connect to host
|
||||
gzitech.com: could not connect to host
|
||||
h2check.org: could not connect to host
|
||||
haarkliniek.com: did not receive HSTS header
|
||||
habanaavenue.com: did not receive HSTS header
|
||||
|
@ -1788,6 +1810,7 @@ hardfalcon.net: could not connect to host
|
|||
hardline.xyz: could not connect to host
|
||||
haribosupermix.com: could not connect to host
|
||||
harmonycosmetic.com: max-age too low: 300
|
||||
harrisonsand.com: could not connect to host
|
||||
harristony.com: could not connect to host
|
||||
hartmancpa.com: did not receive HSTS header
|
||||
harvestrenewal.org: did not receive HSTS header
|
||||
|
@ -1824,6 +1847,7 @@ helpmebuild.com: did not receive HSTS header
|
|||
hemdal.se: could not connect to host
|
||||
hencagon.com: could not connect to host
|
||||
henriknoerr.com: could not connect to host
|
||||
heritagedentistry.ca: could not connect to host
|
||||
hermes-net.de: could not connect to host
|
||||
herrenfahrt.com: did not receive HSTS header
|
||||
herzbotschaft.de: did not receive HSTS header
|
||||
|
@ -1834,6 +1858,7 @@ hicn.gq: could not connect to host
|
|||
hiddendepth.ie: max-age too low: 0
|
||||
hiddenmail.xyz: could not connect to host
|
||||
hiddenrefuge.eu.org: could not connect to host
|
||||
hideftv.deals: did not receive HSTS header
|
||||
highseer.com: did not receive HSTS header
|
||||
highsurf-miyazaki.com: did not receive HSTS header
|
||||
highvelocitydesign.com: could not connect to host
|
||||
|
@ -1888,12 +1913,14 @@ http418.xyz: could not connect to host
|
|||
httpstatuscode418.xyz: could not connect to host
|
||||
hu.search.yahoo.com: did not receive HSTS header
|
||||
huarongdao.com: max-age too low: 1
|
||||
huffduffer.com: could not connect to host
|
||||
hugocollignon.fr: could not connect to host
|
||||
hugosleep.com.au: did not receive HSTS header
|
||||
humblefinances.com: could not connect to host
|
||||
humeurs.net: could not connect to host
|
||||
humpteedumptee.in: did not receive HSTS header
|
||||
huntshomeinspections.com: [Exception... "Component returned failure code: 0x80004005 (NS_ERROR_FAILURE) [nsISiteSecurityService.processHeader]" nsresult: "0x80004005 (NS_ERROR_FAILURE)" location: "JS frame :: /builds/slave/m-cen-l64-periodicupdate-00000/getHSTSPreloadList.js :: processStsHeader :: line 121" data: no]
|
||||
hupp.se: could not connect to host
|
||||
hurricanelabs.com: did not receive HSTS header
|
||||
huskybutt.dog: could not connect to host
|
||||
hydra.ws: could not connect to host
|
||||
|
@ -1943,6 +1970,7 @@ ihrnationalrat.ch: could not connect to host
|
|||
ihsbsd.me: could not connect to host
|
||||
ihsbsd.tk: could not connect to host
|
||||
ihuanmeng.com: did not receive HSTS header
|
||||
ikkatsu-satei.jp: did not receive HSTS header
|
||||
ikujii.com: max-age too low: 0
|
||||
ikwilguidobellen.nl: did not receive HSTS header
|
||||
ilbuongiorno.it: did not receive HSTS header
|
||||
|
@ -1953,7 +1981,7 @@ ilona.graphics: max-age too low: 3600
|
|||
iluvscotland.co.uk: did not receive HSTS header
|
||||
imakepoems.net: could not connect to host
|
||||
ime.moe: could not connect to host
|
||||
imguoguo.com: could not connect to host
|
||||
imguoguo.com: did not receive HSTS header
|
||||
imim.pw: did not receive HSTS header
|
||||
immersionwealth.com: could not connect to host
|
||||
immoprotect.ca: did not receive HSTS header
|
||||
|
@ -1977,6 +2005,7 @@ incendiary-arts.com: could not connect to host
|
|||
inchomatic.com: did not receive HSTS header
|
||||
indoorskiassen.nl: did not receive HSTS header
|
||||
indust.me: did not receive HSTS header
|
||||
inexpensivecomputers.net: could not connect to host
|
||||
infcof.com: max-age too low: 0
|
||||
infilock.com: could not connect to host
|
||||
infinitude.xyz: could not connect to host
|
||||
|
@ -2046,7 +2075,7 @@ ishillaryclintoninprisonyet.com: could not connect to host
|
|||
isitamor.pm: could not connect to host
|
||||
iskaz.rs: did not receive HSTS header
|
||||
isogram.nl: could not connect to host
|
||||
israkurort.com: did not receive HSTS header
|
||||
israkurort.com: could not connect to host
|
||||
isslshop.com: could not connect to host
|
||||
istaspirtslietas.lv: did not receive HSTS header
|
||||
it-go.net: did not receive HSTS header
|
||||
|
@ -2101,10 +2130,10 @@ jardins-utopie.net: [Exception... "Component returned failure code: 0x80004005 (
|
|||
jaredeberle.org: did not receive HSTS header
|
||||
jaroslavtrsek.cz: did not receive HSTS header
|
||||
jartza.org: could not connect to host
|
||||
jasmineconseil.com: did not receive HSTS header
|
||||
jasmineconseil.com: could not connect to host
|
||||
jasonrobinson.me: [Exception... "Component returned failure code: 0x80004005 (NS_ERROR_FAILURE) [nsISiteSecurityService.processHeader]" nsresult: "0x80004005 (NS_ERROR_FAILURE)" location: "JS frame :: /builds/slave/m-cen-l64-periodicupdate-00000/getHSTSPreloadList.js :: processStsHeader :: line 121" data: no]
|
||||
jasonroe.me: did not receive HSTS header
|
||||
jasonsansone.com: [Exception... "Component returned failure code: 0x80004005 (NS_ERROR_FAILURE) [nsISiteSecurityService.processHeader]" nsresult: "0x80004005 (NS_ERROR_FAILURE)" location: "JS frame :: /builds/slave/m-cen-l64-periodicupdate-00000/getHSTSPreloadList.js :: processStsHeader :: line 121" data: no]
|
||||
jasonsansone.com: could not connect to host
|
||||
jastoria.pl: could not connect to host
|
||||
jayblock.com: did not receive HSTS header
|
||||
jayschulman.com: did not receive HSTS header
|
||||
|
@ -2124,7 +2153,7 @@ jeremye77.com: could not connect to host
|
|||
jesorsenville.com: did not receive HSTS header
|
||||
jessicabenedictus.nl: could not connect to host
|
||||
jesuisformidable.nl: could not connect to host
|
||||
jetaprices.com: could not connect to host
|
||||
jetaprices.com: max-age too low: 0
|
||||
jetsetcharge.com: could not connect to host
|
||||
jetsetpay.com: could not connect to host
|
||||
jettshome.org: could not connect to host
|
||||
|
@ -2162,6 +2191,7 @@ jonn.me: could not connect to host
|
|||
joostbovee.nl: did not receive HSTS header
|
||||
jordanhamilton.me: could not connect to host
|
||||
joretapo.fr: did not receive HSTS header
|
||||
jornadasciberdefensa2016.es: did not receive HSTS header
|
||||
josahrens.me: could not connect to host
|
||||
joshi.su: could not connect to host
|
||||
joshstroup.me: could not connect to host
|
||||
|
@ -2195,7 +2225,6 @@ jznet.org: max-age too low: 86400
|
|||
k-dev.de: could not connect to host
|
||||
ka-clan.com: could not connect to host
|
||||
kabuabc.com: did not receive HSTS header
|
||||
kabus.org: could not connect to host
|
||||
kadioglumakina.com.tr: did not receive HSTS header
|
||||
kaela.design: could not connect to host
|
||||
kahopoon.net: could not connect to host
|
||||
|
@ -2303,7 +2332,6 @@ krayx.com: could not connect to host
|
|||
kreavis.com: did not receive HSTS header
|
||||
kredite.sale: could not connect to host
|
||||
kriegt.es: could not connect to host
|
||||
kristikala.nl: could not connect to host
|
||||
krmela.com: could not connect to host
|
||||
kroetenfuchs.de: could not connect to host
|
||||
kropkait.pl: could not connect to host
|
||||
|
@ -2354,6 +2382,7 @@ langenbach.rocks: could not connect to host
|
|||
langhun.me: did not receive HSTS header
|
||||
laobox.fr: could not connect to host
|
||||
laozhu.me: did not receive HSTS header
|
||||
laquack.com: did not receive HSTS header
|
||||
laserfuchs.de: did not receive HSTS header
|
||||
lashstuff.com: did not receive HSTS header
|
||||
lask.in: did not receive HSTS header
|
||||
|
@ -2408,6 +2437,7 @@ lgrs.com.au: did not receive HSTS header
|
|||
lgts.se: could not connect to host
|
||||
li.search.yahoo.com: did not receive HSTS header
|
||||
liaillustr.at: did not receive HSTS header
|
||||
liam-w.com: did not receive HSTS header
|
||||
liamjack.fr: could not connect to host
|
||||
lianye.in: could not connect to host
|
||||
lianye1.cc: could not connect to host
|
||||
|
@ -2443,6 +2473,7 @@ limiteddata.co.uk: could not connect to host
|
|||
limpido.it: could not connect to host
|
||||
lincolnwayflorist.com: could not connect to host
|
||||
lindberg.io: did not receive HSTS header
|
||||
lingerie.com.br: could not connect to host
|
||||
lingotaxi.com: [Exception... "Component returned failure code: 0x80004005 (NS_ERROR_FAILURE) [nsISiteSecurityService.processHeader]" nsresult: "0x80004005 (NS_ERROR_FAILURE)" location: "JS frame :: /builds/slave/m-cen-l64-periodicupdate-00000/getHSTSPreloadList.js :: processStsHeader :: line 121" data: no]
|
||||
lingros-test.tk: could not connect to host
|
||||
linguaquote.com: did not receive HSTS header
|
||||
|
@ -2536,6 +2567,7 @@ maarten.nyc: did not receive HSTS header
|
|||
maartenvandekamp.nl: did not receive HSTS header
|
||||
mac-torrents.me: did not receive HSTS header
|
||||
macchaberrycream.com: could not connect to host
|
||||
macchedil.com: did not receive HSTS header
|
||||
macdj.tk: could not connect to host
|
||||
macgeneral.de: did not receive HSTS header
|
||||
machon.biz: could not connect to host
|
||||
|
@ -2548,7 +2580,6 @@ mafamane.com: could not connect to host
|
|||
maff.scot: did not receive HSTS header
|
||||
mafiareturns.com: max-age too low: 2592000
|
||||
magenx.com: did not receive HSTS header
|
||||
magicbroccoli.de: [Exception... "Component returned failure code: 0x80004005 (NS_ERROR_FAILURE) [nsISiteSecurityService.processHeader]" nsresult: "0x80004005 (NS_ERROR_FAILURE)" location: "JS frame :: /builds/slave/m-cen-l64-periodicupdate-00000/getHSTSPreloadList.js :: processStsHeader :: line 121" data: no]
|
||||
mahamed91.pw: could not connect to host
|
||||
mail-settings.google.com: did not receive HSTS header (error ignored - included regardless)
|
||||
mail.google.com: did not receive HSTS header (error ignored - included regardless)
|
||||
|
@ -2584,6 +2615,7 @@ mario.party: did not receive HSTS header
|
|||
markaconnor.com: could not connect to host
|
||||
markayapilandirma.com: could not connect to host
|
||||
market.android.com: did not receive HSTS header (error ignored - included regardless)
|
||||
markprof.ru: could not connect to host
|
||||
markrego.com: could not connect to host
|
||||
marktboten.de: did not receive HSTS header
|
||||
markus-dev.com: did not receive HSTS header
|
||||
|
@ -2608,6 +2640,7 @@ matsuz.com: could not connect to host
|
|||
mattberryman.com: did not receive HSTS header
|
||||
mattcoles.io: did not receive HSTS header
|
||||
mattfin.ch: could not connect to host
|
||||
matthewkenny.co.uk: could not connect to host
|
||||
matthewprenger.com: could not connect to host
|
||||
matthiassteen.be: max-age too low: 0
|
||||
mattressinsider.com: max-age too low: 3153600
|
||||
|
@ -2645,7 +2678,6 @@ medwayindia.com: could not connect to host
|
|||
meedoenzaanstad.nl: did not receive HSTS header
|
||||
meetings2.com: did not receive HSTS header
|
||||
meetscompany.jp: did not receive HSTS header
|
||||
megablogging.org: could not connect to host
|
||||
megakiste.de: could not connect to host
|
||||
megashur.se: did not receive HSTS header
|
||||
megaxchange.com: did not receive HSTS header
|
||||
|
@ -2681,7 +2713,7 @@ mfiles.pl: [Exception... "Component returned failure code: 0x80004005 (NS_ERROR_
|
|||
mh-bloemen.co.jp: could not connect to host
|
||||
mhdsyarif.com: did not receive HSTS header
|
||||
mhealthdemocamp.com: could not connect to host
|
||||
mhertel.com: could not connect to host
|
||||
mhertel.com: did not receive HSTS header
|
||||
mhict.nl: max-age too low: 0
|
||||
mhx.pw: could not connect to host
|
||||
mia.to: could not connect to host
|
||||
|
@ -2763,7 +2795,6 @@ moneytoday.com: max-age too low: 0
|
|||
monitman.com: could not connect to host
|
||||
montenero.pl: could not connect to host
|
||||
moon.lc: could not connect to host
|
||||
moonless.net: could not connect to host
|
||||
moov.is: could not connect to host
|
||||
moparisthebest.biz: could not connect to host
|
||||
moparisthebest.info: could not connect to host
|
||||
|
@ -2783,10 +2814,12 @@ motoryz.com: max-age too low: 300
|
|||
mottvd.com: could not connect to host
|
||||
moula.com.au: did not receive HSTS header
|
||||
mountainmusicpromotions.com: did not receive HSTS header
|
||||
movepin.com: did not receive HSTS header
|
||||
moviesabout.net: could not connect to host
|
||||
moy-gorod.od.ua: did not receive HSTS header
|
||||
moy.cat: did not receive HSTS header
|
||||
mp3juices.is: could not connect to host
|
||||
mpintaamalabanna.it: could not connect to host
|
||||
mqas.net: could not connect to host
|
||||
mrdani.net: could not connect to host
|
||||
mrettich.org: did not receive HSTS header
|
||||
|
@ -2908,6 +2941,7 @@ netloanusa.com: max-age too low: 0
|
|||
netmagik.com: did not receive HSTS header
|
||||
nettefoundation.com: could not connect to host
|
||||
netulo.com: could not connect to host
|
||||
networx-online.de: could not connect to host
|
||||
netzbit.de: could not connect to host
|
||||
netzpolitik.org: did not receive HSTS header
|
||||
netztest.at: did not receive HSTS header
|
||||
|
@ -2944,6 +2978,7 @@ nien.chat: could not connect to host
|
|||
nightwinds.tk: could not connect to host
|
||||
nightx.uk: could not connect to host
|
||||
niho.jp: [Exception... "Component returned failure code: 0x80004005 (NS_ERROR_FAILURE) [nsISiteSecurityService.processHeader]" nsresult: "0x80004005 (NS_ERROR_FAILURE)" location: "JS frame :: /builds/slave/m-cen-l64-periodicupdate-00000/getHSTSPreloadList.js :: processStsHeader :: line 121" data: no]
|
||||
niklas.pw: could not connect to host
|
||||
nikomo.fi: could not connect to host
|
||||
ninchisho-online.com: did not receive HSTS header
|
||||
ninhs.org: did not receive HSTS header
|
||||
|
@ -2957,6 +2992,7 @@ nmctest.net: could not connect to host
|
|||
nnya.cat: could not connect to host
|
||||
no17sifangjie.cc: could not connect to host
|
||||
nocallaghan.com: could not connect to host
|
||||
noclegi-online.pl: did not receive HSTS header
|
||||
noctinus.tk: could not connect to host
|
||||
nodebrewery.com: could not connect to host
|
||||
nodetemple.com: could not connect to host
|
||||
|
@ -3006,6 +3042,7 @@ nullpoint.at: did not receive HSTS header
|
|||
number.me: did not receive HSTS header
|
||||
numericacu.com: did not receive HSTS header
|
||||
numero-di-telefono.it: could not connect to host
|
||||
numista.com: did not receive HSTS header
|
||||
nuos.org: could not connect to host
|
||||
nurserybook.co: did not receive HSTS header
|
||||
nutleyeducationalfoundation.org: did not receive HSTS header
|
||||
|
@ -3017,6 +3054,7 @@ nwa.xyz: could not connect to host
|
|||
nwgh.org: max-age too low: 86400
|
||||
nwork.media: could not connect to host
|
||||
nyantec.com: did not receive HSTS header
|
||||
nys-hk.com: could not connect to host
|
||||
nysepho.pw: could not connect to host
|
||||
nystart.no: did not receive HSTS header
|
||||
nz.search.yahoo.com: max-age too low: 172800
|
||||
|
@ -3254,6 +3292,7 @@ piggott.me.uk: did not receive HSTS header
|
|||
pilgermaske.org: did not receive HSTS header
|
||||
piligrimname.com: could not connect to host
|
||||
pillowandpepper.com: did not receive HSTS header
|
||||
pincodeit.com: could not connect to host
|
||||
pippen.io: could not connect to host
|
||||
piratedb.com: could not connect to host
|
||||
piratedot.com: could not connect to host
|
||||
|
@ -3264,7 +3303,6 @@ pirati.cz: max-age too low: 604800
|
|||
pirlitu.com: did not receive HSTS header
|
||||
pisexy.me: did not receive HSTS header
|
||||
pisidia.de: could not connect to host
|
||||
pittaya.com: could not connect to host
|
||||
pittonpreschool.com: did not receive HSTS header
|
||||
pixel.google.com: did not receive HSTS header (error ignored - included regardless)
|
||||
pixelcode.com.au: could not connect to host
|
||||
|
@ -3345,12 +3383,14 @@ pro-zone.com: could not connect to host
|
|||
prodpad.com: did not receive HSTS header
|
||||
professionalboundaries.com: did not receive HSTS header
|
||||
profi-durchgangsmelder.de: did not receive HSTS header
|
||||
profpay.com: could not connect to host
|
||||
profundr.com: could not connect to host
|
||||
progblog.net: could not connect to host
|
||||
progg.no: could not connect to host
|
||||
progress-technologies.com: could not connect to host
|
||||
prohostonline.fi: could not connect to host
|
||||
projectdp.net: could not connect to host
|
||||
projectmercury.space: could not connect to host
|
||||
promecon-gmbh.de: did not receive HSTS header
|
||||
prontocleaners.co.uk: could not connect to host
|
||||
prontolight.com: did not receive HSTS header
|
||||
|
@ -3364,8 +3404,10 @@ proximato.com: could not connect to host
|
|||
proxybay.al: could not connect to host
|
||||
proxybay.club: could not connect to host
|
||||
proxybay.info: did not receive HSTS header
|
||||
proxybay.top: could not connect to host
|
||||
prxio.site: did not receive HSTS header
|
||||
prytkov.com: did not receive HSTS header
|
||||
psicologia.co.ve: could not connect to host
|
||||
psw.academy: did not receive HSTS header
|
||||
psw.consulting: did not receive HSTS header
|
||||
ptn.moscow: could not connect to host
|
||||
|
@ -3419,7 +3461,6 @@ raajheshkannaa.com: could not connect to host
|
|||
radicaleducation.net: could not connect to host
|
||||
rafaelcz.de: could not connect to host
|
||||
railgun.com.cn: could not connect to host
|
||||
railjob.cn: could not connect to host
|
||||
rainbowbarracuda.com: could not connect to host
|
||||
ramonj.nl: could not connect to host
|
||||
randomcage.com: did not receive HSTS header
|
||||
|
@ -3498,6 +3539,7 @@ respostas.com.br: did not receive HSTS header
|
|||
restchart.com: did not receive HSTS header
|
||||
retcor.net: could not connect to host
|
||||
retrotracks.net: max-age too low: 0
|
||||
reulitz.de: could not connect to host
|
||||
revealdata.com: did not receive HSTS header
|
||||
revello.org: did not receive HSTS header
|
||||
reverie.pw: could not connect to host
|
||||
|
@ -3518,7 +3560,6 @@ rideworks.com: did not receive HSTS header
|
|||
riesenweber.id.au: did not receive HSTS header
|
||||
right2.org: could not connect to host
|
||||
righttoknow.ie: did not receive HSTS header
|
||||
rigolitch.fr: did not receive HSTS header
|
||||
riiconnect24.net: could not connect to host
|
||||
rijndael.xyz: could not connect to host
|
||||
rika.me: could not connect to host
|
||||
|
@ -3540,6 +3581,7 @@ robteix.com: did not receive HSTS header
|
|||
robtex.net: did not receive HSTS header
|
||||
robtex.org: did not receive HSTS header
|
||||
rochman.id: could not connect to host
|
||||
rocketr.net: did not receive HSTS header
|
||||
rocksberg.net: could not connect to host
|
||||
rockstarloan.com: max-age too low: 0
|
||||
roddis.net: did not receive HSTS header
|
||||
|
@ -3548,6 +3590,7 @@ rodosto.com: did not receive HSTS header
|
|||
roeper.party: could not connect to host
|
||||
roesemann.email: could not connect to host
|
||||
roguelikecenter.fr: did not receive HSTS header
|
||||
rolandreed.cn: could not connect to host
|
||||
romans-place.me.uk: did not receive HSTS header
|
||||
romulusapp.com: could not connect to host
|
||||
ronvandordt.info: could not connect to host
|
||||
|
@ -3619,7 +3662,7 @@ sandrolittke.de: did not receive HSTS header
|
|||
sandviks.com: did not receive HSTS header
|
||||
sangwon.org: could not connect to host
|
||||
sansemea.com: did not receive HSTS header
|
||||
sansonehowell.com: [Exception... "Component returned failure code: 0x80004005 (NS_ERROR_FAILURE) [nsISiteSecurityService.processHeader]" nsresult: "0x80004005 (NS_ERROR_FAILURE)" location: "JS frame :: /builds/slave/m-cen-l64-periodicupdate-00000/getHSTSPreloadList.js :: processStsHeader :: line 121" data: no]
|
||||
sansonehowell.com: could not connect to host
|
||||
sarah-beckett-harpist.com: did not receive HSTS header
|
||||
sarahsweetlife.com: could not connect to host
|
||||
sarakas.com: could not connect to host
|
||||
|
@ -3810,11 +3853,11 @@ sitesten.com: did not receive HSTS header
|
|||
sitsy.ru: did not receive HSTS header
|
||||
sixtwentyten.com: did not receive HSTS header
|
||||
skhosting.eu: did not receive HSTS header
|
||||
skidstresser.com: could not connect to host
|
||||
skile.ru: could not connect to host
|
||||
skk.io: could not connect to host
|
||||
skoda-clever-lead.de: could not connect to host
|
||||
skoda-im-dialog.de: could not connect to host
|
||||
skotty.io: did not receive HSTS header
|
||||
skullhouse.nyc: did not receive HSTS header
|
||||
skyflix.me: could not connect to host
|
||||
skyoy.com: did not receive HSTS header
|
||||
|
@ -3883,7 +3926,7 @@ somethingnew.xyz: could not connect to host
|
|||
sonicrainboom.rocks: could not connect to host
|
||||
soobi.org: did not receive HSTS header
|
||||
soondy.com: did not receive HSTS header
|
||||
sotiran.com: did not receive HSTS header
|
||||
sotiran.com: [Exception... "Component returned failure code: 0x80004005 (NS_ERROR_FAILURE) [nsISiteSecurityService.processHeader]" nsresult: "0x80004005 (NS_ERROR_FAILURE)" location: "JS frame :: /builds/slave/m-cen-l64-periodicupdate-00000/getHSTSPreloadList.js :: processStsHeader :: line 121" data: no]
|
||||
sotor.de: did not receive HSTS header
|
||||
soulema.com: [Exception... "Component returned failure code: 0x80004005 (NS_ERROR_FAILURE) [nsISiteSecurityService.processHeader]" nsresult: "0x80004005 (NS_ERROR_FAILURE)" location: "JS frame :: /builds/slave/m-cen-l64-periodicupdate-00000/getHSTSPreloadList.js :: processStsHeader :: line 121" data: no]
|
||||
soulfulglamour.uk: could not connect to host
|
||||
|
@ -3896,6 +3939,7 @@ souyar.us: could not connect to host
|
|||
sovereignshare.com: could not connect to host
|
||||
sown.dyndns.org: could not connect to host
|
||||
spacehq.org: max-age too low: 0
|
||||
spaggel.nl: could not connect to host
|
||||
sparelib.com: max-age too low: 3650
|
||||
spark.team: could not connect to host
|
||||
sparkbase.cn: could not connect to host
|
||||
|
@ -3916,7 +3960,7 @@ sperohub.io: could not connect to host
|
|||
spherenix.org: could not connect to host
|
||||
spicydog.tk: could not connect to host
|
||||
spiegels.nl: could not connect to host
|
||||
spikeykc.me: could not connect to host
|
||||
spikeykc.me: did not receive HSTS header
|
||||
spillmaker.no: did not receive HSTS header
|
||||
spilsbury.io: could not connect to host
|
||||
spititout.it: could not connect to host
|
||||
|
@ -3974,6 +4018,8 @@ stewartremodelingadvantage.com: did not receive HSTS header
|
|||
stig.io: did not receive HSTS header
|
||||
stigroom.com: could not connect to host
|
||||
stillblackhat.id: could not connect to host
|
||||
stirlingpoon.com: did not receive HSTS header
|
||||
stirlingpoon.net: did not receive HSTS header
|
||||
stirlingpoon.xyz: could not connect to host
|
||||
stkbn.com: did not receive HSTS header
|
||||
stmbgr.com: could not connect to host
|
||||
|
@ -4005,6 +4051,7 @@ student.andover.edu: did not receive HSTS header
|
|||
studentresearcher.org: did not receive HSTS header
|
||||
studentskydenik.cz: could not connect to host
|
||||
studenttravel.cz: did not receive HSTS header
|
||||
studinf.xyz: did not receive HSTS header
|
||||
studiozelden.com: did not receive HSTS header
|
||||
studybay.com: did not receive HSTS header
|
||||
studydrive.net: did not receive HSTS header
|
||||
|
@ -4045,7 +4092,6 @@ suzukikenichi.com: did not receive HSTS header
|
|||
sv.search.yahoo.com: did not receive HSTS header
|
||||
svarovani.tk: could not connect to host
|
||||
svatba-frantovi.cz: did not receive HSTS header
|
||||
sweetll.me: could not connect to host
|
||||
sweetstreats.ca: could not connect to host
|
||||
swimbee.nl: did not receive HSTS header
|
||||
swimming.ca: did not receive HSTS header
|
||||
|
@ -4068,7 +4114,6 @@ syriatalk.org: could not connect to host
|
|||
sysadmin.xyz: did not receive HSTS header
|
||||
syso.name: could not connect to host
|
||||
szaszm.tk: max-age too low: 0
|
||||
t-shirts4less.nl: did not receive HSTS header
|
||||
t-tz.com: could not connect to host
|
||||
ta-65.com: could not connect to host
|
||||
ta65.com: could not connect to host
|
||||
|
@ -4078,7 +4123,6 @@ tadigitalstore.com: could not connect to host
|
|||
tafoma.com: did not receive HSTS header
|
||||
tageau.com: could not connect to host
|
||||
taglondon.org: did not receive HSTS header
|
||||
tahf.net: could not connect to host
|
||||
tails.com.ar: did not receive HSTS header
|
||||
talk.google.com: did not receive HSTS header (error ignored - included regardless)
|
||||
talktwincities.com: could not connect to host
|
||||
|
@ -4113,7 +4157,7 @@ team-teasers.com: could not connect to host
|
|||
teamsocial.co: did not receive HSTS header
|
||||
teamzeus.cz: could not connect to host
|
||||
tech55i.com: did not receive HSTS header
|
||||
techassist.io: did not receive HSTS header
|
||||
techassist.io: could not connect to host
|
||||
techelements.co: could not connect to host
|
||||
techhipster.net: could not connect to host
|
||||
techhub.ml: could not connect to host
|
||||
|
@ -4123,8 +4167,8 @@ techmatehq.com: could not connect to host
|
|||
technogroup.cz: did not receive HSTS header
|
||||
technosavvyport.com: did not receive HSTS header
|
||||
techpointed.com: could not connect to host
|
||||
techreview.link: could not connect to host
|
||||
tedb.us: could not connect to host
|
||||
teemo.gg: did not receive HSTS header
|
||||
tegelsensanitaironline.nl: did not receive HSTS header
|
||||
tekshrek.com: did not receive HSTS header
|
||||
telefonnummer.online: could not connect to host
|
||||
|
@ -4288,6 +4332,7 @@ tonburi.jp: [Exception... "Component returned failure code: 0x80004005 (NS_ERROR
|
|||
tonyfantjr.com: could not connect to host
|
||||
tonyw.xyz: could not connect to host
|
||||
toomanypillows.com: could not connect to host
|
||||
top-stage.net: could not connect to host
|
||||
topbargains.com.au: did not receive HSTS header
|
||||
topdeskdev.net: could not connect to host
|
||||
topmarine.se: could not connect to host
|
||||
|
@ -4446,7 +4491,6 @@ uzmandroid.top: could not connect to host
|
|||
v2.pw: did not receive HSTS header
|
||||
v4veedu.com: could not connect to host
|
||||
vaddder.com: could not connect to host
|
||||
valasi.eu: could not connect to host
|
||||
valethound.com: could not connect to host
|
||||
valis.sx: could not connect to host
|
||||
valkyrja.xyz: did not receive HSTS header
|
||||
|
@ -4514,6 +4558,7 @@ vm0.eu: did not receive HSTS header
|
|||
vmc.co.id: could not connect to host
|
||||
vmrdev.com: could not connect to host
|
||||
voceinveste.com: did not receive HSTS header
|
||||
vodpay.com: could not connect to host
|
||||
vodpay.net: could not connect to host
|
||||
vodpay.org: could not connect to host
|
||||
voicesuk.co.uk: did not receive HSTS header
|
||||
|
@ -4529,7 +4574,7 @@ vpl.me: did not receive HSTS header
|
|||
vpn-byen.dk: did not receive HSTS header
|
||||
vratny.space: could not connect to host
|
||||
vrobert.fr: could not connect to host
|
||||
vvl.me: could not connect to host
|
||||
vvl.me: did not receive HSTS header
|
||||
vxstream-sandbox.com: [Exception... "Component returned failure code: 0x80004005 (NS_ERROR_FAILURE) [nsISiteSecurityService.processHeader]" nsresult: "0x80004005 (NS_ERROR_FAILURE)" location: "JS frame :: /builds/slave/m-cen-l64-periodicupdate-00000/getHSTSPreloadList.js :: processStsHeader :: line 121" data: no]
|
||||
vyncke.org: max-age too low: 2678400
|
||||
vzk.io: could not connect to host
|
||||
|
@ -4588,7 +4633,7 @@ webtechgadgetry.com: did not receive HSTS header
|
|||
webtiles.co.uk: could not connect to host
|
||||
webwork.pw: could not connect to host
|
||||
weddingenvelopes.co.uk: did not receive HSTS header
|
||||
weicn.org: did not receive HSTS header
|
||||
weiyuz.com: could not connect to host
|
||||
weizenke.im: could not connect to host
|
||||
wellastore.ru: did not receive HSTS header
|
||||
wellsolveit.com: [Exception... "Component returned failure code: 0x80004005 (NS_ERROR_FAILURE) [nsISiteSecurityService.processHeader]" nsresult: "0x80004005 (NS_ERROR_FAILURE)" location: "JS frame :: /builds/slave/m-cen-l64-periodicupdate-00000/getHSTSPreloadList.js :: processStsHeader :: line 121" data: no]
|
||||
|
@ -4762,7 +4807,7 @@ xtream-hosting.eu: could not connect to host
|
|||
xtreamhosting.eu: could not connect to host
|
||||
xuri.me: max-age too low: 2592000
|
||||
xuwei.de: could not connect to host
|
||||
xuyh0120.win: could not connect to host
|
||||
xuyh0120.win: did not receive HSTS header
|
||||
xxbase.com: could not connect to host
|
||||
xyndrac.net: did not receive HSTS header
|
||||
y-o-w.com: did not receive HSTS header
|
||||
|
@ -4788,16 +4833,15 @@ yetcore.io: could not connect to host
|
|||
yhaupenthal.org: could not connect to host
|
||||
yingyj.com: could not connect to host
|
||||
yippie.nl: [Exception... "Component returned failure code: 0x80004005 (NS_ERROR_FAILURE) [nsISiteSecurityService.processHeader]" nsresult: "0x80004005 (NS_ERROR_FAILURE)" location: "JS frame :: /builds/slave/m-cen-l64-periodicupdate-00000/getHSTSPreloadList.js :: processStsHeader :: line 121" data: no]
|
||||
yizhu.com: could not connect to host
|
||||
yjsoft.me: did not receive HSTS header
|
||||
yjsw.sh.cn: could not connect to host
|
||||
ynode.co: did not receive HSTS header
|
||||
ynsn.nl: did not receive HSTS header
|
||||
yoga.is-an-engineer.com: could not connect to host
|
||||
yokeepo.com: max-age too low: 0
|
||||
yoloboatrentals.com: did not receive HSTS header
|
||||
yoloprod.fr: could not connect to host
|
||||
yoloseo.com: could not connect to host
|
||||
yombo.net: could not connect to host
|
||||
youcontrol.ru: could not connect to host
|
||||
youngandunited.nl: did not receive HSTS header
|
||||
yourbapp.ch: could not connect to host
|
||||
|
@ -4845,6 +4889,7 @@ zeytin.pro: could not connect to host
|
|||
zh.search.yahoo.com: did not receive HSTS header
|
||||
zhaojin97.cn: did not receive HSTS header
|
||||
zhendingresources.com: could not connect to host
|
||||
zinenapse.info: could not connect to host
|
||||
zirtue.io: could not connect to host
|
||||
ziyuanabc.xyz: could not connect to host
|
||||
zkillboard.com: did not receive HSTS header
|
||||
|
@ -4866,4 +4911,3 @@ zvncloud.com: did not receive HSTS header
|
|||
zwollemagazine.nl: did not receive HSTS header
|
||||
zwy.me: did not receive HSTS header
|
||||
zyf.pw: could not connect to host
|
||||
zymbit.com: could not connect to host
|
||||
|
|
Разница между файлами не показана из-за своего большого размера
Загрузить разницу
Различия файлов скрыты, потому что одна или несколько строк слишком длинны
Различия файлов скрыты, потому что одна или несколько строк слишком длинны
Различия файлов скрыты, потому что одна или несколько строк слишком длинны
|
@ -0,0 +1,15 @@
|
|||
# -*- Mode: python; c-basic-offset: 4; indent-tabs-mode: nil; tab-width: 40 -*-
|
||||
# vim: set filetype=python:
|
||||
# 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/.
|
||||
|
||||
FINAL_TARGET_FILES.defaults.blocklists += ['addons.json',
|
||||
'certificates.json',
|
||||
'gfx.json',
|
||||
'plugins.json']
|
||||
|
||||
FINAL_TARGET_FILES.defaults.pinning += ['pins.json']
|
||||
|
||||
if CONFIG['MOZ_BUILD_APP'] == 'browser':
|
||||
DIST_SUBDIR = 'browser'
|
|
@ -0,0 +1 @@
|
|||
{"data":[]}
|
Различия файлов скрыты, потому что одна или несколько строк слишком длинны
|
@ -0,0 +1,29 @@
|
|||
# Blocklist
|
||||
|
||||
The blocklist entries are synchronized locally from the Firefox Settings service.
|
||||
|
||||
https://firefox.settings.services.mozilla.com
|
||||
|
||||
In order to reduce the amount of data to be downloaded on first synchronization,
|
||||
a JSON dump from the records present on the remote server is shipped with the
|
||||
release.
|
||||
|
||||
## How to update the JSON files ?
|
||||
|
||||
Even though it is not a problem if the dumps are not up-to-date when shipped, here
|
||||
are the commands to update them:
|
||||
|
||||
```
|
||||
SERVICE_URL="https://firefox.settings.services.mozilla.com/v1"
|
||||
|
||||
curl "$SERVICE_URL/buckets/blocklists/collections/certificates/records?" > services/blocklists/certificates.json
|
||||
curl "$SERVICE_URL/buckets/blocklists/collections/gfx/records?" > services/blocklists/gfx.json
|
||||
curl "$SERVICE_URL/buckets/blocklists/collections/plugins/records?" > services/blocklists/plugins.json
|
||||
curl "$SERVICE_URL/buckets/blocklists/collections/addons/records?" > services/blocklists/addons.json
|
||||
|
||||
curl "$SERVICE_URL/buckets/pinning/collections/pins/records?" > services/blocklists/pins.json
|
||||
```
|
||||
|
||||
## TODO
|
||||
|
||||
- Setup a bot to update it regularly.
|
|
@ -7,15 +7,13 @@
|
|||
this.EXPORTED_SYMBOLS = ["AddonBlocklistClient",
|
||||
"GfxBlocklistClient",
|
||||
"OneCRLBlocklistClient",
|
||||
"PluginBlocklistClient",
|
||||
"PinningBlocklistClient",
|
||||
"FILENAME_ADDONS_JSON",
|
||||
"FILENAME_GFX_JSON",
|
||||
"FILENAME_PLUGINS_JSON"];
|
||||
"PluginBlocklistClient"];
|
||||
|
||||
const { classes: Cc, interfaces: Ci, utils: Cu } = Components;
|
||||
|
||||
Cu.import("resource://gre/modules/Services.jsm");
|
||||
Cu.import("resource://gre/modules/XPCOMUtils.jsm");
|
||||
const { Task } = Cu.import("resource://gre/modules/Task.jsm", {});
|
||||
const { OS } = Cu.import("resource://gre/modules/osfile.jsm", {});
|
||||
Cu.importGlobalProperties(["fetch"]);
|
||||
|
@ -25,6 +23,9 @@ const { KintoHttpClient } = Cu.import("resource://services-common/kinto-http-cli
|
|||
const { FirefoxAdapter } = Cu.import("resource://services-common/kinto-storage-adapter.js", {});
|
||||
const { CanonicalJSON } = Components.utils.import("resource://gre/modules/CanonicalJSON.jsm", {});
|
||||
|
||||
XPCOMUtils.defineLazyModuleGetter(this, "FileUtils", "resource://gre/modules/FileUtils.jsm");
|
||||
|
||||
const KEY_APPDIR = "XCurProcD";
|
||||
const PREF_SETTINGS_SERVER = "services.settings.server";
|
||||
const PREF_BLOCKLIST_BUCKET = "services.blocklist.bucket";
|
||||
const PREF_BLOCKLIST_ONECRL_COLLECTION = "services.blocklist.onecrl.collection";
|
||||
|
@ -48,9 +49,6 @@ const INVALID_SIGNATURE = "Invalid content/signature";
|
|||
// filename, even though it isn't descriptive of who is using it.
|
||||
this.KINTO_STORAGE_PATH = "kinto.sqlite";
|
||||
|
||||
this.FILENAME_ADDONS_JSON = "blocklist-addons.json";
|
||||
this.FILENAME_GFX_JSON = "blocklist-gfx.json";
|
||||
this.FILENAME_PLUGINS_JSON = "blocklist-plugins.json";
|
||||
|
||||
|
||||
function mergeChanges(collection, localRecords, changes) {
|
||||
|
@ -104,6 +102,29 @@ class BlocklistClient {
|
|||
});
|
||||
}
|
||||
|
||||
get filename() {
|
||||
return `${this.bucketName}/${this.collectionName}.json`;
|
||||
}
|
||||
|
||||
/**
|
||||
* Load the the JSON file distributed with the release for this blocklist.
|
||||
*
|
||||
* For Bug 1257565 this method will have to try to load the file from the profile,
|
||||
* in order to leverage the updateJSONBlocklist() below, which writes a new
|
||||
* dump each time the collection changes.
|
||||
*/
|
||||
loadDumpFile() {
|
||||
const fileURI = `resource://app/defaults/${this.filename}`;
|
||||
return Task.spawn(function* loadFile() {
|
||||
const response = yield fetch(fileURI);
|
||||
if (!response.ok) {
|
||||
throw new Error(`Could not read from '${fileURI}'`);
|
||||
}
|
||||
// Will be rejected if JSON is invalid.
|
||||
return yield response.json();
|
||||
});
|
||||
}
|
||||
|
||||
validateCollectionSignature(remote, payload, collection, options = {}) {
|
||||
const {ignoreLocal} = options;
|
||||
|
||||
|
@ -145,14 +166,17 @@ class BlocklistClient {
|
|||
/**
|
||||
* Synchronize from Kinto server, if necessary.
|
||||
*
|
||||
* @param {int} lastModified the lastModified date (on the server) for
|
||||
the remote collection.
|
||||
* @param {Date} serverTime the current date return by the server.
|
||||
* @return {Promise} which rejects on sync or process failure.
|
||||
* @param {int} lastModified the lastModified date (on the server) for
|
||||
the remote collection.
|
||||
* @param {Date} serverTime the current date return by the server.
|
||||
* @param {Object} options additional advanced options.
|
||||
* @param {bool} options.loadDump load initial dump from disk on first sync (default: true)
|
||||
* @return {Promise} which rejects on sync or process failure.
|
||||
*/
|
||||
maybeSync(lastModified, serverTime) {
|
||||
maybeSync(lastModified, serverTime, options = {loadDump: true}) {
|
||||
const {loadDump} = options;
|
||||
const remote = Services.prefs.getCharPref(PREF_SETTINGS_SERVER);
|
||||
let enforceCollectionSigning =
|
||||
const enforceCollectionSigning =
|
||||
Services.prefs.getBoolPref(PREF_BLOCKLIST_ENFORCE_SIGNING);
|
||||
|
||||
// if there is a signerName and collection signing is enforced, add a
|
||||
|
@ -177,13 +201,30 @@ class BlocklistClient {
|
|||
};
|
||||
const collection = this._kinto.collection(this.collectionName, options);
|
||||
|
||||
const collectionLastModified = yield collection.db.getLastModified();
|
||||
let collectionLastModified = yield collection.db.getLastModified();
|
||||
|
||||
// If there is no data currently in the collection, attempt to import
|
||||
// initial data from the application defaults.
|
||||
// This allows to avoid synchronizing the whole collection content on
|
||||
// cold start.
|
||||
if (!collectionLastModified && loadDump) {
|
||||
try {
|
||||
const initialData = yield this.loadDumpFile();
|
||||
yield collection.db.loadDump(initialData.data);
|
||||
collectionLastModified = yield collection.db.getLastModified();
|
||||
} catch (e) {
|
||||
// Report but go-on.
|
||||
Cu.reportError(e);
|
||||
}
|
||||
}
|
||||
|
||||
// If the data is up to date, there's no need to sync. We still need
|
||||
// to record the fact that a check happened.
|
||||
if (lastModified <= collectionLastModified) {
|
||||
this.updateLastCheck(serverTime);
|
||||
return;
|
||||
}
|
||||
|
||||
// Fetch changes from server.
|
||||
try {
|
||||
const {ok} = yield collection.sync({remote});
|
||||
|
@ -315,10 +356,13 @@ function* updatePinningList(records) {
|
|||
function* updateJSONBlocklist(filename, records) {
|
||||
// Write JSON dump for synchronous load at startup.
|
||||
const path = OS.Path.join(OS.Constants.Path.profileDir, filename);
|
||||
const blocklistFolder = OS.Path.dirname(path);
|
||||
|
||||
yield OS.File.makeDir(blocklistFolder, {from: OS.Constants.Path.profileDir});
|
||||
|
||||
const serialized = JSON.stringify({data: records}, null, 2);
|
||||
try {
|
||||
yield OS.File.writeAtomic(path, serialized, {tmpPath: path + ".tmp"});
|
||||
|
||||
// Notify change to `nsBlocklistService`
|
||||
const eventData = {filename};
|
||||
Services.cpmm.sendAsyncMessage("Blocklist:reload-from-disk", eventData);
|
||||
|
@ -338,21 +382,21 @@ this.OneCRLBlocklistClient = new BlocklistClient(
|
|||
this.AddonBlocklistClient = new BlocklistClient(
|
||||
Services.prefs.getCharPref(PREF_BLOCKLIST_ADDONS_COLLECTION),
|
||||
PREF_BLOCKLIST_ADDONS_CHECKED_SECONDS,
|
||||
updateJSONBlocklist.bind(undefined, FILENAME_ADDONS_JSON),
|
||||
(records) => updateJSONBlocklist(this.AddonBlocklistClient.filename, records),
|
||||
Services.prefs.getCharPref(PREF_BLOCKLIST_BUCKET)
|
||||
);
|
||||
|
||||
this.GfxBlocklistClient = new BlocklistClient(
|
||||
Services.prefs.getCharPref(PREF_BLOCKLIST_GFX_COLLECTION),
|
||||
PREF_BLOCKLIST_GFX_CHECKED_SECONDS,
|
||||
updateJSONBlocklist.bind(undefined, FILENAME_GFX_JSON),
|
||||
(records) => updateJSONBlocklist(this.GfxBlocklistClient.filename, records),
|
||||
Services.prefs.getCharPref(PREF_BLOCKLIST_BUCKET)
|
||||
);
|
||||
|
||||
this.PluginBlocklistClient = new BlocklistClient(
|
||||
Services.prefs.getCharPref(PREF_BLOCKLIST_PLUGINS_COLLECTION),
|
||||
PREF_BLOCKLIST_PLUGINS_CHECKED_SECONDS,
|
||||
updateJSONBlocklist.bind(undefined, FILENAME_PLUGINS_JSON),
|
||||
(records) => updateJSONBlocklist(this.PluginBlocklistClient.filename, records),
|
||||
Services.prefs.getCharPref(PREF_BLOCKLIST_BUCKET)
|
||||
);
|
||||
|
||||
|
|
|
@ -12,9 +12,10 @@ const BinaryInputStream = CC("@mozilla.org/binaryinputstream;1",
|
|||
let server;
|
||||
|
||||
// set up what we need to make storage adapters
|
||||
const kintoFilename = "kinto.sqlite";
|
||||
let sqliteHandle;
|
||||
const KINTO_FILENAME = "kinto.sqlite";
|
||||
|
||||
function do_get_kinto_collection(collectionName, sqliteHandle) {
|
||||
function do_get_kinto_collection(collectionName) {
|
||||
let config = {
|
||||
// Set the remote to be some server that will cause test failure when
|
||||
// hit since we should never hit the server directly, only via maybeSync()
|
||||
|
@ -35,8 +36,8 @@ add_task(function* test_something() {
|
|||
const configPath = "/v1/";
|
||||
const recordsPath = "/v1/buckets/blocklists/collections/certificates/records";
|
||||
|
||||
Services.prefs.setCharPref("services.settings.server",
|
||||
`http://localhost:${server.identity.primaryPort}/v1`);
|
||||
const dummyServerURL = `http://localhost:${server.identity.primaryPort}/v1`;
|
||||
Services.prefs.setCharPref("services.settings.server", dummyServerURL);
|
||||
|
||||
// register a handler
|
||||
function handleResponse(request, response) {
|
||||
|
@ -66,24 +67,45 @@ add_task(function* test_something() {
|
|||
// Test an empty db populates
|
||||
yield OneCRLBlocklistClient.maybeSync(2000, Date.now());
|
||||
|
||||
sqliteHandle = yield FirefoxAdapter.openConnection({path: KINTO_FILENAME});
|
||||
const collection = do_get_kinto_collection("certificates");
|
||||
|
||||
// Open the collection, verify it's been populated:
|
||||
// Our test data has a single record; it should be in the local collection
|
||||
let sqliteHandle = yield FirefoxAdapter.openConnection({path: kintoFilename});
|
||||
let collection = do_get_kinto_collection("certificates", sqliteHandle);
|
||||
let list = yield collection.list();
|
||||
// We know there will be initial values from the JSON dump.
|
||||
// (at least as many as in the dump shipped when this test was written).
|
||||
do_check_true(list.data.length >= 363);
|
||||
|
||||
// No sync will be intented if maybeSync() is up-to-date.
|
||||
Services.prefs.clearUserPref("services.settings.server");
|
||||
Services.prefs.setIntPref("services.blocklist.onecrl.checked", 0);
|
||||
// Use any last_modified older than highest shipped in JSON dump.
|
||||
yield OneCRLBlocklistClient.maybeSync(123456, Date.now());
|
||||
// Last check value was updated.
|
||||
do_check_neq(0, Services.prefs.getIntPref("services.blocklist.onecrl.checked"));
|
||||
|
||||
// Restore server pref.
|
||||
Services.prefs.setCharPref("services.settings.server", dummyServerURL);
|
||||
// clear the collection, save a non-zero lastModified so we don't do
|
||||
// import of initial data when we sync again.
|
||||
yield collection.clear();
|
||||
// a lastModified value of 1000 means we get a remote collection with a
|
||||
// single record
|
||||
yield collection.db.saveLastModified(1000);
|
||||
yield OneCRLBlocklistClient.maybeSync(2000, Date.now());
|
||||
|
||||
// Open the collection, verify it's been updated:
|
||||
// Our test data now has two records; both should be in the local collection
|
||||
list = yield collection.list();
|
||||
do_check_eq(list.data.length, 1);
|
||||
yield sqliteHandle.close();
|
||||
|
||||
// Test the db is updated when we call again with a later lastModified value
|
||||
yield OneCRLBlocklistClient.maybeSync(4000, Date.now());
|
||||
|
||||
// Open the collection, verify it's been updated:
|
||||
// Our test data now has two records; both should be in the local collection
|
||||
sqliteHandle = yield FirefoxAdapter.openConnection({path: kintoFilename});
|
||||
collection = do_get_kinto_collection("certificates", sqliteHandle);
|
||||
list = yield collection.list();
|
||||
do_check_eq(list.data.length, 3);
|
||||
yield sqliteHandle.close();
|
||||
|
||||
// Try to maybeSync with the current lastModified value - no connection
|
||||
// should be attempted.
|
||||
|
@ -104,8 +126,7 @@ add_task(function* test_something() {
|
|||
// Check that a sync completes even when there's bad data in the
|
||||
// collection. This will throw on fail, so just calling maybeSync is an
|
||||
// acceptible test.
|
||||
Services.prefs.setCharPref("services.settings.server",
|
||||
`http://localhost:${server.identity.primaryPort}/v1`);
|
||||
Services.prefs.setCharPref("services.settings.server", dummyServerURL);
|
||||
yield OneCRLBlocklistClient.maybeSync(5000, Date.now());
|
||||
});
|
||||
|
||||
|
@ -122,6 +143,7 @@ function run_test() {
|
|||
|
||||
do_register_cleanup(function() {
|
||||
server.stop(() => { });
|
||||
return sqliteHandle.close();
|
||||
});
|
||||
}
|
||||
|
||||
|
@ -150,6 +172,17 @@ function getSampleResponse(req, port) {
|
|||
"responseBody": JSON.stringify({"settings":{"batch_max_requests":25}, "url":`http://localhost:${port}/v1/`, "documentation":"https://kinto.readthedocs.org/", "version":"1.5.1", "commit":"cbc6f58", "hello":"kinto"})
|
||||
},
|
||||
"GET:/v1/buckets/blocklists/collections/certificates/records?_sort=-last_modified": {
|
||||
"sampleHeaders": [
|
||||
"Access-Control-Allow-Origin: *",
|
||||
"Access-Control-Expose-Headers: Retry-After, Content-Length, Alert, Backoff",
|
||||
"Content-Type: application/json; charset=UTF-8",
|
||||
"Server: waitress",
|
||||
"Etag: \"1000\""
|
||||
],
|
||||
"status": {status: 200, statusText: "OK"},
|
||||
"responseBody": JSON.stringify({"data":[{}]})
|
||||
},
|
||||
"GET:/v1/buckets/blocklists/collections/certificates/records?_sort=-last_modified&_since=1000": {
|
||||
"sampleHeaders": [
|
||||
"Access-Control-Allow-Origin: *",
|
||||
"Access-Control-Expose-Headers: Retry-After, Content-Length, Alert, Backoff",
|
||||
|
|
|
@ -17,9 +17,9 @@ const BinaryInputStream = CC("@mozilla.org/binaryinputstream;1",
|
|||
const kintoFilename = "kinto.sqlite";
|
||||
|
||||
const gBlocklistClients = [
|
||||
{client: BlocklistClients.AddonBlocklistClient, filename: BlocklistClients.FILENAME_ADDONS_JSON, testData: ["i808", "i720", "i539"]},
|
||||
{client: BlocklistClients.PluginBlocklistClient, filename: BlocklistClients.FILENAME_PLUGINS_JSON, testData: ["p1044", "p32", "p28"]},
|
||||
{client: BlocklistClients.GfxBlocklistClient, filename: BlocklistClients.FILENAME_GFX_JSON, testData: ["g204", "g200", "g36"]},
|
||||
{client: BlocklistClients.AddonBlocklistClient, testData: ["i808", "i720", "i539"]},
|
||||
{client: BlocklistClients.PluginBlocklistClient, testData: ["p1044", "p32", "p28"]},
|
||||
{client: BlocklistClients.GfxBlocklistClient, testData: ["g204", "g200", "g36"]},
|
||||
];
|
||||
|
||||
|
||||
|
@ -57,14 +57,10 @@ function* clear_state() {
|
|||
} finally {
|
||||
yield sqliteHandle.close();
|
||||
}
|
||||
}
|
||||
|
||||
// Remove profile data.
|
||||
for (let {filename} of gBlocklistClients) {
|
||||
const blocklist = FileUtils.getFile(KEY_PROFILEDIR, [filename]);
|
||||
if (blocklist.exists()) {
|
||||
blocklist.remove(true);
|
||||
}
|
||||
// Remove profile data.
|
||||
const path = OS.Path.join(OS.Constants.Path.profileDir, client.filename);
|
||||
yield OS.File.remove(path, { ignoreAbsent: true });
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -121,7 +117,7 @@ function run_test() {
|
|||
add_task(function* test_records_obtained_from_server_are_stored_in_db() {
|
||||
for (let {client} of gBlocklistClients) {
|
||||
// Test an empty db populates
|
||||
yield client.maybeSync(2000, Date.now());
|
||||
yield client.maybeSync(2000, Date.now(), {loadDump: false});
|
||||
|
||||
// Open the collection, verify it's been populated:
|
||||
// Our test data has a single record; it should be in the local collection
|
||||
|
@ -135,11 +131,11 @@ add_task(function* test_records_obtained_from_server_are_stored_in_db() {
|
|||
add_task(clear_state);
|
||||
|
||||
add_task(function* test_list_is_written_to_file_in_profile() {
|
||||
for (let {client, filename, testData} of gBlocklistClients) {
|
||||
const profFile = FileUtils.getFile(KEY_PROFILEDIR, [filename]);
|
||||
for (let {client, testData} of gBlocklistClients) {
|
||||
const profFile = FileUtils.getFile(KEY_PROFILEDIR, client.filename.split("/"));
|
||||
strictEqual(profFile.exists(), false);
|
||||
|
||||
yield client.maybeSync(2000, Date.now());
|
||||
yield client.maybeSync(2000, Date.now(), {loadDump: false});
|
||||
|
||||
strictEqual(profFile.exists(), true);
|
||||
const content = yield readJSON(profFile.path);
|
||||
|
@ -159,9 +155,9 @@ add_task(function* test_current_server_time_is_saved_in_pref() {
|
|||
add_task(clear_state);
|
||||
|
||||
add_task(function* test_update_json_file_when_addons_has_changes() {
|
||||
for (let {client, filename, testData} of gBlocklistClients) {
|
||||
yield client.maybeSync(2000, Date.now() - 1000);
|
||||
const profFile = FileUtils.getFile(KEY_PROFILEDIR, [filename]);
|
||||
for (let {client, testData} of gBlocklistClients) {
|
||||
yield client.maybeSync(2000, Date.now() - 1000, {loadDump: false});
|
||||
const profFile = FileUtils.getFile(KEY_PROFILEDIR, client.filename.split("/"));
|
||||
const fileLastModified = profFile.lastModifiedTime = profFile.lastModifiedTime - 1000;
|
||||
const serverTime = Date.now();
|
||||
|
||||
|
@ -179,24 +175,24 @@ add_task(function* test_update_json_file_when_addons_has_changes() {
|
|||
add_task(clear_state);
|
||||
|
||||
add_task(function* test_sends_reload_message_when_blocklist_has_changes() {
|
||||
for (let {client, filename} of gBlocklistClients) {
|
||||
for (let {client} of gBlocklistClients) {
|
||||
let received = yield new Promise((resolve, reject) => {
|
||||
Services.ppmm.addMessageListener("Blocklist:reload-from-disk", {
|
||||
receiveMessage(aMsg) { resolve(aMsg) }
|
||||
});
|
||||
|
||||
client.maybeSync(2000, Date.now() - 1000);
|
||||
client.maybeSync(2000, Date.now() - 1000, {loadDump: false});
|
||||
});
|
||||
|
||||
equal(received.data.filename, filename);
|
||||
equal(received.data.filename, client.filename);
|
||||
}
|
||||
});
|
||||
add_task(clear_state);
|
||||
|
||||
add_task(function* test_do_nothing_when_blocklist_is_up_to_date() {
|
||||
for (let {client, filename} of gBlocklistClients) {
|
||||
yield client.maybeSync(2000, Date.now() - 1000);
|
||||
const profFile = FileUtils.getFile(KEY_PROFILEDIR, [filename]);
|
||||
for (let {client} of gBlocklistClients) {
|
||||
yield client.maybeSync(2000, Date.now() - 1000, {loadDump: false});
|
||||
const profFile = FileUtils.getFile(KEY_PROFILEDIR, client.filename.split("/"));
|
||||
const fileLastModified = profFile.lastModifiedTime = profFile.lastModifiedTime - 1000;
|
||||
const serverTime = Date.now();
|
||||
|
||||
|
|
|
@ -294,7 +294,8 @@ add_task(function* test_check_signatures() {
|
|||
|
||||
// With all of this set up, we attempt a sync. This will resolve if all is
|
||||
// well and throw if something goes wrong.
|
||||
yield OneCRLBlocklistClient.maybeSync(1000, startTime);
|
||||
// We don't want to load initial json dumps in this test suite.
|
||||
yield OneCRLBlocklistClient.maybeSync(1000, startTime, {loadDump: false});
|
||||
|
||||
// Check that some additions (2 records) to the collection have a valid
|
||||
// signature.
|
||||
|
|
|
@ -9,6 +9,8 @@ support-files =
|
|||
[test_load_modules.js]
|
||||
|
||||
[test_blocklist_certificates.js]
|
||||
# Initial JSON data for blocklists are not shipped on Android.
|
||||
skip-if = os == "android"
|
||||
[test_blocklist_clients.js]
|
||||
[test_blocklist_updater.js]
|
||||
[test_blocklist_pinning.js]
|
||||
|
|
|
@ -10,7 +10,10 @@ DIRS += [
|
|||
]
|
||||
|
||||
if CONFIG['MOZ_WIDGET_TOOLKIT'] != 'android':
|
||||
DIRS += ['fxaccounts']
|
||||
DIRS += [
|
||||
'fxaccounts',
|
||||
'blocklists',
|
||||
]
|
||||
|
||||
if CONFIG['MOZ_SERVICES_SYNC']:
|
||||
DIRS += ['sync']
|
||||
|
|
|
@ -602,7 +602,7 @@ dependencies = [
|
|||
"devtools_traits 0.0.1",
|
||||
"encoding 0.2.33 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"hyper 0.9.18 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"hyper_serde 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"hyper_serde 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"ipc-channel 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"log 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"msg 0.0.1",
|
||||
|
@ -620,7 +620,7 @@ dependencies = [
|
|||
"heapsize 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"heapsize_derive 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"hyper 0.9.18 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"hyper_serde 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"hyper_serde 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"ipc-channel 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"msg 0.0.1",
|
||||
"serde 0.9.7 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
|
@ -1165,13 +1165,14 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "hyper_serde"
|
||||
version = "0.5.0"
|
||||
version = "0.5.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"cookie 0.2.5 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"hyper 0.9.18 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"mime 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"serde 0.9.7 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"time 0.1.36 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
@ -1638,7 +1639,7 @@ dependencies = [
|
|||
"devtools_traits 0.0.1",
|
||||
"flate2 0.2.17 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"hyper 0.9.18 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"hyper_serde 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"hyper_serde 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"immeta 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"ipc-channel 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"lazy_static 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
|
@ -1652,6 +1653,9 @@ dependencies = [
|
|||
"openssl-verify 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"profile_traits 0.0.1",
|
||||
"rustc-serialize 0.3.22 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"serde 0.9.7 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"serde_derive 0.9.7 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"serde_json 0.9.7 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"servo_config 0.0.1",
|
||||
"servo_url 0.0.1",
|
||||
"threadpool 1.3.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
|
@ -1685,7 +1689,7 @@ dependencies = [
|
|||
"devtools_traits 0.0.1",
|
||||
"flate2 0.2.17 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"hyper 0.9.18 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"hyper_serde 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"hyper_serde 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"ipc-channel 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"msg 0.0.1",
|
||||
"net 0.0.1",
|
||||
|
@ -1706,7 +1710,7 @@ dependencies = [
|
|||
"heapsize 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"heapsize_derive 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"hyper 0.9.18 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"hyper_serde 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"hyper_serde 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"image 0.12.3 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"ipc-channel 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"lazy_static 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
|
@ -2209,7 +2213,7 @@ dependencies = [
|
|||
"html5ever 0.13.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"html5ever-atoms 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"hyper 0.9.18 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"hyper_serde 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"hyper_serde 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"image 0.12.3 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"ipc-channel 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"js 0.1.4 (git+https://github.com/servo/rust-mozjs)",
|
||||
|
@ -2312,7 +2316,7 @@ dependencies = [
|
|||
"heapsize 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"heapsize_derive 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"hyper 0.9.18 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"hyper_serde 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"hyper_serde 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"ipc-channel 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"libc 0.2.20 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"msg 0.0.1",
|
||||
|
@ -3416,7 +3420,7 @@ dependencies = [
|
|||
"checksum html5ever-atoms 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "f9bd86e3b6a5a7933a272cc0a854f24e371f31576e585c0b41e8f857270c5134"
|
||||
"checksum httparse 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "a6e7a63e511f9edffbab707141fbb8707d1a3098615fb2adbd5769cdfcc9b17d"
|
||||
"checksum hyper 0.9.18 (registry+https://github.com/rust-lang/crates.io-index)" = "1b9bf64f730d6ee4b0528a5f0a316363da9d8104318731509d4ccc86248f82b3"
|
||||
"checksum hyper_serde 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)" = "19065fedb73b4d5c617482cedfb3cfb092fc379870a7e3aadd16fd491838129a"
|
||||
"checksum hyper_serde 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "d602a93073c250f49b2e2d931cc1755a5f447824154dc3c711716dee29bd7486"
|
||||
"checksum idna 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "1053236e00ce4f668aeca4a769a09b3bf5a682d802abd6f3cb39374f6b162c11"
|
||||
"checksum image 0.12.3 (registry+https://github.com/rust-lang/crates.io-index)" = "979bad0502082fd60053a490282e87d6c89650942e3a270e0d4c83569c7f5899"
|
||||
"checksum immeta 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)" = "3e76ecb1d64979a91c7fc5b7c0495ef1467e3cbff759044f2b88878a5a845ef7"
|
||||
|
|
|
@ -30,6 +30,9 @@ openssl = "0.7.6"
|
|||
openssl-verify = "0.1"
|
||||
profile_traits = {path = "../profile_traits"}
|
||||
rustc-serialize = "0.3"
|
||||
serde = "0.9"
|
||||
serde_derive = "0.9"
|
||||
serde_json = "0.9"
|
||||
servo_config = {path = "../config"}
|
||||
servo_url = {path = "../url"}
|
||||
threadpool = "1.0"
|
||||
|
|
|
@ -6,6 +6,7 @@
|
|||
//! http://tools.ietf.org/html/rfc6265
|
||||
|
||||
use cookie_rs;
|
||||
use hyper_serde::{self, Serde};
|
||||
use net_traits::CookieSource;
|
||||
use net_traits::pub_domains::is_pub_domain;
|
||||
use servo_url::ServoUrl;
|
||||
|
@ -16,14 +17,20 @@ use time::{Tm, now, at, Duration};
|
|||
/// A stored cookie that wraps the definition in cookie-rs. This is used to implement
|
||||
/// various behaviours defined in the spec that rely on an associated request URL,
|
||||
/// which cookie-rs and hyper's header parsing do not support.
|
||||
#[derive(Clone, Debug, RustcDecodable, RustcEncodable)]
|
||||
#[derive(Clone, Debug, Deserialize, Serialize)]
|
||||
pub struct Cookie {
|
||||
#[serde(deserialize_with = "hyper_serde::deserialize",
|
||||
serialize_with = "hyper_serde::serialize")]
|
||||
pub cookie: cookie_rs::Cookie,
|
||||
pub host_only: bool,
|
||||
pub persistent: bool,
|
||||
#[serde(deserialize_with = "hyper_serde::deserialize",
|
||||
serialize_with = "hyper_serde::serialize")]
|
||||
pub creation_time: Tm,
|
||||
#[serde(deserialize_with = "hyper_serde::deserialize",
|
||||
serialize_with = "hyper_serde::serialize")]
|
||||
pub last_access: Tm,
|
||||
pub expiry_time: Option<Tm>,
|
||||
pub expiry_time: Option<Serde<Tm>>,
|
||||
}
|
||||
|
||||
impl Cookie {
|
||||
|
@ -85,7 +92,7 @@ impl Cookie {
|
|||
persistent: persistent,
|
||||
creation_time: now(),
|
||||
last_access: now(),
|
||||
expiry_time: expiry_time,
|
||||
expiry_time: expiry_time.map(Serde),
|
||||
})
|
||||
}
|
||||
|
||||
|
|
|
@ -16,7 +16,7 @@ use time::Tm;
|
|||
|
||||
extern crate time;
|
||||
|
||||
#[derive(Clone, Debug, RustcDecodable, RustcEncodable)]
|
||||
#[derive(Clone, Debug, Deserialize, Serialize)]
|
||||
pub struct CookieStorage {
|
||||
version: u32,
|
||||
cookies_map: HashMap<String, Vec<Cookie>>,
|
||||
|
@ -192,7 +192,7 @@ fn reg_host<'a>(url: &'a str) -> String {
|
|||
|
||||
fn is_cookie_expired(cookie: &Cookie) -> bool {
|
||||
match cookie.expiry_time {
|
||||
Some(t) => t.to_timespec() <= time::get_time(),
|
||||
Some(ref t) => t.to_timespec() <= time::get_time(),
|
||||
None => false,
|
||||
}
|
||||
}
|
||||
|
|
|
@ -4,7 +4,7 @@
|
|||
|
||||
use net_traits::IncludeSubdomains;
|
||||
use net_traits::pub_domains::reg_suffix;
|
||||
use rustc_serialize::json::decode;
|
||||
use serde_json;
|
||||
use servo_config::resource_files::read_resource_file;
|
||||
use std::collections::HashMap;
|
||||
use std::net::{Ipv4Addr, Ipv6Addr};
|
||||
|
@ -12,7 +12,7 @@ use std::str::from_utf8;
|
|||
use time;
|
||||
use url::Url;
|
||||
|
||||
#[derive(RustcDecodable, RustcEncodable, Clone)]
|
||||
#[derive(Clone, Deserialize, Serialize)]
|
||||
pub struct HstsEntry {
|
||||
pub host: String,
|
||||
pub include_subdomains: bool,
|
||||
|
@ -53,7 +53,7 @@ impl HstsEntry {
|
|||
}
|
||||
}
|
||||
|
||||
#[derive(RustcDecodable, RustcEncodable, Clone)]
|
||||
#[derive(Clone, Deserialize, Serialize)]
|
||||
pub struct HstsList {
|
||||
pub entries_map: HashMap<String, Vec<HstsEntry>>,
|
||||
}
|
||||
|
@ -65,14 +65,14 @@ impl HstsList {
|
|||
|
||||
/// Create an `HstsList` from the bytes of a JSON preload file.
|
||||
pub fn from_preload(preload_content: &[u8]) -> Option<HstsList> {
|
||||
#[derive(RustcDecodable)]
|
||||
#[derive(Deserialize)]
|
||||
struct HstsEntries {
|
||||
entries: Vec<HstsEntry>,
|
||||
}
|
||||
|
||||
let hsts_entries: Option<HstsEntries> = from_utf8(&preload_content)
|
||||
.ok()
|
||||
.and_then(|c| decode(c).ok());
|
||||
.and_then(|c| serde_json::from_str(c).ok());
|
||||
|
||||
hsts_entries.map_or(None, |hsts_entries| {
|
||||
let mut hsts_list: HstsList = HstsList::new();
|
||||
|
|
|
@ -27,6 +27,10 @@ extern crate openssl;
|
|||
extern crate openssl_verify;
|
||||
extern crate profile_traits;
|
||||
extern crate rustc_serialize;
|
||||
extern crate serde;
|
||||
#[macro_use]
|
||||
extern crate serde_derive;
|
||||
extern crate serde_json;
|
||||
extern crate servo_config;
|
||||
extern crate servo_url;
|
||||
extern crate threadpool;
|
||||
|
|
|
@ -23,8 +23,8 @@ use net_traits::{ResourceThreads, WebSocketCommunicate, WebSocketConnectData};
|
|||
use net_traits::request::{Request, RequestInit};
|
||||
use net_traits::storage_thread::StorageThreadMsg;
|
||||
use profile_traits::time::ProfilerChan;
|
||||
use rustc_serialize::{Decodable, Encodable};
|
||||
use rustc_serialize::json;
|
||||
use serde::{Deserialize, Serialize};
|
||||
use serde_json;
|
||||
use servo_url::ServoUrl;
|
||||
use std::borrow::{Cow, ToOwned};
|
||||
use std::collections::HashMap;
|
||||
|
@ -211,7 +211,7 @@ impl ResourceChannelManager {
|
|||
}
|
||||
|
||||
pub fn read_json_from_file<T>(data: &mut T, config_dir: &Path, filename: &str)
|
||||
where T: Decodable
|
||||
where T: Deserialize
|
||||
{
|
||||
let path = config_dir.join(filename);
|
||||
let display = path.display();
|
||||
|
@ -233,17 +233,17 @@ pub fn read_json_from_file<T>(data: &mut T, config_dir: &Path, filename: &str)
|
|||
Ok(_) => println!("successfully read from {}", display),
|
||||
}
|
||||
|
||||
match json::decode(&string_buffer) {
|
||||
match serde_json::from_str(&string_buffer) {
|
||||
Ok(decoded_buffer) => *data = decoded_buffer,
|
||||
Err(why) => warn!("Could not decode buffer{}", why),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn write_json_to_file<T>(data: &T, config_dir: &Path, filename: &str)
|
||||
where T: Encodable
|
||||
where T: Serialize
|
||||
{
|
||||
let json_encoded: String;
|
||||
match json::encode(&data) {
|
||||
match serde_json::to_string_pretty(&data) {
|
||||
Ok(d) => json_encoded = d,
|
||||
Err(_) => return,
|
||||
}
|
||||
|
@ -266,7 +266,7 @@ pub fn write_json_to_file<T>(data: &T, config_dir: &Path, filename: &str)
|
|||
}
|
||||
}
|
||||
|
||||
#[derive(RustcDecodable, RustcEncodable, Clone)]
|
||||
#[derive(Clone, Deserialize, Serialize)]
|
||||
pub struct AuthCacheEntry {
|
||||
pub user_name: String,
|
||||
pub password: String,
|
||||
|
@ -281,7 +281,7 @@ impl AuthCache {
|
|||
}
|
||||
}
|
||||
|
||||
#[derive(RustcDecodable, RustcEncodable, Clone)]
|
||||
#[derive(Clone, Deserialize, Serialize)]
|
||||
pub struct AuthCache {
|
||||
pub version: u32,
|
||||
pub entries: HashMap<String, AuthCacheEntry>,
|
||||
|
|
|
@ -15,6 +15,7 @@ use properties::{PropertyDeclarationId, LonghandId, DeclaredValue};
|
|||
use properties::PropertyDeclarationParseResult;
|
||||
use properties::animated_properties::TransitionProperty;
|
||||
use properties::longhands::transition_timing_function::single_value::SpecifiedValue as SpecifiedTimingFunction;
|
||||
use properties::property_bit_field::PropertyBitField;
|
||||
use std::fmt;
|
||||
use std::sync::Arc;
|
||||
use style_traits::ToCss;
|
||||
|
@ -244,21 +245,23 @@ pub struct KeyframesAnimation {
|
|||
pub properties_changed: Vec<TransitionProperty>,
|
||||
}
|
||||
|
||||
/// Get all the animated properties in a keyframes animation. Note that it's not
|
||||
/// defined what happens when a property is not on a keyframe, so we only peek
|
||||
/// the props of the first one.
|
||||
///
|
||||
/// In practice, browsers seem to try to do their best job at it, so we might
|
||||
/// want to go through all the actual keyframes and deduplicate properties.
|
||||
fn get_animated_properties(keyframe: &Keyframe) -> Vec<TransitionProperty> {
|
||||
/// Get all the animated properties in a keyframes animation.
|
||||
fn get_animated_properties(keyframes: &[Arc<RwLock<Keyframe>>]) -> Vec<TransitionProperty> {
|
||||
let mut ret = vec![];
|
||||
let mut seen = PropertyBitField::new();
|
||||
// NB: declarations are already deduplicated, so we don't have to check for
|
||||
// it here.
|
||||
for &(ref declaration, importance) in keyframe.block.read().declarations.iter() {
|
||||
assert!(!importance.important());
|
||||
for keyframe in keyframes {
|
||||
let keyframe = keyframe.read();
|
||||
for &(ref declaration, importance) in keyframe.block.read().declarations.iter() {
|
||||
assert!(!importance.important());
|
||||
|
||||
if let Some(property) = TransitionProperty::from_declaration(declaration) {
|
||||
ret.push(property);
|
||||
if let Some(property) = TransitionProperty::from_declaration(declaration) {
|
||||
if !seen.has_transition_property_bit(&property) {
|
||||
ret.push(property);
|
||||
seen.set_transition_property_bit(&property);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -284,7 +287,7 @@ impl KeyframesAnimation {
|
|||
return result;
|
||||
}
|
||||
|
||||
result.properties_changed = get_animated_properties(&keyframes[0].read());
|
||||
result.properties_changed = get_animated_properties(keyframes);
|
||||
if result.properties_changed.is_empty() {
|
||||
return result;
|
||||
}
|
||||
|
|
|
@ -43,7 +43,7 @@ use values::specified::Angle as SpecifiedAngle;
|
|||
/// property.
|
||||
// NB: This needs to be here because it needs all the longhands generated
|
||||
// beforehand.
|
||||
#[derive(Copy, Clone, Debug, PartialEq)]
|
||||
#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)]
|
||||
#[cfg_attr(feature = "servo", derive(HeapSizeOf))]
|
||||
pub enum TransitionProperty {
|
||||
/// All, any animatable property changing should generate a transition.
|
||||
|
|
|
@ -181,8 +181,10 @@ pub mod animated_properties {
|
|||
|
||||
// TODO(SimonSapin): Convert this to a syntax extension rather than a Mako template.
|
||||
// Maybe submit for inclusion in libstd?
|
||||
mod property_bit_field {
|
||||
#[allow(missing_docs)]
|
||||
pub mod property_bit_field {
|
||||
use logical_geometry::WritingMode;
|
||||
use properties::animated_properties::TransitionProperty;
|
||||
|
||||
/// A bitfield for all longhand properties, in order to quickly test whether
|
||||
/// we've seen one of them.
|
||||
|
@ -213,7 +215,7 @@ mod property_bit_field {
|
|||
pub fn get_${property.ident}(&self) -> bool {
|
||||
self.get(${i})
|
||||
}
|
||||
#[allow(non_snake_case)]
|
||||
#[allow(non_snake_case, missing_docs)]
|
||||
#[inline]
|
||||
pub fn set_${property.ident}(&mut self) {
|
||||
self.set(${i})
|
||||
|
@ -238,6 +240,32 @@ mod property_bit_field {
|
|||
}
|
||||
% endif
|
||||
% endfor
|
||||
|
||||
/// Set the corresponding bit of TransitionProperty.
|
||||
/// This function will panic if TransitionProperty::All is given.
|
||||
pub fn set_transition_property_bit(&mut self, property: &TransitionProperty) {
|
||||
match *property {
|
||||
% for i, prop in enumerate(data.longhands):
|
||||
% if prop.animatable:
|
||||
TransitionProperty::${prop.camel_case} => self.set(${i}),
|
||||
% endif
|
||||
% endfor
|
||||
TransitionProperty::All => unreachable!("Tried to set TransitionProperty::All in a PropertyBitfield"),
|
||||
}
|
||||
}
|
||||
|
||||
/// Return true if the corresponding bit of TransitionProperty is set.
|
||||
/// This function will panic if TransitionProperty::All is given.
|
||||
pub fn has_transition_property_bit(&self, property: &TransitionProperty) -> bool {
|
||||
match *property {
|
||||
% for i, prop in enumerate(data.longhands):
|
||||
% if prop.animatable:
|
||||
TransitionProperty::${prop.camel_case} => self.get(${i}),
|
||||
% endif
|
||||
% endfor
|
||||
TransitionProperty::All => unreachable!("Tried to get TransitionProperty::All in a PropertyBitfield"),
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -1435,6 +1435,9 @@ pub extern "C" fn Servo_StyleSet_FillKeyframesForName(raw_data: RawServoStyleSet
|
|||
timing_function: *const nsTimingFunction,
|
||||
style: ServoComputedValuesBorrowed,
|
||||
keyframes: RawGeckoKeyframeListBorrowedMut) -> bool {
|
||||
use style::gecko_bindings::structs::Keyframe;
|
||||
use style::properties::property_bit_field::PropertyBitField;
|
||||
|
||||
let data = PerDocumentStyleData::from_ffi(raw_data).borrow_mut();
|
||||
let name = unsafe { Atom::from(name.as_ref().unwrap().as_str_unchecked()) };
|
||||
let style_timing_function = unsafe { timing_function.as_ref().unwrap() };
|
||||
|
@ -1455,16 +1458,25 @@ pub extern "C" fn Servo_StyleSet_FillKeyframesForName(raw_data: RawServoStyleSet
|
|||
&timing_function)
|
||||
};
|
||||
|
||||
fn add_computed_property_value(keyframe: *mut Keyframe,
|
||||
index: usize,
|
||||
style: &ComputedValues,
|
||||
property: &TransitionProperty) {
|
||||
let block = style.to_declaration_block(property.clone().into());
|
||||
unsafe {
|
||||
(*keyframe).mPropertyValues.set_len((index + 1) as u32);
|
||||
(*keyframe).mPropertyValues[index].mProperty = property.clone().into();
|
||||
// FIXME. Do not set computed values once we handles missing keyframes
|
||||
// with additive composition.
|
||||
(*keyframe).mPropertyValues[index].mServoDeclarationBlock.set_arc_leaky(
|
||||
Arc::new(RwLock::new(block)));
|
||||
}
|
||||
}
|
||||
|
||||
match step.value {
|
||||
KeyframesStepValue::ComputedValues => {
|
||||
for (index, property) in animation.properties_changed.iter().enumerate() {
|
||||
let block = style.to_declaration_block(property.clone().into());
|
||||
unsafe {
|
||||
(*keyframe).mPropertyValues.set_len((index + 1) as u32);
|
||||
(*keyframe).mPropertyValues[index].mProperty = property.clone().into();
|
||||
(*keyframe).mPropertyValues[index].mServoDeclarationBlock.set_arc_leaky(
|
||||
Arc::new(RwLock::new(block)));
|
||||
}
|
||||
add_computed_property_value(keyframe, index, style, property);
|
||||
}
|
||||
},
|
||||
KeyframesStepValue::Declarations { ref block } => {
|
||||
|
@ -1476,16 +1488,33 @@ pub extern "C" fn Servo_StyleSet_FillKeyframesForName(raw_data: RawServoStyleSet
|
|||
.filter(|&&(ref declaration, _)| {
|
||||
declaration.is_animatable()
|
||||
});
|
||||
|
||||
let mut seen = PropertyBitField::new();
|
||||
|
||||
for (index, &(ref declaration, _)) in animatable.enumerate() {
|
||||
unsafe {
|
||||
let property = TransitionProperty::from_declaration(declaration).unwrap();
|
||||
(*keyframe).mPropertyValues.set_len((index + 1) as u32);
|
||||
(*keyframe).mPropertyValues[index].mProperty =
|
||||
TransitionProperty::from_declaration(declaration).unwrap().into();
|
||||
(*keyframe).mPropertyValues[index].mProperty = property.into();
|
||||
(*keyframe).mPropertyValues[index].mServoDeclarationBlock.set_arc_leaky(
|
||||
Arc::new(RwLock::new(
|
||||
PropertyDeclarationBlock { declarations: vec![ (declaration.clone(),
|
||||
Importance::Normal) ],
|
||||
important_count: 0 })));
|
||||
if step.start_percentage.0 == 0. ||
|
||||
step.start_percentage.0 == 1. {
|
||||
seen.set_transition_property_bit(&property);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Append missing property values in the initial or the finial keyframes.
|
||||
if step.start_percentage.0 == 0. ||
|
||||
step.start_percentage.0 == 1. {
|
||||
for (index, property) in animation.properties_changed.iter().enumerate() {
|
||||
if !seen.has_transition_property_bit(&property) {
|
||||
add_computed_property_value(keyframe, index, style, property);
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
|
|
|
@ -232,7 +232,7 @@ class MachCommands(CommandBase):
|
|||
test_patterns.append(test)
|
||||
|
||||
if not packages:
|
||||
packages = set(os.listdir(path.join(self.context.topdir, "tests", "unit")))
|
||||
packages = set(os.listdir(path.join(self.context.topdir, "tests", "unit"))) - set(['.DS_Store'])
|
||||
|
||||
packages.discard('stylo')
|
||||
|
||||
|
@ -345,7 +345,7 @@ class MachCommands(CommandBase):
|
|||
test_patterns.append(test)
|
||||
|
||||
if not packages:
|
||||
packages = set(os.listdir(path.join(self.context.topdir, "tests", "compiletest")))
|
||||
packages = set(os.listdir(path.join(self.context.topdir, "tests", "compiletest"))) - set(['.DS_Store'])
|
||||
|
||||
packages.remove("helper")
|
||||
|
||||
|
|
|
@ -5,7 +5,10 @@
|
|||
use parking_lot::RwLock;
|
||||
use std::sync::Arc;
|
||||
use style::keyframes::{Keyframe, KeyframesAnimation, KeyframePercentage, KeyframeSelector};
|
||||
use style::properties::PropertyDeclarationBlock;
|
||||
use style::keyframes::{KeyframesStep, KeyframesStepValue};
|
||||
use style::properties::{DeclaredValue, PropertyDeclaration, PropertyDeclarationBlock, Importance};
|
||||
use style::properties::animated_properties::TransitionProperty;
|
||||
use style::values::specified::{LengthOrPercentageOrAuto, NoCalcLength};
|
||||
|
||||
#[test]
|
||||
fn test_empty_keyframe() {
|
||||
|
@ -38,3 +41,177 @@ fn test_no_property_in_keyframe() {
|
|||
|
||||
assert_eq!(format!("{:#?}", animation), format!("{:#?}", expected));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_missing_property_in_initial_keyframe() {
|
||||
let declarations_on_initial_keyframe =
|
||||
Arc::new(RwLock::new(PropertyDeclarationBlock {
|
||||
declarations: vec![
|
||||
(PropertyDeclaration::Width(
|
||||
DeclaredValue::Value(LengthOrPercentageOrAuto::Length(NoCalcLength::from_px(20f32)))),
|
||||
Importance::Normal),
|
||||
],
|
||||
important_count: 0,
|
||||
}));
|
||||
|
||||
let declarations_on_final_keyframe =
|
||||
Arc::new(RwLock::new(PropertyDeclarationBlock {
|
||||
declarations: vec![
|
||||
(PropertyDeclaration::Width(
|
||||
DeclaredValue::Value(LengthOrPercentageOrAuto::Length(NoCalcLength::from_px(20f32)))),
|
||||
Importance::Normal),
|
||||
|
||||
(PropertyDeclaration::Height(
|
||||
DeclaredValue::Value(LengthOrPercentageOrAuto::Length(NoCalcLength::from_px(20f32)))),
|
||||
Importance::Normal),
|
||||
],
|
||||
important_count: 0,
|
||||
}));
|
||||
|
||||
let keyframes = vec![
|
||||
Arc::new(RwLock::new(Keyframe {
|
||||
selector: KeyframeSelector::new_for_unit_testing(vec![KeyframePercentage::new(0.)]),
|
||||
block: declarations_on_initial_keyframe.clone(),
|
||||
})),
|
||||
|
||||
Arc::new(RwLock::new(Keyframe {
|
||||
selector: KeyframeSelector::new_for_unit_testing(vec![KeyframePercentage::new(1.)]),
|
||||
block: declarations_on_final_keyframe.clone(),
|
||||
})),
|
||||
];
|
||||
let animation = KeyframesAnimation::from_keyframes(&keyframes);
|
||||
let expected = KeyframesAnimation {
|
||||
steps: vec![
|
||||
KeyframesStep {
|
||||
start_percentage: KeyframePercentage(0.),
|
||||
value: KeyframesStepValue::Declarations { block: declarations_on_initial_keyframe },
|
||||
declared_timing_function: false,
|
||||
},
|
||||
KeyframesStep {
|
||||
start_percentage: KeyframePercentage(1.),
|
||||
value: KeyframesStepValue::Declarations { block: declarations_on_final_keyframe },
|
||||
declared_timing_function: false,
|
||||
},
|
||||
],
|
||||
properties_changed: vec![TransitionProperty::Width, TransitionProperty::Height],
|
||||
};
|
||||
|
||||
assert_eq!(format!("{:#?}", animation), format!("{:#?}", expected));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_missing_property_in_final_keyframe() {
|
||||
let declarations_on_initial_keyframe =
|
||||
Arc::new(RwLock::new(PropertyDeclarationBlock {
|
||||
declarations: vec![
|
||||
(PropertyDeclaration::Width(
|
||||
DeclaredValue::Value(LengthOrPercentageOrAuto::Length(NoCalcLength::from_px(20f32)))),
|
||||
Importance::Normal),
|
||||
|
||||
(PropertyDeclaration::Height(
|
||||
DeclaredValue::Value(LengthOrPercentageOrAuto::Length(NoCalcLength::from_px(20f32)))),
|
||||
Importance::Normal),
|
||||
],
|
||||
important_count: 0,
|
||||
}));
|
||||
|
||||
let declarations_on_final_keyframe =
|
||||
Arc::new(RwLock::new(PropertyDeclarationBlock {
|
||||
declarations: vec![
|
||||
(PropertyDeclaration::Height(
|
||||
DeclaredValue::Value(LengthOrPercentageOrAuto::Length(NoCalcLength::from_px(20f32)))),
|
||||
Importance::Normal),
|
||||
],
|
||||
important_count: 0,
|
||||
}));
|
||||
|
||||
let keyframes = vec![
|
||||
Arc::new(RwLock::new(Keyframe {
|
||||
selector: KeyframeSelector::new_for_unit_testing(vec![KeyframePercentage::new(0.)]),
|
||||
block: declarations_on_initial_keyframe.clone(),
|
||||
})),
|
||||
|
||||
Arc::new(RwLock::new(Keyframe {
|
||||
selector: KeyframeSelector::new_for_unit_testing(vec![KeyframePercentage::new(1.)]),
|
||||
block: declarations_on_final_keyframe.clone(),
|
||||
})),
|
||||
];
|
||||
let animation = KeyframesAnimation::from_keyframes(&keyframes);
|
||||
let expected = KeyframesAnimation {
|
||||
steps: vec![
|
||||
KeyframesStep {
|
||||
start_percentage: KeyframePercentage(0.),
|
||||
value: KeyframesStepValue::Declarations { block: declarations_on_initial_keyframe },
|
||||
declared_timing_function: false,
|
||||
},
|
||||
KeyframesStep {
|
||||
start_percentage: KeyframePercentage(1.),
|
||||
value: KeyframesStepValue::Declarations { block: declarations_on_final_keyframe },
|
||||
declared_timing_function: false,
|
||||
},
|
||||
],
|
||||
properties_changed: vec![TransitionProperty::Width, TransitionProperty::Height],
|
||||
};
|
||||
|
||||
assert_eq!(format!("{:#?}", animation), format!("{:#?}", expected));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_missing_keyframe_in_both_of_initial_and_final_keyframe() {
|
||||
let declarations =
|
||||
Arc::new(RwLock::new(PropertyDeclarationBlock {
|
||||
declarations: vec![
|
||||
(PropertyDeclaration::Width(
|
||||
DeclaredValue::Value(LengthOrPercentageOrAuto::Length(NoCalcLength::from_px(20f32)))),
|
||||
Importance::Normal),
|
||||
|
||||
(PropertyDeclaration::Height(
|
||||
DeclaredValue::Value(LengthOrPercentageOrAuto::Length(NoCalcLength::from_px(20f32)))),
|
||||
Importance::Normal),
|
||||
],
|
||||
important_count: 0,
|
||||
}));
|
||||
|
||||
let keyframes = vec![
|
||||
Arc::new(RwLock::new(Keyframe {
|
||||
selector: KeyframeSelector::new_for_unit_testing(vec![KeyframePercentage::new(0.)]),
|
||||
block: Arc::new(RwLock::new(PropertyDeclarationBlock {
|
||||
declarations: vec![],
|
||||
important_count: 0,
|
||||
}))
|
||||
})),
|
||||
Arc::new(RwLock::new(Keyframe {
|
||||
selector: KeyframeSelector::new_for_unit_testing(vec![KeyframePercentage::new(0.5)]),
|
||||
block: declarations.clone(),
|
||||
})),
|
||||
];
|
||||
let animation = KeyframesAnimation::from_keyframes(&keyframes);
|
||||
let expected = KeyframesAnimation {
|
||||
steps: vec![
|
||||
KeyframesStep {
|
||||
start_percentage: KeyframePercentage(0.),
|
||||
value: KeyframesStepValue::Declarations {
|
||||
block: Arc::new(RwLock::new(PropertyDeclarationBlock {
|
||||
// XXX: Should we use ComputedValues in this case?
|
||||
declarations: vec![],
|
||||
important_count: 0,
|
||||
}))
|
||||
},
|
||||
declared_timing_function: false,
|
||||
},
|
||||
KeyframesStep {
|
||||
start_percentage: KeyframePercentage(0.5),
|
||||
value: KeyframesStepValue::Declarations { block: declarations },
|
||||
declared_timing_function: false,
|
||||
},
|
||||
KeyframesStep {
|
||||
start_percentage: KeyframePercentage(1.),
|
||||
value: KeyframesStepValue::ComputedValues,
|
||||
declared_timing_function: false,
|
||||
}
|
||||
],
|
||||
properties_changed: vec![TransitionProperty::Width, TransitionProperty::Height],
|
||||
};
|
||||
|
||||
assert_eq!(format!("{:#?}", animation), format!("{:#?}", expected));
|
||||
}
|
||||
|
|
|
@ -22,6 +22,8 @@ from mach.decorators import (
|
|||
|
||||
from mozbuild.base import MachCommandBase
|
||||
|
||||
ARTIFACT_URL = 'https://queue.taskcluster.net/v1/task/{}/artifacts/{}'
|
||||
|
||||
|
||||
class ShowTaskGraphSubCommand(SubCommand):
|
||||
"""A SubCommand with TaskGraph-specific arguments"""
|
||||
|
|
|
@ -1,7 +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/.
|
||||
|
||||
import os
|
||||
|
||||
GECKO = os.path.realpath(os.path.join(__file__, '..', '..', '..'))
|
|
@ -6,17 +6,18 @@
|
|||
|
||||
from __future__ import absolute_import, print_function, unicode_literals
|
||||
|
||||
import json
|
||||
import logging
|
||||
import requests
|
||||
import yaml
|
||||
|
||||
from .create import create_tasks
|
||||
from .decision import write_artifact
|
||||
from .optimize import optimize_task_graph
|
||||
from .taskgraph import TaskGraph
|
||||
from .util.taskcluster import get_artifact
|
||||
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
TASKCLUSTER_QUEUE_URL = "https://queue.taskcluster.net/v1/task"
|
||||
TREEHERDER_URL = "https://treeherder.mozilla.org/api"
|
||||
|
||||
# We set this to 5 for now because this is what SETA sets the
|
||||
|
@ -62,6 +63,15 @@ def add_tasks(decision_task_id, task_labels, prefix=''):
|
|||
create_tasks(optimized_graph, label_to_taskid, decision_params)
|
||||
|
||||
|
||||
def get_artifact(task_id, path):
|
||||
resp = requests.get(url="{}/{}/artifacts/{}".format(TASKCLUSTER_QUEUE_URL, task_id, path))
|
||||
if path.endswith('.json'):
|
||||
artifact = json.loads(resp.text)
|
||||
elif path.endswith('.yml'):
|
||||
artifact = yaml.load(resp.text)
|
||||
return artifact
|
||||
|
||||
|
||||
def backfill(project, job_id):
|
||||
"""
|
||||
Run the backfill task. This function implements `mach taskgraph backfill-task`,
|
||||
|
|
|
@ -21,7 +21,6 @@ from .util import (
|
|||
calculate_head_rev
|
||||
)
|
||||
from ..create import create_task
|
||||
from .. import GECKO
|
||||
from taskgraph.util.attributes import match_run_on_projects
|
||||
from taskgraph.util.schema import resolve_keyed_by
|
||||
|
||||
|
@ -33,6 +32,7 @@ JOB_TYPES = {
|
|||
'decision-task': decision.run_decision_task,
|
||||
}
|
||||
|
||||
GECKO = os.path.realpath(os.path.join(__file__, '..', '..', '..', '..'))
|
||||
logger = logging.getLogger(__name__)
|
||||
_session = None
|
||||
|
||||
|
|
|
@ -18,7 +18,6 @@ from .create import create_tasks
|
|||
from .parameters import Parameters
|
||||
from .taskgraph import TaskGraph
|
||||
from actions import render_actions_json
|
||||
from . import GECKO
|
||||
|
||||
from taskgraph.util.templates import Templates
|
||||
from taskgraph.util.time import (
|
||||
|
@ -29,6 +28,7 @@ from taskgraph.util.time import (
|
|||
logger = logging.getLogger(__name__)
|
||||
|
||||
ARTIFACTS_DIR = 'artifacts'
|
||||
GECKO = os.path.realpath(os.path.join(__file__, '..', '..', '..'))
|
||||
|
||||
# For each project, this gives a set of parameters specific to the project.
|
||||
# See `taskcluster/docs/parameters.rst` for information on parameters.
|
||||
|
|
|
@ -12,32 +12,31 @@ import sys
|
|||
import subprocess
|
||||
import tarfile
|
||||
import tempfile
|
||||
import urllib2
|
||||
import which
|
||||
from subprocess import Popen, PIPE
|
||||
from io import BytesIO
|
||||
|
||||
from taskgraph.util import docker
|
||||
from taskgraph.util.taskcluster import (
|
||||
find_task_id,
|
||||
get_artifact_url,
|
||||
)
|
||||
from . import GECKO
|
||||
|
||||
DOCKER_INDEX = docker.INDEX_PREFIX + '.{}.{}.hash.{}'
|
||||
GECKO = os.path.realpath(os.path.join(__file__, '..', '..', '..'))
|
||||
INDEX_URL = 'https://index.taskcluster.net/v1/task/' + docker.INDEX_PREFIX + '.{}.{}.hash.{}'
|
||||
ARTIFACT_URL = 'https://queue.taskcluster.net/v1/task/{}/artifacts/{}'
|
||||
|
||||
|
||||
def load_image_by_name(image_name, tag=None):
|
||||
context_path = os.path.join(GECKO, 'taskcluster', 'docker', image_name)
|
||||
context_hash = docker.generate_context_hash(GECKO, context_path, image_name)
|
||||
|
||||
index_path = DOCKER_INDEX.format('level-3', image_name, context_hash)
|
||||
task_id = find_task_id(index_path)
|
||||
image_index_url = INDEX_URL.format('level-3', image_name, context_hash)
|
||||
print("Fetching", image_index_url)
|
||||
task = json.load(urllib2.urlopen(image_index_url))
|
||||
|
||||
return load_image_by_task_id(task_id, tag)
|
||||
return load_image_by_task_id(task['taskId'], tag)
|
||||
|
||||
|
||||
def load_image_by_task_id(task_id, tag=None):
|
||||
artifact_url = get_artifact_url(task_id, 'public/image.tar.zst')
|
||||
artifact_url = ARTIFACT_URL.format(task_id, 'public/image.tar.zst')
|
||||
result = load_image(artifact_url, tag)
|
||||
print("Found docker image: {}:{}".format(result['image'], result['tag']))
|
||||
if tag:
|
||||
|
|
|
@ -5,6 +5,7 @@
|
|||
from __future__ import absolute_import, unicode_literals
|
||||
|
||||
import logging
|
||||
import os
|
||||
|
||||
from . import (
|
||||
target_tasks,
|
||||
|
@ -12,6 +13,8 @@ from . import (
|
|||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
GECKO = os.path.realpath(os.path.join(os.path.dirname(__file__), '..', '..'))
|
||||
|
||||
filter_task_functions = {}
|
||||
|
||||
|
||||
|
|
|
@ -62,7 +62,9 @@ def load_parameters_file(options):
|
|||
Load parameters from the --parameters option
|
||||
"""
|
||||
import urllib
|
||||
from taskgraph.util.taskcluster import get_artifact_url
|
||||
|
||||
url_prefix = "https://queue.taskcluster.net/v1/task/"
|
||||
url_postfix = "/artifacts/public/parameters.yml"
|
||||
|
||||
filename = options['parameters']
|
||||
|
||||
|
@ -76,7 +78,7 @@ def load_parameters_file(options):
|
|||
# fetching parameters.yml using task task-id or supplied url
|
||||
if filename.startswith("task-id="):
|
||||
task_id = filename.split("=")[1]
|
||||
filename = get_artifact_url(task_id, 'public/parameters.yml')
|
||||
filename = url_prefix + task_id + url_postfix
|
||||
f = urllib.urlopen(filename)
|
||||
|
||||
if filename.endswith('.yml'):
|
||||
|
|
Некоторые файлы не были показаны из-за слишком большого количества измененных файлов Показать больше
Загрузка…
Ссылка в новой задаче