15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Copyright (c) 2012 The Chromium Authors. All rights reserved.
25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be
35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// found in the LICENSE file.
45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
55821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <deque>
62a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include <vector>
75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
84e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)#include "base/bind.h"
95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/command_line.h"
104e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)#include "base/files/file_path.h"
118bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)#include "base/memory/ref_counted_memory.h"
125d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "base/memory/scoped_vector.h"
135d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "base/memory/weak_ptr.h"
145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/path_service.h"
152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "base/prefs/pref_service.h"
164e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)#include "base/run_loop.h"
17868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "base/strings/string_util.h"
18868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "base/strings/stringprintf.h"
19868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "base/strings/utf_string_conversions.h"
2003b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)#include "base/test/histogram_tester.h"
215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/test/test_timeouts.h"
225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/values.h"
235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/browsing_data/browsing_data_helper.h"
245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/browsing_data/browsing_data_remover.h"
255c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu#include "chrome/browser/browsing_data/browsing_data_remover_test_util.h"
2668043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)#include "chrome/browser/chrome_content_browser_client.h"
277dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch#include "chrome/browser/chrome_notification_types.h"
285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/content_settings/host_content_settings_map.h"
295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/extensions/api/web_navigation/web_navigation_api.h"
305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/extensions/extension_apitest.h"
315d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "chrome/browser/external_protocol/external_protocol_handler.h"
325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/favicon/favicon_tab_helper.h"
331320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci#include "chrome/browser/net/prediction_options.h"
345c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu#include "chrome/browser/predictors/autocomplete_action_predictor.h"
355c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu#include "chrome/browser/predictors/autocomplete_action_predictor_factory.h"
365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/prerender/prerender_contents.h"
371320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci#include "chrome/browser/prerender/prerender_field_trial.h"
385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/prerender/prerender_handle.h"
395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/prerender/prerender_link_manager.h"
405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/prerender/prerender_link_manager_factory.h"
415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/prerender/prerender_manager.h"
425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/prerender/prerender_manager_factory.h"
435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/profiles/profile.h"
445d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "chrome/browser/profiles/profile_io_data.h"
455d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "chrome/browser/renderer_host/chrome_resource_dispatcher_host_delegate.h"
462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "chrome/browser/safe_browsing/database_manager.h"
475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/safe_browsing/safe_browsing_service.h"
482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "chrome/browser/safe_browsing/safe_browsing_util.h"
495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/task_manager/task_manager.h"
505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/task_manager/task_manager_browsertest_util.h"
515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/ui/browser.h"
525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/ui/browser_commands.h"
535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/ui/browser_finder.h"
548bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)#include "chrome/browser/ui/browser_navigator.h"
555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/ui/browser_window.h"
56116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch#include "chrome/browser/ui/location_bar/location_bar.h"
575c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu#include "chrome/browser/ui/omnibox/omnibox_edit_model.h"
585c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu#include "chrome/browser/ui/omnibox/omnibox_popup_model.h"
595c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu#include "chrome/browser/ui/omnibox/omnibox_view.h"
605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/ui/tabs/tab_strip_model.h"
615d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "chrome/browser/ui/tabs/tab_strip_model_observer.h"
625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/common/chrome_paths.h"
635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/common/chrome_switches.h"
644e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)#include "chrome/common/extensions/extension_constants.h"
65010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)#include "chrome/common/extensions/manifest_handlers/mime_types_handler.h"
665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/common/pref_names.h"
6703b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)#include "chrome/grit/generated_resources.h"
685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/test/base/in_process_browser_test.h"
69a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)#include "chrome/test/base/test_switches.h"
705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/test/base/ui_test_utils.h"
711320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci#include "components/variations/entropy_provider.h"
721320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci#include "components/variations/variations_associated_data.h"
735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "content/public/browser/browser_message_filter.h"
742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "content/public/browser/devtools_agent_host.h"
755d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "content/public/browser/navigation_controller.h"
765d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "content/public/browser/navigation_entry.h"
775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "content/public/browser/notification_service.h"
78a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)#include "content/public/browser/render_frame_host.h"
795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "content/public/browser/render_process_host.h"
805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "content/public/browser/render_view_host.h"
8168043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)#include "content/public/browser/site_instance.h"
825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "content/public/browser/web_contents.h"
835d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "content/public/browser/web_contents_observer.h"
845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "content/public/common/url_constants.h"
855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "content/public/test/browser_test_utils.h"
865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "content/public/test/test_navigation_observer.h"
875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "content/public/test/test_utils.h"
881320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci#include "extensions/common/extension_urls.h"
89ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch#include "extensions/common/switches.h"
901320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci#include "extensions/test/result_catcher.h"
914e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)#include "net/base/escape.h"
925d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "net/cert/x509_certificate.h"
932a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "net/dns/mock_host_resolver.h"
945d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "net/ssl/client_cert_store.h"
955d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "net/ssl/ssl_cert_request_info.h"
961320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci#include "net/test/url_request/url_request_mock_http_job.h"
975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "net/url_request/url_request_context.h"
985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "net/url_request/url_request_context_getter.h"
99868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "net/url_request/url_request_filter.h"
10046d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)#include "net/url_request/url_request_interceptor.h"
101868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "net/url_request/url_request_job.h"
1025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ui/base/l10n/l10n_util.h"
103eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch#include "url/gurl.h"
1045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1051320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucciusing chrome_browser_net::NetworkPredictionOptions;
1065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)using content::BrowserThread;
1075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)using content::DevToolsAgentHost;
1085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)using content::NavigationController;
1095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)using content::OpenURLParams;
1105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)using content::Referrer;
111a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)using content::RenderFrameHost;
1125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)using content::RenderViewHost;
1135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)using content::RenderWidgetHost;
1145d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)using content::TestNavigationObserver;
1155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)using content::WebContents;
1165d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)using content::WebContentsObserver;
1171320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucciusing net::NetworkChangeNotifier;
118a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)using task_manager::browsertest_util::WaitForTaskManagerRows;
1195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Prerender tests work as follows:
1215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//
1225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// A page with a prefetch link to the test page is loaded.  Once prerendered,
1235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// its Javascript function DidPrerenderPass() is called, which returns true if
1245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// the page behaves as expected when prerendered.
1255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//
1265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// The prerendered page is then displayed on a tab.  The Javascript function
1275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// DidDisplayPass() is called, and returns true if the page behaved as it
1285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// should while being displayed.
1295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace prerender {
1315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace {
1335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1341320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucciclass MockNetworkChangeNotifierWIFI : public NetworkChangeNotifier {
1351320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci public:
1361320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  virtual ConnectionType GetCurrentConnectionType() const OVERRIDE {
1371320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    return NetworkChangeNotifier::CONNECTION_WIFI;
1381320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  }
1391320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci};
1401320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
1411320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucciclass MockNetworkChangeNotifier4G : public NetworkChangeNotifier {
1421320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci public:
1431320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  virtual ConnectionType GetCurrentConnectionType() const OVERRIDE {
1441320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    return NetworkChangeNotifier::CONNECTION_4G;
1451320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  }
1461320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci};
1471320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
1485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Constants used in the test HTML files.
1495d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)const char* kReadyTitle = "READY";
1505d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)const char* kPassTitle = "PASS";
1515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)std::string CreateClientRedirect(const std::string& dest_url) {
1535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const char* const kClientRedirectBase = "client-redirect?";
1544e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  return kClientRedirectBase + net::EscapeQueryParamValue(dest_url, false);
1555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)std::string CreateServerRedirect(const std::string& dest_url) {
1585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const char* const kServerRedirectBase = "server-redirect?";
1594e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  return kServerRedirectBase + net::EscapeQueryParamValue(dest_url, false);
1605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Clears the specified data using BrowsingDataRemover.
1635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void ClearBrowsingData(Browser* browser, int remove_mask) {
1645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  BrowsingDataRemover* remover =
1655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      BrowsingDataRemover::CreateForUnboundedRange(browser->profile());
1665c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  BrowsingDataRemoverCompletionObserver observer(remover);
1675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  remover->Remove(remove_mask, BrowsingDataHelper::UNPROTECTED_WEB);
1685c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  observer.BlockUntilCompletion();
1695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // BrowsingDataRemover deletes itself.
1705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1725d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// Returns true if the prerender is expected to abort on its own, before
1735d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// attempting to swap it.
1745d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)bool ShouldAbortPrerenderBeforeSwap(FinalStatus status) {
1755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  switch (status) {
1765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case FINAL_STATUS_USED:
1775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case FINAL_STATUS_WINDOW_OPENER:
1785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case FINAL_STATUS_APP_TERMINATING:
1790529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch    case FINAL_STATUS_PROFILE_DESTROYED:
1805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case FINAL_STATUS_CACHE_OR_HISTORY_CLEARED:
1815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // We'll crash the renderer after it's loaded.
1825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case FINAL_STATUS_RENDERER_CRASHED:
1835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case FINAL_STATUS_CANCELLED:
1845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case FINAL_STATUS_DEVTOOLS_ATTACHED:
185ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch    case FINAL_STATUS_PAGE_BEING_CAPTURED:
1864e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    case FINAL_STATUS_NAVIGATION_UNCOMMITTED:
1875d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    case FINAL_STATUS_WOULD_HAVE_BEEN_USED:
188cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    case FINAL_STATUS_NON_EMPTY_BROWSING_INSTANCE:
1895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return false;
1905d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    default:
1915d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      return true;
1925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1955d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// Convenience function to wait for a title. Handles the case when the
1965d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// WebContents already has the expected title.
1975d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)void WaitForASCIITitle(WebContents* web_contents,
1985d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                       const char* expected_title_ascii) {
1995d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  base::string16 expected_title = base::ASCIIToUTF16(expected_title_ascii);
2005d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  if (web_contents->GetTitle() == expected_title)
2015d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    return;
2025d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  content::TitleWatcher title_watcher(web_contents, expected_title);
2035d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  EXPECT_EQ(expected_title, title_watcher.WaitAndGetTitle());
2045d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}
2055d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
2065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Waits for the destruction of a RenderProcessHost's IPC channel.
2075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Used to make sure the PrerenderLinkManager's OnChannelClosed function has
2085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// been called, before checking its state.
2095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class ChannelDestructionWatcher {
2105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public:
2114e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  ChannelDestructionWatcher() : channel_destroyed_(false) {
2125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ~ChannelDestructionWatcher() {
2155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void WatchChannel(content::RenderProcessHost* host) {
2184e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    host->AddFilter(new DestructionMessageFilter(this));
2195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void WaitForChannelClose() {
2224e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    run_loop_.Run();
2235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    EXPECT_TRUE(channel_destroyed_);
2245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) private:
2275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // When destroyed, calls ChannelDestructionWatcher::OnChannelDestroyed.
2285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Ignores all messages.
2295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  class DestructionMessageFilter : public content::BrowserMessageFilter {
2305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   public:
2315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)     explicit DestructionMessageFilter(ChannelDestructionWatcher* watcher)
2325d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)         : BrowserMessageFilter(0),
2335d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)           watcher_(watcher) {
2345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
2355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   private:
2375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    virtual ~DestructionMessageFilter() {
2385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      content::BrowserThread::PostTask(
2395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          content::BrowserThread::UI, FROM_HERE,
2405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          base::Bind(&ChannelDestructionWatcher::OnChannelDestroyed,
2415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                     base::Unretained(watcher_)));
2425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
2435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
244cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    virtual bool OnMessageReceived(const IPC::Message& message) OVERRIDE {
2455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return false;
2465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
2475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ChannelDestructionWatcher* watcher_;
2495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    DISALLOW_COPY_AND_ASSIGN(DestructionMessageFilter);
2515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  };
2525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void OnChannelDestroyed() {
2545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
2555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    EXPECT_FALSE(channel_destroyed_);
2575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    channel_destroyed_ = true;
2584e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    run_loop_.Quit();
2595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool channel_destroyed_;
2624e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  base::RunLoop run_loop_;
2635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DISALLOW_COPY_AND_ASSIGN(ChannelDestructionWatcher);
2655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
2665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2675d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// A navigation observer to wait on either a new load or a swap of a
2685d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// WebContents. On swap, if the new WebContents is still loading, wait for that
2695d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// load to complete as well. Note that the load must begin after the observer is
2705d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// attached.
2715d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)class NavigationOrSwapObserver : public WebContentsObserver,
2725d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                                 public TabStripModelObserver {
2735d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) public:
2745d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // Waits for either a new load or a swap of |tab_strip_model|'s active
2755d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // WebContents.
2765d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  NavigationOrSwapObserver(TabStripModel* tab_strip_model,
2775d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                           WebContents* web_contents)
2785d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      : WebContentsObserver(web_contents),
2795d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        tab_strip_model_(tab_strip_model),
2805d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        did_start_loading_(false),
2815d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        number_of_loads_(1) {
2825d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    CHECK_NE(TabStripModel::kNoTab,
2835d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)             tab_strip_model->GetIndexOfWebContents(web_contents));
2845d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    tab_strip_model_->AddObserver(this);
2855d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  }
2865d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
2875d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // Waits for either |number_of_loads| loads or a swap of |tab_strip_model|'s
2885d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // active WebContents.
2895d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  NavigationOrSwapObserver(TabStripModel* tab_strip_model,
2905d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                           WebContents* web_contents,
2915d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                           int number_of_loads)
2925d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      : WebContentsObserver(web_contents),
2935d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        tab_strip_model_(tab_strip_model),
2945d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        did_start_loading_(false),
2955d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        number_of_loads_(number_of_loads) {
2965d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    CHECK_NE(TabStripModel::kNoTab,
2975d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)             tab_strip_model->GetIndexOfWebContents(web_contents));
2985d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    tab_strip_model_->AddObserver(this);
2995d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  }
3005d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
3015d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  virtual ~NavigationOrSwapObserver() {
3025d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    tab_strip_model_->RemoveObserver(this);
3035d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  }
3045d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
3050529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  void set_did_start_loading() {
3060529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch    did_start_loading_ = true;
3070529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  }
3080529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch
3095d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  void Wait() {
3105d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    loop_.Run();
3115d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  }
3125d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
3135d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // WebContentsObserver implementation:
3145d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  virtual void DidStartLoading(RenderViewHost* render_view_host) OVERRIDE {
3155d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    did_start_loading_ = true;
3165d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  }
3175d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  virtual void DidStopLoading(RenderViewHost* render_view_host) OVERRIDE {
3185d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    if (!did_start_loading_)
3195d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      return;
3205d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    number_of_loads_--;
3215d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    if (number_of_loads_ == 0)
3225d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      loop_.Quit();
3235d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  }
3245d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
3255d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // TabStripModelObserver implementation:
3265d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  virtual void TabReplacedAt(TabStripModel* tab_strip_model,
3275d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                             WebContents* old_contents,
3285d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                             WebContents* new_contents,
3295d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                             int index) OVERRIDE {
3305d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    if (old_contents != web_contents())
3315d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      return;
3325d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    // Switch to observing the new WebContents.
3335d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    Observe(new_contents);
3345d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    if (new_contents->IsLoading()) {
3355d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      // If the new WebContents is still loading, wait for it to complete. Only
3365d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      // one load post-swap is supported.
3375d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      did_start_loading_ = true;
3385d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      number_of_loads_ = 1;
3395d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    } else {
3405d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      loop_.Quit();
3415d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    }
3425d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  }
3435d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
3445d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) private:
3455d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  TabStripModel* tab_strip_model_;
3465d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  bool did_start_loading_;
3475d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  int number_of_loads_;
3485d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  base::RunLoop loop_;
3495d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)};
3505d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
3515d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// Waits for a new tab to open and a navigation or swap in it.
3525d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)class NewTabNavigationOrSwapObserver {
3535d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) public:
3545d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  NewTabNavigationOrSwapObserver()
3555d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      : new_tab_observer_(
3565d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)            chrome::NOTIFICATION_TAB_ADDED,
3575d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)            base::Bind(&NewTabNavigationOrSwapObserver::OnTabAdded,
3585d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                       base::Unretained(this))) {
3595d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    // Watch for NOTIFICATION_TAB_ADDED. Add a callback so that the
3605d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    // NavigationOrSwapObserver can be attached synchronously and no events are
3615d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    // missed.
3625d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  }
3635d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
3645d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  void Wait() {
3655d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    new_tab_observer_.Wait();
3665d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    swap_observer_->Wait();
3675d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  }
3685d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
3695d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  bool OnTabAdded(const content::NotificationSource& source,
3705d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                  const content::NotificationDetails& details) {
3715d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    if (swap_observer_)
3725d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      return true;
3735d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    WebContents* new_tab = content::Details<WebContents>(details).ptr();
3745d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    // Get the TabStripModel. Assume this is attached to a Browser.
3755d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    TabStripModel* tab_strip_model =
3765d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        static_cast<Browser*>(new_tab->GetDelegate())->tab_strip_model();
3775d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    swap_observer_.reset(new NavigationOrSwapObserver(tab_strip_model,
3785d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                                                      new_tab));
3790529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch    swap_observer_->set_did_start_loading();
3805d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    return true;
3815d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  }
3825d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
3835d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) private:
3845d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  content::WindowedNotificationObserver new_tab_observer_;
3855d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  scoped_ptr<NavigationOrSwapObserver> swap_observer_;
3865d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)};
3875d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
3885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// PrerenderContents that stops the UI message loop on DidStopLoading().
3895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class TestPrerenderContents : public PrerenderContents {
3905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public:
3915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  TestPrerenderContents(
3925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      PrerenderManager* prerender_manager,
3935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      Profile* profile,
3945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      const GURL& url,
3955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      const content::Referrer& referrer,
3965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      Origin origin,
3975d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      FinalStatus expected_final_status)
3982a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      : PrerenderContents(prerender_manager, profile, url,
3995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                          referrer, origin, PrerenderManager::kNoExperiment),
4005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        expected_final_status_(expected_final_status),
4015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        new_render_view_host_(NULL),
4025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        was_hidden_(false),
4035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        was_shown_(false),
4045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        should_be_shown_(expected_final_status == FINAL_STATUS_USED),
4055d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        skip_final_checks_(false) {
4065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
4075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual ~TestPrerenderContents() {
4095d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    if (skip_final_checks_)
4105d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      return;
4115d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
4125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (expected_final_status_ == FINAL_STATUS_MAX) {
4135d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      EXPECT_EQ(MATCH_COMPLETE_REPLACEMENT, match_complete_status());
4145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    } else {
4155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      EXPECT_EQ(expected_final_status_, final_status()) <<
4165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          " when testing URL " << prerender_url().path() <<
4175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          " (Expected: " << NameFromFinalStatus(expected_final_status_) <<
4185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          ", Actual: " << NameFromFinalStatus(final_status()) << ")";
4195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
4205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Prerendering RenderViewHosts should be hidden before the first
4215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // navigation, so this should be happen for every PrerenderContents for
4225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // which a RenderViewHost is created, regardless of whether or not it's
4235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // used.
4245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (new_render_view_host_)
4255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      EXPECT_TRUE(was_hidden_);
4265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // A used PrerenderContents will only be destroyed when we swap out
4285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // WebContents, at the end of a navigation caused by a call to
4295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // NavigateToURLImpl().
4305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (final_status() == FINAL_STATUS_USED)
4315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      EXPECT_TRUE(new_render_view_host_);
4325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    EXPECT_EQ(should_be_shown_, was_shown_);
4345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
4355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4367dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  virtual void RenderProcessGone(base::TerminationStatus status) OVERRIDE {
4375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // On quit, it's possible to end up here when render processes are closed
4385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // before the PrerenderManager is destroyed.  As a result, it's possible to
4395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // get either FINAL_STATUS_APP_TERMINATING or FINAL_STATUS_RENDERER_CRASHED
4405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // on quit.
4415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    //
4425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // It's also possible for this to be called after we've been notified of
4435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // app termination, but before we've been deleted, which is why the second
4445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // check is needed.
4455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (expected_final_status_ == FINAL_STATUS_APP_TERMINATING &&
4465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        final_status() != expected_final_status_) {
4475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      expected_final_status_ = FINAL_STATUS_RENDERER_CRASHED;
4485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
4495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4507dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    PrerenderContents::RenderProcessGone(status);
4515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
4525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4530f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)  virtual bool CheckURL(const GURL& url) OVERRIDE {
4545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Prevent FINAL_STATUS_UNSUPPORTED_SCHEME when navigating to about:crash in
4555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // the PrerenderRendererCrash test.
4562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    if (url.spec() != content::kChromeUICrashURL)
4570f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)      return PrerenderContents::CheckURL(url);
4585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return true;
4595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
4605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // For tests that open the prerender in a new background tab, the RenderView
4625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // will not have been made visible when the PrerenderContents is destroyed
4635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // even though it is used.
4645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void set_should_be_shown(bool value) { should_be_shown_ = value; }
4655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4665d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // For tests which do not know whether the prerender will be used.
4675d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  void set_skip_final_checks(bool value) { skip_final_checks_ = value; }
4685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  FinalStatus expected_final_status() const { return expected_final_status_; }
4705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) private:
4725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual void OnRenderViewHostCreated(
4735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      RenderViewHost* new_render_view_host) OVERRIDE {
4745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Used to make sure the RenderViewHost is hidden and, if used,
4755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // subsequently shown.
4765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    notification_registrar().Add(
4775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        this,
4785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        content::NOTIFICATION_RENDER_WIDGET_VISIBILITY_CHANGED,
4795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        content::Source<RenderWidgetHost>(new_render_view_host));
4805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    new_render_view_host_ = new_render_view_host;
4825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    PrerenderContents::OnRenderViewHostCreated(new_render_view_host);
4845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
4855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual void Observe(int type,
4875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                       const content::NotificationSource& source,
4885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                       const content::NotificationDetails& details) OVERRIDE {
4895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (type ==
4905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        content::NOTIFICATION_RENDER_WIDGET_VISIBILITY_CHANGED) {
4915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      EXPECT_EQ(new_render_view_host_,
4925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                content::Source<RenderWidgetHost>(source).ptr());
4935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      bool is_visible = *content::Details<bool>(details).ptr();
4945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (!is_visible) {
4965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        was_hidden_ = true;
4975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      } else if (is_visible && was_hidden_) {
4985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        // Once hidden, a prerendered RenderViewHost should only be shown after
4995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        // being removed from the PrerenderContents for display.
5005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        EXPECT_FALSE(GetRenderViewHost());
5015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        was_shown_ = true;
5025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
5035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return;
5045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
5055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    PrerenderContents::Observe(type, source, details);
5065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
5075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  FinalStatus expected_final_status_;
5095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // The RenderViewHost created for the prerender, if any.
5115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  RenderViewHost* new_render_view_host_;
5125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Set to true when the prerendering RenderWidget is hidden.
5135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool was_hidden_;
5145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Set to true when the prerendering RenderWidget is shown, after having been
5155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // hidden.
5165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool was_shown_;
5175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Expected final value of was_shown_.  Defaults to true for
5185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // FINAL_STATUS_USED, and false otherwise.
5195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool should_be_shown_;
5205d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // If true, |expected_final_status_| and other shutdown checks are skipped.
5215d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  bool skip_final_checks_;
5225d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)};
5235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5245d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// A handle to a TestPrerenderContents whose lifetime is under the caller's
5255d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// control. A PrerenderContents may be destroyed at any point. This allows
5265d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// tracking the final status, etc.
5275d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)class TestPrerender : public PrerenderContents::Observer,
5285d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                      public base::SupportsWeakPtr<TestPrerender> {
5295d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) public:
5305d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  TestPrerender()
5315d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      : contents_(NULL),
5325d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        number_of_loads_(0),
5335d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        expected_number_of_loads_(0) {
5345d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  }
5355d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  virtual ~TestPrerender() {
5365d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    if (contents_)
5375d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      contents_->RemoveObserver(this);
5385d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  }
5395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5405d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  TestPrerenderContents* contents() const { return contents_; }
5415d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  int number_of_loads() const { return number_of_loads_; }
5425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5435d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  void WaitForCreate() { create_loop_.Run(); }
5445d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  void WaitForStart() { start_loop_.Run(); }
5455d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  void WaitForStop() { stop_loop_.Run(); }
5465d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
5475d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // Waits for |number_of_loads()| to be at least |expected_number_of_loads| OR
5485d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // for the prerender to stop running (just to avoid a timeout if the prerender
5495d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // dies). Note: this does not assert equality on the number of loads; the
5505d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // caller must do it instead.
5515d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  void WaitForLoads(int expected_number_of_loads) {
5525d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    DCHECK(!load_waiter_);
5535d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    DCHECK(!expected_number_of_loads_);
5545d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    if (number_of_loads_ < expected_number_of_loads) {
5555d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      load_waiter_.reset(new base::RunLoop);
5565d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      expected_number_of_loads_ = expected_number_of_loads;
5575d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      load_waiter_->Run();
5585d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      load_waiter_.reset();
5595d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      expected_number_of_loads_ = 0;
5605d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    }
5615d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    EXPECT_LE(expected_number_of_loads, number_of_loads_);
5625d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  }
5635d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
5645d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  void OnPrerenderCreated(TestPrerenderContents* contents) {
5655d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    DCHECK(!contents_);
5665d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    contents_ = contents;
5675d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    contents_->AddObserver(this);
5685d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    create_loop_.Quit();
5695d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  }
5705d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
5715d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // PrerenderContents::Observer implementation:
5725d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  virtual void OnPrerenderStart(PrerenderContents* contents) OVERRIDE {
5735d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    start_loop_.Quit();
5745d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  }
5755d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
5765d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  virtual void OnPrerenderStopLoading(PrerenderContents* contents) OVERRIDE {
5775d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    number_of_loads_++;
5785d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    if (load_waiter_ && number_of_loads_ >= expected_number_of_loads_)
5795d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      load_waiter_->Quit();
5805d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  }
5815d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
5825d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  virtual void OnPrerenderStop(PrerenderContents* contents) OVERRIDE {
5835d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    DCHECK(contents_);
5845d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    contents_ = NULL;
5855d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    stop_loop_.Quit();
5865d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    // If there is a WaitForLoads call and it has yet to see the expected number
5875d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    // of loads, stop the loop so the test fails instead of timing out.
5885d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    if (load_waiter_)
5895d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      load_waiter_->Quit();
5905d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  }
5915d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
5925d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  virtual void OnPrerenderCreatedMatchCompleteReplacement(
5935d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      PrerenderContents* contents, PrerenderContents* replacement) OVERRIDE {
5945d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  }
5955d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
5965d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) private:
5975d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  TestPrerenderContents* contents_;
5985d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  int number_of_loads_;
5995d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
6005d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  int expected_number_of_loads_;
6015d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  scoped_ptr<base::RunLoop> load_waiter_;
6025d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
6035d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  base::RunLoop create_loop_;
6045d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  base::RunLoop start_loop_;
6055d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  base::RunLoop stop_loop_;
6065d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
6075d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  DISALLOW_COPY_AND_ASSIGN(TestPrerender);
6085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
6095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// PrerenderManager that uses TestPrerenderContents.
6115d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)class TestPrerenderContentsFactory : public PrerenderContents::Factory {
6125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public:
6135d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  TestPrerenderContentsFactory() {}
6145d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
6155d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  virtual ~TestPrerenderContentsFactory() {
6165d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    EXPECT_TRUE(expected_contents_queue_.empty());
6175d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  }
6185d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
6195d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  scoped_ptr<TestPrerender> ExpectPrerenderContents(FinalStatus final_status) {
6205d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    scoped_ptr<TestPrerender> handle(new TestPrerender());
6215d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    expected_contents_queue_.push_back(
6225d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        ExpectedContents(final_status, handle->AsWeakPtr()));
6235d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    return handle.Pass();
6245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
6255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual PrerenderContents* CreatePrerenderContents(
6275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      PrerenderManager* prerender_manager,
6285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      Profile* profile,
6295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      const GURL& url,
6305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      const content::Referrer& referrer,
6315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      Origin origin,
6325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      uint8 experiment_id) OVERRIDE {
6335d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    ExpectedContents expected;
6345d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    if (!expected_contents_queue_.empty()) {
6355d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      expected = expected_contents_queue_.front();
6365d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      expected_contents_queue_.pop_front();
6375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
6385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    VLOG(1) << "Creating prerender contents for " << url.path() <<
6395d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)               " with expected final status " << expected.final_status;
6405d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    VLOG(1) << expected_contents_queue_.size() << " left in the queue.";
6415d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    TestPrerenderContents* contents =
6425d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        new TestPrerenderContents(prerender_manager,
6435d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                                  profile, url, referrer, origin,
6445d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                                  expected.final_status);
6455d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    if (expected.handle)
6465d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      expected.handle->OnPrerenderCreated(contents);
6475d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    return contents;
6485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
6495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) private:
6515d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  struct ExpectedContents {
6525d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    ExpectedContents() : final_status(FINAL_STATUS_MAX) { }
6535d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    ExpectedContents(FinalStatus final_status,
6545d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                     const base::WeakPtr<TestPrerender>& handle)
6555d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        : final_status(final_status),
6565d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)          handle(handle) {
6575d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    }
6585d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
6595d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    FinalStatus final_status;
6605d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    base::WeakPtr<TestPrerender> handle;
6615d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  };
6625d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
6635d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  std::deque<ExpectedContents> expected_contents_queue_;
6645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
6655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#if defined(FULL_SAFE_BROWSING)
6672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// A SafeBrowsingDatabaseManager implementation that returns a fixed result for
6682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// a given URL.
6692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)class FakeSafeBrowsingDatabaseManager :  public SafeBrowsingDatabaseManager {
6705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public:
6712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  explicit FakeSafeBrowsingDatabaseManager(SafeBrowsingService* service)
6722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      : SafeBrowsingDatabaseManager(service),
6732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        threat_type_(SB_THREAT_TYPE_SAFE) { }
6745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Called on the IO thread to check if the given url is safe or not.  If we
6765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // can synchronously determine that the url is safe, CheckUrl returns true.
6775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Otherwise it returns false, and "client" is called asynchronously with the
6785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // result when it is ready.
6795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Returns true, indicating a SAFE result, unless the URL is the fixed URL
6805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // specified by the user, and the user-specified result is not SAFE
6815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // (in which that result will be communicated back via a call into the
6825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // client, and false will be returned).
6835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Overrides SafeBrowsingService::CheckBrowseUrl.
6845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual bool CheckBrowseUrl(const GURL& gurl, Client* client) OVERRIDE {
6855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (gurl != url_ || threat_type_ == SB_THREAT_TYPE_SAFE)
6865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return true;
6875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    BrowserThread::PostTask(
6895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        BrowserThread::IO, FROM_HERE,
6902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        base::Bind(&FakeSafeBrowsingDatabaseManager::OnCheckBrowseURLDone,
6912a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                   this, gurl, client));
6925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
6935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
6945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void SetThreatTypeForUrl(const GURL& url, SBThreatType threat_type) {
6965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    url_ = url;
6975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    threat_type_ = threat_type;
6985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
6995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) private:
7012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  virtual ~FakeSafeBrowsingDatabaseManager() {}
7025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void OnCheckBrowseURLDone(const GURL& gurl, Client* client) {
70458537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)    std::vector<SBThreatType> expected_threats;
70558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)    expected_threats.push_back(SB_THREAT_TYPE_URL_MALWARE);
70658537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)    expected_threats.push_back(SB_THREAT_TYPE_URL_PHISHING);
7072a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    SafeBrowsingDatabaseManager::SafeBrowsingCheck sb_check(
7082a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        std::vector<GURL>(1, gurl),
7092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        std::vector<SBFullHash>(),
7102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        client,
71158537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)        safe_browsing_util::MALWARE,
71258537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)        expected_threats);
7132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    sb_check.url_results[0] = threat_type_;
7142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    client->OnSafeBrowsingResult(sb_check);
7155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
7165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  GURL url_;
7185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  SBThreatType threat_type_;
7192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  DISALLOW_COPY_AND_ASSIGN(FakeSafeBrowsingDatabaseManager);
7202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)};
7212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
7222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)class FakeSafeBrowsingService : public SafeBrowsingService {
7232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) public:
7242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  FakeSafeBrowsingService() { }
7252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
7262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Returned pointer has the same lifespan as the database_manager_ refcounted
7272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // object.
7282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  FakeSafeBrowsingDatabaseManager* fake_database_manager() {
7292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return fake_database_manager_;
7302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
7312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
7322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) protected:
7332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  virtual ~FakeSafeBrowsingService() { }
7342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
7352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  virtual SafeBrowsingDatabaseManager* CreateDatabaseManager() OVERRIDE {
7362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    fake_database_manager_ = new FakeSafeBrowsingDatabaseManager(this);
7372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return fake_database_manager_;
7382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
7392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
7402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) private:
7412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  FakeSafeBrowsingDatabaseManager* fake_database_manager_;
7422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
7432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  DISALLOW_COPY_AND_ASSIGN(FakeSafeBrowsingService);
7445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
7455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Factory that creates FakeSafeBrowsingService instances.
7475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class TestSafeBrowsingServiceFactory : public SafeBrowsingServiceFactory {
7485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public:
7495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  TestSafeBrowsingServiceFactory() :
7505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      most_recent_service_(NULL) { }
7515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual ~TestSafeBrowsingServiceFactory() { }
7525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual SafeBrowsingService* CreateSafeBrowsingService() OVERRIDE {
7545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    most_recent_service_ =  new FakeSafeBrowsingService();
7555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return most_recent_service_;
7565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
7575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  FakeSafeBrowsingService* most_recent_service() const {
7595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return most_recent_service_;
7605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
7615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) private:
7635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  FakeSafeBrowsingService* most_recent_service_;
7645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
7655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
7665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
76703b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)class FakeDevToolsClient : public content::DevToolsAgentHostClient {
7685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public:
76903b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  FakeDevToolsClient() {}
77003b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  virtual ~FakeDevToolsClient() {}
77103b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  virtual void DispatchProtocolMessage(
77203b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)      DevToolsAgentHost* agent_host, const std::string& message) OVERRIDE {}
77303b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  virtual void AgentHostClosed(
77403b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)      DevToolsAgentHost* agent_host, bool replaced) OVERRIDE {}
7755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
7765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class RestorePrerenderMode {
7785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public:
7795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  RestorePrerenderMode() : prev_mode_(PrerenderManager::GetMode()) {
7805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
7815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ~RestorePrerenderMode() { PrerenderManager::SetMode(prev_mode_); }
7835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) private:
7845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  PrerenderManager::PrerenderManagerMode prev_mode_;
7855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
7865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7875d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// URLRequestJob (and associated handler) which hangs.
7885d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)class HangingURLRequestJob : public net::URLRequestJob {
789868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) public:
7905d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  HangingURLRequestJob(net::URLRequest* request,
791868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                          net::NetworkDelegate* network_delegate)
792868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      : net::URLRequestJob(request, network_delegate) {
793868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  }
794868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
795868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  virtual void Start() OVERRIDE {}
796868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
797868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) private:
7985d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  virtual ~HangingURLRequestJob() {}
799868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)};
800868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
80146d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)class HangingFirstRequestInterceptor : public net::URLRequestInterceptor {
802868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) public:
80346d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  HangingFirstRequestInterceptor(const base::FilePath& file,
80446d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)                                 base::Closure callback)
8055d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      : file_(file),
8065d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        callback_(callback),
8075d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        first_run_(true) {
8085d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  }
80946d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  virtual ~HangingFirstRequestInterceptor() {}
810868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
81146d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  virtual net::URLRequestJob* MaybeInterceptRequest(
812868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      net::URLRequest* request,
813868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      net::NetworkDelegate* network_delegate) const OVERRIDE {
8145d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    if (first_run_) {
8155d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      first_run_ = false;
816a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      if (!callback_.is_null()) {
817a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)        BrowserThread::PostTask(
818a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)            BrowserThread::UI, FROM_HERE, callback_);
819a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      }
8205d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      return new HangingURLRequestJob(request, network_delegate);
8215d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    }
8221320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    return new net::URLRequestMockHTTPJob(
8231320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci        request,
8241320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci        network_delegate,
8251320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci        file_,
8261320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci        BrowserThread::GetBlockingPool()->GetTaskRunnerWithShutdownBehavior(
8271320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci            base::SequencedWorkerPool::SKIP_ON_SHUTDOWN));
828868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  }
8295d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
8305d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) private:
8315d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  base::FilePath file_;
8325d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  base::Closure callback_;
8335d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  mutable bool first_run_;
834868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)};
835868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
8365d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// Makes |url| never respond on the first load, and then with the contents of
8375d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// |file| afterwards. When the first load has been scheduled, runs |callback| on
8385d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// the UI thread.
83946d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)void CreateHangingFirstRequestInterceptorOnIO(
84046d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    const GURL& url, const base::FilePath& file, base::Closure callback) {
841868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  CHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
84246d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  scoped_ptr<net::URLRequestInterceptor> never_respond_handler(
84346d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)      new HangingFirstRequestInterceptor(file, callback));
84446d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  net::URLRequestFilter::GetInstance()->AddUrlInterceptor(
845868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      url, never_respond_handler.Pass());
846868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)}
847868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
8485d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// Wrapper over URLRequestMockHTTPJob that exposes extra callbacks.
8491320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucciclass MockHTTPJob : public net::URLRequestMockHTTPJob {
8505d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) public:
8515d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  MockHTTPJob(net::URLRequest* request,
8525d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)              net::NetworkDelegate* delegate,
8535d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)              const base::FilePath& file)
8541320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      : net::URLRequestMockHTTPJob(
8551320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci            request,
8561320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci            delegate,
8571320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci            file,
8581320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci            BrowserThread::GetBlockingPool()->GetTaskRunnerWithShutdownBehavior(
8591320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci                base::SequencedWorkerPool::SKIP_ON_SHUTDOWN)) {}
8605d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
8615d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  void set_start_callback(const base::Closure& start_callback) {
8625d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    start_callback_ = start_callback;
8635d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  }
8645d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
8655d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  virtual void Start() OVERRIDE {
8665d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    if (!start_callback_.is_null())
8675d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      start_callback_.Run();
8681320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    net::URLRequestMockHTTPJob::Start();
8695d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  }
8705d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
8715d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) private:
8725d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  virtual ~MockHTTPJob() {}
8735d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
8745d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  base::Closure start_callback_;
8755d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)};
8765d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
8775d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// Dummy counter class to live on the UI thread for counting requests.
8785d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)class RequestCounter : public base::SupportsWeakPtr<RequestCounter> {
8795d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) public:
8805d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  RequestCounter() : count_(0), expected_count_(-1) {}
8815d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  int count() const { return count_; }
8825d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
8835d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  void RequestStarted() {
8845d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    count_++;
8855d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    if (loop_ && count_ == expected_count_)
8865d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      loop_->Quit();
8875d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  }
8885d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
8895d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  void WaitForCount(int expected_count) {
8905d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    ASSERT_TRUE(!loop_);
8915d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    ASSERT_EQ(-1, expected_count_);
8925d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    if (count_ < expected_count) {
8935d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      expected_count_ = expected_count;
8945d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      loop_.reset(new base::RunLoop);
8955d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      loop_->Run();
8965d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      expected_count_ = -1;
8975d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      loop_.reset();
8985d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    }
8995d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
9005d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    EXPECT_EQ(expected_count, count_);
9015d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  }
9025d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) private:
9035d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  int count_;
9045d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  int expected_count_;
9055d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  scoped_ptr<base::RunLoop> loop_;
9065d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)};
9075d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
9085d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// Protocol handler which counts the number of requests that start.
90946d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)class CountingInterceptor : public net::URLRequestInterceptor {
9105d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) public:
91146d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  CountingInterceptor(const base::FilePath& file,
91246d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)                      const base::WeakPtr<RequestCounter>& counter)
9135d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      : file_(file),
9145d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        counter_(counter),
9155d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        weak_factory_(this) {
9165d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  }
91746d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  virtual ~CountingInterceptor() {}
9185d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
91946d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  virtual net::URLRequestJob* MaybeInterceptRequest(
9205d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      net::URLRequest* request,
9215d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      net::NetworkDelegate* network_delegate) const OVERRIDE {
9225d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    MockHTTPJob* job = new MockHTTPJob(request, network_delegate, file_);
92346d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    job->set_start_callback(base::Bind(&CountingInterceptor::RequestStarted,
9245d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                                       weak_factory_.GetWeakPtr()));
9255d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    return job;
9265d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  }
9275d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
9285d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  void RequestStarted() {
9295d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    BrowserThread::PostTask(
9305d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        BrowserThread::UI, FROM_HERE,
9315d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        base::Bind(&RequestCounter::RequestStarted, counter_));
9325d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  }
9335d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
9345d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) private:
9355d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  base::FilePath file_;
9365d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  base::WeakPtr<RequestCounter> counter_;
93746d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  mutable base::WeakPtrFactory<CountingInterceptor> weak_factory_;
9385d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)};
9395d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
9405d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// Makes |url| respond to requests with the contents of |file|, counting the
9415d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// number that start in |counter|.
94246d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)void CreateCountingInterceptorOnIO(
9435d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    const GURL& url,
9445d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    const base::FilePath& file,
9455d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    const base::WeakPtr<RequestCounter>& counter) {
9465d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  CHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
94746d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  scoped_ptr<net::URLRequestInterceptor> request_interceptor(
94846d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)      new CountingInterceptor(file, counter));
94946d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  net::URLRequestFilter::GetInstance()->AddUrlInterceptor(
95046d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)      url, request_interceptor.Pass());
9515d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}
9525d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
9534e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)// Makes |url| respond to requests with the contents of |file|.
95446d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)void CreateMockInterceptorOnIO(const GURL& url, const base::FilePath& file) {
9554e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  CHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
95646d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  net::URLRequestFilter::GetInstance()->AddUrlInterceptor(
95746d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)      url,
9581320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      net::URLRequestMockHTTPJob::CreateInterceptorForSingleFile(
9591320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci          file, BrowserThread::GetBlockingPool()));
9604e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)}
9614e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
96268043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)// A ContentBrowserClient that cancels all prerenderers on OpenURL.
963