| OLD | NEW |
| 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 "content/public/browser/browser_thread.h" | 7 #include "content/public/browser/browser_thread.h" |
| 8 #include "chrome/browser/extensions/event_names.h" | 8 #include "chrome/browser/extensions/event_names.h" |
| 9 #include "chrome/browser/extensions/event_router.h" | 9 #include "chrome/browser/extensions/event_router.h" |
| 10 #include "chrome/browser/extensions/extension_system.h" | 10 #include "chrome/browser/extensions/extension_system.h" |
| (...skipping 15 matching lines...) Expand all Loading... |
| 26 proxy_->Attach(this); | 26 proxy_->Attach(this); |
| 27 registrar_.Add(this, chrome::NOTIFICATION_EXTENSION_UNLOADED, | 27 registrar_.Add(this, chrome::NOTIFICATION_EXTENSION_UNLOADED, |
| 28 content::Source<Profile>(profile_)); | 28 content::Source<Profile>(profile_)); |
| 29 } | 29 } |
| 30 | 30 |
| 31 TabCaptureRegistry::~TabCaptureRegistry() { | 31 TabCaptureRegistry::~TabCaptureRegistry() { |
| 32 proxy_->Detach(); | 32 proxy_->Detach(); |
| 33 } | 33 } |
| 34 | 34 |
| 35 void TabCaptureRegistry::HandleRequestUpdateOnUIThread( | 35 void TabCaptureRegistry::HandleRequestUpdateOnUIThread( |
| 36 int render_process_id, |
| 37 int render_view_id, |
| 36 const content::MediaStreamDevice& device, | 38 const content::MediaStreamDevice& device, |
| 37 const content::MediaRequestState new_state) { | 39 const content::MediaRequestState new_state) { |
| 38 EventRouter* router = profile_ ? | 40 EventRouter* router = profile_ ? |
| 39 extensions::ExtensionSystem::Get(profile_)->event_router() : NULL; | 41 extensions::ExtensionSystem::Get(profile_)->event_router() : NULL; |
| 40 if (!router) | 42 if (!router) |
| 41 return; | 43 return; |
| 42 | 44 |
| 43 if (requests_.find(device.device_id) == requests_.end()) | 45 std::pair<int, int> key = std::make_pair(render_process_id, render_view_id); |
| 46 |
| 47 if (requests_.find(key) == requests_.end()) { |
| 48 LOG(ERROR) << "Receiving updates for invalid tab capture request."; |
| 44 return; | 49 return; |
| 50 } |
| 45 | 51 |
| 46 tab_capture::TabCaptureState state = | 52 tab_capture::TabCaptureState state = |
| 47 tab_capture::TAB_CAPTURE_TAB_CAPTURE_STATE_NONE; | 53 tab_capture::TAB_CAPTURE_TAB_CAPTURE_STATE_NONE; |
| 48 switch (new_state) { | 54 switch (new_state) { |
| 49 case content::MEDIA_REQUEST_STATE_REQUESTED: | 55 case content::MEDIA_REQUEST_STATE_REQUESTED: |
| 50 state = tab_capture::TAB_CAPTURE_TAB_CAPTURE_STATE_REQUESTED; | 56 state = tab_capture::TAB_CAPTURE_TAB_CAPTURE_STATE_REQUESTED; |
| 51 break; | 57 break; |
| 52 case content::MEDIA_REQUEST_STATE_PENDING_APPROVAL: | 58 case content::MEDIA_REQUEST_STATE_PENDING_APPROVAL: |
| 53 state = tab_capture::TAB_CAPTURE_TAB_CAPTURE_STATE_PENDING; | 59 state = tab_capture::TAB_CAPTURE_TAB_CAPTURE_STATE_PENDING; |
| 54 break; | 60 break; |
| 55 case content::MEDIA_REQUEST_STATE_DONE: | 61 case content::MEDIA_REQUEST_STATE_DONE: |
| 56 state = tab_capture::TAB_CAPTURE_TAB_CAPTURE_STATE_ACTIVE; | 62 state = tab_capture::TAB_CAPTURE_TAB_CAPTURE_STATE_ACTIVE; |
| 57 break; | 63 break; |
| 58 case content::MEDIA_REQUEST_STATE_CLOSING: | 64 case content::MEDIA_REQUEST_STATE_CLOSING: |
| 59 state = tab_capture::TAB_CAPTURE_TAB_CAPTURE_STATE_STOPPED; | 65 state = tab_capture::TAB_CAPTURE_TAB_CAPTURE_STATE_STOPPED; |
| 60 break; | 66 break; |
| 61 case content::MEDIA_REQUEST_STATE_ERROR: | 67 case content::MEDIA_REQUEST_STATE_ERROR: |
| 62 state = tab_capture::TAB_CAPTURE_TAB_CAPTURE_STATE_ERROR; | 68 state = tab_capture::TAB_CAPTURE_TAB_CAPTURE_STATE_ERROR; |
| 63 break; | 69 break; |
| 64 default: | 70 default: |
| 65 // TODO(justinlin): Implement muted state notification. | 71 // TODO(justinlin): Implement muted state notification. |
| 66 break; | 72 break; |
| 67 } | 73 } |
| 68 | 74 |
| 69 if (state == tab_capture::TAB_CAPTURE_TAB_CAPTURE_STATE_NONE) { | 75 if (state == tab_capture::TAB_CAPTURE_TAB_CAPTURE_STATE_NONE) { |
| 70 // This is a state we don't handle. | 76 // This is a state we don't handle. |
| 71 return; | 77 return; |
| 72 } | 78 } |
| 73 | 79 |
| 74 TabCaptureRegistry::TabCaptureRequest& request_info = | 80 TabCaptureRegistry::TabCaptureRequest& request_info = requests_[key]; |
| 75 requests_[device.device_id]; | |
| 76 request_info.status = state; | 81 request_info.status = state; |
| 77 | 82 |
| 78 scoped_ptr<tab_capture::CaptureInfo> info(new tab_capture::CaptureInfo()); | 83 scoped_ptr<tab_capture::CaptureInfo> info(new tab_capture::CaptureInfo()); |
| 79 info->tab_id = request_info.tab_id; | 84 info->tab_id = request_info.tab_id; |
| 80 info->status = request_info.status; | 85 info->status = request_info.status; |
| 81 | 86 |
| 82 scoped_ptr<base::ListValue> args(new ListValue()); | 87 scoped_ptr<base::ListValue> args(new ListValue()); |
| 83 args->Append(info->ToValue().release()); | 88 args->Append(info->ToValue().release()); |
| 84 router->DispatchEventToExtension(request_info.extension_id, | 89 router->DispatchEventToExtension(request_info.extension_id, |
| 85 events::kOnTabCaptureStatusChanged, args.Pass(), profile_, GURL()); | 90 events::kOnTabCaptureStatusChanged, args.Pass(), profile_, GURL()); |
| (...skipping 27 matching lines...) Expand all Loading... |
| 113 requests_.erase(it++); | 118 requests_.erase(it++); |
| 114 } else { | 119 } else { |
| 115 ++it; | 120 ++it; |
| 116 } | 121 } |
| 117 } | 122 } |
| 118 break; | 123 break; |
| 119 } | 124 } |
| 120 } | 125 } |
| 121 } | 126 } |
| 122 | 127 |
| 123 bool TabCaptureRegistry::AddRequest( | 128 bool TabCaptureRegistry::AddRequest(const std::pair<int, int> key, |
| 124 const std::string& key, const TabCaptureRequest& request) { | 129 const TabCaptureRequest& request) { |
| 125 // Currently, we do not allow multiple active captures for same tab. | 130 // Currently, we do not allow multiple active captures for same tab. |
| 126 DCHECK(!key.empty()); | |
| 127 if (requests_.find(key) != requests_.end()) | 131 if (requests_.find(key) != requests_.end()) |
| 128 if (requests_[key].status != | 132 if (requests_[key].status != |
| 129 tab_capture::TAB_CAPTURE_TAB_CAPTURE_STATE_STOPPED && | 133 tab_capture::TAB_CAPTURE_TAB_CAPTURE_STATE_STOPPED && |
| 130 requests_[key].status != | 134 requests_[key].status != |
| 131 tab_capture::TAB_CAPTURE_TAB_CAPTURE_STATE_ERROR) | 135 tab_capture::TAB_CAPTURE_TAB_CAPTURE_STATE_ERROR) |
| 132 return false; | 136 return false; |
| 133 requests_[key] = request; | 137 requests_[key] = request; |
| 134 return true; | 138 return true; |
| 135 } | 139 } |
| 136 | 140 |
| 137 bool TabCaptureRegistry::VerifyRequest(const std::string& key) { | 141 bool TabCaptureRegistry::VerifyRequest(int render_process_id, |
| 138 return requests_.find(key) != requests_.end(); | 142 int render_view_id) { |
| 143 return requests_.find(std::make_pair( |
| 144 render_process_id, render_view_id)) != requests_.end(); |
| 139 } | 145 } |
| 140 | 146 |
| 141 void TabCaptureRegistry::MediaObserverProxy::Attach( | 147 void TabCaptureRegistry::MediaObserverProxy::Attach( |
| 142 TabCaptureRegistry* request_handler) { | 148 TabCaptureRegistry* request_handler) { |
| 143 handler_ = request_handler; | 149 handler_ = request_handler; |
| 144 BrowserThread::PostTask(BrowserThread::IO, FROM_HERE, | 150 BrowserThread::PostTask(BrowserThread::IO, FROM_HERE, |
| 145 base::Bind(&TabCaptureRegistry::MediaObserverProxy:: | 151 base::Bind(&TabCaptureRegistry::MediaObserverProxy:: |
| 146 RegisterAsMediaObserverOnIOThread, this, false)); | 152 RegisterAsMediaObserverOnIOThread, this, false)); |
| 147 } | 153 } |
| 148 | 154 |
| 149 void TabCaptureRegistry::MediaObserverProxy::Detach() { | 155 void TabCaptureRegistry::MediaObserverProxy::Detach() { |
| 150 handler_ = NULL; | 156 handler_ = NULL; |
| 151 BrowserThread::PostTask(BrowserThread::IO, FROM_HERE, | 157 BrowserThread::PostTask(BrowserThread::IO, FROM_HERE, |
| 152 base::Bind(&TabCaptureRegistry::MediaObserverProxy:: | 158 base::Bind(&TabCaptureRegistry::MediaObserverProxy:: |
| 153 RegisterAsMediaObserverOnIOThread, this, true)); | 159 RegisterAsMediaObserverOnIOThread, this, true)); |
| 154 } | 160 } |
| 155 | 161 |
| 156 void TabCaptureRegistry::MediaObserverProxy::RegisterAsMediaObserverOnIOThread( | 162 void TabCaptureRegistry::MediaObserverProxy::RegisterAsMediaObserverOnIOThread( |
| 157 bool unregister) { | 163 bool unregister) { |
| 158 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); | 164 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); |
| 159 if (MediaInternals::GetInstance()) { | 165 if (MediaInternals::GetInstance()) { |
| 160 if (!unregister) | 166 if (!unregister) |
| 161 MediaInternals::GetInstance()->AddObserver(this); | 167 MediaInternals::GetInstance()->AddObserver(this); |
| 162 else | 168 else |
| 163 MediaInternals::GetInstance()->RemoveObserver(this); | 169 MediaInternals::GetInstance()->RemoveObserver(this); |
| 164 } | 170 } |
| 165 } | 171 } |
| 166 | 172 |
| 167 void TabCaptureRegistry::MediaObserverProxy::OnRequestUpdate( | 173 void TabCaptureRegistry::MediaObserverProxy::OnRequestUpdate( |
| 174 int render_process_id, |
| 175 int render_view_id, |
| 168 const content::MediaStreamDevice& device, | 176 const content::MediaStreamDevice& device, |
| 169 const content::MediaRequestState new_state) { | 177 const content::MediaRequestState new_state) { |
| 170 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); | 178 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); |
| 171 | 179 |
| 172 // TODO(justinlin): We drop audio device events since they will occur in | 180 // TODO(justinlin): We drop audio device events since they will occur in |
| 173 // parallel with the video device events (we would get duplicate events). When | 181 // parallel with the video device events (we would get duplicate events). When |
| 174 // audio mirroring is implemented, we will want to grab those events when | 182 // audio mirroring is implemented, we will want to grab those events when |
| 175 // video is not requested. | 183 // video is not requested. |
| 176 if (device.type != content::MEDIA_TAB_VIDEO_CAPTURE) | 184 if (device.type != content::MEDIA_TAB_VIDEO_CAPTURE) |
| 177 return; | 185 return; |
| 178 | 186 |
| 179 BrowserThread::PostTask(BrowserThread::UI, FROM_HERE, | 187 BrowserThread::PostTask(BrowserThread::UI, FROM_HERE, |
| 180 base::Bind(&TabCaptureRegistry::MediaObserverProxy::UpdateOnUIThread, | 188 base::Bind(&TabCaptureRegistry::MediaObserverProxy::UpdateOnUIThread, |
| 181 this, device, new_state)); | 189 this, render_process_id, render_view_id, device, new_state)); |
| 182 } | 190 } |
| 183 | 191 |
| 184 void TabCaptureRegistry::MediaObserverProxy::UpdateOnUIThread( | 192 void TabCaptureRegistry::MediaObserverProxy::UpdateOnUIThread( |
| 193 int render_process_id, |
| 194 int render_view_id, |
| 185 const content::MediaStreamDevice& device, | 195 const content::MediaStreamDevice& device, |
| 186 const content::MediaRequestState new_state) { | 196 const content::MediaRequestState new_state) { |
| 187 if (handler_) | 197 if (handler_) |
| 188 handler_->HandleRequestUpdateOnUIThread(device, new_state); | 198 handler_->HandleRequestUpdateOnUIThread(render_process_id, |
| 199 render_view_id, |
| 200 device, |
| 201 new_state); |
| 189 } | 202 } |
| 190 | 203 |
| 191 } // namespace extensions | 204 } // namespace extensions |
| OLD | NEW |