summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorsergeyu@chromium.org <sergeyu@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2013-10-16 17:50:53 +0000
committersergeyu@chromium.org <sergeyu@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2013-10-16 17:50:53 +0000
commit21dc780764094b92ab97334174a051c3e12a4216 (patch)
tree54b39d85d79d665ba1c7374687a1da71c1bc25db
parentd30f31be5176bfd80d5d193fb3f3f2658921fb75 (diff)
downloadchromium_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
-rw-r--r--chrome/browser/extensions/api/desktop_capture/desktop_capture_api.cc66
-rw-r--r--chrome/browser/extensions/api/desktop_capture/desktop_capture_api.h5
-rw-r--r--chrome/browser/media/desktop_streams_registry.cc16
-rw-r--r--chrome/browser/media/desktop_streams_registry.h8
-rw-r--r--chrome/browser/media/media_capture_devices_dispatcher.cc3
-rw-r--r--chrome/common/extensions/api/api.gyp2
-rw-r--r--chrome/common/extensions/api/desktop_capture.idl43
-rw-r--r--chrome/common/extensions/api/desktop_capture.json66
-rw-r--r--chrome/renderer/resources/extensions/desktop_capture_custom_bindings.js10
-rw-r--r--chrome/test/data/extensions/api_test/desktop_capture_delegate/background.js3
-rw-r--r--chrome/test/data/extensions/api_test/desktop_capture_delegate/example.com.html2
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() {