Commit 653f075d authored by rajendrant's avatar rajendrant Committed by Commit Bot

Clear the subresource redirect hints when navigation is started

RenderFrames could be reused for same-origin navigations. This causes
the hints from previous navigations to be used in next navigation
until the new hints fetch finishes and updates the hints. This CL clears
the hints.

Unfortunately this causes race conditions between the image fetch and
the hints update, which causes images to not redirected to compressed
versions. So the image fetches are delayed a bit to circumvent this.

Bug: 1051283
Change-Id: Ie9e5351e68c0081ab9dbfe23faed2c3c5e8e4d42
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2056207
Commit-Queue: rajendrant <rajendrant@chromium.org>
Reviewed-by: default avatarMichael Crouse <mcrouse@chromium.org>
Reviewed-by: default avatarTarun Bansal <tbansal@chromium.org>
Cr-Commit-Position: refs/heads/master@{#742326}
parent 1b8183e8
...@@ -114,7 +114,7 @@ SubresourceRedirectObserver::SubresourceRedirectObserver( ...@@ -114,7 +114,7 @@ SubresourceRedirectObserver::SubresourceRedirectObserver(
SubresourceRedirectObserver::~SubresourceRedirectObserver() = default; SubresourceRedirectObserver::~SubresourceRedirectObserver() = default;
void SubresourceRedirectObserver::ReadyToCommitNavigation( void SubresourceRedirectObserver::DidFinishNavigation(
content::NavigationHandle* navigation_handle) { content::NavigationHandle* navigation_handle) {
DCHECK(navigation_handle); DCHECK(navigation_handle);
if (!navigation_handle->IsInMainFrame() || if (!navigation_handle->IsInMainFrame() ||
......
...@@ -34,7 +34,7 @@ class SubresourceRedirectObserver ...@@ -34,7 +34,7 @@ class SubresourceRedirectObserver
explicit SubresourceRedirectObserver(content::WebContents* web_contents); explicit SubresourceRedirectObserver(content::WebContents* web_contents);
// content::WebContentsObserver. // content::WebContentsObserver.
void ReadyToCommitNavigation( void DidFinishNavigation(
content::NavigationHandle* navigation_handle) override; content::NavigationHandle* navigation_handle) override;
WEB_CONTENTS_USER_DATA_KEY_DECL(); WEB_CONTENTS_USER_DATA_KEY_DECL();
......
...@@ -48,15 +48,16 @@ GURL ResourceLoadingHintsAgent::GetDocumentURL() const { ...@@ -48,15 +48,16 @@ GURL ResourceLoadingHintsAgent::GetDocumentURL() const {
return render_frame()->GetWebFrame()->GetDocument().Url(); return render_frame()->GetWebFrame()->GetDocument().Url();
} }
void ResourceLoadingHintsAgent::DidStartNavigation(
const GURL& url,
base::Optional<blink::WebNavigationType> navigation_type) {
subresource_redirect_hints_agent_.DidStartNavigation();
}
void ResourceLoadingHintsAgent::DidCreateNewDocument() { void ResourceLoadingHintsAgent::DidCreateNewDocument() {
DCHECK(IsMainFrame()); DCHECK(IsMainFrame());
did_create_new_document_ = true;
if (!GetDocumentURL().SchemeIsHTTPOrHTTPS()) if (!GetDocumentURL().SchemeIsHTTPOrHTTPS())
return; return;
if (images_hints_) {
subresource_redirect_hints_agent_.SetCompressPublicImagesHints(
std::move(images_hints_));
}
if (subresource_patterns_to_block_.empty()) if (subresource_patterns_to_block_.empty())
return; return;
...@@ -110,13 +111,8 @@ void ResourceLoadingHintsAgent::SetResourceLoadingHints( ...@@ -110,13 +111,8 @@ void ResourceLoadingHintsAgent::SetResourceLoadingHints(
void ResourceLoadingHintsAgent::SetCompressPublicImagesHints( void ResourceLoadingHintsAgent::SetCompressPublicImagesHints(
blink::mojom::CompressPublicImagesHintsPtr images_hints) { blink::mojom::CompressPublicImagesHintsPtr images_hints) {
if (did_create_new_document_) { subresource_redirect_hints_agent_.SetCompressPublicImagesHints(
subresource_redirect_hints_agent_.SetCompressPublicImagesHints( std::move(images_hints));
std::move(images_hints));
} else {
// Let the hints be sent in DidCreateNewDocument.
images_hints_ = std::move(images_hints);
}
} }
} // namespace previews } // namespace previews
...@@ -46,6 +46,9 @@ class ResourceLoadingHintsAgent ...@@ -46,6 +46,9 @@ class ResourceLoadingHintsAgent
private: private:
// content::RenderFrameObserver: // content::RenderFrameObserver:
void DidStartNavigation(
const GURL& url,
base::Optional<blink::WebNavigationType> navigation_type) override;
void DidCreateNewDocument() override; void DidCreateNewDocument() override;
void OnDestruct() override; void OnDestruct() override;
...@@ -63,8 +66,6 @@ class ResourceLoadingHintsAgent ...@@ -63,8 +66,6 @@ class ResourceLoadingHintsAgent
bool IsMainFrame() const; bool IsMainFrame() const;
bool did_create_new_document_ = false;
std::vector<std::string> subresource_patterns_to_block_; std::vector<std::string> subresource_patterns_to_block_;
base::Optional<int64_t> ukm_source_id_; base::Optional<int64_t> ukm_source_id_;
...@@ -73,7 +74,6 @@ class ResourceLoadingHintsAgent ...@@ -73,7 +74,6 @@ class ResourceLoadingHintsAgent
subresource_redirect::SubresourceRedirectHintsAgent subresource_redirect::SubresourceRedirectHintsAgent
subresource_redirect_hints_agent_; subresource_redirect_hints_agent_;
blink::mojom::CompressPublicImagesHintsPtr images_hints_;
DISALLOW_COPY_AND_ASSIGN(ResourceLoadingHintsAgent); DISALLOW_COPY_AND_ASSIGN(ResourceLoadingHintsAgent);
}; };
......
...@@ -16,8 +16,17 @@ namespace subresource_redirect { ...@@ -16,8 +16,17 @@ namespace subresource_redirect {
SubresourceRedirectHintsAgent::SubresourceRedirectHintsAgent() = default; SubresourceRedirectHintsAgent::SubresourceRedirectHintsAgent() = default;
SubresourceRedirectHintsAgent::~SubresourceRedirectHintsAgent() = default; SubresourceRedirectHintsAgent::~SubresourceRedirectHintsAgent() = default;
void SubresourceRedirectHintsAgent::DidStartNavigation() {
// Clear the hints when a navigation starts, so that hints from previous
// navigation do not apply in case the same renderframe is reused.
public_image_urls_.clear();
public_image_urls_received_ = false;
}
void SubresourceRedirectHintsAgent::SetCompressPublicImagesHints( void SubresourceRedirectHintsAgent::SetCompressPublicImagesHints(
blink::mojom::CompressPublicImagesHintsPtr images_hints) { blink::mojom::CompressPublicImagesHintsPtr images_hints) {
DCHECK(public_image_urls_.empty());
DCHECK(!public_image_urls_received_);
public_image_urls_ = images_hints->image_urls; public_image_urls_ = images_hints->image_urls;
public_image_urls_received_ = true; public_image_urls_received_ = true;
} }
......
...@@ -40,6 +40,10 @@ class SubresourceRedirectHintsAgent { ...@@ -40,6 +40,10 @@ class SubresourceRedirectHintsAgent {
SubresourceRedirectHintsAgent& operator=( SubresourceRedirectHintsAgent& operator=(
const SubresourceRedirectHintsAgent&) = delete; const SubresourceRedirectHintsAgent&) = delete;
// Called when a navigation starts to clear the state from previous
// navigation.
void DidStartNavigation();
void SetCompressPublicImagesHints( void SetCompressPublicImagesHints(
blink::mojom::CompressPublicImagesHintsPtr images_hints); blink::mojom::CompressPublicImagesHintsPtr images_hints);
......
// Copyright (c) 2020 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
function checkImage() {
return imageLoadedPromise(document.images[0]);
}
function imageLoadedPromise(img_element) {
return new Promise((resolve, reject) => {
if (img_element.complete && img_element.src) {
console.log("image loaded callback", img_element.src);
resolve(true);
} else {
img_element.addEventListener('load', () => {
console.log("image loaded callback", img_element.src);
resolve(true);
});
}
});
}
function imageSrc() {
sendValueToTest(document.images[0].src);
}
function sendValueToTest(value) {
window.domAutomationController.send(value);
}
<html> <html>
<head></head> <head></head>
<img alt="long_placeholder_text" src="fail_image.png" /> <img alt="long_placeholder_text"/>
<script src="common.js"></script>
<script> <script>
function checkImage() { window.onload = () => {
sendValueToTest(document.images[0].complete); setTimeout(() => {
} document.images[0].src = "fail_image.png"
}, 1000);
function imageSrc() {
sendValueToTest(document.images[0].src);
}
function sendValueToTest(value) {
window.domAutomationController.send(value);
} }
</script> </script>
</html> </html>
<html>
<head></head>
<img alt="long_placeholder_text"/>
<script src="common.js"></script>
<script>
window.onload = () => {
setTimeout(() => {
document.images[0].src = "image.png"
}, 1000);
}
</script>
</html>
<html> <html>
<body> <body>
<div> div tag </div> <div> div tag </div>
<script src="common.js"></script>
<script> <script>
var img = document.createElement("img"); var img = document.createElement("img");
img.src="image.png"; img.src="image.png";
document.getElementsByTagName('div')[0].appendChild(img); document.getElementsByTagName('div')[0].appendChild(img);
function checkImage() {
sendValueToTest(document.images[0].complete);
}
function imageSrc() {
sendValueToTest(document.images[0].src);
}
function sendValueToTest(value) {
window.domAutomationController.send(value);
}
</script> </script>
</body> </body>
</html> </html>
\ No newline at end of file
<html> <html>
<head></head> <head></head>
<img alt="long_placeholder_text" src="image.png#fragment" /> <img alt="long_placeholder_text"/>
<script src="common.js"></script>
<script> <script>
function checkImage() { window.onload = () => {
sendValueToTest(document.images[0].complete); setTimeout(() => {
} document.images[0].src = "image.png#fragment"
}, 1000)
function imageSrc() {
sendValueToTest(document.images[0].src);
}
function sendValueToTest(value) {
window.domAutomationController.send(value);
} }
</script> </script>
</html> </html>
<html> <html>
<body> <body>
<img alt="long_placeholder_text" src="private_url_image.png" /> <img alt="long_placeholder_text"/>
<script src="common.js"></script>
<script> <script>
function checkImage() { window.onload = () => {
sendValueToTest((document.images[0].complete && (document.images[0].naturalWidth > 0))); setTimeout(() => {
} document.images[0].src = "private_url_image.png"
}, 1000)
function imageSrc() {
sendValueToTest(document.images[0].src);
}
function sendValueToTest(value) {
window.domAutomationController.send(value);
} }
</script> </script>
</body> </body>
</html> </html>
\ No newline at end of file
<html> <html>
<head></head> <head></head>
<img src="image.png" /> <img/>
<img src="image.png?foo" /> <img/>
<script src="common.js"></script>
<script> <script>
function checkBothImagesLoaded() { function checkBothImagesLoaded() {
sendValueToTest(document.images[0].complete && document.images[1].complete); return new Promise((resolve, reject) => {
Promise.all([imageLoadedPromise(document.images[0]),
imageLoadedPromise(document.images[1])]).then(() => {
resolve(true);
});
});
} }
function imageSrc() { window.onload = () => {
sendValueToTest(document.images[0].src); setTimeout(() => {
} document.images[0].src = "image.png"
document.images[1].src = "image.png?foo"
function sendValueToTest(value) { }, 1000)
window.domAutomationController.send(value);
} }
</script> </script>
</html> </html>
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment