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(); | |
Charlie Reis
2013/01/04 18:53:19
Yep, this looks right. This will ensure the new g
Fady Samuel
2013/01/08 17:00:49
OK
| |
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* base_web_contents = static_cast<WebContentsImpl*>( | |
Charlie Reis
2013/01/04 18:53:19
What does base mean? Might be clearer to call thi
Fady Samuel
2013/01/08 17:00:49
Done.
| |
115 guest_opener ? guest_opener->GetWebContents() : NULL); | |
116 guest_web_contents = WebContentsImpl::CreateGuest( | |
117 web_contents()->GetBrowserContext(), | |
sadrul
2013/01/07 15:09:54
Should you be using the browser-context of opener_
Fady Samuel
2013/01/08 17:00:49
This is the embedder's BrowserContext. All guests
Charlie Reis
2013/01/08 21:13:52
The BrowserContext is the part of Profile that liv
| |
118 guest_site_instance, | |
119 routing_id, | |
120 base_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 // If this guest was created by another guest, then don't initialize it yet as | |
154 // it has not yet necessarily been attached to a BrowserPlugin. | |
Charlie Reis
2013/01/04 18:53:19
The comment makes it sound like we should be check
Fady Samuel
2013/01/08 17:00:49
This is a bad comment. Thanks for catching this! A
| |
155 guest->Initialize(params, guest_web_contents->GetRenderViewHost()); | |
156 } | |
157 | |
158 BrowserPluginGuest* BrowserPluginEmbedder::GetGuestByInstanceID( | |
159 int instance_id) const { | |
160 ContainerInstanceMap::const_iterator it = | |
161 guest_web_contents_by_instance_id_.find(instance_id); | |
162 if (it != guest_web_contents_by_instance_id_.end()) | |
163 return static_cast<WebContentsImpl*>(it->second)->GetBrowserPluginGuest(); | |
164 return NULL; | |
165 } | |
166 | |
167 void BrowserPluginEmbedder::DestroyGuestByInstanceID(int instance_id) { | |
168 BrowserPluginGuest* guest = GetGuestByInstanceID(instance_id); | |
169 if (guest) { | |
170 WebContents* guest_web_contents = guest->GetWebContents(); | |
171 | |
172 // Destroy the guest's web_contents. | |
173 delete guest_web_contents; | |
174 guest_web_contents_by_instance_id_.erase(instance_id); | |
175 } | |
176 } | |
177 | |
57 void BrowserPluginEmbedder::GetRenderViewHostAtPosition( | 178 void BrowserPluginEmbedder::GetRenderViewHostAtPosition( |
58 int x, int y, const WebContents::GetRenderViewHostCallback& callback) { | 179 int x, int y, const WebContents::GetRenderViewHostCallback& callback) { |
59 // Store the callback so we can call it later when we have the response. | 180 // Store the callback so we can call it later when we have the response. |
60 pending_get_render_view_callbacks_.insert( | 181 pending_get_render_view_callbacks_.insert( |
61 std::make_pair(next_get_render_view_request_id_, callback)); | 182 std::make_pair(next_get_render_view_request_id_, callback)); |
62 render_view_host_->Send( | 183 render_view_host_->Send( |
63 new BrowserPluginMsg_PluginAtPositionRequest( | 184 new BrowserPluginMsg_PluginAtPositionRequest( |
64 render_view_host_->GetRoutingID(), | 185 render_view_host_->GetRoutingID(), |
65 next_get_render_view_request_id_, | 186 next_get_render_view_request_id_, |
66 gfx::Point(x, y))); | 187 gfx::Point(x, y))); |
(...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
110 case NOTIFICATION_WEB_CONTENTS_VISIBILITY_CHANGED: { | 231 case NOTIFICATION_WEB_CONTENTS_VISIBILITY_CHANGED: { |
111 bool visible = *Details<bool>(details).ptr(); | 232 bool visible = *Details<bool>(details).ptr(); |
112 WebContentsVisibilityChanged(visible); | 233 WebContentsVisibilityChanged(visible); |
113 break; | 234 break; |
114 } | 235 } |
115 default: | 236 default: |
116 NOTREACHED() << "Unexpected notification type: " << type; | 237 NOTREACHED() << "Unexpected notification type: " << type; |
117 } | 238 } |
118 } | 239 } |
119 | 240 |
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, | 241 void BrowserPluginEmbedder::AddGuest(int instance_id, |
130 WebContents* guest_web_contents) { | 242 WebContents* guest_web_contents) { |
131 DCHECK(guest_web_contents_by_instance_id_.find(instance_id) == | 243 DCHECK(guest_web_contents_by_instance_id_.find(instance_id) == |
132 guest_web_contents_by_instance_id_.end()); | 244 guest_web_contents_by_instance_id_.end()); |
133 guest_web_contents_by_instance_id_[instance_id] = guest_web_contents; | 245 guest_web_contents_by_instance_id_[instance_id] = guest_web_contents; |
134 } | 246 } |
135 | 247 |
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() { | 248 void BrowserPluginEmbedder::CleanUp() { |
148 // Destroy guests that are managed by the current embedder. | 249 // Destroy guests that are managed by the current embedder. |
149 STLDeleteContainerPairSecondPointers( | 250 STLDeleteContainerPairSecondPointers( |
150 guest_web_contents_by_instance_id_.begin(), | 251 guest_web_contents_by_instance_id_.begin(), |
151 guest_web_contents_by_instance_id_.end()); | 252 guest_web_contents_by_instance_id_.end()); |
152 guest_web_contents_by_instance_id_.clear(); | 253 guest_web_contents_by_instance_id_.clear(); |
153 | 254 |
154 // CleanUp gets called when BrowserPluginEmbedder's WebContents goes away | 255 // CleanUp gets called when BrowserPluginEmbedder's WebContents goes away |
155 // or the associated RenderViewHost is destroyed or swapped out. Therefore we | 256 // or the associated RenderViewHost is destroyed or swapped out. Therefore we |
156 // don't need to care about the pending callbacks anymore. | 257 // don't need to care about the pending callbacks anymore. |
(...skipping 30 matching lines...) Expand all Loading... | |
187 return true; | 288 return true; |
188 default: | 289 default: |
189 break; | 290 break; |
190 } | 291 } |
191 return false; | 292 return false; |
192 } | 293 } |
193 | 294 |
194 void BrowserPluginEmbedder::OnCreateGuest( | 295 void BrowserPluginEmbedder::OnCreateGuest( |
195 int instance_id, | 296 int instance_id, |
196 const BrowserPluginHostMsg_CreateGuest_Params& params) { | 297 const BrowserPluginHostMsg_CreateGuest_Params& params) { |
197 WebContentsImpl* guest_web_contents = NULL; | 298 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 } | 299 } |
283 | 300 |
284 void BrowserPluginEmbedder::OnNavigateGuest( | 301 void BrowserPluginEmbedder::OnNavigateGuest( |
285 int instance_id, | 302 int instance_id, |
286 const std::string& src) { | 303 const std::string& src) { |
287 BrowserPluginGuest* guest = GetGuestByInstanceID(instance_id); | 304 BrowserPluginGuest* guest = GetGuestByInstanceID(instance_id); |
288 CHECK(guest); | 305 CHECK(guest); |
289 GURL url(src); | 306 GURL url(src); |
290 WebContentsImpl* guest_web_contents = | 307 WebContentsImpl* guest_web_contents = |
291 static_cast<WebContentsImpl*>(guest->GetWebContents()); | 308 static_cast<WebContentsImpl*>(guest->GetWebContents()); |
(...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
335 uint32 sync_point) { | 352 uint32 sync_point) { |
336 AcceleratedSurfaceMsg_BufferPresented_Params ack_params; | 353 AcceleratedSurfaceMsg_BufferPresented_Params ack_params; |
337 ack_params.mailbox_name = mailbox_name; | 354 ack_params.mailbox_name = mailbox_name; |
338 ack_params.sync_point = sync_point; | 355 ack_params.sync_point = sync_point; |
339 RenderWidgetHostImpl::AcknowledgeBufferPresent(route_id, | 356 RenderWidgetHostImpl::AcknowledgeBufferPresent(route_id, |
340 gpu_host_id, | 357 gpu_host_id, |
341 ack_params); | 358 ack_params); |
342 } | 359 } |
343 | 360 |
344 } // namespace content | 361 } // namespace content |
OLD | NEW |