summaryrefslogtreecommitdiff
path: root/chromium/content/browser/web_package
diff options
context:
space:
mode:
Diffstat (limited to 'chromium/content/browser/web_package')
-rw-r--r--chromium/content/browser/web_package/prefetched_signed_exchange_cache.cc9
-rw-r--r--chromium/content/browser/web_package/prefetched_signed_exchange_cache_adapter.cc18
-rw-r--r--chromium/content/browser/web_package/signed_exchange_certificate_chain.cc5
-rw-r--r--chromium/content/browser/web_package/signed_exchange_certificate_chain.h5
-rw-r--r--chromium/content/browser/web_package/signed_exchange_request_handler_browsertest.cc2
-rw-r--r--chromium/content/browser/web_package/signed_exchange_subresource_prefetch_browsertest.cc4
-rw-r--r--chromium/content/browser/web_package/web_bundle_blob_data_source.cc25
-rw-r--r--chromium/content/browser/web_package/web_bundle_browsertest.cc1221
-rw-r--r--chromium/content/browser/web_package/web_bundle_interceptor_for_history_navigation_with_existing_reader.cc23
-rw-r--r--chromium/content/browser/web_package/web_bundle_reader.cc19
10 files changed, 1130 insertions, 201 deletions
diff --git a/chromium/content/browser/web_package/prefetched_signed_exchange_cache.cc b/chromium/content/browser/web_package/prefetched_signed_exchange_cache.cc
index 0d3ae7b6004..82aeed5bf3f 100644
--- a/chromium/content/browser/web_package/prefetched_signed_exchange_cache.cc
+++ b/chromium/content/browser/web_package/prefetched_signed_exchange_cache.cc
@@ -8,7 +8,6 @@
#include "base/feature_list.h"
#include "base/metrics/histogram_macros.h"
#include "base/strings/stringprintf.h"
-#include "base/task/post_task.h"
#include "components/link_header_util/link_header_util.h"
#include "content/browser/loader/cross_origin_read_blocking_checker.h"
#include "content/browser/loader/navigation_loader_interceptor.h"
@@ -277,8 +276,8 @@ class InnerResponseURLLoader : public network::mojom::URLLoader {
return;
}
- base::PostTask(
- FROM_HERE, {BrowserThread::IO},
+ GetIOThreadTaskRunner({})->PostTask(
+ FROM_HERE,
base::BindOnce(
&InnerResponseURLLoader::CreateMojoBlobReader,
weak_factory_.GetWeakPtr(), std::move(pipe_producer_handle),
@@ -315,8 +314,8 @@ class InnerResponseURLLoader : public network::mojom::URLLoader {
static void BlobReaderCompleteOnIO(
base::WeakPtr<InnerResponseURLLoader> loader,
net::Error result) {
- base::PostTask(FROM_HERE, {BrowserThread::UI},
- base::BindOnce(&InnerResponseURLLoader::BlobReaderComplete,
+ GetUIThreadTaskRunner({})->PostTask(
+ FROM_HERE, base::BindOnce(&InnerResponseURLLoader::BlobReaderComplete,
std::move(loader), result));
}
diff --git a/chromium/content/browser/web_package/prefetched_signed_exchange_cache_adapter.cc b/chromium/content/browser/web_package/prefetched_signed_exchange_cache_adapter.cc
index 4dfc440e9d2..beb8f05dedc 100644
--- a/chromium/content/browser/web_package/prefetched_signed_exchange_cache_adapter.cc
+++ b/chromium/content/browser/web_package/prefetched_signed_exchange_cache_adapter.cc
@@ -4,9 +4,9 @@
#include "content/browser/web_package/prefetched_signed_exchange_cache_adapter.h"
-#include "base/task/post_task.h"
#include "content/browser/loader/prefetch_url_loader.h"
#include "content/public/browser/browser_task_traits.h"
+#include "content/public/browser/browser_thread.h"
#include "mojo/public/cpp/bindings/associated_remote.h"
#include "storage/browser/blob/blob_builder_from_stream.h"
#include "storage/browser/blob/blob_data_handle.h"
@@ -21,8 +21,8 @@ void AbortAndDeleteBlobBuilder(
return;
}
- base::PostTask(FROM_HERE, {BrowserThread::IO},
- base::BindOnce(&storage::BlobBuilderFromStream::Abort,
+ GetIOThreadTaskRunner({})->PostTask(
+ FROM_HERE, base::BindOnce(&storage::BlobBuilderFromStream::Abort,
std::move(blob_builder)));
}
@@ -81,8 +81,8 @@ void PrefetchedSignedExchangeCacheAdapter::OnStartLoadingResponseBody(
length_hint = cached_exchange_->inner_response()->content_length;
}
blob_is_streaming_ = true;
- base::PostTaskAndReplyWithResult(
- FROM_HERE, {BrowserThread::IO},
+ GetIOThreadTaskRunner({})->PostTaskAndReplyWithResult(
+ FROM_HERE,
base::BindOnce(
&PrefetchedSignedExchangeCacheAdapter::CreateBlobBuilderFromStream,
weak_factory_.GetWeakPtr(), std::move(body), length_hint,
@@ -103,8 +103,8 @@ void PrefetchedSignedExchangeCacheAdapter::StreamingBlobDone(
storage::BlobBuilderFromStream* builder,
std::unique_ptr<storage::BlobDataHandle> result) {
blob_is_streaming_ = false;
- base::DeleteSoon(FROM_HERE, {BrowserThread::IO},
- std::move(blob_builder_from_stream_));
+ GetIOThreadTaskRunner({})->DeleteSoon(FROM_HERE,
+ std::move(blob_builder_from_stream_));
cached_exchange_->SetBlobDataHandle(std::move(result));
MaybeCallOnSignedExchangeStored();
}
@@ -177,8 +177,8 @@ void PrefetchedSignedExchangeCacheAdapter::StreamingBlobDoneOnIO(
storage::BlobBuilderFromStream* builder,
std::unique_ptr<storage::BlobDataHandle> result) {
DCHECK_CURRENTLY_ON(BrowserThread::IO);
- base::PostTask(
- FROM_HERE, {BrowserThread::UI},
+ GetUIThreadTaskRunner({})->PostTask(
+ FROM_HERE,
base::BindOnce(&PrefetchedSignedExchangeCacheAdapter::StreamingBlobDone,
adapter, builder, std::move(result)));
}
diff --git a/chromium/content/browser/web_package/signed_exchange_certificate_chain.cc b/chromium/content/browser/web_package/signed_exchange_certificate_chain.cc
index d9151fdff48..ceb3dbffb01 100644
--- a/chromium/content/browser/web_package/signed_exchange_certificate_chain.cc
+++ b/chromium/content/browser/web_package/signed_exchange_certificate_chain.cc
@@ -213,9 +213,8 @@ SignedExchangeCertificateChain::IgnoreErrorsSPKIList::IgnoreErrorsSPKIList(
void SignedExchangeCertificateChain::IgnoreErrorsSPKIList::Parse(
const std::string& spki_list) {
- hash_set_ =
- network::IgnoreErrorsCertVerifier::MakeWhitelist(base::SplitString(
- spki_list, ",", base::TRIM_WHITESPACE, base::SPLIT_WANT_ALL));
+ hash_set_ = network::CreateSPKIHashSet(base::SplitString(
+ spki_list, ",", base::TRIM_WHITESPACE, base::SPLIT_WANT_ALL));
}
SignedExchangeCertificateChain::IgnoreErrorsSPKIList::~IgnoreErrorsSPKIList() =
diff --git a/chromium/content/browser/web_package/signed_exchange_certificate_chain.h b/chromium/content/browser/web_package/signed_exchange_certificate_chain.h
index 25e76b901f8..03e3159ea2e 100644
--- a/chromium/content/browser/web_package/signed_exchange_certificate_chain.h
+++ b/chromium/content/browser/web_package/signed_exchange_certificate_chain.h
@@ -8,12 +8,13 @@
#include <memory>
#include "base/containers/span.h"
+#include "base/gtest_prod_util.h"
#include "base/memory/scoped_refptr.h"
#include "base/optional.h"
#include "base/strings/string_piece_forward.h"
#include "content/browser/web_package/signed_exchange_consts.h"
#include "content/common/content_export.h"
-#include "services/network/ignore_errors_cert_verifier.h"
+#include "services/network/public/cpp/spki_hash_set.h"
namespace base {
class CommandLine;
@@ -60,7 +61,7 @@ class CONTENT_EXPORT SignedExchangeCertificateChain {
bool ShouldIgnoreErrorsInternal(
scoped_refptr<net::X509Certificate> certificate);
- network::IgnoreErrorsCertVerifier::SPKIHashSet hash_set_;
+ network::SPKIHashSet hash_set_;
DISALLOW_COPY_AND_ASSIGN(IgnoreErrorsSPKIList);
};
diff --git a/chromium/content/browser/web_package/signed_exchange_request_handler_browsertest.cc b/chromium/content/browser/web_package/signed_exchange_request_handler_browsertest.cc
index 455222105c5..f3c50a9027f 100644
--- a/chromium/content/browser/web_package/signed_exchange_request_handler_browsertest.cc
+++ b/chromium/content/browser/web_package/signed_exchange_request_handler_browsertest.cc
@@ -1025,7 +1025,7 @@ IN_PROC_BROWSER_TEST_P(SignedExchangeRequestHandlerBrowserTest,
EXPECT_TRUE(ExecuteScriptAndExtractBool(shell()->web_contents(),
register_sw_script, &result));
// serviceWorker.register() fails because the document URL of
- // ServiceWorkerProviderHost is empty.
+ // ServiceWorkerHost is empty.
EXPECT_FALSE(result);
}
diff --git a/chromium/content/browser/web_package/signed_exchange_subresource_prefetch_browsertest.cc b/chromium/content/browser/web_package/signed_exchange_subresource_prefetch_browsertest.cc
index 892a8733a4b..5e0de4b2789 100644
--- a/chromium/content/browser/web_package/signed_exchange_subresource_prefetch_browsertest.cc
+++ b/chromium/content/browser/web_package/signed_exchange_subresource_prefetch_browsertest.cc
@@ -254,8 +254,8 @@ class SignedExchangePrefetchBrowserTest
scoped_refptr<ChromeBlobStorageContext> blob_context =
ChromeBlobStorageContext::GetFor(
shell()->web_contents()->GetBrowserContext());
- base::PostTask(
- FROM_HERE, {BrowserThread::IO},
+ GetIOThreadTaskRunner({})->PostTask(
+ FROM_HERE,
base::BindOnce(&SignedExchangePrefetchBrowserTest::SetBlobLimitsOnIO,
blob_context));
}
diff --git a/chromium/content/browser/web_package/web_bundle_blob_data_source.cc b/chromium/content/browser/web_package/web_bundle_blob_data_source.cc
index ee575969d8e..05e98bdb729 100644
--- a/chromium/content/browser/web_package/web_bundle_blob_data_source.cc
+++ b/chromium/content/browser/web_package/web_bundle_blob_data_source.cc
@@ -9,7 +9,6 @@
#include "base/memory/ref_counted.h"
#include "base/numerics/checked_math.h"
#include "base/numerics/safe_conversions.h"
-#include "base/task/post_task.h"
#include "base/task/task_traits.h"
#include "content/public/browser/browser_task_traits.h"
#include "content/public/browser/browser_thread.h"
@@ -110,8 +109,8 @@ WebBundleBlobDataSource::WebBundleBlobDataSource(
network::mojom::URLLoaderClientEndpointsPtr endpoints,
BrowserContext::BlobContextGetter blob_context_getter) {
DCHECK_CURRENTLY_ON(BrowserThread::UI);
- base::PostTask(
- FROM_HERE, {BrowserThread::IO},
+ GetIOThreadTaskRunner({})->PostTask(
+ FROM_HERE,
base::BindOnce(&WebBundleBlobDataSource::CreateCoreOnIO,
weak_factory_.GetWeakPtr(), length_hint,
std::move(outer_response_body), std::move(endpoints),
@@ -121,7 +120,7 @@ WebBundleBlobDataSource::WebBundleBlobDataSource(
WebBundleBlobDataSource::~WebBundleBlobDataSource() {
DCHECK_CURRENTLY_ON(BrowserThread::UI);
if (core_)
- base::DeleteSoon(FROM_HERE, {BrowserThread::IO}, std::move(core_));
+ GetIOThreadTaskRunner({})->DeleteSoon(FROM_HERE, std::move(core_));
auto tasks = std::move(pending_get_core_tasks_);
for (auto& task : tasks) {
@@ -143,8 +142,8 @@ void WebBundleBlobDataSource::AddReceiverImpl(
pending_receiver) {
if (!core_)
return;
- base::PostTask(FROM_HERE, {BrowserThread::IO},
- base::BindOnce(&BlobDataSourceCore::AddReceiver, weak_core_,
+ GetIOThreadTaskRunner({})->PostTask(
+ FROM_HERE, base::BindOnce(&BlobDataSourceCore::AddReceiver, weak_core_,
std::move(pending_receiver)));
}
@@ -160,8 +159,8 @@ void WebBundleBlobDataSource::CreateCoreOnIO(
length_hint, std::move(endpoints), std::move(blob_context_getter));
core->Start(std::move(outer_response_body));
auto weak_core = core->GetWeakPtr();
- base::PostTask(
- FROM_HERE, {BrowserThread::UI},
+ GetUIThreadTaskRunner({})->PostTask(
+ FROM_HERE,
base::BindOnce(&WebBundleBlobDataSource::SetCoreOnUI, std::move(weak_ptr),
std::move(weak_core), std::move(core)));
}
@@ -175,7 +174,7 @@ void WebBundleBlobDataSource::SetCoreOnUI(
if (!weak_ptr) {
// This happens when the WebBundleBlobDataSource was deleted before
// SetCoreOnUI() is called.
- base::DeleteSoon(FROM_HERE, {BrowserThread::IO}, std::move(core));
+ GetIOThreadTaskRunner({})->DeleteSoon(FROM_HERE, std::move(core));
return;
}
weak_ptr->SetCoreOnUIImpl(std::move(weak_core), std::move(core));
@@ -228,12 +227,12 @@ void WebBundleBlobDataSource::ReadToDataPipeImpl(
CompletionCallback wrapped_callback = base::BindOnce(
[](CompletionCallback callback, net::Error net_error) {
DCHECK_CURRENTLY_ON(BrowserThread::IO);
- base::PostTask(FROM_HERE, {BrowserThread::UI},
- base::BindOnce(std::move(callback), net_error));
+ GetUIThreadTaskRunner({})->PostTask(
+ FROM_HERE, base::BindOnce(std::move(callback), net_error));
},
std::move(callback));
- base::PostTask(FROM_HERE, {BrowserThread::IO},
- base::BindOnce(&BlobDataSourceCore::ReadToDataPipe, weak_core_,
+ GetIOThreadTaskRunner({})->PostTask(
+ FROM_HERE, base::BindOnce(&BlobDataSourceCore::ReadToDataPipe, weak_core_,
offset, length, std::move(producer_handle),
std::move(wrapped_callback)));
}
diff --git a/chromium/content/browser/web_package/web_bundle_browsertest.cc b/chromium/content/browser/web_package/web_bundle_browsertest.cc
index ce0f8b43f4b..e6417c50b94 100644
--- a/chromium/content/browser/web_package/web_bundle_browsertest.cc
+++ b/chromium/content/browser/web_package/web_bundle_browsertest.cc
@@ -16,11 +16,15 @@
#include "base/test/scoped_feature_list.h"
#include "base/threading/thread_restrictions.h"
#include "build/build_config.h"
+#include "content/browser/frame_host/frame_tree_node.h"
+#include "content/browser/frame_host/navigation_request.h"
+#include "content/browser/web_contents/web_contents_impl.h"
#include "content/browser/web_package/web_bundle_utils.h"
#include "content/public/browser/browser_context.h"
#include "content/public/browser/content_browser_client.h"
#include "content/public/browser/download_manager.h"
#include "content/public/browser/navigation_handle.h"
+#include "content/public/browser/navigation_type.h"
#include "content/public/common/content_client.h"
#include "content/public/common/content_features.h"
#include "content/public/common/content_switches.h"
@@ -28,6 +32,7 @@
#include "content/public/test/browser_test_utils.h"
#include "content/public/test/content_browser_test.h"
#include "content/shell/browser/shell.h"
+#include "content/test/content_browser_test_utils_internal.h"
#include "net/base/filename_util.h"
#include "net/dns/mock_host_resolver.h"
#include "net/test/embedded_test_server/embedded_test_server.h"
@@ -47,10 +52,6 @@ namespace {
constexpr char kInvalidFileUrl[] = "file:///tmp/test%2F/a.wbn";
constexpr char kTestPageUrl[] = "https://test.example.org/";
-constexpr char kTestPage1Url[] = "https://test.example.org/page1.html";
-constexpr char kTestPage2Url[] = "https://test.example.org/page2.html";
-constexpr char kTestPageForHashUrl[] =
- "https://test.example.org/hash.html#hello";
constexpr char kDefaultHeaders[] =
"HTTP/1.1 200 OK\n"
@@ -96,6 +97,24 @@ void CopyFileAndGetContentUri(const base::FilePath& file,
}
#endif // OS_ANDROID
+std::string ExecuteAndGetString(const ToRenderFrameHost& adapter,
+ const std::string& script) {
+ std::string result;
+ EXPECT_TRUE(content::ExecuteScriptAndExtractString(
+ adapter, "domAutomationController.send(" + script + ")", &result));
+ return result;
+}
+
+void NavigateAndWaitForTitle(content::WebContents* web_contents,
+ const GURL& test_data_url,
+ const GURL& expected_commit_url,
+ base::StringPiece ascii_title) {
+ base::string16 expected_title = base::ASCIIToUTF16(ascii_title);
+ TitleWatcher title_watcher(web_contents, expected_title);
+ EXPECT_TRUE(NavigateToURL(web_contents, test_data_url, expected_commit_url));
+ EXPECT_EQ(expected_title, title_watcher.WaitAndGetTitle());
+}
+
class DownloadObserver : public DownloadManager::Observer {
public:
explicit DownloadObserver(DownloadManager* manager) : manager_(manager) {
@@ -321,19 +340,10 @@ class WebBundleBrowserTestBase : public ContentBrowserTest {
browser_client_.SetAcceptLangs(langs);
}
- void NavigateAndWaitForTitle(const GURL& test_data_url,
- const GURL& expected_commit_url,
- base::StringPiece ascii_title) {
- base::string16 expected_title = base::ASCIIToUTF16(ascii_title);
- TitleWatcher title_watcher(shell()->web_contents(), expected_title);
- EXPECT_TRUE(NavigateToURL(shell()->web_contents(), test_data_url,
- expected_commit_url));
- EXPECT_EQ(expected_title, title_watcher.WaitAndGetTitle());
- }
-
void NavigateToBundleAndWaitForReady(const GURL& test_data_url,
const GURL& expected_commit_url) {
- NavigateAndWaitForTitle(test_data_url, expected_commit_url, "Ready");
+ NavigateAndWaitForTitle(shell()->web_contents(), test_data_url,
+ expected_commit_url, "Ready");
}
void RunTestScript(const std::string& script) {
@@ -388,16 +398,31 @@ class FinishNavigationObserver : public WebContentsObserver {
: WebContentsObserver(contents), done_closure_(std::move(done_closure)) {}
void DidFinishNavigation(NavigationHandle* navigation_handle) override {
+ navigation_types_.push_back(
+ NavigationRequest::From(navigation_handle)->navigation_type());
error_code_ = navigation_handle->GetNetErrorCode();
- std::move(done_closure_).Run();
+ --navigations_remaining_;
+
+ if (navigations_remaining_ == 0)
+ std::move(done_closure_).Run();
+ }
+
+ void set_navigations_remaining(int navigations_remaining) {
+ navigations_remaining_ = navigations_remaining;
}
const base::Optional<net::Error>& error_code() const { return error_code_; }
+ const std::vector<NavigationType>& navigation_types() const {
+ return navigation_types_;
+ }
private:
base::OnceClosure done_closure_;
base::Optional<net::Error> error_code_;
+ int navigations_remaining_ = 1;
+ std::vector<NavigationType> navigation_types_;
+
DISALLOW_COPY_AND_ASSIGN(FinishNavigationObserver);
};
@@ -427,6 +452,13 @@ std::string ExpectNavigationFailureAndReturnConsoleMessage(
return base::UTF16ToUTF8(console_observer.messages()[0].message);
}
+FrameTreeNode* GetFirstChild(WebContents* web_contents) {
+ return static_cast<WebContentsImpl*>(web_contents)
+ ->GetFrameTree()
+ ->root()
+ ->child_at(0);
+}
+
std::string CreateSimpleWebBundle(const GURL& primary_url) {
data_decoder::test::WebBundleBuilder builder(primary_url.spec(), "");
builder.AddExchange(primary_url.spec(),
@@ -668,6 +700,863 @@ void RunSubPageTest(const ToRenderFrameHost& adapter,
.Resolve("#script")));
}
+std::string CreateHtmlForNavigationTest(const std::string& page_info,
+ const std::string& additional_html) {
+ return base::StringPrintf(
+ R"(
+ <body><script>
+ document.page_info = '%s';
+ document.title='Ready';
+ </script>%s</body>
+ )",
+ page_info.c_str(), additional_html.c_str());
+}
+
+std::string CreateScriptForNavigationTest(const std::string& script_info) {
+ return base::StringPrintf("document.script_info = '%s';",
+ script_info.c_str());
+}
+
+void AddHtmlAndScriptForNavigationTest(
+ data_decoder::test::WebBundleBuilder* builder,
+ const GURL& base_url,
+ const std::string& path,
+ const std::string& additional_html) {
+ AddHtmlFile(builder, base_url, path,
+ CreateHtmlForNavigationTest(path + " from wbn", additional_html));
+ AddScriptFile(builder, base_url, path + "script",
+ CreateScriptForNavigationTest(path + "script from wbn"));
+}
+
+std::string GetLoadResultForNavigationTest(const ToRenderFrameHost& adapter) {
+ std::string result;
+ std::string script = R"(
+ (async () => {
+ const script = document.createElement('script');
+ script.src = './script';
+ script.addEventListener('load', () => {
+ domAutomationController.send(
+ document.page_info + ', ' + document.script_info);
+ }, false);
+ script.addEventListener('error', () => {
+ domAutomationController.send(
+ document.page_info + ' failed to load script');
+ }, false);
+
+ if (!document.body) {
+ await new Promise((resolve) => {
+ document.addEventListener('DOMContentLoaded', resolve);
+ });
+ }
+ document.body.appendChild(script);
+ })()
+ )";
+ EXPECT_TRUE(content::ExecuteScriptAndExtractString(adapter, script, &result));
+ return result;
+}
+
+// Sets up |server| to return server generated page HTML files and JavaScript
+// files. |server| will returns a page file created by
+// CreateHtmlForNavigationTest(relative_url + " from server") for all URL which
+// ends with "page/", and returns a script file created by
+// CreateScriptForNavigationTest(relative_url + " from server") for all URL
+// which ends with "script".
+void SetUpNavigationTestServer(net::EmbeddedTestServer* server,
+ GURL* url_origin) {
+ server->RegisterRequestHandler(base::BindRepeating(
+ [](const net::test_server::HttpRequest& request)
+ -> std::unique_ptr<net::test_server::HttpResponse> {
+ if (base::EndsWith(request.relative_url, "page/",
+ base::CompareCase::SENSITIVE)) {
+ return std::make_unique<net::test_server::RawHttpResponse>(
+ kHeadersForHtml, CreateHtmlForNavigationTest(
+ request.relative_url + " from server", ""));
+ }
+ if (base::EndsWith(request.relative_url, "script",
+ base::CompareCase::SENSITIVE)) {
+ return std::make_unique<net::test_server::RawHttpResponse>(
+ kHeadersForJavaScript,
+ CreateScriptForNavigationTest(request.relative_url +
+ " from server"));
+ }
+ return nullptr;
+ }));
+
+ ASSERT_TRUE(server->Start());
+ *url_origin = server->GetURL("/");
+}
+
+void RunScriptAndObserveNavigation(
+ const std::string& message,
+ WebContents* web_contents,
+ const ToRenderFrameHost& execution_target,
+ const std::string& script,
+ const std::vector<NavigationType> expected_navigation_types,
+ const GURL& expected_last_comitted_url,
+ const GURL& expected_last_inner_url,
+ const std::string& expected_load_result) {
+ SCOPED_TRACE(message);
+ base::RunLoop run_loop;
+ FinishNavigationObserver finish_navigation_observer(web_contents,
+ run_loop.QuitClosure());
+ finish_navigation_observer.set_navigations_remaining(
+ expected_navigation_types.size());
+ EXPECT_TRUE(ExecJs(execution_target, script));
+ run_loop.Run();
+ EXPECT_EQ(finish_navigation_observer.navigation_types(),
+ expected_navigation_types);
+ EXPECT_EQ(web_contents->GetLastCommittedURL(), expected_last_comitted_url);
+ EXPECT_EQ(expected_load_result, GetLoadResultForNavigationTest(web_contents));
+ EXPECT_EQ(ExecuteAndGetString(web_contents, "window.location.href"),
+ expected_last_inner_url);
+ EXPECT_EQ(ExecuteAndGetString(web_contents, "document.location.href"),
+ expected_last_inner_url);
+ EXPECT_EQ(ExecuteAndGetString(web_contents, "document.URL"),
+ expected_last_inner_url);
+}
+
+void SetUpSharedNavigationsTest(net::EmbeddedTestServer* server,
+ const std::vector<std::string>& pathes,
+ GURL* url_origin,
+ std::string* web_bundle_content) {
+ SetUpNavigationTestServer(server, url_origin);
+ data_decoder::test::WebBundleBuilder builder(
+ url_origin->Resolve("/top-page/").spec(), "");
+ for (const auto& path : pathes)
+ AddHtmlAndScriptForNavigationTest(&builder, *url_origin, path, "");
+
+ std::vector<uint8_t> bundle = builder.CreateBundle();
+ *web_bundle_content = std::string(bundle.begin(), bundle.end());
+}
+
+void SetUpBasicNavigationTest(net::EmbeddedTestServer* server,
+ GURL* url_origin,
+ std::string* web_bundle_content) {
+ SetUpSharedNavigationsTest(server, {"/top-page/", "/1-page/", "/2-page/"},
+ url_origin, web_bundle_content);
+}
+
+// Runs test for basic history navigations (back/forward/reload).
+void RunBasicNavigationTest(
+ WebContents* web_contents,
+ const GURL& web_bundle_url,
+ const GURL& url_origin,
+ base::RepeatingCallback<GURL(const GURL&)> get_url_for_bundle) {
+ NavigateAndWaitForTitle(
+ web_contents, web_bundle_url,
+ get_url_for_bundle.Run(url_origin.Resolve("/top-page/")), "Ready");
+ RunScriptAndObserveNavigation(
+ "Navigate to /1-page/", web_contents, web_contents /* execution_target */,
+ "location.href = '/1-page/';", {NAVIGATION_TYPE_NEW_PAGE},
+ get_url_for_bundle.Run(
+ url_origin.Resolve("/1-page/")) /* expected_last_comitted_url */,
+ url_origin.Resolve("/1-page/") /* expected_last_inner_url */,
+ "/1-page/ from wbn, /1-page/script from wbn");
+ RunScriptAndObserveNavigation(
+ "Navigate to /2-page/", web_contents, web_contents /* execution_target */,
+ "location.href = '/2-page/';", {NAVIGATION_TYPE_NEW_PAGE},
+ get_url_for_bundle.Run(
+ url_origin.Resolve("/2-page/")) /* expected_last_comitted_url */,
+ url_origin.Resolve("/2-page/") /* expected_last_inner_url */,
+ "/2-page/ from wbn, /2-page/script from wbn");
+ RunScriptAndObserveNavigation(
+ "Back navigate to /1-page/", web_contents,
+ web_contents /* execution_target */, "history.back();",
+ {NAVIGATION_TYPE_EXISTING_PAGE},
+ get_url_for_bundle.Run(
+ url_origin.Resolve("/1-page/")) /* expected_last_comitted_url */,
+ url_origin.Resolve("/1-page/") /* expected_last_inner_url */,
+ "/1-page/ from wbn, /1-page/script from wbn");
+ RunScriptAndObserveNavigation(
+ "Back navigate to /top-page/", web_contents,
+ web_contents /* execution_target */, "history.back();",
+ {NAVIGATION_TYPE_EXISTING_PAGE},
+ get_url_for_bundle.Run(
+ url_origin.Resolve("/top-page/")) /* expected_last_comitted_url */,
+ url_origin.Resolve("/top-page/") /* expected_last_inner_url */,
+ "/top-page/ from wbn, /top-page/script from wbn");
+ RunScriptAndObserveNavigation(
+ "Forward navigate to /1-page/", web_contents,
+ web_contents /* execution_target */, "history.forward();",
+ {NAVIGATION_TYPE_EXISTING_PAGE},
+ get_url_for_bundle.Run(
+ url_origin.Resolve("/1-page/")) /* expected_last_comitted_url */,
+ url_origin.Resolve("/1-page/") /* expected_last_inner_url */,
+ "/1-page/ from wbn, /1-page/script from wbn");
+ RunScriptAndObserveNavigation(
+ "Reload /1-page/", web_contents, web_contents /* execution_target */,
+ "location.reload();", {NAVIGATION_TYPE_EXISTING_PAGE},
+ get_url_for_bundle.Run(
+ url_origin.Resolve("/1-page/")) /* expected_last_comitted_url */,
+ url_origin.Resolve("/1-page/") /* expected_last_inner_url */,
+ "/1-page/ from wbn, /1-page/script from wbn");
+ RunScriptAndObserveNavigation(
+ "Forward navigate to /2-page/", web_contents,
+ web_contents /* execution_target */, "history.forward();",
+ {NAVIGATION_TYPE_EXISTING_PAGE},
+ get_url_for_bundle.Run(
+ url_origin.Resolve("/2-page/")) /* expected_last_comitted_url */,
+ url_origin.Resolve("/2-page/") /* expected_last_inner_url */,
+ "/2-page/ from wbn, /2-page/script from wbn");
+}
+
+void SetUpBrowserInitiatedOutOfBundleNavigationTest(
+ net::EmbeddedTestServer* server,
+ GURL* url_origin,
+ std::string* web_bundle_content) {
+ SetUpSharedNavigationsTest(
+ server, {"/top-page/", "/1-page/", "/2-page/", "/3-page/", "/4-page/"},
+ url_origin, web_bundle_content);
+}
+
+// Runs test for history navigations after browser initiated navigation going
+// out of the web bundle.
+void RunBrowserInitiatedOutOfBundleNavigationTest(
+ WebContents* web_contents,
+ const GURL& web_bundle_url,
+ const GURL& url_origin,
+ base::RepeatingCallback<GURL(const GURL&)> get_url_for_bundle) {
+ NavigateAndWaitForTitle(
+ web_contents, web_bundle_url,
+ get_url_for_bundle.Run(url_origin.Resolve("/top-page/")), "Ready");
+ RunScriptAndObserveNavigation(
+ "Navigate to /1-page/", web_contents, web_contents /* execution_target */,
+ "location.href = '/1-page/';", {NAVIGATION_TYPE_NEW_PAGE},
+ get_url_for_bundle.Run(
+ url_origin.Resolve("/1-page/")) /* expected_last_comitted_url */,
+ url_origin.Resolve("/1-page/") /* expected_last_inner_url */,
+ "/1-page/ from wbn, /1-page/script from wbn");
+ RunScriptAndObserveNavigation(
+ "Navigate to /2-page/", web_contents, web_contents /* execution_target */,
+ "location.href = '/2-page/';", {NAVIGATION_TYPE_NEW_PAGE},
+ get_url_for_bundle.Run(
+ url_origin.Resolve("/2-page/")) /* expected_last_comitted_url */,
+ url_origin.Resolve("/2-page/") /* expected_last_inner_url */,
+ "/2-page/ from wbn, /2-page/script from wbn");
+ {
+ SCOPED_TRACE("Browser initiated navigation to /3-page/");
+ EXPECT_TRUE(NavigateToURL(web_contents, url_origin.Resolve("/3-page/")));
+ EXPECT_EQ(web_contents->GetLastCommittedURL(),
+ url_origin.Resolve("/3-page/"));
+ // Browser initiated navigation must be loaded from the server even if the
+ // page is in the web bundle.
+ EXPECT_EQ("/3-page/ from server, /3-page/script from server",
+ GetLoadResultForNavigationTest(web_contents));
+ }
+ // Navigation from the out of web bundle page must be loaded from the server
+ // even if the page is in the web bundle.
+ RunScriptAndObserveNavigation(
+ "Navigate to /4-page/", web_contents, web_contents /* execution_target */,
+ "location.href = '/4-page/';", {NAVIGATION_TYPE_NEW_PAGE},
+ url_origin.Resolve("/4-page/") /* expected_last_comitted_url */,
+ url_origin.Resolve("/4-page/") /* expected_last_inner_url */,
+ "/4-page/ from server, /4-page/script from server");
+ RunScriptAndObserveNavigation(
+ "Back navigate to /3-page/", web_contents,
+ web_contents /* execution_target */, "history.back();",
+ {NAVIGATION_TYPE_EXISTING_PAGE},
+ url_origin.Resolve("/3-page/") /* expected_last_comitted_url */,
+ url_origin.Resolve("/3-page/") /* expected_last_inner_url */,
+ "/3-page/ from server, /3-page/script from server");
+ RunScriptAndObserveNavigation(
+ "Back navigate to /2-page/", web_contents,
+ web_contents /* execution_target */, "history.back();",
+ {NAVIGATION_TYPE_EXISTING_PAGE},
+ get_url_for_bundle.Run(
+ url_origin.Resolve("/2-page/")) /* expected_last_comitted_url */,
+ url_origin.Resolve("/2-page/") /* expected_last_inner_url */,
+ "/2-page/ from wbn, /2-page/script from wbn");
+ RunScriptAndObserveNavigation(
+ "Back navigate to /1-page/", web_contents,
+ web_contents /* execution_target */, "history.back();",
+ {NAVIGATION_TYPE_EXISTING_PAGE},
+ get_url_for_bundle.Run(
+ url_origin.Resolve("/1-page/")) /* expected_last_comitted_url */,
+ url_origin.Resolve("/1-page/") /* expected_last_inner_url */,
+ "/1-page/ from wbn, /1-page/script from wbn");
+ RunScriptAndObserveNavigation(
+ "Forward navigate to /2-page/", web_contents,
+ web_contents /* execution_target */, "history.forward();",
+ {NAVIGATION_TYPE_EXISTING_PAGE},
+ get_url_for_bundle.Run(
+ url_origin.Resolve("/2-page/")) /* expected_last_comitted_url */,
+ url_origin.Resolve("/2-page/") /* expected_last_inner_url */,
+ "/2-page/ from wbn, /2-page/script from wbn");
+ RunScriptAndObserveNavigation(
+ "Forward navigate to /3-page/", web_contents,
+ web_contents /* execution_target */, "history.forward();",
+ {NAVIGATION_TYPE_EXISTING_PAGE},
+ url_origin.Resolve("/3-page/") /* expected_last_comitted_url */,
+ url_origin.Resolve("/3-page/") /* expected_last_inner_url */,
+ "/3-page/ from server, /3-page/script from server");
+ RunScriptAndObserveNavigation(
+ "Forward navigate to /4-page/", web_contents,
+ web_contents /* execution_target */, "history.forward();",
+ {NAVIGATION_TYPE_EXISTING_PAGE},
+ url_origin.Resolve("/4-page/") /* expected_last_comitted_url */,
+ url_origin.Resolve("/4-page/") /* expected_last_inner_url */,
+ "/4-page/ from server, /4-page/script from server");
+}
+
+void SetUpRendererInitiatedOutOfBundleNavigationTest(
+ net::EmbeddedTestServer* server,
+ GURL* url_origin,
+ std::string* web_bundle_content) {
+ SetUpSharedNavigationsTest(server,
+ {"/top-page/", "/1-page/", "/2-page/", "/3-page/"},
+ url_origin, web_bundle_content);
+}
+
+// Runs test for history navigations after renderer initiated navigation going
+// out of the web bundle.
+void RunRendererInitiatedOutOfBundleNavigationTest(
+ WebContents* web_contents,
+ const GURL& web_bundle_url,
+ const GURL& url_origin,
+ base::RepeatingCallback<GURL(const GURL&)> get_url_for_bundle) {
+ NavigateAndWaitForTitle(
+ web_contents, web_bundle_url,
+ get_url_for_bundle.Run(url_origin.Resolve("/top-page/")), "Ready");
+ RunScriptAndObserveNavigation(
+ "Navigate to /1-page/", web_contents, web_contents /* execution_target */,
+ "location.href = '/1-page/';", {NAVIGATION_TYPE_NEW_PAGE},
+ get_url_for_bundle.Run(
+ url_origin.Resolve("/1-page/")) /* expected_last_comitted_url */,
+ url_origin.Resolve("/1-page/") /* expected_last_inner_url */,
+ "/1-page/ from wbn, /1-page/script from wbn");
+ RunScriptAndObserveNavigation(
+ "Navigate to /2-page/", web_contents, web_contents /* execution_target */,
+ "location.href = '/2-page/';", {NAVIGATION_TYPE_NEW_PAGE},
+ get_url_for_bundle.Run(
+ url_origin.Resolve("/2-page/")) /* expected_last_comitted_url */,
+ url_origin.Resolve("/2-page/") /* expected_last_inner_url */,
+ "/2-page/ from wbn, /2-page/script from wbn");
+ RunScriptAndObserveNavigation(
+ "Navigate to /server-page/", web_contents,
+ web_contents /* execution_target */, "location.href = '/server-page/';",
+ {NAVIGATION_TYPE_NEW_PAGE},
+ url_origin.Resolve("/server-page/") /* expected_last_comitted_url */,
+ url_origin.Resolve("/server-page/") /* expected_last_inner_url */,
+ "/server-page/ from server, /server-page/script from server");
+ // Navigation from the out of web bundle page must be loaded from the server
+ // even if the page is in the web bundle.
+ RunScriptAndObserveNavigation(
+ "Navigate to /3-page/", web_contents, web_contents /* execution_target */,
+ "location.href = '/3-page/';", {NAVIGATION_TYPE_NEW_PAGE},
+ url_origin.Resolve("/3-page/") /* expected_last_comitted_url */,
+ url_origin.Resolve("/3-page/") /* expected_last_inner_url */,
+ "/3-page/ from server, /3-page/script from server");
+ RunScriptAndObserveNavigation(
+ "Back navigate to /server-page/", web_contents,
+ web_contents /* execution_target */, "history.back();",
+ {NAVIGATION_TYPE_EXISTING_PAGE},
+ url_origin.Resolve("/server-page/") /* expected_last_comitted_url */,
+ url_origin.Resolve("/server-page/") /* expected_last_inner_url */,
+ "/server-page/ from server, /server-page/script from server");
+ RunScriptAndObserveNavigation(
+ "Back navigate to /2-page/", web_contents,
+ web_contents /* execution_target */, "history.back();",
+ {NAVIGATION_TYPE_EXISTING_PAGE},
+ get_url_for_bundle.Run(
+ url_origin.Resolve("/2-page/")) /* expected_last_comitted_url */,
+ url_origin.Resolve("/2-page/") /* expected_last_inner_url */,
+ "/2-page/ from wbn, /2-page/script from wbn");
+ RunScriptAndObserveNavigation(
+ "Back navigate to /1-page/", web_contents,
+ web_contents /* execution_target */, "history.back();",
+ {NAVIGATION_TYPE_EXISTING_PAGE},
+ get_url_for_bundle.Run(
+ url_origin.Resolve("/1-page/")) /* expected_last_comitted_url */,
+ url_origin.Resolve("/1-page/") /* expected_last_inner_url */,
+ "/1-page/ from wbn, /1-page/script from wbn");
+ RunScriptAndObserveNavigation(
+ "Forward navigate to /2-page/", web_contents,
+ web_contents /* execution_target */, "history.forward();",
+ {NAVIGATION_TYPE_EXISTING_PAGE},
+ get_url_for_bundle.Run(
+ url_origin.Resolve("/2-page/")) /* expected_last_comitted_url */,
+ url_origin.Resolve("/2-page/") /* expected_last_inner_url */,
+ "/2-page/ from wbn, /2-page/script from wbn");
+ RunScriptAndObserveNavigation(
+ "Forward navigate to /server-page/", web_contents,
+ web_contents /* execution_target */, "history.forward();",
+ {NAVIGATION_TYPE_EXISTING_PAGE},
+ url_origin.Resolve("/server-page/") /* expected_last_comitted_url */,
+ url_origin.Resolve("/server-page/") /* expected_last_inner_url */,
+ "/server-page/ from server, /server-page/script from server");
+ RunScriptAndObserveNavigation(
+ "Forward navigate to /3-page/", web_contents,
+ web_contents /* execution_target */, "history.forward();",
+ {NAVIGATION_TYPE_EXISTING_PAGE},
+ url_origin.Resolve("/3-page/") /* expected_last_comitted_url */,
+ url_origin.Resolve("/3-page/") /* expected_last_inner_url */,
+ "/3-page/ from server, /3-page/script from server");
+}
+
+void SetUpSameDocumentNavigationTest(net::EmbeddedTestServer* server,
+ GURL* url_origin,
+ std::string* web_bundle_content) {
+ SetUpSharedNavigationsTest(server, {"/top-page/", "/1-page/", "/2-page/"},
+ url_origin, web_bundle_content);
+}
+
+// Runs test for history navigations after same document navigations.
+void RunSameDocumentNavigationTest(
+ WebContents* web_contents,
+ const GURL& web_bundle_url,
+ const GURL& url_origin,
+ base::RepeatingCallback<GURL(const GURL&)> get_url_for_bundle) {
+ NavigateAndWaitForTitle(
+ web_contents, web_bundle_url,
+ get_url_for_bundle.Run(url_origin.Resolve("/top-page/")), "Ready");
+ RunScriptAndObserveNavigation(
+ "Navigate to /1-page/", web_contents, web_contents /* execution_target */,
+ "location.href = '/1-page/';", {NAVIGATION_TYPE_NEW_PAGE},
+ get_url_for_bundle.Run(
+ url_origin.Resolve("/1-page/")) /* expected_last_comitted_url */,
+ url_origin.Resolve("/1-page/") /* expected_last_inner_url */,
+ "/1-page/ from wbn, /1-page/script from wbn");
+ RunScriptAndObserveNavigation(
+ "Navigate to /1-page/#hash1", web_contents,
+ web_contents /* execution_target */, "location.href = '#hash1';",
+ {NAVIGATION_TYPE_NEW_PAGE},
+ get_url_for_bundle.Run(url_origin.Resolve(
+ "/1-page/#hash1")) /* expected_last_comitted_url */,
+ url_origin.Resolve("/1-page/#hash1") /* expected_last_inner_url */,
+ "/1-page/ from wbn, /1-page/script from wbn");
+ RunScriptAndObserveNavigation(
+ "Navigate to /1-page/#hash2", web_contents,
+ web_contents /* execution_target */, "location.href = '#hash2';",
+ {NAVIGATION_TYPE_NEW_PAGE},
+ get_url_for_bundle.Run(url_origin.Resolve(
+ "/1-page/#hash2")) /* expected_last_comitted_url */,
+ url_origin.Resolve("/1-page/#hash2") /* expected_last_inner_url */,
+ "/1-page/ from wbn, /1-page/script from wbn");
+ RunScriptAndObserveNavigation(
+ "Navigate to /2-page/", web_contents, web_contents /* execution_target */,
+ "location.href = '/2-page/';", {NAVIGATION_TYPE_NEW_PAGE},
+ get_url_for_bundle.Run(
+ url_origin.Resolve("/2-page/")) /* expected_last_comitted_url */,
+ url_origin.Resolve("/2-page/") /* expected_last_inner_url */,
+ "/2-page/ from wbn, /2-page/script from wbn");
+ RunScriptAndObserveNavigation(
+ "Back navigate to /1-page/#hash2", web_contents,
+ web_contents /* execution_target */, "history.back();",
+ {NAVIGATION_TYPE_EXISTING_PAGE},
+ get_url_for_bundle.Run(url_origin.Resolve(
+ "/1-page/#hash2")) /* expected_last_comitted_url */,
+ url_origin.Resolve("/1-page/#hash2") /* expected_last_inner_url */,
+ "/1-page/ from wbn, /1-page/script from wbn");
+ RunScriptAndObserveNavigation(
+ "Back navigate to /1-page/#hash1", web_contents,
+ web_contents /* execution_target */, "history.back();",
+ {NAVIGATION_TYPE_EXISTING_PAGE},
+ get_url_for_bundle.Run(url_origin.Resolve(
+ "/1-page/#hash1")) /* expected_last_comitted_url */,
+ url_origin.Resolve("/1-page/#hash1") /* expected_last_inner_url */,
+ "/1-page/ from wbn, /1-page/script from wbn");
+ RunScriptAndObserveNavigation(
+ "Back navigate to /1-page/", web_contents,
+ web_contents /* execution_target */, "history.back();",
+ {NAVIGATION_TYPE_EXISTING_PAGE},
+ get_url_for_bundle.Run(
+ url_origin.Resolve("/1-page/")) /* expected_last_comitted_url */,
+ url_origin.Resolve("/1-page/") /* expected_last_inner_url */,
+ "/1-page/ from wbn, /1-page/script from wbn");
+ RunScriptAndObserveNavigation(
+ "Forward navigate to /1-page/#hash1", web_contents,
+ web_contents /* execution_target */, "history.forward();",
+ {NAVIGATION_TYPE_EXISTING_PAGE},
+ get_url_for_bundle.Run(url_origin.Resolve(
+ "/1-page/#hash1")) /* expected_last_comitted_url */,
+ url_origin.Resolve("/1-page/#hash1") /* expected_last_inner_url */,
+ "/1-page/ from wbn, /1-page/script from wbn");
+ RunScriptAndObserveNavigation(
+ "Forward navigate to /1-page/#hash2", web_contents,
+ web_contents /* execution_target */, "history.forward();",
+ {NAVIGATION_TYPE_EXISTING_PAGE},
+ get_url_for_bundle.Run(url_origin.Resolve(
+ "/1-page/#hash2")) /* expected_last_comitted_url */,
+ url_origin.Resolve("/1-page/#hash2") /* expected_last_inner_url */,
+ "/1-page/ from wbn, /1-page/script from wbn");
+ RunScriptAndObserveNavigation(
+ "Forward navigate to /2-page/", web_contents,
+ web_contents /* execution_target */, "history.forward();",
+ {NAVIGATION_TYPE_EXISTING_PAGE},
+ get_url_for_bundle.Run(
+ url_origin.Resolve("/2-page/")) /* expected_last_comitted_url */,
+ url_origin.Resolve("/2-page/") /* expected_last_inner_url */,
+ "/2-page/ from wbn, /2-page/script from wbn");
+}
+
+void SetUpIframeNavigationTest(net::EmbeddedTestServer* server,
+ GURL* url_origin,
+ std::string* web_bundle_content) {
+ SetUpNavigationTestServer(server, url_origin);
+ data_decoder::test::WebBundleBuilder builder(
+ url_origin->Resolve("/top-page/").spec(), "");
+ const std::vector<std::string> pathes = {"/top-page/", "/1-page/",
+ "/2-page/"};
+ for (const auto& path : pathes)
+ AddHtmlAndScriptForNavigationTest(&builder, *url_origin, path, "");
+ AddHtmlAndScriptForNavigationTest(&builder, *url_origin, "/iframe-test-page/",
+ "<iframe src=\"/1-page/\" />");
+
+ std::vector<uint8_t> bundle = builder.CreateBundle();
+ *web_bundle_content = std::string(bundle.begin(), bundle.end());
+}
+
+// Runs test for history navigations with an iframe.
+void RunIframeNavigationTest(
+ WebContents* web_contents,
+ const GURL& web_bundle_url,
+ const GURL& url_origin,
+ base::RepeatingCallback<GURL(const GURL&)> get_url_for_bundle) {
+ NavigateAndWaitForTitle(
+ web_contents, web_bundle_url,
+ get_url_for_bundle.Run(url_origin.Resolve("/top-page/")), "Ready");
+
+ RunScriptAndObserveNavigation(
+ "Navigate to /iframe-test-page/", web_contents,
+ web_contents /* execution_target */,
+ "location.href = '/iframe-test-page/';",
+ {NAVIGATION_TYPE_NEW_PAGE, NAVIGATION_TYPE_AUTO_SUBFRAME},
+ get_url_for_bundle.Run(url_origin.Resolve(
+ "/iframe-test-page/")) /* expected_last_comitted_url */,
+ url_origin.Resolve("/iframe-test-page/") /* expected_last_inner_url */,
+ "/iframe-test-page/ from wbn, /iframe-test-page/script from wbn");
+ EXPECT_EQ("/1-page/ from wbn, /1-page/script from wbn",
+ GetLoadResultForNavigationTest(GetFirstChild(web_contents)));
+
+ RunScriptAndObserveNavigation(
+ "Navigate the iframe to /2-page/", web_contents,
+ GetFirstChild(web_contents) /* execution_target */,
+ "location.href = '/2-page/';", {NAVIGATION_TYPE_NEW_SUBFRAME},
+ get_url_for_bundle.Run(url_origin.Resolve(
+ "/iframe-test-page/")) /* expected_last_comitted_url */,
+ url_origin.Resolve("/iframe-test-page/") /* expected_last_inner_url */,
+ "/iframe-test-page/ from wbn, /iframe-test-page/script from wbn");
+ EXPECT_EQ("/2-page/ from wbn, /2-page/script from wbn",
+ GetLoadResultForNavigationTest(GetFirstChild(web_contents)));
+
+ RunScriptAndObserveNavigation(
+ "Back navigate the iframe to /1-page/", web_contents,
+ web_contents /* execution_target */, "history.back();",
+ {NAVIGATION_TYPE_AUTO_SUBFRAME},
+ get_url_for_bundle.Run(url_origin.Resolve(
+ "/iframe-test-page/")) /* expected_last_comitted_url */,
+ url_origin.Resolve("/iframe-test-page/") /* expected_last_inner_url */,
+ "/iframe-test-page/ from wbn, /iframe-test-page/script from wbn");
+ EXPECT_EQ("/1-page/ from wbn, /1-page/script from wbn",
+ GetLoadResultForNavigationTest(GetFirstChild(web_contents)));
+
+ RunScriptAndObserveNavigation(
+ "Back navigate to /top-page/", web_contents,
+ web_contents /* execution_target */, "history.back();",
+ {NAVIGATION_TYPE_EXISTING_PAGE},
+ get_url_for_bundle.Run(
+ url_origin.Resolve("/top-page/")) /* expected_last_comitted_url */,
+ url_origin.Resolve("/top-page/") /* expected_last_inner_url */,
+ "/top-page/ from wbn, /top-page/script from wbn");
+
+ RunScriptAndObserveNavigation(
+ "Forward navigate to /iframe-test-page/", web_contents,
+ web_contents /* execution_target */, "history.forward();",
+ {NAVIGATION_TYPE_EXISTING_PAGE, NAVIGATION_TYPE_AUTO_SUBFRAME},
+ get_url_for_bundle.Run(url_origin.Resolve(
+ "/iframe-test-page/")) /* expected_last_comitted_url */,
+ url_origin.Resolve("/iframe-test-page/") /* expected_last_inner_url */,
+ "/iframe-test-page/ from wbn, /iframe-test-page/script from wbn");
+ EXPECT_EQ("/1-page/ from wbn, /1-page/script from wbn",
+ GetLoadResultForNavigationTest(GetFirstChild(web_contents)));
+
+ RunScriptAndObserveNavigation(
+ "Forward navigate the iframe to /2-page/", web_contents,
+ web_contents /* execution_target */, "history.forward();",
+ {NAVIGATION_TYPE_AUTO_SUBFRAME},
+ get_url_for_bundle.Run(url_origin.Resolve(
+ "/iframe-test-page/")) /* expected_last_comitted_url */,
+ url_origin.Resolve("/iframe-test-page/") /* expected_last_inner_url */,
+ "/iframe-test-page/ from wbn, /iframe-test-page/script from wbn");
+ EXPECT_EQ("/2-page/ from wbn, /2-page/script from wbn",
+ GetLoadResultForNavigationTest(GetFirstChild(web_contents)));
+}
+
+// Runs test for navigations in an iframe after going out of the web bundle by
+// changing location.href inside the iframe.
+void RunIframeOutOfBundleNavigationTest(
+ WebContents* web_contents,
+ const GURL& web_bundle_url,
+ const GURL& url_origin,
+ base::RepeatingCallback<GURL(const GURL&)> get_url_for_bundle) {
+ NavigateAndWaitForTitle(
+ web_contents, web_bundle_url,
+ get_url_for_bundle.Run(url_origin.Resolve("/top-page/")), "Ready");
+
+ RunScriptAndObserveNavigation(
+ "Navigate to /iframe-test-page/", web_contents,
+ web_contents /* execution_target */,
+ "location.href = '/iframe-test-page/';",
+ {NAVIGATION_TYPE_NEW_PAGE, NAVIGATION_TYPE_AUTO_SUBFRAME},
+ get_url_for_bundle.Run(url_origin.Resolve(
+ "/iframe-test-page/")) /* expected_last_comitted_url */,
+ url_origin.Resolve("/iframe-test-page/") /* expected_last_inner_url */,
+ "/iframe-test-page/ from wbn, /iframe-test-page/script from wbn");
+ EXPECT_EQ("/1-page/ from wbn, /1-page/script from wbn",
+ GetLoadResultForNavigationTest(GetFirstChild(web_contents)));
+
+ // The web bundle doesn't contain /server-page/. So the server returns the
+ // page and script.
+ RunScriptAndObserveNavigation(
+ "Navigate the iframe to /server-page/", web_contents,
+ GetFirstChild(web_contents) /* execution_target */,
+ "location.href = /server-page/;", {NAVIGATION_TYPE_NEW_SUBFRAME},
+ get_url_for_bundle.Run(url_origin.Resolve(
+ "/iframe-test-page/")) /* expected_last_comitted_url */,
+ url_origin.Resolve("/iframe-test-page/") /* expected_last_inner_url */,
+ "/iframe-test-page/ from wbn, /iframe-test-page/script from wbn");
+ EXPECT_EQ("/server-page/ from server, /server-page/script from server",
+ GetLoadResultForNavigationTest(GetFirstChild(web_contents)));
+
+ // Even if location.href is changed by /server-page/, /1-page/ is loaded from
+ // the bundle.
+ RunScriptAndObserveNavigation(
+ "Navigate the iframe to /1-page/", web_contents,
+ GetFirstChild(web_contents) /* execution_target */,
+ "location.href = /1-page/;", {NAVIGATION_TYPE_NEW_SUBFRAME},
+ get_url_for_bundle.Run(url_origin.Resolve(
+ "/iframe-test-page/")) /* expected_last_comitted_url */,
+ url_origin.Resolve("/iframe-test-page/") /* expected_last_inner_url */,
+ "/iframe-test-page/ from wbn, /iframe-test-page/script from wbn");
+ EXPECT_EQ("/1-page/ from wbn, /1-page/script from wbn",
+ GetLoadResultForNavigationTest(GetFirstChild(web_contents)));
+}
+
+// Runs test for navigations in an iframe after going out of the web bundle by
+// changing iframe.src from the parent frame.
+void RunIframeParentInitiatedOutOfBundleNavigationTest(
+ WebContents* web_contents,
+ const GURL& web_bundle_url,
+ const GURL& url_origin,
+ base::RepeatingCallback<GURL(const GURL&)> get_url_for_bundle) {
+ NavigateAndWaitForTitle(
+ web_contents, web_bundle_url,
+ get_url_for_bundle.Run(url_origin.Resolve("/top-page/")), "Ready");
+
+ RunScriptAndObserveNavigation(
+ "Navigate to /iframe-test-page/", web_contents,
+ web_contents /* execution_target */,
+ "location.href = '/iframe-test-page/';",
+ {NAVIGATION_TYPE_NEW_PAGE, NAVIGATION_TYPE_AUTO_SUBFRAME},
+ get_url_for_bundle.Run(url_origin.Resolve(
+ "/iframe-test-page/")) /* expected_last_comitted_url */,
+ url_origin.Resolve("/iframe-test-page/") /* expected_last_inner_url */,
+ "/iframe-test-page/ from wbn, /iframe-test-page/script from wbn");
+ EXPECT_EQ("/1-page/ from wbn, /1-page/script from wbn",
+ GetLoadResultForNavigationTest(GetFirstChild(web_contents)));
+
+ // The web bundle doesn't contain /server-page/. So the server returns the
+ // page and script.
+ RunScriptAndObserveNavigation(
+ "Navigate the iframe to /server-page/", web_contents,
+ web_contents /* execution_target */,
+ "document.querySelector('iframe').src = /server-page/;",
+ {NAVIGATION_TYPE_NEW_SUBFRAME},
+ get_url_for_bundle.Run(url_origin.Resolve(
+ "/iframe-test-page/")) /* expected_last_comitted_url */,
+ url_origin.Resolve("/iframe-test-page/") /* expected_last_inner_url */,
+ "/iframe-test-page/ from wbn, /iframe-test-page/script from wbn");
+ EXPECT_EQ("/server-page/ from server, /server-page/script from server",
+ GetLoadResultForNavigationTest(GetFirstChild(web_contents)));
+
+ FrameTreeNode* iframe_node = GetFirstChild(web_contents);
+ bool is_same_process = (iframe_node->parent()->GetProcess() ==
+ iframe_node->current_frame_host()->GetProcess());
+
+ RunScriptAndObserveNavigation(
+ "Navigate the iframe to /1-page/", web_contents,
+ web_contents /* execution_target */,
+ "document.querySelector('iframe').src = /1-page/;",
+ {NAVIGATION_TYPE_NEW_SUBFRAME},
+ get_url_for_bundle.Run(url_origin.Resolve(
+ "/iframe-test-page/")) /* expected_last_comitted_url */,
+ url_origin.Resolve("/iframe-test-page/") /* expected_last_inner_url */,
+ "/iframe-test-page/ from wbn, /iframe-test-page/script from wbn");
+
+ // TODO(crbug.com/1040800): Currently the remote iframe can't load the page
+ // from web bundle. To support this case we need to change
+ // NavigationControllerImpl::NavigateFromFrameProxy() to correctly handle
+ // the WebBundleHandleTracker.
+ EXPECT_EQ(is_same_process
+ ? "/1-page/ from wbn, /1-page/script from wbn"
+ : "/1-page/ from server, /1-page/script from server",
+ GetLoadResultForNavigationTest(GetFirstChild(web_contents)));
+}
+
+// Runs test for history navigations in an iframe after same document
+// navigation.
+void RunIframeSameDocumentNavigationTest(
+ WebContents* web_contents,
+ const GURL& web_bundle_url,
+ const GURL& url_origin,
+ base::RepeatingCallback<GURL(const GURL&)> get_url_for_bundle) {
+ NavigateAndWaitForTitle(
+ web_contents, web_bundle_url,
+ get_url_for_bundle.Run(url_origin.Resolve("/top-page/")), "Ready");
+ NavigateAndWaitForTitle(
+ web_contents, web_bundle_url,
+ get_url_for_bundle.Run(url_origin.Resolve("/top-page/")), "Ready");
+
+ RunScriptAndObserveNavigation(
+ "Navigate to /iframe-test-page/", web_contents,
+ web_contents /* execution_target */,
+ "location.href = '/iframe-test-page/';",
+ {NAVIGATION_TYPE_NEW_PAGE, NAVIGATION_TYPE_AUTO_SUBFRAME},
+ get_url_for_bundle.Run(url_origin.Resolve(
+ "/iframe-test-page/")) /* expected_last_comitted_url */,
+ url_origin.Resolve("/iframe-test-page/") /* expected_last_inner_url */,
+ "/iframe-test-page/ from wbn, /iframe-test-page/script from wbn");
+ EXPECT_EQ("/1-page/ from wbn, /1-page/script from wbn",
+ GetLoadResultForNavigationTest(GetFirstChild(web_contents)));
+
+ RunScriptAndObserveNavigation(
+ "Navigate the iframe to /1-page/#hash1", web_contents,
+ GetFirstChild(web_contents) /* execution_target */,
+ "location.href = '#hash1';", {NAVIGATION_TYPE_NEW_SUBFRAME},
+ get_url_for_bundle.Run(url_origin.Resolve(
+ "/iframe-test-page/")) /* expected_last_comitted_url */,
+ url_origin.Resolve("/iframe-test-page/") /* expected_last_inner_url */,
+ "/iframe-test-page/ from wbn, /iframe-test-page/script from wbn");
+ EXPECT_EQ("/1-page/ from wbn, /1-page/script from wbn",
+ GetLoadResultForNavigationTest(GetFirstChild(web_contents)));
+ EXPECT_EQ(ExecuteAndGetString(GetFirstChild(web_contents), "location.href"),
+ url_origin.Resolve("/1-page/#hash1"));
+
+ RunScriptAndObserveNavigation(
+ "Navigate the iframe to /1-page/#hash2", web_contents,
+ GetFirstChild(web_contents) /* execution_target */,
+ "location.href = '#hash2';", {NAVIGATION_TYPE_NEW_SUBFRAME},
+ get_url_for_bundle.Run(url_origin.Resolve(
+ "/iframe-test-page/")) /* expected_last_comitted_url */,
+ url_origin.Resolve("/iframe-test-page/") /* expected_last_inner_url */,
+ "/iframe-test-page/ from wbn, /iframe-test-page/script from wbn");
+ EXPECT_EQ("/1-page/ from wbn, /1-page/script from wbn",
+ GetLoadResultForNavigationTest(GetFirstChild(web_contents)));
+ EXPECT_EQ(ExecuteAndGetString(GetFirstChild(web_contents), "location.href"),
+ url_origin.Resolve("/1-page/#hash2"));
+
+ RunScriptAndObserveNavigation(
+ "Navigate the iframe to /2-page/", web_contents,
+ GetFirstChild(web_contents) /* execution_target */,
+ "location.href = '/2-page/';", {NAVIGATION_TYPE_NEW_SUBFRAME},
+ get_url_for_bundle.Run(url_origin.Resolve(
+ "/iframe-test-page/")) /* expected_last_comitted_url */,
+ url_origin.Resolve("/iframe-test-page/") /* expected_last_inner_url */,
+ "/iframe-test-page/ from wbn, /iframe-test-page/script from wbn");
+ EXPECT_EQ("/2-page/ from wbn, /2-page/script from wbn",
+ GetLoadResultForNavigationTest(GetFirstChild(web_contents)));
+ EXPECT_EQ(ExecuteAndGetString(GetFirstChild(web_contents), "location.href"),
+ url_origin.Resolve("/2-page/"));
+
+ RunScriptAndObserveNavigation(
+ "Back navigate the iframe to /1-page/#hash2", web_contents,
+ web_contents /* execution_target */, "history.back();",
+ {NAVIGATION_TYPE_AUTO_SUBFRAME},
+ get_url_for_bundle.Run(url_origin.Resolve(
+ "/iframe-test-page/")) /* expected_last_comitted_url */,
+ url_origin.Resolve("/iframe-test-page/") /* expected_last_inner_url */,
+ "/iframe-test-page/ from wbn, /iframe-test-page/script from wbn");
+ EXPECT_EQ("/1-page/ from wbn, /1-page/script from wbn",
+ GetLoadResultForNavigationTest(GetFirstChild(web_contents)));
+ EXPECT_EQ(ExecuteAndGetString(GetFirstChild(web_contents), "location.href"),
+ url_origin.Resolve("/1-page/#hash2"));
+
+ RunScriptAndObserveNavigation(
+ "Back navigate the iframe to /1-page/#hash1", web_contents,
+ web_contents /* execution_target */, "history.back();",
+ {NAVIGATION_TYPE_AUTO_SUBFRAME},
+ get_url_for_bundle.Run(url_origin.Resolve(
+ "/iframe-test-page/")) /* expected_last_comitted_url */,
+ url_origin.Resolve("/iframe-test-page/") /* expected_last_inner_url */,
+ "/iframe-test-page/ from wbn, /iframe-test-page/script from wbn");
+ EXPECT_EQ("/1-page/ from wbn, /1-page/script from wbn",
+ GetLoadResultForNavigationTest(GetFirstChild(web_contents)));
+ EXPECT_EQ(ExecuteAndGetString(GetFirstChild(web_contents), "location.href"),
+ url_origin.Resolve("/1-page/#hash1"));
+
+ RunScriptAndObserveNavigation(
+ "Back navigate the iframe to /1-page/", web_contents,
+ web_contents /* execution_target */, "history.back();",
+ {NAVIGATION_TYPE_AUTO_SUBFRAME},
+ get_url_for_bundle.Run(url_origin.Resolve(
+ "/iframe-test-page/")) /* expected_last_comitted_url */,
+ url_origin.Resolve("/iframe-test-page/") /* expected_last_inner_url */,
+ "/iframe-test-page/ from wbn, /iframe-test-page/script from wbn");
+ EXPECT_EQ("/1-page/ from wbn, /1-page/script from wbn",
+ GetLoadResultForNavigationTest(GetFirstChild(web_contents)));
+ EXPECT_EQ(ExecuteAndGetString(GetFirstChild(web_contents), "location.href"),
+ url_origin.Resolve("/1-page/"));
+
+ RunScriptAndObserveNavigation(
+ "Back navigate to /top-page/", web_contents,
+ web_contents /* execution_target */, "history.back();",
+ {NAVIGATION_TYPE_EXISTING_PAGE},
+ get_url_for_bundle.Run(
+ url_origin.Resolve("/top-page/")) /* expected_last_comitted_url */,
+ url_origin.Resolve("/top-page/") /* expected_last_inner_url */,
+ "/top-page/ from wbn, /top-page/script from wbn");
+
+ RunScriptAndObserveNavigation(
+ "Forward navigate to /iframe-test-page/", web_contents,
+ web_contents /* execution_target */, "history.forward();",
+ {NAVIGATION_TYPE_EXISTING_PAGE, NAVIGATION_TYPE_AUTO_SUBFRAME},
+ get_url_for_bundle.Run(url_origin.Resolve(
+ "/iframe-test-page/")) /* expected_last_comitted_url */,
+ url_origin.Resolve("/iframe-test-page/") /* expected_last_inner_url */,
+ "/iframe-test-page/ from wbn, /iframe-test-page/script from wbn");
+ EXPECT_EQ("/1-page/ from wbn, /1-page/script from wbn",
+ GetLoadResultForNavigationTest(GetFirstChild(web_contents)));
+ EXPECT_EQ(ExecuteAndGetString(GetFirstChild(web_contents), "location.href"),
+ url_origin.Resolve("/1-page/"));
+
+ RunScriptAndObserveNavigation(
+ "Forward navigate the iframe to /1-page/#hash1", web_contents,
+ web_contents /* execution_target */, "history.forward();",
+ {NAVIGATION_TYPE_AUTO_SUBFRAME},
+ get_url_for_bundle.Run(url_origin.Resolve(
+ "/iframe-test-page/")) /* expected_last_comitted_url */,
+ url_origin.Resolve("/iframe-test-page/") /* expected_last_inner_url */,
+ "/iframe-test-page/ from wbn, /iframe-test-page/script from wbn");
+ EXPECT_EQ("/1-page/ from wbn, /1-page/script from wbn",
+ GetLoadResultForNavigationTest(GetFirstChild(web_contents)));
+ EXPECT_EQ(ExecuteAndGetString(GetFirstChild(web_contents), "location.href"),
+ url_origin.Resolve("/1-page/#hash1"));
+
+ RunScriptAndObserveNavigation(
+ "Forward navigate the iframe to /1-page/#hash2", web_contents,
+ web_contents /* execution_target */, "history.forward();",
+ {NAVIGATION_TYPE_AUTO_SUBFRAME},
+ get_url_for_bundle.Run(url_origin.Resolve(
+ "/iframe-test-page/")) /* expected_last_comitted_url */,
+ url_origin.Resolve("/iframe-test-page/") /* expected_last_inner_url */,
+ "/iframe-test-page/ from wbn, /iframe-test-page/script from wbn");
+ EXPECT_EQ("/1-page/ from wbn, /1-page/script from wbn",
+ GetLoadResultForNavigationTest(GetFirstChild(web_contents)));
+ EXPECT_EQ(ExecuteAndGetString(GetFirstChild(web_contents), "location.href"),
+ url_origin.Resolve("/1-page/#hash2"));
+
+ RunScriptAndObserveNavigation(
+ "Forward navigate the iframe to /2-page/", web_contents,
+ web_contents /* execution_target */, "history.forward();",
+ {NAVIGATION_TYPE_AUTO_SUBFRAME},
+ get_url_for_bundle.Run(url_origin.Resolve(
+ "/iframe-test-page/")) /* expected_last_comitted_url */,
+ url_origin.Resolve("/iframe-test-page/") /* expected_last_inner_url */,
+ "/iframe-test-page/ from wbn, /iframe-test-page/script from wbn");
+ EXPECT_EQ("/2-page/ from wbn, /2-page/script from wbn",
+ GetLoadResultForNavigationTest(GetFirstChild(web_contents)));
+}
+
} // namespace
class InvalidTrustableWebBundleFileUrlBrowserTest : public ContentBrowserTest {
@@ -762,12 +1651,19 @@ class WebBundleTrustableFileBrowserTest
const GURL& test_data_url() const { return test_data_url_; }
const GURL& empty_page_url() const { return empty_page_url_; }
- std::string ExecuteAndGetString(const std::string& script) {
- std::string result;
- EXPECT_TRUE(content::ExecuteScriptAndExtractString(
- shell()->web_contents(), "domAutomationController.send(" + script + ")",
- &result));
- return result;
+ void RunSharedNavigationTest(
+ void (*setup_func)(net::EmbeddedTestServer*, GURL*, std::string*),
+ void (*run_test_func)(WebContents*,
+ const GURL&,
+ const GURL&,
+ base::RepeatingCallback<GURL(const GURL&)>)) {
+ GURL url_origin;
+ std::string web_bundle_content;
+ (*setup_func)(embedded_test_server(), &url_origin, &web_bundle_content);
+ WriteWebBundleFile(web_bundle_content);
+
+ (*run_test_func)(shell()->web_contents(), test_data_url(), url_origin,
+ base::BindRepeating([](const GURL& url) { return url; }));
}
private:
@@ -818,70 +1714,57 @@ IN_PROC_BROWSER_TEST_P(WebBundleTrustableFileBrowserTest, RangeRequest) {
RunTestScript("test-range-request.js");
}
-IN_PROC_BROWSER_TEST_P(WebBundleTrustableFileBrowserTest, Navigations) {
- WriteCommonWebBundleFile();
- NavigateToBundleAndWaitForReady(test_data_url(), GURL(kTestPageUrl));
- // Move to page 1.
- NavigateToURLAndWaitForTitle(GURL(kTestPage1Url), "Page 1");
- EXPECT_EQ(shell()->web_contents()->GetLastCommittedURL(),
- GURL(kTestPage1Url));
- // Move to page 2.
- NavigateToURLAndWaitForTitle(GURL(kTestPage2Url), "Page 2");
- EXPECT_EQ(shell()->web_contents()->GetLastCommittedURL(),
- GURL(kTestPage2Url));
- // Back to page 1.
- ExecuteScriptAndWaitForTitle("history.back();", "Page 1");
- EXPECT_EQ(shell()->web_contents()->GetLastCommittedURL(),
- GURL(kTestPage1Url));
-
- // Back to the initial page.
- ExecuteScriptAndWaitForTitle("history.back();", "Ready");
- EXPECT_EQ(shell()->web_contents()->GetLastCommittedURL(), GURL(kTestPageUrl));
+IN_PROC_BROWSER_TEST_P(WebBundleTrustableFileBrowserTest, BasicNavigation) {
+ RunSharedNavigationTest(&SetUpBasicNavigationTest, &RunBasicNavigationTest);
+}
- // Move to page 1.
- ExecuteScriptAndWaitForTitle("history.forward();", "Page 1");
- EXPECT_EQ(shell()->web_contents()->GetLastCommittedURL(),
- GURL(kTestPage1Url));
+IN_PROC_BROWSER_TEST_P(WebBundleTrustableFileBrowserTest,
+ BrowserInitiatedOutOfBundleNavigation) {
+ RunSharedNavigationTest(&SetUpBrowserInitiatedOutOfBundleNavigationTest,
+ &RunBrowserInitiatedOutOfBundleNavigationTest);
+}
- // Reload.
- ExecuteScriptAndWaitForTitle("document.title = 'reset';", "reset");
- ExecuteScriptAndWaitForTitle("location.reload();", "Page 1");
- EXPECT_EQ(shell()->web_contents()->GetLastCommittedURL(),
- GURL(kTestPage1Url));
+IN_PROC_BROWSER_TEST_P(WebBundleTrustableFileBrowserTest,
+ RendererInitiatedOutOfBundleNavigation) {
+ RunSharedNavigationTest(&SetUpRendererInitiatedOutOfBundleNavigationTest,
+ &RunRendererInitiatedOutOfBundleNavigationTest);
+}
- // Move to page 2.
- ExecuteScriptAndWaitForTitle("history.forward();", "Page 2");
- EXPECT_EQ(shell()->web_contents()->GetLastCommittedURL(),
- GURL(kTestPage2Url));
+IN_PROC_BROWSER_TEST_P(WebBundleTrustableFileBrowserTest,
+ SameDocumentNavigation) {
+ RunSharedNavigationTest(&SetUpSameDocumentNavigationTest,
+ &RunSameDocumentNavigationTest);
+}
- // Move out of the Web Bundle.
- NavigateAndWaitForTitle(empty_page_url(), empty_page_url(), "Empty Page");
+IN_PROC_BROWSER_TEST_P(WebBundleTrustableFileBrowserTest, IframeNavigation) {
+ RunSharedNavigationTest(&SetUpIframeNavigationTest, &RunIframeNavigationTest);
+}
- // Back to the page 2.
- ExecuteScriptAndWaitForTitle("history.back();", "Page 2");
- EXPECT_EQ(shell()->web_contents()->GetLastCommittedURL(),
- GURL(kTestPage2Url));
+IN_PROC_BROWSER_TEST_P(WebBundleTrustableFileBrowserTest,
+ IframeOutOfBundleNavigation) {
+ RunSharedNavigationTest(&SetUpIframeNavigationTest,
+ &RunIframeOutOfBundleNavigationTest);
}
-IN_PROC_BROWSER_TEST_P(WebBundleTrustableFileBrowserTest, NavigationWithHash) {
- WriteCommonWebBundleFile();
- NavigateToBundleAndWaitForReady(test_data_url(), GURL(kTestPageUrl));
- NavigateToURLAndWaitForTitle(GURL(kTestPageForHashUrl), "#hello");
+IN_PROC_BROWSER_TEST_P(WebBundleTrustableFileBrowserTest,
+ IframeParentInitiatedOutOfBundleNavigation) {
+ RunSharedNavigationTest(&SetUpIframeNavigationTest,
+ &RunIframeParentInitiatedOutOfBundleNavigationTest);
+}
- EXPECT_EQ(ExecuteAndGetString("window.location.href"),
- "https://test.example.org/hash.html#hello");
- EXPECT_EQ(ExecuteAndGetString("document.location.href"),
- "https://test.example.org/hash.html#hello");
- EXPECT_EQ(ExecuteAndGetString("document.URL"),
- "https://test.example.org/hash.html#hello");
+IN_PROC_BROWSER_TEST_P(WebBundleTrustableFileBrowserTest,
+ IframeSameDocumentNavigation) {
+ RunSharedNavigationTest(&SetUpIframeNavigationTest,
+ &RunIframeSameDocumentNavigationTest);
}
IN_PROC_BROWSER_TEST_P(WebBundleTrustableFileBrowserTest, BaseURI) {
WriteCommonWebBundleFile();
NavigateToBundleAndWaitForReady(test_data_url(), GURL(kTestPageUrl));
- EXPECT_EQ(ExecuteAndGetString("(new Request('./foo/bar')).url"),
+ EXPECT_EQ(ExecuteAndGetString(shell()->web_contents(),
+ "(new Request('./foo/bar')).url"),
"https://test.example.org/foo/bar");
- EXPECT_EQ(ExecuteAndGetString(R"(
+ EXPECT_EQ(ExecuteAndGetString(shell()->web_contents(), R"(
(() => {
const base_element = document.createElement('base');
base_element.href = 'https://example.org/piyo/';
@@ -890,7 +1773,8 @@ IN_PROC_BROWSER_TEST_P(WebBundleTrustableFileBrowserTest, BaseURI) {
})()
)"),
"https://example.org/piyo/");
- EXPECT_EQ(ExecuteAndGetString("(new Request('./foo/bar')).url"),
+ EXPECT_EQ(ExecuteAndGetString(shell()->web_contents(),
+ "(new Request('./foo/bar')).url"),
"https://example.org/piyo/foo/bar");
}
@@ -988,6 +1872,26 @@ class WebBundleFileBrowserTest
return content_uri;
}
+ void RunSharedNavigationTest(
+ void (*setup_func)(net::EmbeddedTestServer*, GURL*, std::string*),
+ void (*run_test_func)(WebContents*,
+ const GURL&,
+ const GURL&,
+ base::RepeatingCallback<GURL(const GURL&)>)) {
+ GURL url_origin;
+ std::string web_bundle_content;
+ (*setup_func)(embedded_test_server(), &url_origin, &web_bundle_content);
+
+ base::FilePath file_path;
+ CreateTemporaryWebBundleFile(web_bundle_content, &file_path);
+ const GURL test_data_url = GetTestUrlForFile(file_path);
+
+ (*run_test_func)(
+ shell()->web_contents(), test_data_url, url_origin,
+ base::BindRepeating(&web_bundle_utils::GetSynthesizedUrlForWebBundle,
+ test_data_url));
+ }
+
private:
base::test::ScopedFeatureList feature_list_;
@@ -995,83 +1899,44 @@ class WebBundleFileBrowserTest
};
IN_PROC_BROWSER_TEST_P(WebBundleFileBrowserTest, BasicNavigation) {
- const GURL test_data_url =
- GetTestUrlForFile(GetTestDataPath("web_bundle_browsertest.wbn"));
- NavigateToBundleAndWaitForReady(
- test_data_url, web_bundle_utils::GetSynthesizedUrlForWebBundle(
- test_data_url, GURL(kTestPageUrl)));
+ RunSharedNavigationTest(&SetUpBasicNavigationTest, &RunBasicNavigationTest);
}
-IN_PROC_BROWSER_TEST_P(WebBundleFileBrowserTest, Navigations) {
- const GURL test_data_url =
- GetTestUrlForFile(GetTestDataPath("web_bundle_browsertest.wbn"));
- NavigateToBundleAndWaitForReady(
- test_data_url, web_bundle_utils::GetSynthesizedUrlForWebBundle(
- test_data_url, GURL(kTestPageUrl)));
- // Move to page 1.
- NavigateToURLAndWaitForTitle(GURL(kTestPage1Url), "Page 1");
- EXPECT_EQ(shell()->web_contents()->GetLastCommittedURL(),
- web_bundle_utils::GetSynthesizedUrlForWebBundle(
- test_data_url, GURL(kTestPage1Url)));
- // Move to page 2.
- NavigateToURLAndWaitForTitle(GURL(kTestPage2Url), "Page 2");
- EXPECT_EQ(shell()->web_contents()->GetLastCommittedURL(),
- web_bundle_utils::GetSynthesizedUrlForWebBundle(
- test_data_url, GURL(kTestPage2Url)));
-
- // Back to page 1.
- ExecuteScriptAndWaitForTitle("history.back();", "Page 1");
- EXPECT_EQ(shell()->web_contents()->GetLastCommittedURL(),
- web_bundle_utils::GetSynthesizedUrlForWebBundle(
- test_data_url, GURL(kTestPage1Url)));
- // Back to the initial page.
- ExecuteScriptAndWaitForTitle("history.back();", "Ready");
- EXPECT_EQ(shell()->web_contents()->GetLastCommittedURL(),
- web_bundle_utils::GetSynthesizedUrlForWebBundle(
- test_data_url, GURL(kTestPageUrl)));
-
- // Move to page 1.
- ExecuteScriptAndWaitForTitle("history.forward();", "Page 1");
- EXPECT_EQ(shell()->web_contents()->GetLastCommittedURL(),
- web_bundle_utils::GetSynthesizedUrlForWebBundle(
- test_data_url, GURL(kTestPage1Url)));
+IN_PROC_BROWSER_TEST_P(WebBundleFileBrowserTest,
+ BrowserInitiatedOutOfBundleNavigation) {
+ RunSharedNavigationTest(&SetUpBrowserInitiatedOutOfBundleNavigationTest,
+ &RunBrowserInitiatedOutOfBundleNavigationTest);
+}
- // Reload.
- ExecuteScriptAndWaitForTitle("document.title = 'reset';", "reset");
- ExecuteScriptAndWaitForTitle("location.reload();", "Page 1");
- EXPECT_EQ(shell()->web_contents()->GetLastCommittedURL(),
- web_bundle_utils::GetSynthesizedUrlForWebBundle(
- test_data_url, GURL(kTestPage1Url)));
+IN_PROC_BROWSER_TEST_P(WebBundleFileBrowserTest,
+ RendererInitiatedOutOfBundleNavigation) {
+ RunSharedNavigationTest(&SetUpRendererInitiatedOutOfBundleNavigationTest,
+ &RunRendererInitiatedOutOfBundleNavigationTest);
+}
- // Move to page 2.
- ExecuteScriptAndWaitForTitle("history.forward();", "Page 2");
- EXPECT_EQ(shell()->web_contents()->GetLastCommittedURL(),
- web_bundle_utils::GetSynthesizedUrlForWebBundle(
- test_data_url, GURL(kTestPage2Url)));
+IN_PROC_BROWSER_TEST_P(WebBundleFileBrowserTest, SameDocumentNavigation) {
+ RunSharedNavigationTest(&SetUpSameDocumentNavigationTest,
+ &RunSameDocumentNavigationTest);
+}
- const GURL empty_page_url =
- GetTestUrlForFile(GetTestDataPath("empty_page.html"));
+IN_PROC_BROWSER_TEST_P(WebBundleFileBrowserTest, IframeNavigation) {
+ RunSharedNavigationTest(&SetUpIframeNavigationTest, &RunIframeNavigationTest);
+}
- // Move out of the Web Bundle.
- NavigateAndWaitForTitle(empty_page_url, empty_page_url, "Empty Page");
+IN_PROC_BROWSER_TEST_P(WebBundleFileBrowserTest, IframeOutOfBundleNavigation) {
+ RunSharedNavigationTest(&SetUpIframeNavigationTest,
+ &RunIframeOutOfBundleNavigationTest);
+}
- // Back to the page 2 in the Web Bundle.
- ExecuteScriptAndWaitForTitle("history.back();", "Page 2");
- EXPECT_EQ(shell()->web_contents()->GetLastCommittedURL(),
- web_bundle_utils::GetSynthesizedUrlForWebBundle(
- test_data_url, GURL(kTestPage2Url)));
+IN_PROC_BROWSER_TEST_P(WebBundleFileBrowserTest,
+ IframeParentInitiatedOutOfBundleNavigation) {
+ RunSharedNavigationTest(&SetUpIframeNavigationTest,
+ &RunIframeParentInitiatedOutOfBundleNavigationTest);
}
-IN_PROC_BROWSER_TEST_P(WebBundleFileBrowserTest, NavigationWithHash) {
- const GURL test_data_url =
- GetTestUrlForFile(GetTestDataPath("web_bundle_browsertest.wbn"));
- NavigateToBundleAndWaitForReady(
- test_data_url, web_bundle_utils::GetSynthesizedUrlForWebBundle(
- test_data_url, GURL(kTestPageUrl)));
- NavigateToURLAndWaitForTitle(GURL(kTestPageForHashUrl), "#hello");
- EXPECT_EQ(shell()->web_contents()->GetLastCommittedURL(),
- web_bundle_utils::GetSynthesizedUrlForWebBundle(
- test_data_url, GURL(kTestPageForHashUrl)));
+IN_PROC_BROWSER_TEST_P(WebBundleFileBrowserTest, IframeSameDocumentNavigation) {
+ RunSharedNavigationTest(&SetUpIframeNavigationTest,
+ &RunIframeSameDocumentNavigationTest);
}
IN_PROC_BROWSER_TEST_P(WebBundleFileBrowserTest, InvalidWebBundleFile) {
@@ -1152,13 +2017,15 @@ IN_PROC_BROWSER_TEST_P(WebBundleFileBrowserTest, NoLocalFileScheme) {
}
IN_PROC_BROWSER_TEST_P(WebBundleFileBrowserTest, DataDecoderRestart) {
+ constexpr char kTestPage1Url[] = "https://test.example.org/page1.html";
+ constexpr char kTestPage2Url[] = "https://test.example.org/page2.html";
// The content of this file will be read as response body of any exchange.
base::FilePath test_file_path = GetTestDataPath("mocked.wbn");
MockParserFactory mock_factory(
{GURL(kTestPageUrl), GURL(kTestPage1Url), GURL(kTestPage2Url)},
test_file_path);
const GURL test_data_url = GetTestUrlForFile(test_file_path);
- NavigateAndWaitForTitle(test_data_url,
+ NavigateAndWaitForTitle(shell()->web_contents(), test_data_url,
web_bundle_utils::GetSynthesizedUrlForWebBundle(
test_data_url, GURL(kTestPageUrl)),
kTestPageUrl);
@@ -1214,12 +2081,12 @@ IN_PROC_BROWSER_TEST_P(WebBundleFileBrowserTest, Variants) {
SetAcceptLangs("ja,en");
const GURL test_data_url =
GetTestUrlForFile(GetTestDataPath("variants_test.wbn"));
- NavigateAndWaitForTitle(test_data_url,
+ NavigateAndWaitForTitle(shell()->web_contents(), test_data_url,
web_bundle_utils::GetSynthesizedUrlForWebBundle(
test_data_url, GURL(kTestPageUrl)),
"lang=ja");
SetAcceptLangs("en,ja");
- NavigateAndWaitForTitle(test_data_url,
+ NavigateAndWaitForTitle(shell()->web_contents(), test_data_url,
web_bundle_utils::GetSynthesizedUrlForWebBundle(
test_data_url, GURL(kTestPageUrl)),
"lang=en");
@@ -1421,6 +2288,24 @@ class WebBundleNetworkBrowserTest : public WebBundleBrowserTestBase {
void SetContents(const std::string& contents) { contents_ = contents; }
const std::string& contents() const { return contents_; }
+ void RunSharedNavigationTest(
+ void (*setup_func)(net::EmbeddedTestServer*, GURL*, std::string*),
+ void (*run_test_func)(WebContents*,
+ const GURL&,
+ const GURL&,
+ base::RepeatingCallback<GURL(const GURL&)>)) {
+ const std::string wbn_path = "/test.wbn";
+ RegisterRequestHandler(wbn_path);
+ GURL url_origin;
+ std::string web_bundle_content;
+ (*setup_func)(embedded_test_server(), &url_origin, &web_bundle_content);
+ SetContents(web_bundle_content);
+
+ (*run_test_func)(shell()->web_contents(), url_origin.Resolve(wbn_path),
+ url_origin,
+ base::BindRepeating([](const GURL& url) { return url; }));
+ }
+
private:
base::test::ScopedFeatureList feature_list_;
std::string headers_ = kDefaultHeaders;
@@ -1669,7 +2554,50 @@ IN_PROC_BROWSER_TEST_F(WebBundleNetworkBrowserTest, PathMismatch) {
primary_url.spec().c_str(), wbn_url.spec().c_str()));
}
-IN_PROC_BROWSER_TEST_F(WebBundleNetworkBrowserTest, Navigations) {
+IN_PROC_BROWSER_TEST_F(WebBundleNetworkBrowserTest, BasicNavigation) {
+ RunSharedNavigationTest(&SetUpBasicNavigationTest, &RunBasicNavigationTest);
+}
+
+IN_PROC_BROWSER_TEST_F(WebBundleNetworkBrowserTest,
+ BrowserInitiatedOutOfBundleNavigation) {
+ RunSharedNavigationTest(&SetUpBrowserInitiatedOutOfBundleNavigationTest,
+ &RunBrowserInitiatedOutOfBundleNavigationTest);
+}
+
+IN_PROC_BROWSER_TEST_F(WebBundleNetworkBrowserTest,
+ RendererInitiatedOutOfBundleNavigation) {
+ RunSharedNavigationTest(&SetUpRendererInitiatedOutOfBundleNavigationTest,
+ &RunRendererInitiatedOutOfBundleNavigationTest);
+}
+
+IN_PROC_BROWSER_TEST_F(WebBundleNetworkBrowserTest, SameDocumentNavigation) {
+ RunSharedNavigationTest(&SetUpSameDocumentNavigationTest,
+ &RunSameDocumentNavigationTest);
+}
+
+IN_PROC_BROWSER_TEST_F(WebBundleNetworkBrowserTest, IframeNavigation) {
+ RunSharedNavigationTest(&SetUpIframeNavigationTest, &RunIframeNavigationTest);
+}
+
+IN_PROC_BROWSER_TEST_F(WebBundleNetworkBrowserTest,
+ IframeOutOfBundleNavigation) {
+ RunSharedNavigationTest(&SetUpIframeNavigationTest,
+ &RunIframeOutOfBundleNavigationTest);
+}
+
+IN_PROC_BROWSER_TEST_F(WebBundleNetworkBrowserTest,
+ IframeParentInitiatedOutOfBundleNavigation) {
+ RunSharedNavigationTest(&SetUpIframeNavigationTest,
+ &RunIframeParentInitiatedOutOfBundleNavigationTest);
+}
+
+IN_PROC_BROWSER_TEST_F(WebBundleNetworkBrowserTest,
+ IframeSameDocumentNavigation) {
+ RunSharedNavigationTest(&SetUpIframeNavigationTest,
+ &RunIframeSameDocumentNavigationTest);
+}
+
+IN_PROC_BROWSER_TEST_F(WebBundleNetworkBrowserTest, CrossScopeNavigations) {
const std::string wbn_path = "/web_bundle/path_test/in_scope/path_test.wbn";
RegisterRequestHandler(wbn_path);
ASSERT_TRUE(embedded_test_server()->Start());
@@ -1694,7 +2622,8 @@ IN_PROC_BROWSER_TEST_F(WebBundleNetworkBrowserTest, Navigations) {
"In scope page from server / in scope script from server");
}
-IN_PROC_BROWSER_TEST_F(WebBundleNetworkBrowserTest, HistoryNavigations) {
+IN_PROC_BROWSER_TEST_F(WebBundleNetworkBrowserTest,
+ CrossScopeHistoryNavigations) {
const std::string wbn_path = "/web_bundle/path_test/in_scope/path_test.wbn";
RegisterRequestHandler(wbn_path);
ASSERT_TRUE(embedded_test_server()->Start());
diff --git a/chromium/content/browser/web_package/web_bundle_interceptor_for_history_navigation_with_existing_reader.cc b/chromium/content/browser/web_package/web_bundle_interceptor_for_history_navigation_with_existing_reader.cc
index cb9d37dd19f..03a8934792e 100644
--- a/chromium/content/browser/web_package/web_bundle_interceptor_for_history_navigation_with_existing_reader.cc
+++ b/chromium/content/browser/web_package/web_bundle_interceptor_for_history_navigation_with_existing_reader.cc
@@ -8,6 +8,7 @@
#include "content/browser/web_package/web_bundle_reader.h"
#include "content/browser/web_package/web_bundle_source.h"
#include "content/browser/web_package/web_bundle_utils.h"
+#include "net/base/url_util.h"
#include "services/network/public/cpp/resource_request.h"
#include "url/gurl.h"
@@ -35,12 +36,13 @@ void WebBundleInterceptorForHistoryNavigationWithExistingReader::
LoaderCallback callback,
FallbackCallback fallback_callback) {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
- DCHECK_EQ(resource_request.url,
+ DCHECK_EQ(net::SimplifyUrlForRequest(resource_request.url),
url_loader_factory_->reader()->source().is_file()
- ? web_bundle_utils::GetSynthesizedUrlForWebBundle(
- url_loader_factory_->reader()->source().url(),
- target_inner_url_)
- : target_inner_url_);
+ ? net::SimplifyUrlForRequest(
+ web_bundle_utils::GetSynthesizedUrlForWebBundle(
+ url_loader_factory_->reader()->source().url(),
+ target_inner_url_))
+ : net::SimplifyUrlForRequest(target_inner_url_));
std::move(callback).Run(
base::MakeRefCounted<SingleRequestURLLoaderFactory>(base::BindOnce(
&WebBundleInterceptorForHistoryNavigationWithExistingReader::
@@ -54,12 +56,13 @@ void WebBundleInterceptorForHistoryNavigationWithExistingReader::
mojo::PendingReceiver<network::mojom::URLLoader> receiver,
mojo::PendingRemote<network::mojom::URLLoaderClient> client) {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
- DCHECK_EQ(resource_request.url,
+ DCHECK_EQ(net::SimplifyUrlForRequest(resource_request.url),
url_loader_factory_->reader()->source().is_file()
- ? web_bundle_utils::GetSynthesizedUrlForWebBundle(
- url_loader_factory_->reader()->source().url(),
- target_inner_url_)
- : target_inner_url_);
+ ? net::SimplifyUrlForRequest(
+ web_bundle_utils::GetSynthesizedUrlForWebBundle(
+ url_loader_factory_->reader()->source().url(),
+ target_inner_url_))
+ : net::SimplifyUrlForRequest(target_inner_url_));
CreateLoaderAndStartAndDone(resource_request, std::move(receiver),
std::move(client));
}
diff --git a/chromium/content/browser/web_package/web_bundle_reader.cc b/chromium/content/browser/web_package/web_bundle_reader.cc
index 869195a08d2..75051285636 100644
--- a/chromium/content/browser/web_package/web_bundle_reader.cc
+++ b/chromium/content/browser/web_package/web_bundle_reader.cc
@@ -8,7 +8,6 @@
#include "base/check_op.h"
#include "base/numerics/safe_math.h"
-#include "base/task/post_task.h"
#include "base/task/task_traits.h"
#include "base/task/thread_pool.h"
#include "content/browser/web_package/web_bundle_blob_data_source.h"
@@ -188,7 +187,7 @@ void WebBundleReader::ReadResponse(
auto it = entries_.find(net::SimplifyUrlForRequest(resource_request.url));
if (it == entries_.end() || it->second->response_locations.empty()) {
- PostTask(
+ base::ThreadPool::PostTask(
FROM_HERE,
base::BindOnce(
std::move(callback), nullptr,
@@ -206,7 +205,7 @@ void WebBundleReader::ReadResponse(
accept_langs);
auto found = matcher.FindBestMatchingIndex(entry->variants_value);
if (!found || *found >= entry->response_locations.size()) {
- PostTask(
+ base::ThreadPool::PostTask(
FROM_HERE,
base::BindOnce(
std::move(callback), nullptr,
@@ -257,8 +256,8 @@ void WebBundleReader::Reconnect() {
pending_remote.InitWithNewPipeAndPassReceiver());
parser_->OpenDataSource(std::move(pending_remote));
- base::PostTask(FROM_HERE, {BrowserThread::UI},
- base::BindOnce(&WebBundleReader::DidReconnect, this,
+ GetUIThreadTaskRunner({})->PostTask(
+ FROM_HERE, base::BindOnce(&WebBundleReader::DidReconnect, this,
base::nullopt /* error */));
}
@@ -267,8 +266,8 @@ void WebBundleReader::ReconnectForFile(base::File file) {
base::Optional<std::string> error;
if (file_error != base::File::FILE_OK)
error = base::File::ErrorToString(file_error);
- base::PostTask(
- FROM_HERE, {BrowserThread::UI},
+ GetUIThreadTaskRunner({})->PostTask(
+ FROM_HERE,
base::BindOnce(&WebBundleReader::DidReconnect, this, std::move(error)));
}
@@ -279,7 +278,7 @@ void WebBundleReader::DidReconnect(base::Optional<std::string> error) {
if (error) {
for (auto& pair : read_tasks) {
- PostTask(
+ base::ThreadPool::PostTask(
FROM_HERE,
base::BindOnce(std::move(pair.second), nullptr,
data_decoder::mojom::BundleResponseParseError::New(
@@ -352,8 +351,8 @@ void WebBundleReader::ReadMetadataInternal(MetadataCallback callback,
DCHECK(source_->is_trusted_file() || source_->is_file());
base::File::Error error = parser_->OpenFile(std::move(file));
if (base::File::FILE_OK != error) {
- base::PostTask(
- FROM_HERE, {BrowserThread::UI},
+ GetUIThreadTaskRunner({})->PostTask(
+ FROM_HERE,
base::BindOnce(
std::move(callback),
data_decoder::mojom::BundleMetadataParseError::New(