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
3 // found in the LICENSE file.
5 #include "chrome/renderer/prerender/prerender_dispatcher.h"
7 #include "base/logging.h"
8 #include "chrome/common/prerender_messages.h"
9 #include "chrome/common/prerender_types.h"
10 #include "chrome/renderer/prerender/prerender_extra_data.h"
11 #include "content/public/common/referrer.h"
12 #include "content/public/renderer/render_thread.h"
13 #include "content/public/renderer/render_view.h"
14 #include "third_party/WebKit/public/platform/WebPrerenderingSupport.h"
15 #include "third_party/WebKit/public/platform/WebString.h"
16 #include "third_party/WebKit/public/platform/WebURL.h"
21 using blink::WebPrerender
;
22 using blink::WebPrerenderingSupport
;
24 PrerenderDispatcher::PrerenderDispatcher() {
25 WebPrerenderingSupport::initialize(this);
28 PrerenderDispatcher::~PrerenderDispatcher() {
29 WebPrerenderingSupport::shutdown();
32 bool PrerenderDispatcher::IsPrerenderURL(const GURL
& url
) const {
33 return running_prerender_urls_
.count(url
) >= 1;
36 void PrerenderDispatcher::OnPrerenderStart(int prerender_id
) {
37 std::map
<int, WebPrerender
>::iterator it
= prerenders_
.find(prerender_id
);
38 if (it
== prerenders_
.end())
41 WebPrerender
& prerender
= it
->second
;
43 // The prerender should only be null in unit tests.
44 if (prerender
.isNull())
47 prerender
.didStartPrerender();
50 void PrerenderDispatcher::OnPrerenderStopLoading(int prerender_id
) {
51 std::map
<int, WebPrerender
>::iterator it
= prerenders_
.find(prerender_id
);
52 if (it
== prerenders_
.end())
55 WebPrerender
& prerender
= it
->second
;
56 DCHECK(!prerender
.isNull())
57 << "OnPrerenderStopLoading shouldn't be called from a unit test, the only"
58 << "context in which a WebPrerender in the dispatcher can be null.";
60 prerender
.didSendLoadForPrerender();
63 void PrerenderDispatcher::OnPrerenderDomContentLoaded(int prerender_id
) {
64 std::map
<int, WebPrerender
>::iterator it
= prerenders_
.find(prerender_id
);
65 if (it
== prerenders_
.end())
68 WebPrerender
& prerender
= it
->second
;
69 DCHECK(!prerender
.isNull())
70 << "OnPrerenderDomContentLoaded shouldn't be called from a unit test,"
71 << " the only context in which a WebPrerender in the dispatcher can be"
74 prerender
.didSendDOMContentLoadedForPrerender();
77 void PrerenderDispatcher::OnPrerenderAddAlias(const GURL
& alias
) {
78 running_prerender_urls_
.insert(alias
);
81 void PrerenderDispatcher::OnPrerenderRemoveAliases(
82 const std::vector
<GURL
>& aliases
) {
83 for (size_t i
= 0; i
< aliases
.size(); ++i
) {
84 std::multiset
<GURL
>::iterator it
= running_prerender_urls_
.find(aliases
[i
]);
85 if (it
!= running_prerender_urls_
.end()) {
86 running_prerender_urls_
.erase(it
);
91 void PrerenderDispatcher::OnPrerenderStop(int prerender_id
) {
92 std::map
<int, WebPrerender
>::iterator it
= prerenders_
.find(prerender_id
);
93 if (it
== prerenders_
.end())
95 WebPrerender
& prerender
= it
->second
;
97 // The prerender should only be null in unit tests.
98 if (!prerender
.isNull())
99 prerender
.didStopPrerender();
101 // TODO(cbentzel): We'd also want to send the map of active prerenders when
102 // creating a new render process, so the Add/Remove go relative to that.
103 // This may not be that big of a deal in practice, since the newly created tab
104 // is unlikely to go to the prerendered page.
105 prerenders_
.erase(prerender_id
);
108 bool PrerenderDispatcher::OnControlMessageReceived(
109 const IPC::Message
& message
) {
111 IPC_BEGIN_MESSAGE_MAP(PrerenderDispatcher
, message
)
112 IPC_MESSAGE_HANDLER(PrerenderMsg_OnPrerenderStart
, OnPrerenderStart
)
113 IPC_MESSAGE_HANDLER(PrerenderMsg_OnPrerenderStopLoading
,
114 OnPrerenderStopLoading
)
115 IPC_MESSAGE_HANDLER(PrerenderMsg_OnPrerenderDomContentLoaded
,
116 OnPrerenderDomContentLoaded
)
117 IPC_MESSAGE_HANDLER(PrerenderMsg_OnPrerenderAddAlias
, OnPrerenderAddAlias
)
118 IPC_MESSAGE_HANDLER(PrerenderMsg_OnPrerenderRemoveAliases
,
119 OnPrerenderRemoveAliases
)
120 IPC_MESSAGE_HANDLER(PrerenderMsg_OnPrerenderStop
, OnPrerenderStop
)
121 IPC_MESSAGE_UNHANDLED(handled
= false)
122 IPC_END_MESSAGE_MAP()
127 void PrerenderDispatcher::add(const WebPrerender
& prerender
) {
128 const PrerenderExtraData
& extra_data
=
129 PrerenderExtraData::FromPrerender(prerender
);
130 if (prerenders_
.count(extra_data
.prerender_id()) != 0) {
131 // TODO(gavinp): Determine why these apparently duplicate adds occur.
135 prerenders_
[extra_data
.prerender_id()] = prerender
;
137 PrerenderAttributes attributes
;
138 attributes
.url
= GURL(prerender
.url());
139 attributes
.rel_types
= prerender
.relTypes();
141 content::RenderThread::Get()->Send(new PrerenderHostMsg_AddLinkRelPrerender(
142 extra_data
.prerender_id(), attributes
,
143 content::Referrer::SanitizeForRequest(
144 GURL(prerender
.url()), content::Referrer(GURL(prerender
.referrer()),
145 prerender
.referrerPolicy())),
146 extra_data
.size(), extra_data
.render_view_route_id()));
149 void PrerenderDispatcher::cancel(const WebPrerender
& prerender
) {
150 const PrerenderExtraData
& extra_data
=
151 PrerenderExtraData::FromPrerender(prerender
);
152 content::RenderThread::Get()->Send(
153 new PrerenderHostMsg_CancelLinkRelPrerender(extra_data
.prerender_id()));
154 // The browser will not send an OnPrerenderStop (the prerender may have even
155 // been canceled before it was started), so release it to avoid a
156 // leak. Moreover, if it did, the PrerenderClient in Blink will have been
158 prerenders_
.erase(extra_data
.prerender_id());
161 void PrerenderDispatcher::abandon(const WebPrerender
& prerender
) {
162 const PrerenderExtraData
& extra_data
=
163 PrerenderExtraData::FromPrerender(prerender
);
164 content::RenderThread::Get()->Send(
165 new PrerenderHostMsg_AbandonLinkRelPrerender(extra_data
.prerender_id()));
166 // The browser will not send an OnPrerenderStop (the prerender may have even
167 // been canceled before it was started), so release it to avoid a
168 // leak. Moreover, if it did, the PrerenderClient in Blink will have been
170 prerenders_
.erase(extra_data
.prerender_id());
173 } // namespace prerender