Remove unused parameter.
[chromium-blink-merge.git] / extensions / browser / guest_view / guest_view_manager.cc
blobb7ddae913cb8c7fbf2a050471b3d5b70b9b56817
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
3 // found in the LICENSE file.
5 #include "extensions/browser/guest_view/guest_view_manager.h"
7 #include "base/strings/stringprintf.h"
8 #include "content/public/browser/browser_context.h"
9 #include "content/public/browser/render_frame_host.h"
10 #include "content/public/browser/render_process_host.h"
11 #include "content/public/browser/render_view_host.h"
12 #include "content/public/browser/user_metrics.h"
13 #include "content/public/browser/web_contents_observer.h"
14 #include "content/public/common/child_process_host.h"
15 #include "content/public/common/result_codes.h"
16 #include "content/public/common/url_constants.h"
17 #include "extensions/browser/extension_system.h"
18 #include "extensions/browser/guest_view/guest_view_base.h"
19 #include "extensions/browser/guest_view/guest_view_manager_factory.h"
20 #include "extensions/common/extension_messages.h"
21 #include "extensions/common/guest_view/guest_view_constants.h"
22 #include "net/base/escape.h"
23 #include "url/gurl.h"
25 using content::BrowserContext;
26 using content::SiteInstance;
27 using content::WebContents;
29 namespace extensions {
31 // static
32 GuestViewManagerFactory* GuestViewManager::factory_ = nullptr;
34 GuestViewManager::GuestViewManager(content::BrowserContext* context)
35 : current_instance_id_(0), last_instance_id_removed_(0), context_(context) {
38 GuestViewManager::~GuestViewManager() {}
40 // static
41 GuestViewManager* GuestViewManager::FromBrowserContext(
42 BrowserContext* context) {
43 GuestViewManager* guest_manager =
44 static_cast<GuestViewManager*>(context->GetUserData(
45 guestview::kGuestViewManagerKeyName));
46 if (!guest_manager) {
47 if (factory_) {
48 guest_manager = factory_->CreateGuestViewManager(context);
49 } else {
50 guest_manager = new GuestViewManager(context);
52 context->SetUserData(guestview::kGuestViewManagerKeyName, guest_manager);
54 return guest_manager;
57 // static
58 GuestViewManager* GuestViewManager::FromBrowserContextIfAvailable(
59 BrowserContext* context) {
60 return static_cast<GuestViewManager*>(context->GetUserData(
61 guestview::kGuestViewManagerKeyName));
64 content::WebContents* GuestViewManager::GetGuestByInstanceIDSafely(
65 int guest_instance_id,
66 int embedder_render_process_id) {
67 if (!CanEmbedderAccessInstanceIDMaybeKill(embedder_render_process_id,
68 guest_instance_id)) {
69 return nullptr;
71 return GetGuestByInstanceID(guest_instance_id);
74 void GuestViewManager::AttachGuest(int embedder_process_id,
75 int element_instance_id,
76 int guest_instance_id,
77 const base::DictionaryValue& attach_params) {
78 auto guest_view = GuestViewBase::From(embedder_process_id, guest_instance_id);
79 if (!guest_view)
80 return;
82 ElementInstanceKey key(embedder_process_id, element_instance_id);
83 auto it = instance_id_map_.find(key);
84 // If there is an existing guest attached to the element, then destroy the
85 // existing guest.
86 if (it != instance_id_map_.end()) {
87 int old_guest_instance_id = it->second;
88 if (old_guest_instance_id == guest_instance_id)
89 return;
91 auto old_guest_view = GuestViewBase::From(embedder_process_id,
92 old_guest_instance_id);
93 old_guest_view->Destroy();
95 instance_id_map_[key] = guest_instance_id;
96 reverse_instance_id_map_[guest_instance_id] = key;
97 guest_view->SetAttachParams(attach_params);
100 void GuestViewManager::DetachGuest(GuestViewBase* guest) {
101 if (!guest->attached())
102 return;
104 auto reverse_it = reverse_instance_id_map_.find(guest->guest_instance_id());
105 if (reverse_it == reverse_instance_id_map_.end())
106 return;
108 const ElementInstanceKey& key = reverse_it->second;
110 auto it = instance_id_map_.find(key);
111 DCHECK(it != instance_id_map_.end());
113 reverse_instance_id_map_.erase(reverse_it);
114 instance_id_map_.erase(it);
117 int GuestViewManager::GetNextInstanceID() {
118 return ++current_instance_id_;
121 void GuestViewManager::CreateGuest(const std::string& view_type,
122 content::WebContents* owner_web_contents,
123 const base::DictionaryValue& create_params,
124 const WebContentsCreatedCallback& callback) {
125 auto guest = GuestViewBase::Create(owner_web_contents, view_type);
126 if (!guest) {
127 callback.Run(nullptr);
128 return;
130 guest->Init(create_params, callback);
133 content::WebContents* GuestViewManager::CreateGuestWithWebContentsParams(
134 const std::string& view_type,
135 content::WebContents* owner_web_contents,
136 const content::WebContents::CreateParams& create_params) {
137 auto guest = GuestViewBase::Create(owner_web_contents, view_type);
138 if (!guest)
139 return nullptr;
140 content::WebContents::CreateParams guest_create_params(create_params);
141 guest_create_params.guest_delegate = guest;
142 auto guest_web_contents = WebContents::Create(guest_create_params);
143 guest->InitWithWebContents(base::DictionaryValue(), guest_web_contents);
144 return guest_web_contents;
147 content::WebContents* GuestViewManager::GetGuestByInstanceID(
148 int owner_process_id,
149 int element_instance_id) {
150 int guest_instance_id = GetGuestInstanceIDForElementID(owner_process_id,
151 element_instance_id);
152 if (guest_instance_id == guestview::kInstanceIDNone)
153 return nullptr;
155 return GetGuestByInstanceID(guest_instance_id);
158 int GuestViewManager::GetGuestInstanceIDForElementID(int owner_process_id,
159 int element_instance_id) {
160 auto iter = instance_id_map_.find(
161 ElementInstanceKey(owner_process_id, element_instance_id));
162 if (iter == instance_id_map_.end())
163 return guestview::kInstanceIDNone;
164 return iter->second;
167 SiteInstance* GuestViewManager::GetGuestSiteInstance(
168 const GURL& guest_site) {
169 for (const auto& guest : guest_web_contents_by_instance_id_) {
170 if (guest.second->GetSiteInstance()->GetSiteURL() == guest_site)
171 return guest.second->GetSiteInstance();
173 return nullptr;
176 bool GuestViewManager::ForEachGuest(WebContents* owner_web_contents,
177 const GuestCallback& callback) {
178 for (const auto& guest : guest_web_contents_by_instance_id_) {
179 auto guest_view = GuestViewBase::FromWebContents(guest.second);
180 if (guest_view->owner_web_contents() != owner_web_contents)
181 continue;
183 if (callback.Run(guest_view->web_contents()))
184 return true;
186 return false;
189 void GuestViewManager::AddGuest(int guest_instance_id,
190 WebContents* guest_web_contents) {
191 CHECK(!ContainsKey(guest_web_contents_by_instance_id_, guest_instance_id));
192 CHECK(CanUseGuestInstanceID(guest_instance_id));
193 guest_web_contents_by_instance_id_[guest_instance_id] = guest_web_contents;
196 void GuestViewManager::RemoveGuest(int guest_instance_id) {
197 auto it = guest_web_contents_by_instance_id_.find(guest_instance_id);
198 DCHECK(it != guest_web_contents_by_instance_id_.end());
199 guest_web_contents_by_instance_id_.erase(it);
201 auto id_iter = reverse_instance_id_map_.find(guest_instance_id);
202 if (id_iter != reverse_instance_id_map_.end()) {
203 const ElementInstanceKey& instance_id_key = id_iter->second;
204 instance_id_map_.erase(instance_id_map_.find(instance_id_key));
205 reverse_instance_id_map_.erase(id_iter);
208 // All the instance IDs that lie within [0, last_instance_id_removed_]
209 // are invalid.
210 // The remaining sparse invalid IDs are kept in |removed_instance_ids_| set.
211 // The following code compacts the set by incrementing
212 // |last_instance_id_removed_|.
213 if (guest_instance_id == last_instance_id_removed_ + 1) {
214 ++last_instance_id_removed_;
215 // Compact.
216 auto iter = removed_instance_ids_.begin();
217 while (iter != removed_instance_ids_.end()) {
218 int instance_id = *iter;
219 // The sparse invalid IDs must not lie within
220 // [0, last_instance_id_removed_]
221 DCHECK(instance_id > last_instance_id_removed_);
222 if (instance_id != last_instance_id_removed_ + 1)
223 break;
224 ++last_instance_id_removed_;
225 removed_instance_ids_.erase(iter++);
227 } else {
228 removed_instance_ids_.insert(guest_instance_id);
232 content::WebContents* GuestViewManager::GetGuestByInstanceID(
233 int guest_instance_id) {
234 auto it = guest_web_contents_by_instance_id_.find(guest_instance_id);
235 if (it == guest_web_contents_by_instance_id_.end())
236 return nullptr;
237 return it->second;
240 bool GuestViewManager::CanEmbedderAccessInstanceIDMaybeKill(
241 int embedder_render_process_id,
242 int guest_instance_id) {
243 if (!CanEmbedderAccessInstanceID(embedder_render_process_id,
244 guest_instance_id)) {
245 // The embedder process is trying to access a guest it does not own.
246 content::RecordAction(
247 base::UserMetricsAction("BadMessageTerminate_BPGM"));
248 content::RenderProcessHost::FromID(embedder_render_process_id)
249 ->Shutdown(content::RESULT_CODE_KILLED_BAD_MESSAGE, false);
250 return false;
252 return true;
255 bool GuestViewManager::CanUseGuestInstanceID(int guest_instance_id) {
256 if (guest_instance_id <= last_instance_id_removed_)
257 return false;
258 return !ContainsKey(removed_instance_ids_, guest_instance_id);
261 bool GuestViewManager::CanEmbedderAccessInstanceID(
262 int embedder_render_process_id,
263 int guest_instance_id) {
264 // The embedder is trying to access a guest with a negative or zero
265 // instance ID.
266 if (guest_instance_id <= guestview::kInstanceIDNone)
267 return false;
269 // The embedder is trying to access an instance ID that has not yet been
270 // allocated by GuestViewManager. This could cause instance ID
271 // collisions in the future, and potentially give one embedder access to a
272 // guest it does not own.
273 if (guest_instance_id > current_instance_id_)
274 return false;
276 // We might get some late arriving messages at tear down. Let's let the
277 // embedder tear down in peace.
278 auto it = guest_web_contents_by_instance_id_.find(guest_instance_id);
279 if (it == guest_web_contents_by_instance_id_.end())
280 return true;
282 auto guest_view = GuestViewBase::FromWebContents(it->second);
283 if (!guest_view)
284 return false;
286 return embedder_render_process_id ==
287 guest_view->owner_web_contents()->GetRenderProcessHost()->GetID();
290 GuestViewManager::ElementInstanceKey::ElementInstanceKey()
291 : embedder_process_id(content::ChildProcessHost::kInvalidUniqueID),
292 element_instance_id(content::ChildProcessHost::kInvalidUniqueID) {
295 GuestViewManager::ElementInstanceKey::ElementInstanceKey(
296 int embedder_process_id,
297 int element_instance_id)
298 : embedder_process_id(embedder_process_id),
299 element_instance_id(element_instance_id) {
302 bool GuestViewManager::ElementInstanceKey::operator<(
303 const GuestViewManager::ElementInstanceKey& other) const {
304 if (embedder_process_id != other.embedder_process_id)
305 return embedder_process_id < other.embedder_process_id;
307 return element_instance_id < other.element_instance_id;
310 bool GuestViewManager::ElementInstanceKey::operator==(
311 const GuestViewManager::ElementInstanceKey& other) const {
312 return (embedder_process_id == other.embedder_process_id) &&
313 (element_instance_id == other.element_instance_id);
316 } // namespace extensions