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 "content/browser/browser_plugin/browser_plugin_embedder.h" | 5 #include "content/browser/browser_plugin/browser_plugin_embedder.h" |
6 | 6 |
7 #include "base/stl_util.h" | 7 #include "base/stl_util.h" |
8 #include "content/browser/browser_plugin/browser_plugin_guest.h" | 8 #include "content/browser/browser_plugin/browser_plugin_guest.h" |
9 #include "content/browser/browser_plugin/browser_plugin_host_factory.h" | 9 #include "content/browser/browser_plugin/browser_plugin_host_factory.h" |
10 #include "content/browser/renderer_host/render_view_host_impl.h" | 10 #include "content/browser/renderer_host/render_view_host_impl.h" |
(...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
47 BrowserPluginEmbedder* BrowserPluginEmbedder::Create( | 47 BrowserPluginEmbedder* BrowserPluginEmbedder::Create( |
48 WebContentsImpl* web_contents, | 48 WebContentsImpl* web_contents, |
49 content::RenderViewHost* render_view_host) { | 49 content::RenderViewHost* render_view_host) { |
50 if (factory_) { | 50 if (factory_) { |
51 return factory_->CreateBrowserPluginEmbedder(web_contents, | 51 return factory_->CreateBrowserPluginEmbedder(web_contents, |
52 render_view_host); | 52 render_view_host); |
53 } | 53 } |
54 return new BrowserPluginEmbedder(web_contents, render_view_host); | 54 return new BrowserPluginEmbedder(web_contents, render_view_host); |
55 } | 55 } |
56 | 56 |
| 57 void BrowserPluginEmbedder::CreateGuest( |
| 58 int instance_id, |
| 59 int routing_id, |
| 60 BrowserPluginGuest* guest_opener, |
| 61 const BrowserPluginHostMsg_CreateGuest_Params& params) { |
| 62 WebContentsImpl* guest_web_contents = NULL; |
| 63 BrowserPluginGuest* guest = GetGuestByInstanceID(instance_id); |
| 64 CHECK(!guest); |
| 65 |
| 66 // Validate that the partition id coming from the renderer is valid UTF-8, |
| 67 // since we depend on this in other parts of the code, such as FilePath |
| 68 // creation. If the validation fails, treat it as a bad message and kill the |
| 69 // renderer process. |
| 70 if (!IsStringUTF8(params.storage_partition_id)) { |
| 71 content::RecordAction(UserMetricsAction("BadMessageTerminate_BPE")); |
| 72 base::KillProcess(render_view_host_->GetProcess()->GetHandle(), |
| 73 content::RESULT_CODE_KILLED_BAD_MESSAGE, false); |
| 74 return; |
| 75 } |
| 76 |
| 77 const std::string& host = |
| 78 render_view_host_->GetSiteInstance()->GetSiteURL().host(); |
| 79 std::string url_encoded_partition = net::EscapeQueryParamValue( |
| 80 params.storage_partition_id, false); |
| 81 |
| 82 SiteInstance* guest_site_instance = NULL; |
| 83 if (guest_opener) { |
| 84 guest_site_instance = guest_opener->GetWebContents()->GetSiteInstance(); |
| 85 } else { |
| 86 // The SiteInstance of a given webview tag is based on the fact that it's a |
| 87 // guest process in addition to which platform application the tag belongs |
| 88 // to and what storage partition is in use, rather than the URL that the tag |
| 89 // is being navigated to. |
| 90 GURL guest_site( |
| 91 base::StringPrintf("%s://%s/%s?%s", chrome::kGuestScheme, |
| 92 host.c_str(), params.persist_storage ? "persist" : "", |
| 93 url_encoded_partition.c_str())); |
| 94 |
| 95 // If we already have a webview tag in the same app using the same storage |
| 96 // partition, we should use the same SiteInstance so the existing tag and |
| 97 // the new tag can script each other. |
| 98 for (ContainerInstanceMap::const_iterator it = |
| 99 guest_web_contents_by_instance_id_.begin(); |
| 100 it != guest_web_contents_by_instance_id_.end(); ++it) { |
| 101 if (it->second->GetSiteInstance()->GetSiteURL() == guest_site) { |
| 102 guest_site_instance = it->second->GetSiteInstance(); |
| 103 break; |
| 104 } |
| 105 } |
| 106 if (!guest_site_instance) { |
| 107 // Create the SiteInstance in a new BrowsingInstance, which will ensure |
| 108 // that webview tags are also not allowed to send messages across |
| 109 // different partitions. |
| 110 guest_site_instance = SiteInstance::CreateForURL( |
| 111 web_contents()->GetBrowserContext(), guest_site); |
| 112 } |
| 113 } |
| 114 WebContentsImpl* opener_web_contents = static_cast<WebContentsImpl*>( |
| 115 guest_opener ? guest_opener->GetWebContents() : NULL); |
| 116 guest_web_contents = WebContentsImpl::CreateGuest( |
| 117 web_contents()->GetBrowserContext(), |
| 118 guest_site_instance, |
| 119 routing_id, |
| 120 opener_web_contents, |
| 121 instance_id, |
| 122 params); |
| 123 |
| 124 guest = guest_web_contents->GetBrowserPluginGuest(); |
| 125 guest->set_embedder_web_contents( |
| 126 static_cast<WebContentsImpl*>(web_contents())); |
| 127 |
| 128 RendererPreferences* guest_renderer_prefs = |
| 129 guest_web_contents->GetMutableRendererPrefs(); |
| 130 // Copy renderer preferences (and nothing else) from the embedder's |
| 131 // TabContents to the guest. |
| 132 // |
| 133 // For GTK and Aura this is necessary to get proper renderer configuration |
| 134 // values for caret blinking interval, colors related to selection and |
| 135 // focus. |
| 136 *guest_renderer_prefs = *web_contents()->GetMutableRendererPrefs(); |
| 137 |
| 138 guest_renderer_prefs->throttle_input_events = false; |
| 139 // Navigation is disabled in Chrome Apps. We want to make sure guest-initiated |
| 140 // navigations still continue to function inside the app. |
| 141 guest_renderer_prefs->browser_handles_all_top_level_requests = false; |
| 142 AddGuest(instance_id, guest_web_contents); |
| 143 guest_web_contents->SetDelegate(guest); |
| 144 |
| 145 // Create a swapped out RenderView for the guest in the embedder render |
| 146 // process, so that the embedder can access the guest's window object. |
| 147 int guest_routing_id = |
| 148 static_cast<WebContentsImpl*>(guest->GetWebContents())-> |
| 149 CreateSwappedOutRenderView(web_contents()->GetSiteInstance()); |
| 150 render_view_host_->Send(new BrowserPluginMsg_GuestContentWindowReady( |
| 151 render_view_host_->GetRoutingID(), instance_id, guest_routing_id)); |
| 152 |
| 153 guest->Initialize(params, guest_web_contents->GetRenderViewHost()); |
| 154 } |
| 155 |
| 156 BrowserPluginGuest* BrowserPluginEmbedder::GetGuestByInstanceID( |
| 157 int instance_id) const { |
| 158 ContainerInstanceMap::const_iterator it = |
| 159 guest_web_contents_by_instance_id_.find(instance_id); |
| 160 if (it != guest_web_contents_by_instance_id_.end()) |
| 161 return static_cast<WebContentsImpl*>(it->second)->GetBrowserPluginGuest(); |
| 162 return NULL; |
| 163 } |
| 164 |
| 165 void BrowserPluginEmbedder::DestroyGuestByInstanceID(int instance_id) { |
| 166 BrowserPluginGuest* guest = GetGuestByInstanceID(instance_id); |
| 167 if (guest) { |
| 168 WebContents* guest_web_contents = guest->GetWebContents(); |
| 169 |
| 170 // Destroy the guest's web_contents. |
| 171 delete guest_web_contents; |
| 172 guest_web_contents_by_instance_id_.erase(instance_id); |
| 173 } |
| 174 } |
| 175 |
57 void BrowserPluginEmbedder::GetRenderViewHostAtPosition( | 176 void BrowserPluginEmbedder::GetRenderViewHostAtPosition( |
58 int x, int y, const WebContents::GetRenderViewHostCallback& callback) { | 177 int x, int y, const WebContents::GetRenderViewHostCallback& callback) { |
59 // Store the callback so we can call it later when we have the response. | 178 // Store the callback so we can call it later when we have the response. |
60 pending_get_render_view_callbacks_.insert( | 179 pending_get_render_view_callbacks_.insert( |
61 std::make_pair(next_get_render_view_request_id_, callback)); | 180 std::make_pair(next_get_render_view_request_id_, callback)); |
62 render_view_host_->Send( | 181 render_view_host_->Send( |
63 new BrowserPluginMsg_PluginAtPositionRequest( | 182 new BrowserPluginMsg_PluginAtPositionRequest( |
64 render_view_host_->GetRoutingID(), | 183 render_view_host_->GetRoutingID(), |
65 next_get_render_view_request_id_, | 184 next_get_render_view_request_id_, |
66 gfx::Point(x, y))); | 185 gfx::Point(x, y))); |
(...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
110 case NOTIFICATION_WEB_CONTENTS_VISIBILITY_CHANGED: { | 229 case NOTIFICATION_WEB_CONTENTS_VISIBILITY_CHANGED: { |
111 bool visible = *Details<bool>(details).ptr(); | 230 bool visible = *Details<bool>(details).ptr(); |
112 WebContentsVisibilityChanged(visible); | 231 WebContentsVisibilityChanged(visible); |
113 break; | 232 break; |
114 } | 233 } |
115 default: | 234 default: |
116 NOTREACHED() << "Unexpected notification type: " << type; | 235 NOTREACHED() << "Unexpected notification type: " << type; |
117 } | 236 } |
118 } | 237 } |
119 | 238 |
120 BrowserPluginGuest* BrowserPluginEmbedder::GetGuestByInstanceID( | |
121 int instance_id) const { | |
122 ContainerInstanceMap::const_iterator it = | |
123 guest_web_contents_by_instance_id_.find(instance_id); | |
124 if (it != guest_web_contents_by_instance_id_.end()) | |
125 return static_cast<WebContentsImpl*>(it->second)->GetBrowserPluginGuest(); | |
126 return NULL; | |
127 } | |
128 | |
129 void BrowserPluginEmbedder::AddGuest(int instance_id, | 239 void BrowserPluginEmbedder::AddGuest(int instance_id, |
130 WebContents* guest_web_contents) { | 240 WebContents* guest_web_contents) { |
131 DCHECK(guest_web_contents_by_instance_id_.find(instance_id) == | 241 DCHECK(guest_web_contents_by_instance_id_.find(instance_id) == |
132 guest_web_contents_by_instance_id_.end()); | 242 guest_web_contents_by_instance_id_.end()); |
133 guest_web_contents_by_instance_id_[instance_id] = guest_web_contents; | 243 guest_web_contents_by_instance_id_[instance_id] = guest_web_contents; |
134 } | 244 } |
135 | 245 |
136 void BrowserPluginEmbedder::DestroyGuestByInstanceID(int instance_id) { | |
137 BrowserPluginGuest* guest = GetGuestByInstanceID(instance_id); | |
138 if (guest) { | |
139 WebContents* guest_web_contents = guest->GetWebContents(); | |
140 | |
141 // Destroy the guest's web_contents. | |
142 delete guest_web_contents; | |
143 guest_web_contents_by_instance_id_.erase(instance_id); | |
144 } | |
145 } | |
146 | |
147 void BrowserPluginEmbedder::CleanUp() { | 246 void BrowserPluginEmbedder::CleanUp() { |
148 // Destroy guests that are managed by the current embedder. | 247 // Destroy guests that are managed by the current embedder. |
149 STLDeleteContainerPairSecondPointers( | 248 STLDeleteContainerPairSecondPointers( |
150 guest_web_contents_by_instance_id_.begin(), | 249 guest_web_contents_by_instance_id_.begin(), |
151 guest_web_contents_by_instance_id_.end()); | 250 guest_web_contents_by_instance_id_.end()); |
152 guest_web_contents_by_instance_id_.clear(); | 251 guest_web_contents_by_instance_id_.clear(); |
153 | 252 |
154 // CleanUp gets called when BrowserPluginEmbedder's WebContents goes away | 253 // CleanUp gets called when BrowserPluginEmbedder's WebContents goes away |
155 // or the associated RenderViewHost is destroyed or swapped out. Therefore we | 254 // or the associated RenderViewHost is destroyed or swapped out. Therefore we |
156 // don't need to care about the pending callbacks anymore. | 255 // don't need to care about the pending callbacks anymore. |
(...skipping 30 matching lines...) Expand all Loading... |
187 return true; | 286 return true; |
188 default: | 287 default: |
189 break; | 288 break; |
190 } | 289 } |
191 return false; | 290 return false; |
192 } | 291 } |
193 | 292 |
194 void BrowserPluginEmbedder::OnCreateGuest( | 293 void BrowserPluginEmbedder::OnCreateGuest( |
195 int instance_id, | 294 int instance_id, |
196 const BrowserPluginHostMsg_CreateGuest_Params& params) { | 295 const BrowserPluginHostMsg_CreateGuest_Params& params) { |
197 WebContentsImpl* guest_web_contents = NULL; | 296 CreateGuest(instance_id, MSG_ROUTING_NONE, NULL, params); |
198 BrowserPluginGuest* guest = GetGuestByInstanceID(instance_id); | |
199 CHECK(!guest); | |
200 | |
201 // Validate that the partition id coming from the renderer is valid UTF-8, | |
202 // since we depend on this in other parts of the code, such as FilePath | |
203 // creation. If the validation fails, treat it as a bad message and kill the | |
204 // renderer process. | |
205 if (!IsStringUTF8(params.storage_partition_id)) { | |
206 content::RecordAction(UserMetricsAction("BadMessageTerminate_BPE")); | |
207 base::KillProcess(render_view_host_->GetProcess()->GetHandle(), | |
208 content::RESULT_CODE_KILLED_BAD_MESSAGE, false); | |
209 return; | |
210 } | |
211 | |
212 const std::string& host = | |
213 render_view_host_->GetSiteInstance()->GetSiteURL().host(); | |
214 std::string url_encoded_partition = net::EscapeQueryParamValue( | |
215 params.storage_partition_id, false); | |
216 | |
217 // The SiteInstance of a given webview tag is based on the fact that it's a | |
218 // guest process in addition to which platform application the tag belongs to | |
219 // and what storage partition is in use, rather than the URL that the tag is | |
220 // being navigated to. | |
221 GURL guest_site( | |
222 base::StringPrintf("%s://%s/%s?%s", chrome::kGuestScheme, | |
223 host.c_str(), params.persist_storage ? "persist" : "", | |
224 url_encoded_partition.c_str())); | |
225 | |
226 // If we already have a webview tag in the same app using the same storage | |
227 // partition, we should use the same SiteInstance so the existing tag and | |
228 // the new tag can script each other. | |
229 SiteInstance* guest_site_instance = NULL; | |
230 for (ContainerInstanceMap::const_iterator it = | |
231 guest_web_contents_by_instance_id_.begin(); | |
232 it != guest_web_contents_by_instance_id_.end(); ++it) { | |
233 if (it->second->GetSiteInstance()->GetSiteURL() == guest_site) { | |
234 guest_site_instance = it->second->GetSiteInstance(); | |
235 break; | |
236 } | |
237 } | |
238 if (!guest_site_instance) { | |
239 // Create the SiteInstance in a new BrowsingInstance, which will ensure that | |
240 // webview tags are also not allowed to send messages across different | |
241 // partitions. | |
242 guest_site_instance = SiteInstance::CreateForURL( | |
243 web_contents()->GetBrowserContext(), guest_site); | |
244 } | |
245 | |
246 guest_web_contents = WebContentsImpl::CreateGuest( | |
247 web_contents()->GetBrowserContext(), | |
248 guest_site_instance, | |
249 instance_id, | |
250 params); | |
251 | |
252 guest = guest_web_contents->GetBrowserPluginGuest(); | |
253 guest->set_embedder_web_contents( | |
254 static_cast<WebContentsImpl*>(web_contents())); | |
255 | |
256 RendererPreferences* guest_renderer_prefs = | |
257 guest_web_contents->GetMutableRendererPrefs(); | |
258 // Copy renderer preferences (and nothing else) from the embedder's | |
259 // TabContents to the guest. | |
260 // | |
261 // For GTK and Aura this is necessary to get proper renderer configuration | |
262 // values for caret blinking interval, colors related to selection and | |
263 // focus. | |
264 *guest_renderer_prefs = *web_contents()->GetMutableRendererPrefs(); | |
265 | |
266 guest_renderer_prefs->throttle_input_events = false; | |
267 // Navigation is disabled in Chrome Apps. We want to make sure guest-initiated | |
268 // navigations still continue to function inside the app. | |
269 guest_renderer_prefs->browser_handles_all_top_level_requests = false; | |
270 AddGuest(instance_id, guest_web_contents); | |
271 guest_web_contents->SetDelegate(guest); | |
272 | |
273 // Create a swapped out RenderView for the guest in the embedder render | |
274 // process, so that the embedder can access the guest's window object. | |
275 int guest_routing_id = | |
276 static_cast<WebContentsImpl*>(guest->GetWebContents())-> | |
277 CreateSwappedOutRenderView(web_contents()->GetSiteInstance()); | |
278 render_view_host_->Send(new BrowserPluginMsg_GuestContentWindowReady( | |
279 render_view_host_->GetRoutingID(), instance_id, guest_routing_id)); | |
280 | |
281 guest->Initialize(params, guest_web_contents->GetRenderViewHost()); | |
282 } | 297 } |
283 | 298 |
284 void BrowserPluginEmbedder::OnNavigateGuest( | 299 void BrowserPluginEmbedder::OnNavigateGuest( |
285 int instance_id, | 300 int instance_id, |
286 const std::string& src) { | 301 const std::string& src) { |
287 BrowserPluginGuest* guest = GetGuestByInstanceID(instance_id); | 302 BrowserPluginGuest* guest = GetGuestByInstanceID(instance_id); |
288 CHECK(guest); | 303 CHECK(guest); |
289 GURL url(src); | 304 GURL url(src); |
290 WebContentsImpl* guest_web_contents = | 305 WebContentsImpl* guest_web_contents = |
291 static_cast<WebContentsImpl*>(guest->GetWebContents()); | 306 static_cast<WebContentsImpl*>(guest->GetWebContents()); |
(...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
335 uint32 sync_point) { | 350 uint32 sync_point) { |
336 AcceleratedSurfaceMsg_BufferPresented_Params ack_params; | 351 AcceleratedSurfaceMsg_BufferPresented_Params ack_params; |
337 ack_params.mailbox_name = mailbox_name; | 352 ack_params.mailbox_name = mailbox_name; |
338 ack_params.sync_point = sync_point; | 353 ack_params.sync_point = sync_point; |
339 RenderWidgetHostImpl::AcknowledgeBufferPresent(route_id, | 354 RenderWidgetHostImpl::AcknowledgeBufferPresent(route_id, |
340 gpu_host_id, | 355 gpu_host_id, |
341 ack_params); | 356 ack_params); |
342 } | 357 } |
343 | 358 |
344 } // namespace content | 359 } // namespace content |
OLD | NEW |