OLD | NEW |
| (Empty) |
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 "content/browser/browser_plugin/old/browser_plugin_host.h" | |
6 | |
7 #include "content/browser/browser_plugin/old/browser_plugin_host_helper.h" | |
8 #include "content/browser/renderer_host/render_view_host_impl.h" | |
9 #include "content/browser/web_contents/web_contents_impl.h" | |
10 #include "content/common/old_browser_plugin_messages.h" | |
11 #include "content/public/common/url_constants.h" | |
12 #include "content/public/browser/notification_details.h" | |
13 #include "content/public/browser/notification_source.h" | |
14 #include "content/public/browser/notification_types.h" | |
15 #include "content/public/browser/render_process_host.h" | |
16 #include "content/public/browser/render_widget_host_view.h" | |
17 #include "content/public/browser/site_instance.h" | |
18 #include "content/public/browser/web_contents_view.h" | |
19 #include "ppapi/proxy/ppapi_messages.h" | |
20 | |
21 namespace content { | |
22 namespace old { | |
23 | |
24 BrowserPluginHost::BrowserPluginHost( | |
25 WebContentsImpl* web_contents) | |
26 : WebContentsObserver(web_contents), | |
27 embedder_render_process_host_(NULL), | |
28 instance_id_(0) { | |
29 // Listen to visibility changes so that an embedder hides its guests | |
30 // as well. | |
31 registrar_.Add(this, | |
32 NOTIFICATION_WEB_CONTENTS_VISIBILITY_CHANGED, | |
33 Source<WebContents>(web_contents)); | |
34 // Construct plumbing helpers when a new RenderViewHost is created for | |
35 // this BrowserPluginHost's WebContentsImpl. | |
36 registrar_.Add(this, | |
37 NOTIFICATION_WEB_CONTENTS_RENDER_VIEW_HOST_CREATED, | |
38 Source<WebContents>(web_contents)); | |
39 } | |
40 | |
41 BrowserPluginHost::~BrowserPluginHost() { | |
42 } | |
43 | |
44 BrowserPluginHost* BrowserPluginHost::GetGuestByContainerID(int container_id) { | |
45 ContainerInstanceMap::const_iterator it = | |
46 guests_by_container_id_.find(container_id); | |
47 if (it != guests_by_container_id_.end()) | |
48 return it->second; | |
49 return NULL; | |
50 } | |
51 | |
52 void BrowserPluginHost::RegisterContainerInstance( | |
53 int container_id, | |
54 BrowserPluginHost* observer) { | |
55 DCHECK(guests_by_container_id_.find(container_id) == | |
56 guests_by_container_id_.end()); | |
57 guests_by_container_id_[container_id] = observer; | |
58 } | |
59 | |
60 bool BrowserPluginHost::TakeFocus(bool reverse) { | |
61 embedder_render_process_host()->Send( | |
62 new OldBrowserPluginMsg_AdvanceFocus(instance_id(), reverse)); | |
63 return true; | |
64 } | |
65 | |
66 bool BrowserPluginHost::OnMessageReceived(const IPC::Message& message) { | |
67 bool handled = true; | |
68 IPC_BEGIN_MESSAGE_MAP(BrowserPluginHost, message) | |
69 IPC_MESSAGE_HANDLER(OldBrowserPluginHostMsg_NavigateFromGuest, | |
70 OnNavigateFromGuest) | |
71 IPC_MESSAGE_UNHANDLED(handled = false) | |
72 IPC_END_MESSAGE_MAP() | |
73 return handled; | |
74 } | |
75 | |
76 void BrowserPluginHost::NavigateGuestFromEmbedder( | |
77 RenderViewHost* render_view_host, | |
78 int container_instance_id, | |
79 long long frame_id, | |
80 const std::string& src) { | |
81 BrowserPluginHost* guest_observer = | |
82 GetGuestByContainerID(container_instance_id); | |
83 WebContentsImpl* guest_web_contents = | |
84 guest_observer ? | |
85 static_cast<WebContentsImpl*>(guest_observer->web_contents()): NULL; | |
86 GURL url(src); | |
87 if (!guest_observer) { | |
88 std::string host = render_view_host->GetSiteInstance()->GetSite().host(); | |
89 GURL guest_url( | |
90 base::StringPrintf("%s://%s", chrome::kGuestScheme, host.c_str())); | |
91 // The SiteInstance of a given guest is based on the fact that it's a guest | |
92 // in addition to which platform application the guest belongs to, rather | |
93 // than the URL that the guest is being navigated to. | |
94 SiteInstance* guest_site_instance = | |
95 SiteInstance::CreateForURL(web_contents()->GetBrowserContext(), | |
96 guest_url); | |
97 guest_web_contents = | |
98 static_cast<WebContentsImpl*>( | |
99 WebContents::Create( | |
100 web_contents()->GetBrowserContext(), | |
101 guest_site_instance, | |
102 MSG_ROUTING_NONE, | |
103 NULL, // base WebContents | |
104 NULL // session storage namespace | |
105 )); | |
106 guest_observer = | |
107 guest_web_contents->browser_plugin_host(); | |
108 guest_observer->set_embedder_render_process_host( | |
109 render_view_host->GetProcess()); | |
110 guest_observer->set_instance_id(container_instance_id); | |
111 RegisterContainerInstance(container_instance_id, guest_observer); | |
112 AddGuest(guest_web_contents, frame_id); | |
113 } | |
114 guest_observer->web_contents()->SetDelegate(guest_observer); | |
115 guest_observer->web_contents()->GetController().LoadURL( | |
116 url, | |
117 Referrer(), | |
118 PAGE_TRANSITION_AUTO_SUBFRAME, | |
119 std::string()); | |
120 } | |
121 | |
122 void BrowserPluginHost::OnNavigateFromGuest( | |
123 PP_Instance instance, | |
124 const std::string& src) { | |
125 DCHECK(embedder_render_process_host()); | |
126 GURL url(src); | |
127 web_contents()->GetController().LoadURL( | |
128 url, | |
129 Referrer(), | |
130 PAGE_TRANSITION_AUTO_SUBFRAME, | |
131 std::string()); | |
132 } | |
133 | |
134 void BrowserPluginHost::ConnectEmbedderToChannel( | |
135 RenderViewHost* render_view_host, | |
136 const IPC::ChannelHandle& channel_handle) { | |
137 DCHECK(embedder_render_process_host()); | |
138 // Tell the BrowserPlugin in the embedder that we're done and that it can | |
139 // begin using the guest renderer. | |
140 embedder_render_process_host()->Send( | |
141 new OldBrowserPluginMsg_LoadGuest( | |
142 instance_id(), | |
143 render_view_host->GetProcess()-> | |
144 GetID(), | |
145 channel_handle)); | |
146 } | |
147 | |
148 void BrowserPluginHost::AddGuest(WebContentsImpl* guest, int64 frame_id) { | |
149 guests_[guest] = frame_id; | |
150 } | |
151 | |
152 void BrowserPluginHost::RemoveGuest(WebContentsImpl* guest) { | |
153 guests_.erase(guest); | |
154 } | |
155 | |
156 void BrowserPluginHost::DestroyGuests() { | |
157 for (GuestMap::const_iterator it = guests_.begin(); | |
158 it != guests_.end(); ++it) { | |
159 WebContentsImpl* web_contents = it->first; | |
160 delete web_contents; | |
161 } | |
162 guests_.clear(); | |
163 guests_by_container_id_.clear(); | |
164 } | |
165 | |
166 void BrowserPluginHost::DidCommitProvisionalLoadForFrame( | |
167 int64 frame_id, | |
168 bool is_main_frame, | |
169 const GURL& url, | |
170 PageTransition transition_type, | |
171 RenderViewHost* render_view_host) { | |
172 // Clean-up guests that lie in the frame that we're navigating. | |
173 typedef std::set<WebContentsImpl*> GuestSet; | |
174 GuestSet guests_to_delete; | |
175 for (GuestMap::const_iterator it = guests_.begin(); | |
176 it != guests_.end(); ++it) { | |
177 WebContentsImpl* web_contents = it->first; | |
178 if (it->second == frame_id) { | |
179 guests_to_delete.insert(web_contents); | |
180 } | |
181 } | |
182 for (GuestSet::const_iterator it = guests_to_delete.begin(); | |
183 it != guests_to_delete.end(); ++it) { | |
184 delete *it; | |
185 guests_.erase(*it); | |
186 } | |
187 } | |
188 | |
189 void BrowserPluginHost::RenderViewDeleted(RenderViewHost* render_view_host) { | |
190 // TODO(fsamuel): For some reason ToT hangs when killing a guest, this wasn't | |
191 // the case earlier. Presumably, when a guest is killed/crashes, one of | |
192 // RenderViewDeleted, RenderViewGone or WebContentsDestroyed will get called. | |
193 // At that point, we should remove reference to this BrowserPluginHost | |
194 // from its embedder, in addition to destroying its guests, to ensure | |
195 // that we do not attempt a double delete. | |
196 DestroyGuests(); | |
197 } | |
198 | |
199 void BrowserPluginHost::RenderViewGone(base::TerminationStatus status) { | |
200 DestroyGuests(); | |
201 } | |
202 | |
203 void BrowserPluginHost::WebContentsDestroyed(WebContents* web_contents) { | |
204 DestroyGuests(); | |
205 } | |
206 | |
207 void BrowserPluginHost::Observe( | |
208 int type, | |
209 const NotificationSource& source, | |
210 const NotificationDetails& details) { | |
211 switch (type) { | |
212 case NOTIFICATION_WEB_CONTENTS_RENDER_VIEW_HOST_CREATED: { | |
213 RenderViewHost* render_view_host = | |
214 Details<RenderViewHost>(details).ptr(); | |
215 // BrowserPluginHostHelper is destroyed when its associated RenderViewHost | |
216 // is destroyed. | |
217 new BrowserPluginHostHelper(this, render_view_host); | |
218 break; | |
219 } | |
220 case NOTIFICATION_WEB_CONTENTS_VISIBILITY_CHANGED: { | |
221 bool visible = *Details<bool>(details).ptr(); | |
222 // If the embedder is hidden we need to hide the guests as well. | |
223 for (GuestMap::const_iterator it = guests_.begin(); | |
224 it != guests_.end(); ++it) { | |
225 WebContentsImpl* web_contents = it->first; | |
226 if (visible) | |
227 web_contents->WasShown(); | |
228 else | |
229 web_contents->WasHidden(); | |
230 } | |
231 break; | |
232 } | |
233 default: | |
234 NOTREACHED() << "Unexpected notification type: " << type; | |
235 } | |
236 } | |
237 | |
238 } // namespace old | |
239 } // namespace content | |
OLD | NEW |