Skip to content

Commit

Permalink
media: Add MediaPermission interface and MediaPermissionDispatcher.
Browse files Browse the repository at this point in the history
MediaPermission is the interface for media code to check/request media related
permissions. MediaPermissionDispatcher is a MediaPermission implementation in
content/.

Plan of follow-up CL:
- Use MediaPermission in ProxyDecryptor and remove current protected media
  identifier info bar code in the browser process (on Android and ChromeOS).

BUG=446263
TEST=Tested on Android with encrypted-media-requestmediakeysystemaccess.html
layout test by calling MediaPermission methods manually in
webencryptedmediaclient_impl.cc.

Review URL: https://codereview.chromium.org/871663003

Cr-Commit-Position: refs/heads/master@{#313303}
  • Loading branch information
xhwang-chromium authored and Commit bot committed Jan 27, 2015
1 parent 8bd6f98 commit 36b1f3b
Show file tree
Hide file tree
Showing 16 changed files with 251 additions and 9 deletions.
1 change: 1 addition & 0 deletions chrome/browser/chrome_content_browser_client.cc
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@
#include "chrome/browser/media/media_capture_devices_dispatcher.h"
#include "chrome/browser/media/midi_permission_context.h"
#include "chrome/browser/media/midi_permission_context_factory.h"
#include "chrome/browser/media/protected_media_identifier_permission_context_factory.h"
#include "chrome/browser/metrics/chrome_browser_main_extra_parts_metrics.h"
#include "chrome/browser/nacl_host/nacl_browser_delegate_impl.h"
#include "chrome/browser/net/chrome_net_log.h"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,14 +24,14 @@ class ProtectedMediaIdentifierPermissionContextFactory
ProtectedMediaIdentifierPermissionContextFactory>;

ProtectedMediaIdentifierPermissionContextFactory();
virtual ~ProtectedMediaIdentifierPermissionContextFactory();
~ProtectedMediaIdentifierPermissionContextFactory() override;

// BrowserContextKeyedBaseFactory methods:
virtual KeyedService* BuildServiceInstanceFor(
KeyedService* BuildServiceInstanceFor(
content::BrowserContext* profile) const override;
virtual void RegisterProfilePrefs(
void RegisterProfilePrefs(
user_prefs::PrefRegistrySyncable* registry) override;
virtual content::BrowserContext* GetBrowserContextToUse(
content::BrowserContext* GetBrowserContextToUse(
content::BrowserContext* context) const override;

DISALLOW_COPY_AND_ASSIGN(
Expand Down
2 changes: 2 additions & 0 deletions content/browser/permissions/permission_service_impl.cc
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,8 @@ PermissionType PermissionNameToPermissionType(PermissionName name) {
return PERMISSION_MIDI_SYSEX;
case PERMISSION_NAME_NOTIFICATIONS:
return PERMISSION_NOTIFICATIONS;
case PERMISSION_NAME_PROTECTED_MEDIA_IDENTIFIER:
return PERMISSION_PROTECTED_MEDIA;
}

NOTREACHED();
Expand Down
1 change: 1 addition & 0 deletions content/common/permission_service.mojom
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ enum PermissionName {
GEOLOCATION,
MIDI_SYSEX,
NOTIFICATIONS,
PROTECTED_MEDIA_IDENTIFIER,
};

// The Permission service provides permission handling capabilities by exposing
Expand Down
2 changes: 2 additions & 0 deletions content/content_renderer.gypi
Original file line number Diff line number Diff line change
Expand Up @@ -272,6 +272,8 @@
'renderer/media/media_stream_dispatcher_eventhandler.h',
'renderer/media/media_stream_track.cc',
'renderer/media/media_stream_track.h',
'renderer/media/media_permission_dispatcher.cc',
'renderer/media/media_permission_dispatcher.h',
'renderer/media/midi_dispatcher.cc',
'renderer/media/midi_dispatcher.h',
'renderer/media/midi_message_filter.cc',
Expand Down
96 changes: 96 additions & 0 deletions content/renderer/media/media_permission_dispatcher.cc
Original file line number Diff line number Diff line change
@@ -0,0 +1,96 @@
// Copyright 2015 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.

#include "content/renderer/media/media_permission_dispatcher.h"

#include "base/bind.h"
#include "base/logging.h"
#include "content/public/common/service_registry.h"
#include "content/public/renderer/render_frame.h"
#include "third_party/WebKit/public/web/WebUserGestureIndicator.h"
#include "url/gurl.h"

namespace content {

MediaPermissionDispatcher::MediaPermissionDispatcher(RenderFrame* render_frame)
: RenderFrameObserver(render_frame), next_request_id_(0) {
}

MediaPermissionDispatcher::~MediaPermissionDispatcher() {
DCHECK(thread_checker_.CalledOnValidThread());

// Fire all pending callbacks with |false|.
for (auto& request : requests_)
request.second.Run(false);

requests_.clear();
}

void MediaPermissionDispatcher::HasPermission(
Type type,
const GURL& security_origin,
const PermissionStatusCB& permission_status_cb) {
DCHECK(thread_checker_.CalledOnValidThread());
CHECK_EQ(PROTECTED_MEDIA_IDENTIFIER, type);

if (!permission_service_.get()) {
render_frame()->GetServiceRegistry()->ConnectToRemoteService(
&permission_service_);
}

uint32_t request_id = next_request_id_++;
DCHECK(!requests_.count(request_id));
requests_[request_id] = permission_status_cb;

DVLOG(2) << __FUNCTION__ << ": request ID " << request_id;

permission_service_->HasPermission(
PERMISSION_NAME_PROTECTED_MEDIA_IDENTIFIER, security_origin.spec(),
base::Bind(&MediaPermissionDispatcher::OnPermissionStatus,
base::Unretained(this), request_id));
}

void MediaPermissionDispatcher::RequestPermission(
Type type,
const GURL& security_origin,
const PermissionStatusCB& permission_status_cb) {
DCHECK(thread_checker_.CalledOnValidThread());
CHECK_EQ(PROTECTED_MEDIA_IDENTIFIER, type);

if (!permission_service_.get()) {
render_frame()->GetServiceRegistry()->ConnectToRemoteService(
&permission_service_);
}

uint32_t request_id = next_request_id_++;
DCHECK(!requests_.count(request_id));
requests_[request_id] = permission_status_cb;

DVLOG(2) << __FUNCTION__ << ": request ID " << request_id;

permission_service_->RequestPermission(
PERMISSION_NAME_PROTECTED_MEDIA_IDENTIFIER, security_origin.spec(),
blink::WebUserGestureIndicator::isProcessingUserGesture(),
base::Bind(&MediaPermissionDispatcher::OnPermissionStatus,
base::Unretained(this), request_id));
}

void MediaPermissionDispatcher::OnPermissionStatus(uint32_t request_id,
PermissionStatus status) {
DVLOG(2) << __FUNCTION__ << ": (" << request_id << ", " << status << ")";
DCHECK(thread_checker_.CalledOnValidThread());

RequestMap::iterator iter = requests_.find(request_id);
if (iter == requests_.end()) {
DVLOG(2) << "Request not found.";
return;
}

PermissionStatusCB permission_status_cb = iter->second;
requests_.erase(iter);

permission_status_cb.Run(status == PERMISSION_STATUS_GRANTED);
}

} // namespace content
53 changes: 53 additions & 0 deletions content/renderer/media/media_permission_dispatcher.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
// Copyright 2015 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.

#ifndef CONTENT_RENDERER_MEDIA_MEDIA_PERMISSION_DISPATCHER_H_
#define CONTENT_RENDERER_MEDIA_MEDIA_PERMISSION_DISPATCHER_H_

#include <map>

#include "base/threading/thread_checker.h"
#include "content/common/content_export.h"
#include "content/common/permission_service.mojom.h"
#include "content/public/renderer/render_frame_observer.h"
#include "media/base/media_permission.h"

namespace content {

// MediaPermission implementation in content. This class is not thread safe
// and should only be used on one thread.
class CONTENT_EXPORT MediaPermissionDispatcher : public media::MediaPermission,
public RenderFrameObserver {
public:
explicit MediaPermissionDispatcher(RenderFrame* render_frame);
~MediaPermissionDispatcher() override;

// media::MediaPermission implementation.
void HasPermission(Type type,
const GURL& security_origin,
const PermissionStatusCB& permission_status_cb) override;
void RequestPermission(
Type type,
const GURL& security_origin,
const PermissionStatusCB& permission_status_cb) override;

private:
// Map of request IDs and pending PermissionStatusCBs.
typedef std::map<uint32_t, PermissionStatusCB> RequestMap;

// Callback for |permission_service_| calls.
void OnPermissionStatus(uint32_t request_id, PermissionStatus status);

uint32_t next_request_id_;
RequestMap requests_;
PermissionServicePtr permission_service_;

base::ThreadChecker thread_checker_;

DISALLOW_COPY_AND_ASSIGN(MediaPermissionDispatcher);
};

} // namespace content

#endif // CONTENT_RENDERER_MEDIA_MEDIA_PERMISSION_DISPATCHER_H_
10 changes: 8 additions & 2 deletions content/renderer/render_frame_impl.cc
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,7 @@
#include "content/renderer/manifest/manifest_manager.h"
#include "content/renderer/media/audio_renderer_mixer_manager.h"
#include "content/renderer/media/crypto/render_cdm_factory.h"
#include "content/renderer/media/media_permission_dispatcher.h"
#include "content/renderer/media/media_stream_dispatcher.h"
#include "content/renderer/media/media_stream_renderer_factory.h"
#include "content/renderer/media/midi_dispatcher.h"
Expand Down Expand Up @@ -675,6 +676,7 @@ RenderFrameImpl::RenderFrameImpl(RenderViewImpl* render_view, int routing_id)
handling_select_range_(false),
notification_permission_dispatcher_(NULL),
web_user_media_client_(NULL),
media_permission_dispatcher_(NULL),
midi_dispatcher_(NULL),
#if defined(OS_ANDROID)
media_player_manager_(NULL),
Expand Down Expand Up @@ -3389,8 +3391,12 @@ blink::WebEncryptedMediaClient* RenderFrameImpl::encryptedMediaClient() {
#else
scoped_ptr<media::CdmFactory> cdm_factory(new RenderCdmFactory());
#endif
web_encrypted_media_client_.reset(
new media::WebEncryptedMediaClientImpl(cdm_factory.Pass()));

DCHECK(!media_permission_dispatcher_);
media_permission_dispatcher_ = new MediaPermissionDispatcher(this);

web_encrypted_media_client_.reset(new media::WebEncryptedMediaClientImpl(
cdm_factory.Pass(), media_permission_dispatcher_));
}
return web_encrypted_media_client_.get();
}
Expand Down
4 changes: 4 additions & 0 deletions content/renderer/render_frame_impl.h
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,7 @@ class GeolocationDispatcher;
class ManifestManager;
class MediaStreamDispatcher;
class MediaStreamRendererFactory;
class MediaPermissionDispatcher;
class MidiDispatcher;
class NotificationPermissionDispatcher;
class PageState;
Expand Down Expand Up @@ -816,6 +817,9 @@ class CONTENT_EXPORT RenderFrameImpl
// EncryptedMediaClient attached to this frame; lazily initialized.
scoped_ptr<media::WebEncryptedMediaClientImpl> web_encrypted_media_client_;

// The media permission dispatcher attached to this frame, lazily initialized.
MediaPermissionDispatcher* media_permission_dispatcher_;

// MidiClient attached to this frame; lazily initialized.
MidiDispatcher* midi_dispatcher_;

Expand Down
2 changes: 2 additions & 0 deletions media/base/BUILD.gn
Original file line number Diff line number Diff line change
Expand Up @@ -113,6 +113,8 @@ source_set("base") {
"media_log.cc",
"media_log.h",
"media_log_event.h",
"media_permission.cc",
"media_permission.h",
"media_switches.cc",
"media_switches.h",
"multi_channel_resampler.cc",
Expand Down
15 changes: 15 additions & 0 deletions media/base/media_permission.cc
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
// Copyright 2015 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.

#include "media/base/media_permission.h"

namespace media {

MediaPermission::MediaPermission() {
}

MediaPermission::~MediaPermission() {
}

} // namespace media
49 changes: 49 additions & 0 deletions media/base/media_permission.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
// Copyright 2015 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.

#ifndef MEDIA_BASE_MEDIA_PERMISSION_H_
#define MEDIA_BASE_MEDIA_PERMISSION_H_

#include "base/callback.h"
#include "base/macros.h"
#include "media/base/media_export.h"

class GURL;

namespace media {

// Interface to handle media related permission checks and requests.
class MEDIA_EXPORT MediaPermission {
public:
typedef base::Callback<void(bool)> PermissionStatusCB;

enum Type {
PROTECTED_MEDIA_IDENTIFIER,
};

MediaPermission();
virtual ~MediaPermission();

// Checks whether |type| is permitted for |security_origion| without
// triggering user interaction (e.g. permission prompt). The status will be
// |false| if the permission has never been set.
virtual void HasPermission(
Type type,
const GURL& security_origin,
const PermissionStatusCB& permission_status_cb) = 0;

// Requests |type| permission for |security_origion|. This may trigger user
// interaction (e.g. permission prompt) if the permission has never been set.
virtual void RequestPermission(
Type type,
const GURL& security_origin,
const PermissionStatusCB& permission_status_cb) = 0;

private:
DISALLOW_COPY_AND_ASSIGN(MediaPermission);
};

} // namespace media

#endif // MEDIA_BASE_MEDIA_PERMISSION_H_
6 changes: 5 additions & 1 deletion media/blink/webencryptedmediaclient_impl.cc
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
#include "base/strings/string_util.h"
#include "base/strings/utf_string_conversions.h"
#include "media/base/key_systems.h"
#include "media/base/media_permission.h"
#include "net/base/mime_util.h"
#include "third_party/WebKit/public/platform/WebEncryptedMediaRequest.h"
#include "third_party/WebKit/public/platform/WebMediaKeySystemConfiguration.h"
Expand Down Expand Up @@ -131,8 +132,11 @@ static bool GetSupportedConfiguration(
}

WebEncryptedMediaClientImpl::WebEncryptedMediaClientImpl(
scoped_ptr<CdmFactory> cdm_factory)
scoped_ptr<CdmFactory> cdm_factory,
MediaPermission* /* media_permission */)
: cdm_factory_(cdm_factory.Pass()) {
// TODO(sandersd): Use |media_permission| to check for media permissions in
// this class.
}

WebEncryptedMediaClientImpl::~WebEncryptedMediaClientImpl() {
Expand Down
5 changes: 4 additions & 1 deletion media/blink/webencryptedmediaclient_impl.h
Original file line number Diff line number Diff line change
Expand Up @@ -13,10 +13,13 @@

namespace media {

class MediaPermission;

class MEDIA_EXPORT WebEncryptedMediaClientImpl
: public blink::WebEncryptedMediaClient {
public:
WebEncryptedMediaClientImpl(scoped_ptr<CdmFactory> cdm_factory);
WebEncryptedMediaClientImpl(scoped_ptr<CdmFactory> cdm_factory,
MediaPermission* media_permission);
virtual ~WebEncryptedMediaClientImpl();

// WebEncryptedMediaClient implementation.
Expand Down
2 changes: 2 additions & 0 deletions media/media.gyp
Original file line number Diff line number Diff line change
Expand Up @@ -325,6 +325,8 @@
'base/media_log.h',
'base/media_log_event.h',
'base/media_posix.cc',
'base/media_permission.cc',
'base/media_permission.h',
'base/media_switches.cc',
'base/media_switches.h',
'base/media_win.cc',
Expand Down
4 changes: 3 additions & 1 deletion mojo/services/html_viewer/html_document.cc
Original file line number Diff line number Diff line change
Expand Up @@ -277,8 +277,10 @@ void HTMLDocument::didNavigateWithinPage(

blink::WebEncryptedMediaClient* HTMLDocument::encryptedMediaClient() {
if (!web_encrypted_media_client_) {
// TODO(xhwang): Hook up permission services and add a MediaPermission
// implementation for HTMLDocument.
web_encrypted_media_client_.reset(new media::WebEncryptedMediaClientImpl(
make_scoped_ptr(new media::DefaultCdmFactory())));
make_scoped_ptr(new media::DefaultCdmFactory()), nullptr));
}
return web_encrypted_media_client_.get();
}
Expand Down

0 comments on commit 36b1f3b

Please sign in to comment.