зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1648064 - Make service workers of the original document intercept the static document's requests. r=smaug,asuth
We need to set the original document ASAP so images triggered from the clone use the right service worker. It is a bit unfortunate to have the static document checks twice, but we may get to Document::GetClientInfo before the cloned doc has a window, so it's not 100% clear to me how we could avoid it. Differential Revision: https://phabricator.services.mozilla.com/D82081
This commit is contained in:
Родитель
d088111466
Коммит
91062db9ac
|
@ -7564,26 +7564,44 @@ Element* Document::GetAnonRootIfInAnonymousContentContainer(
|
|||
}
|
||||
|
||||
Maybe<ClientInfo> Document::GetClientInfo() const {
|
||||
nsPIDOMWindowInner* inner = GetInnerWindow();
|
||||
if (inner) {
|
||||
if (const Document* orig = GetOriginalDocument()) {
|
||||
if (Maybe<ClientInfo> info = orig->GetClientInfo()) {
|
||||
return info;
|
||||
}
|
||||
}
|
||||
|
||||
if (nsPIDOMWindowInner* inner = GetInnerWindow()) {
|
||||
return inner->GetClientInfo();
|
||||
}
|
||||
|
||||
return Maybe<ClientInfo>();
|
||||
}
|
||||
|
||||
Maybe<ClientState> Document::GetClientState() const {
|
||||
nsPIDOMWindowInner* inner = GetInnerWindow();
|
||||
if (inner) {
|
||||
if (const Document* orig = GetOriginalDocument()) {
|
||||
if (Maybe<ClientState> state = orig->GetClientState()) {
|
||||
return state;
|
||||
}
|
||||
}
|
||||
|
||||
if (nsPIDOMWindowInner* inner = GetInnerWindow()) {
|
||||
return inner->GetClientState();
|
||||
}
|
||||
|
||||
return Maybe<ClientState>();
|
||||
}
|
||||
|
||||
Maybe<ServiceWorkerDescriptor> Document::GetController() const {
|
||||
nsPIDOMWindowInner* inner = GetInnerWindow();
|
||||
if (inner) {
|
||||
if (const Document* orig = GetOriginalDocument()) {
|
||||
if (Maybe<ServiceWorkerDescriptor> controller = orig->GetController()) {
|
||||
return controller;
|
||||
}
|
||||
}
|
||||
|
||||
if (nsPIDOMWindowInner* inner = GetInnerWindow()) {
|
||||
return inner->GetController();
|
||||
}
|
||||
|
||||
return Maybe<ServiceWorkerDescriptor>();
|
||||
}
|
||||
|
||||
|
@ -11105,6 +11123,14 @@ nsresult Document::CloneDocHelper(Document* clone) const {
|
|||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
if (mCreatingStaticClone) {
|
||||
if (mOriginalDocument) {
|
||||
clone->mOriginalDocument = mOriginalDocument;
|
||||
} else {
|
||||
clone->mOriginalDocument = const_cast<Document*>(this);
|
||||
}
|
||||
clone->mOriginalDocument->mLatestStaticClone = clone;
|
||||
clone->mOriginalDocument->mStaticCloneCount++;
|
||||
|
||||
nsCOMPtr<nsILoadGroup> loadGroup;
|
||||
|
||||
// |mDocumentContainer| is the container of the document that is being
|
||||
|
@ -12117,16 +12143,6 @@ already_AddRefed<Document> Document::CreateStaticClone(
|
|||
|
||||
nsCOMPtr<Document> clonedDoc = do_QueryInterface(clonedNode);
|
||||
if (clonedDoc) {
|
||||
if (IsStaticDocument()) {
|
||||
clonedDoc->mOriginalDocument = mOriginalDocument;
|
||||
mOriginalDocument->mLatestStaticClone = clonedDoc;
|
||||
} else {
|
||||
clonedDoc->mOriginalDocument = this;
|
||||
mLatestStaticClone = clonedDoc;
|
||||
}
|
||||
|
||||
clonedDoc->mOriginalDocument->mStaticCloneCount++;
|
||||
|
||||
size_t sheetsCount = SheetCount();
|
||||
for (size_t i = 0; i < sheetsCount; ++i) {
|
||||
RefPtr<StyleSheet> sheet = SheetAt(i);
|
||||
|
|
|
@ -2809,7 +2809,7 @@ class Document : public nsINode,
|
|||
* If this document is a static clone, this returns the original
|
||||
* document.
|
||||
*/
|
||||
Document* GetOriginalDocument() {
|
||||
Document* GetOriginalDocument() const {
|
||||
MOZ_ASSERT(!mOriginalDocument || !mOriginalDocument->GetOriginalDocument());
|
||||
return mOriginalDocument;
|
||||
}
|
||||
|
|
|
@ -5476,6 +5476,12 @@ CallState nsGlobalWindowInner::CallOnInProcessChildren(Method aMethod,
|
|||
|
||||
Maybe<ClientInfo> nsGlobalWindowInner::GetClientInfo() const {
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
if (mDoc && mDoc->IsStaticDocument()) {
|
||||
if (Maybe<ClientInfo> info = mDoc->GetOriginalDocument()->GetClientInfo()) {
|
||||
return info;
|
||||
}
|
||||
}
|
||||
|
||||
Maybe<ClientInfo> clientInfo;
|
||||
if (mClientSource) {
|
||||
clientInfo.emplace(mClientSource->Info());
|
||||
|
@ -5485,6 +5491,13 @@ Maybe<ClientInfo> nsGlobalWindowInner::GetClientInfo() const {
|
|||
|
||||
Maybe<ClientState> nsGlobalWindowInner::GetClientState() const {
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
if (mDoc && mDoc->IsStaticDocument()) {
|
||||
if (Maybe<ClientState> state =
|
||||
mDoc->GetOriginalDocument()->GetClientState()) {
|
||||
return state;
|
||||
}
|
||||
}
|
||||
|
||||
Maybe<ClientState> clientState;
|
||||
if (mClientSource) {
|
||||
Result<ClientState, ErrorResult> res = mClientSource->SnapshotState();
|
||||
|
@ -5499,6 +5512,13 @@ Maybe<ClientState> nsGlobalWindowInner::GetClientState() const {
|
|||
|
||||
Maybe<ServiceWorkerDescriptor> nsGlobalWindowInner::GetController() const {
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
if (mDoc && mDoc->IsStaticDocument()) {
|
||||
if (Maybe<ServiceWorkerDescriptor> controller =
|
||||
mDoc->GetOriginalDocument()->GetController()) {
|
||||
return controller;
|
||||
}
|
||||
}
|
||||
|
||||
Maybe<ServiceWorkerDescriptor> controller;
|
||||
if (mClientSource) {
|
||||
controller = mClientSource->GetController();
|
||||
|
|
|
@ -24,6 +24,9 @@ support-files =
|
|||
printpreview_quirks_ref.html
|
||||
printpreview_images.html
|
||||
printpreview_images_ref.html
|
||||
printpreview_images_sw.html
|
||||
printpreview_images_sw_ref.html
|
||||
printpreview_images_sw.js
|
||||
test_document_adopted_styles.html
|
||||
test_document_adopted_styles_ref.html
|
||||
test_shadow_root_adopted_styles.html
|
||||
|
|
|
@ -405,20 +405,36 @@ async function runTest10() {
|
|||
requestAnimationFrame(function() { setTimeout(runTest11); } );
|
||||
}
|
||||
|
||||
async function compareFiles(src1, src2) {
|
||||
async function compareFiles(src1, src2, options = {}) {
|
||||
const BASE = "https://example.org/chrome/layout/base/tests/chrome/";
|
||||
|
||||
info(`Comparing ${src1} with ${src2}`);
|
||||
const iframeElement = document.getElementsByTagName("iframe")[0];
|
||||
|
||||
let messagePromise = null;
|
||||
if (options.waitForMessage) {
|
||||
messagePromise = new Promise(resolve => {
|
||||
iframeElement.addEventListener("message", resolve, { capture: true, once: true });
|
||||
});
|
||||
}
|
||||
|
||||
await new Promise((resolve) => {
|
||||
iframeElement.addEventListener("load", resolve, { capture: true, once: true });
|
||||
iframeElement.setAttribute("src", src1);
|
||||
iframeElement.setAttribute("src", BASE + src1);
|
||||
});
|
||||
|
||||
if (messagePromise) {
|
||||
info("awaiting for message to arrive");
|
||||
await messagePromise;
|
||||
}
|
||||
|
||||
await printpreview();
|
||||
ctx1.drawWindow(frameElts[1].contentWindow, 0, 0, 400, 400, "rgb(255,255,255)");
|
||||
exitprintpreview();
|
||||
|
||||
await new Promise((resolve) => {
|
||||
iframeElement.addEventListener("load", resolve, { capture: true, once: true });
|
||||
iframeElement.setAttribute("src", src2);
|
||||
iframeElement.setAttribute("src", BASE + src2);
|
||||
});
|
||||
|
||||
await printpreview();
|
||||
|
@ -470,6 +486,11 @@ async function runTest15() {
|
|||
// Various image tests.
|
||||
async function runTest16() {
|
||||
await compareFiles("printpreview_images.html", "printpreview_images_ref.html");
|
||||
requestAnimationFrame(function() { setTimeout(runTest17); } );
|
||||
}
|
||||
|
||||
async function runTest17() {
|
||||
await compareFiles("printpreview_images_sw.html", "printpreview_images_sw_ref.html", { waitForMessage: true });
|
||||
finish();
|
||||
}
|
||||
|
||||
|
|
|
@ -19,7 +19,7 @@
|
|||
</picture>
|
||||
<img src="blue-32x32.png" width=32 height=32>
|
||||
<object data="blue-32x32.png" width=32 height=32></object>
|
||||
<input type="image" src="blue-32x32.png" width=32 height=32>
|
||||
<svg width="32" height="32">
|
||||
<image x=0 y=0 href="blue-32x32.png" width=32 height=32></image>
|
||||
</svg>
|
||||
<input type="image" src="blue-32x32.png" width=32 height=32>
|
||||
|
|
|
@ -0,0 +1,46 @@
|
|||
<!doctype html>
|
||||
<style>
|
||||
img, object, svg, input { display: block }
|
||||
div {
|
||||
content: url(nonexistent.png?1);
|
||||
width: 32px;
|
||||
height: 32px;
|
||||
}
|
||||
</style>
|
||||
<script>
|
||||
const WORKER = "printpreview_images_sw.js";
|
||||
if (location.href.includes("registered")) {
|
||||
console.log("REGISTERED");
|
||||
onload = function() {
|
||||
postMessage("ready", "*");
|
||||
}
|
||||
onbeforeunload = function() {
|
||||
navigator.serviceWorker.getRegistrations().then(function(registrations) {
|
||||
for(let registration of registrations) {
|
||||
registration.unregister()
|
||||
}
|
||||
})
|
||||
navigator.serviceWorker.unregister(WORKER);
|
||||
}
|
||||
} else {
|
||||
navigator.serviceWorker.oncontrollerchange = function() {
|
||||
location.href = location.href + "?registered";
|
||||
};
|
||||
navigator.serviceWorker.register(WORKER);
|
||||
}
|
||||
</script>
|
||||
<div></div>
|
||||
<picture>
|
||||
<source srcset="nonexistent.png?2">
|
||||
<img width=32 height=32>
|
||||
</picture>
|
||||
<picture>
|
||||
<source srcset="nonexistent.png?3" media="print">
|
||||
<source srcset="animated.gif" media="not print">
|
||||
<img width=32 height=32>
|
||||
</picture>
|
||||
<img src="nonexistent.png?4" width=32 height=32>
|
||||
<svg width="32" height="32">
|
||||
<image x=0 y=0 href="nonexistent.png?7" width=32 height=32></image>
|
||||
</svg>
|
||||
<input type="image" src="nonexistent.png?6" width=32 height=32>
|
|
@ -0,0 +1,11 @@
|
|||
self.addEventListener("fetch", event => {
|
||||
if (event.request.url.includes("nonexistent.png")) {
|
||||
event.respondWith(
|
||||
fetch(event.request.url.replace("nonexistent.png", "blue-32x32.png"))
|
||||
);
|
||||
}
|
||||
});
|
||||
|
||||
self.addEventListener("activate", event => {
|
||||
event.waitUntil(clients.claim());
|
||||
});
|
|
@ -0,0 +1,14 @@
|
|||
<!doctype html>
|
||||
<style>
|
||||
div {
|
||||
width: 32px;
|
||||
height: 32px;
|
||||
background-color: blue;
|
||||
}
|
||||
</style>
|
||||
<div></div>
|
||||
<div></div>
|
||||
<div></div>
|
||||
<div></div>
|
||||
<div></div>
|
||||
<div></div>
|
Загрузка…
Ссылка в новой задаче