diff options
13 files changed, 162 insertions, 8 deletions
diff --git a/android_webview/browser/aw_browser_context.cc b/android_webview/browser/aw_browser_context.cc index 7c94d79..51f1c17 100644 --- a/android_webview/browser/aw_browser_context.cc +++ b/android_webview/browser/aw_browser_context.cc @@ -44,6 +44,12 @@ class AwResourceContext : public content::ResourceContext { DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::IO)); return getter_->GetURLRequestContext(); } + virtual bool AllowMicAccess(const GURL& origin) OVERRIDE { + return false; + } + virtual bool AllowCameraAccess(const GURL& origin) OVERRIDE { + return false; + } private: net::URLRequestContextGetter* getter_; diff --git a/chrome/browser/profiles/profile_io_data.cc b/chrome/browser/profiles/profile_io_data.cc index df99e8e..0776e53 100644 --- a/chrome/browser/profiles/profile_io_data.cc +++ b/chrome/browser/profiles/profile_io_data.cc @@ -21,6 +21,7 @@ #include "base/strings/stringprintf.h" #include "chrome/browser/browser_process.h" #include "chrome/browser/chrome_notification_types.h" +#include "chrome/browser/content_settings/content_settings_provider.h" #include "chrome/browser/content_settings/cookie_settings.h" #include "chrome/browser/content_settings/host_content_settings_map.h" #include "chrome/browser/custom_handlers/protocol_handler_registry.h" @@ -691,6 +692,23 @@ net::URLRequestContext* ProfileIOData::ResourceContext::GetRequestContext() { return request_context_; } +bool ProfileIOData::ResourceContext::AllowMicAccess(const GURL& origin) { + return AllowContentAccess(origin, CONTENT_SETTINGS_TYPE_MEDIASTREAM_MIC); +} + +bool ProfileIOData::ResourceContext::AllowCameraAccess(const GURL& origin) { + return AllowContentAccess(origin, CONTENT_SETTINGS_TYPE_MEDIASTREAM_CAMERA); +} + +bool ProfileIOData::ResourceContext::AllowContentAccess( + const GURL& origin, ContentSettingsType type) { + HostContentSettingsMap* content_settings = + io_data_->GetHostContentSettingsMap(); + ContentSetting setting = content_settings->GetContentSetting( + origin, origin, type, NO_RESOURCE_IDENTIFIER); + return setting == CONTENT_SETTING_ALLOW; +} + // static std::string ProfileIOData::GetSSLSessionCacheShard() { DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); diff --git a/chrome/browser/profiles/profile_io_data.h b/chrome/browser/profiles/profile_io_data.h index ee2f303..cec73bc 100644 --- a/chrome/browser/profiles/profile_io_data.h +++ b/chrome/browser/profiles/profile_io_data.h @@ -19,6 +19,7 @@ #include "chrome/browser/io_thread.h" #include "chrome/browser/net/chrome_url_request_context.h" #include "chrome/browser/profiles/storage_partition_descriptor.h" +#include "chrome/common/content_settings_types.h" #include "content/public/browser/content_browser_client.h" #include "content/public/browser/resource_context.h" #include "net/cookies/cookie_monster.h" @@ -362,10 +363,16 @@ class ProfileIOData { // ResourceContext implementation: virtual net::HostResolver* GetHostResolver() OVERRIDE; virtual net::URLRequestContext* GetRequestContext() OVERRIDE; + virtual bool AllowMicAccess(const GURL& origin) OVERRIDE; + virtual bool AllowCameraAccess(const GURL& origin) OVERRIDE; private: friend class ProfileIOData; + // Helper method that returns true if |type| is allowed for |origin|, false + // otherwise. + bool AllowContentAccess(const GURL& origin, ContentSettingsType type); + ProfileIOData* const io_data_; net::HostResolver* host_resolver_; diff --git a/content/browser/loader/resource_scheduler_unittest.cc b/content/browser/loader/resource_scheduler_unittest.cc index 2066294..9d87f2d 100644 --- a/content/browser/loader/resource_scheduler_unittest.cc +++ b/content/browser/loader/resource_scheduler_unittest.cc @@ -89,6 +89,8 @@ class FakeResourceContext : public ResourceContext { private: virtual net::HostResolver* GetHostResolver() OVERRIDE { return NULL; } virtual net::URLRequestContext* GetRequestContext() OVERRIDE { return NULL; } + virtual bool AllowMicAccess(const GURL& origin) OVERRIDE { return false; } + virtual bool AllowCameraAccess(const GURL& origin) OVERRIDE { return false; } }; class FakeURLRequestContextSelector diff --git a/content/browser/renderer_host/media/device_request_message_filter.cc b/content/browser/renderer_host/media/device_request_message_filter.cc index bcd9dcf..fba074b 100644 --- a/content/browser/renderer_host/media/device_request_message_filter.cc +++ b/content/browser/renderer_host/media/device_request_message_filter.cc @@ -10,13 +10,26 @@ #include "content/browser/browser_main_loop.h" #include "content/browser/renderer_host/media/media_stream_manager.h" #include "content/common/media/media_stream_messages.h" +#include "content/public/browser/resource_context.h" #include "crypto/hmac.h" +// Clears the MediaStreamDevice.name from all devices in |device_list|. +static void ClearDeviceLabels(content::StreamDeviceInfoArray* devices) { + for (content::StreamDeviceInfoArray::iterator device_itr = devices->begin(); + device_itr != devices->end(); + ++device_itr) { + device_itr->device.name.clear(); + } +} + namespace content { DeviceRequestMessageFilter::DeviceRequestMessageFilter( + ResourceContext* resource_context, MediaStreamManager* media_stream_manager) - : media_stream_manager_(media_stream_manager) { + : resource_context_(resource_context), + media_stream_manager_(media_stream_manager) { + DCHECK(resource_context); DCHECK(media_stream_manager); } @@ -93,7 +106,13 @@ void DeviceRequestMessageFilter::DevicesEnumerated( return; } - // Both audio and video devices are ready. + // Query for mic and camera permissions. + if (!resource_context_->AllowMicAccess(request_it->origin)) + ClearDeviceLabels(audio_devices); + if (!resource_context_->AllowCameraAccess(request_it->origin)) + ClearDeviceLabels(video_devices); + + // Both audio and video devices are ready for copying. StreamDeviceInfoArray all_devices = *audio_devices; all_devices.insert( all_devices.end(), video_devices->begin(), video_devices->end()); diff --git a/content/browser/renderer_host/media/device_request_message_filter.h b/content/browser/renderer_host/media/device_request_message_filter.h index 4e42186..2ae1e77 100644 --- a/content/browser/renderer_host/media/device_request_message_filter.h +++ b/content/browser/renderer_host/media/device_request_message_filter.h @@ -16,13 +16,15 @@ namespace content { class MediaStreamManager; +class ResourceContext; // DeviceRequestMessageFilter used to delegate requests from the // MediaStreamCenter. class CONTENT_EXPORT DeviceRequestMessageFilter : public BrowserMessageFilter, public MediaStreamRequester { public: - explicit DeviceRequestMessageFilter(MediaStreamManager* media_stream_manager); + DeviceRequestMessageFilter(ResourceContext* resource_context, + MediaStreamManager* media_stream_manager); // MediaStreamRequester implementation. // TODO(vrk): Replace MediaStreamRequester interface with a single callback so @@ -58,6 +60,8 @@ class CONTENT_EXPORT DeviceRequestMessageFilter : public BrowserMessageFilter, const StreamDeviceInfoArray& raw_devices, StreamDeviceInfoArray* devices_with_guids); + // Owned by ProfileIOData which is guaranteed to outlive DRMF. + ResourceContext* resource_context_; MediaStreamManager* media_stream_manager_; struct DeviceRequest; diff --git a/content/browser/renderer_host/media/device_request_message_filter_unittest.cc b/content/browser/renderer_host/media/device_request_message_filter_unittest.cc index 9043027..04a7bb6 100644 --- a/content/browser/renderer_host/media/device_request_message_filter_unittest.cc +++ b/content/browser/renderer_host/media/device_request_message_filter_unittest.cc @@ -6,6 +6,7 @@ #include "content/browser/renderer_host/media/device_request_message_filter.h" #include "content/browser/renderer_host/media/media_stream_manager.h" #include "content/common/media/media_stream_messages.h" +#include "content/public/test/mock_resource_context.h" #include "content/public/test/test_browser_thread.h" #include "testing/gmock/include/gmock/gmock.h" #include "testing/gtest/include/gtest/gtest.h" @@ -49,8 +50,9 @@ class MockMediaStreamManager : public MediaStreamManager { class MockDeviceRequestMessageFilter : public DeviceRequestMessageFilter { public: - MockDeviceRequestMessageFilter(MockMediaStreamManager* manager) - : DeviceRequestMessageFilter(manager), received_id_(-1) {} + MockDeviceRequestMessageFilter(MockResourceContext* context, + MockMediaStreamManager* manager) + : DeviceRequestMessageFilter(context, manager), received_id_(-1) {} StreamDeviceInfoArray requested_devices() { return requested_devices_; } int received_id() { return received_id_; } @@ -122,6 +124,15 @@ class DeviceRequestMessageFilterTest : public testing::Test { EXPECT_TRUE(DoesEveryDeviceMapToRawId(host_->requested_devices(), origin)); } + bool AreLabelsPresent(MediaStreamType type) { + const StreamDeviceInfoArray& devices = host_->requested_devices(); + for (size_t i = 0; i < devices.size(); i++) { + if (devices[i].device.type == type && !devices[i].device.name.empty()) + return true; + } + return false; + } + protected: virtual ~DeviceRequestMessageFilterTest() {} @@ -135,11 +146,14 @@ class DeviceRequestMessageFilterTest : public testing::Test { .WillByDefault(Invoke(media_stream_manager_.get(), &MockMediaStreamManager::DoEnumerateDevices)); - host_ = new MockDeviceRequestMessageFilter(media_stream_manager_.get()); + resource_context_.reset(new MockResourceContext(NULL)); + host_ = new MockDeviceRequestMessageFilter(resource_context_.get(), + media_stream_manager_.get()); } scoped_refptr<MockDeviceRequestMessageFilter> host_; scoped_ptr<MockMediaStreamManager> media_stream_manager_; + scoped_ptr<MockResourceContext> resource_context_; StreamDeviceInfoArray physical_audio_devices_; StreamDeviceInfoArray physical_video_devices_; scoped_ptr<base::MessageLoop> message_loop_; @@ -255,4 +269,36 @@ TEST_F(DeviceRequestMessageFilterTest, TestGetSources_NoDevices) { RunTest(0, 0); } +TEST_F(DeviceRequestMessageFilterTest, TestGetSources_DenyMicDenyCamera) { + resource_context_->set_mic_access(false); + resource_context_->set_camera_access(false); + RunTest(3, 3); + EXPECT_FALSE(AreLabelsPresent(MEDIA_DEVICE_AUDIO_CAPTURE)); + EXPECT_FALSE(AreLabelsPresent(MEDIA_DEVICE_VIDEO_CAPTURE)); +} + +TEST_F(DeviceRequestMessageFilterTest, TestGetSources_AllowMicDenyCamera) { + resource_context_->set_mic_access(true); + resource_context_->set_camera_access(false); + RunTest(3, 3); + EXPECT_TRUE(AreLabelsPresent(MEDIA_DEVICE_AUDIO_CAPTURE)); + EXPECT_FALSE(AreLabelsPresent(MEDIA_DEVICE_VIDEO_CAPTURE)); +} + +TEST_F(DeviceRequestMessageFilterTest, TestGetSources_DenyMicAllowCamera) { + resource_context_->set_mic_access(false); + resource_context_->set_camera_access(true); + RunTest(3, 3); + EXPECT_FALSE(AreLabelsPresent(MEDIA_DEVICE_AUDIO_CAPTURE)); + EXPECT_TRUE(AreLabelsPresent(MEDIA_DEVICE_VIDEO_CAPTURE)); +} + +TEST_F(DeviceRequestMessageFilterTest, TestGetSources_AllowMicAllowCamera) { + resource_context_->set_mic_access(true); + resource_context_->set_camera_access(true); + RunTest(3, 3); + EXPECT_TRUE(AreLabelsPresent(MEDIA_DEVICE_AUDIO_CAPTURE)); + EXPECT_TRUE(AreLabelsPresent(MEDIA_DEVICE_VIDEO_CAPTURE)); +} + }; // namespace content diff --git a/content/browser/renderer_host/render_process_host_impl.cc b/content/browser/renderer_host/render_process_host_impl.cc index 5204117..36acbd9 100644 --- a/content/browser/renderer_host/render_process_host_impl.cc +++ b/content/browser/renderer_host/render_process_host_impl.cc @@ -657,7 +657,8 @@ void RenderProcessHostImpl::CreateMessageFilters() { channel_->AddFilter(peer_connection_tracker_host_.get()); channel_->AddFilter(new MediaStreamDispatcherHost( GetID(), media_stream_manager)); - channel_->AddFilter(new DeviceRequestMessageFilter(media_stream_manager)); + channel_->AddFilter( + new DeviceRequestMessageFilter(resource_context, media_stream_manager)); #endif #if defined(ENABLE_PLUGINS) // TODO(raymes): PepperMessageFilter should be removed from here. diff --git a/content/public/browser/resource_context.h b/content/public/browser/resource_context.h index 7acfff4..191f30a 100644 --- a/content/public/browser/resource_context.h +++ b/content/public/browser/resource_context.h @@ -10,6 +10,8 @@ #include "build/build_config.h" #include "content/common/content_export.h" +class GURL; + namespace appcache { class AppCacheService; } @@ -38,6 +40,16 @@ class CONTENT_EXPORT ResourceContext : public base::SupportsUserData { // storage partitioning. This getter returns the default context associated // with a BrowsingContext. virtual net::URLRequestContext* GetRequestContext() = 0; + + // Returns true if microphone access is allowed for |origin|. Used to + // determine what level of authorization is given to |origin| to access + // resource metadata. + virtual bool AllowMicAccess(const GURL& origin) = 0; + + // Returns true if web camera access is allowed for |origin|. Used to + // determine what level of authorization is given to |origin| to access + // resource metadata. + virtual bool AllowCameraAccess(const GURL& origin) = 0; }; } // namespace content diff --git a/content/public/test/mock_resource_context.cc b/content/public/test/mock_resource_context.cc index adbb6b5..342766c 100644 --- a/content/public/test/mock_resource_context.cc +++ b/content/public/test/mock_resource_context.cc @@ -14,7 +14,9 @@ MockResourceContext::MockResourceContext() MockResourceContext::MockResourceContext( net::URLRequestContext* test_request_context) - : test_request_context_(test_request_context) { + : test_request_context_(test_request_context), + mic_allowed_(false), + camera_allowed_(false) { } MockResourceContext::~MockResourceContext() {} @@ -28,4 +30,12 @@ net::URLRequestContext* MockResourceContext::GetRequestContext() { return test_request_context_; } +bool MockResourceContext::AllowMicAccess(const GURL& origin) { + return mic_allowed_; +} + +bool MockResourceContext::AllowCameraAccess(const GURL& origin) { + return camera_allowed_; +} + } // namespace content diff --git a/content/public/test/mock_resource_context.h b/content/public/test/mock_resource_context.h index e42f5c6..8f1791a 100644 --- a/content/public/test/mock_resource_context.h +++ b/content/public/test/mock_resource_context.h @@ -28,10 +28,25 @@ class MockResourceContext : public ResourceContext { // ResourceContext implementation: virtual net::HostResolver* GetHostResolver() OVERRIDE; virtual net::URLRequestContext* GetRequestContext() OVERRIDE; + virtual bool AllowMicAccess(const GURL& origin) OVERRIDE; + virtual bool AllowCameraAccess(const GURL& origin) OVERRIDE; + + ////////////////////////////////////////////////////////////////////////// + // The following functions are used by tests. + void set_mic_access(bool mic_allowed) { + mic_allowed_ = mic_allowed; + } + + void set_camera_access(bool camera_allowed) { + camera_allowed_ = camera_allowed; + } private: net::URLRequestContext* test_request_context_; + bool mic_allowed_; + bool camera_allowed_; + DISALLOW_COPY_AND_ASSIGN(MockResourceContext); }; diff --git a/content/shell/shell_browser_context.cc b/content/shell/shell_browser_context.cc index 58b966c..1c89355 100644 --- a/content/shell/shell_browser_context.cc +++ b/content/shell/shell_browser_context.cc @@ -43,6 +43,12 @@ class ShellBrowserContext::ShellResourceContext : public ResourceContext { CHECK(getter_); return getter_->GetURLRequestContext(); } + virtual bool AllowMicAccess(const GURL& origin) OVERRIDE { + return false; + } + virtual bool AllowCameraAccess(const GURL& origin) OVERRIDE { + return false; + } void set_url_request_context_getter(ShellURLRequestContextGetter* getter) { getter_ = getter; diff --git a/content/test/webrtc_audio_device_test.cc b/content/test/webrtc_audio_device_test.cc index eb5b1df..c258caf 100644 --- a/content/test/webrtc_audio_device_test.cc +++ b/content/test/webrtc_audio_device_test.cc @@ -110,6 +110,14 @@ class MockRTCResourceContext : public ResourceContext { return test_request_context_; } + virtual bool AllowMicAccess(const GURL& origin) OVERRIDE { + return false; + } + + virtual bool AllowCameraAccess(const GURL& origin) OVERRIDE { + return false; + } + private: net::URLRequestContext* test_request_context_; |