Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(31)

Side by Side Diff: chrome/browser/guest_view/guest_view_manager.cc

Issue 258373002: Towards moving guest management to chrome: Introduce GuestViewManager (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Merge with ToT Created 6 years, 7 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
(Empty)
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.
4
5 #include "chrome/browser/guest_view/guest_view_manager.h"
6
7 #include "chrome/browser/extensions/extension_service.h"
8 #include "chrome/browser/guest_view/guest_view_base.h"
9 #include "chrome/browser/guest_view/guest_view_constants.h"
10 #include "chrome/browser/profiles/profile.h"
11 #include "content/public/browser/browser_context.h"
12 #include "content/public/browser/render_process_host.h"
13 #include "content/public/browser/user_metrics.h"
14 #include "content/public/browser/web_contents_observer.h"
15 #include "content/public/common/result_codes.h"
16 #include "extensions/browser/extension_system.h"
17 #include "url/gurl.h"
18
19 using content::BrowserContext;
20 using content::SiteInstance;
21 using content::WebContents;
22
23 // A WebContents does not immediately have a RenderProcessHost. It acquires one
24 // on initial navigation. This observer exists until that initial navigation in
25 // order to grab the ID if tis RenderProcessHost so that it can register it as
26 // a guest.
27 class GuestWebContentsObserver
28 : public content::WebContentsObserver {
29 public:
30 explicit GuestWebContentsObserver(WebContents* guest_web_contents)
31 : WebContentsObserver(guest_web_contents) {
32 }
33
34 virtual ~GuestWebContentsObserver() {
35 }
36
37 // WebContentsObserver:
38 virtual void DidStartProvisionalLoadForFrame(
39 int64 frame_id,
40 int64 parent_frame_id,
41 bool is_main_frame,
42 const GURL& validated_url,
43 bool is_error_page,
44 bool is_iframe_srcdoc,
45 content::RenderViewHost* render_view_host) OVERRIDE {
46 GuestViewManager::FromBrowserContext(web_contents()->GetBrowserContext())->
47 AddRenderProcessHostID(web_contents()->GetRenderProcessHost()->GetID());
48 delete this;
49 }
50
51 virtual void WebContentsDestroyed(WebContents* web_contents) OVERRIDE {
52 delete this;
53 }
54
55 private:
56 DISALLOW_COPY_AND_ASSIGN(GuestWebContentsObserver);
57 };
58
59 GuestViewManager::GuestViewManager(content::BrowserContext* context)
60 : current_instance_id_(0),
61 context_(context) {}
62
63 GuestViewManager::~GuestViewManager() {}
64
65 // static.
66 GuestViewManager* GuestViewManager::FromBrowserContext(
67 BrowserContext* context) {
68 GuestViewManager* guest_manager =
69 static_cast<GuestViewManager*>(context->GetUserData(
70 guestview::kGuestViewManagerKeyName));
71 if (!guest_manager) {
72 guest_manager = new GuestViewManager(context);
73 context->SetUserData(guestview::kGuestViewManagerKeyName, guest_manager);
74 }
75 return guest_manager;
76 }
77
78 int GuestViewManager::GetNextInstanceID() {
79 return ++current_instance_id_;
80 }
81
82 void GuestViewManager::AddGuest(int guest_instance_id,
83 WebContents* guest_web_contents) {
84 DCHECK(guest_web_contents_by_instance_id_.find(guest_instance_id) ==
85 guest_web_contents_by_instance_id_.end());
86 guest_web_contents_by_instance_id_[guest_instance_id] = guest_web_contents;
87 // This will add the RenderProcessHost ID when we get one.
88 new GuestWebContentsObserver(guest_web_contents);
89 }
90
91 void GuestViewManager::RemoveGuest(int guest_instance_id) {
92 GuestInstanceMap::iterator it =
93 guest_web_contents_by_instance_id_.find(guest_instance_id);
94 DCHECK(it != guest_web_contents_by_instance_id_.end());
95 render_process_host_id_set_.erase(
96 it->second->GetRenderProcessHost()->GetID());
97 guest_web_contents_by_instance_id_.erase(it);
98 }
99
100 content::WebContents* GuestViewManager::GetGuestByInstanceID(
101 int guest_instance_id,
102 int embedder_render_process_id) {
103 if (!CanEmbedderAccessInstanceIDMaybeKill(embedder_render_process_id,
104 guest_instance_id)) {
105 return NULL;
106 }
107 GuestInstanceMap::const_iterator it =
108 guest_web_contents_by_instance_id_.find(guest_instance_id);
109 if (it == guest_web_contents_by_instance_id_.end())
110 return NULL;
111 return it->second;
112 }
113
114 bool GuestViewManager::CanEmbedderAccessInstanceIDMaybeKill(
115 int embedder_render_process_id,
116 int guest_instance_id) {
117 if (!CanEmbedderAccessInstanceID(embedder_render_process_id,
118 guest_instance_id)) {
119 // The embedder process is trying to access a guest it does not own.
120 content::RecordAction(
121 base::UserMetricsAction("BadMessageTerminate_BPGM"));
122 base::KillProcess(
123 content::RenderProcessHost::FromID(embedder_render_process_id)->
124 GetHandle(),
125 content::RESULT_CODE_KILLED_BAD_MESSAGE, false);
126 return false;
127 }
128 return true;
129 }
130
131 bool GuestViewManager::CanEmbedderAccessInstanceID(
132 int embedder_render_process_id,
133 int guest_instance_id) {
134 // The embedder is trying to access a guest with a negative or zero
135 // instance ID.
136 if (guest_instance_id <= guestview::kInstanceIDNone)
137 return false;
138
139 // The embedder is trying to access an instance ID that has not yet been
140 // allocated by GuestViewManager. This could cause instance ID
141 // collisions in the future, and potentially give one embedder access to a
142 // guest it does not own.
143 if (guest_instance_id > current_instance_id_)
144 return false;
145
146 GuestInstanceMap::const_iterator it =
147 guest_web_contents_by_instance_id_.find(guest_instance_id);
148 if (it == guest_web_contents_by_instance_id_.end())
149 return true;
150
151 GuestViewBase* guest_view = GuestViewBase::FromWebContents(it->second);
152 if (!guest_view)
153 return false;
154
155 return CanEmbedderAccessGuest(embedder_render_process_id, guest_view);
156 }
157
158 SiteInstance* GuestViewManager::GetGuestSiteInstance(
159 const GURL& guest_site) {
160 for (GuestInstanceMap::const_iterator it =
161 guest_web_contents_by_instance_id_.begin();
162 it != guest_web_contents_by_instance_id_.end(); ++it) {
163 if (it->second->GetSiteInstance()->GetSiteURL() == guest_site)
164 return it->second->GetSiteInstance();
165 }
166 return NULL;
167 }
168
169 bool GuestViewManager::ForEachGuest(WebContents* embedder_web_contents,
170 const GuestCallback& callback) {
171 for (GuestInstanceMap::iterator it =
172 guest_web_contents_by_instance_id_.begin();
173 it != guest_web_contents_by_instance_id_.end(); ++it) {
174 WebContents* guest = it->second;
175 if (embedder_web_contents != guest->GetEmbedderWebContents())
176 continue;
177
178 if (callback.Run(guest))
179 return true;
180 }
181 return false;
182 }
183
184 void GuestViewManager::RequestInstanceID(
185 const std::string& src,
186 const InstanceIDResponseCallback& callback) {
187 GURL url(src);
188 if (!url.is_valid() || !url.SchemeIs("chrome-extension")) {
lazyboy 2014/05/01 20:06:59 Use existing kExtensionScheme instead of "chrome-e
Fady Samuel 2014/05/01 21:05:28 Removed.
189 callback.Run(GetNextInstanceID());
190 return;
191 }
192 const std::string& extension_id = url.host();
lazyboy 2014/05/01 20:06:59 The whole function just does callback.Run(GetNextI
Fady Samuel 2014/05/01 21:05:28 Removed this function entirely for now.
193 Profile* profile = Profile::FromBrowserContext(context_);
194 ExtensionService* service =
195 extensions::ExtensionSystem::Get(profile)->extension_service();
196 if (!service) {
197 callback.Run(GetNextInstanceID());
198 return;
199 }
200 const extensions::Extension* extension =
201 service->GetExtensionById(extension_id, false);
202 if (!extension || !extension->is_platform_app()) {
203 callback.Run(GetNextInstanceID());
204 return;
205 }
206 callback.Run(GetNextInstanceID());
207 }
208
209 void GuestViewManager::AddRenderProcessHostID(int render_process_host_id) {
210 render_process_host_id_set_.insert(render_process_host_id);
211 }
212
213 bool GuestViewManager::CanEmbedderAccessGuest(int embedder_render_process_id,
214 GuestViewBase* guest) {
215 // The embedder can access the guest if it has not been attached and its
216 // opener's embedder lives in the same process as the given embedder.
217 if (!guest->attached()) {
218 if (!guest->GetOpener())
219 return false;
220
221 return embedder_render_process_id ==
222 guest->GetOpener()->GetEmbedderWebContents()->GetRenderProcessHost()->
223 GetID();
224 }
225
226 return embedder_render_process_id ==
227 guest->embedder_web_contents()->GetRenderProcessHost()->GetID();
228 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698