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