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

Side by Side Diff: chrome/browser/extensions/api/tab_capture/tab_capture_registry.cc

Issue 364123002: [Cross-Site Isolation] Migrate entire MediaStream verticals to be per-RenderFrame. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Created 6 years, 5 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 | Annotate | Revision Log
OLDNEW
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 "chrome/browser/extensions/api/tab_capture/tab_capture_registry.h" 5 #include "chrome/browser/extensions/api/tab_capture/tab_capture_registry.h"
6 6
7 #include "base/lazy_instance.h" 7 #include "base/lazy_instance.h"
8 #include "chrome/browser/chrome_notification_types.h"
9 #include "chrome/browser/ui/fullscreen/fullscreen_controller.h"
10 #include "components/keyed_service/content/browser_context_dependency_manager.h" 8 #include "components/keyed_service/content/browser_context_dependency_manager.h"
11 #include "content/public/browser/browser_thread.h" 9 #include "content/public/browser/browser_thread.h"
12 #include "content/public/browser/notification_details.h" 10 #include "content/public/browser/render_frame_host.h"
13 #include "content/public/browser/notification_service.h"
14 #include "content/public/browser/notification_source.h"
15 #include "content/public/browser/render_view_host.h"
16 #include "content/public/browser/web_contents.h" 11 #include "content/public/browser/web_contents.h"
17 #include "content/public/browser/web_contents_observer.h" 12 #include "content/public/browser/web_contents_observer.h"
18 #include "extensions/browser/event_router.h" 13 #include "extensions/browser/event_router.h"
19 #include "extensions/browser/extension_registry.h" 14 #include "extensions/browser/extension_registry.h"
20 #include "extensions/common/extension.h" 15 #include "extensions/common/extension.h"
21 16
22 using content::BrowserThread; 17 using content::BrowserThread;
23 using extensions::tab_capture::TabCaptureState; 18 using extensions::tab_capture::TabCaptureState;
24 19
25 namespace extensions { 20 namespace extensions {
26 21
27 namespace tab_capture = api::tab_capture; 22 namespace tab_capture = api::tab_capture;
28 23
29 class FullscreenObserver : public content::WebContentsObserver { 24 class FullscreenObserver : public content::WebContentsObserver {
30 public: 25 public:
26 // Caller of this constructor must guarantee that |request->target_contents|
27 // is a valid pointer (i.e., it will be dereferenced).
ncarter (slow) 2014/07/10 01:17:51 Just say: "... is not NULL". The rest is implicit.
miu 2014/07/10 22:16:11 I think this was left over from earlier prototypin
31 FullscreenObserver(TabCaptureRequest* request, 28 FullscreenObserver(TabCaptureRequest* request,
32 const TabCaptureRegistry* registry); 29 const TabCaptureRegistry* registry);
33 virtual ~FullscreenObserver() {} 30 virtual ~FullscreenObserver() {}
34 31
35 private: 32 private:
36 // content::WebContentsObserver implementation. 33 // content::WebContentsObserver implementation.
37 virtual void DidShowFullscreenWidget(int routing_id) OVERRIDE; 34 virtual void DidShowFullscreenWidget(int routing_id) OVERRIDE;
38 virtual void DidDestroyFullscreenWidget(int routing_id) OVERRIDE; 35 virtual void DidDestroyFullscreenWidget(int routing_id) OVERRIDE;
36 virtual void DidToggleFullscreenModeForTab(bool entered_fullscreen) OVERRIDE;
39 37
40 TabCaptureRequest* request_; 38 TabCaptureRequest* request_;
41 const TabCaptureRegistry* registry_; 39 const TabCaptureRegistry* registry_;
42 40
43 DISALLOW_COPY_AND_ASSIGN(FullscreenObserver); 41 DISALLOW_COPY_AND_ASSIGN(FullscreenObserver);
44 }; 42 };
45 43
46 // Holds all the state related to a tab capture stream. 44 // Holds all the state related to a tab capture stream.
47 struct TabCaptureRequest { 45 struct TabCaptureRequest {
48 TabCaptureRequest(int render_process_id, 46 TabCaptureRequest(content::WebContents* target_contents,
49 int render_view_id,
50 const std::string& extension_id, 47 const std::string& extension_id,
51 int tab_id, 48 int tab_id,
52 TabCaptureState status); 49 TabCaptureState status);
53 ~TabCaptureRequest(); 50 ~TabCaptureRequest();
54 51
55 const int render_process_id; 52 content::WebContents* const target_contents;
56 const int render_view_id;
57 const std::string extension_id; 53 const std::string extension_id;
58 const int tab_id; 54 const int tab_id;
59 TabCaptureState status; 55 TabCaptureState status;
60 TabCaptureState last_status; 56 TabCaptureState last_status;
61 bool fullscreen; 57 bool fullscreen;
62 scoped_ptr<FullscreenObserver> fullscreen_observer; 58 scoped_ptr<FullscreenObserver> fullscreen_observer;
63 }; 59 };
64 60
65 FullscreenObserver::FullscreenObserver( 61 FullscreenObserver::FullscreenObserver(
66 TabCaptureRequest* request, 62 TabCaptureRequest* request,
67 const TabCaptureRegistry* registry) 63 const TabCaptureRegistry* registry)
68 : request_(request), 64 : content::WebContentsObserver(request->target_contents),
65 request_(request),
69 registry_(registry) { 66 registry_(registry) {
70 content::RenderViewHost* const rvh =
71 content::RenderViewHost::FromID(request->render_process_id,
72 request->render_view_id);
73 Observe(rvh ? content::WebContents::FromRenderViewHost(rvh) : NULL);
74 } 67 }
75 68
76 void FullscreenObserver::DidShowFullscreenWidget( 69 void FullscreenObserver::DidShowFullscreenWidget(
77 int routing_id) { 70 int routing_id) {
78 request_->fullscreen = true; 71 request_->fullscreen = true;
79 registry_->DispatchStatusChangeEvent(request_); 72 registry_->DispatchStatusChangeEvent(request_);
80 } 73 }
81 74
82 void FullscreenObserver::DidDestroyFullscreenWidget( 75 void FullscreenObserver::DidDestroyFullscreenWidget(
83 int routing_id) { 76 int routing_id) {
84 request_->fullscreen = false; 77 request_->fullscreen = false;
85 registry_->DispatchStatusChangeEvent(request_); 78 registry_->DispatchStatusChangeEvent(request_);
86 } 79 }
87 80
81 void FullscreenObserver::DidToggleFullscreenModeForTab(
82 bool entered_fullscreen) {
83 request_->fullscreen = entered_fullscreen;
84 registry_->DispatchStatusChangeEvent(request_);
85 }
86
88 TabCaptureRequest::TabCaptureRequest( 87 TabCaptureRequest::TabCaptureRequest(
89 int render_process_id, 88 content::WebContents* target_contents,
90 int render_view_id,
91 const std::string& extension_id, 89 const std::string& extension_id,
92 const int tab_id, 90 const int tab_id,
93 TabCaptureState status) 91 TabCaptureState status)
94 : render_process_id(render_process_id), 92 : target_contents(target_contents),
95 render_view_id(render_view_id),
96 extension_id(extension_id), 93 extension_id(extension_id),
97 tab_id(tab_id), 94 tab_id(tab_id),
98 status(status), 95 status(status),
99 last_status(status), 96 last_status(status),
97 // TODO(miu): This initial value for |fullscreen| is a faulty assumption.
98 // http://crbug.com/350491
100 fullscreen(false) { 99 fullscreen(false) {
101 } 100 }
102 101
103 TabCaptureRequest::~TabCaptureRequest() { 102 TabCaptureRequest::~TabCaptureRequest() {
104 } 103 }
105 104
106 TabCaptureRegistry::TabCaptureRegistry(content::BrowserContext* context) 105 TabCaptureRegistry::TabCaptureRegistry(content::BrowserContext* context)
107 : browser_context_(context), extension_registry_observer_(this) { 106 : browser_context_(context), extension_registry_observer_(this) {
108 MediaCaptureDevicesDispatcher::GetInstance()->AddObserver(this); 107 MediaCaptureDevicesDispatcher::GetInstance()->AddObserver(this);
109 registrar_.Add(this,
110 chrome::NOTIFICATION_FULLSCREEN_CHANGED,
111 content::NotificationService::AllSources());
112 extension_registry_observer_.Add(ExtensionRegistry::Get(browser_context_)); 108 extension_registry_observer_.Add(ExtensionRegistry::Get(browser_context_));
113 } 109 }
114 110
115 TabCaptureRegistry::~TabCaptureRegistry() { 111 TabCaptureRegistry::~TabCaptureRegistry() {
116 MediaCaptureDevicesDispatcher::GetInstance()->RemoveObserver(this); 112 MediaCaptureDevicesDispatcher::GetInstance()->RemoveObserver(this);
117 } 113 }
118 114
119 // static 115 // static
120 TabCaptureRegistry* TabCaptureRegistry::Get(content::BrowserContext* context) { 116 TabCaptureRegistry* TabCaptureRegistry::Get(content::BrowserContext* context) {
121 return BrowserContextKeyedAPIFactory<TabCaptureRegistry>::Get(context); 117 return BrowserContextKeyedAPIFactory<TabCaptureRegistry>::Get(context);
(...skipping 14 matching lines...) Expand all
136 RegistryCaptureInfo list; 132 RegistryCaptureInfo list;
137 for (ScopedVector<TabCaptureRequest>::const_iterator it = requests_.begin(); 133 for (ScopedVector<TabCaptureRequest>::const_iterator it = requests_.begin();
138 it != requests_.end(); ++it) { 134 it != requests_.end(); ++it) {
139 if ((*it)->extension_id == extension_id) { 135 if ((*it)->extension_id == extension_id) {
140 list.push_back(std::make_pair((*it)->tab_id, (*it)->status)); 136 list.push_back(std::make_pair((*it)->tab_id, (*it)->status));
141 } 137 }
142 } 138 }
143 return list; 139 return list;
144 } 140 }
145 141
146 void TabCaptureRegistry::Observe(int type,
147 const content::NotificationSource& source,
148 const content::NotificationDetails& details) {
149 DCHECK_CURRENTLY_ON(BrowserThread::UI);
150 DCHECK_EQ(chrome::NOTIFICATION_FULLSCREEN_CHANGED, type);
151 FullscreenController* fullscreen_controller =
152 content::Source<FullscreenController>(source).ptr();
153 const bool is_fullscreen = *content::Details<bool>(details).ptr();
154 for (ScopedVector<TabCaptureRequest>::iterator it = requests_.begin();
155 it != requests_.end();
156 ++it) {
157 // If we are exiting fullscreen mode, we only need to check if any of
158 // the requests had the fullscreen flag toggled previously. The
159 // fullscreen controller no longer has the reference to the fullscreen
160 // web_contents here.
161 if (!is_fullscreen) {
162 if ((*it)->fullscreen) {
163 (*it)->fullscreen = false;
164 DispatchStatusChangeEvent(*it);
165 break;
166 }
167 continue;
168 }
169
170 // If we are entering fullscreen mode, find whether the web_contents we
171 // are capturing entered fullscreen mode.
172 content::RenderViewHost* const rvh = content::RenderViewHost::FromID(
173 (*it)->render_process_id, (*it)->render_view_id);
174 if (rvh &&
175 fullscreen_controller->IsFullscreenForTabOrPending(
176 content::WebContents::FromRenderViewHost(rvh))) {
177 (*it)->fullscreen = true;
178 DispatchStatusChangeEvent(*it);
179 break;
180 }
181 }
182 }
183
184 void TabCaptureRegistry::OnExtensionUnloaded( 142 void TabCaptureRegistry::OnExtensionUnloaded(
185 content::BrowserContext* browser_context, 143 content::BrowserContext* browser_context,
186 const Extension* extension, 144 const Extension* extension,
187 UnloadedExtensionInfo::Reason reason) { 145 UnloadedExtensionInfo::Reason reason) {
188 // Cleanup all the requested media streams for this extension. 146 // Cleanup all the requested media streams for this extension.
189 for (ScopedVector<TabCaptureRequest>::iterator it = requests_.begin(); 147 for (ScopedVector<TabCaptureRequest>::iterator it = requests_.begin();
190 it != requests_.end();) { 148 it != requests_.end();) {
191 if ((*it)->extension_id == extension->id()) { 149 if ((*it)->extension_id == extension->id()) {
192 it = requests_.erase(it); 150 it = requests_.erase(it);
193 } else { 151 } else {
194 ++it; 152 ++it;
195 } 153 }
196 } 154 }
197 } 155 }
198 156
199 bool TabCaptureRegistry::AddRequest(int render_process_id, 157 bool TabCaptureRegistry::AddRequest(content::WebContents* target_contents,
200 int render_view_id,
201 const std::string& extension_id, 158 const std::string& extension_id,
202 int tab_id, 159 int tab_id,
203 TabCaptureState status) { 160 TabCaptureState status) {
204 TabCaptureRequest* request = FindCaptureRequest(render_process_id, 161 TabCaptureRequest* const request = FindCaptureRequest(target_contents);
205 render_view_id); 162
206 // Currently, we do not allow multiple active captures for same tab. 163 // Currently, we do not allow multiple active captures for same tab.
207 if (request != NULL) { 164 if (request != NULL) {
208 if (request->status != tab_capture::TAB_CAPTURE_STATE_STOPPED && 165 if (request->status != tab_capture::TAB_CAPTURE_STATE_STOPPED &&
209 request->status != tab_capture::TAB_CAPTURE_STATE_ERROR) { 166 request->status != tab_capture::TAB_CAPTURE_STATE_ERROR) {
210 return false; 167 return false;
211 } else { 168 } else {
212 DeleteCaptureRequest(render_process_id, render_view_id); 169 // Delete the request.
170 // TODO(miu): It's not clear that this code path will ever get executed
171 // and, in fact, it seems impossible that TabCaptureRequests will ever get
172 // deleted. Probably the root cause of http://crbug.com/338445.
ncarter (slow) 2014/07/10 01:17:51 If the entries of |requests_| are not properly cle
miu 2014/07/10 22:16:11 Done. I used exactly your suggested approach of m
ncarter (slow) 2014/07/11 22:32:24 Wonderful, glad it worked out.
173 for (ScopedVector<TabCaptureRequest>::iterator it = requests_.begin();
174 it != requests_.end(); ++it) {
175 if ((*it)->target_contents == target_contents) {
176 requests_.erase(it);
177 break;
178 }
179 }
213 } 180 }
214 } 181 }
215 182
216 requests_.push_back(new TabCaptureRequest(render_process_id, 183 requests_.push_back(new TabCaptureRequest(target_contents,
217 render_view_id,
218 extension_id, 184 extension_id,
219 tab_id, 185 tab_id,
220 status)); 186 status));
221 return true; 187 return true;
222 } 188 }
223 189
224 bool TabCaptureRegistry::VerifyRequest(int render_process_id, 190 bool TabCaptureRegistry::VerifyRequest(
225 int render_view_id) { 191 const content::WebContents* target_contents,
192 const std::string& extension_id) {
226 DCHECK_CURRENTLY_ON(BrowserThread::UI); 193 DCHECK_CURRENTLY_ON(BrowserThread::UI);
227 DVLOG(1) << "Verifying tabCapture request for " 194 TabCaptureRequest* const request = FindCaptureRequest(target_contents);
228 << render_process_id << ":" << render_view_id; 195 // TODO(miu): We should probably also verify the origin, like the desktop
229 // TODO(justinlin): Verify extension too. 196 // capture API. http://crbug.com/163100
230 return (FindCaptureRequest(render_process_id, render_view_id) != NULL); 197 return request && request->extension_id == extension_id;
231 } 198 }
232 199
233 void TabCaptureRegistry::OnRequestUpdate( 200 void TabCaptureRegistry::OnRequestUpdate(
234 int render_process_id, 201 int render_process_id,
235 int render_view_id, 202 int render_frame_id,
236 const content::MediaStreamDevice& device, 203 content::MediaStreamType stream_type,
237 const content::MediaRequestState new_state) { 204 const content::MediaRequestState new_state) {
238 DCHECK_CURRENTLY_ON(BrowserThread::UI); 205 DCHECK_CURRENTLY_ON(BrowserThread::UI);
239 if (device.type != content::MEDIA_TAB_VIDEO_CAPTURE && 206 if (stream_type != content::MEDIA_TAB_VIDEO_CAPTURE &&
240 device.type != content::MEDIA_TAB_AUDIO_CAPTURE) { 207 stream_type != content::MEDIA_TAB_AUDIO_CAPTURE) {
241 return; 208 return;
242 } 209 }
243 210
244 TabCaptureRequest* request = FindCaptureRequest(render_process_id, 211 TabCaptureRequest* const request = FindCaptureRequest(
245 render_view_id); 212 content::WebContents::FromRenderFrameHost(
213 content::RenderFrameHost::FromID(
214 render_process_id, render_frame_id)));
246 if (request == NULL) { 215 if (request == NULL) {
247 // TODO(justinlin): This can happen because the extension's renderer does 216 // TODO(justinlin): This can happen because the extension's renderer does
248 // not seem to always cleanup streams correctly. 217 // not seem to always cleanup streams correctly.
249 LOG(ERROR) << "Receiving updates for deleted capture request."; 218 LOG(ERROR) << "Receiving updates for deleted capture request.";
250 return; 219 return;
251 } 220 }
252 221
253 bool opening_stream = false; 222 bool opening_stream = false;
254 bool stopping_stream = false; 223 bool stopping_stream = false;
255 224
(...skipping 65 matching lines...) Expand 10 before | Expand all | Expand 10 after
321 scoped_ptr<base::ListValue> args(new base::ListValue()); 290 scoped_ptr<base::ListValue> args(new base::ListValue());
322 args->Append(info->ToValue().release()); 291 args->Append(info->ToValue().release());
323 scoped_ptr<Event> event(new Event(tab_capture::OnStatusChanged::kEventName, 292 scoped_ptr<Event> event(new Event(tab_capture::OnStatusChanged::kEventName,
324 args.Pass())); 293 args.Pass()));
325 event->restrict_to_browser_context = browser_context_; 294 event->restrict_to_browser_context = browser_context_;
326 295
327 router->DispatchEventToExtension(request->extension_id, event.Pass()); 296 router->DispatchEventToExtension(request->extension_id, event.Pass());
328 } 297 }
329 298
330 TabCaptureRequest* TabCaptureRegistry::FindCaptureRequest( 299 TabCaptureRequest* TabCaptureRegistry::FindCaptureRequest(
331 int render_process_id, int render_view_id) const { 300 const content::WebContents* target_contents) const {
332 for (ScopedVector<TabCaptureRequest>::const_iterator it = requests_.begin(); 301 for (ScopedVector<TabCaptureRequest>::const_iterator it = requests_.begin();
333 it != requests_.end(); ++it) { 302 it != requests_.end(); ++it) {
334 if ((*it)->render_process_id == render_process_id && 303 if ((*it)->target_contents == target_contents)
335 (*it)->render_view_id == render_view_id) {
336 return *it; 304 return *it;
337 }
338 } 305 }
339 return NULL; 306 return NULL;
340 } 307 }
341 308
342 void TabCaptureRegistry::DeleteCaptureRequest(int render_process_id,
343 int render_view_id) {
344 for (ScopedVector<TabCaptureRequest>::iterator it = requests_.begin();
345 it != requests_.end(); ++it) {
346 if ((*it)->render_process_id == render_process_id &&
347 (*it)->render_view_id == render_view_id) {
348 requests_.erase(it);
349 return;
350 }
351 }
352 }
353
354 } // namespace extensions 309 } // namespace extensions
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698