OLD | NEW |
---|---|
1 // Copyright (c) 2013 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2013 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_guest_manager.h" | 5 #include "content/browser/browser_plugin/browser_plugin_guest_manager.h" |
6 | 6 |
7 #include "content/browser/browser_plugin/browser_plugin_guest.h" | 7 #include "content/browser/browser_plugin/browser_plugin_guest.h" |
8 #include "content/browser/browser_plugin/browser_plugin_host_factory.h" | 8 #include "content/browser/browser_plugin/browser_plugin_host_factory.h" |
9 #include "content/browser/renderer_host/render_view_host_impl.h" | 9 #include "content/browser/renderer_host/render_view_host_impl.h" |
10 #include "content/browser/web_contents/web_contents_impl.h" | 10 #include "content/browser/web_contents/web_contents_impl.h" |
11 #include "content/common/browser_plugin/browser_plugin_constants.h" | 11 #include "content/common/browser_plugin/browser_plugin_constants.h" |
12 #include "content/common/browser_plugin/browser_plugin_messages.h" | 12 #include "content/common/browser_plugin/browser_plugin_messages.h" |
13 #include "content/common/content_export.h" | 13 #include "content/common/content_export.h" |
14 #include "content/public/browser/browser_context.h" | |
15 #include "content/public/browser/browser_plugin_guest_manager_delegate.h" | |
16 #include "content/public/browser/content_browser_client.h" | |
14 #include "content/public/browser/render_process_host.h" | 17 #include "content/public/browser/render_process_host.h" |
15 #include "content/public/browser/user_metrics.h" | 18 #include "content/public/browser/user_metrics.h" |
19 #include "content/public/common/content_client.h" | |
16 #include "content/public/common/result_codes.h" | 20 #include "content/public/common/result_codes.h" |
17 #include "content/public/common/url_constants.h" | 21 #include "content/public/common/url_constants.h" |
18 #include "content/public/common/url_utils.h" | 22 #include "content/public/common/url_utils.h" |
19 #include "net/base/escape.h" | 23 #include "net/base/escape.h" |
20 | 24 |
21 namespace content { | 25 namespace content { |
22 | 26 |
23 // static | 27 // static |
24 BrowserPluginHostFactory* BrowserPluginGuestManager::factory_ = NULL; | 28 BrowserPluginHostFactory* BrowserPluginGuestManager::factory_ = NULL; |
25 | 29 |
26 BrowserPluginGuestManager::BrowserPluginGuestManager() | 30 BrowserPluginGuestManager::BrowserPluginGuestManager(BrowserContext* context) |
27 : next_instance_id_(browser_plugin::kInstanceIDNone) { | 31 : context_(context) {} |
32 | |
33 BrowserPluginGuestManagerDelegate* | |
34 BrowserPluginGuestManager::GetDelegate() const { | |
35 return GetContentClient()->browser()->GetGuestManagerDelegate(context_); | |
28 } | 36 } |
29 | 37 |
30 BrowserPluginGuestManager::~BrowserPluginGuestManager() { | 38 BrowserPluginGuestManager::~BrowserPluginGuestManager() { |
31 } | 39 } |
32 | 40 |
41 // static. | |
42 BrowserPluginGuestManager* BrowserPluginGuestManager::FromBrowserContext( | |
43 BrowserContext* context) { | |
44 BrowserPluginGuestManager* guest_manager = | |
45 static_cast<BrowserPluginGuestManager*>( | |
46 context->GetUserData( | |
47 browser_plugin::kBrowserPluginGuestManagerKeyName)); | |
48 if (!guest_manager) { | |
49 guest_manager = BrowserPluginGuestManager::Create(context); | |
50 context->SetUserData(browser_plugin::kBrowserPluginGuestManagerKeyName, | |
51 guest_manager); | |
52 } | |
53 return guest_manager; | |
54 } | |
55 | |
33 // static | 56 // static |
34 BrowserPluginGuestManager* BrowserPluginGuestManager::Create() { | 57 BrowserPluginGuestManager* BrowserPluginGuestManager::Create( |
58 BrowserContext* context) { | |
35 if (factory_) | 59 if (factory_) |
36 return factory_->CreateBrowserPluginGuestManager(); | 60 return factory_->CreateBrowserPluginGuestManager(context); |
37 return new BrowserPluginGuestManager(); | 61 return new BrowserPluginGuestManager(context); |
62 } | |
63 | |
64 int BrowserPluginGuestManager::GetNextInstanceID() { | |
65 if (!GetDelegate()) | |
66 return 0; | |
67 return GetDelegate()->GetNextInstanceID(); | |
38 } | 68 } |
39 | 69 |
40 BrowserPluginGuest* BrowserPluginGuestManager::CreateGuest( | 70 BrowserPluginGuest* BrowserPluginGuestManager::CreateGuest( |
41 SiteInstance* embedder_site_instance, | 71 SiteInstance* embedder_site_instance, |
42 int instance_id, | 72 int instance_id, |
43 const BrowserPluginHostMsg_Attach_Params& params, | 73 const BrowserPluginHostMsg_Attach_Params& params, |
44 scoped_ptr<base::DictionaryValue> extra_params) { | 74 scoped_ptr<base::DictionaryValue> extra_params) { |
45 RenderProcessHost* embedder_process_host = | 75 RenderProcessHost* embedder_process_host = |
46 embedder_site_instance->GetProcess(); | 76 embedder_site_instance->GetProcess(); |
47 // Validate that the partition id coming from the renderer is valid UTF-8, | 77 // Validate that the partition id coming from the renderer is valid UTF-8, |
48 // since we depend on this in other parts of the code, such as FilePath | 78 // since we depend on this in other parts of the code, such as FilePath |
49 // creation. If the validation fails, treat it as a bad message and kill the | 79 // creation. If the validation fails, treat it as a bad message and kill the |
50 // renderer process. | 80 // renderer process. |
51 if (!IsStringUTF8(params.storage_partition_id)) { | 81 if (!IsStringUTF8(params.storage_partition_id)) { |
52 content::RecordAction( | 82 content::RecordAction( |
53 base::UserMetricsAction("BadMessageTerminate_BPGM")); | 83 base::UserMetricsAction("BadMessageTerminate_BPGM")); |
54 base::KillProcess( | 84 base::KillProcess( |
55 embedder_process_host->GetHandle(), | 85 embedder_process_host->GetHandle(), |
56 content::RESULT_CODE_KILLED_BAD_MESSAGE, false); | 86 content::RESULT_CODE_KILLED_BAD_MESSAGE, false); |
57 return NULL; | 87 return NULL; |
58 } | 88 } |
59 | 89 |
60 // We usually require BrowserPlugins to be hosted by a storage isolated | 90 // We usually require BrowserPlugins to be hosted by a storage isolated |
61 // extension. We treat WebUI pages as a special case if they host the | 91 // extension. We treat WebUI pages as a special case if they host the |
lazyboy
2014/05/01 20:06:59
This comment is stale now.
Fady Samuel
2014/05/01 21:05:28
Done. I removed the comment entirely.
| |
62 // BrowserPlugin in a component extension iframe. In that case, we use the | 92 // BrowserPlugin in a component extension iframe. In that case, we use the |
63 // iframe's URL to determine the extension. | 93 // iframe's URL to determine the extension. |
64 const GURL& embedder_site_url = embedder_site_instance->GetSiteURL(); | 94 const GURL& embedder_site_url = embedder_site_instance->GetSiteURL(); |
65 GURL validated_frame_url(params.embedder_frame_url); | 95 const std::string& host = embedder_site_url.host(); |
lazyboy
2014/05/01 20:06:59
Is the check for WebUI pages gone b/c of signin pa
Fady Samuel
2014/05/01 21:05:28
Yup. Once BrowserPluginGuestManager::CreateGuest m
| |
66 embedder_process_host->FilterURL(false, &validated_frame_url); | |
67 const std::string& host = content::HasWebUIScheme(embedder_site_url) ? | |
68 validated_frame_url.host() : embedder_site_url.host(); | |
69 | 96 |
70 std::string url_encoded_partition = net::EscapeQueryParamValue( | 97 std::string url_encoded_partition = net::EscapeQueryParamValue( |
71 params.storage_partition_id, false); | 98 params.storage_partition_id, false); |
72 // The SiteInstance of a given webview tag is based on the fact that it's | 99 // The SiteInstance of a given webview tag is based on the fact that it's |
73 // a guest process in addition to which platform application the tag | 100 // a guest process in addition to which platform application the tag |
74 // belongs to and what storage partition is in use, rather than the URL | 101 // belongs to and what storage partition is in use, rather than the URL |
75 // that the tag is being navigated to. | 102 // that the tag is being navigated to. |
76 GURL guest_site(base::StringPrintf("%s://%s/%s?%s", | 103 GURL guest_site(base::StringPrintf("%s://%s/%s?%s", |
77 kGuestScheme, | 104 kGuestScheme, |
78 host.c_str(), | 105 host.c_str(), |
(...skipping 15 matching lines...) Expand all Loading... | |
94 return WebContentsImpl::CreateGuest( | 121 return WebContentsImpl::CreateGuest( |
95 embedder_site_instance->GetBrowserContext(), | 122 embedder_site_instance->GetBrowserContext(), |
96 guest_site_instance, | 123 guest_site_instance, |
97 instance_id, | 124 instance_id, |
98 extra_params.Pass()); | 125 extra_params.Pass()); |
99 } | 126 } |
100 | 127 |
101 BrowserPluginGuest* BrowserPluginGuestManager::GetGuestByInstanceID( | 128 BrowserPluginGuest* BrowserPluginGuestManager::GetGuestByInstanceID( |
102 int instance_id, | 129 int instance_id, |
103 int embedder_render_process_id) const { | 130 int embedder_render_process_id) const { |
104 if (!CanEmbedderAccessInstanceIDMaybeKill(embedder_render_process_id, | 131 if (!GetDelegate()) |
105 instance_id)) { | |
106 return NULL; | 132 return NULL; |
107 } | 133 |
108 GuestInstanceMap::const_iterator it = | 134 WebContentsImpl* guest_web_contents = static_cast<WebContentsImpl*>( |
109 guest_web_contents_by_instance_id_.find(instance_id); | 135 GetDelegate()->GetGuestByInstanceID(instance_id, |
110 if (it == guest_web_contents_by_instance_id_.end()) | 136 embedder_render_process_id)); |
111 return NULL; | 137 |
112 return static_cast<WebContentsImpl*>(it->second)->GetBrowserPluginGuest(); | 138 return guest_web_contents ? |
139 guest_web_contents->GetBrowserPluginGuest() : NULL; | |
113 } | 140 } |
114 | 141 |
115 void BrowserPluginGuestManager::AddGuest(int instance_id, | 142 void BrowserPluginGuestManager::AddGuest(int instance_id, |
116 WebContentsImpl* guest_web_contents) { | 143 WebContents* guest_web_contents) { |
117 DCHECK(guest_web_contents_by_instance_id_.find(instance_id) == | 144 if (!GetDelegate()) |
118 guest_web_contents_by_instance_id_.end()); | 145 return; |
119 guest_web_contents_by_instance_id_[instance_id] = guest_web_contents; | 146 GetDelegate()->AddGuest(instance_id, guest_web_contents); |
120 } | 147 } |
121 | 148 |
122 void BrowserPluginGuestManager::RemoveGuest(int instance_id) { | 149 void BrowserPluginGuestManager::RemoveGuest(int instance_id) { |
123 DCHECK(guest_web_contents_by_instance_id_.find(instance_id) != | 150 if (!GetDelegate()) |
124 guest_web_contents_by_instance_id_.end()); | 151 return; |
125 guest_web_contents_by_instance_id_.erase(instance_id); | 152 GetDelegate()->RemoveGuest(instance_id); |
126 } | 153 } |
127 | 154 |
128 bool BrowserPluginGuestManager::CanEmbedderAccessInstanceIDMaybeKill( | 155 bool BrowserPluginGuestManager::CanEmbedderAccessInstanceIDMaybeKill( |
129 int embedder_render_process_id, | 156 int embedder_render_process_id, |
130 int instance_id) const { | 157 int instance_id) const { |
131 if (!CanEmbedderAccessInstanceID(embedder_render_process_id, instance_id)) { | 158 if (!GetDelegate()) |
132 // The embedder process is trying to access a guest it does not own. | |
133 content::RecordAction( | |
134 base::UserMetricsAction("BadMessageTerminate_BPGM")); | |
135 base::KillProcess( | |
136 RenderProcessHost::FromID(embedder_render_process_id)->GetHandle(), | |
137 content::RESULT_CODE_KILLED_BAD_MESSAGE, false); | |
138 return false; | 159 return false; |
139 } | 160 |
140 return true; | 161 return GetDelegate()->CanEmbedderAccessInstanceIDMaybeKill( |
162 embedder_render_process_id, instance_id); | |
141 } | 163 } |
142 | 164 |
143 void BrowserPluginGuestManager::OnMessageReceived(const IPC::Message& message, | 165 void BrowserPluginGuestManager::OnMessageReceived(const IPC::Message& message, |
144 int render_process_id) { | 166 int render_process_id) { |
145 DCHECK(BrowserPluginGuest::ShouldForwardToBrowserPluginGuest(message)); | 167 DCHECK(BrowserPluginGuest::ShouldForwardToBrowserPluginGuest(message)); |
146 int instance_id = 0; | 168 int instance_id = 0; |
147 // All allowed messages must have instance_id as their first parameter. | 169 // All allowed messages must have instance_id as their first parameter. |
148 PickleIterator iter(message); | 170 PickleIterator iter(message); |
149 bool success = iter.ReadInt(&instance_id); | 171 bool success = iter.ReadInt(&instance_id); |
150 DCHECK(success); | 172 DCHECK(success); |
151 BrowserPluginGuest* guest = | 173 BrowserPluginGuest* guest = |
152 GetGuestByInstanceID(instance_id, render_process_id); | 174 GetGuestByInstanceID(instance_id, render_process_id); |
153 if (!guest) | 175 if (!guest) |
154 return; | 176 return; |
155 guest->OnMessageReceivedFromEmbedder(message); | 177 guest->OnMessageReceivedFromEmbedder(message); |
156 } | 178 } |
157 | 179 |
158 // static | |
159 bool BrowserPluginGuestManager::CanEmbedderAccessGuest( | |
160 int embedder_render_process_id, | |
161 BrowserPluginGuest* guest) { | |
162 // The embedder can access the guest if it has not been attached and its | |
163 // opener's embedder lives in the same process as the given embedder. | |
164 if (!guest->attached()) { | |
165 if (!guest->opener()) | |
166 return false; | |
167 | |
168 return embedder_render_process_id == | |
169 guest->opener()->embedder_web_contents()->GetRenderProcessHost()-> | |
170 GetID(); | |
171 } | |
172 | |
173 return embedder_render_process_id == | |
174 guest->embedder_web_contents()->GetRenderProcessHost()->GetID(); | |
175 } | |
176 | |
177 bool BrowserPluginGuestManager::CanEmbedderAccessInstanceID( | |
178 int embedder_render_process_id, | |
179 int instance_id) const { | |
180 // The embedder is trying to access a guest with a negative or zero | |
181 // instance ID. | |
182 if (instance_id <= browser_plugin::kInstanceIDNone) | |
183 return false; | |
184 | |
185 // The embedder is trying to access an instance ID that has not yet been | |
186 // allocated by BrowserPluginGuestManager. This could cause instance ID | |
187 // collisions in the future, and potentially give one embedder access to a | |
188 // guest it does not own. | |
189 if (instance_id > next_instance_id_) | |
190 return false; | |
191 | |
192 GuestInstanceMap::const_iterator it = | |
193 guest_web_contents_by_instance_id_.find(instance_id); | |
194 if (it == guest_web_contents_by_instance_id_.end()) | |
195 return true; | |
196 BrowserPluginGuest* guest = | |
197 static_cast<WebContentsImpl*>(it->second)->GetBrowserPluginGuest(); | |
198 | |
199 return CanEmbedderAccessGuest(embedder_render_process_id, guest); | |
200 } | |
201 | |
202 SiteInstance* BrowserPluginGuestManager::GetGuestSiteInstance( | 180 SiteInstance* BrowserPluginGuestManager::GetGuestSiteInstance( |
203 const GURL& guest_site) { | 181 const GURL& guest_site) { |
204 for (GuestInstanceMap::const_iterator it = | 182 if (!GetDelegate()) |
205 guest_web_contents_by_instance_id_.begin(); | 183 return NULL; |
206 it != guest_web_contents_by_instance_id_.end(); ++it) { | 184 return GetDelegate()->GetGuestSiteInstance(guest_site); |
207 if (it->second->GetSiteInstance()->GetSiteURL() == guest_site) | 185 } |
208 return it->second->GetSiteInstance(); | 186 |
209 } | 187 static bool BrowserPluginGuestCallback( |
210 return NULL; | 188 const BrowserPluginGuestManager::GuestCallback& callback, |
189 WebContents* guest_web_contents) { | |
190 return callback.Run(static_cast<WebContentsImpl*>(guest_web_contents) | |
191 ->GetBrowserPluginGuest()); | |
211 } | 192 } |
212 | 193 |
213 bool BrowserPluginGuestManager::ForEachGuest( | 194 bool BrowserPluginGuestManager::ForEachGuest( |
214 WebContentsImpl* embedder_web_contents, const GuestCallback& callback) { | 195 WebContents* embedder_web_contents, const GuestCallback& callback) { |
215 for (GuestInstanceMap::iterator it = | 196 if (!GetDelegate()) |
216 guest_web_contents_by_instance_id_.begin(); | 197 return false; |
217 it != guest_web_contents_by_instance_id_.end(); ++it) { | 198 return GetDelegate()->ForEachGuest(embedder_web_contents, |
218 BrowserPluginGuest* guest = it->second->GetBrowserPluginGuest(); | 199 base::Bind(&BrowserPluginGuestCallback, |
219 if (embedder_web_contents != guest->embedder_web_contents()) | 200 callback)); |
220 continue; | 201 } |
221 | 202 |
222 if (callback.Run(guest)) | 203 void BrowserPluginGuestManager::RequestInstanceID( |
223 return true; | 204 const std::string& src, |
205 const InstanceIDResponseCallback& callback) { | |
206 if (!GetDelegate()) { | |
207 callback.Run(0); | |
208 return; | |
224 } | 209 } |
225 return false; | 210 GetDelegate()->RequestInstanceID(src, callback); |
226 } | 211 } |
227 | 212 |
228 } // namespace content | 213 } // namespace content |
OLD | NEW |