Upstream version 5.34.104.0
[platform/framework/web/crosswalk.git] / src / chrome / renderer / prerender / prerender_dispatcher.cc
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.
4
5 #include "chrome/renderer/prerender/prerender_dispatcher.h"
6
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"
17 #include "url/gurl.h"
18
19 namespace prerender {
20
21 using blink::WebPrerender;
22 using blink::WebPrerenderingSupport;
23
24 PrerenderDispatcher::PrerenderDispatcher() {
25   WebPrerenderingSupport::initialize(this);
26 }
27
28 PrerenderDispatcher::~PrerenderDispatcher() {
29   WebPrerenderingSupport::shutdown();
30 }
31
32 bool PrerenderDispatcher::IsPrerenderURL(const GURL& url) const {
33   return running_prerender_urls_.count(url) >= 1;
34 }
35
36 void PrerenderDispatcher::OnPrerenderStart(int prerender_id) {
37   std::map<int, WebPrerender>::iterator it = prerenders_.find(prerender_id);
38   if (it == prerenders_.end())
39     return;
40
41   WebPrerender& prerender = it->second;
42
43   // The prerender should only be null in unit tests.
44   if (prerender.isNull())
45     return;
46
47   prerender.didStartPrerender();
48 }
49
50 void PrerenderDispatcher::OnPrerenderStopLoading(int prerender_id) {
51   std::map<int, WebPrerender>::iterator it = prerenders_.find(prerender_id);
52   if (it == prerenders_.end())
53     return;
54
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.";
59
60   prerender.didSendLoadForPrerender();
61 }
62
63 void PrerenderDispatcher::OnPrerenderDomContentLoaded(int prerender_id) {
64   std::map<int, WebPrerender>::iterator it = prerenders_.find(prerender_id);
65   if (it == prerenders_.end())
66     return;
67
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"
72       << " null.";
73
74   prerender.didSendDOMContentLoadedForPrerender();
75 }
76
77 void PrerenderDispatcher::OnPrerenderAddAlias(const GURL& alias) {
78   running_prerender_urls_.insert(alias);
79 }
80
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);
87     }
88   }
89 }
90
91 void PrerenderDispatcher::OnPrerenderStop(int prerender_id) {
92   std::map<int, WebPrerender>::iterator it = prerenders_.find(prerender_id);
93   if (it == prerenders_.end())
94     return;
95   WebPrerender& prerender = it->second;
96
97   // The prerender should only be null in unit tests.
98   if (!prerender.isNull())
99     prerender.didStopPrerender();
100
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);
106 }
107
108 bool PrerenderDispatcher::OnControlMessageReceived(
109     const IPC::Message& message) {
110   bool handled = true;
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()
123
124   return handled;
125 }
126
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.
132     return;
133   }
134
135   prerenders_[extra_data.prerender_id()] = prerender;
136
137   PrerenderAttributes attributes;
138   attributes.url = GURL(prerender.url());
139   attributes.rel_types = prerender.relTypes();
140
141   content::RenderThread::Get()->Send(new PrerenderHostMsg_AddLinkRelPrerender(
142       extra_data.prerender_id(), attributes,
143       content::Referrer(GURL(prerender.referrer()),
144                         prerender.referrerPolicy()),
145       extra_data.size(), extra_data.render_view_route_id()));
146 }
147
148 void PrerenderDispatcher::cancel(const WebPrerender& prerender) {
149   const PrerenderExtraData& extra_data =
150       PrerenderExtraData::FromPrerender(prerender);
151   content::RenderThread::Get()->Send(
152       new PrerenderHostMsg_CancelLinkRelPrerender(extra_data.prerender_id()));
153   // The browser will not send an OnPrerenderStop (the prerender may have even
154   // been canceled before it was started), so release it to avoid a
155   // leak. Moreover, if it did, the PrerenderClient in Blink will have been
156   // detached already.
157    prerenders_.erase(extra_data.prerender_id());
158 }
159
160 void PrerenderDispatcher::abandon(const WebPrerender& prerender) {
161   const PrerenderExtraData& extra_data =
162       PrerenderExtraData::FromPrerender(prerender);
163   content::RenderThread::Get()->Send(
164       new PrerenderHostMsg_AbandonLinkRelPrerender(extra_data.prerender_id()));
165   // The browser will not send an OnPrerenderStop (the prerender may have even
166   // been canceled before it was started), so release it to avoid a
167   // leak. Moreover, if it did, the PrerenderClient in Blink will have been
168   // detached already.
169   prerenders_.erase(extra_data.prerender_id());
170 }
171
172 }  // namespace prerender