Upstream version 10.39.225.0
[platform/framework/web/crosswalk.git] / src / chrome / browser / prerender / prerender_unittest.cc
index 810d0f3..545308b 100644 (file)
@@ -2,18 +2,26 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
+#include <map>
+#include <utility>
+
 #include "base/command_line.h"
 #include "base/format_macros.h"
 #include "base/memory/scoped_vector.h"
 #include "base/message_loop/message_loop.h"
+#include "base/metrics/field_trial.h"
+#include "base/prefs/pref_service.h"
 #include "base/strings/stringprintf.h"
 #include "base/time/time.h"
+#include "chrome/browser/net/prediction_options.h"
 #include "chrome/browser/prerender/prerender_contents.h"
 #include "chrome/browser/prerender/prerender_handle.h"
 #include "chrome/browser/prerender/prerender_link_manager.h"
 #include "chrome/browser/prerender/prerender_manager.h"
 #include "chrome/browser/prerender/prerender_origin.h"
 #include "chrome/common/chrome_switches.h"
+#include "chrome/common/pref_names.h"
+#include "chrome/common/prerender_types.h"
 #include "chrome/test/base/testing_browser_process.h"
 #include "chrome/test/base/testing_profile.h"
 #include "content/public/browser/render_view_host.h"
@@ -42,14 +50,13 @@ class DummyPrerenderContents : public PrerenderContents {
                          Origin origin,
                          FinalStatus expected_final_status);
 
-  virtual ~DummyPrerenderContents() {
-    EXPECT_EQ(expected_final_status_, final_status());
-  }
+  virtual ~DummyPrerenderContents();
 
   virtual void StartPrerendering(
       int ALLOW_UNUSED creator_child_id,
       const gfx::Size& ALLOW_UNUSED size,
-      content::SessionStorageNamespace* ALLOW_UNUSED session_storage_namespace)
+      content::SessionStorageNamespace* ALLOW_UNUSED session_storage_namespace,
+      net::URLRequestContextGetter* ALLOW_UNUSED request_context)
       OVERRIDE;
 
   virtual bool GetChildId(int* child_id) const OVERRIDE {
@@ -82,6 +89,8 @@ int DummyPrerenderContents::g_next_route_id_ = 0;
 
 const gfx::Size kSize(640, 480);
 
+const uint32 kDefaultRelTypes = PrerenderRelTypePrerender;
+
 }  // namespace
 
 class UnitTestPrerenderManager : public PrerenderManager {
@@ -96,12 +105,13 @@ class UnitTestPrerenderManager : public PrerenderManager {
         time_ticks_(TimeTicks::Now()),
         prerender_tracker_(prerender_tracker) {
     set_rate_limit_enabled(false);
+    OnCookieStoreLoaded();
   }
 
   virtual ~UnitTestPrerenderManager() {
   }
 
-  // From BrowserContextKeyedService, via PrererenderManager:
+  // From KeyedService, via PrererenderManager:
   virtual void Shutdown() OVERRIDE {
     if (next_prerender_contents())
       next_prerender_contents_->Destroy(FINAL_STATUS_MANAGER_SHUTDOWN);
@@ -134,7 +144,6 @@ class UnitTestPrerenderManager : public PrerenderManager {
     PrerenderContents* prerender_contents = prerender_data->ReleaseContents();
     active_prerenders_.erase(to_erase);
 
-    prerender_contents->SetFinalStatus(FINAL_STATUS_USED);
     prerender_contents->PrepareForUse();
     return prerender_contents;
   }
@@ -203,6 +212,33 @@ class UnitTestPrerenderManager : public PrerenderManager {
     return time_ticks_;
   }
 
+  virtual PrerenderContents* GetPrerenderContentsForRoute(
+      int child_id, int route_id) const OVERRIDE {
+    // Overridden for the PrerenderLinkManager's pending prerender logic.
+    PrerenderContentsMap::const_iterator iter = prerender_contents_map_.find(
+        std::make_pair(child_id, route_id));
+    if (iter == prerender_contents_map_.end())
+      return NULL;
+    return iter->second;
+  }
+
+  void DummyPrerenderContentsStarted(int child_id,
+                                     int route_id,
+                                     PrerenderContents* prerender_contents) {
+    prerender_contents_map_[std::make_pair(child_id, route_id)] =
+        prerender_contents;
+  }
+
+  void DummyPrerenderContentsDestroyed(int child_id,
+                                       int route_id) {
+    prerender_contents_map_.erase(std::make_pair(child_id, route_id));
+  }
+
+ protected:
+  virtual net::URLRequestContextGetter* GetURLRequestContext() OVERRIDE {
+    return NULL;
+  }
+
  private:
   void SetNextPrerenderContents(DummyPrerenderContents* prerender_contents) {
     CHECK(!next_prerender_contents_.get());
@@ -223,6 +259,11 @@ class UnitTestPrerenderManager : public PrerenderManager {
     return next_prerender_contents_.release();
   }
 
+  // Maintain a map from route pairs to PrerenderContents for
+  // GetPrerenderContentsForRoute.
+  typedef std::map<std::pair<int,int>, PrerenderContents*> PrerenderContentsMap;
+  PrerenderContentsMap prerender_contents_map_;
+
   Time time_;
   TimeTicks time_ticks_;
   scoped_ptr<PrerenderContents> next_prerender_contents_;
@@ -257,10 +298,16 @@ DummyPrerenderContents::DummyPrerenderContents(
       expected_final_status_(expected_final_status) {
 }
 
+DummyPrerenderContents::~DummyPrerenderContents() {
+  EXPECT_EQ(expected_final_status_, final_status());
+  test_prerender_manager_->DummyPrerenderContentsDestroyed(-1, route_id_);
+}
+
 void DummyPrerenderContents::StartPrerendering(
     int ALLOW_UNUSED creator_child_id,
     const gfx::Size& ALLOW_UNUSED size,
-    content::SessionStorageNamespace* ALLOW_UNUSED session_storage_namespace) {
+    content::SessionStorageNamespace* ALLOW_UNUSED session_storage_namespace,
+    net::URLRequestContextGetter* ALLOW_UNUSED request_context) {
   // In the base PrerenderContents implementation, StartPrerendering will
   // be called even when the PrerenderManager is part of the control group,
   // but it will early exit before actually creating a new RenderView if
@@ -268,6 +315,7 @@ void DummyPrerenderContents::StartPrerendering(
   load_start_time_ = test_prerender_manager_->GetCurrentTimeTicks();
   if (!test_prerender_manager_->IsControlGroup(experiment_id())) {
     prerendering_has_started_ = true;
+    test_prerender_manager_->DummyPrerenderContentsStarted(-1, route_id_, this);
     NotifyPrerenderStart();
   }
 }
@@ -282,7 +330,8 @@ class PrerenderTest : public testing::Test {
                         &profile_, prerender_tracker())),
                     prerender_link_manager_(
                         new PrerenderLinkManager(prerender_manager_.get())),
-                    last_prerender_id_(0) {
+                    last_prerender_id_(0),
+                    field_trial_list_(NULL) {
     // Enable omnibox prerendering.
     CommandLine::ForCurrentProcess()->AppendSwitchASCII(
         switches::kPrerenderFromOmnibox,
@@ -330,17 +379,29 @@ class PrerenderTest : public testing::Test {
     return prerender && prerender->handle;
   }
 
+  bool LauncherHasScheduledPrerender(int child_id, int prerender_id) {
+    PrerenderLinkManager::LinkPrerender* prerender =
+        prerender_link_manager()->FindByLauncherChildIdAndPrerenderId(
+            child_id, prerender_id);
+    return prerender != NULL;
+  }
+
   // Shorthand to add a simple prerender with a reasonable source. Returns
   // true iff the prerender has been added to the PrerenderManager by the
   // PrerenderLinkManager and the PrerenderManager returned a handle.
   bool AddSimplePrerender(const GURL& url) {
-    prerender_link_manager()->OnAddPrerender(kDefaultChildId,
-                                             GetNextPrerenderID(),
-                                             url, content::Referrer(),
-                                             kSize, kDefaultRenderViewRouteId);
+    prerender_link_manager()->OnAddPrerender(
+        kDefaultChildId, GetNextPrerenderID(), url, kDefaultRelTypes,
+        content::Referrer(), kSize, kDefaultRenderViewRouteId);
     return LauncherHasRunningPrerender(kDefaultChildId, last_prerender_id());
   }
 
+  void DisablePrerender() {
+    profile_.GetPrefs()->SetInteger(
+        prefs::kNetworkPredictionOptions,
+        chrome_browser_net::NETWORK_PREDICTION_NEVER);
+  }
+
  private:
   PrerenderTracker* prerender_tracker() {
     return g_browser_process->prerender_tracker();
@@ -353,6 +414,7 @@ class PrerenderTest : public testing::Test {
   scoped_ptr<UnitTestPrerenderManager> prerender_manager_;
   scoped_ptr<PrerenderLinkManager> prerender_link_manager_;
   int last_prerender_id_;
+  base::FieldTrialList field_trial_list_;
 };
 
 TEST_F(PrerenderTest, FoundTest) {
@@ -584,21 +646,16 @@ TEST_F(PrerenderTest, MaxConcurrencyTest) {
     if (concurrencies_to_test[i].max_link_concurrency >
             effective_max_link_concurrency) {
       // We should be able to launch more prerenders on this system, but not for
-      // our current launcher.
-      int child_id;
-      int route_id;
-      ASSERT_TRUE(prerender_contentses.back()->GetChildId(&child_id));
-      ASSERT_TRUE(prerender_contentses.back()->GetRouteId(&route_id));
-
+      // the default launcher.
       GURL extra_url("http://google.com/extraurl");
-      prerender_link_manager()->OnAddPrerender(child_id,
-                                               GetNextPrerenderID(),
-                                               extra_url, content::Referrer(),
-                                               kSize, route_id);
+      EXPECT_FALSE(AddSimplePrerender(extra_url));
       const int prerender_id = last_prerender_id();
-      EXPECT_TRUE(LauncherHasRunningPrerender(child_id, prerender_id));
-      prerender_link_manager()->OnCancelPrerender(child_id, prerender_id);
-      EXPECT_FALSE(LauncherHasRunningPrerender(child_id, prerender_id));
+      EXPECT_TRUE(LauncherHasScheduledPrerender(kDefaultChildId,
+                                                prerender_id));
+      prerender_link_manager()->OnCancelPrerender(kDefaultChildId,
+                                                  prerender_id);
+      EXPECT_FALSE(LauncherHasScheduledPrerender(kDefaultChildId,
+                                                 prerender_id));
     }
 
     DummyPrerenderContents* prerender_contents_to_delay =
@@ -674,25 +731,28 @@ TEST_F(PrerenderTest, PendingPrerenderTest) {
 
   GURL pending_url("http://news.google.com/");
 
+  // Schedule a pending prerender launched from the prerender.
   DummyPrerenderContents* pending_prerender_contents =
       prerender_manager()->CreateNextPrerenderContents(
           pending_url,
           ORIGIN_GWS_PRERENDER,
           FINAL_STATUS_USED);
-  scoped_ptr<PrerenderHandle> pending_prerender_handle(
-      prerender_manager()->AddPrerenderFromLinkRelPrerender(
-          child_id, route_id, pending_url,
-          Referrer(url, WebKit::WebReferrerPolicyDefault), kSize));
-  CHECK(pending_prerender_handle.get());
-  EXPECT_FALSE(pending_prerender_handle->IsPrerendering());
-
+  prerender_link_manager()->OnAddPrerender(
+      child_id, GetNextPrerenderID(), pending_url, kDefaultRelTypes,
+      Referrer(url, blink::WebReferrerPolicyDefault),
+      kSize, route_id);
+  EXPECT_FALSE(LauncherHasRunningPrerender(child_id, last_prerender_id()));
+  EXPECT_FALSE(pending_prerender_contents->prerendering_has_started());
+
+  // Use the referring prerender.
   EXPECT_TRUE(prerender_contents->prerendering_has_started());
   ASSERT_EQ(prerender_contents, prerender_manager()->FindAndUseEntry(url));
 
-  EXPECT_TRUE(pending_prerender_handle->IsPrerendering());
+  // The pending prerender should start now.
+  EXPECT_TRUE(LauncherHasRunningPrerender(child_id, last_prerender_id()));
+  EXPECT_TRUE(pending_prerender_contents->prerendering_has_started());
   ASSERT_EQ(pending_prerender_contents,
             prerender_manager()->FindAndUseEntry(pending_url));
-  EXPECT_FALSE(pending_prerender_handle->IsPrerendering());
 }
 
 TEST_F(PrerenderTest, InvalidPendingPrerenderTest) {
@@ -712,21 +772,26 @@ TEST_F(PrerenderTest, InvalidPendingPrerenderTest) {
   // to start.
   GURL pending_url("ftp://news.google.com/");
 
-  prerender_manager()->CreateNextPrerenderContents(
-      pending_url,
-      ORIGIN_GWS_PRERENDER,
-      FINAL_STATUS_UNSUPPORTED_SCHEME);
-  scoped_ptr<PrerenderHandle> pending_prerender_handle(
-      prerender_manager()->AddPrerenderFromLinkRelPrerender(
-          child_id, route_id, pending_url,
-          Referrer(url, WebKit::WebReferrerPolicyDefault), kSize));
-  DCHECK(pending_prerender_handle.get());
-  EXPECT_FALSE(pending_prerender_handle->IsPrerendering());
-
+  // Schedule a pending prerender launched from the prerender.
+  DummyPrerenderContents* pending_prerender_contents =
+      prerender_manager()->CreateNextPrerenderContents(
+          pending_url,
+          ORIGIN_GWS_PRERENDER,
+          FINAL_STATUS_UNSUPPORTED_SCHEME);
+  prerender_link_manager()->OnAddPrerender(
+      child_id, GetNextPrerenderID(), pending_url, kDefaultRelTypes,
+      Referrer(url, blink::WebReferrerPolicyDefault),
+      kSize, route_id);
+  EXPECT_FALSE(LauncherHasRunningPrerender(child_id, last_prerender_id()));
+  EXPECT_FALSE(pending_prerender_contents->prerendering_has_started());
+
+  // Use the referring prerender.
   EXPECT_TRUE(prerender_contents->prerendering_has_started());
   ASSERT_EQ(prerender_contents, prerender_manager()->FindAndUseEntry(url));
 
-  EXPECT_FALSE(pending_prerender_handle->IsPrerendering());
+  // The pending prerender still doesn't start.
+  EXPECT_FALSE(LauncherHasRunningPrerender(child_id, last_prerender_id()));
+  EXPECT_FALSE(pending_prerender_contents->prerendering_has_started());
 }
 
 TEST_F(PrerenderTest, CancelPendingPrerenderTest) {
@@ -744,18 +809,22 @@ TEST_F(PrerenderTest, CancelPendingPrerenderTest) {
 
   GURL pending_url("http://news.google.com/");
 
-  scoped_ptr<PrerenderHandle> pending_prerender_handle(
-      prerender_manager()->AddPrerenderFromLinkRelPrerender(
-          child_id, route_id, pending_url,
-          Referrer(url, WebKit::WebReferrerPolicyDefault), kSize));
-  CHECK(pending_prerender_handle.get());
-  EXPECT_FALSE(pending_prerender_handle->IsPrerendering());
-
-  EXPECT_TRUE(prerender_contents->prerendering_has_started());
+  // Schedule a pending prerender launched from the prerender.
+  prerender_link_manager()->OnAddPrerender(
+      child_id, GetNextPrerenderID(), pending_url, kDefaultRelTypes,
+      Referrer(url, blink::WebReferrerPolicyDefault),
+      kSize, route_id);
+  EXPECT_FALSE(LauncherHasRunningPrerender(child_id, last_prerender_id()));
 
-  pending_prerender_handle.reset();
+  // Cancel the pending prerender.
+  prerender_link_manager()->OnCancelPrerender(child_id, last_prerender_id());
 
+  // Use the referring prerender.
+  EXPECT_TRUE(prerender_contents->prerendering_has_started());
   ASSERT_EQ(prerender_contents, prerender_manager()->FindAndUseEntry(url));
+
+  // The pending prerender doesn't start.
+  EXPECT_FALSE(LauncherHasRunningPrerender(child_id, last_prerender_id()));
 }
 
 // Tests that a PrerenderManager created for a browser session in the control
@@ -781,11 +850,40 @@ TEST_F(PrerenderTest, SourceRenderViewClosed) {
   prerender_manager()->CreateNextPrerenderContents(
       url,
       FINAL_STATUS_MANAGER_SHUTDOWN);
-  prerender_link_manager()->OnAddPrerender(100, GetNextPrerenderID(), url,
-                                           Referrer(), kSize, 200);
+  prerender_link_manager()->OnAddPrerender(
+      100, GetNextPrerenderID(), url, kDefaultRelTypes, Referrer(), kSize, 200);
   EXPECT_FALSE(LauncherHasRunningPrerender(100, last_prerender_id()));
 }
 
+// Tests that prerendering doesn't launch rel=next prerenders without the field
+// trial.
+TEST_F(PrerenderTest, NoRelNextByDefault) {
+  GURL url("http://www.google.com/");
+  prerender_manager()->CreateNextPrerenderContents(
+      url, FINAL_STATUS_MANAGER_SHUTDOWN);
+  DummyPrerenderContents* null = NULL;
+
+  prerender_link_manager()->OnAddPrerender(
+      kDefaultChildId, GetNextPrerenderID(), url, PrerenderRelTypeNext,
+      Referrer(), kSize, kDefaultRenderViewRouteId);
+  EXPECT_EQ(null, prerender_manager()->FindEntry(url));
+}
+
+// Tests that prerendering does launch rel=next prerenders with the field trial.
+TEST_F(PrerenderTest, RelNextByFieldTrial) {
+  ASSERT_TRUE(base::FieldTrialList::CreateFieldTrial("PrerenderRelNextTrial",
+                                                     "Yes"));
+  GURL url("http://www.google.com/");
+  DummyPrerenderContents* prerender_contents =
+      prerender_manager()->CreateNextPrerenderContents(
+          url, ORIGIN_LINK_REL_NEXT, FINAL_STATUS_USED);
+
+  prerender_link_manager()->OnAddPrerender(
+      kDefaultChildId, GetNextPrerenderID(), url, PrerenderRelTypeNext,
+      Referrer(), kSize, kDefaultRenderViewRouteId);
+  EXPECT_EQ(prerender_contents, prerender_manager()->FindAndUseEntry(url));
+}
+
 // Tests that prerendering is cancelled when we launch a second prerender of
 // the same target within a short time interval.
 TEST_F(PrerenderTest, RecentlyVisited) {
@@ -818,6 +916,10 @@ TEST_F(PrerenderTest, NotSoRecentlyVisited) {
 
 // Tests that our PPLT dummy prerender gets created properly.
 TEST_F(PrerenderTest, PPLTDummy) {
+  RestorePrerenderMode restore_prerender_mode;
+  PrerenderManager::SetMode(
+      PrerenderManager::PRERENDER_MODE_EXPERIMENT_MATCH_COMPLETE_GROUP);
+
   GURL url("http://www.google.com/");
   DummyPrerenderContents* prerender_contents =
       prerender_manager()->CreateNextPrerenderContents(
@@ -841,6 +943,10 @@ TEST_F(PrerenderTest, PPLTDummy) {
 // Tests that our PPLT dummy prerender gets created properly, even
 // when navigating to a page that has been recently navigated to.
 TEST_F(PrerenderTest, RecentlyVisitedPPLTDummy) {
+  RestorePrerenderMode restore_prerender_mode;
+  PrerenderManager::SetMode(
+      PrerenderManager::PRERENDER_MODE_EXPERIMENT_MATCH_COMPLETE_GROUP);
+
   GURL url("http://www.google.com/");
   DummyPrerenderContents* prerender_contents =
       prerender_manager()->CreateNextPrerenderContents(
@@ -859,6 +965,10 @@ TEST_F(PrerenderTest, RecentlyVisitedPPLTDummy) {
 }
 
 TEST_F(PrerenderTest, PPLTLateCancel) {
+  RestorePrerenderMode restore_prerender_mode;
+  PrerenderManager::SetMode(
+      PrerenderManager::PRERENDER_MODE_EXPERIMENT_MATCH_COMPLETE_GROUP);
+
   GURL url("http://www.google.com");
   DummyPrerenderContents* prerender_contents =
       prerender_manager()->CreateNextPrerenderContents(
@@ -941,13 +1051,13 @@ TEST_F(PrerenderTest, CancelAllTest) {
 }
 
 TEST_F(PrerenderTest, OmniboxNotAllowedWhenDisabled) {
-  prerender_manager()->set_enabled(false);
+  DisablePrerender();
   EXPECT_FALSE(prerender_manager()->AddPrerenderFromOmnibox(
       GURL("http://www.example.com"), NULL, gfx::Size()));
 }
 
 TEST_F(PrerenderTest, LinkRelNotAllowedWhenDisabled) {
-  prerender_manager()->set_enabled(false);
+  DisablePrerender();
   EXPECT_FALSE(AddSimplePrerender(
       GURL("http://www.example.com")));
 }
@@ -1341,10 +1451,9 @@ TEST_F(PrerenderTest, LinkManagerClearOnPendingAbandon) {
   ASSERT_TRUE(prerender_contents->GetRouteId(&route_id));
 
   GURL pending_url("http://www.neverlaunched.com");
-  prerender_link_manager()->OnAddPrerender(child_id,
-                                           GetNextPrerenderID(),
-                                           pending_url, content::Referrer(),
-                                           kSize, route_id);
+  prerender_link_manager()->OnAddPrerender(
+      child_id, GetNextPrerenderID(), pending_url, kDefaultRelTypes,
+      content::Referrer(), kSize, route_id);
   const int second_prerender_id = last_prerender_id();
 
   EXPECT_FALSE(IsEmptyPrerenderLinkManager());
@@ -1452,4 +1561,32 @@ TEST_F(PrerenderTest, LinkManagerExpireRevealingLaunch) {
             prerender_manager()->FindAndUseEntry(second_url));
 }
 
+TEST_F(PrerenderTest, InstantSearchNotAllowedWhenDisabled) {
+  ASSERT_TRUE(base::FieldTrialList::CreateFieldTrial(
+      "EmbeddedSearch",
+      "Group82 espv:8 use_cacheable_ntp:1 prefetch_results:1"));
+  DisablePrerender();
+  EXPECT_FALSE(prerender_manager()->AddPrerenderForInstant(
+      GURL("http://www.example.com/instant_search"), NULL, gfx::Size()));
+}
+
+TEST_F(PrerenderTest, PrerenderContentsForInstantSearch) {
+  ASSERT_TRUE(base::FieldTrialList::CreateFieldTrial(
+      "EmbeddedSearch",
+      "Group82 espv:8 use_cacheable_ntp:1 prefetch_results:1"));
+  GURL url("http://www.example.com/instant_search");
+  DummyPrerenderContents* prerender_contents =
+      prerender_manager()->CreateNextPrerenderContents(url, ORIGIN_INSTANT,
+                                                       FINAL_STATUS_USED);
+  scoped_ptr<PrerenderHandle> prerender_handle(
+      prerender_manager()->AddPrerenderForInstant(url, NULL, kSize));
+  CHECK(prerender_handle.get());
+  EXPECT_TRUE(prerender_handle->IsPrerendering());
+  EXPECT_TRUE(prerender_contents->prerendering_has_started());
+  EXPECT_EQ(prerender_contents, prerender_handle->contents());
+  EXPECT_EQ(ORIGIN_INSTANT, prerender_handle->contents()->origin());
+  ASSERT_EQ(prerender_contents, prerender_manager()->FindAndUseEntry(url));
+  EXPECT_FALSE(prerender_handle->IsPrerendering());
+}
+
 }  // namespace prerender