Commit 16be5206 authored by timvolodine's avatar timvolodine Committed by Commit bot

Implement RevokePermission() method in PermissionService.

This patch implements RevokePermission() method in the mojo
PermissionService. This method will probably be for internal
use only for now. The semantics of the method is that it
will reset the permission to its default value in chrome if
the permission is currently granted.

BUG=430238

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

Cr-Commit-Position: refs/heads/master@{#314163}
parent b7c9d5e0
...@@ -620,6 +620,36 @@ ContentSettingToPermissionStatus(ContentSetting setting) { ...@@ -620,6 +620,36 @@ ContentSettingToPermissionStatus(ContentSetting setting) {
return content::PERMISSION_STATUS_DENIED; return content::PERMISSION_STATUS_DENIED;
} }
PermissionContextBase* GetPermissionContext(Profile* profile,
content::PermissionType permission) {
switch (permission) {
case content::PERMISSION_MIDI_SYSEX:
return MidiPermissionContextFactory::GetForProfile(profile);
case content::PERMISSION_NOTIFICATIONS:
#if defined(ENABLE_NOTIFICATIONS)
return DesktopNotificationServiceFactory::GetForProfile(profile);
#else
NOTIMPLEMENTED();
#endif
case content::PERMISSION_GEOLOCATION:
return GeolocationPermissionContextFactory::GetForProfile(profile);
case content::PERMISSION_PROTECTED_MEDIA_IDENTIFIER:
#if defined(OS_ANDROID)
return ProtectedMediaIdentifierPermissionContextFactory::GetForProfile(
profile);
#else
NOTIMPLEMENTED();
break;
#endif
case content::PERMISSION_PUSH_MESSAGING:
return gcm::PushMessagingPermissionContextFactory::GetForProfile(profile);
case content::PERMISSION_NUM:
NOTREACHED() << "Invalid RequestPermission for " << permission;
break;
}
return nullptr;
}
} // namespace } // namespace
namespace chrome { namespace chrome {
...@@ -1946,45 +1976,30 @@ content::PermissionStatus ChromeContentBrowserClient::GetPermissionStatus( ...@@ -1946,45 +1976,30 @@ content::PermissionStatus ChromeContentBrowserClient::GetPermissionStatus(
const GURL& embedding_origin) { const GURL& embedding_origin) {
DCHECK(browser_context); DCHECK(browser_context);
Profile* profile = Profile::FromBrowserContext(browser_context); Profile* profile = Profile::FromBrowserContext(browser_context);
PermissionContextBase* context = GetPermissionContext(profile, permission);
PermissionContextBase* context = nullptr; if (!context)
switch (permission) { return content::PERMISSION_STATUS_ASK;
case content::PERMISSION_MIDI_SYSEX:
context = MidiPermissionContextFactory::GetForProfile(profile); return ContentSettingToPermissionStatus(
break; context->GetPermissionStatus(requesting_origin.GetOrigin(),
case content::PERMISSION_NOTIFICATIONS: embedding_origin.GetOrigin()));
#if defined(ENABLE_NOTIFICATIONS) }
context = DesktopNotificationServiceFactory::GetForProfile(profile);
#else void ChromeContentBrowserClient::ResetPermission(
NOTIMPLEMENTED(); content::PermissionType permission,
#endif content::BrowserContext* browser_context,
break; const GURL& requesting_origin,
case content::PERMISSION_GEOLOCATION: const GURL& embedding_origin) {
context = GeolocationPermissionContextFactory::GetForProfile(profile); DCHECK(browser_context);
break; Profile* profile = Profile::FromBrowserContext(browser_context);
case content::PERMISSION_PROTECTED_MEDIA_IDENTIFIER: PermissionContextBase* context = GetPermissionContext(profile, permission);
#if defined(OS_ANDROID)
context = ProtectedMediaIdentifierPermissionContextFactory::GetForProfile(
profile);
#else
NOTIMPLEMENTED();
#endif
break;
case content::PERMISSION_PUSH_MESSAGING:
context = gcm::PushMessagingPermissionContextFactory::GetForProfile(
profile);
break;
case content::PERMISSION_NUM:
NOTREACHED() << "Invalid RequestPermission for " << permission;
break;
}
ContentSetting result = context if (!context)
? context->GetPermissionStatus(requesting_origin.GetOrigin(), return;
embedding_origin.GetOrigin())
: CONTENT_SETTING_DEFAULT;
return ContentSettingToPermissionStatus(result); context->ResetPermission(requesting_origin.GetOrigin(),
embedding_origin.GetOrigin());
} }
void ChromeContentBrowserClient::CancelPermissionRequest( void ChromeContentBrowserClient::CancelPermissionRequest(
......
...@@ -194,6 +194,11 @@ class ChromeContentBrowserClient : public content::ContentBrowserClient { ...@@ -194,6 +194,11 @@ class ChromeContentBrowserClient : public content::ContentBrowserClient {
content::BrowserContext* browser_context, content::BrowserContext* browser_context,
const GURL& requesting_origin, const GURL& requesting_origin,
const GURL& embedding_origin) override; const GURL& embedding_origin) override;
void ResetPermission(
content::PermissionType permission,
content::BrowserContext* browser_context,
const GURL& requesting_origin,
const GURL& embedding_origin) override;
void CancelPermissionRequest(content::PermissionType permission, void CancelPermissionRequest(content::PermissionType permission,
content::WebContents* web_contents, content::WebContents* web_contents,
int bridge_id, int bridge_id,
......
...@@ -55,6 +55,15 @@ ContentSetting PermissionContextBase::GetPermissionStatus( ...@@ -55,6 +55,15 @@ ContentSetting PermissionContextBase::GetPermissionStatus(
requesting_origin, embedding_origin, permission_type_, std::string()); requesting_origin, embedding_origin, permission_type_, std::string());
} }
void PermissionContextBase::ResetPermission(
const GURL& requesting_origin,
const GURL& embedding_origin) {
profile_->GetHostContentSettingsMap()->SetContentSetting(
ContentSettingsPattern::FromURLNoWildcard(requesting_origin),
ContentSettingsPattern::FromURLNoWildcard(embedding_origin),
permission_type_, std::string(), CONTENT_SETTING_DEFAULT);
}
void PermissionContextBase::CancelPermissionRequest( void PermissionContextBase::CancelPermissionRequest(
content::WebContents* web_contents, content::WebContents* web_contents,
const PermissionRequestID& id) { const PermissionRequestID& id) {
......
...@@ -69,6 +69,10 @@ class PermissionContextBase : public KeyedService { ...@@ -69,6 +69,10 @@ class PermissionContextBase : public KeyedService {
const GURL& requesting_origin, const GURL& requesting_origin,
const GURL& embedding_origin) const; const GURL& embedding_origin) const;
// Resets the permission to its default value.
virtual void ResetPermission(const GURL& requesting_origin,
const GURL& embedding_origin);
// Withdraw an existing permission request, no op if the permission request // Withdraw an existing permission request, no op if the permission request
// was already cancelled by some other means. // was already cancelled by some other means.
virtual void CancelPermissionRequest(content::WebContents* web_contents, virtual void CancelPermissionRequest(content::WebContents* web_contents,
......
...@@ -121,7 +121,7 @@ class PermissionContextBaseTests : public ChromeRenderViewHostTestHarness { ...@@ -121,7 +121,7 @@ class PermissionContextBaseTests : public ChromeRenderViewHostTestHarness {
profile()->GetHostContentSettingsMap()->GetContentSetting( profile()->GetHostContentSettingsMap()->GetContentSetting(
url.GetOrigin(), url.GetOrigin(), url.GetOrigin(), url.GetOrigin(),
CONTENT_SETTINGS_TYPE_NOTIFICATIONS, std::string()); CONTENT_SETTINGS_TYPE_NOTIFICATIONS, std::string());
EXPECT_EQ(CONTENT_SETTING_ALLOW , setting); EXPECT_EQ(CONTENT_SETTING_ALLOW, setting);
} }
void TestAskAndDismiss_TestContent() { void TestAskAndDismiss_TestContent() {
...@@ -149,7 +149,7 @@ class PermissionContextBaseTests : public ChromeRenderViewHostTestHarness { ...@@ -149,7 +149,7 @@ class PermissionContextBaseTests : public ChromeRenderViewHostTestHarness {
profile()->GetHostContentSettingsMap()->GetContentSetting( profile()->GetHostContentSettingsMap()->GetContentSetting(
url.GetOrigin(), url.GetOrigin(), url.GetOrigin(), url.GetOrigin(),
CONTENT_SETTINGS_TYPE_MIDI_SYSEX, std::string()); CONTENT_SETTINGS_TYPE_MIDI_SYSEX, std::string());
EXPECT_EQ(CONTENT_SETTING_ASK , setting); EXPECT_EQ(CONTENT_SETTING_ASK, setting);
} }
void TestRequestPermissionInvalidUrl(ContentSettingsType type) { void TestRequestPermissionInvalidUrl(ContentSettingsType type) {
...@@ -178,6 +178,45 @@ class PermissionContextBaseTests : public ChromeRenderViewHostTestHarness { ...@@ -178,6 +178,45 @@ class PermissionContextBaseTests : public ChromeRenderViewHostTestHarness {
EXPECT_EQ(CONTENT_SETTING_ASK, setting); EXPECT_EQ(CONTENT_SETTING_ASK, setting);
} }
void TestGrantAndRevoke_TestContent(ContentSettingsType type,
ContentSetting expected_default) {
TestPermissionContext permission_context(profile(), type);
GURL url("http://www.google.com");
content::WebContentsTester::For(web_contents())->NavigateAndCommit(url);
const PermissionRequestID id(
web_contents()->GetRenderProcessHost()->GetID(),
web_contents()->GetRenderViewHost()->GetRoutingID(),
-1, GURL());
permission_context.RequestPermission(
web_contents(),
id, url, true,
base::Bind(&TestPermissionContext::TrackPermissionDecision,
base::Unretained(&permission_context)));
RespondToPermission(&permission_context, id, url, true);
EXPECT_TRUE(permission_context.permission_set());
EXPECT_TRUE(permission_context.permission_granted());
EXPECT_TRUE(permission_context.tab_context_updated());
ContentSetting setting =
profile()->GetHostContentSettingsMap()->GetContentSetting(
url.GetOrigin(), url.GetOrigin(),
type, std::string());
EXPECT_EQ(CONTENT_SETTING_ALLOW, setting);
// Try to reset permission.
permission_context.ResetPermission(url.GetOrigin(), url.GetOrigin());
ContentSetting setting_after_reset =
profile()->GetHostContentSettingsMap()->GetContentSetting(
url.GetOrigin(), url.GetOrigin(),
type, std::string());
ContentSetting default_setting =
profile()->GetHostContentSettingsMap()->GetDefaultContentSetting(
type, nullptr);
EXPECT_EQ(default_setting, setting_after_reset);
}
private: private:
// ChromeRenderViewHostTestHarness: // ChromeRenderViewHostTestHarness:
void SetUp() override { void SetUp() override {
...@@ -217,3 +256,40 @@ TEST_F(PermissionContextBaseTests, TestNonValidRequestingUrl) { ...@@ -217,3 +256,40 @@ TEST_F(PermissionContextBaseTests, TestNonValidRequestingUrl) {
CONTENT_SETTINGS_TYPE_PROTECTED_MEDIA_IDENTIFIER); CONTENT_SETTINGS_TYPE_PROTECTED_MEDIA_IDENTIFIER);
#endif #endif
} }
// Simulates granting and revoking of permissions.
TEST_F(PermissionContextBaseTests, TestGrantAndRevoke) {
TestGrantAndRevoke_TestContent(CONTENT_SETTINGS_TYPE_GEOLOCATION,
CONTENT_SETTING_ASK);
TestGrantAndRevoke_TestContent(CONTENT_SETTINGS_TYPE_MIDI_SYSEX,
CONTENT_SETTING_ASK);
#if defined(OS_ANDROID)
TestGrantAndRevoke_TestContent(
CONTENT_SETTINGS_TYPE_PROTECTED_MEDIA_IDENTIFIER, CONTENT_SETTING_ASK);
#endif
// TODO(timvolodine): currently no test for
// CONTENT_SETTINGS_TYPE_NOTIFICATIONS because notification permissions work
// differently with infobars as compared to bubbles (crbug.com/453784).
// TODO(timvolodine): currently no test for
// CONTENT_SETTINGS_TYPE_PUSH_MESSAGING because infobars do not implement push
// messaging permissions (crbug.com/453788).
}
// Simulates granting and revoking of permissions using permission bubbles.
TEST_F(PermissionContextBaseTests, TestGrantAndRevokeWithBubbles) {
StartUsingPermissionBubble();
TestGrantAndRevoke_TestContent(CONTENT_SETTINGS_TYPE_GEOLOCATION,
CONTENT_SETTING_ASK);
#if defined(ENABLE_NOTIFICATIONS)
TestGrantAndRevoke_TestContent(CONTENT_SETTINGS_TYPE_NOTIFICATIONS,
CONTENT_SETTING_ASK);
#endif
TestGrantAndRevoke_TestContent(CONTENT_SETTINGS_TYPE_MIDI_SYSEX,
CONTENT_SETTING_ASK);
TestGrantAndRevoke_TestContent(CONTENT_SETTINGS_TYPE_PUSH_MESSAGING,
CONTENT_SETTING_ASK);
#if defined(OS_ANDROID)
TestGrantAndRevoke_TestContent(
CONTENT_SETTINGS_TYPE_PROTECTED_MEDIA_IDENTIFIER, CONTENT_SETTING_ASK);
#endif
}
...@@ -114,14 +114,42 @@ void PermissionServiceImpl::HasPermission( ...@@ -114,14 +114,42 @@ void PermissionServiceImpl::HasPermission(
const mojo::Callback<void(PermissionStatus)>& callback) { const mojo::Callback<void(PermissionStatus)>& callback) {
DCHECK(context_->GetBrowserContext()); DCHECK(context_->GetBrowserContext());
callback.Run(GetPermissionStatus(PermissionNameToPermissionType(permission),
GURL(origin)));
}
void PermissionServiceImpl::RevokePermission(
PermissionName permission,
const mojo::String& origin,
const mojo::Callback<void(PermissionStatus)>& callback) {
GURL origin_url(origin);
PermissionType permission_type = PermissionNameToPermissionType(permission);
PermissionStatus status = GetPermissionStatus(permission_type, origin_url);
if (status != PERMISSION_STATUS_GRANTED)
callback.Run(status);
ResetPermissionStatus(permission_type, origin_url);
callback.Run(GetPermissionStatus(permission_type, origin_url));
}
PermissionStatus PermissionServiceImpl::GetPermissionStatus(PermissionType type,
GURL origin) {
// If the embedding_origin is empty we'll use |origin| instead. // If the embedding_origin is empty we'll use |origin| instead.
GURL embedding_origin = context_->GetEmbeddingOrigin(); GURL embedding_origin = context_->GetEmbeddingOrigin();
return GetContentClient()->browser()->GetPermissionStatus(
type, context_->GetBrowserContext(), origin,
embedding_origin.is_empty() ? origin : embedding_origin);
}
callback.Run(GetContentClient()->browser()->GetPermissionStatus( void PermissionServiceImpl::ResetPermissionStatus(PermissionType type,
PermissionNameToPermissionType(permission), GURL origin) {
context_->GetBrowserContext(), // If the embedding_origin is empty we'll use |origin| instead.
GURL(origin), GURL embedding_origin = context_->GetEmbeddingOrigin();
embedding_origin.is_empty() ? GURL(origin) : embedding_origin)); GetContentClient()->browser()->ResetPermission(
type, context_->GetBrowserContext(), origin,
embedding_origin.is_empty() ? origin : embedding_origin);
} }
} // namespace content } // namespace content
...@@ -52,6 +52,10 @@ class PermissionServiceImpl : public mojo::InterfaceImpl<PermissionService> { ...@@ -52,6 +52,10 @@ class PermissionServiceImpl : public mojo::InterfaceImpl<PermissionService> {
const mojo::String& origin, const mojo::String& origin,
bool user_gesture, bool user_gesture,
const mojo::Callback<void(PermissionStatus)>& callback) override; const mojo::Callback<void(PermissionStatus)>& callback) override;
void RevokePermission(
PermissionName permission,
const mojo::String& origin,
const mojo::Callback<void(PermissionStatus)>& callback) override;
// mojo::InterfaceImpl. // mojo::InterfaceImpl.
void OnConnectionError() override; void OnConnectionError() override;
...@@ -61,6 +65,9 @@ class PermissionServiceImpl : public mojo::InterfaceImpl<PermissionService> { ...@@ -61,6 +65,9 @@ class PermissionServiceImpl : public mojo::InterfaceImpl<PermissionService> {
int request_id, int request_id,
bool allowed); bool allowed);
PermissionStatus GetPermissionStatus(PermissionType type, GURL origin);
void ResetPermissionStatus(PermissionType type, GURL origin);
RequestsMap pending_requests_; RequestsMap pending_requests_;
// context_ owns |this|. // context_ owns |this|.
PermissionServiceContext* context_; PermissionServiceContext* context_;
......
...@@ -21,4 +21,6 @@ interface PermissionService { ...@@ -21,4 +21,6 @@ interface PermissionService {
=> (PermissionStatus status); => (PermissionStatus status);
RequestPermission(PermissionName permission, string origin, bool user_gesture) RequestPermission(PermissionName permission, string origin, bool user_gesture)
=> (PermissionStatus status); => (PermissionStatus status);
RevokePermission(PermissionName permission, string origin)
=> (PermissionStatus status);
}; };
...@@ -450,6 +450,11 @@ class CONTENT_EXPORT ContentBrowserClient { ...@@ -450,6 +450,11 @@ class CONTENT_EXPORT ContentBrowserClient {
const GURL& requesting_origin, const GURL& requesting_origin,
const GURL& embedding_origin); const GURL& embedding_origin);
virtual void ResetPermission(PermissionType permission,
BrowserContext* browser_context,
const GURL& requesting_origin,
const GURL& embedding_origin) {}
// Returns true if the given page is allowed to open a window of the given // Returns true if the given page is allowed to open a window of the given
// type. If true is returned, |no_javascript_access| will indicate whether // type. If true is returned, |no_javascript_access| will indicate whether
// the window that is created should be scriptable/in the same process. // the window that is created should be scriptable/in the same process.
......
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