Commit 1baa3886 authored by timvolodine's avatar timvolodine Committed by Commit bot

Refactor ProtectedMediaIdentifierPermissionContext to derive from PermissionContextBase.

Refactoring of ProtectedMediaIdentifierPermissionContext to derive from
PermissionContextBase class to conform with other APIs like geolocation
and midi. This has the advantage of less code and a consistent path for
all permissions. Also it makes it easier to implement PermissionService
because some functionality like HasPermission() can be implemented at
the level of PermissionContextBase.

Also add the corresponding UMA bits in histograms.xml and
permission_context_uma_util.cc.

BUG=

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

Cr-Commit-Position: refs/heads/master@{#308100}
parent 5a17b565
......@@ -1915,8 +1915,11 @@ void ChromeContentBrowserClient::RequestPermission(
case content::PERMISSION_PROTECTED_MEDIA:
#if defined(OS_ANDROID)
ProtectedMediaIdentifierPermissionContextFactory::GetForProfile(profile)
->RequestProtectedMediaIdentifierPermission(
web_contents, requesting_frame, result_callback);
->RequestPermission(web_contents,
request_id,
requesting_frame.GetOrigin(),
user_gesture,
result_callback);
#else
NOTIMPLEMENTED();
#endif
......@@ -2012,8 +2015,7 @@ void ChromeContentBrowserClient::CancelPermissionRequest(
case content::PERMISSION_PROTECTED_MEDIA:
#if defined(OS_ANDROID)
ProtectedMediaIdentifierPermissionContextFactory::GetForProfile(profile)
->CancelProtectedMediaIdentifierPermissionRequests(
render_process_id, render_view_id, requesting_frame);
->CancelPermissionRequest(web_contents, request_id);
#else
NOTIMPLEMENTED();
#endif
......@@ -2039,7 +2041,7 @@ static ContentSettingsType PermissionToContentSetting(
return CONTENT_SETTINGS_TYPE_NOTIFICATIONS;
case content::PERMISSION_GEOLOCATION:
return CONTENT_SETTINGS_TYPE_GEOLOCATION;
#if defined(OS_ANDROID)
#if defined(OS_ANDROID) || defined(OS_CHROMEOS)
case content::PERMISSION_PROTECTED_MEDIA:
return CONTENT_SETTINGS_TYPE_PROTECTED_MEDIA_IDENTIFIER;
#endif
......
......@@ -168,6 +168,10 @@ PermissionQueueController* PermissionContextBase::GetQueueController() {
return permission_queue_controller_.get();
}
Profile* PermissionContextBase::profile() const {
return profile_;
}
void PermissionContextBase::NotifyPermissionSet(
const PermissionRequestID& id,
const GURL& requesting_origin,
......
......@@ -109,6 +109,9 @@ class PermissionContextBase : public KeyedService {
// Return an instance of the infobar queue controller, creating it if needed.
PermissionQueueController* GetQueueController();
// Returns the profile associated with this permission context.
Profile* profile() const;
// Store the decided permission as a content setting.
// virtual since the permission might be stored with different restrictions
// (for example for desktop notifications).
......
......@@ -78,10 +78,14 @@ void RecordPermissionAction(
"ContentSettings.PermissionActionsInsecureOrigin_PushMessaging",
action);
break;
#if defined(OS_ANDROID)
#if defined(OS_ANDROID) || defined(OS_CHROMEOS)
case CONTENT_SETTINGS_TYPE_PROTECTED_MEDIA_IDENTIFIER:
// TODO(miguelg): support protected media through
// the generic permission class.
PERMISSION_ACTION_UMA(
secure_origin,
"ContentSettings.PermissionActions_ProtectedMedia",
"ContentSettings.PermissionActionsSecureOrigin_ProtectedMedia",
"ContentSettings.PermissionActionsInsecureOrigin_ProtectedMedia",
action);
break;
#endif
default:
......@@ -105,6 +109,11 @@ void RecordPermissionRequest(
case CONTENT_SETTINGS_TYPE_PUSH_MESSAGING:
type = content::PERMISSION_PUSH_MESSAGING;
break;
#if defined(OS_ANDROID) || defined(OS_CHROMEOS)
case CONTENT_SETTINGS_TYPE_PROTECTED_MEDIA_IDENTIFIER:
type = content::PERMISSION_PROTECTED_MEDIA;
break;
#endif
default:
NOTREACHED() << "PERMISSION " << permission << " not accounted for";
return;
......
......@@ -4,22 +4,12 @@
#include "chrome/browser/media/protected_media_identifier_permission_context.h"
#include <functional>
#include <string>
#include <vector>
#include "base/bind.h"
#include "base/prefs/pref_service.h"
#include "base/strings/utf_string_conversions.h"
#include "chrome/browser/content_settings/tab_specific_content_settings.h"
#include "chrome/browser/profiles/profile.h"
#include "chrome/browser/tab_contents/tab_util.h"
#include "chrome/common/pref_names.h"
#include "components/content_settings/core/browser/host_content_settings_map.h"
#include "components/content_settings/core/common/permission_request_id.h"
#include "content/public/browser/browser_thread.h"
#include "content/public/browser/render_process_host.h"
#include "content/public/browser/render_view_host.h"
#include "content/public/browser/web_contents.h"
#if defined(ENABLE_EXTENSIONS)
......@@ -34,30 +24,23 @@ using extensions::APIPermission;
ProtectedMediaIdentifierPermissionContext::
ProtectedMediaIdentifierPermissionContext(Profile* profile)
: profile_(profile), shutting_down_(false) {}
: PermissionContextBase(profile,
CONTENT_SETTINGS_TYPE_PROTECTED_MEDIA_IDENTIFIER) {
}
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(
content::WebContents* web_contents,
const GURL& origin,
base::Callback<void(bool)> result_callback) {
DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
if (shutting_down_)
return;
int render_process_id = web_contents->GetRenderProcessHost()->GetID();
int render_view_id = web_contents->GetRenderViewHost()->GetRoutingID();
void ProtectedMediaIdentifierPermissionContext::RequestPermission(
content::WebContents* web_contents,
const PermissionRequestID& id,
const GURL& requesting_frame_origin,
bool user_gesture,
const BrowserPermissionCallback& callback) {
DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
const PermissionRequestID id(
render_process_id, render_view_id, 0, origin);
GURL embedder = web_contents->GetLastCommittedURL().GetOrigin();
#if defined(ENABLE_EXTENSIONS)
if (extensions::GetViewType(web_contents) !=
......@@ -67,102 +50,42 @@ void ProtectedMediaIdentifierPermissionContext::
<< "Attempt to use protected media identifier in tabless renderer: "
<< id.ToString()
<< " (can't prompt user without a visible tab)";
NotifyPermissionSet(id, origin, result_callback, false);
NotifyPermissionSet(id, origin, embedder, callback, false, false);
return;
}
#endif
GURL embedder = web_contents->GetLastCommittedURL();
if (!origin.is_valid() || !embedder.is_valid()) {
if (!requesting_frame_origin.is_valid() || !embedder.is_valid()) {
LOG(WARNING)
<< "Attempt to use protected media identifier from an invalid URL: "
<< origin << "," << embedder
<< requesting_frame_origin << "," << embedder
<< " (proteced media identifier is not supported in popups)";
NotifyPermissionSet(id, origin, result_callback, false);
NotifyPermissionSet(id, requesting_frame_origin, embedder,
callback, false, false);
return;
}
content::RenderViewHost* rvh = web_contents->GetRenderViewHost();
DecidePermission(id, origin, embedder, rvh, result_callback);
}
void ProtectedMediaIdentifierPermissionContext::
CancelProtectedMediaIdentifierPermissionRequests(
int render_process_id,
int render_view_id,
const GURL& origin) {
CancelPendingInfobarRequests(
render_process_id, render_view_id, origin);
}
void ProtectedMediaIdentifierPermissionContext::DecidePermission(
const PermissionRequestID& id,
const GURL& origin,
const GURL& embedder,
content::RenderViewHost* rvh,
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, origin, embedder, callback, false);
NotifyPermissionSet(id, requesting_frame_origin, embedder, callback,
false, false);
return;
}
#endif
ContentSetting content_setting =
profile_->GetHostContentSettingsMap()->GetContentSetting(
origin,
embedder,
CONTENT_SETTINGS_TYPE_PROTECTED_MEDIA_IDENTIFIER,
std::string());
switch (content_setting) {
case CONTENT_SETTING_BLOCK:
PermissionDecided(id, origin, embedder, callback, false);
break;
case CONTENT_SETTING_ALLOW:
PermissionDecided(id, origin, embedder, callback, true);
break;
case CONTENT_SETTING_ASK:
QueueController()->CreateInfoBarRequest(
id,
origin,
embedder,
base::Bind(&ProtectedMediaIdentifierPermissionContext::
NotifyPermissionSet,
base::Unretained(this),
id,
origin,
callback));
break;
default:
NOTREACHED();
}
}
void ProtectedMediaIdentifierPermissionContext::ShutdownOnUIThread() {
DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
permission_queue_controller_.reset();
shutting_down_ = true;
PermissionContextBase::RequestPermission(web_contents, id,
requesting_frame_origin,
user_gesture,
callback);
}
void ProtectedMediaIdentifierPermissionContext::PermissionDecided(
void ProtectedMediaIdentifierPermissionContext::UpdateTabContext(
const PermissionRequestID& id,
const GURL& origin,
const GURL& embedder,
const base::Callback<void(bool)>& callback,
const GURL& requesting_frame,
bool allowed) {
NotifyPermissionSet(id, origin, callback, allowed);
}
void ProtectedMediaIdentifierPermissionContext::NotifyPermissionSet(
const PermissionRequestID& id,
const GURL& origin,
const base::Callback<void(bool)>& callback,
bool allowed) {
DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
// WebContents may have gone away.
TabSpecificContentSettings* content_settings =
......@@ -170,49 +93,7 @@ void ProtectedMediaIdentifierPermissionContext::NotifyPermissionSet(
id.render_view_id());
if (content_settings) {
content_settings->OnProtectedMediaIdentifierPermissionSet(
origin.GetOrigin(), allowed);
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::CancelPendingInfobarRequests(
int render_process_id,
int render_view_id,
const GURL& origin) {
if (!content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)) {
content::BrowserThread::PostTask(
content::BrowserThread::UI,
FROM_HERE,
base::Bind(&ProtectedMediaIdentifierPermissionContext::
CancelPendingInfobarRequests,
this,
render_process_id,
render_view_id,
origin));
return;
}
DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
if (shutting_down_)
return;
QueueController()->CancelInfoBarRequest(
PermissionRequestID(render_process_id, render_view_id, 0,
origin));
}
......@@ -5,12 +5,7 @@
#ifndef CHROME_BROWSER_MEDIA_PROTECTED_MEDIA_IDENTIFIER_PERMISSION_CONTEXT_H_
#define CHROME_BROWSER_MEDIA_PROTECTED_MEDIA_IDENTIFIER_PERMISSION_CONTEXT_H_
#include <map>
#include <string>
#include "base/callback_forward.h"
#include "base/memory/scoped_ptr.h"
#include "chrome/browser/content_settings/permission_queue_controller.h"
#include "chrome/browser/content_settings/permission_context_base.h"
class PermissionRequestID;
class Profile;
......@@ -23,76 +18,24 @@ class WebContents;
// Manages protected media identifier permissions flow, and delegates UI
// handling via PermissionQueueController.
class ProtectedMediaIdentifierPermissionContext
: public base::RefCountedThreadSafe<
ProtectedMediaIdentifierPermissionContext> {
: public PermissionContextBase {
public:
explicit ProtectedMediaIdentifierPermissionContext(Profile* profile);
void RequestProtectedMediaIdentifierPermission(
content::WebContents* web_contents,
const GURL& origin,
base::Callback<void(bool)> result_callback);
void CancelProtectedMediaIdentifierPermissionRequests(int render_process_id,
int render_view_id,
const GURL& origin);
// Called on the UI thread when the profile is about to be destroyed.
void ShutdownOnUIThread();
// In addition to the base class flow checks that it is only code from
// valid iframes. It also adds special logic when called through an extension.
void RequestPermission(content::WebContents* web_contents,
const PermissionRequestID& id,
const GURL& requesting_frame_origin,
bool user_gesture,
const BrowserPermissionCallback& callback) override;
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& origin,
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& origin,
const GURL& embedder,
content::RenderViewHost* rvh,
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& origin,
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 pending InfoBar requests that match |bridge_id| from the tab
// given by |render_process_id| and |render_view_id|.
void CancelPendingInfobarRequests(int render_process_id,
int render_view_id,
const GURL& origin);
~ProtectedMediaIdentifierPermissionContext() override;
// These must only be accessed from the UI thread.
Profile* const profile_;
bool shutting_down_;
scoped_ptr<PermissionQueueController> permission_queue_controller_;
void UpdateTabContext(const PermissionRequestID& id,
const GURL& requesting_frame,
bool allowed) override;
DISALLOW_COPY_AND_ASSIGN(ProtectedMediaIdentifierPermissionContext);
};
......
......@@ -9,39 +9,14 @@
#include "chrome/browser/profiles/profile.h"
#include "chrome/common/pref_names.h"
#include "components/keyed_service/content/browser_context_dependency_manager.h"
#include "components/keyed_service/core/keyed_service.h"
#include "components/pref_registry/pref_registry_syncable.h"
namespace {
class Service : public KeyedService {
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();
return static_cast<ProtectedMediaIdentifierPermissionContext*>(
GetInstance()->GetServiceForBrowserContext(profile, true));
}
// static
......@@ -65,7 +40,8 @@ ProtectedMediaIdentifierPermissionContextFactory::
KeyedService*
ProtectedMediaIdentifierPermissionContextFactory::BuildServiceInstanceFor(
content::BrowserContext* profile) const {
return new Service(static_cast<Profile*>(profile));
return new ProtectedMediaIdentifierPermissionContext(
static_cast<Profile*>(profile));
}
void
......
......@@ -52789,6 +52789,7 @@ To add a new entry, add it with any value and run test to compute valid value.
<int value="2" label="PERMISSION_PUSH_MESSAGING"/>
<int value="3" label="PERMISSION_NOTIFICATIONS"/>
<int value="4" label="PERMISSION_GEOLOCATION"/>
<int value="5" label="PERMISSION_PROTECTED_MEDIA"/>
</enum>
<enum name="PhotoEditorFileType" type="int">
......@@ -60613,6 +60614,7 @@ To add a new entry, add it with any value and run test to compute valid value.
<suffix name="PushMessaging" label="Push messaging permission actions"/>
<suffix name="Notifications" label="Notification permission actions"/>
<suffix name="Geolocation" label="Geolocation permission actions"/>
<suffix name="ProtectedMedia" label="Protected media permission actions"/>
<affected-histogram name="ContentSettings.PermissionActions"/>
<affected-histogram name="ContentSettings.PermissionActionsInsecureOrigin"/>
<affected-histogram name="ContentSettings.PermissionActionsSecureOrigin"/>
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment