Chromium Code Reviews| Index: chrome/browser/prerender/prerender_nostate_prefetch_browsertest.cc |
| diff --git a/chrome/browser/prerender/prerender_nostate_prefetch_browsertest.cc b/chrome/browser/prerender/prerender_nostate_prefetch_browsertest.cc |
| index 65551c02de58d59c99c39ad334468b006e804518..ecd184603c075034e793d07ca048085d831e1d85 100644 |
| --- a/chrome/browser/prerender/prerender_nostate_prefetch_browsertest.cc |
| +++ b/chrome/browser/prerender/prerender_nostate_prefetch_browsertest.cc |
| @@ -3,10 +3,14 @@ |
| // found in the LICENSE file. |
| #include "base/command_line.h" |
| +#include "base/memory/ptr_util.h" |
| +#include "base/memory/ref_counted.h" |
| #include "base/strings/string16.h" |
| #include "base/strings/string_split.h" |
| +#include "base/strings/stringprintf.h" |
| #include "base/strings/utf_string_conversions.h" |
| #include "base/task_scheduler/post_task.h" |
| +#include "base/test/simple_test_tick_clock.h" |
| #include "chrome/browser/history/history_service_factory.h" |
| #include "chrome/browser/history/history_test_utils.h" |
| #include "chrome/browser/prerender/prerender_handle.h" |
| @@ -21,7 +25,9 @@ |
| #include "chrome/common/chrome_switches.h" |
| #include "chrome/grit/generated_resources.h" |
| #include "chrome/test/base/ui_test_utils.h" |
| +#include "content/public/browser/appcache_service.h" |
| #include "content/public/browser/render_process_host.h" |
| +#include "content/public/browser/storage_partition.h" |
| #include "content/public/common/result_codes.h" |
| #include "content/public/common/url_constants.h" |
| #include "content/public/test/browser_test_utils.h" |
| @@ -40,6 +46,8 @@ namespace prerender { |
| // These URLs used for test resources must be relative with the exception of |
| // |kPrefetchLoaderPath|. |
| +const char kPrefetchAppcache[] = "prerender/prefetch_appcache.html"; |
| +const char kPrefetchAppcacheManifest[] = "prerender/appcache.manifest"; |
| const char kPrefetchImagePage[] = "prerender/prefetch_image.html"; |
| const char kPrefetchJpeg[] = "prerender/image.jpeg"; |
| const char kPrefetchLoaderPath[] = "/prerender/prefetch_loader.html"; |
| @@ -89,6 +97,32 @@ class NoStatePrefetchBrowserTest |
| url_file, counter->AsWeakPtr())); |
| } |
| + base::SimpleTestTickClock* OverridePrerenderManagerTimeTicks() { |
| + auto clock = base::MakeUnique<base::SimpleTestTickClock>(); |
| + auto* clock_ptr = clock.get(); |
| + // The default zero time causes the prerender manager to do strange things. |
| + clock->Advance(base::TimeDelta::FromSeconds(1)); |
| + GetPrerenderManager()->SetTickClockForTesting(std::move(clock)); |
| + return clock_ptr; |
| + } |
| + |
| + // Block until an AppCache exists for |manifest_url|. |
| + void WaitForAppcache(const GURL& manifest_url) { |
| + bool found_manifest = false; |
| + content::AppCacheService* appcache_service = |
| + content::BrowserContext::GetDefaultStoragePartition( |
| + current_browser()->profile()) |
| + ->GetAppCacheService(); |
| + do { |
| + base::RunLoop wait_loop; |
| + content::BrowserThread::PostTask( |
| + content::BrowserThread::IO, FROM_HERE, |
| + base::Bind(WaitForAppcacheOnIO, manifest_url, appcache_service, |
| + wait_loop.QuitClosure(), &found_manifest)); |
| + wait_loop.Run(); |
| + } while (!found_manifest); |
|
droger
2017/04/13 13:40:29
Can we remove the while loop and just EXPECT_TRUE(
mattcary
2017/04/13 14:05:53
No, it sometimes takes a while for the manifest to
|
| + } |
| + |
| protected: |
| std::unique_ptr<TestPrerender> PrefetchFromURL( |
| const GURL& target_url, |
| @@ -111,6 +145,45 @@ class NoStatePrefetchBrowserTest |
| } |
| private: |
| + // Schedule a task to retrieve AppCacheInfo from |appcache_service|. This sets |
| + // |found_manifest| if an appcache exists for |manifest_url|. |callback| will |
| + // be called on the UI thread after the info is retrieved, whether or not the |
| + // manifest exists. |
| + static void WaitForAppcacheOnIO(const GURL& manifest_url, |
| + content::AppCacheService* appcache_service, |
| + base::Closure callback, |
| + bool* found_manifest) { |
| + scoped_refptr<content::AppCacheInfoCollection> info_collection = |
| + new content::AppCacheInfoCollection(); |
| + appcache_service->GetAllAppCacheInfo( |
| + info_collection.get(), |
| + base::Bind(ProcessAppCacheInfo, manifest_url, callback, found_manifest, |
| + info_collection)); |
| + } |
| + |
| + // Look through |info_collection| for an entry matching |target_manifest|, |
| + // setting |found_manifest| appropriately. Then |callback| will be invoked on |
| + // the UI thread. |
| + static void ProcessAppCacheInfo( |
| + const GURL& target_manifest, |
| + base::Closure callback, |
| + bool* found_manifest, |
| + scoped_refptr<content::AppCacheInfoCollection> info_collection, |
| + int status) { |
| + if (status == net::OK) { |
| + for (const auto& origin_pair : info_collection->infos_by_origin) { |
| + for (const auto& info : origin_pair.second) { |
| + if (info.manifest_url == target_manifest) { |
| + *found_manifest = true; |
| + break; |
| + } |
| + } |
| + } |
| + } |
| + content::BrowserThread::PostTask(content::BrowserThread::UI, FROM_HERE, |
| + callback); |
| + } |
| + |
| DISALLOW_COPY_AND_ASSIGN(NoStatePrefetchBrowserTest); |
| }; |
| @@ -185,15 +258,10 @@ IN_PROC_BROWSER_TEST_F(NoStatePrefetchBrowserTest, PrefetchHistograms) { |
| IN_PROC_BROWSER_TEST_F(NoStatePrefetchBrowserTest, PrefetchImage) { |
| RequestCounter image_counter; |
| CountRequestFor(kPrefetchJpeg, &image_counter); |
| - base::StringPairs replacement_text; |
| - replacement_text.push_back( |
| - std::make_pair("REPLACE_WITH_IMAGE_URL", MakeAbsolute(kPrefetchJpeg))); |
| - std::string main_page_path; |
| - net::test_server::GetFilePathWithReplacements( |
| - kPrefetchImagePage, replacement_text, &main_page_path); |
| - // Note CountRequestFor cannot be used on the main page as the test server |
| - // must handling the image url replacement. |
| - PrefetchFromFile(main_page_path, FINAL_STATUS_NOSTATE_PREFETCH_FINISHED); |
| + GURL main_page_url = |
| + GetURLWithReplacement(kPrefetchImagePage, "REPLACE_WITH_IMAGE_URL", |
| + MakeAbsolute(kPrefetchJpeg)); |
| + PrefetchFromURL(main_page_url, FINAL_STATUS_NOSTATE_PREFETCH_FINISHED); |
| image_counter.WaitForCount(1); |
| } |
| @@ -405,17 +473,13 @@ IN_PROC_BROWSER_TEST_F(NoStatePrefetchBrowserTest, SSLSubresourceError) { |
| https_server.ServeFilesFromSourceDirectory("chrome/test/data"); |
| ASSERT_TRUE(https_server.Start()); |
| GURL https_url = https_server.GetURL("/prerender/image.jpeg"); |
| - base::StringPairs replacement_text; |
| - replacement_text.push_back( |
| - std::make_pair("REPLACE_WITH_IMAGE_URL", https_url.spec())); |
| - std::string main_page_path; |
| - net::test_server::GetFilePathWithReplacements( |
| - kPrefetchImagePage, replacement_text, &main_page_path); |
| + GURL main_page_url = GetURLWithReplacement( |
| + kPrefetchImagePage, "REPLACE_WITH_IMAGE_URL", https_url.spec()); |
| RequestCounter script_counter; |
| CountRequestFor(kPrefetchScript, &script_counter); |
| std::unique_ptr<TestPrerender> prerender = |
| - PrefetchFromFile(main_page_path, FINAL_STATUS_NOSTATE_PREFETCH_FINISHED); |
| + PrefetchFromURL(main_page_url, FINAL_STATUS_NOSTATE_PREFETCH_FINISHED); |
| // Checks that the presumed failure of the image load didn't affect the script |
| // fetch. This assumes waiting for the script load is enough to see any error |
| // from the image load. |
| @@ -603,4 +667,94 @@ IN_PROC_BROWSER_TEST_F(NoStatePrefetchBrowserTest, ServiceWorkerIntercept) { |
| image_counter.WaitForCount(1); |
| } |
| +// Checks that prefetching happens if an appcache is mentioned in the html tag |
| +// but is uninitialized. |
| +IN_PROC_BROWSER_TEST_F(NoStatePrefetchBrowserTest, AppCacheHtmlUninitialized) { |
| + RequestCounter image_counter; |
| + CountRequestFor(kPrefetchPng, &image_counter); |
| + PrefetchFromFile(kPrefetchAppcache, FINAL_STATUS_NOSTATE_PREFETCH_FINISHED); |
| + image_counter.WaitForCount(1); |
| +} |
| + |
| +// Checks that prefetching does not if an initialized appcache is mentioned in |
| +// the html tag. |
| +IN_PROC_BROWSER_TEST_F(NoStatePrefetchBrowserTest, AppCacheHtmlInitialized) { |
| + base::TimeTicks current_time = GetPrerenderManager()->GetCurrentTimeTicks(); |
| + auto* clock = OverridePrerenderManagerTimeTicks(); |
| + // Some navigations have already occurred in test setup. In order to track |
| + // duplicate prefetches correctly the test clock needs to be beyond those |
| + // navigations. |
| + clock->SetNowTicks(current_time); |
| + clock->Advance(base::TimeDelta::FromSeconds(600)); |
| + |
| + // Fill manifest with the image url. The main resource will be cached |
| + // implicitly. |
| + GURL image_url = src_server()->GetURL(MakeAbsolute(kPrefetchPng)); |
| + GURL manifest_url = GetURLWithReplacement( |
| + kPrefetchAppcacheManifest, "REPLACE_WITH_URL", image_url.spec()); |
| + GURL appcache_page_url = GetURLWithReplacement( |
| + kPrefetchAppcache, "REPLACE_WITH_MANIFEST", manifest_url.spec()); |
| + |
| + // Load the page into the appcache. |
| + ui_test_utils::NavigateToURL(current_browser(), appcache_page_url); |
| + |
| + WaitForAppcache(manifest_url); |
| + |
| + // If a page is prefetch shortly after being loading, the prefetch is |
| + // canceled. Advancing the clock prevents the cancelation. |
| + clock->Advance(base::TimeDelta::FromSeconds(6000)); |
| + |
| + RequestCounter script_counter; |
| + CountRequestFor(kPrefetchScript, &script_counter); |
| + // While the prefetch stops when it sees the AppCache manifest, from the point |
| + // of view of the prerender manager the prefetch stops normally. |
| + PrefetchFromURL(appcache_page_url, FINAL_STATUS_NOSTATE_PREFETCH_FINISHED); |
| + |
| + // The prefetch should have been canceled before the script in |
| + // kPrefetchAppcache is loaded (note the script is not mentioned in the |
| + // manifest). |
| + script_counter.WaitForCount(0); |
| +} |
| + |
| +// If a page has been cached by another AppCache, the prefetch should be |
| +// canceled. |
| +IN_PROC_BROWSER_TEST_F(NoStatePrefetchBrowserTest, AppCacheRegistered) { |
| + base::TimeTicks current_time = GetPrerenderManager()->GetCurrentTimeTicks(); |
| + auto* clock = OverridePrerenderManagerTimeTicks(); |
| + // Some navigations have already occurred in test setup. In order to track |
| + // duplicate prefetches correctly the test clock needs to be beyond those |
| + // navigations. |
| + clock->SetNowTicks(current_time); |
| + clock->Advance(base::TimeDelta::FromSeconds(600)); |
| + |
| + // Fill manifest with kPrefetchPage so that it is cached without explicitly |
| + // listing a manifest. |
| + GURL prefetch_page_url = src_server()->GetURL(MakeAbsolute(kPrefetchPage)); |
| + GURL manifest_url = GetURLWithReplacement( |
| + kPrefetchAppcacheManifest, "REPLACE_WITH_URL", prefetch_page_url.spec()); |
| + |
| + GURL appcache_page_url = GetURLWithReplacement( |
| + kPrefetchAppcache, "REPLACE_WITH_MANIFEST", manifest_url.spec()); |
| + |
| + // Load the page into the appcache. |
| + ui_test_utils::NavigateToURL(current_browser(), appcache_page_url); |
| + // Load the prefetch page so it can be cached. |
| + ui_test_utils::NavigateToURL(current_browser(), prefetch_page_url); |
| + |
| + WaitForAppcache(manifest_url); |
| + |
| + // If a page is prefetch shortly after being loading, the prefetch is |
| + // canceled. Advancing the clock prevents the cancelation. |
| + clock->Advance(base::TimeDelta::FromSeconds(6000)); |
| + |
| + RequestCounter page_counter; |
| + CountRequestFor(kPrefetchPage, &page_counter); |
| + RequestCounter script_counter; |
| + CountRequestFor(kPrefetchScript, &script_counter); |
| + PrefetchFromURL(prefetch_page_url, FINAL_STATUS_NOSTATE_PREFETCH_FINISHED); |
| + // Neither the page nor the script should be prefetched. |
| + script_counter.WaitForCount(0); |
| + page_counter.WaitForCount(0); |
| +} |
| + |
| } // namespace prerender |