summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--apps/custom_launcher_page_contents.cc8
-rw-r--r--apps/custom_launcher_page_contents.h4
-rw-r--r--athena/extensions/chrome/athena_app_delegate.cc10
-rw-r--r--athena/extensions/chrome/athena_app_delegate.h5
-rw-r--r--chrome/browser/android/chrome_web_contents_delegate_android.cc8
-rw-r--r--chrome/browser/android/chrome_web_contents_delegate_android.h4
-rw-r--r--chrome/browser/chromeos/login/ui/webui_login_view.cc9
-rw-r--r--chrome/browser/chromeos/login/ui/webui_login_view.h4
-rw-r--r--chrome/browser/extensions/chrome_extension_host_delegate.cc10
-rw-r--r--chrome/browser/extensions/chrome_extension_host_delegate.h4
-rw-r--r--chrome/browser/guest_view/web_view/chrome_web_view_permission_helper_delegate.cc13
-rw-r--r--chrome/browser/guest_view/web_view/chrome_web_view_permission_helper_delegate.h4
-rw-r--r--chrome/browser/media/media_capture_devices_dispatcher.cc63
-rw-r--r--chrome/browser/media/media_capture_devices_dispatcher.h14
-rw-r--r--chrome/browser/ui/app_list/start_page_service.cc8
-rw-r--r--chrome/browser/ui/apps/chrome_app_delegate.cc10
-rw-r--r--chrome/browser/ui/apps/chrome_app_delegate.h5
-rw-r--r--chrome/browser/ui/browser.cc6
-rw-r--r--chrome/browser/ui/browser.h4
-rw-r--r--chrome/browser/ui/media_utils.cc50
-rw-r--r--chrome/browser/ui/media_utils.h6
-rw-r--r--content/browser/frame_host/render_frame_host_delegate.cc8
-rw-r--r--content/browser/frame_host/render_frame_host_delegate.h6
-rw-r--r--content/browser/renderer_host/media/media_stream_dispatcher_host_unittest.cc53
-rw-r--r--content/browser/renderer_host/media/media_stream_manager.cc42
-rw-r--r--content/browser/renderer_host/media/media_stream_manager.h5
-rw-r--r--content/browser/renderer_host/media/media_stream_ui_proxy.cc125
-rw-r--r--content/browser/renderer_host/media/media_stream_ui_proxy.h24
-rw-r--r--content/browser/renderer_host/media/media_stream_ui_proxy_unittest.cc16
-rw-r--r--content/browser/web_contents/web_contents_impl.cc8
-rw-r--r--content/browser/web_contents/web_contents_impl.h2
-rw-r--r--content/public/browser/web_contents_delegate.cc9
-rw-r--r--content/public/browser/web_contents_delegate.h7
-rw-r--r--extensions/browser/app_window/app_delegate.h4
-rw-r--r--extensions/browser/app_window/app_web_contents_helper.cc11
-rw-r--r--extensions/browser/app_window/app_web_contents_helper.h5
-rw-r--r--extensions/browser/app_window/app_window.cc7
-rw-r--r--extensions/browser/app_window/app_window.h4
-rw-r--r--extensions/browser/extension_host.cc8
-rw-r--r--extensions/browser/extension_host.h4
-rw-r--r--extensions/browser/extension_host_delegate.h8
-rw-r--r--extensions/browser/guest_view/web_view/web_view_guest.cc7
-rw-r--r--extensions/browser/guest_view/web_view/web_view_guest.h4
-rw-r--r--extensions/browser/guest_view/web_view/web_view_permission_helper.cc10
-rw-r--r--extensions/browser/guest_view/web_view/web_view_permission_helper.h3
-rw-r--r--extensions/browser/guest_view/web_view/web_view_permission_helper_delegate.cc8
-rw-r--r--extensions/browser/guest_view/web_view/web_view_permission_helper_delegate.h4
-rw-r--r--extensions/shell/browser/media_capture_util.cc27
-rw-r--r--extensions/shell/browser/media_capture_util.h4
-rw-r--r--extensions/shell/browser/shell_app_delegate.cc9
-rw-r--r--extensions/shell/browser/shell_app_delegate.h4
-rw-r--r--extensions/shell/browser/shell_extension_host_delegate.cc10
-rw-r--r--extensions/shell/browser/shell_extension_host_delegate.h4
53 files changed, 583 insertions, 116 deletions
diff --git a/apps/custom_launcher_page_contents.cc b/apps/custom_launcher_page_contents.cc
index 023c305..7a2f4b2 100644
--- a/apps/custom_launcher_page_contents.cc
+++ b/apps/custom_launcher_page_contents.cc
@@ -126,6 +126,14 @@ void CustomLauncherPageContents::RequestMediaAccessPermission(
helper_->RequestMediaAccessPermission(request, callback);
}
+bool CustomLauncherPageContents::CheckMediaAccessPermission(
+ content::WebContents* web_contents,
+ const GURL& security_origin,
+ content::MediaStreamType type) {
+ DCHECK_EQ(web_contents_.get(), web_contents);
+ return helper_->CheckMediaAccessPermission(security_origin, type);
+}
+
bool CustomLauncherPageContents::OnMessageReceived(
const IPC::Message& message) {
bool handled = true;
diff --git a/apps/custom_launcher_page_contents.h b/apps/custom_launcher_page_contents.h
index 36e7f79..eaa7673 100644
--- a/apps/custom_launcher_page_contents.h
+++ b/apps/custom_launcher_page_contents.h
@@ -71,6 +71,10 @@ class CustomLauncherPageContents
content::WebContents* web_contents,
const content::MediaStreamRequest& request,
const content::MediaResponseCallback& callback) OVERRIDE;
+ virtual bool CheckMediaAccessPermission(
+ content::WebContents* web_contents,
+ const GURL& security_origin,
+ content::MediaStreamType type) OVERRIDE;
private:
// content::WebContentsObserver overrides:
diff --git a/athena/extensions/chrome/athena_app_delegate.cc b/athena/extensions/chrome/athena_app_delegate.cc
index 64d8d0a..1046cc7 100644
--- a/athena/extensions/chrome/athena_app_delegate.cc
+++ b/athena/extensions/chrome/athena_app_delegate.cc
@@ -146,6 +146,16 @@ void AthenaAppDelegate::RequestMediaAccessPermission(
web_contents, request, callback, extension);
}
+bool AthenaAppDelegate::CheckMediaAccessPermission(
+ content::WebContents* web_contents,
+ const GURL& security_origin,
+ content::MediaStreamType type,
+ const extensions::Extension* extension) {
+ return MediaCaptureDevicesDispatcher::GetInstance()
+ ->CheckMediaAccessPermission(
+ web_contents, security_origin, type, extension);
+}
+
int AthenaAppDelegate::PreferredIconSize() {
// TODO(oshima): Find out what to use.
return extension_misc::EXTENSION_ICON_SMALL;
diff --git a/athena/extensions/chrome/athena_app_delegate.h b/athena/extensions/chrome/athena_app_delegate.h
index 0c41a7b..90d0496 100644
--- a/athena/extensions/chrome/athena_app_delegate.h
+++ b/athena/extensions/chrome/athena_app_delegate.h
@@ -45,6 +45,11 @@ class AthenaAppDelegate : public extensions::AppDelegate {
const content::MediaStreamRequest& request,
const content::MediaResponseCallback& callback,
const extensions::Extension* extension) OVERRIDE;
+ virtual bool CheckMediaAccessPermission(
+ content::WebContents* web_contents,
+ const GURL& security_origin,
+ content::MediaStreamType type,
+ const extensions::Extension* extension) OVERRIDE;
virtual int PreferredIconSize() OVERRIDE;
virtual gfx::ImageSkia GetAppDefaultIcon() OVERRIDE;
virtual void SetWebContentsBlocked(content::WebContents* web_contents,
diff --git a/chrome/browser/android/chrome_web_contents_delegate_android.cc b/chrome/browser/android/chrome_web_contents_delegate_android.cc
index 5da0e30..6463083 100644
--- a/chrome/browser/android/chrome_web_contents_delegate_android.cc
+++ b/chrome/browser/android/chrome_web_contents_delegate_android.cc
@@ -226,6 +226,14 @@ void ChromeWebContentsDelegateAndroid::RequestMediaAccessPermission(
web_contents, request, callback, NULL);
}
+bool ChromeWebContentsDelegateAndroid::CheckMediaAccessPermission(
+ content::WebContents* web_contents,
+ const GURL& security_origin,
+ content::MediaStreamType type) {
+ return MediaCaptureDevicesDispatcher::GetInstance()
+ ->CheckMediaAccessPermission(web_contents, security_origin, type);
+}
+
bool ChromeWebContentsDelegateAndroid::RequestPpapiBrokerPermission(
WebContents* web_contents,
const GURL& url,
diff --git a/chrome/browser/android/chrome_web_contents_delegate_android.h b/chrome/browser/android/chrome_web_contents_delegate_android.h
index 2b2bef1..e7fdccd 100644
--- a/chrome/browser/android/chrome_web_contents_delegate_android.h
+++ b/chrome/browser/android/chrome_web_contents_delegate_android.h
@@ -59,6 +59,10 @@ class ChromeWebContentsDelegateAndroid
content::WebContents* web_contents,
const content::MediaStreamRequest& request,
const content::MediaResponseCallback& callback) OVERRIDE;
+ virtual bool CheckMediaAccessPermission(
+ content::WebContents* web_contents,
+ const GURL& security_origin,
+ content::MediaStreamType type) OVERRIDE;
virtual bool RequestPpapiBrokerPermission(
content::WebContents* web_contents,
const GURL& url,
diff --git a/chrome/browser/chromeos/login/ui/webui_login_view.cc b/chrome/browser/chromeos/login/ui/webui_login_view.cc
index 6bd2ea7..9fac03a 100644
--- a/chrome/browser/chromeos/login/ui/webui_login_view.cc
+++ b/chrome/browser/chromeos/login/ui/webui_login_view.cc
@@ -19,6 +19,7 @@
#include "chrome/browser/chromeos/login/ui/webui_login_display.h"
#include "chrome/browser/chromeos/profiles/profile_helper.h"
#include "chrome/browser/extensions/chrome_extension_web_contents_observer.h"
+#include "chrome/browser/media/media_capture_devices_dispatcher.h"
#include "chrome/browser/media/media_stream_infobar_delegate.h"
#include "chrome/browser/password_manager/chrome_password_manager_client.h"
#include "chrome/browser/renderer_preferences_util.h"
@@ -452,6 +453,14 @@ void WebUILoginView::RequestMediaAccessPermission(
NOTREACHED() << "Media stream not allowed for WebUI";
}
+bool WebUILoginView::CheckMediaAccessPermission(
+ content::WebContents* web_contents,
+ const GURL& security_origin,
+ content::MediaStreamType type) {
+ return MediaCaptureDevicesDispatcher::GetInstance()
+ ->CheckMediaAccessPermission(web_contents, security_origin, type);
+}
+
bool WebUILoginView::PreHandleGestureEvent(
content::WebContents* source,
const blink::WebGestureEvent& event) {
diff --git a/chrome/browser/chromeos/login/ui/webui_login_view.h b/chrome/browser/chromeos/login/ui/webui_login_view.h
index 82713db..b48964d 100644
--- a/chrome/browser/chromeos/login/ui/webui_login_view.h
+++ b/chrome/browser/chromeos/login/ui/webui_login_view.h
@@ -147,6 +147,10 @@ class WebUILoginView : public views::View,
content::WebContents* web_contents,
const content::MediaStreamRequest& request,
const content::MediaResponseCallback& callback) OVERRIDE;
+ virtual bool CheckMediaAccessPermission(
+ content::WebContents* web_contents,
+ const GURL& security_origin,
+ content::MediaStreamType type) OVERRIDE;
virtual bool PreHandleGestureEvent(
content::WebContents* source,
const blink::WebGestureEvent& event) OVERRIDE;
diff --git a/chrome/browser/extensions/chrome_extension_host_delegate.cc b/chrome/browser/extensions/chrome_extension_host_delegate.cc
index 2b23d82..aaf9fca 100644
--- a/chrome/browser/extensions/chrome_extension_host_delegate.cc
+++ b/chrome/browser/extensions/chrome_extension_host_delegate.cc
@@ -56,4 +56,14 @@ void ChromeExtensionHostDelegate::ProcessMediaAccessRequest(
web_contents, request, callback, extension);
}
+bool ChromeExtensionHostDelegate::CheckMediaAccessPermission(
+ content::WebContents* web_contents,
+ const GURL& security_origin,
+ content::MediaStreamType type,
+ const Extension* extension) {
+ return MediaCaptureDevicesDispatcher::GetInstance()
+ ->CheckMediaAccessPermission(
+ web_contents, security_origin, type, extension);
+}
+
} // namespace extensions
diff --git a/chrome/browser/extensions/chrome_extension_host_delegate.h b/chrome/browser/extensions/chrome_extension_host_delegate.h
index 207cd68..da8bcb2 100644
--- a/chrome/browser/extensions/chrome_extension_host_delegate.h
+++ b/chrome/browser/extensions/chrome_extension_host_delegate.h
@@ -32,6 +32,10 @@ class ChromeExtensionHostDelegate : public ExtensionHostDelegate {
const content::MediaStreamRequest& request,
const content::MediaResponseCallback& callback,
const Extension* extension) OVERRIDE;
+ virtual bool CheckMediaAccessPermission(content::WebContents* web_contents,
+ const GURL& security_origin,
+ content::MediaStreamType type,
+ const Extension* extension) OVERRIDE;
};
} // namespace extensions
diff --git a/chrome/browser/guest_view/web_view/chrome_web_view_permission_helper_delegate.cc b/chrome/browser/guest_view/web_view/chrome_web_view_permission_helper_delegate.cc
index 3279b88..07d924c 100644
--- a/chrome/browser/guest_view/web_view/chrome_web_view_permission_helper_delegate.cc
+++ b/chrome/browser/guest_view/web_view/chrome_web_view_permission_helper_delegate.cc
@@ -138,7 +138,18 @@ void ChromeWebViewPermissionHelperDelegate::RequestMediaAccessPermission(
false /* allowed_by_default */);
}
- void ChromeWebViewPermissionHelperDelegate::OnMediaPermissionResponse(
+bool ChromeWebViewPermissionHelperDelegate::CheckMediaAccessPermission(
+ content::WebContents* source,
+ const GURL& security_origin,
+ content::MediaStreamType type) {
+ return web_view_guest()
+ ->embedder_web_contents()
+ ->GetDelegate()
+ ->CheckMediaAccessPermission(
+ web_view_guest()->embedder_web_contents(), security_origin, type);
+}
+
+void ChromeWebViewPermissionHelperDelegate::OnMediaPermissionResponse(
const content::MediaStreamRequest& request,
const content::MediaResponseCallback& callback,
bool allow,
diff --git a/chrome/browser/guest_view/web_view/chrome_web_view_permission_helper_delegate.h b/chrome/browser/guest_view/web_view/chrome_web_view_permission_helper_delegate.h
index fbf5bab..d8a9fb2 100644
--- a/chrome/browser/guest_view/web_view/chrome_web_view_permission_helper_delegate.h
+++ b/chrome/browser/guest_view/web_view/chrome_web_view_permission_helper_delegate.h
@@ -24,6 +24,10 @@ class ChromeWebViewPermissionHelperDelegate :
content::WebContents* source,
const content::MediaStreamRequest& request,
const content::MediaResponseCallback& callback) OVERRIDE;
+ virtual bool CheckMediaAccessPermission(
+ content::WebContents* source,
+ const GURL& security_origin,
+ content::MediaStreamType type) OVERRIDE;
virtual void CanDownload(
content::RenderViewHost* render_view_host,
const GURL& url,
diff --git a/chrome/browser/media/media_capture_devices_dispatcher.cc b/chrome/browser/media/media_capture_devices_dispatcher.cc
index a3a1ddc..ed05b5f 100644
--- a/chrome/browser/media/media_capture_devices_dispatcher.cc
+++ b/chrome/browser/media/media_capture_devices_dispatcher.cc
@@ -403,6 +403,69 @@ bool MediaCaptureDevicesDispatcher::CheckMediaAccessPermission(
return false;
}
+bool MediaCaptureDevicesDispatcher::CheckMediaAccessPermission(
+ content::WebContents* web_contents,
+ const GURL& security_origin,
+ content::MediaStreamType type) {
+ DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
+ DCHECK(type == content::MEDIA_DEVICE_AUDIO_CAPTURE ||
+ type == content::MEDIA_DEVICE_VIDEO_CAPTURE);
+
+ Profile* profile =
+ Profile::FromBrowserContext(web_contents->GetBrowserContext());
+
+ if (CheckAllowAllMediaStreamContentForOrigin(profile, security_origin))
+ return true;
+
+ const char* policy_name = type == content::MEDIA_DEVICE_AUDIO_CAPTURE
+ ? prefs::kAudioCaptureAllowed
+ : prefs::kVideoCaptureAllowed;
+ const char* list_policy_name = type == content::MEDIA_DEVICE_AUDIO_CAPTURE
+ ? prefs::kAudioCaptureAllowedUrls
+ : prefs::kVideoCaptureAllowedUrls;
+ if (GetDevicePolicy(
+ profile, security_origin, policy_name, list_policy_name) ==
+ ALWAYS_ALLOW) {
+ return true;
+ }
+
+ // There's no secondary URL for these content types, hence duplicating
+ // |security_origin|.
+ if (profile->GetHostContentSettingsMap()->GetContentSetting(
+ security_origin,
+ security_origin,
+ type == content::MEDIA_DEVICE_AUDIO_CAPTURE
+ ? CONTENT_SETTINGS_TYPE_MEDIASTREAM_MIC
+ : CONTENT_SETTINGS_TYPE_MEDIASTREAM_CAMERA,
+ NO_RESOURCE_IDENTIFIER) == CONTENT_SETTING_ALLOW) {
+ return true;
+ }
+
+ return false;
+}
+
+#if defined(ENABLE_EXTENSIONS)
+bool MediaCaptureDevicesDispatcher::CheckMediaAccessPermission(
+ content::WebContents* web_contents,
+ const GURL& security_origin,
+ content::MediaStreamType type,
+ const extensions::Extension* extension) {
+ DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
+ DCHECK(type == content::MEDIA_DEVICE_AUDIO_CAPTURE ||
+ type == content::MEDIA_DEVICE_VIDEO_CAPTURE);
+
+ if (extension->is_platform_app() ||
+ IsMediaRequestWhitelistedForExtension(extension)) {
+ return extension->permissions_data()->HasAPIPermission(
+ type == content::MEDIA_DEVICE_AUDIO_CAPTURE
+ ? extensions::APIPermission::kAudioCapture
+ : extensions::APIPermission::kVideoCapture);
+ }
+
+ return CheckMediaAccessPermission(web_contents, security_origin, type);
+}
+#endif
+
void MediaCaptureDevicesDispatcher::ProcessDesktopCaptureAccessRequest(
content::WebContents* web_contents,
const content::MediaStreamRequest& request,
diff --git a/chrome/browser/media/media_capture_devices_dispatcher.h b/chrome/browser/media/media_capture_devices_dispatcher.h
index 162c654..a6930ad 100644
--- a/chrome/browser/media/media_capture_devices_dispatcher.h
+++ b/chrome/browser/media/media_capture_devices_dispatcher.h
@@ -90,6 +90,20 @@ class MediaCaptureDevicesDispatcher : public content::MediaObserver,
const GURL& security_origin,
content::MediaStreamType type);
+ // Method called from WebCapturerDelegate implementations to check media
+ // access permission. Note that this does not query the user.
+ bool CheckMediaAccessPermission(content::WebContents* web_contents,
+ const GURL& security_origin,
+ content::MediaStreamType type);
+
+ // Same as above but for an |extension|, which may not be NULL.
+#if defined(ENABLE_EXTENSIONS)
+ bool CheckMediaAccessPermission(content::WebContents* web_contents,
+ const GURL& security_origin,
+ content::MediaStreamType type,
+ const extensions::Extension* extension);
+#endif
+
// Helper to get the default devices which can be used by the media request.
// Uses the first available devices if the default devices are not available.
// If the return list is empty, it means there is no available device on the
diff --git a/chrome/browser/ui/app_list/start_page_service.cc b/chrome/browser/ui/app_list/start_page_service.cc
index 3615a6e..8392be2 100644
--- a/chrome/browser/ui/app_list/start_page_service.cc
+++ b/chrome/browser/ui/app_list/start_page_service.cc
@@ -88,6 +88,14 @@ class StartPageService::StartPageWebContentsDelegate
NOTREACHED() << "Media stream not allowed for WebUI";
}
+ virtual bool CheckMediaAccessPermission(
+ content::WebContents* web_contents,
+ const GURL& security_origin,
+ content::MediaStreamType type) OVERRIDE {
+ return MediaCaptureDevicesDispatcher::GetInstance()
+ ->CheckMediaAccessPermission(web_contents, security_origin, type);
+ }
+
private:
DISALLOW_COPY_AND_ASSIGN(StartPageWebContentsDelegate);
};
diff --git a/chrome/browser/ui/apps/chrome_app_delegate.cc b/chrome/browser/ui/apps/chrome_app_delegate.cc
index 2cf0588..d146250 100644
--- a/chrome/browser/ui/apps/chrome_app_delegate.cc
+++ b/chrome/browser/ui/apps/chrome_app_delegate.cc
@@ -245,6 +245,16 @@ void ChromeAppDelegate::RequestMediaAccessPermission(
web_contents, request, callback, extension);
}
+bool ChromeAppDelegate::CheckMediaAccessPermission(
+ content::WebContents* web_contents,
+ const GURL& security_origin,
+ content::MediaStreamType type,
+ const extensions::Extension* extension) {
+ return MediaCaptureDevicesDispatcher::GetInstance()
+ ->CheckMediaAccessPermission(
+ web_contents, security_origin, type, extension);
+}
+
int ChromeAppDelegate::PreferredIconSize() {
#if defined(USE_ASH)
return ash::kShelfSize;
diff --git a/chrome/browser/ui/apps/chrome_app_delegate.h b/chrome/browser/ui/apps/chrome_app_delegate.h
index 382dda4..3e9e444 100644
--- a/chrome/browser/ui/apps/chrome_app_delegate.h
+++ b/chrome/browser/ui/apps/chrome_app_delegate.h
@@ -54,6 +54,11 @@ class ChromeAppDelegate : public extensions::AppDelegate,
const content::MediaStreamRequest& request,
const content::MediaResponseCallback& callback,
const extensions::Extension* extension) OVERRIDE;
+ virtual bool CheckMediaAccessPermission(
+ content::WebContents* web_contents,
+ const GURL& security_origin,
+ content::MediaStreamType type,
+ const extensions::Extension* extension) OVERRIDE;
virtual int PreferredIconSize() OVERRIDE;
virtual gfx::ImageSkia GetAppDefaultIcon() OVERRIDE;
virtual void SetWebContentsBlocked(content::WebContents* web_contents,
diff --git a/chrome/browser/ui/browser.cc b/chrome/browser/ui/browser.cc
index 6770f8e..0525e02 100644
--- a/chrome/browser/ui/browser.cc
+++ b/chrome/browser/ui/browser.cc
@@ -1759,6 +1759,12 @@ void Browser::RequestMediaAccessPermission(
::RequestMediaAccessPermission(web_contents, profile_, request, callback);
}
+bool Browser::CheckMediaAccessPermission(content::WebContents* web_contents,
+ const GURL& security_origin,
+ content::MediaStreamType type) {
+ return ::CheckMediaAccessPermission(web_contents, security_origin, type);
+}
+
bool Browser::RequestPpapiBrokerPermission(
WebContents* web_contents,
const GURL& url,
diff --git a/chrome/browser/ui/browser.h b/chrome/browser/ui/browser.h
index 5f358cb..02e343c 100644
--- a/chrome/browser/ui/browser.h
+++ b/chrome/browser/ui/browser.h
@@ -647,6 +647,10 @@ class Browser : public TabStripModelObserver,
content::WebContents* web_contents,
const content::MediaStreamRequest& request,
const content::MediaResponseCallback& callback) OVERRIDE;
+ virtual bool CheckMediaAccessPermission(
+ content::WebContents* web_contents,
+ const GURL& security_origin,
+ content::MediaStreamType type) OVERRIDE;
virtual bool RequestPpapiBrokerPermission(
content::WebContents* web_contents,
const GURL& url,
diff --git a/chrome/browser/ui/media_utils.cc b/chrome/browser/ui/media_utils.cc
index 7101cc4..52d4633 100644
--- a/chrome/browser/ui/media_utils.cc
+++ b/chrome/browser/ui/media_utils.cc
@@ -6,6 +6,7 @@
#include "chrome/browser/media/media_capture_devices_dispatcher.h"
#include "chrome/browser/profiles/profile.h"
+#include "content/public/browser/web_contents.h"
#if defined(ENABLE_EXTENSIONS)
#include "chrome/browser/extensions/extension_service.h"
@@ -13,11 +14,24 @@
#include "extensions/common/constants.h"
#endif
-class Profile;
+namespace {
-namespace content {
-class WebContents;
+#if defined(ENABLE_EXTENSIONS)
+const extensions::Extension* GetExtensionForOrigin(Profile* profile,
+ const GURL& security_origin) {
+ if (!security_origin.SchemeIs(extensions::kExtensionScheme))
+ return NULL;
+
+ ExtensionService* extensions_service =
+ extensions::ExtensionSystem::Get(profile)->extension_service();
+ const extensions::Extension* extension =
+ extensions_service->extensions()->GetByID(security_origin.host());
+ DCHECK(extension);
+ return extension;
}
+#endif
+
+} // namespace
void RequestMediaAccessPermission(
content::WebContents* web_contents,
@@ -26,15 +40,29 @@ void RequestMediaAccessPermission(
const content::MediaResponseCallback& callback) {
const extensions::Extension* extension = NULL;
#if defined(ENABLE_EXTENSIONS)
- GURL origin(request.security_origin);
- if (origin.SchemeIs(extensions::kExtensionScheme)) {
- ExtensionService* extensions_service =
- extensions::ExtensionSystem::Get(profile)->extension_service();
- extension = extensions_service->extensions()->GetByID(origin.host());
- DCHECK(extension);
- }
+ extension = GetExtensionForOrigin(profile, request.security_origin);
#endif
-
MediaCaptureDevicesDispatcher::GetInstance()->ProcessMediaAccessRequest(
web_contents, request, callback, extension);
}
+
+bool CheckMediaAccessPermission(content::WebContents* web_contents,
+ const GURL& security_origin,
+ content::MediaStreamType type) {
+#if defined(ENABLE_EXTENSIONS)
+ Profile* profile =
+ Profile::FromBrowserContext(web_contents->GetBrowserContext());
+ const extensions::Extension* extension =
+ GetExtensionForOrigin(profile, security_origin);
+ if (extension) {
+ return MediaCaptureDevicesDispatcher::GetInstance()
+ ->CheckMediaAccessPermission(
+ web_contents, security_origin, type, extension);
+ }
+ return MediaCaptureDevicesDispatcher::GetInstance()
+ ->CheckMediaAccessPermission(web_contents, security_origin, type);
+#else
+ return MediaCaptureDevicesDispatcher::GetInstance()
+ ->CheckMediaAccessPermission(web_contents, security_origin, type);
+#endif
+}
diff --git a/chrome/browser/ui/media_utils.h b/chrome/browser/ui/media_utils.h
index 8da821b..5db46e6 100644
--- a/chrome/browser/ui/media_utils.h
+++ b/chrome/browser/ui/media_utils.h
@@ -5,8 +5,10 @@
#ifndef CHROME_BROWSER_UI_MEDIA_UTILS_H_
#define CHROME_BROWSER_UI_MEDIA_UTILS_H_
+#include "base/callback.h"
#include "content/public/common/media_stream_request.h"
+class GURL;
class Profile;
namespace content {
@@ -19,4 +21,8 @@ void RequestMediaAccessPermission(
const content::MediaStreamRequest& request,
const content::MediaResponseCallback& callback);
+bool CheckMediaAccessPermission(content::WebContents* web_contents,
+ const GURL& security_origin,
+ content::MediaStreamType type);
+
#endif // CHROME_BROWSER_UI_MEDIA_UTILS_H_
diff --git a/content/browser/frame_host/render_frame_host_delegate.cc b/content/browser/frame_host/render_frame_host_delegate.cc
index ea95490..b96f2b5 100644
--- a/content/browser/frame_host/render_frame_host_delegate.cc
+++ b/content/browser/frame_host/render_frame_host_delegate.cc
@@ -44,6 +44,14 @@ void RenderFrameHostDelegate::RequestMediaAccessPermission(
scoped_ptr<MediaStreamUI>());
}
+bool RenderFrameHostDelegate::CheckMediaAccessPermission(
+ const GURL& security_origin,
+ MediaStreamType type) {
+ DCHECK(type == MEDIA_DEVICE_AUDIO_CAPTURE ||
+ type == MEDIA_DEVICE_VIDEO_CAPTURE);
+ return false;
+}
+
AccessibilityMode RenderFrameHostDelegate::GetAccessibilityMode() const {
return AccessibilityModeOff;
}
diff --git a/content/browser/frame_host/render_frame_host_delegate.h b/content/browser/frame_host/render_frame_host_delegate.h
index b0ebe38..0d927a4 100644
--- a/content/browser/frame_host/render_frame_host_delegate.h
+++ b/content/browser/frame_host/render_frame_host_delegate.h
@@ -130,6 +130,12 @@ class CONTENT_EXPORT RenderFrameHostDelegate {
const MediaStreamRequest& request,
const MediaResponseCallback& callback);
+ // Checks if we have permission to access the microphone or camera. Note that
+ // this does not query the user. |type| must be MEDIA_DEVICE_AUDIO_CAPTURE
+ // or MEDIA_DEVICE_VIDEO_CAPTURE.
+ virtual bool CheckMediaAccessPermission(const GURL& security_origin,
+ MediaStreamType type);
+
// Get the accessibility mode for the WebContents that owns this frame.
virtual AccessibilityMode GetAccessibilityMode() const;
diff --git a/content/browser/renderer_host/media/media_stream_dispatcher_host_unittest.cc b/content/browser/renderer_host/media/media_stream_dispatcher_host_unittest.cc
index 5f4b7e96..ba78d44 100644
--- a/content/browser/renderer_host/media/media_stream_dispatcher_host_unittest.cc
+++ b/content/browser/renderer_host/media/media_stream_dispatcher_host_unittest.cc
@@ -212,39 +212,6 @@ class MockMediaStreamUIProxy : public FakeMediaStreamUIProxy {
const MediaStreamUIProxy::WindowIdCallback& window_id_callback));
};
-class MediaStreamManagerForTest : public MediaStreamManager {
- public:
- MediaStreamManagerForTest(media::AudioManager* audio_manager)
- : MediaStreamManager(audio_manager),
- mic_access_(true),
- camera_access_(true) {}
-
- virtual ~MediaStreamManagerForTest() {}
-
- void set_mic_access(bool allow_access) {
- mic_access_ = allow_access;
- }
-
- void set_camera_access(bool allow_access) {
- camera_access_ = allow_access;
- }
-
- private:
- virtual bool CheckMediaAccessPermissionOnUIThread(
- int render_process_id,
- const GURL& security_origin,
- MediaStreamType type) OVERRIDE {
- if (type == MEDIA_DEVICE_AUDIO_CAPTURE)
- return mic_access_;
- else if (type == MEDIA_DEVICE_VIDEO_CAPTURE)
- return camera_access_;
- return false;
- }
-
- bool mic_access_;
- bool camera_access_;
-};
-
class MediaStreamDispatcherHostTest : public testing::Test {
public:
MediaStreamDispatcherHostTest()
@@ -257,8 +224,7 @@ class MediaStreamDispatcherHostTest : public testing::Test {
base::CommandLine::ForCurrentProcess()->AppendSwitch(
switches::kUseFakeDeviceForMediaStream);
// Create our own MediaStreamManager.
- media_stream_manager_.reset(
- new MediaStreamManagerForTest(audio_manager_.get()));
+ media_stream_manager_.reset(new MediaStreamManager(audio_manager_.get()));
video_capture_device_factory_ =
static_cast<media::FakeVideoCaptureDeviceFactory*>(
media_stream_manager_->video_capture_manager()
@@ -298,12 +264,12 @@ class MediaStreamDispatcherHostTest : public testing::Test {
protected:
virtual void SetupFakeUI(bool expect_started) {
- scoped_ptr<MockMediaStreamUIProxy> stream_ui(new MockMediaStreamUIProxy());
+ stream_ui_ = new MockMediaStreamUIProxy();
if (expect_started) {
- EXPECT_CALL(*stream_ui, OnStarted(_, _));
+ EXPECT_CALL(*stream_ui_, OnStarted(_, _));
}
media_stream_manager_->UseFakeUI(
- stream_ui.PassAs<FakeMediaStreamUIProxy>());
+ scoped_ptr<FakeMediaStreamUIProxy>(stream_ui_));
}
void GenerateStreamAndWaitForResult(int render_frame_id,
@@ -446,7 +412,8 @@ class MediaStreamDispatcherHostTest : public testing::Test {
scoped_refptr<MockMediaStreamDispatcherHost> host_;
scoped_ptr<media::AudioManager> audio_manager_;
- scoped_ptr<MediaStreamManagerForTest> media_stream_manager_;
+ scoped_ptr<MediaStreamManager> media_stream_manager_;
+ MockMediaStreamUIProxy* stream_ui_;
ContentBrowserClient* old_browser_client_;
scoped_ptr<ContentClient> content_client_;
content::TestBrowserThreadBundle thread_bundle_;
@@ -911,26 +878,30 @@ TEST_F(MediaStreamDispatcherHostTest, VideoDeviceUnplugged) {
}
TEST_F(MediaStreamDispatcherHostTest, EnumerateAudioDevices) {
+ SetupFakeUI(false);
EnumerateDevicesAndWaitForResult(kRenderId, kPageRequestId,
MEDIA_DEVICE_AUDIO_CAPTURE);
EXPECT_TRUE(DoesContainLabels(host_->enumerated_devices_));
}
TEST_F(MediaStreamDispatcherHostTest, EnumerateVideoDevices) {
+ SetupFakeUI(false);
EnumerateDevicesAndWaitForResult(kRenderId, kPageRequestId,
MEDIA_DEVICE_VIDEO_CAPTURE);
EXPECT_TRUE(DoesContainLabels(host_->enumerated_devices_));
}
TEST_F(MediaStreamDispatcherHostTest, EnumerateAudioDevicesNoAccess) {
- media_stream_manager_->set_mic_access(false);
+ SetupFakeUI(false);
+ stream_ui_->SetMicAccess(false);
EnumerateDevicesAndWaitForResult(kRenderId, kPageRequestId,
MEDIA_DEVICE_AUDIO_CAPTURE);
EXPECT_TRUE(DoesNotContainLabels(host_->enumerated_devices_));
}
TEST_F(MediaStreamDispatcherHostTest, EnumerateVideoDevicesNoAccess) {
- media_stream_manager_->set_camera_access(false);
+ SetupFakeUI(false);
+ stream_ui_->SetCameraAccess(false);
EnumerateDevicesAndWaitForResult(kRenderId, kPageRequestId,
MEDIA_DEVICE_VIDEO_CAPTURE);
EXPECT_TRUE(DoesNotContainLabels(host_->enumerated_devices_));
diff --git a/content/browser/renderer_host/media/media_stream_manager.cc b/content/browser/renderer_host/media/media_stream_manager.cc
index 991d174..4080cbe 100644
--- a/content/browser/renderer_host/media/media_stream_manager.cc
+++ b/content/browser/renderer_host/media/media_stream_manager.cc
@@ -1472,6 +1472,14 @@ void MediaStreamManager::FinalizeEnumerateDevices(const std::string& label,
request->devices.clear();
}
+ if (use_fake_ui_) {
+ if (!fake_ui_)
+ fake_ui_.reset(new FakeMediaStreamUIProxy());
+ request->ui_proxy = fake_ui_.Pass();
+ } else {
+ request->ui_proxy = MediaStreamUIProxy::Create();
+ }
+
// Output label permissions are based on input permission.
MediaStreamType type =
request->audio_type() == MEDIA_DEVICE_AUDIO_CAPTURE ||
@@ -1479,40 +1487,16 @@ void MediaStreamManager::FinalizeEnumerateDevices(const std::string& label,
? MEDIA_DEVICE_AUDIO_CAPTURE
: MEDIA_DEVICE_VIDEO_CAPTURE;
- BrowserThread::PostTaskAndReplyWithResult(
- BrowserThread::UI,
- FROM_HERE,
- base::Bind(&MediaStreamManager::CheckMediaAccessPermissionOnUIThread,
- base::Unretained(this),
- request->requesting_process_id,
- request->security_origin,
- type),
+ request->ui_proxy->CheckAccess(
+ request->security_origin,
+ type,
+ request->requesting_process_id,
+ request->requesting_frame_id,
base::Bind(&MediaStreamManager::HandleCheckMediaAccessResponse,
base::Unretained(this),
label));
}
-bool MediaStreamManager::CheckMediaAccessPermissionOnUIThread(
- int render_process_id,
- const GURL& security_origin,
- MediaStreamType type) {
- DCHECK_CURRENTLY_ON(BrowserThread::UI);
-
- RenderProcessHost* host =
- RenderProcessHost::FromID(render_process_id);
- if (!host) {
- // This can happen if the renderer goes away during the lifetime of a
- // request.
- return false;
- }
- content::BrowserContext* context = host->GetBrowserContext();
- DCHECK(context);
- return GetContentClient()->browser()->CheckMediaAccessPermission(
- context,
- security_origin,
- type);
-}
-
void MediaStreamManager::HandleCheckMediaAccessResponse(
const std::string& label,
bool have_access) {
diff --git a/content/browser/renderer_host/media/media_stream_manager.h b/content/browser/renderer_host/media/media_stream_manager.h
index 50cef78..1eba375 100644
--- a/content/browser/renderer_host/media/media_stream_manager.h
+++ b/content/browser/renderer_host/media/media_stream_manager.h
@@ -321,11 +321,6 @@ class CONTENT_EXPORT MediaStreamManager
const MediaStreamDevices& devices);
void FinalizeEnumerateDevices(const std::string& label,
DeviceRequest* request);
-
- // Checks for media access. Overridden by unit tests.
- virtual bool CheckMediaAccessPermissionOnUIThread(int render_process_id,
- const GURL& security_origin,
- MediaStreamType type);
void HandleCheckMediaAccessResponse(const std::string& label,
bool have_access);
diff --git a/content/browser/renderer_host/media/media_stream_ui_proxy.cc b/content/browser/renderer_host/media/media_stream_ui_proxy.cc
index 837577a..c4eb0d7 100644
--- a/content/browser/renderer_host/media/media_stream_ui_proxy.cc
+++ b/content/browser/renderer_host/media/media_stream_ui_proxy.cc
@@ -20,6 +20,10 @@ class MediaStreamUIProxy::Core {
~Core();
void RequestAccess(const MediaStreamRequest& request);
+ bool CheckAccess(const GURL& security_origin,
+ MediaStreamType type,
+ int process_id,
+ int frame_id);
void OnStarted(gfx::NativeViewId* window_id);
private:
@@ -27,6 +31,8 @@ class MediaStreamUIProxy::Core {
content::MediaStreamRequestResult result,
scoped_ptr<MediaStreamUI> stream_ui);
void ProcessStopRequestFromUI();
+ RenderFrameHostDelegate* GetRenderFrameHostDelegate(int render_process_id,
+ int render_frame_id);
base::WeakPtr<MediaStreamUIProxy> proxy_;
scoped_ptr<MediaStreamUI> ui_;
@@ -55,14 +61,8 @@ void MediaStreamUIProxy::Core::RequestAccess(
const MediaStreamRequest& request) {
DCHECK_CURRENTLY_ON(BrowserThread::UI);
- RenderFrameHostDelegate* render_delegate;
- if (test_render_delegate_) {
- render_delegate = test_render_delegate_;
- } else {
- RenderFrameHostImpl* const host = RenderFrameHostImpl::FromID(
- request.render_process_id, request.render_frame_id);
- render_delegate = host ? host->delegate() : NULL;
- }
+ RenderFrameHostDelegate* render_delegate = GetRenderFrameHostDelegate(
+ request.render_process_id, request.render_frame_id);
// Tab may have gone away, or has no delegate from which to request access.
if (!render_delegate) {
@@ -78,6 +78,20 @@ void MediaStreamUIProxy::Core::RequestAccess(
weak_factory_.GetWeakPtr()));
}
+bool MediaStreamUIProxy::Core::CheckAccess(const GURL& security_origin,
+ MediaStreamType type,
+ int render_process_id,
+ int render_frame_id) {
+ DCHECK_CURRENTLY_ON(BrowserThread::UI);
+
+ RenderFrameHostDelegate* render_delegate =
+ GetRenderFrameHostDelegate(render_process_id, render_frame_id);
+ if (!render_delegate)
+ return false;
+
+ return render_delegate->CheckMediaAccessPermission(security_origin, type);
+}
+
void MediaStreamUIProxy::Core::OnStarted(gfx::NativeViewId* window_id) {
DCHECK_CURRENTLY_ON(BrowserThread::UI);
if (ui_) {
@@ -107,6 +121,16 @@ void MediaStreamUIProxy::Core::ProcessStopRequestFromUI() {
base::Bind(&MediaStreamUIProxy::ProcessStopRequestFromUI, proxy_));
}
+RenderFrameHostDelegate* MediaStreamUIProxy::Core::GetRenderFrameHostDelegate(
+ int render_process_id,
+ int render_frame_id) {
+ if (test_render_delegate_)
+ return test_render_delegate_;
+ RenderFrameHostImpl* host =
+ RenderFrameHostImpl::FromID(render_process_id, render_frame_id);
+ return host ? host->delegate() : NULL;
+}
+
// static
scoped_ptr<MediaStreamUIProxy> MediaStreamUIProxy::Create() {
return scoped_ptr<MediaStreamUIProxy>(new MediaStreamUIProxy(NULL));
@@ -141,6 +165,28 @@ void MediaStreamUIProxy::RequestAccess(
base::Bind(&Core::RequestAccess, base::Unretained(core_.get()), request));
}
+void MediaStreamUIProxy::CheckAccess(
+ const GURL& security_origin,
+ MediaStreamType type,
+ int render_process_id,
+ int render_frame_id,
+ const base::Callback<void(bool)>& callback) {
+ DCHECK_CURRENTLY_ON(BrowserThread::IO);
+
+ BrowserThread::PostTaskAndReplyWithResult(
+ BrowserThread::UI,
+ FROM_HERE,
+ base::Bind(&Core::CheckAccess,
+ base::Unretained(core_.get()),
+ security_origin,
+ type,
+ render_process_id,
+ render_frame_id),
+ base::Bind(&MediaStreamUIProxy::OnCheckedAccess,
+ weak_factory_.GetWeakPtr(),
+ callback));
+}
+
void MediaStreamUIProxy::OnStarted(const base::Closure& stop_callback,
const WindowIdCallback& window_id_callback) {
DCHECK_CURRENTLY_ON(BrowserThread::IO);
@@ -160,13 +206,6 @@ void MediaStreamUIProxy::OnStarted(const base::Closure& stop_callback,
base::Owned(window_id)));
}
-void MediaStreamUIProxy::OnWindowId(const WindowIdCallback& window_id_callback,
- gfx::NativeViewId* window_id) {
- DCHECK_CURRENTLY_ON(BrowserThread::IO);
- if (!window_id_callback.is_null())
- window_id_callback.Run(*window_id);
-}
-
void MediaStreamUIProxy::ProcessAccessRequestResponse(
const MediaStreamDevices& devices,
content::MediaStreamRequestResult result) {
@@ -187,8 +226,25 @@ void MediaStreamUIProxy::ProcessStopRequestFromUI() {
cb.Run();
}
+void MediaStreamUIProxy::OnWindowId(const WindowIdCallback& window_id_callback,
+ gfx::NativeViewId* window_id) {
+ DCHECK_CURRENTLY_ON(BrowserThread::IO);
+ if (!window_id_callback.is_null())
+ window_id_callback.Run(*window_id);
+}
+
+void MediaStreamUIProxy::OnCheckedAccess(
+ const base::Callback<void(bool)>& callback,
+ bool have_access) {
+ DCHECK_CURRENTLY_ON(BrowserThread::IO);
+ if (!callback.is_null())
+ callback.Run(have_access);
+}
+
FakeMediaStreamUIProxy::FakeMediaStreamUIProxy()
- : MediaStreamUIProxy(NULL) {
+ : MediaStreamUIProxy(NULL),
+ mic_access_(true),
+ camera_access_(true) {
}
FakeMediaStreamUIProxy::~FakeMediaStreamUIProxy() {}
@@ -198,6 +254,14 @@ void FakeMediaStreamUIProxy::SetAvailableDevices(
devices_ = devices;
}
+void FakeMediaStreamUIProxy::SetMicAccess(bool access) {
+ mic_access_ = access;
+}
+
+void FakeMediaStreamUIProxy::SetCameraAccess(bool access) {
+ camera_access_ = access;
+}
+
void FakeMediaStreamUIProxy::RequestAccess(
const MediaStreamRequest& request,
const ResponseCallback& response_callback) {
@@ -242,7 +306,7 @@ void FakeMediaStreamUIProxy::RequestAccess(
}
}
- // Fail the request if a device exist for the requested type.
+ // Fail the request if a device doesn't exist for the requested type.
if ((request.audio_type != MEDIA_NO_SERVICE && !accepted_audio) ||
(request.video_type != MEDIA_NO_SERVICE && !accepted_video)) {
devices_to_use.clear();
@@ -258,6 +322,33 @@ void FakeMediaStreamUIProxy::RequestAccess(
MEDIA_DEVICE_OK));
}
+void FakeMediaStreamUIProxy::CheckAccess(
+ const GURL& security_origin,
+ MediaStreamType type,
+ int render_process_id,
+ int render_frame_id,
+ const base::Callback<void(bool)>& callback) {
+ DCHECK_CURRENTLY_ON(BrowserThread::IO);
+ DCHECK(type == MEDIA_DEVICE_AUDIO_CAPTURE ||
+ type == MEDIA_DEVICE_VIDEO_CAPTURE);
+
+ bool have_access = false;
+ if (CommandLine::ForCurrentProcess()->GetSwitchValueASCII(
+ switches::kUseFakeUIForMediaStream) != "deny") {
+ have_access =
+ type == MEDIA_DEVICE_AUDIO_CAPTURE ? mic_access_ : camera_access_;
+ }
+
+ BrowserThread::PostTask(
+ BrowserThread::IO,
+ FROM_HERE,
+ base::Bind(&MediaStreamUIProxy::OnCheckedAccess,
+ weak_factory_.GetWeakPtr(),
+ callback,
+ have_access));
+ return;
+}
+
void FakeMediaStreamUIProxy::OnStarted(
const base::Closure& stop_callback,
const WindowIdCallback& window_id_callback) {}
diff --git a/content/browser/renderer_host/media/media_stream_ui_proxy.h b/content/browser/renderer_host/media/media_stream_ui_proxy.h
index 810a29a..cf5ba1a 100644
--- a/content/browser/renderer_host/media/media_stream_ui_proxy.h
+++ b/content/browser/renderer_host/media/media_stream_ui_proxy.h
@@ -41,6 +41,16 @@ class CONTENT_EXPORT MediaStreamUIProxy {
virtual void RequestAccess(const MediaStreamRequest& request,
const ResponseCallback& response_callback);
+ // Checks if we have permission to access the microphone or camera. Note that
+ // this does not query the user, it checks any stored settings such as policy
+ // or extension permissions. |type| must be MEDIA_DEVICE_AUDIO_CAPTURE
+ // or MEDIA_DEVICE_VIDEO_CAPTURE.
+ virtual void CheckAccess(const GURL& security_origin,
+ MediaStreamType type,
+ int render_process_id,
+ int render_frame_id,
+ const base::Callback<void(bool)>& callback);
+
// Notifies the UI that the MediaStream has been started. Must be called after
// access has been approved using RequestAccess(). |stop_callback| is be
// called on the IO thread after the user has requests the stream to be
@@ -65,6 +75,8 @@ class CONTENT_EXPORT MediaStreamUIProxy {
void ProcessStopRequestFromUI();
void OnWindowId(const WindowIdCallback& window_id_callback,
gfx::NativeViewId* window_id);
+ void OnCheckedAccess(const base::Callback<void(bool)>& callback,
+ bool have_access);
scoped_ptr<Core, content::BrowserThread::DeleteOnUIThread> core_;
ResponseCallback response_callback_;
@@ -81,17 +93,29 @@ class CONTENT_EXPORT FakeMediaStreamUIProxy : public MediaStreamUIProxy {
virtual ~FakeMediaStreamUIProxy();
void SetAvailableDevices(const MediaStreamDevices& devices);
+ void SetMicAccess(bool access);
+ void SetCameraAccess(bool access);
// MediaStreamUIProxy overrides.
virtual void RequestAccess(
const MediaStreamRequest& request,
const ResponseCallback& response_callback) OVERRIDE;
+ virtual void CheckAccess(const GURL& security_origin,
+ MediaStreamType type,
+ int render_process_id,
+ int render_frame_id,
+ const base::Callback<void(bool)>& callback) OVERRIDE;
virtual void OnStarted(const base::Closure& stop_callback,
const WindowIdCallback& window_id_callback) OVERRIDE;
private:
+ // This is used for RequestAccess().
MediaStreamDevices devices_;
+ // These are used for CheckAccess().
+ bool mic_access_;
+ bool camera_access_;
+
DISALLOW_COPY_AND_ASSIGN(FakeMediaStreamUIProxy);
};
diff --git a/content/browser/renderer_host/media/media_stream_ui_proxy_unittest.cc b/content/browser/renderer_host/media/media_stream_ui_proxy_unittest.cc
index 3bc1b06..e729717 100644
--- a/content/browser/renderer_host/media/media_stream_ui_proxy_unittest.cc
+++ b/content/browser/renderer_host/media/media_stream_ui_proxy_unittest.cc
@@ -24,6 +24,9 @@ class MockRenderFrameHostDelegate : public RenderFrameHostDelegate {
MOCK_METHOD2(RequestMediaAccessPermission,
void(const MediaStreamRequest& request,
const MediaResponseCallback& callback));
+ MOCK_METHOD2(CheckMediaAccessPermission,
+ bool(const GURL& security_origin,
+ MediaStreamType type));
};
class MockResponseCallback {
@@ -31,6 +34,7 @@ class MockResponseCallback {
MOCK_METHOD2(OnAccessRequestResponse,
void(const MediaStreamDevices& devices,
content::MediaStreamRequestResult result));
+ MOCK_METHOD1(OnCheckResponse, void(bool have_access));
};
class MockMediaStreamUI : public MediaStreamUI {
@@ -247,4 +251,16 @@ TEST_F(MediaStreamUIProxyTest, WindowIdCallbackCalled) {
message_loop_.RunUntilIdle();
}
+TEST_F(MediaStreamUIProxyTest, CheckAccess) {
+ proxy_->CheckAccess(GURL("http://origin/"),
+ MEDIA_DEVICE_AUDIO_CAPTURE,
+ 0,
+ 0,
+ base::Bind(&MockResponseCallback::OnCheckResponse,
+ base::Unretained(&response_callback_)));
+ EXPECT_CALL(delegate_, CheckMediaAccessPermission(_, _));
+ EXPECT_CALL(response_callback_, OnCheckResponse(_));
+ message_loop_.RunUntilIdle();
+}
+
} // content
diff --git a/content/browser/web_contents/web_contents_impl.cc b/content/browser/web_contents/web_contents_impl.cc
index 8cf5a0f..976c921 100644
--- a/content/browser/web_contents/web_contents_impl.cc
+++ b/content/browser/web_contents/web_contents_impl.cc
@@ -1779,6 +1779,14 @@ void WebContentsImpl::RequestMediaAccessPermission(
}
}
+bool WebContentsImpl::CheckMediaAccessPermission(const GURL& security_origin,
+ MediaStreamType type) {
+ DCHECK(type == MEDIA_DEVICE_AUDIO_CAPTURE ||
+ type == MEDIA_DEVICE_VIDEO_CAPTURE);
+ return delegate_ &&
+ delegate_->CheckMediaAccessPermission(this, security_origin, type);
+}
+
SessionStorageNamespace* WebContentsImpl::GetSessionStorageNamespace(
SiteInstance* instance) {
return controller_.GetSessionStorageNamespace(instance);
diff --git a/content/browser/web_contents/web_contents_impl.h b/content/browser/web_contents/web_contents_impl.h
index c50025c..dd998c6 100644
--- a/content/browser/web_contents/web_contents_impl.h
+++ b/content/browser/web_contents/web_contents_impl.h
@@ -477,6 +477,8 @@ class CONTENT_EXPORT WebContentsImpl
virtual void RequestMediaAccessPermission(
const MediaStreamRequest& request,
const MediaResponseCallback& callback) OVERRIDE;
+ virtual bool CheckMediaAccessPermission(const GURL& security_origin,
+ MediaStreamType type) OVERRIDE;
virtual SessionStorageNamespace* GetSessionStorageNamespace(
SiteInstance* instance) OVERRIDE;
virtual SessionStorageNamespaceMap GetSessionStorageNamespaceMap() OVERRIDE;
diff --git a/content/public/browser/web_contents_delegate.cc b/content/public/browser/web_contents_delegate.cc
index 0028339..d930aed 100644
--- a/content/public/browser/web_contents_delegate.cc
+++ b/content/public/browser/web_contents_delegate.cc
@@ -169,6 +169,15 @@ void WebContentsDelegate::RequestMediaAccessPermission(
scoped_ptr<MediaStreamUI>());
}
+bool WebContentsDelegate::CheckMediaAccessPermission(
+ WebContents* web_contents,
+ const GURL& security_origin,
+ MediaStreamType type) {
+ DCHECK(type == MEDIA_DEVICE_AUDIO_CAPTURE ||
+ type == MEDIA_DEVICE_VIDEO_CAPTURE);
+ return false;
+}
+
bool WebContentsDelegate::RequestPpapiBrokerPermission(
WebContents* web_contents,
const GURL& url,
diff --git a/content/public/browser/web_contents_delegate.h b/content/public/browser/web_contents_delegate.h
index b9aa02d..d040256 100644
--- a/content/public/browser/web_contents_delegate.h
+++ b/content/public/browser/web_contents_delegate.h
@@ -444,6 +444,13 @@ class CONTENT_EXPORT WebContentsDelegate {
const MediaStreamRequest& request,
const MediaResponseCallback& callback);
+ // Checks if we have permission to access the microphone or camera. Note that
+ // this does not query the user. |type| must be MEDIA_DEVICE_AUDIO_CAPTURE
+ // or MEDIA_DEVICE_VIDEO_CAPTURE.
+ virtual bool CheckMediaAccessPermission(WebContents* web_contents,
+ const GURL& security_origin,
+ MediaStreamType type);
+
// Requests permission to access the PPAPI broker. The delegate should return
// true and call the passed in |callback| with the result, or return false
// to indicate that it does not support asking for permission.
diff --git a/extensions/browser/app_window/app_delegate.h b/extensions/browser/app_window/app_delegate.h
index 7b247af..2d5fa1d 100644
--- a/extensions/browser/app_window/app_delegate.h
+++ b/extensions/browser/app_window/app_delegate.h
@@ -63,6 +63,10 @@ class AppDelegate {
const content::MediaStreamRequest& request,
const content::MediaResponseCallback& callback,
const Extension* extension) = 0;
+ virtual bool CheckMediaAccessPermission(content::WebContents* web_contents,
+ const GURL& security_origin,
+ content::MediaStreamType type,
+ const Extension* extension) = 0;
virtual int PreferredIconSize() = 0;
virtual gfx::ImageSkia GetAppDefaultIcon() = 0;
diff --git a/extensions/browser/app_window/app_web_contents_helper.cc b/extensions/browser/app_window/app_web_contents_helper.cc
index 54153ac..fb66479 100644
--- a/extensions/browser/app_window/app_web_contents_helper.cc
+++ b/extensions/browser/app_window/app_web_contents_helper.cc
@@ -97,6 +97,17 @@ void AppWebContentsHelper::RequestMediaAccessPermission(
web_contents_, request, callback, extension);
}
+bool AppWebContentsHelper::CheckMediaAccessPermission(
+ const GURL& security_origin,
+ content::MediaStreamType type) const {
+ const Extension* extension = GetExtension();
+ if (!extension)
+ return false;
+
+ return app_delegate_->CheckMediaAccessPermission(
+ web_contents_, security_origin, type, extension);
+}
+
const Extension* AppWebContentsHelper::GetExtension() const {
return ExtensionRegistry::Get(browser_context_)
->enabled_extensions()
diff --git a/extensions/browser/app_window/app_web_contents_helper.h b/extensions/browser/app_window/app_web_contents_helper.h
index 3d17851..ea4f13e 100644
--- a/extensions/browser/app_window/app_web_contents_helper.h
+++ b/extensions/browser/app_window/app_web_contents_helper.h
@@ -48,6 +48,11 @@ class AppWebContentsHelper {
const content::MediaStreamRequest& request,
const content::MediaResponseCallback& callback) const;
+ // Checks permission to use the camera or microphone. See
+ // WebContentsDelegate.
+ bool CheckMediaAccessPermission(const GURL& security_origin,
+ content::MediaStreamType type) const;
+
private:
const Extension* GetExtension() const;
diff --git a/extensions/browser/app_window/app_window.cc b/extensions/browser/app_window/app_window.cc
index 3218a24..1cc9ae2 100644
--- a/extensions/browser/app_window/app_window.cc
+++ b/extensions/browser/app_window/app_window.cc
@@ -346,6 +346,13 @@ void AppWindow::RequestMediaAccessPermission(
helper_->RequestMediaAccessPermission(request, callback);
}
+bool AppWindow::CheckMediaAccessPermission(content::WebContents* web_contents,
+ const GURL& security_origin,
+ content::MediaStreamType type) {
+ DCHECK_EQ(AppWindow::web_contents(), web_contents);
+ return helper_->CheckMediaAccessPermission(security_origin, type);
+}
+
WebContents* AppWindow::OpenURLFromTab(WebContents* source,
const content::OpenURLParams& params) {
DCHECK_EQ(web_contents(), source);
diff --git a/extensions/browser/app_window/app_window.h b/extensions/browser/app_window/app_window.h
index 7b84ed7..3cef2ed 100644
--- a/extensions/browser/app_window/app_window.h
+++ b/extensions/browser/app_window/app_window.h
@@ -382,6 +382,10 @@ class AppWindow : public content::WebContentsDelegate,
content::WebContents* web_contents,
const content::MediaStreamRequest& request,
const content::MediaResponseCallback& callback) OVERRIDE;
+ virtual bool CheckMediaAccessPermission(
+ content::WebContents* web_contents,
+ const GURL& security_origin,
+ content::MediaStreamType type) OVERRIDE;
virtual content::WebContents* OpenURLFromTab(
content::WebContents* source,
const content::OpenURLParams& params) OVERRIDE;
diff --git a/extensions/browser/extension_host.cc b/extensions/browser/extension_host.cc
index 2f0572e..3920e47 100644
--- a/extensions/browser/extension_host.cc
+++ b/extensions/browser/extension_host.cc
@@ -428,6 +428,14 @@ void ExtensionHost::RequestMediaAccessPermission(
web_contents, request, callback, extension());
}
+bool ExtensionHost::CheckMediaAccessPermission(
+ content::WebContents* web_contents,
+ const GURL& security_origin,
+ content::MediaStreamType type) {
+ return delegate_->CheckMediaAccessPermission(
+ web_contents, security_origin, type, extension());
+}
+
bool ExtensionHost::IsNeverVisible(content::WebContents* web_contents) {
ViewType view_type = extensions::GetViewType(web_contents);
return view_type == extensions::VIEW_TYPE_EXTENSION_BACKGROUND_PAGE;
diff --git a/extensions/browser/extension_host.h b/extensions/browser/extension_host.h
index 24bd9ba..548e8f8 100644
--- a/extensions/browser/extension_host.h
+++ b/extensions/browser/extension_host.h
@@ -101,6 +101,10 @@ class ExtensionHost : public content::WebContentsDelegate,
content::WebContents* web_contents,
const content::MediaStreamRequest& request,
const content::MediaResponseCallback& callback) OVERRIDE;
+ virtual bool CheckMediaAccessPermission(
+ content::WebContents* web_contents,
+ const GURL& security_origin,
+ content::MediaStreamType type) OVERRIDE;
virtual bool IsNeverVisible(content::WebContents* web_contents) OVERRIDE;
// content::NotificationObserver
diff --git a/extensions/browser/extension_host_delegate.h b/extensions/browser/extension_host_delegate.h
index 0bf52a4..b14580d 100644
--- a/extensions/browser/extension_host_delegate.h
+++ b/extensions/browser/extension_host_delegate.h
@@ -56,6 +56,14 @@ class ExtensionHostDelegate {
const content::MediaStreamRequest& request,
const content::MediaResponseCallback& callback,
const Extension* extension) = 0;
+
+ // Checks if we have permission to access the microphone or camera. Note that
+ // this does not query the user. |type| must be MEDIA_DEVICE_AUDIO_CAPTURE
+ // or MEDIA_DEVICE_VIDEO_CAPTURE.
+ virtual bool CheckMediaAccessPermission(content::WebContents* web_contents,
+ const GURL& security_origin,
+ content::MediaStreamType type,
+ const Extension* extension) = 0;
};
} // namespace extensions
diff --git a/extensions/browser/guest_view/web_view/web_view_guest.cc b/extensions/browser/guest_view/web_view/web_view_guest.cc
index 0522514..bfc29f5 100644
--- a/extensions/browser/guest_view/web_view/web_view_guest.cc
+++ b/extensions/browser/guest_view/web_view/web_view_guest.cc
@@ -791,6 +791,13 @@ void WebViewGuest::RequestMediaAccessPermission(
callback);
}
+bool WebViewGuest::CheckMediaAccessPermission(content::WebContents* source,
+ const GURL& security_origin,
+ content::MediaStreamType type) {
+ return web_view_permission_helper_->CheckMediaAccessPermission(
+ source, security_origin, type);
+}
+
void WebViewGuest::CanDownload(
content::RenderViewHost* render_view_host,
const GURL& url,
diff --git a/extensions/browser/guest_view/web_view/web_view_guest.h b/extensions/browser/guest_view/web_view/web_view_guest.h
index 926a67b..f593213 100644
--- a/extensions/browser/guest_view/web_view/web_view_guest.h
+++ b/extensions/browser/guest_view/web_view/web_view_guest.h
@@ -121,6 +121,10 @@ class WebViewGuest : public GuestView<WebViewGuest>,
content::WebContents* source,
const content::MediaStreamRequest& request,
const content::MediaResponseCallback& callback) OVERRIDE;
+ virtual bool CheckMediaAccessPermission(
+ content::WebContents* source,
+ const GURL& security_origin,
+ content::MediaStreamType type) OVERRIDE;
virtual void CanDownload(content::RenderViewHost* render_view_host,
const GURL& url,
const std::string& request_method,
diff --git a/extensions/browser/guest_view/web_view/web_view_permission_helper.cc b/extensions/browser/guest_view/web_view/web_view_permission_helper.cc
index 079282b..d713279 100644
--- a/extensions/browser/guest_view/web_view/web_view_permission_helper.cc
+++ b/extensions/browser/guest_view/web_view/web_view_permission_helper.cc
@@ -180,10 +180,18 @@ void WebViewPermissionHelper::RequestMediaAccessPermission(
content::WebContents* source,
const content::MediaStreamRequest& request,
const content::MediaResponseCallback& callback) {
- web_view_permission_helper_delegate_-> RequestMediaAccessPermission(
+ web_view_permission_helper_delegate_->RequestMediaAccessPermission(
source, request, callback);
}
+bool WebViewPermissionHelper::CheckMediaAccessPermission(
+ content::WebContents* source,
+ const GURL& security_origin,
+ content::MediaStreamType type) {
+ return web_view_permission_helper_delegate_->CheckMediaAccessPermission(
+ source, security_origin, type);
+}
+
void WebViewPermissionHelper::CanDownload(
content::RenderViewHost* render_view_host,
const GURL& url,
diff --git a/extensions/browser/guest_view/web_view/web_view_permission_helper.h b/extensions/browser/guest_view/web_view/web_view_permission_helper.h
index db9f1ab..8fb9037 100644
--- a/extensions/browser/guest_view/web_view/web_view_permission_helper.h
+++ b/extensions/browser/guest_view/web_view/web_view_permission_helper.h
@@ -60,6 +60,9 @@ class WebViewPermissionHelper
content::WebContents* source,
const content::MediaStreamRequest& request,
const content::MediaResponseCallback& callback);
+ bool CheckMediaAccessPermission(content::WebContents* source,
+ const GURL& security_origin,
+ content::MediaStreamType type);
void CanDownload(content::RenderViewHost* render_view_host,
const GURL& url,
const std::string& request_method,
diff --git a/extensions/browser/guest_view/web_view/web_view_permission_helper_delegate.cc b/extensions/browser/guest_view/web_view/web_view_permission_helper_delegate.cc
index 1ce7c28..4fbbef8 100644
--- a/extensions/browser/guest_view/web_view/web_view_permission_helper_delegate.cc
+++ b/extensions/browser/guest_view/web_view/web_view_permission_helper_delegate.cc
@@ -18,4 +18,12 @@ WebViewPermissionHelperDelegate::WebViewPermissionHelperDelegate(
WebViewPermissionHelperDelegate::~WebViewPermissionHelperDelegate() {
}
+bool WebViewPermissionHelperDelegate::CheckMediaAccessPermission(
+ content::WebContents* source,
+ const GURL& security_origin,
+ content::MediaStreamType type) {
+ // Defensive default implementation for privacy reasons.
+ return false;
+}
+
} // namespace extensions
diff --git a/extensions/browser/guest_view/web_view/web_view_permission_helper_delegate.h b/extensions/browser/guest_view/web_view/web_view_permission_helper_delegate.h
index b43b73a..d919105 100644
--- a/extensions/browser/guest_view/web_view/web_view_permission_helper_delegate.h
+++ b/extensions/browser/guest_view/web_view/web_view_permission_helper_delegate.h
@@ -25,6 +25,10 @@ class WebViewPermissionHelperDelegate : public content::WebContentsObserver {
const content::MediaStreamRequest& request,
const content::MediaResponseCallback& callback) {}
+ virtual bool CheckMediaAccessPermission(content::WebContents* source,
+ const GURL& security_origin,
+ content::MediaStreamType type);
+
virtual void CanDownload(
content::RenderViewHost* render_view_host,
const GURL& url,
diff --git a/extensions/shell/browser/media_capture_util.cc b/extensions/shell/browser/media_capture_util.cc
index 364e19d..30e3fb6 100644
--- a/extensions/shell/browser/media_capture_util.cc
+++ b/extensions/shell/browser/media_capture_util.cc
@@ -42,14 +42,9 @@ void GrantMediaStreamRequest(content::WebContents* web_contents,
request.video_type == content::MEDIA_DEVICE_VIDEO_CAPTURE);
MediaStreamDevices devices;
- const PermissionsData* permissions_data = extension->permissions_data();
if (request.audio_type == content::MEDIA_DEVICE_AUDIO_CAPTURE) {
- // app_shell has no UI surface to show an error, and on an embedded device
- // it's better to crash than to have a feature not work.
- CHECK(permissions_data->HasAPIPermission(APIPermission::kAudioCapture))
- << "Audio capture request but no audioCapture permission in manifest.";
-
+ VerifyMediaAccessPermission(request.audio_type, extension);
const MediaStreamDevice* device = GetRequestedDeviceOrDefault(
MediaCaptureDevices::GetInstance()->GetAudioCaptureDevices(),
request.requested_audio_device_id);
@@ -58,10 +53,7 @@ void GrantMediaStreamRequest(content::WebContents* web_contents,
}
if (request.video_type == content::MEDIA_DEVICE_VIDEO_CAPTURE) {
- // See APIPermission::kAudioCapture check above.
- CHECK(permissions_data->HasAPIPermission(APIPermission::kVideoCapture))
- << "Video capture request but no videoCapture permission in manifest.";
-
+ VerifyMediaAccessPermission(request.video_type, extension);
const MediaStreamDevice* device = GetRequestedDeviceOrDefault(
MediaCaptureDevices::GetInstance()->GetVideoCaptureDevices(),
request.requested_video_device_id);
@@ -77,5 +69,20 @@ void GrantMediaStreamRequest(content::WebContents* web_contents,
ui.Pass());
}
+void VerifyMediaAccessPermission(content::MediaStreamType type,
+ const Extension* extension) {
+ const PermissionsData* permissions_data = extension->permissions_data();
+ if (type == content::MEDIA_DEVICE_AUDIO_CAPTURE) {
+ // app_shell has no UI surface to show an error, and on an embedded device
+ // it's better to crash than to have a feature not work.
+ CHECK(permissions_data->HasAPIPermission(APIPermission::kAudioCapture))
+ << "Audio capture request but no audioCapture permission in manifest.";
+ } else {
+ DCHECK(type == content::MEDIA_DEVICE_VIDEO_CAPTURE);
+ CHECK(permissions_data->HasAPIPermission(APIPermission::kVideoCapture))
+ << "Video capture request but no videoCapture permission in manifest.";
+ }
+}
+
} // namespace media_capture_util
} // namespace extensions
diff --git a/extensions/shell/browser/media_capture_util.h b/extensions/shell/browser/media_capture_util.h
index f254071..b1b15ba 100644
--- a/extensions/shell/browser/media_capture_util.h
+++ b/extensions/shell/browser/media_capture_util.h
@@ -28,6 +28,10 @@ void GrantMediaStreamRequest(content::WebContents* web_contents,
const content::MediaResponseCallback& callback,
const Extension* extension);
+// Verifies that the extension has permission for |type|. If not, crash.
+void VerifyMediaAccessPermission(content::MediaStreamType type,
+ const Extension* extension);
+
} // namespace media_capture_util
} // namespace extensions
diff --git a/extensions/shell/browser/shell_app_delegate.cc b/extensions/shell/browser/shell_app_delegate.cc
index 4380d6a..483da67 100644
--- a/extensions/shell/browser/shell_app_delegate.cc
+++ b/extensions/shell/browser/shell_app_delegate.cc
@@ -62,6 +62,15 @@ void ShellAppDelegate::RequestMediaAccessPermission(
web_contents, request, callback, extension);
}
+bool ShellAppDelegate::CheckMediaAccessPermission(
+ content::WebContents* web_contents,
+ const GURL& security_origin,
+ content::MediaStreamType type,
+ const Extension* extension) {
+ media_capture_util::VerifyMediaAccessPermission(type, extension);
+ return true;
+}
+
int ShellAppDelegate::PreferredIconSize() {
return extension_misc::EXTENSION_ICON_SMALL;
}
diff --git a/extensions/shell/browser/shell_app_delegate.h b/extensions/shell/browser/shell_app_delegate.h
index 6e58e17..b842edb 100644
--- a/extensions/shell/browser/shell_app_delegate.h
+++ b/extensions/shell/browser/shell_app_delegate.h
@@ -40,6 +40,10 @@ class ShellAppDelegate : public AppDelegate {
const content::MediaStreamRequest& request,
const content::MediaResponseCallback& callback,
const Extension* extension) OVERRIDE;
+ virtual bool CheckMediaAccessPermission(content::WebContents* web_contents,
+ const GURL& security_origin,
+ content::MediaStreamType type,
+ const Extension* extension) OVERRIDE;
virtual int PreferredIconSize() OVERRIDE;
virtual gfx::ImageSkia GetAppDefaultIcon() OVERRIDE;
virtual void SetWebContentsBlocked(content::WebContents* web_contents,
diff --git a/extensions/shell/browser/shell_extension_host_delegate.cc b/extensions/shell/browser/shell_extension_host_delegate.cc
index 0053c64..a02d604 100644
--- a/extensions/shell/browser/shell_extension_host_delegate.cc
+++ b/extensions/shell/browser/shell_extension_host_delegate.cc
@@ -52,5 +52,13 @@ void ShellExtensionHostDelegate::ProcessMediaAccessRequest(
web_contents, request, callback, extension);
}
-} // namespace extensions
+bool ShellExtensionHostDelegate::CheckMediaAccessPermission(
+ content::WebContents* web_contents,
+ const GURL& security_origin,
+ content::MediaStreamType type,
+ const Extension* extension) {
+ media_capture_util::VerifyMediaAccessPermission(type, extension);
+ return true;
+}
+} // namespace extensions
diff --git a/extensions/shell/browser/shell_extension_host_delegate.h b/extensions/shell/browser/shell_extension_host_delegate.h
index 759a465..d7265f3 100644
--- a/extensions/shell/browser/shell_extension_host_delegate.h
+++ b/extensions/shell/browser/shell_extension_host_delegate.h
@@ -33,6 +33,10 @@ class ShellExtensionHostDelegate : public ExtensionHostDelegate {
const content::MediaStreamRequest& request,
const content::MediaResponseCallback& callback,
const Extension* extension) OVERRIDE;
+ virtual bool CheckMediaAccessPermission(content::WebContents* web_contents,
+ const GURL& security_origin,
+ content::MediaStreamType type,
+ const Extension* extension) OVERRIDE;
private:
DISALLOW_COPY_AND_ASSIGN(ShellExtensionHostDelegate);