| OLD | NEW |
| 1 // Copyright 2014 The Chromium Authors. All rights reserved. | 1 // Copyright 2014 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 "chrome/browser/guest_view/guest_view_manager.h" | 5 #include "chrome/browser/guest_view/guest_view_manager.h" |
| 6 | 6 |
| 7 #include "base/strings/stringprintf.h" | 7 #include "base/strings/stringprintf.h" |
| 8 #include "chrome/browser/extensions/extension_service.h" | 8 #include "chrome/browser/extensions/extension_service.h" |
| 9 #include "chrome/browser/guest_view/guest_view_base.h" | 9 #include "chrome/browser/guest_view/guest_view_base.h" |
| 10 #include "chrome/browser/guest_view/guest_view_constants.h" | 10 #include "chrome/browser/guest_view/guest_view_constants.h" |
| (...skipping 48 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 59 return NULL; | 59 return NULL; |
| 60 } | 60 } |
| 61 return GetGuestByInstanceID(guest_instance_id, embedder_render_process_id); | 61 return GetGuestByInstanceID(guest_instance_id, embedder_render_process_id); |
| 62 } | 62 } |
| 63 | 63 |
| 64 int GuestViewManager::GetNextInstanceID() { | 64 int GuestViewManager::GetNextInstanceID() { |
| 65 return ++current_instance_id_; | 65 return ++current_instance_id_; |
| 66 } | 66 } |
| 67 | 67 |
| 68 content::WebContents* GuestViewManager::CreateGuest( | 68 content::WebContents* GuestViewManager::CreateGuest( |
| 69 content::SiteInstance* embedder_site_instance, | 69 const std::string& view_type, |
| 70 int instance_id, | 70 const std::string& embedder_extension_id, |
| 71 scoped_ptr<base::DictionaryValue> extra_params) { | 71 int embedder_render_process_id, |
| 72 std::string storage_partition_id; | 72 const base::DictionaryValue& create_params) { |
| 73 bool persist_storage = false; | 73 int guest_instance_id = GetNextInstanceID(); |
| 74 std::string storage_partition_string; | 74 GuestViewBase* guest = GuestViewBase::Create(guest_instance_id, view_type); |
| 75 WebViewGuest::ParsePartitionParam( | 75 if (!guest) |
| 76 extra_params.get(), &storage_partition_id, &persist_storage); | 76 return NULL; |
| 77 guest->Init(embedder_extension_id, |
| 78 embedder_render_process_id, |
| 79 create_params); |
| 80 return guest->guest_web_contents(); |
| 81 } |
| 77 | 82 |
| 78 content::RenderProcessHost* embedder_process_host = | 83 content::WebContents* GuestViewManager::CreateGuestWithWebContentsParams( |
| 79 embedder_site_instance->GetProcess(); | 84 const std::string& view_type, |
| 80 // Validate that the partition id coming from the renderer is valid UTF-8, | 85 const std::string& embedder_extension_id, |
| 81 // since we depend on this in other parts of the code, such as FilePath | 86 int embedder_render_process_id, |
| 82 // creation. If the validation fails, treat it as a bad message and kill the | 87 const content::WebContents::CreateParams& create_params) { |
| 83 // renderer process. | 88 int guest_instance_id = GetNextInstanceID(); |
| 84 if (!base::IsStringUTF8(storage_partition_id)) { | 89 GuestViewBase* guest = GuestViewBase::Create(guest_instance_id, view_type); |
| 85 content::RecordAction( | 90 if (!guest) |
| 86 base::UserMetricsAction("BadMessageTerminate_BPGM")); | |
| 87 base::KillProcess( | |
| 88 embedder_process_host->GetHandle(), | |
| 89 content::RESULT_CODE_KILLED_BAD_MESSAGE, false); | |
| 90 return NULL; | 91 return NULL; |
| 91 } | 92 content::WebContents::CreateParams guest_create_params(create_params); |
| 92 | 93 guest_create_params.guest_delegate = guest; |
| 93 const GURL& embedder_site_url = embedder_site_instance->GetSiteURL(); | 94 content::WebContents* guest_web_contents = |
| 94 const std::string& host = embedder_site_url.host(); | 95 WebContents::Create(guest_create_params); |
| 95 | 96 guest->InitWithWebContents(embedder_extension_id, |
| 96 std::string url_encoded_partition = net::EscapeQueryParamValue( | 97 embedder_render_process_id, |
| 97 storage_partition_id, false); | 98 guest_web_contents); |
| 98 // The SiteInstance of a given webview tag is based on the fact that it's | 99 return guest_web_contents; |
| 99 // a guest process in addition to which platform application the tag | |
| 100 // belongs to and what storage partition is in use, rather than the URL | |
| 101 // that the tag is being navigated to. | |
| 102 GURL guest_site(base::StringPrintf("%s://%s/%s?%s", | |
| 103 content::kGuestScheme, | |
| 104 host.c_str(), | |
| 105 persist_storage ? "persist" : "", | |
| 106 url_encoded_partition.c_str())); | |
| 107 | |
| 108 // If we already have a webview tag in the same app using the same storage | |
| 109 // partition, we should use the same SiteInstance so the existing tag and | |
| 110 // the new tag can script each other. | |
| 111 SiteInstance* guest_site_instance = GetGuestSiteInstance(guest_site); | |
| 112 if (!guest_site_instance) { | |
| 113 // Create the SiteInstance in a new BrowsingInstance, which will ensure | |
| 114 // that webview tags are also not allowed to send messages across | |
| 115 // different partitions. | |
| 116 guest_site_instance = SiteInstance::CreateForURL( | |
| 117 embedder_site_instance->GetBrowserContext(), guest_site); | |
| 118 } | |
| 119 WebContents::CreateParams create_params( | |
| 120 embedder_site_instance->GetBrowserContext(), | |
| 121 guest_site_instance); | |
| 122 create_params.guest_instance_id = instance_id; | |
| 123 create_params.guest_extra_params.reset(extra_params.release()); | |
| 124 return WebContents::Create(create_params); | |
| 125 } | 100 } |
| 126 | 101 |
| 127 void GuestViewManager::MaybeGetGuestByInstanceIDOrKill( | 102 void GuestViewManager::MaybeGetGuestByInstanceIDOrKill( |
| 128 int guest_instance_id, | 103 int guest_instance_id, |
| 129 int embedder_render_process_id, | 104 int embedder_render_process_id, |
| 130 const GuestByInstanceIDCallback& callback) { | 105 const GuestByInstanceIDCallback& callback) { |
| 131 if (!CanEmbedderAccessInstanceIDMaybeKill(embedder_render_process_id, | 106 if (!CanEmbedderAccessInstanceIDMaybeKill(embedder_render_process_id, |
| 132 guest_instance_id)) { | 107 guest_instance_id)) { |
| 133 // If we kill the embedder, then don't bother calling back. | 108 // If we kill the embedder, then don't bother calling back. |
| 134 return; | 109 return; |
| (...skipping 108 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 243 if (guest_instance_id <= guestview::kInstanceIDNone) | 218 if (guest_instance_id <= guestview::kInstanceIDNone) |
| 244 return false; | 219 return false; |
| 245 | 220 |
| 246 // The embedder is trying to access an instance ID that has not yet been | 221 // The embedder is trying to access an instance ID that has not yet been |
| 247 // allocated by GuestViewManager. This could cause instance ID | 222 // allocated by GuestViewManager. This could cause instance ID |
| 248 // collisions in the future, and potentially give one embedder access to a | 223 // collisions in the future, and potentially give one embedder access to a |
| 249 // guest it does not own. | 224 // guest it does not own. |
| 250 if (guest_instance_id > current_instance_id_) | 225 if (guest_instance_id > current_instance_id_) |
| 251 return false; | 226 return false; |
| 252 | 227 |
| 228 // We might get some late arriving messages at tear down. Let's let the |
| 229 // embedder tear down in peace. |
| 253 GuestInstanceMap::const_iterator it = | 230 GuestInstanceMap::const_iterator it = |
| 254 guest_web_contents_by_instance_id_.find(guest_instance_id); | 231 guest_web_contents_by_instance_id_.find(guest_instance_id); |
| 255 if (it == guest_web_contents_by_instance_id_.end()) | 232 if (it == guest_web_contents_by_instance_id_.end()) |
| 256 return true; | 233 return true; |
| 257 | 234 |
| 258 GuestViewBase* guest_view = GuestViewBase::FromWebContents(it->second); | 235 GuestViewBase* guest_view = GuestViewBase::FromWebContents(it->second); |
| 259 if (!guest_view) | 236 if (!guest_view) |
| 260 return false; | 237 return false; |
| 261 | 238 |
| 262 return CanEmbedderAccessGuest(embedder_render_process_id, guest_view); | 239 return embedder_render_process_id == guest_view->embedder_render_process_id(); |
| 263 } | 240 } |
| 264 | |
| 265 bool GuestViewManager::CanEmbedderAccessGuest(int embedder_render_process_id, | |
| 266 GuestViewBase* guest) { | |
| 267 // The embedder can access the guest if it has not been attached and its | |
| 268 // opener's embedder lives in the same process as the given embedder. | |
| 269 if (!guest->attached()) { | |
| 270 if (!guest->GetOpener()) | |
| 271 return false; | |
| 272 | |
| 273 return embedder_render_process_id == | |
| 274 guest->GetOpener()->embedder_web_contents()->GetRenderProcessHost()-> | |
| 275 GetID(); | |
| 276 } | |
| 277 | |
| 278 return embedder_render_process_id == | |
| 279 guest->embedder_web_contents()->GetRenderProcessHost()->GetID(); | |
| 280 } | |
| OLD | NEW |