diff options
author | sergeyu@chromium.org <sergeyu@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2013-10-16 17:50:53 +0000 |
---|---|---|
committer | sergeyu@chromium.org <sergeyu@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2013-10-16 17:50:53 +0000 |
commit | 21dc780764094b92ab97334174a051c3e12a4216 (patch) | |
tree | 54b39d85d79d665ba1c7374687a1da71c1bc25db | |
parent | d30f31be5176bfd80d5d193fb3f3f2658921fb75 (diff) | |
download | chromium_src-21dc780764094b92ab97334174a051c3e12a4216.zip chromium_src-21dc780764094b92ab97334174a051c3e12a4216.tar.gz chromium_src-21dc780764094b92ab97334174a051c3e12a4216.tar.bz2 |
Update Desktop Capture API to use 'tabs.Tab' instead of origin.
When delegating access to desktop capture stream the API has origin
parameter. Problem is that with that approach Chrome didn't know which
tab the request is coming from, so it didn't assign dialog parent
appropriately. Replaced the origin parameter with a parameter of
tabs.Tab type, so now chrome knows which window should be parent
for the dialog.
Also converted interface defintion to JSON, becase IDL doesn't allow
refererencing types from other namespaces.
BUG=289781
R=mpcomplete@chromium.org
Review URL: https://codereview.chromium.org/27282002
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@228943 0039d316-1c4b-4281-b951-d872f2087c98
11 files changed, 158 insertions, 66 deletions
diff --git a/chrome/browser/extensions/api/desktop_capture/desktop_capture_api.cc b/chrome/browser/extensions/api/desktop_capture/desktop_capture_api.cc index 22bef12..4c00e25 100644 --- a/chrome/browser/extensions/api/desktop_capture/desktop_capture_api.cc +++ b/chrome/browser/extensions/api/desktop_capture/desktop_capture_api.cc @@ -6,11 +6,15 @@ #include "base/compiler_specific.h" #include "base/strings/utf_string_conversions.h" +#include "chrome/browser/extensions/extension_tab_util.h" #include "chrome/browser/media/desktop_streams_registry.h" #include "chrome/browser/media/media_capture_devices_dispatcher.h" +#include "chrome/common/extensions/api/tabs.h" #include "content/public/browser/browser_thread.h" #include "content/public/browser/render_process_host.h" #include "content/public/browser/render_view_host.h" +#include "content/public/browser/web_contents.h" +#include "content/public/browser/web_contents_view.h" #include "third_party/webrtc/modules/desktop_capture/screen_capturer.h" #include "third_party/webrtc/modules/desktop_capture/window_capturer.h" @@ -22,6 +26,10 @@ const char kInvalidSourceNameError[] = "Invalid source type specified."; const char kEmptySourcesListError[] = "At least one source type must be specified."; const char kTabCaptureNotSupportedError[] = "Tab capture is not supported yet."; +const char kNoTabIdError[] = "targetTab doesn't have id field set."; +const char kNoUrlError[] = "targetTab doesn't have URL field set."; +const char kInvalidTabIdError[] = "Invalid tab specified."; +const char kTabUrlChangedError[] = "URL for the specified tab has changed."; DesktopCaptureChooseDesktopMediaFunction::PickerFactory* g_picker_factory = NULL; @@ -35,7 +43,10 @@ void DesktopCaptureChooseDesktopMediaFunction::SetPickerFactoryForTests( } DesktopCaptureChooseDesktopMediaFunction:: - DesktopCaptureChooseDesktopMediaFunction() {} + DesktopCaptureChooseDesktopMediaFunction() + : render_process_id_(0), + render_view_id_(0) { +} DesktopCaptureChooseDesktopMediaFunction:: ~DesktopCaptureChooseDesktopMediaFunction() { @@ -70,6 +81,46 @@ bool DesktopCaptureChooseDesktopMediaFunction::RunImpl() { DesktopCaptureRequestsRegistry::GetInstance()->AddRequest( render_view_host()->GetProcess()->GetID(), request_id_, this); + gfx::NativeWindow parent_window; + content::RenderViewHost* render_view; + if (params->target_tab) { + if (!params->target_tab->url) { + error_ = kNoUrlError; + return false; + } + origin_ = GURL(*(params->target_tab->url)).GetOrigin(); + + if (!params->target_tab->id) { + error_ = kNoTabIdError; + return false; + } + + content::WebContents* web_contents = NULL; + if (!ExtensionTabUtil::GetTabById( + *(params->target_tab->id), profile(), false, + NULL, NULL, &web_contents, NULL)) { + error_ = kInvalidTabIdError; + return false; + } + + GURL current_origin_ = + web_contents->GetLastCommittedURL().GetOrigin(); + if (current_origin_ != origin_) { + error_ = kTabUrlChangedError; + return false; + } + + render_view = web_contents->GetRenderViewHost(); + parent_window = web_contents->GetView()->GetTopLevelNativeWindow(); + } else { + origin_ = GetExtension()->url(); + render_view = render_view_host(); + parent_window = + GetAssociatedWebContents()->GetView()->GetTopLevelNativeWindow(); + } + render_process_id_ = render_view->GetProcess()->GetID(); + render_view_id_ = render_view->GetRoutingID(); + scoped_ptr<webrtc::ScreenCapturer> screen_capturer; scoped_ptr<webrtc::WindowCapturer> window_capturer; @@ -105,12 +156,6 @@ bool DesktopCaptureChooseDesktopMediaFunction::RunImpl() { return false; } - if (params->origin) { - origin_ = GURL(*(params->origin)); - } else { - origin_ = GetExtension()->url(); - } - scoped_ptr<DesktopMediaPickerModel> model; if (g_picker_factory) { model = g_picker_factory->CreateModel( @@ -132,7 +177,9 @@ bool DesktopCaptureChooseDesktopMediaFunction::RunImpl() { } DesktopMediaPicker::DoneCallback callback = base::Bind( &DesktopCaptureChooseDesktopMediaFunction::OnPickerDialogResults, this); - picker_->Show(NULL, NULL, UTF8ToUTF16(GetExtension()->name()), + + picker_->Show(parent_window, parent_window, + UTF8ToUTF16(GetExtension()->name()), model.Pass(), callback); return true; } @@ -144,7 +191,8 @@ void DesktopCaptureChooseDesktopMediaFunction::OnPickerDialogResults( DesktopStreamsRegistry* registry = MediaCaptureDevicesDispatcher::GetInstance()-> GetDesktopStreamsRegistry(); - result = registry->RegisterStream(origin_, source); + result = registry->RegisterStream( + render_process_id_, render_view_id_, origin_, source); } SetResult(new base::StringValue(result)); diff --git a/chrome/browser/extensions/api/desktop_capture/desktop_capture_api.h b/chrome/browser/extensions/api/desktop_capture/desktop_capture_api.h index 862decf..2073547 100644 --- a/chrome/browser/extensions/api/desktop_capture/desktop_capture_api.h +++ b/chrome/browser/extensions/api/desktop_capture/desktop_capture_api.h @@ -52,8 +52,9 @@ class DesktopCaptureChooseDesktopMediaFunction : public AsyncExtensionFunction { int request_id_; - // Origin parameter specified when chooseDesktopMedia() was called. Indicates - // origin of the target page to use the media source chosen by the user. + // Parameters of the tab the stream is requested for. + int render_process_id_; + int render_view_id_; GURL origin_; scoped_ptr<DesktopMediaPicker> picker_; diff --git a/chrome/browser/media/desktop_streams_registry.cc b/chrome/browser/media/desktop_streams_registry.cc index 0c87357..64e4160 100644 --- a/chrome/browser/media/desktop_streams_registry.cc +++ b/chrome/browser/media/desktop_streams_registry.cc @@ -33,12 +33,16 @@ DesktopStreamsRegistry::DesktopStreamsRegistry() {} DesktopStreamsRegistry::~DesktopStreamsRegistry() {} std::string DesktopStreamsRegistry::RegisterStream( + int render_process_id, + int render_view_id, const GURL& origin, const content::DesktopMediaID& source) { DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)); std::string id = GenerateRandomStreamId(); ApprovedDesktopMediaStream& stream = approved_streams_[id]; + stream.render_process_id = render_process_id; + stream.render_view_id = render_view_id; stream.origin = origin; stream.source = source; @@ -53,12 +57,22 @@ std::string DesktopStreamsRegistry::RegisterStream( content::DesktopMediaID DesktopStreamsRegistry::RequestMediaForStreamId( const std::string& id, + int render_process_id, + int render_view_id, const GURL& origin) { DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)); StreamsMap::iterator it = approved_streams_.find(id); - if (it == approved_streams_.end() || origin != it->second.origin) + + // Verify that if there is a request with the specified ID it was created for + // the same origin and the same renderer. + if (it == approved_streams_.end() || + render_process_id != it->second.render_process_id || + render_view_id != it->second.render_view_id || + origin != it->second.origin) { return content::DesktopMediaID(); + } + content::DesktopMediaID result = it->second.source; approved_streams_.erase(it); return result; diff --git a/chrome/browser/media/desktop_streams_registry.h b/chrome/browser/media/desktop_streams_registry.h index 348708c..2399c72 100644 --- a/chrome/browser/media/desktop_streams_registry.h +++ b/chrome/browser/media/desktop_streams_registry.h @@ -22,7 +22,9 @@ class DesktopStreamsRegistry { // Adds new stream to the registry. Called by the implementation of // desktopCapture.chooseDesktopMedia() API after user has approved access to // |source| for the |origin|. Returns identifier of the new stream. - std::string RegisterStream(const GURL& origin, + std::string RegisterStream(int render_process_id, + int render_view_id, + const GURL& origin, const content::DesktopMediaID& source); // Validates stream identifier specified in getUserMedia(). Returns null @@ -30,11 +32,15 @@ class DesktopStreamsRegistry { // using RegisterStream() or if it was generated for a different origin. // Otherwise returns ID of the source and removes it from the registry. content::DesktopMediaID RequestMediaForStreamId(const std::string& id, + int render_process_id, + int render_view_id, const GURL& origin); private: // Type used to store list of accepted desktop media streams. struct ApprovedDesktopMediaStream { + int render_process_id; + int render_view_id; GURL origin; content::DesktopMediaID source; }; diff --git a/chrome/browser/media/media_capture_devices_dispatcher.cc b/chrome/browser/media/media_capture_devices_dispatcher.cc index 09dc5dd..12b56b7 100644 --- a/chrome/browser/media/media_capture_devices_dispatcher.cc +++ b/chrome/browser/media/media_capture_devices_dispatcher.cc @@ -236,7 +236,8 @@ void MediaCaptureDevicesDispatcher::ProcessDesktopCaptureAccessRequest( // chrome.desktopCapture.chooseDesktopMedia()) was used to generate device Id. content::DesktopMediaID media_id = GetDesktopStreamsRegistry()->RequestMediaForStreamId( - request.requested_video_device_id, request.security_origin); + request.requested_video_device_id, request.render_process_id, + request.render_view_id, request.security_origin); // If the id wasn't generated using Desktop Capture API then process it as a // screen capture request. diff --git a/chrome/common/extensions/api/api.gyp b/chrome/common/extensions/api/api.gyp index 885f9dc..84e2f28 100644 --- a/chrome/common/extensions/api/api.gyp +++ b/chrome/common/extensions/api/api.gyp @@ -42,7 +42,7 @@ 'context_menus.json', 'cookies.json', 'debugger.json', - 'desktop_capture.idl', + 'desktop_capture.json', 'developer_private.idl', 'dial.idl', 'dns.idl', diff --git a/chrome/common/extensions/api/desktop_capture.idl b/chrome/common/extensions/api/desktop_capture.idl deleted file mode 100644 index 7a62207..0000000 --- a/chrome/common/extensions/api/desktop_capture.idl +++ /dev/null @@ -1,43 +0,0 @@ -// Copyright 2013 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -// Desktop Capture API that can be used to capture content of screen or -// individual windows or tabs. -namespace desktopCapture { - // Enum used to define set of desktop media sources used in - // chooseDesktopMedia(). - enum DesktopCaptureSourceType { - screen, - window, - tab - }; - - // |streamId|: An opaque string that can be passed to - // <code>getUserMedia()</code> API to generate media stream that corresponds - // to the source selected by the user. If user didn't select any source - // (i.e. canceled the prompt) then the callback is called with an empty - // <code>streamId</code>. - callback ChooseDesktopMediaCallback = void (DOMString streamId); - - interface Functions { - // Shows desktop media picker UI with the specified set of sources. Returns - // an id that can be passed to cancelChooseDesktopMedia() in case the prompt - // need to be canceled. - // - // |sources|: Set of sources that should be shown to the user. - // - // |origin|: Optional origin of the page for which the stream is created. If - // not specified then the resulting stream can be used only the calling - // extension, otherwise the stream can be used only by a page with the - // specified origin. - static long chooseDesktopMedia(DesktopCaptureSourceType[] sources, - optional DOMString origin, - ChooseDesktopMediaCallback callback); - - // Hides desktop media picker dialog shown by chooseDesktopMedia(). - // - // |desktopMediaRequestId|: Id returned by chooseDesktopMedia() - static void cancelChooseDesktopMedia(long desktopMediaRequestId); - }; -}; diff --git a/chrome/common/extensions/api/desktop_capture.json b/chrome/common/extensions/api/desktop_capture.json new file mode 100644 index 0000000..8359a7b --- /dev/null +++ b/chrome/common/extensions/api/desktop_capture.json @@ -0,0 +1,66 @@ +// Copyright 2013 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +[ + { + "namespace": "desktopCapture", + "description": "Desktop Capture API that can be used to capture content of screen, individual windows or tabs.", + "types": [ + { + "id": "DesktopCaptureSourceType", + "type": "string", + "enum": ["screen", "window", "tab"], + "description": "Enum used to define set of desktop media sources used in chooseDesktopMedia()." + } + ], + "functions": [ + { + "name": "chooseDesktopMedia", + "type": "function", + "description": "Shows desktop media picker UI with the specified set of sources.", + "parameters": [ + { + "type": "array", + "items": { "$ref": "DesktopCaptureSourceType" }, + "name": "sources", + "description": "Set of sources that should be shown to the user." + }, + { + "$ref": "tabs.Tab", + "name": "targetTab", + "optional": true, + "description": "Optional tab for which the stream is created. If not specified then the resulting stream can be used only by the calling extension, otherwise the stream can be used only by the specified tab. If the tab's security origin changes before this function returns, the call may fail." + }, + { + "type": "function", + "name": "callback", + "parameters": [ + { + "name": "streamId", + "type": "string", + "description": "An opaque string that can be passed to <code>getUserMedia()</code> API to generate media stream that corresponds to the source selected by the user. If user didn't select any source (i.e. canceled the prompt) then the callback is called with an empty <code>streamId</code>" + } + ] + } + ], + "returns": { + "type": "integer", + "description": "An id that can be passed to cancelChooseDesktopMedia() in case the prompt need to be canceled." + } + }, + { + "name": "cancelChooseDesktopMedia", + "type": "function", + "description": "Hides desktop media picker dialog shown by chooseDesktopMedia().", + "parameters": [ + { + "name": "desktopMediaRequestId", + "type": "integer", + "description": "Id returned by chooseDesktopMedia()" + } + ] + } + ] + } +] diff --git a/chrome/renderer/resources/extensions/desktop_capture_custom_bindings.js b/chrome/renderer/resources/extensions/desktop_capture_custom_bindings.js index a81f8a0..3176009 100644 --- a/chrome/renderer/resources/extensions/desktop_capture_custom_bindings.js +++ b/chrome/renderer/resources/extensions/desktop_capture_custom_bindings.js @@ -22,16 +22,16 @@ binding.registerCustomHook(function(bindingsAPI) { } apiFunctions.setHandleRequest('chooseDesktopMedia', - function(sources, origin, callback) { - // |origin| is an optional parameter. + function(sources, target_tab, callback) { + // |target_tab| is an optional parameter. if (callback === undefined) { - callback = origin; - origin = undefined; + callback = target_tab; + target_tab = undefined; } var id = idGenerator.GetNextId(); pendingRequests[id] = callback; sendRequest(this.name, - [id, sources, origin, onRequestResult.bind(null, id)], + [id, sources, target_tab, onRequestResult.bind(null, id)], this.definition.parameters, {}); return id; }); diff --git a/chrome/test/data/extensions/api_test/desktop_capture_delegate/background.js b/chrome/test/data/extensions/api_test/desktop_capture_delegate/background.js index 79dae9f..25686e0 100644 --- a/chrome/test/data/extensions/api_test/desktop_capture_delegate/background.js +++ b/chrome/test/data/extensions/api_test/desktop_capture_delegate/background.js @@ -4,10 +4,9 @@ chrome.runtime.onMessageExternal.addListener(function(message, sender, reply) { if (message[0] == "getStream") { - origin = message[1]; chrome.desktopCapture.chooseDesktopMedia( ["screen", "window"], - origin, + sender.tab, function(id) { reply({"id": id}); }); diff --git a/chrome/test/data/extensions/api_test/desktop_capture_delegate/example.com.html b/chrome/test/data/extensions/api_test/desktop_capture_delegate/example.com.html index 70cce98..50b9f48 100644 --- a/chrome/test/data/extensions/api_test/desktop_capture_delegate/example.com.html +++ b/chrome/test/data/extensions/api_test/desktop_capture_delegate/example.com.html @@ -23,7 +23,7 @@ function requestStreamId(callback) { }; chrome.runtime.sendMessage( - extensionId, ["getStream", document.location.origin + "/"], onResponse); + extensionId, ["getStream"], onResponse); } function getStream() { |