diff options
author | kkimlabs@chromium.org <kkimlabs@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2013-09-23 04:15:45 +0000 |
---|---|---|
committer | kkimlabs@chromium.org <kkimlabs@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2013-09-23 04:15:45 +0000 |
commit | f961a0fedd9bfae93284d6d0d989f42da3caac7b (patch) | |
tree | 770a1f9679799f8e50decff35ecc27cad4d89f8a /chrome/browser/media | |
parent | d34e683c837a2e48a19c576b768ea516b2dfca1f (diff) | |
download | chromium_src-f961a0fedd9bfae93284d6d0d989f42da3caac7b.zip chromium_src-f961a0fedd9bfae93284d6d0d989f42da3caac7b.tar.gz chromium_src-f961a0fedd9bfae93284d6d0d989f42da3caac7b.tar.bz2 |
[Android] EME permission on/off pref and infobar UI.
For protected media identifier access permission,
add global on/off preference setting and infobar permission gate UI.
BUG=281576
Review URL: https://chromiumcodereview.appspot.com/23531021
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@224650 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'chrome/browser/media')
6 files changed, 584 insertions, 0 deletions
diff --git a/chrome/browser/media/protected_media_identifier_infobar_delegate.cc b/chrome/browser/media/protected_media_identifier_infobar_delegate.cc new file mode 100644 index 0000000..bde3fbf --- /dev/null +++ b/chrome/browser/media/protected_media_identifier_infobar_delegate.cc @@ -0,0 +1,108 @@ +// Copyright 2013 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "chrome/browser/media/protected_media_identifier_infobar_delegate.h" + +#include "chrome/browser/content_settings/permission_queue_controller.h" +#include "content/public/browser/navigation_details.h" +#include "content/public/browser/navigation_entry.h" +#include "grit/generated_resources.h" +#include "grit/theme_resources.h" +#include "net/base/net_util.h" +#include "ui/base/l10n/l10n_util.h" + +// static +InfoBarDelegate* ProtectedMediaIdentifierInfoBarDelegate::Create( + InfoBarService* infobar_service, + PermissionQueueController* controller, + const PermissionRequestID& id, + const GURL& requesting_frame, + const std::string& display_languages) { + const content::NavigationEntry* committed_entry = + infobar_service->web_contents()->GetController().GetLastCommittedEntry(); + return infobar_service->AddInfoBar( + scoped_ptr<InfoBarDelegate>(new ProtectedMediaIdentifierInfoBarDelegate( + infobar_service, + controller, + id, + requesting_frame, + committed_entry ? committed_entry->GetUniqueID() : 0, + display_languages))); +} + + +ProtectedMediaIdentifierInfoBarDelegate:: + ProtectedMediaIdentifierInfoBarDelegate( + InfoBarService* infobar_service, + PermissionQueueController* controller, + const PermissionRequestID& id, + const GURL& requesting_frame, + int contents_unique_id, + const std::string& display_languages) + : ConfirmInfoBarDelegate(infobar_service), + controller_(controller), + id_(id), + requesting_frame_(requesting_frame), + contents_unique_id_(contents_unique_id), + display_languages_(display_languages) {} + +ProtectedMediaIdentifierInfoBarDelegate:: + ~ProtectedMediaIdentifierInfoBarDelegate() {} + +bool ProtectedMediaIdentifierInfoBarDelegate::Accept() { + SetPermission(true, true); + return true; +} + +void ProtectedMediaIdentifierInfoBarDelegate::SetPermission( + bool update_content_setting, + bool allowed) { + controller_->OnPermissionSet(id_, + requesting_frame_, + web_contents()->GetLastCommittedURL(), + update_content_setting, + allowed); +} + +void ProtectedMediaIdentifierInfoBarDelegate::InfoBarDismissed() { + SetPermission(false, false); +} + +int ProtectedMediaIdentifierInfoBarDelegate::GetIconID() const { + return IDR_PROTECTED_MEDIA_IDENTIFIER_INFOBAR_ICON; +} + +InfoBarDelegate::Type ProtectedMediaIdentifierInfoBarDelegate::GetInfoBarType() + const { + return PAGE_ACTION_TYPE; +} + +bool ProtectedMediaIdentifierInfoBarDelegate::ShouldExpireInternal( + const content::LoadCommittedDetails& details) const { + // This implementation matches InfoBarDelegate::ShouldExpireInternal(), but + // uses the unique ID we set in the constructor instead of that stored in the + // base class. + return (contents_unique_id_ != details.entry->GetUniqueID()) || + (content::PageTransitionStripQualifier( + details.entry->GetTransitionType()) == + content::PAGE_TRANSITION_RELOAD); +} + +string16 ProtectedMediaIdentifierInfoBarDelegate::GetMessageText() const { + return l10n_util::GetStringFUTF16( + IDS_PROTECTED_MEDIA_IDENTIFIER_INFOBAR_QUESTION, + net::FormatUrl(requesting_frame_.GetOrigin(), display_languages_)); +} + +string16 ProtectedMediaIdentifierInfoBarDelegate::GetButtonLabel( + InfoBarButton button) const { + return l10n_util::GetStringUTF16( + (button == BUTTON_OK) ? IDS_PROTECTED_MEDIA_IDENTIFIER_ALLOW_BUTTON + : IDS_PROTECTED_MEDIA_IDENTIFIER_DENY_BUTTON); +} + +bool ProtectedMediaIdentifierInfoBarDelegate::Cancel() { + SetPermission(true, false); + return true; +} diff --git a/chrome/browser/media/protected_media_identifier_infobar_delegate.h b/chrome/browser/media/protected_media_identifier_infobar_delegate.h new file mode 100644 index 0000000..9510772 --- /dev/null +++ b/chrome/browser/media/protected_media_identifier_infobar_delegate.h @@ -0,0 +1,60 @@ +// Copyright 2013 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef CHROME_BROWSER_MEDIA_PROTECTED_MEDIA_IDENTIFIER_INFOBAR_DELEGATE_H_ +#define CHROME_BROWSER_MEDIA_PROTECTED_MEDIA_IDENTIFIER_INFOBAR_DELEGATE_H_ + +#include <string> + +#include "chrome/browser/content_settings/permission_request_id.h" +#include "chrome/browser/infobars/confirm_infobar_delegate.h" +#include "url/gurl.h" + +class PermissionQueueController; +class InfoBarService; + +class ProtectedMediaIdentifierInfoBarDelegate : public ConfirmInfoBarDelegate { + public: + // Creates a protected media identifier infobar delegate and adds it to + // |infobar_service|. + // Returns the delegate if it was successfully added. + static InfoBarDelegate* Create(InfoBarService* infobar_service, + PermissionQueueController* controller, + const PermissionRequestID& id, + const GURL& requesting_frame, + const std::string& display_languages); + protected: + ProtectedMediaIdentifierInfoBarDelegate(InfoBarService* infobar_service, + PermissionQueueController* controller, + const PermissionRequestID& id, + const GURL& requesting_frame, + int contents_unique_id, + const std::string& display_languages); + virtual ~ProtectedMediaIdentifierInfoBarDelegate(); + + // Call back to the controller, to inform of the user's decision. + void SetPermission(bool update_content_setting, bool allowed); + + private: + // ConfirmInfoBarDelegate: + virtual void InfoBarDismissed() OVERRIDE; + virtual int GetIconID() const OVERRIDE; + virtual Type GetInfoBarType() const OVERRIDE; + virtual bool ShouldExpireInternal( + const content::LoadCommittedDetails& details) const OVERRIDE; + virtual string16 GetMessageText() const OVERRIDE; + virtual string16 GetButtonLabel(InfoBarButton button) const OVERRIDE; + virtual bool Accept() OVERRIDE; + virtual bool Cancel() OVERRIDE; + + PermissionQueueController* controller_; + const PermissionRequestID id_; + GURL requesting_frame_; + int contents_unique_id_; + std::string display_languages_; + + DISALLOW_COPY_AND_ASSIGN(ProtectedMediaIdentifierInfoBarDelegate); +}; + +#endif // CHROME_BROWSER_MEDIA_PROTECTED_MEDIA_IDENTIFIER_INFOBAR_DELEGATE_H_ diff --git a/chrome/browser/media/protected_media_identifier_permission_context.cc b/chrome/browser/media/protected_media_identifier_permission_context.cc new file mode 100644 index 0000000..6f01795 --- /dev/null +++ b/chrome/browser/media/protected_media_identifier_permission_context.cc @@ -0,0 +1,202 @@ +// Copyright 2013 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "chrome/browser/media/protected_media_identifier_permission_context.h" + +#include <functional> +#include <string> +#include <vector> + +#include "base/bind.h" +#include "base/strings/utf_string_conversions.h" +#include "chrome/browser/content_settings/host_content_settings_map.h" +#include "chrome/browser/content_settings/permission_request_id.h" +#include "chrome/browser/content_settings/tab_specific_content_settings.h" +#include "chrome/browser/extensions/extension_service.h" +#include "chrome/browser/extensions/extension_system.h" +#include "chrome/browser/extensions/suggest_permission_util.h" +#include "chrome/browser/profiles/profile.h" +#include "chrome/browser/tab_contents/tab_util.h" +#include "chrome/common/extensions/extension.h" +#include "chrome/common/pref_names.h" +#include "content/public/browser/browser_thread.h" +#include "content/public/browser/render_view_host.h" +#include "content/public/browser/web_contents.h" +#include "extensions/browser/view_type_utils.h" + +using extensions::APIPermission; + +ProtectedMediaIdentifierPermissionContext:: + ProtectedMediaIdentifierPermissionContext(Profile* profile) + : profile_(profile), shutting_down_(false) {} + +ProtectedMediaIdentifierPermissionContext:: + ~ProtectedMediaIdentifierPermissionContext() { + // ProtectedMediaIdentifierPermissionContext may be destroyed on either + // the UI thread or the IO thread, but the PermissionQueueController must have + // been destroyed on the UI thread. + DCHECK(!permission_queue_controller_.get()); +} + +void ProtectedMediaIdentifierPermissionContext:: + RequestProtectedMediaIdentifierPermission( + int render_process_id, + int render_view_id, + const GURL& requesting_frame, + const base::Callback<void(bool)>& callback) { + DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)); + if (shutting_down_) + return; + + content::WebContents* web_contents = + tab_util::GetWebContentsByID(render_process_id, render_view_id); + const PermissionRequestID id(render_process_id, render_view_id, 0); + + if (extensions::GetViewType(web_contents) != + extensions::VIEW_TYPE_TAB_CONTENTS) { + // The tab may have gone away, or the request may not be from a tab at all. + LOG(WARNING) + << "Attempt to use protected media identifier in tabless renderer: " + << id.ToString() + << " (can't prompt user without a visible tab)"; + NotifyPermissionSet(id, requesting_frame, callback, false); + return; + } + + GURL embedder = web_contents->GetLastCommittedURL(); + if (!requesting_frame.is_valid() || !embedder.is_valid()) { + LOG(WARNING) + << "Attempt to use protected media identifier from an invalid URL: " + << requesting_frame << "," << embedder + << " (proteced media identifier is not supported in popups)"; + NotifyPermissionSet(id, requesting_frame, callback, false); + return; + } + + DecidePermission(id, requesting_frame, embedder, callback); +} + +void ProtectedMediaIdentifierPermissionContext:: + CancelProtectedMediaIdentifierPermissionRequest( + int render_process_id, + int render_view_id, + const GURL& requesting_frame) { + CancelPendingInfoBarRequest( + PermissionRequestID(render_process_id, render_view_id, 0)); +} + +void ProtectedMediaIdentifierPermissionContext::DecidePermission( + const PermissionRequestID& id, + const GURL& requesting_frame, + const GURL& embedder, + const base::Callback<void(bool)>& callback) { + DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)); + +#if defined(OS_ANDROID) + // Check if the protected media identifier master switch is disabled. + if (!profile()->GetPrefs()->GetBoolean( + prefs::kProtectedMediaIdentifierEnabled)) { + PermissionDecided(id, requesting_frame, embedder, callback, false); + return; + } +#endif + + ContentSetting content_setting = + profile_->GetHostContentSettingsMap()->GetContentSetting( + requesting_frame, + embedder, + CONTENT_SETTINGS_TYPE_PROTECTED_MEDIA_IDENTIFIER, + std::string()); + switch (content_setting) { + case CONTENT_SETTING_BLOCK: + PermissionDecided(id, requesting_frame, embedder, callback, false); + break; + case CONTENT_SETTING_ALLOW: + PermissionDecided(id, requesting_frame, embedder, callback, true); + break; + case CONTENT_SETTING_ASK: + QueueController()->CreateInfoBarRequest( + id, + requesting_frame, + embedder, + base::Bind(&ProtectedMediaIdentifierPermissionContext:: + NotifyPermissionSet, + base::Unretained(this), + id, + requesting_frame, + callback)); + break; + default: + NOTREACHED(); + } +} + +void ProtectedMediaIdentifierPermissionContext::ShutdownOnUIThread() { + DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)); + permission_queue_controller_.reset(); + shutting_down_ = true; +} + +void ProtectedMediaIdentifierPermissionContext::PermissionDecided( + const PermissionRequestID& id, + const GURL& requesting_frame, + const GURL& embedder, + const base::Callback<void(bool)>& callback, + bool allowed) { + NotifyPermissionSet(id, requesting_frame, callback, allowed); +} + +void ProtectedMediaIdentifierPermissionContext::NotifyPermissionSet( + const PermissionRequestID& id, + const GURL& requesting_frame, + const base::Callback<void(bool)>& callback, + bool allowed) { + DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)); + + // WebContents may have gone away. + TabSpecificContentSettings* content_settings = + TabSpecificContentSettings::Get(id.render_process_id(), + id.render_view_id()); + if (content_settings) { + content_settings->OnProtectedMediaIdentifierPermissionSet( + requesting_frame.GetOrigin(), allowed); + } + + callback.Run(allowed); +} + +PermissionQueueController* + ProtectedMediaIdentifierPermissionContext::QueueController() { + DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)); + DCHECK(!shutting_down_); + if (!permission_queue_controller_) + permission_queue_controller_.reset(CreateQueueController()); + return permission_queue_controller_.get(); +} + +PermissionQueueController* + ProtectedMediaIdentifierPermissionContext::CreateQueueController() { + DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)); + return new PermissionQueueController( + profile(), CONTENT_SETTINGS_TYPE_PROTECTED_MEDIA_IDENTIFIER); +} + +void +ProtectedMediaIdentifierPermissionContext::CancelPendingInfoBarRequest( + const PermissionRequestID& id) { + if (!content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)) { + content::BrowserThread::PostTask( + content::BrowserThread::UI, + FROM_HERE, + base::Bind(&ProtectedMediaIdentifierPermissionContext:: + CancelPendingInfoBarRequest, + this, + id)); + return; + } + DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)); + if (shutting_down_) + return; + QueueController()->CancelInfoBarRequest(id); +} diff --git a/chrome/browser/media/protected_media_identifier_permission_context.h b/chrome/browser/media/protected_media_identifier_permission_context.h new file mode 100644 index 0000000..b30fc236d --- /dev/null +++ b/chrome/browser/media/protected_media_identifier_permission_context.h @@ -0,0 +1,90 @@ +// Copyright 2013 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef CHROME_BROWSER_MEDIA_PROTECTED_MEDIA_IDENTIFIER_PERMISSION_CONTEXT_H_ +#define CHROME_BROWSER_MEDIA_PROTECTED_MEDIA_IDENTIFIER_PERMISSION_CONTEXT_H_ + +#include <string> + +#include "base/memory/scoped_ptr.h" +#include "chrome/browser/content_settings/permission_queue_controller.h" + +class PermissionRequestID; +class Profile; + +// Manages protected media identifier permissions flow, and delegates UI +// handling via PermissionQueueController. +class ProtectedMediaIdentifierPermissionContext + : public base::RefCountedThreadSafe< + ProtectedMediaIdentifierPermissionContext> { + public: + explicit ProtectedMediaIdentifierPermissionContext(Profile* profile); + + void RequestProtectedMediaIdentifierPermission( + int render_process_id, + int render_view_id, + const GURL& requesting_frame, + const base::Callback<void(bool)>& callback); + void CancelProtectedMediaIdentifierPermissionRequest( + int render_process_id, + int render_view_id, + const GURL& requesting_frame); + + // Called on the UI thread when the profile is about to be destroyed. + void ShutdownOnUIThread(); + + private: + friend class base::RefCountedThreadSafe< + ProtectedMediaIdentifierPermissionContext>; + ~ProtectedMediaIdentifierPermissionContext(); + + Profile* profile() const { return profile_; } + + // Return an instance of the infobar queue controller, creating it + // if necessary. + PermissionQueueController* QueueController(); + + // Notifies whether or not the corresponding bridge is allowed to use + // protected media identifier via + // SetProtectedMediaIdentifierPermissionResponse(). Called on the UI thread. + void NotifyPermissionSet(const PermissionRequestID& id, + const GURL& requesting_frame, + const base::Callback<void(bool)>& callback, + bool allowed); + + // Decide whether the protected media identifier permission should be granted. + // Calls PermissionDecided if permission can be decided non-interactively, + // or NotifyPermissionSet if permission decided by presenting an + // infobar to the user. Called on the UI thread. + void DecidePermission(const PermissionRequestID& id, + const GURL& requesting_frame, + const GURL& embedder, + const base::Callback<void(bool)>& callback); + + // Called when permission is granted without interactively asking + // the user. Can be overridden to introduce additional UI flow. + // Should ultimately ensure that NotifyPermissionSet is called. + // Called on the UI thread. + void PermissionDecided(const PermissionRequestID& id, + const GURL& requesting_frame, + const GURL& embedder, + const base::Callback<void(bool)>& callback, + bool allowed); + + // Create an PermissionQueueController. overridden in derived classes to + // provide additional UI flow. Called on the UI thread. + PermissionQueueController* CreateQueueController(); + + // Removes any pending InfoBar request. + void CancelPendingInfoBarRequest(const PermissionRequestID& id); + + // These must only be accessed from the UI thread. + Profile* const profile_; + bool shutting_down_; + scoped_ptr<PermissionQueueController> permission_queue_controller_; + + DISALLOW_COPY_AND_ASSIGN(ProtectedMediaIdentifierPermissionContext); +}; + +#endif // CHROME_BROWSER_MEDIA_PROTECTED_MEDIA_IDENTIFIER_PERMISSION_CONTEXT_H_ diff --git a/chrome/browser/media/protected_media_identifier_permission_context_factory.cc b/chrome/browser/media/protected_media_identifier_permission_context_factory.cc new file mode 100644 index 0000000..b4a2f47 --- /dev/null +++ b/chrome/browser/media/protected_media_identifier_permission_context_factory.cc @@ -0,0 +1,83 @@ +// Copyright 2013 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "chrome/browser/media/protected_media_identifier_permission_context_factory.h" + +#include "chrome/browser/media/protected_media_identifier_permission_context.h" +#include "chrome/browser/profiles/incognito_helpers.h" +#include "chrome/browser/profiles/profile.h" +#include "chrome/common/pref_names.h" +#include "components/browser_context_keyed_service/browser_context_dependency_manager.h" +#include "components/user_prefs/pref_registry_syncable.h" + +namespace { + +class Service : public BrowserContextKeyedService { + public: + explicit Service(Profile* profile) { + context_ = new ProtectedMediaIdentifierPermissionContext(profile); + } + + ProtectedMediaIdentifierPermissionContext* context() { + return context_.get(); + } + + virtual void Shutdown() OVERRIDE { + context()->ShutdownOnUIThread(); + } + + private: + scoped_refptr<ProtectedMediaIdentifierPermissionContext> context_; + + DISALLOW_COPY_AND_ASSIGN(Service); +}; + +} // namespace + +// static +ProtectedMediaIdentifierPermissionContext* +ProtectedMediaIdentifierPermissionContextFactory::GetForProfile( + Profile* profile) { + return static_cast<Service*>( + GetInstance()->GetServiceForBrowserContext(profile, true))->context(); +} + +// static +ProtectedMediaIdentifierPermissionContextFactory* +ProtectedMediaIdentifierPermissionContextFactory::GetInstance() { + return Singleton< + ProtectedMediaIdentifierPermissionContextFactory>::get(); +} + +ProtectedMediaIdentifierPermissionContextFactory:: +ProtectedMediaIdentifierPermissionContextFactory() + : BrowserContextKeyedServiceFactory( + "ProtectedMediaIdentifierPermissionContext", + BrowserContextDependencyManager::GetInstance()) { +} + +ProtectedMediaIdentifierPermissionContextFactory:: +~ProtectedMediaIdentifierPermissionContextFactory() { +} + +BrowserContextKeyedService* +ProtectedMediaIdentifierPermissionContextFactory::BuildServiceInstanceFor( + content::BrowserContext* profile) const { + return new Service(static_cast<Profile*>(profile)); +} + +void +ProtectedMediaIdentifierPermissionContextFactory::RegisterProfilePrefs( + user_prefs::PrefRegistrySyncable* registry) { + registry->RegisterBooleanPref( + prefs::kProtectedMediaIdentifierEnabled, + true, + user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF); +} + +content::BrowserContext* +ProtectedMediaIdentifierPermissionContextFactory::GetBrowserContextToUse( + content::BrowserContext* context) const { + return chrome::GetBrowserContextOwnInstanceInIncognito(context); +} diff --git a/chrome/browser/media/protected_media_identifier_permission_context_factory.h b/chrome/browser/media/protected_media_identifier_permission_context_factory.h new file mode 100644 index 0000000..a6f85fe --- /dev/null +++ b/chrome/browser/media/protected_media_identifier_permission_context_factory.h @@ -0,0 +1,41 @@ +// Copyright 2013 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef CHROME_BROWSER_MEDIA_PROTECTED_MEDIA_IDENTIFIER_PERMISSION_CONTEXT_FACTORY_H_ +#define CHROME_BROWSER_MEDIA_PROTECTED_MEDIA_IDENTIFIER_PERMISSION_CONTEXT_FACTORY_H_ + +#include "base/memory/singleton.h" +#include "components/browser_context_keyed_service/browser_context_keyed_service_factory.h" + +class ProtectedMediaIdentifierPermissionContext; +class Profile; + +class ProtectedMediaIdentifierPermissionContextFactory + : public BrowserContextKeyedServiceFactory { + public: + static ProtectedMediaIdentifierPermissionContext* GetForProfile( + Profile* profile); + + static ProtectedMediaIdentifierPermissionContextFactory* GetInstance(); + + private: + friend struct DefaultSingletonTraits< + ProtectedMediaIdentifierPermissionContextFactory>; + + ProtectedMediaIdentifierPermissionContextFactory(); + virtual ~ProtectedMediaIdentifierPermissionContextFactory(); + + // BrowserContextKeyedBaseFactory methods: + virtual BrowserContextKeyedService* BuildServiceInstanceFor( + content::BrowserContext* profile) const OVERRIDE; + virtual void RegisterProfilePrefs( + user_prefs::PrefRegistrySyncable* registry) OVERRIDE; + virtual content::BrowserContext* GetBrowserContextToUse( + content::BrowserContext* context) const OVERRIDE; + + DISALLOW_COPY_AND_ASSIGN( + ProtectedMediaIdentifierPermissionContextFactory); +}; + +#endif // CHROME_BROWSER_MEDIA_PROTECTED_MEDIA_IDENTIFIER_PERMISSION_CONTEXT_FACTORY_H_ |