Added metrics to help with one time permissions on desktop
Add metrics that will record - Elapsed time between grant and permission use - Elapsed time between grant and revoke Only for Geolocation, mic and camera permission Bug: 1119738 Change-Id: Ia01cee7921b246844e90d789761f3beebebb98de Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2367832 Commit-Queue: Ravjit Singh Uppal <ravjit@chromium.org> Reviewed-by: Balazs Engedy <engedy@chromium.org> Reviewed-by: Colin Blundell <blundell@chromium.org> Reviewed-by: Jesse Doherty <jwd@chromium.org> Cr-Commit-Position: refs/heads/master@{#810544}
This commit is contained in:

committed by
Commit Bot

parent
abbf0250d3
commit
884cd3901f
chrome
browser
content_settings
test
components
content_settings
browser
permissions
tools/metrics/histograms
weblayer/browser
@ -19,6 +19,7 @@
|
||||
#include "chrome/common/renderer_configuration.mojom.h"
|
||||
#include "components/content_settings/browser/page_specific_content_settings.h"
|
||||
#include "components/permissions/permission_decision_auto_blocker.h"
|
||||
#include "components/permissions/permission_uma_util.h"
|
||||
#include "components/prefs/pref_service.h"
|
||||
#include "content/public/browser/navigation_handle.h"
|
||||
#include "content/public/browser/render_process_host.h"
|
||||
@ -159,6 +160,25 @@ PageSpecificContentSettingsDelegate::GetMicrophoneCameraState() {
|
||||
return state;
|
||||
}
|
||||
|
||||
void PageSpecificContentSettingsDelegate::OnContentAllowed(
|
||||
ContentSettingsType type) {
|
||||
if (!(type == ContentSettingsType::GEOLOCATION ||
|
||||
type == ContentSettingsType::MEDIASTREAM_CAMERA ||
|
||||
type == ContentSettingsType::MEDIASTREAM_MIC)) {
|
||||
return;
|
||||
}
|
||||
content_settings::SettingInfo setting_info;
|
||||
GetSettingsMap()->GetWebsiteSetting(web_contents()->GetLastCommittedURL(),
|
||||
web_contents()->GetLastCommittedURL(),
|
||||
type, std::string(), &setting_info);
|
||||
const base::Time grant_time = GetSettingsMap()->GetSettingLastModifiedDate(
|
||||
setting_info.primary_pattern, setting_info.secondary_pattern, type);
|
||||
if (grant_time.is_null())
|
||||
return;
|
||||
permissions::PermissionUmaUtil::RecordTimeElapsedBetweenGrantAndUse(
|
||||
type, base::Time::Now() - grant_time);
|
||||
}
|
||||
|
||||
void PageSpecificContentSettingsDelegate::OnContentBlocked(
|
||||
ContentSettingsType type) {
|
||||
if (type == ContentSettingsType::PLUGINS) {
|
||||
|
@ -78,6 +78,7 @@ class PageSpecificContentSettingsDelegate
|
||||
const std::string& media_stream_selected_video_device) override;
|
||||
content_settings::PageSpecificContentSettings::MicrophoneCameraState
|
||||
GetMicrophoneCameraState() override;
|
||||
void OnContentAllowed(ContentSettingsType type) override;
|
||||
void OnContentBlocked(ContentSettingsType type) override;
|
||||
void OnCacheStorageAccessAllowed(const url::Origin& origin) override;
|
||||
void OnCookieAccessAllowed(const net::CookieList& accessed_cookies) override;
|
||||
|
@ -0,0 +1,95 @@
|
||||
// Copyright 2020 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 "components/content_settings/browser/page_specific_content_settings.h"
|
||||
|
||||
#include "chrome/browser/content_settings/host_content_settings_map_factory.h"
|
||||
#include "chrome/browser/content_settings/page_specific_content_settings_delegate.h"
|
||||
#include "chrome/test/base/chrome_render_view_host_test_harness.h"
|
||||
#include "testing/gmock/include/gmock/gmock-matchers.h"
|
||||
|
||||
namespace content_settings {
|
||||
|
||||
class PageSpecificContentSettingsTest : public ChromeRenderViewHostTestHarness {
|
||||
public:
|
||||
PageSpecificContentSettingsTest()
|
||||
: ChromeRenderViewHostTestHarness(
|
||||
base::test::TaskEnvironment::TimeSource::MOCK_TIME) {}
|
||||
|
||||
void SetUp() override {
|
||||
ChromeRenderViewHostTestHarness::SetUp();
|
||||
PageSpecificContentSettings::CreateForWebContents(
|
||||
web_contents(),
|
||||
std::make_unique<chrome::PageSpecificContentSettingsDelegate>(
|
||||
web_contents()));
|
||||
}
|
||||
};
|
||||
|
||||
TEST_F(PageSpecificContentSettingsTest, HistogramTest) {
|
||||
base::HistogramTester histograms;
|
||||
const GURL test_url("https://test.com/");
|
||||
const char kGeolocationHistogramName[] =
|
||||
"Permissions.Usage.ElapsedTimeSinceGrant.Geolocation";
|
||||
const char kMicrophoneHistogramName[] =
|
||||
"Permissions.Usage.ElapsedTimeSinceGrant.AudioCapture";
|
||||
const char kCameraHistogramName[] =
|
||||
"Permissions.Usage.ElapsedTimeSinceGrant.VideoCapture";
|
||||
NavigateAndCommit(test_url);
|
||||
HostContentSettingsMap* map =
|
||||
HostContentSettingsMapFactory::GetForProfile(profile());
|
||||
map->SetContentSettingDefaultScope(
|
||||
test_url, test_url, ContentSettingsType::GEOLOCATION, std::string(),
|
||||
ContentSetting::CONTENT_SETTING_ALLOW);
|
||||
map->SetContentSettingDefaultScope(
|
||||
test_url, test_url, ContentSettingsType::MEDIASTREAM_MIC, std::string(),
|
||||
ContentSetting::CONTENT_SETTING_ALLOW);
|
||||
map->SetContentSettingDefaultScope(
|
||||
test_url, test_url, ContentSettingsType::MEDIASTREAM_CAMERA,
|
||||
std::string(), ContentSetting::CONTENT_SETTING_ALLOW);
|
||||
|
||||
task_environment()->FastForwardBy(base::TimeDelta::FromSeconds(1));
|
||||
PageSpecificContentSettings* content_settings =
|
||||
PageSpecificContentSettings::GetForFrame(web_contents()->GetMainFrame());
|
||||
|
||||
histograms.ExpectTotalCount(kGeolocationHistogramName, 0);
|
||||
content_settings->OnContentAllowed(ContentSettingsType::GEOLOCATION);
|
||||
histograms.ExpectTotalCount(kGeolocationHistogramName, 1);
|
||||
EXPECT_THAT(histograms.GetAllSamples(kGeolocationHistogramName),
|
||||
testing::ElementsAre(base::Bucket(1, 1)));
|
||||
content_settings->OnContentAllowed(ContentSettingsType::GEOLOCATION);
|
||||
// Count should stay same even after multiple usage of permission
|
||||
histograms.ExpectTotalCount(kGeolocationHistogramName, 1);
|
||||
|
||||
PageSpecificContentSettings::MicrophoneCameraState microphone_accessed =
|
||||
PageSpecificContentSettings::MICROPHONE_ACCESSED |
|
||||
PageSpecificContentSettings::CAMERA_ACCESSED |
|
||||
PageSpecificContentSettings::CAMERA_BLOCKED;
|
||||
|
||||
histograms.ExpectTotalCount(kMicrophoneHistogramName, 0);
|
||||
content_settings->OnMediaStreamPermissionSet(test_url, microphone_accessed,
|
||||
std::string(), std::string(),
|
||||
std::string(), std::string());
|
||||
histograms.ExpectTotalCount(kMicrophoneHistogramName, 1);
|
||||
EXPECT_THAT(histograms.GetAllSamples(kMicrophoneHistogramName),
|
||||
testing::ElementsAre(base::Bucket(1, 1)));
|
||||
const PageSpecificContentSettings::MicrophoneCameraState mic_camera_accessed =
|
||||
PageSpecificContentSettings::MICROPHONE_ACCESSED |
|
||||
PageSpecificContentSettings::CAMERA_ACCESSED;
|
||||
|
||||
histograms.ExpectTotalCount(kCameraHistogramName, 0);
|
||||
content_settings->OnMediaStreamPermissionSet(test_url, mic_camera_accessed,
|
||||
std::string(), std::string(),
|
||||
std::string(), std::string());
|
||||
histograms.ExpectTotalCount(kCameraHistogramName, 1);
|
||||
EXPECT_THAT(histograms.GetAllSamples(kCameraHistogramName),
|
||||
testing::ElementsAre(base::Bucket(1, 1)));
|
||||
content_settings->OnMediaStreamPermissionSet(test_url, mic_camera_accessed,
|
||||
std::string(), std::string(),
|
||||
std::string(), std::string());
|
||||
// Count should stay same even after multiple usage of permission
|
||||
histograms.ExpectTotalCount(kMicrophoneHistogramName, 1);
|
||||
histograms.ExpectTotalCount(kCameraHistogramName, 1);
|
||||
}
|
||||
|
||||
} // namespace content_settings
|
@ -3358,6 +3358,7 @@ test("unit_tests") {
|
||||
"../browser/content_settings/host_content_settings_map_unittest.cc",
|
||||
"../browser/content_settings/mock_settings_observer.cc",
|
||||
"../browser/content_settings/mock_settings_observer.h",
|
||||
"../browser/content_settings/page_specific_content_settings_unittest.cc",
|
||||
"../browser/content_settings/sound_content_setting_observer_unittest.cc",
|
||||
"../browser/custom_handlers/protocol_handler_registry_unittest.cc",
|
||||
"../browser/custom_handlers/test_protocol_handler_registry_delegate.cc",
|
||||
|
@ -574,10 +574,10 @@ void PageSpecificContentSettings::OnContentAllowed(ContentSettingsType type) {
|
||||
status.blocked = false;
|
||||
access_changed = true;
|
||||
}
|
||||
|
||||
if (!status.allowed) {
|
||||
status.allowed = true;
|
||||
access_changed = true;
|
||||
delegate_->OnContentAllowed(ContentSettingsType::GEOLOCATION);
|
||||
}
|
||||
|
||||
if (access_changed)
|
||||
@ -775,6 +775,8 @@ void PageSpecificContentSettings::OnMediaStreamPermissionSet(
|
||||
bool mic_blocked = (new_microphone_camera_state & MICROPHONE_BLOCKED) != 0;
|
||||
ContentSettingsStatus& status =
|
||||
content_settings_status_[ContentSettingsType::MEDIASTREAM_MIC];
|
||||
if (!status.allowed && !mic_blocked)
|
||||
delegate_->OnContentAllowed(ContentSettingsType::MEDIASTREAM_MIC);
|
||||
status.allowed = !mic_blocked;
|
||||
status.blocked = mic_blocked;
|
||||
}
|
||||
@ -785,6 +787,8 @@ void PageSpecificContentSettings::OnMediaStreamPermissionSet(
|
||||
bool cam_blocked = (new_microphone_camera_state & CAMERA_BLOCKED) != 0;
|
||||
ContentSettingsStatus& status =
|
||||
content_settings_status_[ContentSettingsType::MEDIASTREAM_CAMERA];
|
||||
if (!status.allowed && !cam_blocked)
|
||||
delegate_->OnContentAllowed(ContentSettingsType::MEDIASTREAM_CAMERA);
|
||||
status.allowed = !cam_blocked;
|
||||
status.blocked = cam_blocked;
|
||||
}
|
||||
|
@ -124,6 +124,10 @@ class PageSpecificContentSettings
|
||||
// media stream request.
|
||||
virtual MicrophoneCameraState GetMicrophoneCameraState() = 0;
|
||||
|
||||
// Notifies the delegate a particular content settings type was allowed for
|
||||
// the first time on this page.
|
||||
virtual void OnContentAllowed(ContentSettingsType type) = 0;
|
||||
|
||||
// Notifies the delegate a particular content settings type was blocked.
|
||||
virtual void OnContentBlocked(ContentSettingsType type) = 0;
|
||||
|
||||
|
@ -58,6 +58,9 @@ TestPageSpecificContentSettingsDelegate::GetMicrophoneCameraState() {
|
||||
return PageSpecificContentSettings::MICROPHONE_CAMERA_NOT_ACCESSED;
|
||||
}
|
||||
|
||||
void TestPageSpecificContentSettingsDelegate::OnContentAllowed(
|
||||
ContentSettingsType type) {}
|
||||
|
||||
void TestPageSpecificContentSettingsDelegate::OnContentBlocked(
|
||||
ContentSettingsType type) {}
|
||||
|
||||
|
@ -36,6 +36,7 @@ class TestPageSpecificContentSettingsDelegate
|
||||
const std::string& media_stream_selected_video_device) override;
|
||||
PageSpecificContentSettings::MicrophoneCameraState GetMicrophoneCameraState()
|
||||
override;
|
||||
void OnContentAllowed(ContentSettingsType type) override;
|
||||
void OnContentBlocked(ContentSettingsType type) override;
|
||||
void OnCacheStorageAccessAllowed(const url::Origin& origin) override;
|
||||
void OnCookieAccessAllowed(const net::CookieList& accessed_cookies) override;
|
||||
|
@ -444,6 +444,12 @@ PermissionUmaUtil::ScopedRevocationReporter::ScopedRevocationReporter(
|
||||
ContentSetting initial_content_setting = settings_map->GetContentSetting(
|
||||
primary_url_, secondary_url_, content_type_, std::string());
|
||||
is_initially_allowed_ = initial_content_setting == CONTENT_SETTING_ALLOW;
|
||||
content_settings::SettingInfo setting_info;
|
||||
settings_map->GetWebsiteSetting(primary_url, secondary_url, content_type_,
|
||||
std::string(), &setting_info);
|
||||
last_modified_date_ = settings_map->GetSettingLastModifiedDate(
|
||||
setting_info.primary_pattern, setting_info.secondary_pattern,
|
||||
content_type);
|
||||
}
|
||||
|
||||
PermissionUmaUtil::ScopedRevocationReporter::ScopedRevocationReporter(
|
||||
@ -473,6 +479,13 @@ PermissionUmaUtil::ScopedRevocationReporter::~ScopedRevocationReporter() {
|
||||
GURL requesting_origin = primary_url_.GetOrigin();
|
||||
PermissionRevoked(content_type_, source_ui_, requesting_origin,
|
||||
browser_context_);
|
||||
if ((content_type_ == ContentSettingsType::GEOLOCATION ||
|
||||
content_type_ == ContentSettingsType::MEDIASTREAM_CAMERA ||
|
||||
content_type_ == ContentSettingsType::MEDIASTREAM_MIC) &&
|
||||
!last_modified_date_.is_null()) {
|
||||
RecordTimeElapsedBetweenGrantAndRevoke(
|
||||
content_type_, base::Time::Now() - last_modified_date_);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -608,4 +621,22 @@ void PermissionUmaUtil::RecordPromptDecided(
|
||||
}
|
||||
}
|
||||
|
||||
void PermissionUmaUtil::RecordTimeElapsedBetweenGrantAndUse(
|
||||
ContentSettingsType type,
|
||||
base::TimeDelta delta) {
|
||||
base::UmaHistogramCustomCounts(
|
||||
"Permissions.Usage.ElapsedTimeSinceGrant." +
|
||||
PermissionUtil::GetPermissionString(type),
|
||||
delta.InSeconds(), 1, base::TimeDelta::FromDays(365).InSeconds(), 100);
|
||||
}
|
||||
|
||||
void PermissionUmaUtil::RecordTimeElapsedBetweenGrantAndRevoke(
|
||||
ContentSettingsType type,
|
||||
base::TimeDelta delta) {
|
||||
base::UmaHistogramCustomCounts(
|
||||
"Permissions.Revocation.ElapsedTimeSinceGrant." +
|
||||
PermissionUtil::GetPermissionString(type),
|
||||
delta.InSeconds(), 1, base::TimeDelta::FromDays(365).InSeconds(), 100);
|
||||
}
|
||||
|
||||
} // namespace permissions
|
||||
|
@ -161,6 +161,12 @@ class PermissionUmaUtil {
|
||||
PermissionAction action,
|
||||
const std::vector<ContentSettingsType>& content_settings_types);
|
||||
|
||||
static void RecordTimeElapsedBetweenGrantAndUse(ContentSettingsType type,
|
||||
base::TimeDelta delta);
|
||||
|
||||
static void RecordTimeElapsedBetweenGrantAndRevoke(ContentSettingsType type,
|
||||
base::TimeDelta delta);
|
||||
|
||||
// A scoped class that will check the current resolved content setting on
|
||||
// construction and report a revocation metric accordingly if the revocation
|
||||
// condition is met (from ALLOW to something else).
|
||||
@ -187,6 +193,7 @@ class PermissionUmaUtil {
|
||||
ContentSettingsType content_type_;
|
||||
PermissionSourceUI source_ui_;
|
||||
bool is_initially_allowed_;
|
||||
base::Time last_modified_date_;
|
||||
};
|
||||
|
||||
private:
|
||||
|
@ -130036,6 +130036,16 @@ reviews. Googlers can read more about this at go/gwsq-gerrit.
|
||||
</summary>
|
||||
</histogram>
|
||||
|
||||
<histogram base="true" name="Permissions.Revocation.ElapsedTimeSinceGrant"
|
||||
units="seconds" expires_after="2021-08-20">
|
||||
<owner>engedy@chromium.org</owner>
|
||||
<owner>src/components/permissions/PERMISSIONS_OWNERS</owner>
|
||||
<summary>
|
||||
Records the time elapsed since the grant of the permission until it's
|
||||
revoked.
|
||||
</summary>
|
||||
</histogram>
|
||||
|
||||
<histogram name="Permissions.Serial.ChooserClosed" enum="SerialChooserOutcome"
|
||||
expires_after="2021-06-21">
|
||||
<owner>reillyg@chromium.org</owner>
|
||||
@ -130053,6 +130063,17 @@ reviews. Googlers can read more about this at go/gwsq-gerrit.
|
||||
<summary>Records when permission to access a serial port is revoked.</summary>
|
||||
</histogram>
|
||||
|
||||
<histogram base="true" name="Permissions.Usage.ElapsedTimeSinceGrant"
|
||||
units="seconds" expires_after="2021-08-20">
|
||||
<owner>engedy@chromium.org</owner>
|
||||
<owner>src/components/permissions/PERMISSIONS_OWNERS</owner>
|
||||
<summary>
|
||||
Records the time elapsed since the grant of the permission until it's latest
|
||||
usage. This histogram will be recorded only for the first usage of a given
|
||||
permission after the site has loaded.
|
||||
</summary>
|
||||
</histogram>
|
||||
|
||||
<histogram base="true" name="PhoneHub.MultiDeviceFeatureState"
|
||||
enum="MultiDevice_FeatureState" expires_after="2021-08-01">
|
||||
<!-- Name completed by histogram_suffixes name="PhoneHubFeature" -->
|
||||
@ -211568,6 +211589,8 @@ regressions. -->
|
||||
<affected-histogram name="Permissions.Prompt.Ignored.PriorIgnoreCount"/>
|
||||
<affected-histogram name="Permissions.Prompt.Ignored.PriorIgnoreCount2"/>
|
||||
<affected-histogram name="Permissions.Requested.CrossOrigin"/>
|
||||
<affected-histogram name="Permissions.Revocation.ElapsedTimeSinceGrant"/>
|
||||
<affected-histogram name="Permissions.Usage.ElapsedTimeSinceGrant"/>
|
||||
</histogram_suffixes>
|
||||
|
||||
<histogram_suffixes name="PhoneHubFeature" separator=".">
|
||||
|
@ -94,6 +94,9 @@ PageSpecificContentSettingsDelegate::GetMicrophoneCameraState() {
|
||||
MICROPHONE_CAMERA_NOT_ACCESSED;
|
||||
}
|
||||
|
||||
void PageSpecificContentSettingsDelegate::OnContentAllowed(
|
||||
ContentSettingsType type) {}
|
||||
|
||||
void PageSpecificContentSettingsDelegate::OnContentBlocked(
|
||||
ContentSettingsType type) {}
|
||||
|
||||
|
@ -44,6 +44,7 @@ class PageSpecificContentSettingsDelegate
|
||||
const std::string& media_stream_selected_video_device) override;
|
||||
content_settings::PageSpecificContentSettings::MicrophoneCameraState
|
||||
GetMicrophoneCameraState() override;
|
||||
void OnContentAllowed(ContentSettingsType type) override;
|
||||
void OnContentBlocked(ContentSettingsType type) override;
|
||||
void OnCacheStorageAccessAllowed(const url::Origin& origin) override;
|
||||
void OnCookieAccessAllowed(const net::CookieList& accessed_cookies) override;
|
||||
|
Reference in New Issue
Block a user