OLD | NEW |
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "chrome/browser/prerender/prerender_link_manager.h" | 5 #include "chrome/browser/prerender/prerender_link_manager.h" |
6 | 6 |
7 #include <functional> | 7 #include <functional> |
8 #include <limits> | 8 #include <limits> |
9 #include <set> | 9 #include <set> |
| 10 #include <string> |
10 #include <utility> | 11 #include <utility> |
11 | 12 |
12 #include "base/memory/scoped_ptr.h" | 13 #include "base/memory/scoped_ptr.h" |
| 14 #include "base/metrics/field_trial.h" |
13 #include "chrome/browser/prerender/prerender_contents.h" | 15 #include "chrome/browser/prerender/prerender_contents.h" |
14 #include "chrome/browser/prerender/prerender_handle.h" | 16 #include "chrome/browser/prerender/prerender_handle.h" |
15 #include "chrome/browser/prerender/prerender_manager.h" | 17 #include "chrome/browser/prerender/prerender_manager.h" |
16 #include "chrome/browser/prerender/prerender_manager_factory.h" | 18 #include "chrome/browser/prerender/prerender_manager_factory.h" |
17 #include "chrome/browser/profiles/profile.h" | 19 #include "chrome/browser/profiles/profile.h" |
18 #include "chrome/common/prerender_messages.h" | 20 #include "chrome/common/prerender_messages.h" |
| 21 #include "chrome/common/prerender_types.h" |
19 #include "content/public/browser/render_process_host.h" | 22 #include "content/public/browser/render_process_host.h" |
20 #include "content/public/browser/render_view_host.h" | 23 #include "content/public/browser/render_view_host.h" |
21 #include "content/public/browser/session_storage_namespace.h" | 24 #include "content/public/browser/session_storage_namespace.h" |
22 #include "content/public/common/referrer.h" | 25 #include "content/public/common/referrer.h" |
23 #include "ui/gfx/size.h" | 26 #include "ui/gfx/size.h" |
24 #include "url/gurl.h" | 27 #include "url/gurl.h" |
25 | 28 |
26 using base::TimeDelta; | 29 using base::TimeDelta; |
27 using base::TimeTicks; | 30 using base::TimeTicks; |
28 using content::RenderViewHost; | 31 using content::RenderViewHost; |
29 using content::SessionStorageNamespace; | 32 using content::SessionStorageNamespace; |
30 | 33 |
| 34 namespace prerender { |
| 35 |
31 namespace { | 36 namespace { |
32 | 37 |
| 38 bool ShouldStartRelNextPrerenders() { |
| 39 const std::string experiment_name = |
| 40 base::FieldTrialList::FindFullName("PrerenderRelNextTrial"); |
| 41 |
| 42 return experiment_name.find("Yes") != std::string::npos; |
| 43 } |
| 44 |
| 45 bool ShouldStartPrerender(uint32 rel_types) { |
| 46 const bool should_start_rel_next_prerenders = |
| 47 ShouldStartRelNextPrerenders(); |
| 48 |
| 49 if (rel_types & PrerenderRelTypePrerender) { |
| 50 return true; |
| 51 } else if (should_start_rel_next_prerenders && |
| 52 (rel_types & PrerenderRelTypeNext) == PrerenderRelTypeNext) { |
| 53 return true; |
| 54 } |
| 55 return false; |
| 56 } |
| 57 |
33 void Send(int child_id, IPC::Message* raw_message) { | 58 void Send(int child_id, IPC::Message* raw_message) { |
34 using content::RenderProcessHost; | 59 using content::RenderProcessHost; |
35 scoped_ptr<IPC::Message> own_message(raw_message); | 60 scoped_ptr<IPC::Message> own_message(raw_message); |
36 | 61 |
37 RenderProcessHost* render_process_host = RenderProcessHost::FromID(child_id); | 62 RenderProcessHost* render_process_host = RenderProcessHost::FromID(child_id); |
38 if (!render_process_host) | 63 if (!render_process_host) |
39 return; | 64 return; |
40 render_process_host->Send(own_message.release()); | 65 render_process_host->Send(own_message.release()); |
41 } | 66 } |
42 | 67 |
43 } // namespace | 68 } // namespace |
44 | 69 |
45 namespace prerender { | |
46 | |
47 // Helper class to implement PrerenderContents::Observer and watch prerenders | 70 // Helper class to implement PrerenderContents::Observer and watch prerenders |
48 // which launch other prerenders. | 71 // which launch other prerenders. |
49 class PrerenderLinkManager::PendingPrerenderManager | 72 class PrerenderLinkManager::PendingPrerenderManager |
50 : public PrerenderContents::Observer { | 73 : public PrerenderContents::Observer { |
51 public: | 74 public: |
52 explicit PendingPrerenderManager(PrerenderLinkManager* link_manager) | 75 explicit PendingPrerenderManager(PrerenderLinkManager* link_manager) |
53 : link_manager_(link_manager) {} | 76 : link_manager_(link_manager) {} |
54 | 77 |
55 virtual ~PendingPrerenderManager() { | 78 virtual ~PendingPrerenderManager() { |
56 DCHECK(observed_launchers_.empty()); | 79 DCHECK(observed_launchers_.empty()); |
(...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
102 << "PrerenderManager."; | 125 << "PrerenderManager."; |
103 delete i->handle; | 126 delete i->handle; |
104 i->handle = 0; | 127 i->handle = 0; |
105 } | 128 } |
106 } | 129 } |
107 } | 130 } |
108 | 131 |
109 void PrerenderLinkManager::OnAddPrerender(int launcher_child_id, | 132 void PrerenderLinkManager::OnAddPrerender(int launcher_child_id, |
110 int prerender_id, | 133 int prerender_id, |
111 const GURL& url, | 134 const GURL& url, |
| 135 uint32 rel_types, |
112 const content::Referrer& referrer, | 136 const content::Referrer& referrer, |
113 const gfx::Size& size, | 137 const gfx::Size& size, |
114 int render_view_route_id) { | 138 int render_view_route_id) { |
115 DCHECK_EQ(static_cast<LinkPrerender*>(NULL), | 139 DCHECK_EQ(static_cast<LinkPrerender*>(NULL), |
116 FindByLauncherChildIdAndPrerenderId(launcher_child_id, | 140 FindByLauncherChildIdAndPrerenderId(launcher_child_id, |
117 prerender_id)); | 141 prerender_id)); |
118 content::RenderProcessHost* rph = | 142 content::RenderProcessHost* rph = |
119 content::RenderProcessHost::FromID(launcher_child_id); | 143 content::RenderProcessHost::FromID(launcher_child_id); |
120 // Guests inside <webview> do not support cross-process navigation and so we | 144 // Guests inside <webview> do not support cross-process navigation and so we |
121 // do not allow guests to prerender content. | 145 // do not allow guests to prerender content. |
122 if (rph && rph->IsGuest()) | 146 if (rph && rph->IsGuest()) |
123 return; | 147 return; |
124 | 148 |
125 // Check if the launcher is itself an unswapped prerender. | 149 // Check if the launcher is itself an unswapped prerender. |
126 PrerenderContents* prerender_contents = | 150 PrerenderContents* prerender_contents = |
127 manager_->GetPrerenderContentsForRoute(launcher_child_id, | 151 manager_->GetPrerenderContentsForRoute(launcher_child_id, |
128 render_view_route_id); | 152 render_view_route_id); |
129 if (prerender_contents && | 153 if (prerender_contents && |
130 prerender_contents->final_status() != FINAL_STATUS_MAX) { | 154 prerender_contents->final_status() != FINAL_STATUS_MAX) { |
131 // The launcher is a prerender about to be destroyed asynchronously, but | 155 // The launcher is a prerender about to be destroyed asynchronously, but |
132 // its AddLinkRelPrerender message raced with shutdown. Ignore it. | 156 // its AddLinkRelPrerender message raced with shutdown. Ignore it. |
133 DCHECK_NE(FINAL_STATUS_USED, prerender_contents->final_status()); | 157 DCHECK_NE(FINAL_STATUS_USED, prerender_contents->final_status()); |
134 return; | 158 return; |
135 } | 159 } |
136 | 160 |
137 LinkPrerender | 161 LinkPrerender |
138 prerender(launcher_child_id, prerender_id, url, referrer, size, | 162 prerender(launcher_child_id, prerender_id, url, rel_types, referrer, size, |
139 render_view_route_id, manager_->GetCurrentTimeTicks(), | 163 render_view_route_id, manager_->GetCurrentTimeTicks(), |
140 prerender_contents); | 164 prerender_contents); |
141 prerenders_.push_back(prerender); | 165 prerenders_.push_back(prerender); |
142 if (prerender_contents) | 166 if (prerender_contents) |
143 pending_prerender_manager_->ObserveLauncher(prerender_contents); | 167 pending_prerender_manager_->ObserveLauncher(prerender_contents); |
144 else | 168 else |
145 StartPrerenders(); | 169 StartPrerenders(); |
146 } | 170 } |
147 | 171 |
148 void PrerenderLinkManager::OnCancelPrerender(int child_id, int prerender_id) { | 172 void PrerenderLinkManager::OnCancelPrerender(int child_id, int prerender_id) { |
(...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
189 const size_t running_prerender_count = CountRunningPrerenders(); | 213 const size_t running_prerender_count = CountRunningPrerenders(); |
190 OnAbandonPrerender(child_id, it->prerender_id); | 214 OnAbandonPrerender(child_id, it->prerender_id); |
191 DCHECK_EQ(running_prerender_count, CountRunningPrerenders()); | 215 DCHECK_EQ(running_prerender_count, CountRunningPrerenders()); |
192 } | 216 } |
193 } | 217 } |
194 | 218 |
195 PrerenderLinkManager::LinkPrerender::LinkPrerender( | 219 PrerenderLinkManager::LinkPrerender::LinkPrerender( |
196 int launcher_child_id, | 220 int launcher_child_id, |
197 int prerender_id, | 221 int prerender_id, |
198 const GURL& url, | 222 const GURL& url, |
| 223 uint32 rel_types, |
199 const content::Referrer& referrer, | 224 const content::Referrer& referrer, |
200 const gfx::Size& size, | 225 const gfx::Size& size, |
201 int render_view_route_id, | 226 int render_view_route_id, |
202 TimeTicks creation_time, | 227 TimeTicks creation_time, |
203 PrerenderContents* deferred_launcher) | 228 PrerenderContents* deferred_launcher) |
204 : launcher_child_id(launcher_child_id), | 229 : launcher_child_id(launcher_child_id), |
205 prerender_id(prerender_id), | 230 prerender_id(prerender_id), |
206 url(url), | 231 url(url), |
| 232 rel_types(rel_types), |
207 referrer(referrer), | 233 referrer(referrer), |
208 size(size), | 234 size(size), |
209 render_view_route_id(render_view_route_id), | 235 render_view_route_id(render_view_route_id), |
210 creation_time(creation_time), | 236 creation_time(creation_time), |
211 deferred_launcher(deferred_launcher), | 237 deferred_launcher(deferred_launcher), |
212 handle(NULL), | 238 handle(NULL), |
213 is_match_complete_replacement(false), | 239 is_match_complete_replacement(false), |
214 has_been_abandoned(false) { | 240 has_been_abandoned(false) { |
215 } | 241 } |
216 | 242 |
(...skipping 90 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
307 // an abandoned prerender to make room? | 333 // an abandoned prerender to make room? |
308 if (!abandoned_prerenders.empty()) { | 334 if (!abandoned_prerenders.empty()) { |
309 CancelPrerender(abandoned_prerenders.front()); | 335 CancelPrerender(abandoned_prerenders.front()); |
310 --total_started_prerender_count; | 336 --total_started_prerender_count; |
311 abandoned_prerenders.pop_front(); | 337 abandoned_prerenders.pop_front(); |
312 } else { | 338 } else { |
313 return; | 339 return; |
314 } | 340 } |
315 } | 341 } |
316 | 342 |
| 343 if (!ShouldStartPrerender((*i)->rel_types)) { |
| 344 prerenders_.erase(*i); |
| 345 continue; |
| 346 } |
| 347 |
317 PrerenderHandle* handle = manager_->AddPrerenderFromLinkRelPrerender( | 348 PrerenderHandle* handle = manager_->AddPrerenderFromLinkRelPrerender( |
318 (*i)->launcher_child_id, (*i)->render_view_route_id, | 349 (*i)->launcher_child_id, (*i)->render_view_route_id, |
319 (*i)->url, (*i)->referrer, (*i)->size); | 350 (*i)->url, (*i)->referrer, (*i)->size); |
320 if (!handle) { | 351 if (!handle) { |
321 // This prerender couldn't be launched, it's gone. | 352 // This prerender couldn't be launched, it's gone. |
322 prerenders_.erase(*i); | 353 prerenders_.erase(*i); |
323 continue; | 354 continue; |
324 } | 355 } |
325 | 356 |
326 // We have successfully started a new prerender. | 357 // We have successfully started a new prerender. |
(...skipping 137 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
464 DCHECK(!prerender->is_match_complete_replacement); | 495 DCHECK(!prerender->is_match_complete_replacement); |
465 prerender->is_match_complete_replacement = true; | 496 prerender->is_match_complete_replacement = true; |
466 Send(prerender->launcher_child_id, | 497 Send(prerender->launcher_child_id, |
467 new PrerenderMsg_OnPrerenderStop(prerender->prerender_id)); | 498 new PrerenderMsg_OnPrerenderStop(prerender->prerender_id)); |
468 // Do not call RemovePrerender here. The replacement needs to stay connected | 499 // Do not call RemovePrerender here. The replacement needs to stay connected |
469 // to the HTMLLinkElement in the renderer so it notices renderer-triggered | 500 // to the HTMLLinkElement in the renderer so it notices renderer-triggered |
470 // cancelations. | 501 // cancelations. |
471 } | 502 } |
472 | 503 |
473 } // namespace prerender | 504 } // namespace prerender |
OLD | NEW |