Merge mozilla-central to mozilla-inbound on a CLOSED TREE

This commit is contained in:
Andreea Pavel 2019-07-13 00:57:12 +03:00
Родитель c0c614ea67 3fed932eaa
Коммит edf80a9c6c
240 изменённых файлов: 62705 добавлений и 3483 удалений

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

@ -198,3 +198,7 @@ tps_result\.json
# Ignore the build directories of WebRender standalone builds.
gfx/wr/target/
# Ignore this files in certviewer
toolkit/components/certviewer/content/node_modules/
toolkit/components/certviewer/content/package-lock.json

65
Cargo.lock сгенерированный
Просмотреть файл

@ -106,7 +106,7 @@ dependencies = [
"mio-named-pipes 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)",
"scoped-tls 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
"serde 1.0.88 (registry+https://github.com/rust-lang/crates.io-index)",
"serde_derive 1.0.88 (git+https://github.com/servo/serde?branch=deserialize_from_enums10)",
"serde_derive 1.0.88 (registry+https://github.com/rust-lang/crates.io-index)",
"tokio-core 0.1.17 (registry+https://github.com/rust-lang/crates.io-index)",
"tokio-io 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)",
"tokio-uds 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)",
@ -315,7 +315,7 @@ dependencies = [
"filetime_win 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
"guid_win 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
"serde 1.0.88 (registry+https://github.com/rust-lang/crates.io-index)",
"serde_derive 1.0.88 (git+https://github.com/servo/serde?branch=deserialize_from_enums10)",
"serde_derive 1.0.88 (registry+https://github.com/rust-lang/crates.io-index)",
"winapi 0.3.6 (git+https://github.com/froydnj/winapi-rs?branch=aarch64)",
]
@ -976,7 +976,7 @@ dependencies = [
"lazy_static 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
"libc 0.2.51 (registry+https://github.com/rust-lang/crates.io-index)",
"serde 1.0.88 (registry+https://github.com/rust-lang/crates.io-index)",
"serde_derive 1.0.88 (git+https://github.com/servo/serde?branch=deserialize_from_enums10)",
"serde_derive 1.0.88 (registry+https://github.com/rust-lang/crates.io-index)",
"winapi 0.3.6 (git+https://github.com/froydnj/winapi-rs?branch=aarch64)",
]
@ -1030,7 +1030,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "euclid"
version = "0.19.5"
version = "0.19.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"euclid_macros 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
@ -1183,7 +1183,7 @@ dependencies = [
"mozversion 0.2.0",
"regex 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)",
"serde 1.0.88 (registry+https://github.com/rust-lang/crates.io-index)",
"serde_derive 1.0.88 (git+https://github.com/servo/serde?branch=deserialize_from_enums10)",
"serde_derive 1.0.88 (registry+https://github.com/rust-lang/crates.io-index)",
"serde_json 1.0.26 (registry+https://github.com/rust-lang/crates.io-index)",
"uuid 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)",
"webdriver 0.39.0",
@ -1715,7 +1715,7 @@ version = "0.0.1"
dependencies = [
"app_units 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)",
"cssparser 0.25.7 (registry+https://github.com/rust-lang/crates.io-index)",
"euclid 0.19.5 (registry+https://github.com/rust-lang/crates.io-index)",
"euclid 0.19.9 (registry+https://github.com/rust-lang/crates.io-index)",
"hashglobe 0.1.0",
"selectors 0.21.0",
"servo_arc 0.1.1",
@ -1911,7 +1911,7 @@ dependencies = [
"proc-macro2 0.4.27 (registry+https://github.com/rust-lang/crates.io-index)",
"quote 0.6.11 (registry+https://github.com/rust-lang/crates.io-index)",
"serde 1.0.88 (registry+https://github.com/rust-lang/crates.io-index)",
"serde_derive 1.0.88 (git+https://github.com/servo/serde?branch=deserialize_from_enums10)",
"serde_derive 1.0.88 (registry+https://github.com/rust-lang/crates.io-index)",
"syn 0.15.30 (registry+https://github.com/rust-lang/crates.io-index)",
"void 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)",
"winapi 0.3.6 (git+https://github.com/froydnj/winapi-rs?branch=aarch64)",
@ -2191,6 +2191,25 @@ dependencies = [
"winapi 0.3.6 (git+https://github.com/froydnj/winapi-rs?branch=aarch64)",
]
[[package]]
name = "peek-poke"
version = "0.2.0"
dependencies = [
"euclid 0.19.9 (registry+https://github.com/rust-lang/crates.io-index)",
"peek-poke-derive 0.2.0",
]
[[package]]
name = "peek-poke-derive"
version = "0.2.0"
dependencies = [
"proc-macro2 0.4.27 (registry+https://github.com/rust-lang/crates.io-index)",
"quote 0.6.11 (registry+https://github.com/rust-lang/crates.io-index)",
"syn 0.15.30 (registry+https://github.com/rust-lang/crates.io-index)",
"synstructure 0.10.1 (registry+https://github.com/rust-lang/crates.io-index)",
"unicode-xid 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "peeking_take_while"
version = "0.1.2"
@ -2252,7 +2271,7 @@ version = "0.13.8"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"binary-space-partition 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
"euclid 0.19.5 (registry+https://github.com/rust-lang/crates.io-index)",
"euclid 0.19.9 (registry+https://github.com/rust-lang/crates.io-index)",
"log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)",
"num-traits 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)",
]
@ -2573,7 +2592,7 @@ dependencies = [
"lmdb-rkv 0.11.4 (registry+https://github.com/rust-lang/crates.io-index)",
"ordered-float 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)",
"serde 1.0.88 (registry+https://github.com/rust-lang/crates.io-index)",
"serde_derive 1.0.88 (git+https://github.com/servo/serde?branch=deserialize_from_enums10)",
"serde_derive 1.0.88 (registry+https://github.com/rust-lang/crates.io-index)",
"url 1.7.2 (registry+https://github.com/rust-lang/crates.io-index)",
"uuid 0.7.4 (registry+https://github.com/rust-lang/crates.io-index)",
]
@ -2740,7 +2759,7 @@ name = "serde"
version = "1.0.88"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"serde_derive 1.0.88 (git+https://github.com/servo/serde?branch=deserialize_from_enums10)",
"serde_derive 1.0.88 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
@ -2754,7 +2773,7 @@ dependencies = [
[[package]]
name = "serde_derive"
version = "1.0.88"
source = "git+https://github.com/servo/serde?branch=deserialize_from_enums10#84b2795d2a7b5312125a99b1ef11c67fd8d17c35"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"proc-macro2 0.4.27 (registry+https://github.com/rust-lang/crates.io-index)",
"quote 0.6.11 (registry+https://github.com/rust-lang/crates.io-index)",
@ -2926,7 +2945,7 @@ dependencies = [
"byteorder 1.3.1 (registry+https://github.com/rust-lang/crates.io-index)",
"cssparser 0.25.7 (registry+https://github.com/rust-lang/crates.io-index)",
"derive_more 0.13.0 (registry+https://github.com/rust-lang/crates.io-index)",
"euclid 0.19.5 (registry+https://github.com/rust-lang/crates.io-index)",
"euclid 0.19.9 (registry+https://github.com/rust-lang/crates.io-index)",
"fallible 0.0.1",
"fxhash 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
"hashglobe 0.1.0",
@ -2987,7 +3006,7 @@ dependencies = [
"app_units 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)",
"bitflags 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)",
"cssparser 0.25.7 (registry+https://github.com/rust-lang/crates.io-index)",
"euclid 0.19.5 (registry+https://github.com/rust-lang/crates.io-index)",
"euclid 0.19.9 (registry+https://github.com/rust-lang/crates.io-index)",
"lazy_static 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
"malloc_size_of 0.0.1",
"malloc_size_of_derive 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
@ -3575,7 +3594,7 @@ dependencies = [
"log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)",
"regex 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)",
"serde 1.0.88 (registry+https://github.com/rust-lang/crates.io-index)",
"serde_derive 1.0.88 (git+https://github.com/servo/serde?branch=deserialize_from_enums10)",
"serde_derive 1.0.88 (registry+https://github.com/rust-lang/crates.io-index)",
"serde_json 1.0.26 (registry+https://github.com/rust-lang/crates.io-index)",
"time 0.1.40 (registry+https://github.com/rust-lang/crates.io-index)",
"tokio 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)",
@ -3598,7 +3617,7 @@ dependencies = [
"core-text 13.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
"cstr 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)",
"dwrote 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)",
"euclid 0.19.5 (registry+https://github.com/rust-lang/crates.io-index)",
"euclid 0.19.9 (registry+https://github.com/rust-lang/crates.io-index)",
"freetype 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
"fxhash 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
"gleam 0.6.17 (registry+https://github.com/rust-lang/crates.io-index)",
@ -3629,17 +3648,17 @@ name = "webrender_api"
version = "0.60.0"
dependencies = [
"app_units 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)",
"bincode 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
"bitflags 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)",
"byteorder 1.3.1 (registry+https://github.com/rust-lang/crates.io-index)",
"core-foundation 0.6.3 (registry+https://github.com/rust-lang/crates.io-index)",
"core-graphics 0.17.1 (registry+https://github.com/rust-lang/crates.io-index)",
"derive_more 0.13.0 (registry+https://github.com/rust-lang/crates.io-index)",
"euclid 0.19.5 (registry+https://github.com/rust-lang/crates.io-index)",
"euclid 0.19.9 (registry+https://github.com/rust-lang/crates.io-index)",
"malloc_size_of_derive 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
"peek-poke 0.2.0",
"serde 1.0.88 (registry+https://github.com/rust-lang/crates.io-index)",
"serde_bytes 0.10.4 (registry+https://github.com/rust-lang/crates.io-index)",
"serde_derive 1.0.88 (git+https://github.com/servo/serde?branch=deserialize_from_enums10)",
"serde_derive 1.0.88 (registry+https://github.com/rust-lang/crates.io-index)",
"time 0.1.40 (registry+https://github.com/rust-lang/crates.io-index)",
"wr_malloc_size_of 0.0.1",
]
@ -3653,7 +3672,7 @@ dependencies = [
"core-foundation 0.6.3 (registry+https://github.com/rust-lang/crates.io-index)",
"core-graphics 0.17.1 (registry+https://github.com/rust-lang/crates.io-index)",
"dwrote 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)",
"euclid 0.19.5 (registry+https://github.com/rust-lang/crates.io-index)",
"euclid 0.19.9 (registry+https://github.com/rust-lang/crates.io-index)",
"foreign-types 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)",
"fxhash 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
"gleam 0.6.17 (registry+https://github.com/rust-lang/crates.io-index)",
@ -3680,7 +3699,7 @@ version = "0.1.0"
dependencies = [
"log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)",
"serde 1.0.88 (registry+https://github.com/rust-lang/crates.io-index)",
"serde_derive 1.0.88 (git+https://github.com/servo/serde?branch=deserialize_from_enums10)",
"serde_derive 1.0.88 (registry+https://github.com/rust-lang/crates.io-index)",
"serde_json 1.0.26 (registry+https://github.com/rust-lang/crates.io-index)",
]
@ -3750,7 +3769,7 @@ name = "wr_malloc_size_of"
version = "0.0.1"
dependencies = [
"app_units 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)",
"euclid 0.19.5 (registry+https://github.com/rust-lang/crates.io-index)",
"euclid 0.19.9 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
@ -3948,7 +3967,7 @@ dependencies = [
"checksum encoding_rs 0.8.17 (registry+https://github.com/rust-lang/crates.io-index)" = "4155785c79f2f6701f185eb2e6b4caf0555ec03477cb4c70db67b465311620ed"
"checksum env_logger 0.5.6 (registry+https://github.com/rust-lang/crates.io-index)" = "0561146661ae44c579e993456bc76d11ce1e0c7d745e57b2fa7146b6e49fa2ad"
"checksum error-chain 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ff511d5dc435d703f4971bc399647c9bc38e20cb41452e3b9feb4765419ed3f3"
"checksum euclid 0.19.5 (registry+https://github.com/rust-lang/crates.io-index)" = "d1a7698bdda3d7444a79d33bdc96e8b518d44ea3ff101d8492a6ca1207b886ea"
"checksum euclid 0.19.9 (registry+https://github.com/rust-lang/crates.io-index)" = "596b99621b9477e7a5f94d2d8dd13a9c5c302ac358b822c67a42b6f1054450e1"
"checksum euclid_macros 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "fdcb84c18ea5037a1c5a23039b4ff29403abce2e0d6b1daa11cf0bde2b30be15"
"checksum failure 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "6dd377bcc1b1b7ce911967e3ec24fa19c3224394ec05b54aa7b083d498341ac7"
"checksum failure_derive 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "64c2d913fe8ed3b6c6518eedf4538255b989945c14c2a7d5cbff62a5e2120596"
@ -4107,7 +4126,7 @@ dependencies = [
"checksum semver-parser 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "388a1df253eca08550bef6c72392cfe7c30914bf41df5269b68cbd6ff8f570a3"
"checksum serde 1.0.88 (registry+https://github.com/rust-lang/crates.io-index)" = "9f301d728f2b94c9a7691c90f07b0b4e8a4517181d9461be94c04bddeb4bd850"
"checksum serde_bytes 0.10.4 (registry+https://github.com/rust-lang/crates.io-index)" = "adb6e51a6b3696b301bc221d785f898b4457c619b51d7ce195a6d20baecb37b3"
"checksum serde_derive 1.0.88 (git+https://github.com/servo/serde?branch=deserialize_from_enums10)" = "<none>"
"checksum serde_derive 1.0.88 (registry+https://github.com/rust-lang/crates.io-index)" = "beed18e6f5175aef3ba670e57c60ef3b1b74d250d962a26604bff4c80e970dd4"
"checksum serde_json 1.0.26 (registry+https://github.com/rust-lang/crates.io-index)" = "44dd2cfde475037451fa99b7e5df77aa3cfd1536575fa8e7a538ab36dcde49ae"
"checksum serde_repr 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)" = "29a734c298df0346c4cd5919595981c266dabbf12dc747c85e1a95e96077a52b"
"checksum serde_urlencoded 0.5.5 (registry+https://github.com/rust-lang/crates.io-index)" = "642dd69105886af2efd227f75a520ec9b44a820d65bc133a9131f7d229fd165a"

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

@ -58,7 +58,6 @@ codegen-units = 1
[patch.crates-io]
libudev-sys = { path = "dom/webauthn/libudev-sys" }
serde_derive = { git = "https://github.com/servo/serde", branch = "deserialize_from_enums10" }
winapi = { git = "https://github.com/froydnj/winapi-rs", branch = "aarch64" }
packed_simd = { git = "https://github.com/hsivonen/packed_simd", branch = "rust_1_32" }

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

@ -1229,10 +1229,5 @@ class PluginChild extends ActorChild {
messageString,
pluginID,
});
// Remove the notification when the page is reloaded.
doc.defaultView.top.addEventListener("unload", event => {
this.hideNotificationBar("plugin-crashed");
});
}
}

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

@ -8944,58 +8944,39 @@ var gPrivateBrowsingUI = {
// temporary fix until bug 463607 is fixed
document.getElementById("Tools:Sanitize").setAttribute("disabled", "true");
if (window.location.href == AppConstants.BROWSER_CHROME_URL) {
// Adjust the window's title
let docElement = document.documentElement;
if (!PrivateBrowsingUtils.permanentPrivateBrowsing) {
docElement.setAttribute(
"title",
docElement.getAttribute("title_privatebrowsing")
);
docElement.setAttribute(
"titlemodifier",
docElement.getAttribute("titlemodifier_privatebrowsing")
);
}
if (window.location.href != AppConstants.BROWSER_CHROME_URL) {
return;
}
// Adjust the window's title
let docElement = document.documentElement;
if (!PrivateBrowsingUtils.permanentPrivateBrowsing) {
docElement.setAttribute(
"privatebrowsingmode",
PrivateBrowsingUtils.permanentPrivateBrowsing
? "permanent"
: "temporary"
"title",
docElement.getAttribute("title_privatebrowsing")
);
gBrowser.updateTitlebar();
docElement.setAttribute(
"titlemodifier",
docElement.getAttribute("titlemodifier_privatebrowsing")
);
}
docElement.setAttribute(
"privatebrowsingmode",
PrivateBrowsingUtils.permanentPrivateBrowsing ? "permanent" : "temporary"
);
gBrowser.updateTitlebar();
if (PrivateBrowsingUtils.permanentPrivateBrowsing) {
// Adjust the New Window menu entries
[
{ normal: "menu_newNavigator", private: "menu_newPrivateWindow" },
].forEach(function(menu) {
let newWindow = document.getElementById(menu.normal);
let newPrivateWindow = document.getElementById(menu.private);
if (newWindow && newPrivateWindow) {
newPrivateWindow.hidden = true;
newWindow.label = newPrivateWindow.label;
newWindow.accessKey = newPrivateWindow.accessKey;
newWindow.command = newPrivateWindow.command;
}
});
if (PrivateBrowsingUtils.permanentPrivateBrowsing) {
// Adjust the New Window menu entries
let newWindow = document.getElementById("menu_newNavigator");
let newPrivateWindow = document.getElementById("menu_newPrivateWindow");
if (newWindow && newPrivateWindow) {
newPrivateWindow.hidden = true;
newWindow.label = newPrivateWindow.label;
newWindow.accessKey = newPrivateWindow.accessKey;
newWindow.command = newPrivateWindow.command;
}
}
let urlBarSearchParam =
gURLBar.getAttribute("autocompletesearchparam") || "";
if (
!PrivateBrowsingUtils.permanentPrivateBrowsing &&
!urlBarSearchParam.includes("disable-private-actions")
) {
// Disable switch to tab autocompletion for private windows.
// We leave it enabled for permanent private browsing mode though.
urlBarSearchParam += " disable-private-actions";
}
if (!urlBarSearchParam.includes("private-window")) {
urlBarSearchParam += " private-window";
}
gURLBar.setAttribute("autocompletesearchparam", urlBarSearchParam);
},
};

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

@ -20,6 +20,8 @@ const kESModuleList = new Set([
/browser\/aboutlogins\/.*\.js$/,
/browser\/protections.js$/,
/browser\/lockwise-card.js$/,
/toolkit\/content\/global\/certviewer\/components\/.*\.js$/,
/toolkit\/content\/global\/certviewer\/.*\.js$/,
]);
// Normally we would use reflect.jsm to get Reflect.parse. However, if

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

@ -104,6 +104,7 @@ class UrlbarInput {
this._textValueOnLastSearch = "";
this._resultForCurrentValue = null;
this._suppressStartQuery = false;
this._suppressPrimaryAdjustment = false;
this._untrimmedValue = "";
// This exists only for tests.
@ -118,7 +119,6 @@ class UrlbarInput {
"setAttribute",
"removeAttribute",
"toggleAttribute",
"select",
];
const READ_ONLY_PROPERTIES = ["inputField", "editor"];
const READ_WRITE_PROPERTIES = [
@ -308,6 +308,14 @@ class UrlbarInput {
this.inputField.blur();
}
select() {
// See _on_select(). HTMLInputElement.select() dispatches a "select"
// event but does not set the primary selection.
this._suppressPrimaryAdjustment = true;
this.inputField.select();
this._suppressPrimaryAdjustment = false;
}
/**
* Converts an internal URI (e.g. a URI with a username or password) into one
* which we can expose to the user.
@ -1551,7 +1559,22 @@ class UrlbarInput {
}
_on_select(event) {
// On certain user input, AutoCopyListener::OnSelectionChange() updates
// the primary selection with user-selected text (when supported).
// Selection::NotifySelectionListeners() then dispatches a "select" event
// under similar conditions via TextInputListener::OnSelectionChange().
// This event is received here in order to replace the primary selection
// from the editor with text having the adjustments of
// _getSelectedValueForClipboard(), such as adding the scheme for the url.
//
// Other "select" events are also received, however, and must be excluded.
if (
// _suppressPrimaryAdjustment is set during select(). Don't update
// the primary selection because that is not the intent of user input,
// which may be new tab or urlbar focus.
this._suppressPrimaryAdjustment ||
// The check on isHandlingUserInput filters out async "select" events
// from setSelectionRange(), which occur when autofill text is selected.
!this.window.windowUtils.isHandlingUserInput ||
!Services.clipboard.supportsSelectionClipboard()
) {

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

@ -72,6 +72,7 @@ skip-if = (os == 'mac' && os_version == '10.14') # bug 1554807
tags = clipboard
[browser_percent_encoded.js]
[browser_populateAfterPushState.js]
[browser_primary_selection_safe_on_new_tab.js]
[browser_privateBrowsingWindowChange.js]
[browser_raceWithTabs.js]
skip-if = os == "linux" # Bug 1533807

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

@ -0,0 +1,74 @@
/* Any copyright is dedicated to the Public Domain.
* http://creativecommons.org/publicdomain/zero/1.0/ */
/**
* Verify that the primary selection is unaffected by opening a new tab.
*
* The steps here follow STR for regression
* https://bugzilla.mozilla.org/show_bug.cgi?id=1457355.
*/
"use strict";
let tabs = [];
let supportsPrimary = Services.clipboard.supportsSelectionClipboard();
let ClipboardHelper = Cc["@mozilla.org/widget/clipboardhelper;1"].getService(
Ci.nsIClipboardHelper
);
const NON_EMPTY_URL = "data:text/html,Hello";
const TEXT_FOR_PRIMARY = "Text for PRIMARY selection";
add_task(async function() {
tabs.push(
await BrowserTestUtils.openNewForegroundTab(gBrowser, NON_EMPTY_URL)
);
// Bug 1457355 reproduced only when the url had a non-empty selection.
gURLBar.select();
Assert.equal(gURLBar.inputField.selectionStart, 0);
Assert.equal(
gURLBar.inputField.selectionEnd,
gURLBar.inputField.value.length
);
if (supportsPrimary) {
ClipboardHelper.copyStringToClipboard(
TEXT_FOR_PRIMARY,
Services.clipboard.kSelectionClipboard
);
}
tabs.push(
await BrowserTestUtils.openNewForegroundTab({
gBrowser,
opening: () => {
// Simulate tab open from user input such as keyboard shortcut or new
// tab button.
let userInput = window.windowUtils.setHandlingUserInput(true);
try {
BrowserOpenTab();
} finally {
userInput.destruct();
}
},
waitForLoad: false,
})
);
if (!supportsPrimary) {
info("Primary selection not supported. Skipping assertion.");
return;
}
let primaryAsText = SpecialPowers.getClipboardData(
"text/unicode",
SpecialPowers.Ci.nsIClipboard.kSelectionClipboard
);
Assert.equal(primaryAsText, TEXT_FOR_PRIMARY);
});
registerCleanupFunction(() => {
for (let tab of tabs) {
BrowserTestUtils.removeTab(tab);
}
});

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

@ -11,7 +11,7 @@
}
.deleteOptions {
border: thin solid lightgray;
border: 1px solid var(--in-content-box-border-color);
padding: 1em;
}
@ -20,7 +20,7 @@
}
.deleteData {
color: gray;
color: var(--in-content-deemphasized-text);
}
.disconnectThrobber {

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

@ -2,11 +2,23 @@
* 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/. */
/*
* Global styles
*/
@import "resource://devtools/client/application/src/base.css";
/*
* Components
*/
@import "resource://devtools/client/application/src/components/App.css";
@import "resource://devtools/client/application/src/components/Worker.css";
@import "resource://devtools/client/application/src/components/WorkerList.css";
@import "resource://devtools/client/application/src/components/WorkerListEmpty.css";
/*
* Reset
*/
* {
box-sizing: border-box;
}

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

@ -0,0 +1,61 @@
/* 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/. */
:root {
/* Typography from Photon */
/* See https://firefox-dev.tools/photon/visuals/typography.html */
--body-10-font-size: 13px;
--body-10-font-weight: 400;
--body-20-font-size: 15px;
--body-20-font-weight: 400;
--body-20-font-weight-bold: 700;
--title-20-font-size: 17px;
--title-20-font-weight: 600;
--title-30-font-size: 22px;
--title-30-font-weight: 300;
/* Global styles */
--base-font-size: var(--body-10-font-size);
--base-font-weight: var(--body-10-font-weight);
--base-line-height: 1.8;
--list-line-height: 1.25;
/* Global colours */
--bg-color: var(--grey-10);
--text-color: var(--grey-90);
/* Global layout vars */
--base-unit: 4px;
}
/*
* Reset some tags
*/
body {
margin: 0;
padding: 0;
line-height: var(--base-line-height);
}
ul {
line-height: var(--list-line-height);
}
a {
color: var(--theme-highlight-blue);
text-decoration: none;
cursor: pointer;
}
h1,
.application--title {
font-size: var(--title-30-font-size);
font-weight: var(--title-30-font-weight);
line-height: var(--base-line-height);
}
p {
margin: 0;
}

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

@ -6,26 +6,10 @@
* General styles
*/
h1 {
font-size: 22px;
font-weight: normal;
}
a {
margin: 0 10px;
}
a,
a:hover,
a:visited {
color: var(--theme-highlight-blue) !important;
cursor: pointer;
}
a.disabled-link,
a.disabled-link:hover,
a.disabled-link:visited {
opacity: 0.5 !important;
opacity: 0.5;
cursor: not-allowed;
}

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

@ -22,9 +22,8 @@
width: 100%;
grid-column-gap: 0;
padding: 1rem 0;
line-height: 1.5;
font-size: 1.2rem;
font-size: var(--body-10-font-size);
}
.worker:first-child {
@ -73,3 +72,8 @@
.worker__data__updated {
color: var(--theme-text-color-alt);
}
.worker__link-start,
.worker__link-debug {
margin: 0 calc(var(--base-unit) * 2);
}

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

@ -154,7 +154,7 @@ class Worker extends Component {
},
a({
onClick: !shallDisableLink ? this.debug : null,
className: `${linkClass} worker__debug-link js-debug-link`,
className: `${linkClass} worker__link-debug js-link-debug`,
})
);
return link;
@ -174,7 +174,7 @@ class Worker extends Component {
},
a({
onClick: this.start,
className: `worker__start-link js-start-link ${linkClass}`,
className: `worker__link-start js-link-start ${linkClass}`,
})
);
return link;

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

@ -42,7 +42,12 @@ class WorkerList extends Component {
return [
article(
{ className: "workers-container" },
Localized({ id: "serviceworker-list-header" }, h1({})),
Localized(
{ id: "serviceworker-list-header" },
h1({
className: "application--title",
})
),
ul(
{},
workers.map(worker =>
@ -56,7 +61,7 @@ class WorkerList extends Component {
),
Localized(
{
id: "serviceworker-list-aboutdebugging2",
id: "serviceworker-list-aboutdebugging",
a: a({
className: "aboutdebugging-plug__link",
onClick: () => openTrustedLink("about:debugging#workers"),

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

@ -3,16 +3,20 @@
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
.worker-list-empty {
max-width: 65rem;
font-size: 1.2rem;
line-height: 1.25;
max-width: calc(var(--base-unit) * 179);
font-size: var(--body-10-font-size);
color: var(--theme-toolbar-color);
}
.worker-list-empty__title {
font-size: 1.4rem;
font-size: var(--title-20-font-size);
font-weight: var(--title-20-font-weight);
}
.worker-list-empty__title .external-link {
font-weight: var(--title-30-font-weight);
}
.worker-list-empty__tips {
margin-inline-start: 2rem;
}
@ -20,4 +24,4 @@
.worker-list-empty__tips__item {
margin-block-start: 0.5rem;
margin-block-end: 0.5rem;
}
}

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

@ -13,7 +13,6 @@ const {
const {
a,
article,
h1,
li,
p,
ul,
@ -64,7 +63,7 @@ class WorkerListEmpty extends Component {
onClick: () => this.openDocumentation(),
}),
},
h1({ className: "worker-list-empty__title" })
p({ className: "worker-list-empty__title" })
),
Localized({ id: "serviceworker-empty-suggestions" }, p({})),
ul(

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

@ -10,6 +10,7 @@ DIRS += [
]
DevToolsModules(
'base.css',
'constants.js',
'create-store.js',
)

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

@ -29,13 +29,13 @@ add_task(async function() {
const container = getWorkerContainers(doc)[0];
info("Wait until the debug link is displayed and enabled");
await waitUntil(() =>
container.querySelector(".js-debug-link:not(.worker__debug-link--disabled)")
container.querySelector(".js-link-debug:not(.worker__debug-link--disabled)")
);
info("Click on the debug link and wait for the new toolbox to be ready");
const onToolboxReady = gDevTools.once("toolbox-ready");
const debugLink = container.querySelector(".js-debug-link");
const debugLink = container.querySelector(".js-link-debug");
debugLink.click();
const serviceWorkerToolbox = await onToolboxReady;

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

@ -29,10 +29,10 @@ add_task(async function() {
info("Wait until the start link is displayed and enabled");
const container = getWorkerContainers(doc)[0];
await waitUntil(() =>
container.querySelector(".js-start-link:not(.disabled-link)")
container.querySelector(".js-link-start:not(.disabled-link)")
);
info("Click the link and wait for the worker to start");
const link = container.querySelector(".js-start-link");
const link = container.querySelector(".js-link-start");
link.click();
await waitUntil(
() => container.querySelector(".js-worker-status").textContent === "Running"
@ -61,9 +61,9 @@ add_task(async function() {
info("Wait until the start link is displayed");
const container = getWorkerContainers(doc)[0];
await waitUntil(() => container.querySelector(".js-start-link"));
await waitUntil(() => container.querySelector(".js-link-start"));
ok(
container.querySelector(".js-start-link.disabled-link"),
container.querySelector(".js-link-start.disabled-link"),
"Start link is disabled"
);

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

@ -803,7 +803,6 @@ skip-if = os == "win"
[browser_dbg-react-app.js]
skip-if = os == "win"
[browser_dbg-wasm-sourcemaps.js]
skip-if = (os == "win") || os == ("linux") && debug # Bug 1561092
[browser_dbg-windowless-workers.js]
[browser_dbg-windowless-workers-early-breakpoint.js]
[browser_dbg-worker-scopes.js]

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

@ -83,22 +83,8 @@ class GridItem extends PureComponent {
this.props.onSetGridOverlayColor(this.props.grid.nodeFront, color);
}
onGridCheckboxClick(e) {
// If the click was on the svg icon to select the node in the inspector, bail out.
const originalTarget =
e.nativeEvent && e.nativeEvent.explicitOriginalTarget;
if (
originalTarget &&
originalTarget.namespaceURI === "http://www.w3.org/2000/svg"
) {
// We should be able to cancel the click event propagation after the following reps
// issue is implemented : https://github.com/firefox-devtools/reps/issues/95 .
e.preventDefault();
return;
}
onGridCheckboxClick() {
const { grid, onToggleGridHighlighter } = this.props;
onToggleGridHighlighter(grid.nodeFront);
}
@ -164,8 +150,11 @@ class GridItem extends PureComponent {
onDOMNodeMouseOut: () => onHideBoxModelHighlighter(),
onDOMNodeMouseOver: () =>
onShowBoxModelHighlighterForNode(grid.nodeFront),
onInspectIconClick: () =>
this.onGridInspectIconClick(grid.nodeFront),
onInspectIconClick: (_, e) => {
// Stoping click propagation to avoid firing onGridCheckboxClick()
e.stopPropagation();
this.onGridInspectIconClick(grid.nodeFront);
},
})
),
dom.div({

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

@ -645,9 +645,9 @@ netmonitor.ws.toolbar.frameType=Type
# in the websocket frame table header, above the "size" column.
netmonitor.ws.toolbar.size=Size
# LOCALIZATION NOTE (netmonitor.ws.toolbar.payload): This is the label displayed
# in the websocket frame table header, above the "payload" column.
netmonitor.ws.toolbar.payload=Payload
# LOCALIZATION NOTE (netmonitor.ws.toolbar.data): This is the label displayed
# in the websocket frame table header, above the "data" column.
netmonitor.ws.toolbar.data=Data
# LOCALIZATION NOTE (netmonitor.ws.toolbar.opCode): This is the label displayed
# in the websocket frame table header, above the "opCode" column.
@ -665,13 +665,49 @@ netmonitor.ws.toolbar.finBit=FinBit
# in the websocket frame table header, above the "time" column.
netmonitor.ws.toolbar.time=Time
# LOCALIZATION NOTE (netmonitor.ws.toolbar.clear): This is the label displayed
# in the websocket toolbar for the "Clear" button.
netmonitor.ws.toolbar.clear=Clear
# LOCALIZATION NOTE (netmonitor.ws.toolbar.filterFreetext.label): This is the label
# displayed in the websocket toolbar for the frames filtering textbox.
netmonitor.ws.toolbar.filterFreetext.label=Filter Messages
# LOCALIZATION NOTE (netmonitor.ws.toolbar.filterFreetext.key): This is the
# shortcut key to focus on the websocket toolbar frames filtering textbox
netmonitor.ws.toolbar.filterFreetext.key=CmdOrCtrl+E
# LOCALIZATION NOTE (netmonitor.ws.context.all): This is the label displayed
# on the context menu that shows "All" WebSocket frames.
netmonitor.ws.context.all=All
# LOCALIZATION NOTE (netmonitor.ws.context.all.accesskey): This is the access key
# for the "All" menu item displayed in the context menu in the websocket toolbar.
netmonitor.ws.context.all.accesskey=A
# LOCALIZATION NOTE (netmonitor.ws.context.sent): This is the label displayed
# on the context menu that shows "Sent" WebSocket frames.
netmonitor.ws.context.sent=Sent
# LOCALIZATION NOTE (netmonitor.ws.context.sent.accesskey): This is the access key
# for the "Sent" menu item displayed in the context menu in the websocket toolbar.
netmonitor.ws.context.sent.accesskey=S
# LOCALIZATION NOTE (netmonitor.ws.context.received): This is the label displayed
# on the context menu that shows "Received" WebSocket frames.
netmonitor.ws.context.received=Received
# LOCALIZATION NOTE (netmonitor.ws.context.received.accesskey): This is the access key
# for the "Received" menu item displayed in the context menu in the websocket toolbar.
netmonitor.ws.context.received.accesskey=R
# LOCALIZATION NOTE (netmonitor.tab.headers): This is the label displayed
# in the network details pane identifying the headers tab.
netmonitor.tab.headers=Headers
# LOCALIZATION NOTE (netmonitor.tab.webSockets): This is the label displayed
# in the network details pane identifying the webSockets tab.
netmonitor.tab.webSockets=WebSockets
# LOCALIZATION NOTE (netmonitor.tab.messages): This is the label displayed
# in the network details pane identifying the messages tab.
netmonitor.tab.messages=Messages
# LOCALIZATION NOTE (netmonitor.tab.cookies): This is the label displayed
# in the network details pane identifying the cookies tab.

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

@ -15,10 +15,11 @@ const PAGE_SIZE_ITEM_COUNT_RATIO = 5;
/**
* Select request with a given id.
*/
function selectRequest(id) {
function selectRequest(id, httpChannelId) {
return {
type: SELECT_REQUEST,
id,
httpChannelId,
};
}

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

@ -8,8 +8,14 @@ const {
WS_ADD_FRAME,
WS_SELECT_FRAME,
WS_OPEN_FRAME_DETAILS,
WS_CLEAR_FRAMES,
WS_TOGGLE_FRAME_FILTER_TYPE,
WS_SET_REQUEST_FILTER_TEXT,
} = require("../constants");
/**
* Add frame into state.
*/
function addFrame(httpChannelId, data) {
return {
type: WS_ADD_FRAME,
@ -41,8 +47,43 @@ function openFrameDetails(open) {
};
}
/**
* Clear all frames from the FrameListContent
* component belonging to the current channelId
*/
function clearFrames() {
return {
type: WS_CLEAR_FRAMES,
};
}
/**
* Show filtered frames from the FrameListContent
* component belonging to the current channelId
*/
function toggleFrameFilterType(filter) {
return {
type: WS_TOGGLE_FRAME_FILTER_TYPE,
filter,
};
}
/**
* Set filter text in toolbar.
*
*/
function setFrameFilterText(text) {
return {
type: WS_SET_REQUEST_FILTER_TEXT,
text,
};
}
module.exports = {
addFrame,
selectFrame,
openFrameDetails,
clearFrames,
toggleFrameFilterType,
setFrameFilterText,
};

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

@ -14,11 +14,6 @@
min-height: var(--primary-toolbar-height);
}
.requests-list-filter-buttons {
white-space: nowrap;
margin: 0 7px;
}
.devtools-button.devtools-pause-icon::before,
.devtools-button.devtools-play-icon::before {
margin-bottom: 1px;

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

@ -232,9 +232,9 @@ class RequestListContent extends Component {
this.tooltip.hide();
}
onMouseDown(evt, id) {
onMouseDown(evt, id, channelId) {
if (evt.button === LEFT_MOUSE_BUTTON) {
this.props.selectRequest(id);
this.props.selectRequest(id, channelId);
} else if (evt.button === RIGHT_MOUSE_BUTTON) {
this.props.onItemRightMouseButtonDown(id);
}
@ -383,7 +383,8 @@ class RequestListContent extends Component {
onContextMenu: this.onContextMenu,
onFocusedNodeChange: this.onFocusedNodeChange,
onDoubleClick: () => this.onDoubleClick(item),
onMouseDown: evt => this.onMouseDown(evt, item.id),
onMouseDown: evt =>
this.onMouseDown(evt, item.id, item.channelId),
onCauseBadgeMouseDown: () => onCauseBadgeMouseDown(item.cause),
onSecurityIconMouseDown: () =>
onSecurityIconMouseDown(item.securityState),
@ -435,7 +436,8 @@ module.exports = connect(
dispatch(Actions.selectDetailsPanelTab("stack-trace"));
}
},
selectRequest: id => dispatch(Actions.selectRequest(id)),
selectRequest: (id, channelId) =>
dispatch(Actions.selectRequest(id, channelId)),
onItemRightMouseButtonDown: id => dispatch(Actions.rightClickRequest(id)),
onItemMouseDown: id => dispatch(Actions.selectRequest(id)),
/**

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

@ -34,7 +34,7 @@ const COLLAPSE_DETAILS_PANE = L10N.getStr("collapseDetailsPane");
const CACHE_TITLE = L10N.getStr("netmonitor.tab.cache");
const COOKIES_TITLE = L10N.getStr("netmonitor.tab.cookies");
const HEADERS_TITLE = L10N.getStr("netmonitor.tab.headers");
const WEBSOCKETS_TITLE = L10N.getStr("netmonitor.tab.webSockets");
const MESSAGES_TITLE = L10N.getStr("netmonitor.tab.messages");
const PARAMS_TITLE = L10N.getStr("netmonitor.tab.params");
const RESPONSE_TITLE = L10N.getStr("netmonitor.tab.response");
const SECURITY_TITLE = L10N.getStr("netmonitor.tab.security");
@ -96,7 +96,6 @@ class TabboxPanel extends Component {
return null;
}
const channelId = request.channelId;
const showWebSocketsPanel =
request.cause.type === "websocket" &&
Services.prefs.getBoolPref("devtools.netmonitor.features.webSockets") &&
@ -135,11 +134,10 @@ class TabboxPanel extends Component {
showWebSocketsPanel &&
TabPanel(
{
id: PANELS.WEBSOCKETS,
title: WEBSOCKETS_TITLE,
id: PANELS.MESSAGES,
title: MESSAGES_TITLE,
},
WebSocketsPanel({
channelId,
connector,
})
),

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

@ -0,0 +1,85 @@
/* 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 { PureComponent } = require("devtools/client/shared/vendor/react");
const dom = require("devtools/client/shared/vendor/react-dom-factories");
const PropTypes = require("devtools/client/shared/vendor/react-prop-types");
const { L10N } = require("devtools/client/netmonitor/src/utils/l10n.js");
// Menu
loader.lazyRequireGetter(
this,
"showMenu",
"devtools/client/shared/components/menu/utils",
true
);
class FrameFilterMenu extends PureComponent {
static get propTypes() {
return {
frameFilterType: PropTypes.string.isRequired,
toggleFrameFilterType: PropTypes.func.isRequired,
};
}
constructor(props) {
super(props);
this.onShowFilterMenu = this.onShowFilterMenu.bind(this);
}
onShowFilterMenu(event) {
const { frameFilterType, toggleFrameFilterType } = this.props;
const menuItems = [
{
id: "ws-frame-list-context-filter-all",
label: L10N.getStr("netmonitor.ws.context.all"),
accesskey: L10N.getStr("netmonitor.ws.context.all.accesskey"),
checked: frameFilterType === "all",
click: () => {
toggleFrameFilterType("all");
},
},
{
id: "ws-frame-list-context-filter-sent",
label: L10N.getStr("netmonitor.ws.context.sent"),
accesskey: L10N.getStr("netmonitor.ws.context.sent.accesskey"),
checked: frameFilterType === "sent",
click: () => {
toggleFrameFilterType("sent");
},
},
{
id: "ws-frame-list-context-filter-received",
label: L10N.getStr("netmonitor.ws.context.received"),
accesskey: L10N.getStr("netmonitor.ws.context.received.accesskey"),
checked: frameFilterType === "received",
click: () => {
toggleFrameFilterType("received");
},
},
];
showMenu(menuItems, { button: event.target });
}
render() {
const { frameFilterType } = this.props;
const title = L10N.getStr(`netmonitor.ws.context.${frameFilterType}`);
return dom.button(
{
id: "frame-filter-menu",
className: "devtools-button devtools-dropdown-button",
title,
onClick: this.onShowFilterMenu,
},
dom.span({ className: "title" }, title)
);
}
}
module.exports = FrameFilterMenu;

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

@ -10,9 +10,9 @@ const PropTypes = require("devtools/client/shared/vendor/react-prop-types");
const { getFramePayload } = require("../../utils/request-utils");
/**
* Renders the "Payload" column of a WebSocket frame.
* Renders the "Data" column of a WebSocket frame.
*/
class FrameListColumnPayload extends Component {
class FrameListColumnData extends Component {
static get propTypes() {
return {
item: PropTypes.object.isRequired,
@ -61,4 +61,4 @@ class FrameListColumnPayload extends Component {
}
}
module.exports = FrameListColumnPayload;
module.exports = FrameListColumnData;

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

@ -29,6 +29,7 @@ class FrameListColumnTime extends Component {
// Convert microseconds (DOMHighResTimeStamp) to milliseconds
const time = timeStamp / 1000;
const microseconds = (timeStamp % 1000).toString().padStart(3, "0");
return dom.td(
{
@ -36,7 +37,9 @@ class FrameListColumnTime extends Component {
className: "ws-frames-list-column ws-frames-list-time",
title: timeStamp,
},
new Date(time).toLocaleTimeString()
new Date(time).toLocaleTimeString(undefined, { hour12: false }) +
"." +
microseconds
);
}
}

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

@ -12,7 +12,7 @@ const PropTypes = require("devtools/client/shared/vendor/react-prop-types");
const {
connect,
} = require("devtools/client/shared/redux/visibility-handler-connect");
const { getFramesByChannelId } = require("../../selectors/index");
const { getDisplayedFrames } = require("../../selectors/index");
const dom = require("devtools/client/shared/vendor/react-dom-factories");
const { table, tbody, div } = dom;
@ -38,7 +38,6 @@ const LEFT_MOUSE_BUTTON = 0;
class FrameListContent extends Component {
static get propTypes() {
return {
channelId: PropTypes.number,
connector: PropTypes.object.isRequired,
frames: PropTypes.array,
selectedFrame: PropTypes.object,
@ -59,7 +58,7 @@ class FrameListContent extends Component {
render() {
const { frames, selectedFrame, connector } = this.props;
if (!frames) {
if (frames.length === 0) {
return div(
{ className: "empty-notice ws-frame-list-empty-notice" },
FRAMES_EMPTY_TEXT
@ -89,9 +88,9 @@ class FrameListContent extends Component {
}
module.exports = connect(
(state, props) => ({
state => ({
selectedFrame: getSelectedFrame(state),
frames: getFramesByChannelId(state, props.channelId),
frames: getDisplayedFrames(state),
}),
dispatch => ({
selectFrame: item => dispatch(Actions.selectFrame(item)),

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

@ -18,8 +18,8 @@ loader.lazyGetter(this, "FrameListColumnType", function() {
loader.lazyGetter(this, "FrameListColumnSize", function() {
return createFactory(require("./FrameListColumnSize"));
});
loader.lazyGetter(this, "FrameListColumnPayload", function() {
return createFactory(require("./FrameListColumnPayload"));
loader.lazyGetter(this, "FrameListColumnData", function() {
return createFactory(require("./FrameListColumnData"));
});
loader.lazyGetter(this, "FrameListColumnOpCode", function() {
return createFactory(require("./FrameListColumnOpCode"));
@ -37,7 +37,7 @@ loader.lazyGetter(this, "FrameListColumnTime", function() {
const COLUMN_COMPONENTS = [
{ column: "type", ColumnComponent: FrameListColumnType },
{ column: "size", ColumnComponent: FrameListColumnSize },
{ column: "payload", ColumnComponent: FrameListColumnPayload },
{ column: "data", ColumnComponent: FrameListColumnData },
{ column: "opCode", ColumnComponent: FrameListColumnOpCode },
{ column: "maskBit", ColumnComponent: FrameListColumnMaskBit },
{ column: "finBit", ColumnComponent: FrameListColumnFinBit },

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

@ -0,0 +1,129 @@
/* 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 {
Component,
createFactory,
} = require("devtools/client/shared/vendor/react");
const {
connect,
} = require("devtools/client/shared/redux/visibility-handler-connect");
const PropTypes = require("devtools/client/shared/vendor/react-prop-types");
const Actions = require("devtools/client/netmonitor/src/actions/index");
const {
FILTER_SEARCH_DELAY,
} = require("devtools/client/netmonitor/src/constants");
const dom = require("devtools/client/shared/vendor/react-dom-factories");
const { L10N } = require("devtools/client/netmonitor/src/utils/l10n.js");
const { button, span, div } = dom;
// Components
const FrameFilterMenu = createFactory(require("./FrameFilterMenu"));
const SearchBox = createFactory(
require("devtools/client/shared/components/SearchBox")
);
// Localization
const WS_TOOLBAR_CLEAR = L10N.getStr("netmonitor.ws.toolbar.clear");
const WS_SEARCH_KEY_SHORTCUT = L10N.getStr(
"netmonitor.ws.toolbar.filterFreetext.key"
);
const WS_SEARCH_PLACE_HOLDER = L10N.getStr(
"netmonitor.ws.toolbar.filterFreetext.label"
);
/**
* WebSocketsPanel toolbar component.
*
* Toolbar contains a set of useful tools that clear the list of
* existing frames as well as filter content.
*/
class Toolbar extends Component {
static get propTypes() {
return {
searchboxRef: PropTypes.object.isRequired,
toggleFrameFilterType: PropTypes.func.isRequired,
clearFrames: PropTypes.func.isRequired,
setFrameFilterText: PropTypes.func.isRequired,
frameFilterType: PropTypes.string.isRequired,
};
}
/**
* Render a separator.
*/
renderSeparator() {
return span({ className: "devtools-separator" });
}
/**
* Render a clear button.
*/
renderClearButton(clearFrames) {
return button({
className:
"devtools-button devtools-clear-icon ws-frames-list-clear-button",
title: WS_TOOLBAR_CLEAR,
onClick: () => {
clearFrames();
},
});
}
/**
* Render the frame filter menu button.
*/
renderFrameFilterMenu() {
const { frameFilterType, toggleFrameFilterType } = this.props;
return FrameFilterMenu({
frameFilterType,
toggleFrameFilterType,
});
}
/**
* Render filter Searchbox.
*/
renderFilterBox(setFrameFilterText) {
return SearchBox({
delay: FILTER_SEARCH_DELAY,
keyShortcut: WS_SEARCH_KEY_SHORTCUT,
placeholder: WS_SEARCH_PLACE_HOLDER,
type: "filter",
ref: this.props.searchboxRef,
onChange: setFrameFilterText,
});
}
render() {
const { clearFrames, setFrameFilterText } = this.props;
return div(
{
id: "netmonitor-toolbar-container",
className: "devtools-toolbar devtools-input-toolbar",
},
this.renderClearButton(clearFrames),
this.renderSeparator(),
this.renderFrameFilterMenu(),
this.renderSeparator(),
this.renderFilterBox(setFrameFilterText)
);
}
}
module.exports = connect(
state => ({
frameFilterType: state.webSockets.frameFilterType,
}),
dispatch => ({
clearFrames: () => dispatch(Actions.clearFrames()),
toggleFrameFilterType: filter =>
dispatch(Actions.toggleFrameFilterType(filter)),
setFrameFilterText: text => dispatch(Actions.setFrameFilterText(text)),
})
)(Toolbar);

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

@ -7,8 +7,11 @@
const Services = require("Services");
const {
Component,
createRef,
createFactory,
} = require("devtools/client/shared/vendor/react");
const dom = require("devtools/client/shared/vendor/react-dom-factories");
const { div } = dom;
const PropTypes = require("devtools/client/shared/vendor/react-prop-types");
const {
connect,
@ -25,6 +28,7 @@ const SplitBox = createFactory(
require("devtools/client/shared/components/splitter/SplitBox")
);
const FrameListContent = createFactory(require("./FrameListContent"));
const Toolbar = createFactory(require("./Toolbar"));
loader.lazyGetter(this, "FramePayload", function() {
return createFactory(require("./FramePayload"));
@ -37,33 +41,44 @@ loader.lazyGetter(this, "FramePayload", function() {
class WebSocketsPanel extends Component {
static get propTypes() {
return {
channelId: PropTypes.number,
connector: PropTypes.object.isRequired,
selectedFrame: PropTypes.object,
frameDetailsOpen: PropTypes.bool.isRequired,
openFrameDetailsTab: PropTypes.func.isRequired,
selectedFrameVisible: PropTypes.bool.isRequired,
channelId: PropTypes.number,
};
}
constructor(props) {
super(props);
this.searchboxRef = createRef();
this.clearFilterText = this.clearFilterText.bind(this);
}
componentDidUpdate() {
const { selectedFrameVisible, openFrameDetailsTab } = this.props;
componentDidUpdate(nextProps) {
const { selectedFrameVisible, openFrameDetailsTab, channelId } = this.props;
// If a new WebSocket connection is selected, clear the filter text
if (channelId !== nextProps.channelId) {
this.clearFilterText();
}
if (!selectedFrameVisible) {
openFrameDetailsTab(false);
}
}
// Reset the filter text
clearFilterText() {
if (this.searchboxRef) {
this.searchboxRef.current.onClearButtonClick();
}
}
render() {
const {
frameDetailsOpen,
channelId,
connector,
selectedFrame,
} = this.props;
const { frameDetailsOpen, connector, selectedFrame } = this.props;
const initialWidth = Services.prefs.getIntPref(
"devtools.netmonitor.ws.payload-preview-width"
@ -72,36 +87,39 @@ class WebSocketsPanel extends Component {
"devtools.netmonitor.ws.payload-preview-height"
);
return SplitBox({
className: "devtools-responsive-container",
initialWidth: initialWidth,
initialHeight: initialHeight,
minSize: "50px",
maxSize: "50%",
splitterSize: frameDetailsOpen ? 1 : 0,
startPanel: FrameListContent({ channelId, connector }),
endPanel:
frameDetailsOpen &&
FramePayload({
connector,
selectedFrame,
}),
endPanelCollapsed: !frameDetailsOpen,
endPanelControl: true,
vert: false,
});
return div(
{ className: "monitor-panel" },
Toolbar({
searchboxRef: this.searchboxRef,
}),
SplitBox({
className: "devtools-responsive-container",
initialWidth: initialWidth,
initialHeight: initialHeight,
minSize: "50px",
maxSize: "50%",
splitterSize: frameDetailsOpen ? 1 : 0,
startPanel: FrameListContent({ connector }),
endPanel:
frameDetailsOpen &&
FramePayload({
connector,
selectedFrame,
}),
endPanelCollapsed: !frameDetailsOpen,
endPanelControl: true,
vert: false,
})
);
}
}
module.exports = connect(
(state, props) => ({
selectedFrame: getSelectedFrame(state),
state => ({
channelId: state.webSockets.currentChannelId,
frameDetailsOpen: state.webSockets.frameDetailsOpen,
selectedFrameVisible: isSelectedFrameVisible(
state,
props.channelId,
getSelectedFrame(state)
),
selectedFrame: getSelectedFrame(state),
selectedFrameVisible: isSelectedFrameVisible(state),
}),
dispatch => ({
openFrameDetailsTab: open => dispatch(Actions.openFrameDetails(open)),

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

@ -3,10 +3,11 @@
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
DevToolsModules(
'FrameFilterMenu.js',
'FrameListColumnData.js',
'FrameListColumnFinBit.js',
'FrameListColumnMaskBit.js',
'FrameListColumnOpCode.js',
'FrameListColumnPayload.js',
'FrameListColumnSize.js',
'FrameListColumnTime.js',
'FrameListColumnType.js',
@ -14,5 +15,6 @@ DevToolsModules(
'FrameListHeader.js',
'FrameListItem.js',
'FramePayload.js',
'Toolbar.js',
'WebSocketsPanel.js',
)

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

@ -37,6 +37,9 @@ const actionTypes = {
WS_ADD_FRAME: "WS_ADD_FRAME",
WS_SELECT_FRAME: "WS_SELECT_FRAME",
WS_OPEN_FRAME_DETAILS: "WS_OPEN_FRAME_DETAILS",
WS_CLEAR_FRAMES: "WS_CLEAR_FRAMES",
WS_TOGGLE_FRAME_FILTER_TYPE: "WS_TOGGLE_FRAME_FILTER_TYPE",
WS_SET_REQUEST_FILTER_TEXT: "WS_SET_REQUEST_FILTER_TEXT",
};
// Descriptions for what this frontend is currently doing.
@ -163,7 +166,7 @@ const UPDATE_PROPS = [
const PANELS = {
COOKIES: "cookies",
HEADERS: "headers",
WEBSOCKETS: "webSockets",
MESSAGES: "messages",
PARAMS: "params",
RESPONSE: "response",
CACHE: "cache",
@ -325,7 +328,7 @@ const WS_FRAMES_HEADERS = [
name: "size",
},
{
name: "payload",
name: "data",
},
{
name: "opCode",

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

@ -5,9 +5,13 @@
"use strict";
const {
SELECT_REQUEST,
WS_ADD_FRAME,
WS_SELECT_FRAME,
WS_OPEN_FRAME_DETAILS,
WS_CLEAR_FRAMES,
WS_TOGGLE_FRAME_FILTER_TYPE,
WS_SET_REQUEST_FILTER_TEXT,
} = require("../constants");
/**
@ -18,26 +22,47 @@ function WebSockets() {
return {
// Map with all requests (key = channelId, value = array of frame objects)
frames: new Map(),
frameFilterText: "",
// Default filter type is "all",
frameFilterType: "all",
selectedFrame: null,
frameDetailsOpen: false,
currentChannelId: null,
};
}
// Appending new frame into the map.
/**
* When a network request is selected,
* set the current channelId affiliated with the WebSocket connection.
*/
function setChannelId(state, action) {
return {
...state,
currentChannelId: action.httpChannelId,
// Default filter text is empty string for a new WebSocket connection
frameFilterText: "",
};
}
/**
* Appending new frame into the map.
*/
function addFrame(state, action) {
const { httpChannelId } = action;
const nextState = { ...state };
const newFrame = {
httpChannelId: action.httpChannelId,
httpChannelId,
...action.data,
};
nextState.frames = mapSet(state.frames, newFrame.httpChannelId, newFrame);
nextState.frames = mapSet(nextState.frames, newFrame.httpChannelId, newFrame);
return nextState;
}
// Select specific frame.
/**
* Select specific frame.
*/
function selectFrame(state, action) {
return {
...state,
@ -46,6 +71,9 @@ function selectFrame(state, action) {
};
}
/**
* Shows/Hides the FramePayload component.
*/
function openFrameDetails(state, action) {
return {
...state,
@ -53,6 +81,45 @@ function openFrameDetails(state, action) {
};
}
/**
* Clear WS frames of the request from the state.
*/
function clearFrames(state) {
const nextState = { ...state };
nextState.frames = new Map(nextState.frames);
nextState.frames.delete(nextState.currentChannelId);
return {
...WebSockets(),
// Preserving the Map objects as they might contain state for other channelIds
frames: nextState.frames,
// Preserving the currentChannelId as there would not be another reset of channelId
currentChannelId: nextState.currentChannelId,
frameFilterType: nextState.frameFilterType,
frameFilterText: nextState.frameFilterText,
};
}
/**
* Toggle the frame filter type of the WebSocket connection.
*/
function toggleFrameFilterType(state, action) {
return {
...state,
frameFilterType: action.filter,
};
}
/**
* Set the filter text of the current channelId.
*/
function setFrameFilterText(state, action) {
return {
...state,
frameFilterText: action.text,
};
}
/**
* Append new item into existing map and return new map.
*/
@ -73,12 +140,20 @@ function mapSet(map, key, value) {
*/
function webSockets(state = WebSockets(), action) {
switch (action.type) {
case SELECT_REQUEST:
return setChannelId(state, action);
case WS_ADD_FRAME:
return addFrame(state, action);
case WS_SELECT_FRAME:
return selectFrame(state, action);
case WS_OPEN_FRAME_DETAILS:
return openFrameDetails(state, action);
case WS_CLEAR_FRAMES:
return clearFrames(state);
case WS_TOGGLE_FRAME_FILTER_TYPE:
return toggleFrameFilterType(state, action);
case WS_SET_REQUEST_FILTER_TEXT:
return setFrameFilterText(state, action);
default:
return state;
}

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

@ -6,30 +6,52 @@
const { createSelector } = require("devtools/client/shared/vendor/reselect");
function getFramesByChannelId(state, channelId) {
return state.webSockets.frames.get(channelId);
}
/**
* Returns list of frames that are visible to the user.
* Filtered frames by types and text are factored in.
*/
const getDisplayedFrames = createSelector(
state => state.webSockets,
({ frames, frameFilterType, frameFilterText, currentChannelId }) => {
if (!currentChannelId || !frames.get(currentChannelId)) {
return [];
}
const framesArray = frames.get(currentChannelId);
if (frameFilterType === "all" && frameFilterText.length === 0) {
return framesArray;
}
return framesArray.filter(
frame =>
frame.payload.includes(frameFilterText) &&
(frameFilterType === "all" || frameFilterType === frame.type)
);
}
);
/**
* Checks if the selected frame is visible.
* If the selected frame is not visible, the SplitBox component
* should not show the FramePayload component.
*/
function isSelectedFrameVisible(state, channelId, targetFrame) {
const displayedFrames = getFramesByChannelId(state, channelId);
if (displayedFrames && targetFrame) {
return displayedFrames.some(frame => frame === targetFrame);
}
return false;
}
const isSelectedFrameVisible = createSelector(
state => state.webSockets,
getDisplayedFrames,
({ selectedFrame }, displayedFrames) =>
displayedFrames.some(frame => frame === selectedFrame)
);
/**
* Returns the current selected frame.
*/
const getSelectedFrame = createSelector(
state => state.webSockets,
({ selectedFrame }) => (selectedFrame ? selectedFrame : undefined)
);
module.exports = {
getFramesByChannelId,
getSelectedFrame,
isSelectedFrameVisible,
getDisplayedFrames,
};

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

@ -1287,7 +1287,13 @@ class MOZ_STACK_CLASS HeapSnapshotHandler {
if (!first) return true;
CoreDumpWriter::EdgePolicy policy;
if (!ShouldIncludeEdge(compartments, origin, edge, &policy)) return true;
if (!ShouldIncludeEdge(compartments, origin, edge, &policy)) {
// Because ShouldIncludeEdge considers the |origin| node as well, we don't
// want to consider this node 'visited' until we write it to the core
// dump.
traversal.doNotMarkReferentAsVisited();
return true;
}
nodeCount++;

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

@ -9153,7 +9153,7 @@ nsresult nsDocShell::MaybeHandleSameDocumentNavigation(
} else {
newURITriggeringPrincipal = aLoadState->TriggeringPrincipal();
newURIPrincipalToInherit = doc->NodePrincipal();
newURIStoragePrincipalToInherit = doc->EffectiveStoragePrincipal();
newURIStoragePrincipalToInherit = doc->IntrinsicStoragePrincipal();
newCsp = doc->GetCsp();
}
// Pass true for aCloneSHChildren, since we're not
@ -9717,7 +9717,7 @@ nsIPrincipal* nsDocShell::GetInheritedPrincipal(
//-- Get the document's principal
if (document) {
nsIPrincipal* docPrincipal = aConsiderStoragePrincipal
? document->EffectiveStoragePrincipal()
? document->IntrinsicStoragePrincipal()
: document->NodePrincipal();
// Don't allow loads in typeContent docShells to inherit the system

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

@ -559,6 +559,14 @@ class Document : public nsINode,
return EffectiveStoragePrincipal();
}
// You should probably not be using this function, since it performs no
// checks to ensure that the intrinsic storage principal should really be
// used here. It is only designed to be used in very specific circumstances,
// such as when inheriting the document/storage principal.
nsIPrincipal* IntrinsicStoragePrincipal() const {
return mIntrinsicStoragePrincipal;
}
// EventTarget
void GetEventTargetParent(EventChainPreVisitor& aVisitor) override;
EventListenerManager* GetOrCreateListenerManager() override;

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

@ -12,7 +12,7 @@ typedef CustomEventInit TestDictionaryTypedef;
interface TestExternalInterface;
// We need a pref name that's in StaticPrefList.h here.
[Pref="abc.def"]
[Pref="dom.webidl.test1"]
interface TestRenamedInterface {
};
@ -899,63 +899,63 @@ interface TestInterface {
void passVariadicThirdArg(DOMString arg1, long arg2, TestInterface... arg3);
// Conditionally exposed methods/attributes
[Pref="abc.def"]
[Pref="dom.webidl.test1"]
readonly attribute boolean prefable1;
[Pref="abc.def"]
[Pref="dom.webidl.test1"]
readonly attribute boolean prefable2;
[Pref="ghi.jkl"]
[Pref="dom.webidl.test2"]
readonly attribute boolean prefable3;
[Pref="ghi.jkl"]
[Pref="dom.webidl.test2"]
readonly attribute boolean prefable4;
[Pref="abc.def"]
[Pref="dom.webidl.test1"]
readonly attribute boolean prefable5;
[Pref="abc.def", Func="nsGenericHTMLElement::LegacyTouchAPIEnabled"]
[Pref="dom.webidl.test1", Func="nsGenericHTMLElement::LegacyTouchAPIEnabled"]
readonly attribute boolean prefable6;
[Pref="abc.def", Func="nsGenericHTMLElement::LegacyTouchAPIEnabled"]
[Pref="dom.webidl.test1", Func="nsGenericHTMLElement::LegacyTouchAPIEnabled"]
readonly attribute boolean prefable7;
[Pref="ghi.jkl", Func="nsGenericHTMLElement::LegacyTouchAPIEnabled"]
[Pref="dom.webidl.test2", Func="nsGenericHTMLElement::LegacyTouchAPIEnabled"]
readonly attribute boolean prefable8;
[Pref="abc.def", Func="nsGenericHTMLElement::LegacyTouchAPIEnabled"]
[Pref="dom.webidl.test1", Func="nsGenericHTMLElement::LegacyTouchAPIEnabled"]
readonly attribute boolean prefable9;
[Pref="abc.def"]
[Pref="dom.webidl.test1"]
void prefable10();
[Pref="abc.def", Func="nsGenericHTMLElement::LegacyTouchAPIEnabled"]
[Pref="dom.webidl.test1", Func="nsGenericHTMLElement::LegacyTouchAPIEnabled"]
void prefable11();
[Pref="abc.def", Func="TestFuncControlledMember"]
[Pref="dom.webidl.test1", Func="TestFuncControlledMember"]
readonly attribute boolean prefable12;
[Pref="abc.def", Func="nsGenericHTMLElement::LegacyTouchAPIEnabled"]
[Pref="dom.webidl.test1", Func="nsGenericHTMLElement::LegacyTouchAPIEnabled"]
void prefable13();
[Pref="abc.def", Func="TestFuncControlledMember"]
[Pref="dom.webidl.test1", Func="TestFuncControlledMember"]
readonly attribute boolean prefable14;
[Func="TestFuncControlledMember"]
readonly attribute boolean prefable15;
[Func="TestFuncControlledMember"]
readonly attribute boolean prefable16;
[Pref="abc.def", Func="TestFuncControlledMember"]
[Pref="dom.webidl.test1", Func="TestFuncControlledMember"]
void prefable17();
[Func="TestFuncControlledMember"]
void prefable18();
[Func="TestFuncControlledMember"]
void prefable19();
[Pref="abc.def", Func="TestFuncControlledMember", ChromeOnly]
[Pref="dom.webidl.test1", Func="TestFuncControlledMember", ChromeOnly]
void prefable20();
// Conditionally exposed methods/attributes involving [SecureContext]
[SecureContext]
readonly attribute boolean conditionalOnSecureContext1;
[SecureContext, Pref="abc.def"]
[SecureContext, Pref="dom.webidl.test1"]
readonly attribute boolean conditionalOnSecureContext2;
[SecureContext, Pref="abc.def", Func="nsGenericHTMLElement::LegacyTouchAPIEnabled"]
[SecureContext, Pref="dom.webidl.test1", Func="nsGenericHTMLElement::LegacyTouchAPIEnabled"]
readonly attribute boolean conditionalOnSecureContext3;
[SecureContext, Pref="abc.def", Func="TestFuncControlledMember"]
[SecureContext, Pref="dom.webidl.test1", Func="TestFuncControlledMember"]
readonly attribute boolean conditionalOnSecureContext4;
[SecureContext]
void conditionalOnSecureContext5();
[SecureContext, Pref="abc.def"]
[SecureContext, Pref="dom.webidl.test1"]
void conditionalOnSecureContext6();
[SecureContext, Pref="abc.def", Func="nsGenericHTMLElement::LegacyTouchAPIEnabled"]
[SecureContext, Pref="dom.webidl.test1", Func="nsGenericHTMLElement::LegacyTouchAPIEnabled"]
void conditionalOnSecureContext7();
[SecureContext, Pref="abc.def", Func="TestFuncControlledMember"]
[SecureContext, Pref="dom.webidl.test1", Func="TestFuncControlledMember"]
void conditionalOnSecureContext8();
// Miscellania
@ -1221,9 +1221,9 @@ dictionary DictWithConditionalMembers {
[ChromeOnly, Func="nsGenericHTMLElement::LegacyTouchAPIEnabled"]
long chromeOnlyFuncControlledMember;
// We need a pref name that's in StaticPrefList.h here.
[Pref="abc.def"]
[Pref="dom.webidl.test1"]
long prefControlledMember;
[Pref="abc.def", ChromeOnly, Func="TestFuncControlledMember"]
[Pref="dom.webidl.test1", ChromeOnly, Func="TestFuncControlledMember"]
long chromeOnlyFuncAndPrefControlledMember;
};

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

@ -705,39 +705,39 @@ interface TestExampleInterface {
void passVariadicThirdArg(DOMString arg1, long arg2, TestInterface... arg3);
// Conditionally exposed methods/attributes
[Pref="abc.def"]
[Pref="dom.webidl.test1"]
readonly attribute boolean prefable1;
[Pref="abc.def"]
[Pref="dom.webidl.test1"]
readonly attribute boolean prefable2;
[Pref="ghi.jkl"]
[Pref="dom.webidl.test2"]
readonly attribute boolean prefable3;
[Pref="ghi.jkl"]
[Pref="dom.webidl.test2"]
readonly attribute boolean prefable4;
[Pref="abc.def"]
[Pref="dom.webidl.test1"]
readonly attribute boolean prefable5;
[Pref="abc.def", Func="nsGenericHTMLElement::LegacyTouchAPIEnabled"]
[Pref="dom.webidl.test1", Func="nsGenericHTMLElement::LegacyTouchAPIEnabled"]
readonly attribute boolean prefable6;
[Pref="abc.def", Func="nsGenericHTMLElement::LegacyTouchAPIEnabled"]
[Pref="dom.webidl.test1", Func="nsGenericHTMLElement::LegacyTouchAPIEnabled"]
readonly attribute boolean prefable7;
[Pref="ghi.jkl", Func="nsGenericHTMLElement::LegacyTouchAPIEnabled"]
[Pref="dom.webidl.test2", Func="nsGenericHTMLElement::LegacyTouchAPIEnabled"]
readonly attribute boolean prefable8;
[Pref="abc.def", Func="nsGenericHTMLElement::LegacyTouchAPIEnabled"]
[Pref="dom.webidl.test1", Func="nsGenericHTMLElement::LegacyTouchAPIEnabled"]
readonly attribute boolean prefable9;
[Pref="abc.def"]
[Pref="dom.webidl.test1"]
void prefable10();
[Pref="abc.def", Func="nsGenericHTMLElement::LegacyTouchAPIEnabled"]
[Pref="dom.webidl.test1", Func="nsGenericHTMLElement::LegacyTouchAPIEnabled"]
void prefable11();
[Pref="abc.def", Func="TestFuncControlledMember"]
[Pref="dom.webidl.test1", Func="TestFuncControlledMember"]
readonly attribute boolean prefable12;
[Pref="abc.def", Func="nsGenericHTMLElement::LegacyTouchAPIEnabled"]
[Pref="dom.webidl.test1", Func="nsGenericHTMLElement::LegacyTouchAPIEnabled"]
void prefable13();
[Pref="abc.def", Func="TestFuncControlledMember"]
[Pref="dom.webidl.test1", Func="TestFuncControlledMember"]
readonly attribute boolean prefable14;
[Func="TestFuncControlledMember"]
readonly attribute boolean prefable15;
[Func="TestFuncControlledMember"]
readonly attribute boolean prefable16;
[Pref="abc.def", Func="TestFuncControlledMember"]
[Pref="dom.webidl.test1", Func="TestFuncControlledMember"]
void prefable17();
[Func="TestFuncControlledMember"]
void prefable18();
@ -747,19 +747,19 @@ interface TestExampleInterface {
// Conditionally exposed methods/attributes involving [SecureContext]
[SecureContext]
readonly attribute boolean conditionalOnSecureContext1;
[SecureContext, Pref="abc.def"]
[SecureContext, Pref="dom.webidl.test1"]
readonly attribute boolean conditionalOnSecureContext2;
[SecureContext, Pref="abc.def", Func="nsGenericHTMLElement::LegacyTouchAPIEnabled"]
[SecureContext, Pref="dom.webidl.test1", Func="nsGenericHTMLElement::LegacyTouchAPIEnabled"]
readonly attribute boolean conditionalOnSecureContext3;
[SecureContext, Pref="abc.def", Func="TestFuncControlledMember"]
[SecureContext, Pref="dom.webidl.test1", Func="TestFuncControlledMember"]
readonly attribute boolean conditionalOnSecureContext4;
[SecureContext]
void conditionalOnSecureContext5();
[SecureContext, Pref="abc.def"]
[SecureContext, Pref="dom.webidl.test1"]
void conditionalOnSecureContext6();
[SecureContext, Pref="abc.def", Func="nsGenericHTMLElement::LegacyTouchAPIEnabled"]
[SecureContext, Pref="dom.webidl.test1", Func="nsGenericHTMLElement::LegacyTouchAPIEnabled"]
void conditionalOnSecureContext7();
[SecureContext, Pref="abc.def", Func="TestFuncControlledMember"]
[SecureContext, Pref="dom.webidl.test1", Func="TestFuncControlledMember"]
void conditionalOnSecureContext8();
// Miscellania

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

@ -723,63 +723,63 @@ interface TestJSImplInterface {
void passVariadicThirdArg(DOMString arg1, long arg2, TestJSImplInterface... arg3);
// Conditionally exposed methods/attributes
[Pref="abc.def"]
[Pref="dom.webidl.test1"]
readonly attribute boolean prefable1;
[Pref="abc.def"]
[Pref="dom.webidl.test1"]
readonly attribute boolean prefable2;
[Pref="ghi.jkl"]
[Pref="dom.webidl.test2"]
readonly attribute boolean prefable3;
[Pref="ghi.jkl"]
[Pref="dom.webidl.test2"]
readonly attribute boolean prefable4;
[Pref="abc.def"]
[Pref="dom.webidl.test1"]
readonly attribute boolean prefable5;
[Pref="abc.def", Func="nsGenericHTMLElement::LegacyTouchAPIEnabled"]
[Pref="dom.webidl.test1", Func="nsGenericHTMLElement::LegacyTouchAPIEnabled"]
readonly attribute boolean prefable6;
[Pref="abc.def", Func="nsGenericHTMLElement::LegacyTouchAPIEnabled"]
[Pref="dom.webidl.test1", Func="nsGenericHTMLElement::LegacyTouchAPIEnabled"]
readonly attribute boolean prefable7;
[Pref="ghi.jkl", Func="nsGenericHTMLElement::LegacyTouchAPIEnabled"]
[Pref="dom.webidl.test2", Func="nsGenericHTMLElement::LegacyTouchAPIEnabled"]
readonly attribute boolean prefable8;
[Pref="abc.def", Func="nsGenericHTMLElement::LegacyTouchAPIEnabled"]
[Pref="dom.webidl.test1", Func="nsGenericHTMLElement::LegacyTouchAPIEnabled"]
readonly attribute boolean prefable9;
[Pref="abc.def"]
[Pref="dom.webidl.test1"]
void prefable10();
[Pref="abc.def", Func="nsGenericHTMLElement::LegacyTouchAPIEnabled"]
[Pref="dom.webidl.test1", Func="nsGenericHTMLElement::LegacyTouchAPIEnabled"]
void prefable11();
[Pref="abc.def", Func="TestFuncControlledMember"]
[Pref="dom.webidl.test1", Func="TestFuncControlledMember"]
readonly attribute boolean prefable12;
[Pref="abc.def", Func="nsGenericHTMLElement::LegacyTouchAPIEnabled"]
[Pref="dom.webidl.test1", Func="nsGenericHTMLElement::LegacyTouchAPIEnabled"]
void prefable13();
[Pref="abc.def", Func="TestFuncControlledMember"]
[Pref="dom.webidl.test1", Func="TestFuncControlledMember"]
readonly attribute boolean prefable14;
[Func="TestFuncControlledMember"]
readonly attribute boolean prefable15;
[Func="TestFuncControlledMember"]
readonly attribute boolean prefable16;
[Pref="abc.def", Func="TestFuncControlledMember"]
[Pref="dom.webidl.test1", Func="TestFuncControlledMember"]
void prefable17();
[Func="TestFuncControlledMember"]
void prefable18();
[Func="TestFuncControlledMember"]
void prefable19();
[Pref="abc.def", Func="TestFuncControlledMember", ChromeOnly]
[Pref="dom.webidl.test1", Func="TestFuncControlledMember", ChromeOnly]
void prefable20();
// Conditionally exposed methods/attributes involving [SecureContext]
[SecureContext]
readonly attribute boolean conditionalOnSecureContext1;
[SecureContext, Pref="abc.def"]
[SecureContext, Pref="dom.webidl.test1"]
readonly attribute boolean conditionalOnSecureContext2;
[SecureContext, Pref="abc.def", Func="nsGenericHTMLElement::LegacyTouchAPIEnabled"]
[SecureContext, Pref="dom.webidl.test1", Func="nsGenericHTMLElement::LegacyTouchAPIEnabled"]
readonly attribute boolean conditionalOnSecureContext3;
[SecureContext, Pref="abc.def", Func="TestFuncControlledMember"]
[SecureContext, Pref="dom.webidl.test1", Func="TestFuncControlledMember"]
readonly attribute boolean conditionalOnSecureContext4;
[SecureContext]
void conditionalOnSecureContext5();
[SecureContext, Pref="abc.def"]
[SecureContext, Pref="dom.webidl.test1"]
void conditionalOnSecureContext6();
[SecureContext, Pref="abc.def", Func="nsGenericHTMLElement::LegacyTouchAPIEnabled"]
[SecureContext, Pref="dom.webidl.test1", Func="nsGenericHTMLElement::LegacyTouchAPIEnabled"]
void conditionalOnSecureContext7();
[SecureContext, Pref="abc.def", Func="TestFuncControlledMember"]
[SecureContext, Pref="dom.webidl.test1", Func="TestFuncControlledMember"]
void conditionalOnSecureContext8();
// Miscellania

36
dom/cache/ActorChild.cpp поставляемый
Просмотреть файл

@ -6,45 +6,45 @@
#include "mozilla/dom/cache/ActorChild.h"
#include "mozilla/dom/cache/CacheWorkerHolder.h"
#include "mozilla/dom/cache/CacheWorkerRef.h"
#include "nsThreadUtils.h"
namespace mozilla {
namespace dom {
namespace cache {
void ActorChild::SetWorkerHolder(CacheWorkerHolder* aWorkerHolder) {
void ActorChild::SetWorkerRef(CacheWorkerRef* aWorkerRef) {
// Some of the Cache actors can have multiple DOM objects associated with
// them. In this case the workerHolder will be added multiple times. This is
// permitted, but the workerHolder should be the same each time.
if (mWorkerHolder) {
MOZ_DIAGNOSTIC_ASSERT(mWorkerHolder == aWorkerHolder);
// them. In this case the workerRef will be added multiple times. This is
// permitted, but the workerRef should be the same each time.
if (mWorkerRef) {
MOZ_DIAGNOSTIC_ASSERT(mWorkerRef == aWorkerRef);
return;
}
mWorkerHolder = aWorkerHolder;
if (mWorkerHolder) {
mWorkerHolder->AddActor(this);
mWorkerRef = aWorkerRef;
if (mWorkerRef) {
mWorkerRef->AddActor(this);
}
}
void ActorChild::RemoveWorkerHolder() {
MOZ_ASSERT_IF(!NS_IsMainThread(), mWorkerHolder);
if (mWorkerHolder) {
mWorkerHolder->RemoveActor(this);
mWorkerHolder = nullptr;
void ActorChild::RemoveWorkerRef() {
MOZ_ASSERT_IF(!NS_IsMainThread(), mWorkerRef);
if (mWorkerRef) {
mWorkerRef->RemoveActor(this);
mWorkerRef = nullptr;
}
}
CacheWorkerHolder* ActorChild::GetWorkerHolder() const { return mWorkerHolder; }
CacheWorkerRef* ActorChild::GetWorkerRef() const { return mWorkerRef; }
bool ActorChild::WorkerHolderNotified() const {
return mWorkerHolder && mWorkerHolder->Notified();
bool ActorChild::WorkerRefNotified() const {
return mWorkerRef && mWorkerRef->Notified();
}
ActorChild::ActorChild() {}
ActorChild::~ActorChild() { MOZ_DIAGNOSTIC_ASSERT(!mWorkerHolder); }
ActorChild::~ActorChild() { MOZ_DIAGNOSTIC_ASSERT(!mWorkerRef); }
} // namespace cache
} // namespace dom

12
dom/cache/ActorChild.h поставляемый
Просмотреть файл

@ -13,26 +13,26 @@ namespace mozilla {
namespace dom {
namespace cache {
class CacheWorkerHolder;
class CacheWorkerRef;
class ActorChild {
public:
virtual void StartDestroy() = 0;
void SetWorkerHolder(CacheWorkerHolder* aWorkerHolder);
void SetWorkerRef(CacheWorkerRef* aWorkerRef);
void RemoveWorkerHolder();
void RemoveWorkerRef();
CacheWorkerHolder* GetWorkerHolder() const;
CacheWorkerRef* GetWorkerRef() const;
bool WorkerHolderNotified() const;
bool WorkerRefNotified() const;
protected:
ActorChild();
~ActorChild();
private:
RefPtr<CacheWorkerHolder> mWorkerHolder;
RefPtr<CacheWorkerRef> mWorkerRef;
};
} // namespace cache

18
dom/cache/Cache.cpp поставляемый
Просмотреть файл

@ -15,7 +15,7 @@
#include "mozilla/dom/CacheBinding.h"
#include "mozilla/dom/cache/AutoUtils.h"
#include "mozilla/dom/cache/CacheChild.h"
#include "mozilla/dom/cache/CacheWorkerHolder.h"
#include "mozilla/dom/cache/CacheWorkerRef.h"
#include "mozilla/dom/cache/ReadStream.h"
#include "mozilla/ErrorResult.h"
#include "mozilla/Preferences.h"
@ -96,19 +96,19 @@ static bool IsValidPutResponseStatus(Response& aResponse,
} // namespace
// Helper class to wait for Add()/AddAll() fetch requests to complete and
// then perform a PutAll() with the responses. This class holds a WorkerHolder
// then perform a PutAll() with the responses. This class holds a WorkerRef
// to keep the Worker thread alive. This is mainly to ensure that Add/AddAll
// act the same as other Cache operations that directly create a CacheOpChild
// actor.
class Cache::FetchHandler final : public PromiseNativeHandler {
public:
FetchHandler(CacheWorkerHolder* aWorkerHolder, Cache* aCache,
FetchHandler(CacheWorkerRef* aWorkerRef, Cache* aCache,
nsTArray<RefPtr<Request>>&& aRequestList, Promise* aPromise)
: mWorkerHolder(aWorkerHolder),
: mWorkerRef(aWorkerRef),
mCache(aCache),
mRequestList(std::move(aRequestList)),
mPromise(aPromise) {
MOZ_ASSERT_IF(!NS_IsMainThread(), mWorkerHolder);
MOZ_ASSERT_IF(!NS_IsMainThread(), mWorkerRef);
MOZ_DIAGNOSTIC_ASSERT(mCache);
MOZ_DIAGNOSTIC_ASSERT(mPromise);
}
@ -118,8 +118,8 @@ class Cache::FetchHandler final : public PromiseNativeHandler {
NS_ASSERT_OWNINGTHREAD(FetchHandler);
// Stop holding the worker alive when we leave this method.
RefPtr<CacheWorkerHolder> workerHolder;
workerHolder.swap(mWorkerHolder);
RefPtr<CacheWorkerRef> workerRef;
workerRef.swap(mWorkerRef);
// Promise::All() passed an array of fetch() Promises should give us
// an Array of Response objects. The following code unwraps these
@ -220,7 +220,7 @@ class Cache::FetchHandler final : public PromiseNativeHandler {
mPromise->MaybeReject(rv);
}
RefPtr<CacheWorkerHolder> mWorkerHolder;
RefPtr<CacheWorkerRef> mWorkerRef;
RefPtr<Cache> mCache;
nsTArray<RefPtr<Request>> mRequestList;
RefPtr<Promise> mPromise;
@ -576,7 +576,7 @@ already_AddRefed<Promise> Cache::AddAll(
}
RefPtr<FetchHandler> handler = new FetchHandler(
mActor->GetWorkerHolder(), this, std::move(aRequestList), promise);
mActor->GetWorkerRef(), this, std::move(aRequestList), promise);
RefPtr<Promise> fetchPromise =
Promise::All(aGlobal.Context(), fetchList, aRv);

6
dom/cache/CacheChild.cpp поставляемый
Просмотреть файл

@ -54,7 +54,7 @@ void CacheChild::ExecuteOp(nsIGlobalObject* aGlobal, Promise* aPromise,
nsISupports* aParent, const CacheOpArgs& aArgs) {
mNumChildActors += 1;
MOZ_ALWAYS_TRUE(SendPCacheOpConstructor(
new CacheOpChild(GetWorkerHolder(), aGlobal, aParent, aPromise), aArgs));
new CacheOpChild(GetWorkerRef(), aGlobal, aParent, aPromise), aArgs));
}
void CacheChild::StartDestroyFromListener() {
@ -83,7 +83,7 @@ void CacheChild::StartDestroy() {
RefPtr<Cache> listener = mListener;
// StartDestroy() can get called from either Cache or the WorkerHolder.
// StartDestroy() can get called from either Cache or the WorkerRef.
// Theoretically we can get double called if the right race happens. Handle
// that by just ignoring the second StartDestroy() call.
if (!listener) {
@ -108,7 +108,7 @@ void CacheChild::ActorDestroy(ActorDestroyReason aReason) {
MOZ_DIAGNOSTIC_ASSERT(!mListener);
}
RemoveWorkerHolder();
RemoveWorkerRef();
}
PCacheOpChild* CacheChild::AllocPCacheOpChild(const CacheOpArgs& aOpArgs) {

2
dom/cache/CacheChild.h поставляемый
Просмотреть файл

@ -58,7 +58,7 @@ class CacheChild final : public PCacheChild, public ActorChild {
private:
// ActorChild methods
// WorkerHolder is trying to destroy due to worker shutdown.
// WorkerRef is trying to destroy due to worker shutdown.
virtual void StartDestroy() override;
// PCacheChild methods

56
dom/cache/CacheOpChild.cpp поставляемый
Просмотреть файл

@ -12,7 +12,7 @@
#include "mozilla/dom/cache/Cache.h"
#include "mozilla/dom/cache/CacheChild.h"
#include "mozilla/dom/cache/CacheStreamControlChild.h"
#include "mozilla/dom/cache/CacheWorkerHolder.h"
#include "mozilla/dom/cache/CacheWorkerRef.h"
namespace mozilla {
namespace dom {
@ -22,54 +22,53 @@ using mozilla::ipc::PBackgroundChild;
namespace {
void AddWorkerHolderToStreamChild(const CacheReadStream& aReadStream,
CacheWorkerHolder* aWorkerHolder) {
MOZ_ASSERT_IF(!NS_IsMainThread(), aWorkerHolder);
void AddWorkerRefToStreamChild(const CacheReadStream& aReadStream,
CacheWorkerRef* aWorkerRef) {
MOZ_ASSERT_IF(!NS_IsMainThread(), aWorkerRef);
CacheStreamControlChild* cacheControl =
static_cast<CacheStreamControlChild*>(aReadStream.controlChild());
if (cacheControl) {
cacheControl->SetWorkerHolder(aWorkerHolder);
cacheControl->SetWorkerRef(aWorkerRef);
}
}
void AddWorkerHolderToStreamChild(const CacheResponse& aResponse,
CacheWorkerHolder* aWorkerHolder) {
MOZ_ASSERT_IF(!NS_IsMainThread(), aWorkerHolder);
void AddWorkerRefToStreamChild(const CacheResponse& aResponse,
CacheWorkerRef* aWorkerRef) {
MOZ_ASSERT_IF(!NS_IsMainThread(), aWorkerRef);
if (aResponse.body().isNothing()) {
return;
}
AddWorkerHolderToStreamChild(aResponse.body().ref(), aWorkerHolder);
AddWorkerRefToStreamChild(aResponse.body().ref(), aWorkerRef);
}
void AddWorkerHolderToStreamChild(const CacheRequest& aRequest,
CacheWorkerHolder* aWorkerHolder) {
MOZ_ASSERT_IF(!NS_IsMainThread(), aWorkerHolder);
void AddWorkerRefToStreamChild(const CacheRequest& aRequest,
CacheWorkerRef* aWorkerRef) {
MOZ_ASSERT_IF(!NS_IsMainThread(), aWorkerRef);
if (aRequest.body().isNothing()) {
return;
}
AddWorkerHolderToStreamChild(aRequest.body().ref(), aWorkerHolder);
AddWorkerRefToStreamChild(aRequest.body().ref(), aWorkerRef);
}
} // namespace
CacheOpChild::CacheOpChild(CacheWorkerHolder* aWorkerHolder,
nsIGlobalObject* aGlobal, nsISupports* aParent,
Promise* aPromise)
CacheOpChild::CacheOpChild(CacheWorkerRef* aWorkerRef, nsIGlobalObject* aGlobal,
nsISupports* aParent, Promise* aPromise)
: mGlobal(aGlobal), mParent(aParent), mPromise(aPromise) {
MOZ_DIAGNOSTIC_ASSERT(mGlobal);
MOZ_DIAGNOSTIC_ASSERT(mParent);
MOZ_DIAGNOSTIC_ASSERT(mPromise);
MOZ_ASSERT_IF(!NS_IsMainThread(), aWorkerHolder);
MOZ_ASSERT_IF(!NS_IsMainThread(), aWorkerRef);
RefPtr<CacheWorkerHolder> workerHolder = CacheWorkerHolder::PreferBehavior(
aWorkerHolder, CacheWorkerHolder::PreventIdleShutdownStart);
RefPtr<CacheWorkerRef> workerRef = CacheWorkerRef::PreferBehavior(
aWorkerRef, CacheWorkerRef::eStrongWorkerRef);
SetWorkerHolder(workerHolder);
SetWorkerRef(workerRef);
}
CacheOpChild::~CacheOpChild() {
@ -87,7 +86,7 @@ void CacheOpChild::ActorDestroy(ActorDestroyReason aReason) {
mPromise = nullptr;
}
RemoveWorkerHolder();
RemoveWorkerRef();
}
mozilla::ipc::IPCResult CacheOpChild::Recv__delete__(
@ -147,11 +146,10 @@ mozilla::ipc::IPCResult CacheOpChild::Recv__delete__(
break;
}
RefPtr<CacheWorkerHolder> workerHolder =
CacheWorkerHolder::PreferBehavior(
GetWorkerHolder(), CacheWorkerHolder::AllowIdleShutdownStart);
RefPtr<CacheWorkerRef> workerRef = CacheWorkerRef::PreferBehavior(
GetWorkerRef(), CacheWorkerRef::eIPCWorkerRef);
actor->SetWorkerHolder(workerHolder);
actor->SetWorkerRef(workerRef);
RefPtr<Cache> cache = new Cache(mGlobal, actor, result.ns());
mPromise->MaybeResolve(cache);
break;
@ -176,7 +174,7 @@ mozilla::ipc::IPCResult CacheOpChild::Recv__delete__(
void CacheOpChild::StartDestroy() {
NS_ASSERT_OWNINGTHREAD(CacheOpChild);
// Do not cancel on-going operations when WorkerHolder calls this. Instead,
// Do not cancel on-going operations when WorkerRef calls this. Instead,
// keep the Worker alive until we are done.
}
@ -200,7 +198,7 @@ void CacheOpChild::HandleResponse(const Maybe<CacheResponse>& aMaybeResponse) {
const CacheResponse& cacheResponse = aMaybeResponse.ref();
AddWorkerHolderToStreamChild(cacheResponse, GetWorkerHolder());
AddWorkerRefToStreamChild(cacheResponse, GetWorkerRef());
RefPtr<Response> response = ToResponse(cacheResponse);
mPromise->MaybeResolve(response);
@ -212,7 +210,7 @@ void CacheOpChild::HandleResponseList(
responses.SetCapacity(aResponseList.Length());
for (uint32_t i = 0; i < aResponseList.Length(); ++i) {
AddWorkerHolderToStreamChild(aResponseList[i], GetWorkerHolder());
AddWorkerRefToStreamChild(aResponseList[i], GetWorkerRef());
responses.AppendElement(ToResponse(aResponseList[i]));
}
@ -225,7 +223,7 @@ void CacheOpChild::HandleRequestList(
requests.SetCapacity(aRequestList.Length());
for (uint32_t i = 0; i < aRequestList.Length(); ++i) {
AddWorkerHolderToStreamChild(aRequestList[i], GetWorkerHolder());
AddWorkerRefToStreamChild(aRequestList[i], GetWorkerRef());
requests.AppendElement(ToRequest(aRequestList[i]));
}

2
dom/cache/CacheOpChild.h поставляемый
Просмотреть файл

@ -31,7 +31,7 @@ class CacheOpChild final : public PCacheOpChild,
private:
// This class must be constructed by CacheChild or CacheStorageChild using
// their ExecuteOp() factory method.
CacheOpChild(CacheWorkerHolder* aWorkerHolder, nsIGlobalObject* aGlobal,
CacheOpChild(CacheWorkerRef* aWorkerRef, nsIGlobalObject* aGlobal,
nsISupports* aParent, Promise* aPromise);
~CacheOpChild();

18
dom/cache/CacheStorage.cpp поставляемый
Просмотреть файл

@ -16,7 +16,7 @@
#include "mozilla/dom/cache/Cache.h"
#include "mozilla/dom/cache/CacheChild.h"
#include "mozilla/dom/cache/CacheStorageChild.h"
#include "mozilla/dom/cache/CacheWorkerHolder.h"
#include "mozilla/dom/cache/CacheWorkerRef.h"
#include "mozilla/dom/cache/PCacheChild.h"
#include "mozilla/dom/cache/ReadStream.h"
#include "mozilla/dom/cache/TypeUtils.h"
@ -189,9 +189,9 @@ already_AddRefed<CacheStorage> CacheStorage::CreateOnWorker(
return ref.forget();
}
RefPtr<CacheWorkerHolder> workerHolder = CacheWorkerHolder::Create(
aWorkerPrivate, CacheWorkerHolder::AllowIdleShutdownStart);
if (!workerHolder) {
RefPtr<CacheWorkerRef> workerRef =
CacheWorkerRef::Create(aWorkerPrivate, CacheWorkerRef::eIPCWorkerRef);
if (!workerRef) {
NS_WARNING("Worker thread is shutting down.");
aRv.Throw(NS_ERROR_FAILURE);
return nullptr;
@ -230,7 +230,7 @@ already_AddRefed<CacheStorage> CacheStorage::CreateOnWorker(
}
RefPtr<CacheStorage> ref =
new CacheStorage(aNamespace, aGlobal, principalInfo, workerHolder);
new CacheStorage(aNamespace, aGlobal, principalInfo, workerRef);
return ref.forget();
}
@ -268,7 +268,7 @@ bool CacheStorage::DefineCaches(JSContext* aCx, JS::Handle<JSObject*> aGlobal) {
CacheStorage::CacheStorage(Namespace aNamespace, nsIGlobalObject* aGlobal,
const PrincipalInfo& aPrincipalInfo,
CacheWorkerHolder* aWorkerHolder)
CacheWorkerRef* aWorkerRef)
: mNamespace(aNamespace),
mGlobal(aGlobal),
mPrincipalInfo(MakeUnique<PrincipalInfo>(aPrincipalInfo)),
@ -284,10 +284,10 @@ CacheStorage::CacheStorage(Namespace aNamespace, nsIGlobalObject* aGlobal,
return;
}
// WorkerHolder ownership is passed to the CacheStorageChild actor and any
// actors it may create. The WorkerHolder will keep the worker thread alive
// WorkerRef ownership is passed to the CacheStorageChild actor and any
// actors it may create. The WorkerRef will keep the worker thread alive
// until the actors can gracefully shutdown.
CacheStorageChild* newActor = new CacheStorageChild(this, aWorkerHolder);
CacheStorageChild* newActor = new CacheStorageChild(this, aWorkerRef);
PCacheStorageChild* constructedActor = actor->SendPCacheStorageConstructor(
newActor, mNamespace, *mPrincipalInfo);

4
dom/cache/CacheStorage.h поставляемый
Просмотреть файл

@ -34,7 +34,7 @@ class WorkerPrivate;
namespace cache {
class CacheStorageChild;
class CacheWorkerHolder;
class CacheWorkerRef;
class CacheStorage final : public nsISupports,
public nsWrapperCache,
@ -86,7 +86,7 @@ class CacheStorage final : public nsISupports,
private:
CacheStorage(Namespace aNamespace, nsIGlobalObject* aGlobal,
const mozilla::ipc::PrincipalInfo& aPrincipalInfo,
CacheWorkerHolder* aWorkerHolder);
CacheWorkerRef* aWorkerRef);
explicit CacheStorage(nsresult aFailureResult);
~CacheStorage();

10
dom/cache/CacheStorageChild.cpp поставляемый
Просмотреть файл

@ -19,12 +19,12 @@ namespace cache {
void DeallocPCacheStorageChild(PCacheStorageChild* aActor) { delete aActor; }
CacheStorageChild::CacheStorageChild(CacheStorage* aListener,
CacheWorkerHolder* aWorkerHolder)
CacheWorkerRef* aWorkerRef)
: mListener(aListener), mNumChildActors(0), mDelayedDestroy(false) {
MOZ_COUNT_CTOR(cache::CacheStorageChild);
MOZ_DIAGNOSTIC_ASSERT(mListener);
SetWorkerHolder(aWorkerHolder);
SetWorkerRef(aWorkerRef);
}
CacheStorageChild::~CacheStorageChild() {
@ -44,7 +44,7 @@ void CacheStorageChild::ExecuteOp(nsIGlobalObject* aGlobal, Promise* aPromise,
const CacheOpArgs& aArgs) {
mNumChildActors += 1;
Unused << SendPCacheOpConstructor(
new CacheOpChild(GetWorkerHolder(), aGlobal, aParent, aPromise), aArgs);
new CacheOpChild(GetWorkerRef(), aGlobal, aParent, aPromise), aArgs);
}
void CacheStorageChild::StartDestroyFromListener() {
@ -73,7 +73,7 @@ void CacheStorageChild::StartDestroy() {
RefPtr<CacheStorage> listener = mListener;
// StartDestroy() can get called from either CacheStorage or the
// CacheWorkerHolder.
// CacheWorkerRef.
// Theoretically we can get double called if the right race happens. Handle
// that by just ignoring the second StartDestroy() call.
if (!listener) {
@ -98,7 +98,7 @@ void CacheStorageChild::ActorDestroy(ActorDestroyReason aReason) {
MOZ_DIAGNOSTIC_ASSERT(!mListener);
}
RemoveWorkerHolder();
RemoveWorkerRef();
}
PCacheOpChild* CacheStorageChild::AllocPCacheOpChild(

6
dom/cache/CacheStorageChild.h поставляемый
Просмотреть файл

@ -22,14 +22,14 @@ namespace cache {
class CacheOpArgs;
class CacheStorage;
class CacheWorkerHolder;
class CacheWorkerRef;
class PCacheChild;
class CacheStorageChild final : public PCacheStorageChild, public ActorChild {
friend class PCacheStorageChild;
public:
CacheStorageChild(CacheStorage* aListener, CacheWorkerHolder* aWorkerHolder);
CacheStorageChild(CacheStorage* aListener, CacheWorkerRef* aWorkerRef);
~CacheStorageChild();
// Must be called by the associated CacheStorage listener in its
@ -47,7 +47,7 @@ class CacheStorageChild final : public PCacheStorageChild, public ActorChild {
private:
// ActorChild methods
// CacheWorkerHolder is trying to destroy due to worker shutdown.
// CacheWorkerRef is trying to destroy due to worker shutdown.
virtual void StartDestroy() override;
// PCacheStorageChild methods

8
dom/cache/CacheStreamControlChild.cpp поставляемый
Просмотреть файл

@ -9,7 +9,7 @@
#include "mozilla/Unused.h"
#include "mozilla/dom/cache/ActorUtils.h"
#include "mozilla/dom/cache/CacheTypes.h"
#include "mozilla/dom/cache/CacheWorkerHolder.h"
#include "mozilla/dom/cache/CacheWorkerRef.h"
#include "mozilla/dom/cache/ReadStream.h"
#include "mozilla/ipc/FileDescriptorSetChild.h"
#include "mozilla/ipc/IPCStreamUtils.h"
@ -50,7 +50,7 @@ CacheStreamControlChild::~CacheStreamControlChild() {
void CacheStreamControlChild::StartDestroy() {
NS_ASSERT_OWNINGTHREAD(CacheStreamControlChild);
// This can get called twice under some circumstances. For example, if the
// actor is added to a CacheWorkerHolder that has already been notified and
// actor is added to a CacheWorkerRef that has already been notified and
// the Cache actor has no mListener.
if (mDestroyStarted) {
return;
@ -110,7 +110,7 @@ void CacheStreamControlChild::OpenStream(const nsID& aId,
// rejection here in many cases, we must handle the case where the
// MozPromise resolve runnable is already in the event queue when the
// worker wants to shut down.
RefPtr<CacheWorkerHolder> holder = GetWorkerHolder();
RefPtr<CacheWorkerRef> holder = GetWorkerRef();
SendOpenStream(aId)->Then(
GetCurrentThreadSerialEventTarget(), __func__,
@ -145,7 +145,7 @@ void CacheStreamControlChild::AssertOwningThread() {
void CacheStreamControlChild::ActorDestroy(ActorDestroyReason aReason) {
NS_ASSERT_OWNINGTHREAD(CacheStreamControlChild);
CloseAllReadStreamsWithoutReporting();
RemoveWorkerHolder();
RemoveWorkerRef();
}
mozilla::ipc::IPCResult CacheStreamControlChild::RecvClose(const nsID& aId) {

111
dom/cache/CacheWorkerHolder.cpp поставляемый
Просмотреть файл

@ -1,111 +0,0 @@
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#include "mozilla/dom/cache/CacheWorkerHolder.h"
#include "mozilla/dom/cache/ActorChild.h"
#include "mozilla/dom/WorkerPrivate.h"
namespace mozilla {
namespace dom {
namespace cache {
// static
already_AddRefed<CacheWorkerHolder> CacheWorkerHolder::Create(
WorkerPrivate* aWorkerPrivate, Behavior aBehavior) {
MOZ_DIAGNOSTIC_ASSERT(aWorkerPrivate);
RefPtr<CacheWorkerHolder> workerHolder = new CacheWorkerHolder(aBehavior);
if (NS_WARN_IF(!workerHolder->HoldWorker(aWorkerPrivate, Canceling))) {
return nullptr;
}
return workerHolder.forget();
}
// static
already_AddRefed<CacheWorkerHolder> CacheWorkerHolder::PreferBehavior(
CacheWorkerHolder* aCurrentHolder, Behavior aBehavior) {
if (!aCurrentHolder) {
return nullptr;
}
RefPtr<CacheWorkerHolder> orig = aCurrentHolder;
if (orig->GetBehavior() == aBehavior) {
return orig.forget();
}
RefPtr<CacheWorkerHolder> replace = Create(orig->mWorkerPrivate, aBehavior);
if (!replace) {
return orig.forget();
}
return replace.forget();
}
void CacheWorkerHolder::AddActor(ActorChild* aActor) {
NS_ASSERT_OWNINGTHREAD(CacheWorkerHolder);
MOZ_DIAGNOSTIC_ASSERT(aActor);
MOZ_ASSERT(!mActorList.Contains(aActor));
mActorList.AppendElement(aActor);
// Allow an actor to be added after we've entered the Notifying case. We
// can't stop the actor creation from racing with out destruction of the
// other actors and we need to wait for this extra one to close as well.
// Signal it should destroy itself right away.
if (mNotified) {
aActor->StartDestroy();
}
}
void CacheWorkerHolder::RemoveActor(ActorChild* aActor) {
NS_ASSERT_OWNINGTHREAD(CacheWorkerHolder);
MOZ_DIAGNOSTIC_ASSERT(aActor);
#if defined(RELEASE_OR_BETA)
mActorList.RemoveElement(aActor);
#else
MOZ_DIAGNOSTIC_ASSERT(mActorList.RemoveElement(aActor));
#endif
MOZ_ASSERT(!mActorList.Contains(aActor));
}
bool CacheWorkerHolder::Notified() const { return mNotified; }
bool CacheWorkerHolder::Notify(WorkerStatus aStatus) {
NS_ASSERT_OWNINGTHREAD(CacheWorkerHolder);
// When the service worker thread is stopped we will get Canceling,
// but nothing higher than that. We must shut things down at Canceling.
if (aStatus < Canceling || mNotified) {
return true;
}
mNotified = true;
// Start the asynchronous destruction of our actors. These will call back
// into RemoveActor() once the actor is destroyed.
for (uint32_t i = 0; i < mActorList.Length(); ++i) {
MOZ_DIAGNOSTIC_ASSERT(mActorList[i]);
mActorList[i]->StartDestroy();
}
return true;
}
CacheWorkerHolder::CacheWorkerHolder(Behavior aBehavior)
: WorkerHolder("CacheWorkerHolder", aBehavior), mNotified(false) {}
CacheWorkerHolder::~CacheWorkerHolder() {
NS_ASSERT_OWNINGTHREAD(CacheWorkerHolder);
MOZ_DIAGNOSTIC_ASSERT(mActorList.IsEmpty());
}
} // namespace cache
} // namespace dom
} // namespace mozilla

54
dom/cache/CacheWorkerHolder.h поставляемый
Просмотреть файл

@ -1,54 +0,0 @@
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#ifndef mozilla_dom_cache_CacheWorkerHolder_h
#define mozilla_dom_cache_CacheWorkerHolder_h
#include "nsISupportsImpl.h"
#include "nsTArray.h"
#include "mozilla/dom/WorkerHolder.h"
namespace mozilla {
class WorkerPrivate;
namespace dom {
namespace cache {
class ActorChild;
class CacheWorkerHolder final : public WorkerHolder {
public:
static already_AddRefed<CacheWorkerHolder> Create(
WorkerPrivate* aWorkerPrivate, Behavior aBehavior);
static already_AddRefed<CacheWorkerHolder> PreferBehavior(
CacheWorkerHolder* aCurrentHolder, Behavior aBehavior);
void AddActor(ActorChild* aActor);
void RemoveActor(ActorChild* aActor);
bool Notified() const;
// WorkerHolder methods
virtual bool Notify(WorkerStatus aStatus) override;
private:
explicit CacheWorkerHolder(Behavior aBehavior);
~CacheWorkerHolder();
nsTArray<ActorChild*> mActorList;
bool mNotified;
public:
NS_INLINE_DECL_REFCOUNTING(mozilla::dom::cache::CacheWorkerHolder)
};
} // namespace cache
} // namespace dom
} // namespace mozilla
#endif // mozilla_dom_cache_CacheWorkerHolder_h

130
dom/cache/CacheWorkerRef.cpp поставляемый Normal file
Просмотреть файл

@ -0,0 +1,130 @@
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#include "mozilla/dom/cache/CacheWorkerRef.h"
#include "mozilla/dom/cache/ActorChild.h"
#include "mozilla/dom/WorkerPrivate.h"
#include "mozilla/dom/WorkerRef.h"
namespace mozilla {
namespace dom {
namespace cache {
// static
already_AddRefed<CacheWorkerRef> CacheWorkerRef::Create(
WorkerPrivate* aWorkerPrivate, Behavior aBehavior) {
MOZ_DIAGNOSTIC_ASSERT(aWorkerPrivate);
RefPtr<CacheWorkerRef> workerRef = new CacheWorkerRef(aBehavior);
if (aBehavior == eStrongWorkerRef) {
workerRef->mStrongWorkerRef =
StrongWorkerRef::Create(aWorkerPrivate, "CacheWorkerRef-Strong",
[workerRef] { workerRef->Notify(); });
} else {
MOZ_ASSERT(aBehavior == eIPCWorkerRef);
workerRef->mIPCWorkerRef =
IPCWorkerRef::Create(aWorkerPrivate, "CacheWorkerRef-IPC",
[workerRef] { workerRef->Notify(); });
}
if (NS_WARN_IF(!workerRef->mIPCWorkerRef && !workerRef->mStrongWorkerRef)) {
return nullptr;
}
return workerRef.forget();
}
// static
already_AddRefed<CacheWorkerRef> CacheWorkerRef::PreferBehavior(
CacheWorkerRef* aCurrentRef, Behavior aBehavior) {
if (!aCurrentRef) {
return nullptr;
}
RefPtr<CacheWorkerRef> orig = aCurrentRef;
if (orig->mBehavior == aBehavior) {
return orig.forget();
}
WorkerPrivate* workerPrivate = nullptr;
if (orig->mBehavior == eStrongWorkerRef) {
workerPrivate = orig->mStrongWorkerRef->Private();
} else {
MOZ_ASSERT(orig->mBehavior == eIPCWorkerRef);
workerPrivate = orig->mIPCWorkerRef->Private();
}
MOZ_ASSERT(workerPrivate);
RefPtr<CacheWorkerRef> replace = Create(workerPrivate, aBehavior);
if (!replace) {
return orig.forget();
}
return replace.forget();
}
void CacheWorkerRef::AddActor(ActorChild* aActor) {
NS_ASSERT_OWNINGTHREAD(CacheWorkerRef);
MOZ_DIAGNOSTIC_ASSERT(aActor);
MOZ_ASSERT(!mActorList.Contains(aActor));
mActorList.AppendElement(aActor);
// Allow an actor to be added after we've entered the Notifying case. We
// can't stop the actor creation from racing with out destruction of the
// other actors and we need to wait for this extra one to close as well.
// Signal it should destroy itself right away.
if (mNotified) {
aActor->StartDestroy();
}
}
void CacheWorkerRef::RemoveActor(ActorChild* aActor) {
NS_ASSERT_OWNINGTHREAD(CacheWorkerRef);
MOZ_DIAGNOSTIC_ASSERT(aActor);
#if defined(RELEASE_OR_BETA)
mActorList.RemoveElement(aActor);
#else
MOZ_DIAGNOSTIC_ASSERT(mActorList.RemoveElement(aActor));
#endif
MOZ_ASSERT(!mActorList.Contains(aActor));
if (mActorList.IsEmpty()) {
mStrongWorkerRef = nullptr;
mIPCWorkerRef = nullptr;
}
}
bool CacheWorkerRef::Notified() const { return mNotified; }
void CacheWorkerRef::Notify() {
NS_ASSERT_OWNINGTHREAD(CacheWorkerRef);
mNotified = true;
// Start the asynchronous destruction of our actors. These will call back
// into RemoveActor() once the actor is destroyed.
for (uint32_t i = 0; i < mActorList.Length(); ++i) {
MOZ_DIAGNOSTIC_ASSERT(mActorList[i]);
mActorList[i]->StartDestroy();
}
}
CacheWorkerRef::CacheWorkerRef(Behavior aBehavior)
: mBehavior(aBehavior), mNotified(false) {}
CacheWorkerRef::~CacheWorkerRef() {
NS_ASSERT_OWNINGTHREAD(CacheWorkerRef);
MOZ_DIAGNOSTIC_ASSERT(mActorList.IsEmpty());
}
} // namespace cache
} // namespace dom
} // namespace mozilla

64
dom/cache/CacheWorkerRef.h поставляемый Normal file
Просмотреть файл

@ -0,0 +1,64 @@
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#ifndef mozilla_dom_cache_CacheWorkerRef_h
#define mozilla_dom_cache_CacheWorkerRef_h
#include "nsISupportsImpl.h"
#include "nsTArray.h"
namespace mozilla {
namespace dom {
class IPCWorkerRef;
class StrongWorkerRef;
class WorkerPrivate;
namespace cache {
class ActorChild;
class CacheWorkerRef final {
public:
enum Behavior {
eStrongWorkerRef,
eIPCWorkerRef,
};
static already_AddRefed<CacheWorkerRef> Create(WorkerPrivate* aWorkerPrivate,
Behavior aBehavior);
static already_AddRefed<CacheWorkerRef> PreferBehavior(
CacheWorkerRef* aCurrentRef, Behavior aBehavior);
void AddActor(ActorChild* aActor);
void RemoveActor(ActorChild* aActor);
bool Notified() const;
private:
explicit CacheWorkerRef(Behavior aBehavior);
~CacheWorkerRef();
void Notify();
nsTArray<ActorChild*> mActorList;
Behavior mBehavior;
bool mNotified;
RefPtr<StrongWorkerRef> mStrongWorkerRef;
RefPtr<IPCWorkerRef> mIPCWorkerRef;
public:
NS_INLINE_DECL_REFCOUNTING(mozilla::dom::cache::CacheWorkerRef)
};
} // namespace cache
} // namespace dom
} // namespace mozilla
#endif // mozilla_dom_cache_CacheWorkerRef_h

4
dom/cache/moz.build поставляемый
Просмотреть файл

@ -23,7 +23,7 @@ EXPORTS.mozilla.dom.cache += [
'CacheStorageParent.h',
'CacheStreamControlChild.h',
'CacheStreamControlParent.h',
'CacheWorkerHolder.h',
'CacheWorkerRef.h',
'Connection.h',
'Context.h',
'DBAction.h',
@ -56,7 +56,7 @@ UNIFIED_SOURCES += [
'CacheStorageParent.cpp',
'CacheStreamControlChild.cpp',
'CacheStreamControlParent.cpp',
'CacheWorkerHolder.cpp',
'CacheWorkerRef.cpp',
'Connection.cpp',
'Context.cpp',
'DBAction.cpp',

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

@ -42,7 +42,8 @@ struct ImageCacheEntryData {
: mImage(aOther.mImage),
mCanvas(aOther.mCanvas),
mSourceSurface(aOther.mSourceSurface),
mSize(aOther.mSize) {}
mSize(aOther.mSize),
mIntrinsicSize(aOther.mIntrinsicSize) {}
explicit ImageCacheEntryData(const ImageCacheKey& aKey)
: mImage(aKey.mImage), mCanvas(aKey.mCanvas) {}
@ -55,6 +56,7 @@ struct ImageCacheEntryData {
// Value
RefPtr<SourceSurface> mSourceSurface;
IntSize mSize;
IntSize mIntrinsicSize;
nsExpirationState mState;
};
@ -257,7 +259,8 @@ static already_AddRefed<imgIContainer> GetImageContainer(dom::Element* aImage) {
void CanvasImageCache::NotifyDrawImage(Element* aImage,
HTMLCanvasElement* aCanvas,
SourceSurface* aSource,
const IntSize& aSize) {
const IntSize& aSize,
const IntSize& aIntrinsicSize) {
if (!gImageCache) {
gImageCache = new ImageCache();
nsContentUtils::RegisterShutdownObserver(
@ -284,6 +287,7 @@ void CanvasImageCache::NotifyDrawImage(Element* aImage,
gImageCache->AddObject(entry->mData);
entry->mData->mSourceSurface = aSource;
entry->mData->mSize = aSize;
entry->mData->mIntrinsicSize = aIntrinsicSize;
gImageCache->mTotal += entry->mData->SizeInBytes();
AllCanvasImageCacheEntry* allEntry =
@ -321,7 +325,8 @@ SourceSurface* CanvasImageCache::LookupAllCanvas(Element* aImage) {
SourceSurface* CanvasImageCache::LookupCanvas(Element* aImage,
HTMLCanvasElement* aCanvas,
IntSize* aSizeOut) {
IntSize* aSizeOut,
IntSize* aIntrinsicSizeOut) {
if (!gImageCache) {
return nullptr;
}
@ -341,6 +346,7 @@ SourceSurface* CanvasImageCache::LookupCanvas(Element* aImage,
gImageCache->MarkUsed(entry->mData);
*aSizeOut = entry->mData->mSize;
*aIntrinsicSizeOut = entry->mData->mIntrinsicSize;
return entry->mData->mSourceSurface;
}

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

@ -29,12 +29,13 @@ class CanvasImageCache {
/**
* Notify that image element aImage was drawn to aCanvas element
* using the first frame of aRequest's image. The data for the surface is
* in aSurface, and the image size is in aSize.
* in aSurface, and the image size is in aSize. aIntrinsicSize is the size
* the surface is intended to be rendered at.
*/
static void NotifyDrawImage(dom::Element* aImage,
dom::HTMLCanvasElement* aCanvas,
SourceSurface* aSource,
const gfx::IntSize& aSize);
SourceSurface* aSource, const gfx::IntSize& aSize,
const gfx::IntSize& aIntrinsicSize);
/**
* Check whether aImage has recently been drawn any canvas. If we return
@ -48,7 +49,8 @@ class CanvasImageCache {
*/
static SourceSurface* LookupCanvas(dom::Element* aImage,
dom::HTMLCanvasElement* aCanvas,
gfx::IntSize* aSizeOut);
gfx::IntSize* aSizeOut,
gfx::IntSize* aIntrinsicSizeOut);
};
} // namespace mozilla

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

@ -4288,7 +4288,7 @@ CanvasRenderingContext2D::CachedSurfaceFromElement(Element* aElement) {
res.mCORSUsed = corsmode != imgIRequest::CORS_NONE;
}
res.mSize = res.mSourceSurface->GetSize();
res.mSize = res.mIntrinsicSize = res.mSourceSurface->GetSize();
res.mPrincipal = principal.forget();
res.mImageRequest = imgRequest.forget();
res.mIsWriteOnly = CheckWriteOnlySecurity(res.mCORSUsed, res.mPrincipal,
@ -4331,6 +4331,7 @@ void CanvasRenderingContext2D::DrawImage(const CanvasImageSource& aImage,
RefPtr<SourceSurface> srcSurf;
gfx::IntSize imgSize;
gfx::IntSize intrinsicImgSize;
Element* element = nullptr;
@ -4363,7 +4364,8 @@ void CanvasRenderingContext2D::DrawImage(const CanvasImageSource& aImage,
SetWriteOnly();
}
imgSize = gfx::IntSize(imageBitmap.Width(), imageBitmap.Height());
imgSize = intrinsicImgSize =
gfx::IntSize(imageBitmap.Width(), imageBitmap.Height());
} else {
if (aImage.IsHTMLImageElement()) {
HTMLImageElement* img = &aImage.GetAsHTMLImageElement();
@ -4378,7 +4380,8 @@ void CanvasRenderingContext2D::DrawImage(const CanvasImageSource& aImage,
element = video;
}
srcSurf = CanvasImageCache::LookupCanvas(element, mCanvasElement, &imgSize);
srcSurf = CanvasImageCache::LookupCanvas(element, mCanvasElement, &imgSize,
&intrinsicImgSize);
}
nsLayoutUtils::DirectDrawInfo drawInfo;
@ -4408,18 +4411,7 @@ void CanvasRenderingContext2D::DrawImage(const CanvasImageSource& aImage,
}
imgSize = res.mSize;
// Scale sw/sh based on aspect ratio
if (aImage.IsHTMLVideoElement()) {
HTMLVideoElement* video = &aImage.GetAsHTMLVideoElement();
int32_t displayWidth = video->VideoWidth();
int32_t displayHeight = video->VideoHeight();
if (displayWidth == 0 || displayHeight == 0) {
return;
}
aSw *= (double)imgSize.width / (double)displayWidth;
aSh *= (double)imgSize.height / (double)displayHeight;
}
intrinsicImgSize = res.mIntrinsicSize;
if (mCanvasElement) {
CanvasUtils::DoDrawImageSecurityCheck(mCanvasElement, res.mPrincipal,
@ -4429,7 +4421,8 @@ void CanvasRenderingContext2D::DrawImage(const CanvasImageSource& aImage,
if (res.mSourceSurface) {
if (res.mImageRequest) {
CanvasImageCache::NotifyDrawImage(element, mCanvasElement,
res.mSourceSurface, imgSize);
res.mSourceSurface, imgSize,
intrinsicImgSize);
}
srcSurf = res.mSourceSurface;
} else {
@ -4439,8 +4432,10 @@ void CanvasRenderingContext2D::DrawImage(const CanvasImageSource& aImage,
if (aOptional_argc == 0) {
aSx = aSy = 0.0;
aDw = aSw = (double)imgSize.width;
aDh = aSh = (double)imgSize.height;
aSw = (double)imgSize.width;
aSh = (double)imgSize.height;
aDw = (double)intrinsicImgSize.width;
aDh = (double)intrinsicImgSize.height;
} else if (aOptional_argc == 2) {
aSx = aSy = 0.0;
aSw = (double)imgSize.width;

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

@ -455,7 +455,7 @@ bool WebGLContext::CreateAndInitGL(
}
// WebGL2 is separately blocked:
if (IsWebGL2()) {
if (IsWebGL2() && !forceEnabled) {
const nsCOMPtr<nsIGfxInfo> gfxInfo = services::GetGfxInfo();
const auto feature = nsIGfxInfo::FEATURE_WEBGL2;

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

@ -9,7 +9,6 @@
#include "mozilla/dom/ClientIPCTypes.h"
#include "mozilla/dom/ClientOpPromise.h"
#include "mozilla/dom/DOMMozPromiseRequestHolder.h"
#include "mozilla/dom/WorkerHolderToken.h"
#include "mozilla/dom/WorkerPrivate.h"
class nsIGlobalObject;

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

@ -11,7 +11,6 @@
#include "ClientManagerOpChild.h"
#include "ClientPrefs.h"
#include "ClientSource.h"
#include "mozilla/dom/WorkerHolderToken.h"
#include "mozilla/dom/WorkerPrivate.h"
#include "mozilla/ipc/BackgroundChild.h"
#include "mozilla/ipc/PBackgroundChild.h"
@ -54,27 +53,12 @@ ClientManager::ClientManager() {
return;
}
RefPtr<WorkerHolderToken> workerHolderToken;
if (!NS_IsMainThread()) {
WorkerPrivate* workerPrivate = GetCurrentThreadWorkerPrivate();
MOZ_DIAGNOSTIC_ASSERT(workerPrivate);
// Note, it would be nice to replace this with a WorkerRef, but
// currently there is no WorkerRef option that matches what we
// need here. We need something like a StrongWorkerRef that will
// let us keep the worker alive until our actor is destroyed, but
// we also need to use AllowIdleShutdownStart like WeakWorkerRef.
// We need AllowIdleShutdownStart since every worker thread will
// have a ClientManager to support creating its ClientSource.
workerHolderToken = WorkerHolderToken::Create(
workerPrivate, Canceling, WorkerHolderToken::AllowIdleShutdownStart);
if (NS_WARN_IF(!workerHolderToken)) {
Shutdown();
return;
}
ClientManagerChild* actor = ClientManagerChild::Create();
if (NS_WARN_IF(!actor)) {
Shutdown();
return;
}
ClientManagerChild* actor = new ClientManagerChild(workerHolderToken);
PClientManagerChild* sentActor =
parentActor->SendPClientManagerConstructor(actor);
if (NS_WARN_IF(!sentActor)) {

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

@ -11,14 +11,13 @@
#include "ClientNavigateOpChild.h"
#include "ClientSourceChild.h"
#include "mozilla/dom/WorkerRef.h"
namespace mozilla {
namespace dom {
void ClientManagerChild::ActorDestroy(ActorDestroyReason aReason) {
if (mWorkerHolderToken) {
mWorkerHolderToken->RemoveListener(this);
mWorkerHolderToken = nullptr;
}
mIPCWorkerRef = nullptr;
if (mManager) {
mManager->RevokeActor(this);
@ -81,19 +80,33 @@ bool ClientManagerChild::DeallocPClientSourceChild(PClientSourceChild* aActor) {
return true;
}
void ClientManagerChild::WorkerShuttingDown() { MaybeStartTeardown(); }
// static
ClientManagerChild* ClientManagerChild::Create() {
ClientManagerChild* actor = new ClientManagerChild();
ClientManagerChild::ClientManagerChild(WorkerHolderToken* aWorkerHolderToken)
: mManager(nullptr),
mWorkerHolderToken(aWorkerHolderToken),
mTeardownStarted(false) {
MOZ_ASSERT_IF(!NS_IsMainThread(), mWorkerHolderToken);
if (!NS_IsMainThread()) {
WorkerPrivate* workerPrivate = GetCurrentThreadWorkerPrivate();
MOZ_DIAGNOSTIC_ASSERT(workerPrivate);
if (mWorkerHolderToken) {
mWorkerHolderToken->AddListener(this);
RefPtr<IPCWorkerRefHelper<ClientManagerChild>> helper =
new IPCWorkerRefHelper<ClientManagerChild>(actor);
actor->mIPCWorkerRef = IPCWorkerRef::Create(
workerPrivate, "ClientManagerChild",
[helper] { helper->Actor()->MaybeStartTeardown(); });
if (NS_WARN_IF(!actor->mIPCWorkerRef)) {
delete actor;
return nullptr;
}
}
return actor;
}
ClientManagerChild::ClientManagerChild()
: mManager(nullptr), mTeardownStarted(false) {}
void ClientManagerChild::SetOwner(ClientThing<ClientManagerChild>* aThing) {
MOZ_DIAGNOSTIC_ASSERT(aThing);
MOZ_DIAGNOSTIC_ASSERT(!mManager);
@ -115,10 +128,10 @@ void ClientManagerChild::MaybeStartTeardown() {
}
WorkerPrivate* ClientManagerChild::GetWorkerPrivate() const {
if (!mWorkerHolderToken) {
if (!mIPCWorkerRef) {
return nullptr;
}
return mWorkerHolderToken->GetWorkerPrivate();
return mIPCWorkerRef->Private();
}
} // namespace dom

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

@ -8,20 +8,21 @@
#include "ClientThing.h"
#include "mozilla/dom/PClientManagerChild.h"
#include "mozilla/dom/WorkerHolderToken.h"
namespace mozilla {
namespace dom {
class IPCWorkerRef;
class WorkerPrivate;
class ClientManagerChild final : public PClientManagerChild,
public WorkerHolderToken::Listener {
class ClientManagerChild final : public PClientManagerChild {
ClientThing<ClientManagerChild>* mManager;
RefPtr<WorkerHolderToken> mWorkerHolderToken;
RefPtr<IPCWorkerRef> mIPCWorkerRef;
bool mTeardownStarted;
ClientManagerChild();
// PClientManagerChild interface
void ActorDestroy(ActorDestroyReason aReason) override;
@ -49,11 +50,8 @@ class ClientManagerChild final : public PClientManagerChild,
bool DeallocPClientSourceChild(PClientSourceChild* aActor) override;
// WorkerHolderToken::Listener interface
void WorkerShuttingDown() override;
public:
explicit ClientManagerChild(WorkerHolderToken* aWorkerHolderToken);
static ClientManagerChild* Create();
void SetOwner(ClientThing<ClientManagerChild>* aThing);

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

@ -46,9 +46,6 @@ class IDBTransaction final : public DOMEventTargetHelper, public nsIRunnable {
friend class indexedDB::BackgroundCursorChild;
friend class indexedDB::BackgroundRequestChild;
class WorkerHolder;
friend class WorkerHolder;
public:
enum Mode {
READ_ONLY = 0,

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

@ -1132,6 +1132,17 @@ void AudioCallbackDriver::CompleteAudioContextOperations(
}
}
TimeDuration AudioCallbackDriver::AudioOutputLatency() {
uint32_t latency_frames;
int rv = cubeb_stream_get_latency(mAudioStream, &latency_frames);
if (rv || mSampleRate == 0) {
return TimeDuration::FromSeconds(0.0);
}
return TimeDuration::FromSeconds(static_cast<double>(latency_frames) /
mSampleRate);
}
void AudioCallbackDriver::FallbackToSystemClockDriver() {
MOZ_ASSERT(!ThreadRunning());
GraphImpl()->GetMonitor().AssertCurrentThreadOwns();

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

@ -433,6 +433,9 @@ class AudioCallbackDriver : public GraphDriver,
void CompleteAudioContextOperations(AsyncCubebOperation aOperation);
// Returns the output latency for the current audio output stream.
TimeDuration AudioOutputLatency();
private:
/* Remove Mixer callbacks when switching */
void RemoveMixerCallback();

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

@ -2289,10 +2289,17 @@ static void ReduceConstraint(
}
// Keep mediaSource, ignore all other constraints.
auto& c = aConstraint.GetAsMediaTrackConstraints();
MOZ_DIAGNOSTIC_ASSERT(c.mMediaSource.WasPassed());
nsString mediaSource = c.mMediaSource.Value();
aConstraint.SetAsMediaTrackConstraints().mMediaSource.Construct(mediaSource);
Maybe<nsString> mediaSource;
if (aConstraint.GetAsMediaTrackConstraints().mMediaSource.WasPassed()) {
mediaSource =
Some(aConstraint.GetAsMediaTrackConstraints().mMediaSource.Value());
}
if (mediaSource) {
aConstraint.SetAsMediaTrackConstraints().mMediaSource.Value() =
*mediaSource;
} else {
aConstraint.SetAsMediaTrackConstraints();
}
}
/**

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

@ -957,6 +957,10 @@ void MediaStreamGraphImpl::DeviceChanged() {
MediaStreamGraphImpl* mGraphImpl;
};
// Reset the latency, it will get fetched again next time it's queried.
MOZ_ASSERT(NS_IsMainThread());
mAudioOutputLatency = 0.0;
AppendMessage(MakeUnique<Message>(this));
}
@ -3192,7 +3196,8 @@ MediaStreamGraphImpl::MediaStreamGraphImpl(GraphDriverType aDriverRequested,
mCanRunMessagesSynchronously(false)
#endif
,
mMainThreadGraphTime(0, "MediaStreamGraphImpl::mMainThreadGraphTime") {
mMainThreadGraphTime(0, "MediaStreamGraphImpl::mMainThreadGraphTime"),
mAudioOutputLatency(0.0) {
if (mRealtime) {
if (aDriverRequested == AUDIO_THREAD_DRIVER) {
// Always start with zero input channels, and no particular preferences
@ -3796,6 +3801,29 @@ void MediaStreamGraph::ApplyAudioContextOperation(
aDestinationStream, aStreams, aOperation, aPromise, aFlags));
}
double MediaStreamGraph::AudioOutputLatency() {
return static_cast<MediaStreamGraphImpl*>(this)->AudioOutputLatency();
}
double MediaStreamGraphImpl::AudioOutputLatency() {
MOZ_ASSERT(NS_IsMainThread());
if (mAudioOutputLatency != 0.0) {
return mAudioOutputLatency;
}
MonitorAutoLock lock(mMonitor);
if (CurrentDriver()->AsAudioCallbackDriver()) {
mAudioOutputLatency = CurrentDriver()
->AsAudioCallbackDriver()
->AudioOutputLatency()
.ToSeconds();
} else {
// Failure mode: return 0.0 if running on a normal thread.
mAudioOutputLatency = 0.0;
}
return mAudioOutputLatency;
}
bool MediaStreamGraph::IsNonRealtime() const {
return !static_cast<const MediaStreamGraphImpl*>(this)->mRealtime;
}

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

@ -1272,6 +1272,8 @@ class MediaStreamGraph {
*/
TrackRate GraphRate() const { return mSampleRate; }
double AudioOutputLatency();
void RegisterCaptureStreamForWindow(uint64_t aWindowId,
ProcessedMediaStream* aCaptureStream);
void UnregisterCaptureStreamForWindow(uint64_t aWindowId);

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

@ -453,6 +453,8 @@ class MediaStreamGraphImpl : public MediaStreamGraph,
uint32_t AudioOutputChannelCount() const { return mOutputChannels; }
double AudioOutputLatency();
/**
* The audio input channel count for a MediaStreamGraph is the max of all the
* channel counts requested by the listeners. The max channel count is
@ -950,6 +952,12 @@ class MediaStreamGraphImpl : public MediaStreamGraph,
* Read by stable state runnable on main thread. Protected by mMonitor.
*/
GraphTime mNextMainThreadGraphTime = 0;
/**
* Cached audio output latency, in seconds. Main thread only. This is reset
* whenever the audio device running this MediaStreamGraph changes.
*/
double mAudioOutputLatency;
};
} // namespace mozilla

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

@ -36,6 +36,7 @@
#include "mozilla/dom/OscillatorNodeBinding.h"
#include "mozilla/dom/PannerNodeBinding.h"
#include "mozilla/dom/PeriodicWaveBinding.h"
#include "mozilla/dom/Performance.h"
#include "mozilla/dom/Promise.h"
#include "mozilla/dom/StereoPannerNodeBinding.h"
#include "mozilla/dom/WaveShaperNodeBinding.h"
@ -523,6 +524,48 @@ AudioListener* AudioContext::Listener() {
return mListener;
}
double AudioContext::OutputLatency() {
// When reduceFingerprinting is enabled, return a latency figure that is
// fixed, but plausible for the platform.
double latency_s = 0.0;
if (nsRFPService::IsResistFingerprintingEnabled()) {
#ifdef XP_MACOSX
latency_s = 512. / mSampleRate;
#elif MOZ_WIDGET_ANDROID
latency_s = 0.020;
#elif XP_WIN
latency_s = 0.04;
#else // Catchall for other OSes, including Linux.
latency_s = 0.025;
#endif
} else {
return Graph()->AudioOutputLatency();
}
return latency_s;
}
void AudioContext::GetOutputTimestamp(AudioTimestamp& aTimeStamp) {
if (!Destination()) {
aTimeStamp.mContextTime.Construct(0.0);
aTimeStamp.mPerformanceTime.Construct(0.0);
return;
}
// The currentTime currently being output is the currentTime minus the audio
// output latency. The resolution of CurrentTime() is already reduced.
aTimeStamp.mContextTime.Construct(
std::max(0.0, CurrentTime() - OutputLatency()));
nsPIDOMWindowInner* parent = GetParentObject();
Performance* perf = parent ? parent->GetPerformance() : nullptr;
if (perf) {
// perf->Now() already has reduced resolution here, no need to do it again.
aTimeStamp.mPerformanceTime.Construct(
std::max(0., perf->Now() - (OutputLatency() * 1000.)));
} else {
aTimeStamp.mPerformanceTime.Construct(0.0);
}
}
Worklet* AudioContext::GetAudioWorklet(ErrorResult& aRv) {
if (!mWorklet) {
mWorklet = AudioWorkletImpl::CreateWorklet(this, aRv);
@ -530,7 +573,6 @@ Worklet* AudioContext::GetAudioWorklet(ErrorResult& aRv) {
return mWorklet;
}
bool AudioContext::IsRunning() const {
return mAudioContextState == AudioContextState::Running;
}

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

@ -9,6 +9,7 @@
#include "AudioParamDescriptorMap.h"
#include "mozilla/dom/OfflineAudioContextBinding.h"
#include "mozilla/dom/AudioContextBinding.h"
#include "MediaBufferDecoder.h"
#include "mozilla/Attributes.h"
#include "mozilla/DOMEventTargetHelper.h"
@ -192,6 +193,16 @@ class AudioContext final : public DOMEventTargetHelper,
AudioContextState State() const { return mAudioContextState; }
double BaseLatency() const {
// Gecko does not do any buffering between rendering the audio and sending
// it to the audio subsystem.
return 0.0;
}
double OutputLatency();
void GetOutputTimestamp(AudioTimestamp& aTimeStamp);
Worklet* GetAudioWorklet(ErrorResult& aRv);
bool IsRunning() const;

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

@ -13,8 +13,31 @@
namespace mozilla {
namespace dom {
MediaElementAudioSourceNode::MediaElementAudioSourceNode(AudioContext* aContext)
: MediaStreamAudioSourceNode(aContext, TrackChangeBehavior::FollowChanges) {
NS_IMPL_CYCLE_COLLECTION_CLASS(MediaElementAudioSourceNode)
NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(MediaElementAudioSourceNode)
tmp->Destroy();
NS_IMPL_CYCLE_COLLECTION_UNLINK(mElement)
NS_IMPL_CYCLE_COLLECTION_UNLINK_END_INHERITED(AudioNode)
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_INHERITED(MediaElementAudioSourceNode,
MediaStreamAudioSourceNode)
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mElement)
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(MediaElementAudioSourceNode)
NS_INTERFACE_MAP_END_INHERITING(MediaStreamAudioSourceNode)
NS_IMPL_ADDREF_INHERITED(MediaElementAudioSourceNode,
MediaStreamAudioSourceNode)
NS_IMPL_RELEASE_INHERITED(MediaElementAudioSourceNode,
MediaStreamAudioSourceNode)
MediaElementAudioSourceNode::MediaElementAudioSourceNode(
AudioContext* aContext, HTMLMediaElement* aElement)
: MediaStreamAudioSourceNode(aContext, TrackChangeBehavior::FollowChanges),
mElement(aElement) {
MOZ_ASSERT(aElement);
}
/* static */
@ -28,7 +51,7 @@ MediaElementAudioSourceNode::Create(
}
RefPtr<MediaElementAudioSourceNode> node =
new MediaElementAudioSourceNode(&aAudioContext);
new MediaElementAudioSourceNode(&aAudioContext, aOptions.mMediaElement);
RefPtr<DOMMediaStream> stream = aOptions.mMediaElement->CaptureAudio(
aRv, aAudioContext.Destination()->Stream()->Graph());
@ -71,5 +94,9 @@ void MediaElementAudioSourceNode::Destroy() {
MediaStreamAudioSourceNode::Destroy();
}
HTMLMediaElement* MediaElementAudioSourceNode::MediaElement() {
return mElement;
}
} // namespace dom
} // namespace mozilla

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

@ -17,6 +17,9 @@ struct MediaElementAudioSourceOptions;
class MediaElementAudioSourceNode final : public MediaStreamAudioSourceNode {
public:
NS_DECL_ISUPPORTS_INHERITED
NS_DECL_CYCLE_COLLECTION_CLASS_INHERITED(MediaElementAudioSourceNode,
MediaStreamAudioSourceNode)
static already_AddRefed<MediaElementAudioSourceNode> Create(
AudioContext& aAudioContext,
const MediaElementAudioSourceOptions& aOptions, ErrorResult& aRv);
@ -42,8 +45,12 @@ class MediaElementAudioSourceNode final : public MediaStreamAudioSourceNode {
return aMallocSizeOf(this) + SizeOfExcludingThis(aMallocSizeOf);
}
HTMLMediaElement* MediaElement();
private:
explicit MediaElementAudioSourceNode(AudioContext* aContext);
explicit MediaElementAudioSourceNode(AudioContext* aContext,
HTMLMediaElement* aElement);
~MediaElementAudioSourceNode() = default;
void Destroy() override;
@ -52,6 +59,8 @@ class MediaElementAudioSourceNode final : public MediaStreamAudioSourceNode {
void ListenForAllowedToPlay(const MediaElementAudioSourceOptions& aOptions);
MozPromiseRequestHolder<GenericNonExclusivePromise> mAllowedToPlayRequest;
RefPtr<HTMLMediaElement> mElement;
};
} // namespace dom

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

@ -65,6 +65,8 @@ class MediaStreamAudioSourceNode
uint16_t NumberOfInputs() const override { return 0; }
DOMMediaStream* GetMediaStream() { return mInputStream; }
const char* NodeType() const override { return "MediaStreamAudioSourceNode"; }
virtual const char* CrossOriginErrorString() const {

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

@ -997,7 +997,7 @@ Notification::~Notification() {
mData.setUndefined();
mozilla::DropJSObjects(this);
AssertIsOnTargetThread();
MOZ_ASSERT(!mWorkerHolder);
MOZ_ASSERT(!mWorkerRef);
MOZ_ASSERT(!mTempRef);
}
@ -2054,10 +2054,10 @@ void Notification::InitFromBase64(const nsAString& aData, ErrorResult& aRv) {
bool Notification::AddRefObject() {
AssertIsOnTargetThread();
MOZ_ASSERT_IF(mWorkerPrivate && !mWorkerHolder, mTaskCount == 0);
MOZ_ASSERT_IF(mWorkerPrivate && mWorkerHolder, mTaskCount > 0);
if (mWorkerPrivate && !mWorkerHolder) {
if (!RegisterWorkerHolder()) {
MOZ_ASSERT_IF(mWorkerPrivate && !mWorkerRef, mTaskCount == 0);
MOZ_ASSERT_IF(mWorkerPrivate && mWorkerRef, mTaskCount > 0);
if (mWorkerPrivate && !mWorkerRef) {
if (!CreateWorkerRef()) {
return false;
}
}
@ -2069,21 +2069,16 @@ bool Notification::AddRefObject() {
void Notification::ReleaseObject() {
AssertIsOnTargetThread();
MOZ_ASSERT(mTaskCount > 0);
MOZ_ASSERT_IF(mWorkerPrivate, mWorkerHolder);
MOZ_ASSERT_IF(mWorkerPrivate, mWorkerRef);
--mTaskCount;
if (mWorkerPrivate && mTaskCount == 0) {
UnregisterWorkerHolder();
MOZ_ASSERT(mWorkerRef);
mWorkerRef = nullptr;
}
Release();
}
NotificationWorkerHolder::NotificationWorkerHolder(Notification* aNotification)
: WorkerHolder("NotificationWorkerHolder"), mNotification(aNotification) {
MOZ_ASSERT(mNotification->mWorkerPrivate);
mNotification->mWorkerPrivate->AssertIsOnWorkerThread();
}
/*
* Called from the worker, runs on main thread, blocks worker.
*
@ -2116,66 +2111,57 @@ class CloseNotificationRunnable final : public WorkerMainThreadRunnable {
bool HadObserver() { return mHadObserver; }
};
bool NotificationWorkerHolder::Notify(WorkerStatus aStatus) {
if (aStatus >= Canceling) {
// CloseNotificationRunnable blocks the worker by pushing a sync event loop
// on the stack. Meanwhile, WorkerControlRunnables dispatched to the worker
// can still continue running. One of these is
// ReleaseNotificationControlRunnable that releases the notification,
// invalidating the notification and this feature. We hold this reference to
// keep the notification valid until we are done with it.
//
// An example of when the control runnable could get dispatched to the
// worker is if a Notification is created and the worker is immediately
// closed, but there is no permission to show it so that the main thread
// immediately drops the NotificationRef. In this case, this function blocks
// on the main thread, but the main thread dispatches the control runnable,
// invalidating mNotification.
RefPtr<Notification> kungFuDeathGrip = mNotification;
// Dispatched to main thread, blocks on closing the Notification.
RefPtr<CloseNotificationRunnable> r =
new CloseNotificationRunnable(kungFuDeathGrip);
ErrorResult rv;
r->Dispatch(Killing, rv);
// XXXbz I'm told throwing and returning false from here is pointless (and
// also that doing sync stuff from here is really weird), so I guess we just
// suppress the exception on rv, if any.
rv.SuppressException();
// Only call ReleaseObject() to match the observer's NotificationRef
// ownership (since CloseNotificationRunnable asked the observer to drop the
// reference to the notification).
if (r->HadObserver()) {
kungFuDeathGrip->ReleaseObject();
}
// From this point we cannot touch properties of this feature because
// ReleaseObject() may have led to the notification going away and the
// notification owns this feature!
}
return true;
}
bool Notification::RegisterWorkerHolder() {
bool Notification::CreateWorkerRef() {
MOZ_ASSERT(mWorkerPrivate);
mWorkerPrivate->AssertIsOnWorkerThread();
MOZ_ASSERT(!mWorkerHolder);
mWorkerHolder = MakeUnique<NotificationWorkerHolder>(this);
if (NS_WARN_IF(!mWorkerHolder->HoldWorker(mWorkerPrivate, Canceling))) {
MOZ_ASSERT(!mWorkerRef);
RefPtr<Notification> self = this;
mWorkerRef =
StrongWorkerRef::Create(mWorkerPrivate, "Notification", [self]() {
// CloseNotificationRunnable blocks the worker by pushing a sync event
// loop on the stack. Meanwhile, WorkerControlRunnables dispatched to
// the worker can still continue running. One of these is
// ReleaseNotificationControlRunnable that releases the notification,
// invalidating the notification and this feature. We hold this
// reference to keep the notification valid until we are done with it.
//
// An example of when the control runnable could get dispatched to the
// worker is if a Notification is created and the worker is immediately
// closed, but there is no permission to show it so that the main thread
// immediately drops the NotificationRef. In this case, this function
// blocks on the main thread, but the main thread dispatches the control
// runnable, invalidating mNotification.
// Dispatched to main thread, blocks on closing the Notification.
RefPtr<CloseNotificationRunnable> r =
new CloseNotificationRunnable(self);
ErrorResult rv;
r->Dispatch(Killing, rv);
// XXXbz I'm told throwing and returning false from here is pointless
// (and also that doing sync stuff from here is really weird), so I
// guess we just suppress the exception on rv, if any.
rv.SuppressException();
// Only call ReleaseObject() to match the observer's NotificationRef
// ownership (since CloseNotificationRunnable asked the observer to drop
// the reference to the notification).
if (r->HadObserver()) {
self->ReleaseObject();
}
// From this point we cannot touch properties of this feature because
// ReleaseObject() may have led to the notification going away and the
// notification owns this feature!
});
if (NS_WARN_IF(!mWorkerRef)) {
return false;
}
return true;
}
void Notification::UnregisterWorkerHolder() {
MOZ_ASSERT(mWorkerPrivate);
mWorkerPrivate->AssertIsOnWorkerThread();
MOZ_ASSERT(mWorkerHolder);
mWorkerHolder = nullptr;
}
/*
* Checks:
* 1) Is aWorker allowed to show a notification for scope?

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

@ -10,7 +10,6 @@
#include "mozilla/DOMEventTargetHelper.h"
#include "mozilla/UniquePtr.h"
#include "mozilla/dom/NotificationBinding.h"
#include "mozilla/dom/WorkerHolder.h"
#include "nsIObserver.h"
#include "nsISupports.h"
@ -32,20 +31,9 @@ namespace dom {
class NotificationRef;
class WorkerNotificationObserver;
class Promise;
class StrongWorkerRef;
class WorkerPrivate;
class Notification;
class NotificationWorkerHolder final : public WorkerHolder {
// Since the feature is strongly held by a Notification, it is ok to hold
// a raw pointer here.
Notification* mNotification;
public:
explicit NotificationWorkerHolder(Notification* aNotification);
bool Notify(WorkerStatus aStatus) override;
};
// Records telemetry probes at application startup, when a notification is
// shown, and when the notification permission is revoked for a site.
class NotificationTelemetryService final : public nsIObserver {
@ -385,13 +373,12 @@ class Notification : public DOMEventTargetHelper,
bool IsTargetThread() const { return NS_IsMainThread() == !mWorkerPrivate; }
bool RegisterWorkerHolder();
void UnregisterWorkerHolder();
bool CreateWorkerRef();
nsresult ResolveIconAndSoundURL(nsString&, nsString&);
// Only used for Notifications on Workers, worker thread only.
UniquePtr<NotificationWorkerHolder> mWorkerHolder;
RefPtr<StrongWorkerRef> mWorkerRef;
// Target thread only.
uint32_t mTaskCount;
};

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

@ -59,26 +59,6 @@ class PerformanceEntryAdder final : public WorkerControlRunnable {
UniquePtr<PerformanceProxyData> mData;
};
class PerformanceStorageWorkerHolder final : public WorkerHolder {
RefPtr<PerformanceStorageWorker> mStorage;
public:
explicit PerformanceStorageWorkerHolder(PerformanceStorageWorker* aStorage)
: WorkerHolder("PerformanceStorageWorkerHolder",
WorkerHolder::AllowIdleShutdownStart),
mStorage(aStorage) {}
bool Notify(WorkerStatus aStatus) override {
if (mStorage) {
RefPtr<PerformanceStorageWorker> storage;
storage.swap(mStorage);
storage->ShutdownOnWorker();
}
return true;
}
};
} // namespace
/* static */

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

@ -199,22 +199,12 @@ RemoteServiceWorkerContainerImpl::RemoteServiceWorkerContainerImpl()
return;
}
RefPtr<WorkerHolderToken> workerHolderToken;
if (!NS_IsMainThread()) {
WorkerPrivate* workerPrivate = GetCurrentThreadWorkerPrivate();
MOZ_DIAGNOSTIC_ASSERT(workerPrivate);
workerHolderToken = WorkerHolderToken::Create(
workerPrivate, Canceling, WorkerHolderToken::AllowIdleShutdownStart);
if (NS_WARN_IF(!workerHolderToken)) {
Shutdown();
return;
}
ServiceWorkerContainerChild* actor = ServiceWorkerContainerChild::Create();
if (NS_WARN_IF(!actor)) {
Shutdown();
return;
}
ServiceWorkerContainerChild* actor =
new ServiceWorkerContainerChild(workerHolderToken);
PServiceWorkerContainerChild* sentActor =
parentActor->SendPServiceWorkerContainerConstructor(actor);
if (NS_WARN_IF(!sentActor)) {

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

@ -85,21 +85,12 @@ RemoteServiceWorkerImpl::RemoteServiceWorkerImpl(
return;
}
RefPtr<WorkerHolderToken> workerHolderToken;
if (!NS_IsMainThread()) {
WorkerPrivate* workerPrivate = GetCurrentThreadWorkerPrivate();
MOZ_DIAGNOSTIC_ASSERT(workerPrivate);
workerHolderToken = WorkerHolderToken::Create(
workerPrivate, Canceling, WorkerHolderToken::AllowIdleShutdownStart);
if (NS_WARN_IF(!workerHolderToken)) {
Shutdown();
return;
}
ServiceWorkerChild* actor = ServiceWorkerChild::Create();
if (NS_WARN_IF(!actor)) {
Shutdown();
return;
}
ServiceWorkerChild* actor = new ServiceWorkerChild(workerHolderToken);
PServiceWorkerChild* sentActor =
parentActor->SendPServiceWorkerConstructor(actor, aDescriptor.ToIPC());
if (NS_WARN_IF(!sentActor)) {

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

@ -114,22 +114,13 @@ RemoteServiceWorkerRegistrationImpl::RemoteServiceWorkerRegistrationImpl(
return;
}
RefPtr<WorkerHolderToken> workerHolderToken;
if (!NS_IsMainThread()) {
WorkerPrivate* workerPrivate = GetCurrentThreadWorkerPrivate();
MOZ_DIAGNOSTIC_ASSERT(workerPrivate);
workerHolderToken = WorkerHolderToken::Create(
workerPrivate, Canceling, WorkerHolderToken::AllowIdleShutdownStart);
if (NS_WARN_IF(!workerHolderToken)) {
Shutdown();
return;
}
ServiceWorkerRegistrationChild* actor =
ServiceWorkerRegistrationChild::Create();
if (NS_WARN_IF(!actor)) {
Shutdown();
return;
}
ServiceWorkerRegistrationChild* actor =
new ServiceWorkerRegistrationChild(workerHolderToken);
PServiceWorkerRegistrationChild* sentActor =
parentActor->SendPServiceWorkerRegistrationConstructor(
actor, aDescriptor.ToIPC());

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

@ -5,15 +5,13 @@
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#include "ServiceWorkerChild.h"
#include "mozilla/dom/WorkerRef.h"
namespace mozilla {
namespace dom {
void ServiceWorkerChild::ActorDestroy(ActorDestroyReason aReason) {
if (mWorkerHolderToken) {
mWorkerHolderToken->RemoveListener(this);
mWorkerHolderToken = nullptr;
}
mIPCWorkerRef = nullptr;
if (mOwner) {
mOwner->RevokeActor(this);
@ -21,17 +19,33 @@ void ServiceWorkerChild::ActorDestroy(ActorDestroyReason aReason) {
}
}
void ServiceWorkerChild::WorkerShuttingDown() { MaybeStartTeardown(); }
// static
ServiceWorkerChild* ServiceWorkerChild::Create() {
ServiceWorkerChild* actor = new ServiceWorkerChild();
ServiceWorkerChild::ServiceWorkerChild(WorkerHolderToken* aWorkerHolderToken)
: mWorkerHolderToken(aWorkerHolderToken),
mOwner(nullptr),
mTeardownStarted(false) {
if (mWorkerHolderToken) {
mWorkerHolderToken->AddListener(this);
if (!NS_IsMainThread()) {
WorkerPrivate* workerPrivate = GetCurrentThreadWorkerPrivate();
MOZ_DIAGNOSTIC_ASSERT(workerPrivate);
RefPtr<IPCWorkerRefHelper<ServiceWorkerChild>> helper =
new IPCWorkerRefHelper<ServiceWorkerChild>(actor);
actor->mIPCWorkerRef = IPCWorkerRef::Create(
workerPrivate, "ServiceWorkerChild",
[helper] { helper->Actor()->MaybeStartTeardown(); });
if (NS_WARN_IF(!actor->mIPCWorkerRef)) {
delete actor;
return nullptr;
}
}
return actor;
}
ServiceWorkerChild::ServiceWorkerChild()
: mOwner(nullptr), mTeardownStarted(false) {}
void ServiceWorkerChild::SetOwner(RemoteServiceWorkerImpl* aOwner) {
MOZ_DIAGNOSTIC_ASSERT(!mOwner);
MOZ_DIAGNOSTIC_ASSERT(aOwner);

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

@ -8,27 +8,26 @@
#define mozilla_dom_serviceworkerchild_h__
#include "mozilla/dom/PServiceWorkerChild.h"
#include "mozilla/dom/WorkerHolderToken.h"
namespace mozilla {
namespace dom {
class IPCWorkerRef;
class RemoteServiceWorkerImpl;
class ServiceWorkerChild final : public PServiceWorkerChild,
public WorkerHolderToken::Listener {
RefPtr<WorkerHolderToken> mWorkerHolderToken;
class ServiceWorkerChild final : public PServiceWorkerChild {
RefPtr<IPCWorkerRef> mIPCWorkerRef;
RemoteServiceWorkerImpl* mOwner;
bool mTeardownStarted;
ServiceWorkerChild();
// PServiceWorkerChild
void ActorDestroy(ActorDestroyReason aReason) override;
// WorkerHolderToken::Listener
void WorkerShuttingDown() override;
public:
explicit ServiceWorkerChild(WorkerHolderToken* aWorkerHolderToken);
static ServiceWorkerChild* Create();
~ServiceWorkerChild() = default;
void SetOwner(RemoteServiceWorkerImpl* aOwner);

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

@ -5,6 +5,7 @@
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#include "mozilla/dom/PServiceWorkerContainerChild.h"
#include "mozilla/dom/WorkerRef.h"
#include "RemoteServiceWorkerContainerImpl.h"
@ -12,10 +13,7 @@ namespace mozilla {
namespace dom {
void ServiceWorkerContainerChild::ActorDestroy(ActorDestroyReason aReason) {
if (mWorkerHolderToken) {
mWorkerHolderToken->RemoveListener(this);
mWorkerHolderToken = nullptr;
}
mIPCWorkerRef = nullptr;
if (mOwner) {
mOwner->RevokeActor(this);
@ -23,18 +21,32 @@ void ServiceWorkerContainerChild::ActorDestroy(ActorDestroyReason aReason) {
}
}
void ServiceWorkerContainerChild::WorkerShuttingDown() { MaybeStartTeardown(); }
// static
ServiceWorkerContainerChild* ServiceWorkerContainerChild::Create() {
ServiceWorkerContainerChild* actor = new ServiceWorkerContainerChild();
ServiceWorkerContainerChild::ServiceWorkerContainerChild(
WorkerHolderToken* aWorkerHolderToken)
: mWorkerHolderToken(aWorkerHolderToken),
mOwner(nullptr),
mTeardownStarted(false) {
if (mWorkerHolderToken) {
mWorkerHolderToken->AddListener(this);
if (!NS_IsMainThread()) {
WorkerPrivate* workerPrivate = GetCurrentThreadWorkerPrivate();
MOZ_DIAGNOSTIC_ASSERT(workerPrivate);
RefPtr<IPCWorkerRefHelper<ServiceWorkerContainerChild>> helper =
new IPCWorkerRefHelper<ServiceWorkerContainerChild>(actor);
actor->mIPCWorkerRef = IPCWorkerRef::Create(
workerPrivate, "ServiceWorkerContainerChild",
[helper] { helper->Actor()->MaybeStartTeardown(); });
if (NS_WARN_IF(!actor->mIPCWorkerRef)) {
delete actor;
return nullptr;
}
}
return actor;
}
ServiceWorkerContainerChild::ServiceWorkerContainerChild()
: mOwner(nullptr), mTeardownStarted(false) {}
void ServiceWorkerContainerChild::SetOwner(
RemoteServiceWorkerContainerImpl* aOwner) {
MOZ_DIAGNOSTIC_ASSERT(!mOwner);

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

@ -8,25 +8,25 @@
#define mozilla_dom_serviceworkercontainerchild_h__
#include "mozilla/dom/PServiceWorkerContainerChild.h"
#include "mozilla/dom/WorkerHolderToken.h"
namespace mozilla {
namespace dom {
class ServiceWorkerContainerChild final : public PServiceWorkerContainerChild,
public WorkerHolderToken::Listener {
RefPtr<WorkerHolderToken> mWorkerHolderToken;
class IPCWorkerRef;
class ServiceWorkerContainerChild final : public PServiceWorkerContainerChild {
RefPtr<IPCWorkerRef> mIPCWorkerRef;
RemoteServiceWorkerContainerImpl* mOwner;
bool mTeardownStarted;
ServiceWorkerContainerChild();
// PServiceWorkerContainerChild
void ActorDestroy(ActorDestroyReason aReason) override;
// WorkerHolderToken::Listener
void WorkerShuttingDown() override;
public:
explicit ServiceWorkerContainerChild(WorkerHolderToken* aWorkerHolderToken);
static ServiceWorkerContainerChild* Create();
~ServiceWorkerContainerChild() = default;
void SetOwner(RemoteServiceWorkerContainerImpl* aOwner);

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

@ -14,10 +14,7 @@ namespace dom {
using mozilla::ipc::IPCResult;
void ServiceWorkerRegistrationChild::ActorDestroy(ActorDestroyReason aReason) {
if (mWorkerHolderToken) {
mWorkerHolderToken->RemoveListener(this);
mWorkerHolderToken = nullptr;
}
mIPCWorkerRef = nullptr;
if (mOwner) {
mOwner->RevokeActor(this);
@ -40,19 +37,32 @@ IPCResult ServiceWorkerRegistrationChild::RecvFireUpdateFound() {
return IPC_OK();
}
void ServiceWorkerRegistrationChild::WorkerShuttingDown() {
MaybeStartTeardown();
// static
ServiceWorkerRegistrationChild* ServiceWorkerRegistrationChild::Create() {
ServiceWorkerRegistrationChild* actor = new ServiceWorkerRegistrationChild();
if (!NS_IsMainThread()) {
WorkerPrivate* workerPrivate = GetCurrentThreadWorkerPrivate();
MOZ_DIAGNOSTIC_ASSERT(workerPrivate);
RefPtr<IPCWorkerRefHelper<ServiceWorkerRegistrationChild>> helper =
new IPCWorkerRefHelper<ServiceWorkerRegistrationChild>(actor);
actor->mIPCWorkerRef = IPCWorkerRef::Create(
workerPrivate, "ServiceWorkerRegistrationChild",
[helper] { helper->Actor()->MaybeStartTeardown(); });
if (NS_WARN_IF(!actor->mIPCWorkerRef)) {
delete actor;
return nullptr;
}
}
return actor;
}
ServiceWorkerRegistrationChild::ServiceWorkerRegistrationChild(
WorkerHolderToken* aWorkerHolderToken)
: mWorkerHolderToken(aWorkerHolderToken),
mOwner(nullptr),
mTeardownStarted(false) {
if (mWorkerHolderToken) {
mWorkerHolderToken->AddListener(this);
}
}
ServiceWorkerRegistrationChild::ServiceWorkerRegistrationChild()
: mOwner(nullptr), mTeardownStarted(false) {}
void ServiceWorkerRegistrationChild::SetOwner(
RemoteServiceWorkerRegistrationImpl* aOwner) {

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

@ -8,20 +8,21 @@
#define mozilla_dom_serviceworkerregistrationchild_h__
#include "mozilla/dom/PServiceWorkerRegistrationChild.h"
#include "mozilla/dom/WorkerHolderToken.h"
namespace mozilla {
namespace dom {
class IPCWorkerRef;
class RemoteServiceWorkerRegistrationImpl;
class ServiceWorkerRegistrationChild final
: public PServiceWorkerRegistrationChild,
public WorkerHolderToken::Listener {
RefPtr<WorkerHolderToken> mWorkerHolderToken;
: public PServiceWorkerRegistrationChild {
RefPtr<IPCWorkerRef> mIPCWorkerRef;
RemoteServiceWorkerRegistrationImpl* mOwner;
bool mTeardownStarted;
ServiceWorkerRegistrationChild();
// PServiceWorkerRegistrationChild
void ActorDestroy(ActorDestroyReason aReason) override;
@ -30,12 +31,9 @@ class ServiceWorkerRegistrationChild final
mozilla::ipc::IPCResult RecvFireUpdateFound() override;
// WorkerHolderToken::Listener
void WorkerShuttingDown() override;
public:
explicit ServiceWorkerRegistrationChild(
WorkerHolderToken* aWorkerHolderToken);
static ServiceWorkerRegistrationChild* Create();
~ServiceWorkerRegistrationChild() = default;
void SetOwner(RemoteServiceWorkerRegistrationImpl* aOwner);

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

@ -14,12 +14,18 @@ dictionary AudioContextOptions {
float sampleRate = 0;
};
dictionary AudioTimestamp {
double contextTime;
DOMHighResTimeStamp performanceTime;
};
[Pref="dom.webaudio.enabled",
Constructor(optional AudioContextOptions contextOptions = {})]
interface AudioContext : BaseAudioContext {
// Bug 1324545: readonly attribute double outputLatency;
// Bug 1324545: AudioTimestamp getOutputTimestamp ();
readonly attribute double baseLatency;
readonly attribute double outputLatency;
AudioTimestamp getOutputTimestamp();
[Throws]
Promise<void> suspend();

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

@ -27,7 +27,6 @@ interface BaseAudioContext : EventTarget {
readonly attribute AudioContextState state;
[Throws, SameObject, SecureContext, Pref="dom.audioworklet.enabled"]
readonly attribute AudioWorklet audioWorklet;
// Bug 1324552: readonly attribute double baseLatency;
[Throws]
Promise<void> resume();

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

@ -17,7 +17,7 @@ dictionary MediaElementAudioSourceOptions {
[Pref="dom.webaudio.enabled",
Constructor(AudioContext context, MediaElementAudioSourceOptions options)]
interface MediaElementAudioSourceNode : AudioNode {
readonly attribute HTMLMediaElement mediaElement;
};
// Mozilla extensions

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

@ -17,7 +17,8 @@ dictionary MediaStreamAudioSourceOptions {
[Pref="dom.webaudio.enabled",
Constructor(AudioContext context, MediaStreamAudioSourceOptions options)]
interface MediaStreamAudioSourceNode : AudioNode {
[BinaryName="GetMediaStream"]
readonly attribute MediaStream mediaStream;
};
// Mozilla extensions

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

@ -73,7 +73,6 @@
#include "mozilla/dom/ServiceWorkerManager.h"
#include "mozilla/UniquePtr.h"
#include "Principal.h"
#include "WorkerHolder.h"
#include "WorkerPrivate.h"
#include "WorkerRunnable.h"
#include "WorkerScope.h"

Некоторые файлы не были показаны из-за слишком большого количества измененных файлов Показать больше