Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(1907)

Side by Side Diff: chrome/browser/prerender/prerender_contents.cc

Issue 9416031: Prerendered pages are swapped in at browser::Navigate time. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Limit to origin process Created 8 years, 9 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
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_contents.h" 5 #include "chrome/browser/prerender/prerender_contents.h"
6 6
7 #include <algorithm> 7 #include <algorithm>
8 #include <utility> 8 #include <utility>
9 9
10 #include "base/process_util.h" 10 #include "base/process_util.h"
11 #include "base/utf_string_conversions.h" 11 #include "base/utf_string_conversions.h"
12 #include "chrome/browser/history/history_tab_helper.h" 12 #include "chrome/browser/history/history_tab_helper.h"
13 #include "chrome/browser/history/history_types.h" 13 #include "chrome/browser/history/history_types.h"
14 #include "chrome/browser/prerender/prerender_final_status.h" 14 #include "chrome/browser/prerender/prerender_final_status.h"
15 #include "chrome/browser/prerender/prerender_manager.h" 15 #include "chrome/browser/prerender/prerender_manager.h"
16 #include "chrome/browser/prerender/prerender_render_view_host_observer.h" 16 #include "chrome/browser/prerender/prerender_render_view_host_observer.h"
17 #include "chrome/browser/prerender/prerender_tracker.h" 17 #include "chrome/browser/prerender/prerender_tracker.h"
18 #include "chrome/browser/profiles/profile.h" 18 #include "chrome/browser/profiles/profile.h"
19 #include "chrome/browser/ui/browser.h" 19 #include "chrome/browser/ui/browser.h"
20 #include "chrome/browser/ui/browser_list.h" 20 #include "chrome/browser/ui/browser_list.h"
21 #include "chrome/browser/ui/tab_contents/tab_contents_wrapper.h" 21 #include "chrome/browser/ui/tab_contents/tab_contents_wrapper.h"
22 #include "chrome/common/chrome_notification_types.h" 22 #include "chrome/common/chrome_notification_types.h"
23 #include "chrome/common/icon_messages.h" 23 #include "chrome/common/icon_messages.h"
24 #include "chrome/common/render_messages.h" 24 #include "chrome/common/prerender_messages.h"
25 #include "chrome/common/url_constants.h" 25 #include "chrome/common/url_constants.h"
26 #include "content/browser/in_process_webkit/session_storage_namespace.h" 26 #include "content/browser/in_process_webkit/session_storage_namespace.h"
27 #include "content/browser/renderer_host/render_view_host.h" 27 #include "content/browser/renderer_host/render_view_host.h"
28 #include "content/browser/renderer_host/resource_request_details.h" 28 #include "content/browser/renderer_host/resource_request_details.h"
29 #include "content/public/browser/notification_service.h" 29 #include "content/public/browser/notification_service.h"
30 #include "content/public/browser/render_process_host.h" 30 #include "content/public/browser/render_process_host.h"
31 #include "content/public/browser/web_contents.h" 31 #include "content/public/browser/web_contents.h"
32 #include "content/public/browser/web_contents_delegate.h" 32 #include "content/public/browser/web_contents_delegate.h"
33 #include "content/public/browser/web_contents_view.h" 33 #include "content/public/browser/web_contents_view.h"
34 #include "ui/gfx/rect.h" 34 #include "ui/gfx/rect.h"
(...skipping 20 matching lines...) Expand all
55 bool operator()(const GURL& url) const { 55 bool operator()(const GURL& url) const {
56 return url.scheme() == url_.scheme() && 56 return url.scheme() == url_.scheme() &&
57 url.host() == url_.host() && 57 url.host() == url_.host() &&
58 url.port() == url_.port() && 58 url.port() == url_.port() &&
59 url.path() == url_.path() && 59 url.path() == url_.path() &&
60 url.query() == url_.query(); 60 url.query() == url_.query();
61 } 61 }
62 GURL url_; 62 GURL url_;
63 }; 63 };
64 64
65 // Tells the render process at |child_id| whether |url| is a new prerendered
66 // page, or whether |url| is being removed as a prerendered page. Currently
67 // this will only inform the render process that created the prerendered page
68 // with <link rel="prerender"> tags about it. This means that if a prerender
69 // is created from the omnibox or from another page, clicking on the a link
70 // for the same URL in another page will not swap in the prerender.
dominich 2012/02/29 18:32:01 This isn't a problem for Omnibox as we cancel the
cbentzel 2012/02/29 19:22:36 Done.
71 void InformRenderProcessAboutPrerender(const GURL& url,
dominich 2012/02/29 18:32:01 Given this is only called from methods in this cla
cbentzel 2012/02/29 19:22:36 I like it here, because it means that if it change
dominich 2012/02/29 19:44:35 Not modifying a header is a poor reason to base AP
cbentzel 2012/02/29 19:50:10 Huh? It's a pretty stateless function, and does no
72 bool is_add,
73 int child_id) {
74 if (child_id < 0)
75 return;
76 content::RenderProcessHost* render_process_host =
77 content::RenderProcessHost::FromID(child_id);
78 if (!render_process_host)
79 return;
80 IPC::Message* message = NULL;
81 if (is_add) {
dominich 2012/02/29 18:32:01 nit: {} not required
cbentzel 2012/02/29 19:22:36 Done.
82 message = new PrerenderMsg_AddPrerenderURL(url);
83 } else {
84 message = new PrerenderMsg_RemovePrerenderURL(url);
85 }
86 render_process_host->Send(message);
87 }
88
65 } // end namespace 89 } // end namespace
66 90
67 class PrerenderContentsFactoryImpl : public PrerenderContents::Factory { 91 class PrerenderContentsFactoryImpl : public PrerenderContents::Factory {
68 public: 92 public:
69 virtual PrerenderContents* CreatePrerenderContents( 93 virtual PrerenderContents* CreatePrerenderContents(
70 PrerenderManager* prerender_manager, PrerenderTracker* prerender_tracker, 94 PrerenderManager* prerender_manager, PrerenderTracker* prerender_tracker,
71 Profile* profile, const GURL& url, const content::Referrer& referrer, 95 Profile* profile, const GURL& url, const content::Referrer& referrer,
72 Origin origin, uint8 experiment_id) OVERRIDE { 96 Origin origin, uint8 experiment_id) OVERRIDE {
73 return new PrerenderContents(prerender_manager, prerender_tracker, profile, 97 return new PrerenderContents(prerender_manager, prerender_tracker, profile,
74 url, referrer, origin, experiment_id); 98 url, referrer, origin, experiment_id);
(...skipping 145 matching lines...) Expand 10 before | Expand all | Expand 10 after
220 profile_(profile), 244 profile_(profile),
221 page_id_(0), 245 page_id_(0),
222 has_stopped_loading_(false), 246 has_stopped_loading_(false),
223 final_status_(FINAL_STATUS_MAX), 247 final_status_(FINAL_STATUS_MAX),
224 prerendering_has_started_(false), 248 prerendering_has_started_(false),
225 match_complete_status_(MATCH_COMPLETE_DEFAULT), 249 match_complete_status_(MATCH_COMPLETE_DEFAULT),
226 prerendering_has_been_cancelled_(false), 250 prerendering_has_been_cancelled_(false),
227 child_id_(-1), 251 child_id_(-1),
228 route_id_(-1), 252 route_id_(-1),
229 origin_(origin), 253 origin_(origin),
230 experiment_id_(experiment_id) { 254 experiment_id_(experiment_id),
255 creator_child_id_(-1) {
231 DCHECK(prerender_manager != NULL); 256 DCHECK(prerender_manager != NULL);
232 } 257 }
233 258
234 bool PrerenderContents::Init() { 259 bool PrerenderContents::Init() {
235 return AddAliasURL(prerender_url_); 260 return AddAliasURL(prerender_url_);
236 } 261 }
237 262
238 // static 263 // static
239 PrerenderContents::Factory* PrerenderContents::CreateFactory() { 264 PrerenderContents::Factory* PrerenderContents::CreateFactory() {
240 return new PrerenderContentsFactoryImpl(); 265 return new PrerenderContentsFactoryImpl();
241 } 266 }
242 267
243 void PrerenderContents::StartPrerendering( 268 void PrerenderContents::StartPrerendering(
244 const RenderViewHost* source_render_view_host, 269 const RenderViewHost* source_render_view_host,
245 SessionStorageNamespace* session_storage_namespace) { 270 SessionStorageNamespace* session_storage_namespace) {
246 DCHECK(profile_ != NULL); 271 DCHECK(profile_ != NULL);
247 DCHECK(!prerendering_has_started_); 272 DCHECK(!prerendering_has_started_);
248 DCHECK(prerender_contents_.get() == NULL); 273 DCHECK(prerender_contents_.get() == NULL);
249 274
250 prerendering_has_started_ = true; 275 prerendering_has_started_ = true;
276 DCHECK(creator_child_id_ == -1);
277 if (source_render_view_host)
278 creator_child_id_ = source_render_view_host->process()->GetID();
279 InformRenderProcessAboutPrerender(prerender_url_, true,
280 creator_child_id_);
281
251 WebContents* new_contents = WebContents::Create( 282 WebContents* new_contents = WebContents::Create(
252 profile_, NULL, MSG_ROUTING_NONE, NULL, session_storage_namespace); 283 profile_, NULL, MSG_ROUTING_NONE, NULL, session_storage_namespace);
253 prerender_contents_.reset(new TabContentsWrapper(new_contents)); 284 prerender_contents_.reset(new TabContentsWrapper(new_contents));
254 content::WebContentsObserver::Observe(new_contents); 285 content::WebContentsObserver::Observe(new_contents);
255 286
256 gfx::Rect tab_bounds; 287 gfx::Rect tab_bounds;
257 if (source_render_view_host) { 288 if (source_render_view_host) {
258 DCHECK(source_render_view_host->view() != NULL); 289 DCHECK(source_render_view_host->view() != NULL);
259 WebContents* source_wc = 290 WebContents* source_wc =
260 source_render_view_host->delegate()->GetAsWebContents(); 291 source_render_view_host->delegate()->GetAsWebContents();
(...skipping 150 matching lines...) Expand 10 before | Expand all | Expand 10 after
411 442
412 content::Details<RenderViewHost> new_render_view_host(details); 443 content::Details<RenderViewHost> new_render_view_host(details);
413 OnRenderViewHostCreated(new_render_view_host.ptr()); 444 OnRenderViewHostCreated(new_render_view_host.ptr());
414 445
415 // When a new RenderView is created for a prerendering TabContents, 446 // When a new RenderView is created for a prerendering TabContents,
416 // tell the new RenderView it's being used for prerendering before any 447 // tell the new RenderView it's being used for prerendering before any
417 // navigations occur. Note that this is always triggered before the 448 // navigations occur. Note that this is always triggered before the
418 // first navigation, so there's no need to send the message just after 449 // first navigation, so there's no need to send the message just after
419 // the TabContents is created. 450 // the TabContents is created.
420 new_render_view_host->Send( 451 new_render_view_host->Send(
421 new ChromeViewMsg_SetIsPrerendering( 452 new PrerenderMsg_SetIsPrerendering(
422 new_render_view_host->routing_id(), 453 new_render_view_host->routing_id(),
423 true)); 454 true));
424 455
425 // Make sure the size of the RenderViewHost has been passed to the new 456 // Make sure the size of the RenderViewHost has been passed to the new
426 // RenderView. Otherwise, the size may not be sent until the 457 // RenderView. Otherwise, the size may not be sent until the
427 // RenderViewReady event makes it from the render process to the UI 458 // RenderViewReady event makes it from the render process to the UI
428 // thread of the browser process. When the RenderView receives its 459 // thread of the browser process. When the RenderView receives its
429 // size, is also sets itself to be visible, which would then break the 460 // size, is also sets itself to be visible, which would then break the
430 // visibility API. 461 // visibility API.
431 new_render_view_host->WasResized(); 462 new_render_view_host->WasResized();
(...skipping 104 matching lines...) Expand 10 before | Expand all | Expand 10 after
536 bool PrerenderContents::ShouldSuppressDialogs() { 567 bool PrerenderContents::ShouldSuppressDialogs() {
537 // Always suppress JavaScript messages if they're triggered by a page being 568 // Always suppress JavaScript messages if they're triggered by a page being
538 // prerendered. 569 // prerendered.
539 // We still want to show the user the message when they navigate to this 570 // We still want to show the user the message when they navigate to this
540 // page, so cancel this prerender. 571 // page, so cancel this prerender.
541 Destroy(FINAL_STATUS_JAVASCRIPT_ALERT); 572 Destroy(FINAL_STATUS_JAVASCRIPT_ALERT);
542 return true; 573 return true;
543 } 574 }
544 575
545 void PrerenderContents::Destroy(FinalStatus final_status) { 576 void PrerenderContents::Destroy(FinalStatus final_status) {
577 InformRenderProcessAboutPrerender(prerender_url_, false, creator_child_id_);
546 if (prerendering_has_been_cancelled_) 578 if (prerendering_has_been_cancelled_)
547 return; 579 return;
548 580
549 if (child_id_ != -1 && route_id_ != -1) { 581 if (child_id_ != -1 && route_id_ != -1) {
550 // Cancel the prerender in the PrerenderTracker. This is needed 582 // Cancel the prerender in the PrerenderTracker. This is needed
551 // because destroy may be called directly from the UI thread without calling 583 // because destroy may be called directly from the UI thread without calling
552 // TryCancel(). This is difficult to completely avoid, since prerendering 584 // TryCancel(). This is difficult to completely avoid, since prerendering
553 // can be cancelled before a RenderView is created. 585 // can be cancelled before a RenderView is created.
554 bool is_cancelled = prerender_tracker_->TryCancel( 586 bool is_cancelled = prerender_tracker_->TryCancel(
555 child_id_, route_id_, final_status); 587 child_id_, route_id_, final_status);
(...skipping 94 matching lines...) Expand 10 before | Expand all | Expand 10 after
650 bool PrerenderContents::IsCrossSiteNavigationPending() const { 682 bool PrerenderContents::IsCrossSiteNavigationPending() const {
651 if (!prerender_contents_.get() || !prerender_contents_->web_contents()) 683 if (!prerender_contents_.get() || !prerender_contents_->web_contents())
652 return false; 684 return false;
653 const WebContents* web_contents = prerender_contents_->web_contents(); 685 const WebContents* web_contents = prerender_contents_->web_contents();
654 return (web_contents->GetSiteInstance() != 686 return (web_contents->GetSiteInstance() !=
655 web_contents->GetPendingSiteInstance()); 687 web_contents->GetPendingSiteInstance());
656 } 688 }
657 689
658 690
659 } // namespace prerender 691 } // namespace prerender
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698