0

[AW] Record app data dir size in UMA.

Also fix the spelling of OffsetParentNewSpecBehavior as it's breaking a presubmit check.

Test: unit test, manual test (https://photos.app.goo.gl/R344qyHJsEha6onU9)
Bug: 1184061
Change-Id: I0c0b3d380e17d689479557598d4c753fca8d6518
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/3671315
Commit-Queue: Qi Xiao <xiaq@chromium.org>
Reviewed-by: Nate Fischer <ntfschr@chromium.org>
Reviewed-by: Andrey Zaytsev <andzaytsev@google.com>
Cr-Commit-Position: refs/heads/main@{#1012565}
This commit is contained in:
Qi Xiao
2022-06-09 17:09:27 +00:00
committed by Chromium LUCI CQ
parent d297b4e451
commit 15a03a95b4
9 changed files with 174 additions and 7 deletions
android_webview
components/embedder_support/android/metrics
tools/metrics/histograms

@ -13,10 +13,16 @@
#include "base/android/callback_android.h"
#include "base/android/jni_android.h"
#include "base/android/jni_string.h"
#include "base/base_paths_android.h"
#include "base/feature_list.h"
#include "base/files/file_util.h"
#include "base/metrics/histogram_functions.h"
#include "base/metrics/persistent_histogram_allocator.h"
#include "base/path_service.h"
#include "base/task/task_traits.h"
#include "base/task/thread_pool.h"
#include "base/time/time.h"
#include "base/trace_event/trace_event.h"
#include "components/metrics/metrics_pref_names.h"
#include "components/metrics/metrics_service.h"
#include "components/prefs/pref_service.h"
@ -60,6 +66,8 @@ AwMetricsServiceClient* g_aw_metrics_service_client = nullptr;
} // namespace
const base::TimeDelta kRecordAppDataDirectorySizeDelay = base::Seconds(10);
AwMetricsServiceClient::Delegate::Delegate() = default;
AwMetricsServiceClient::Delegate::~Delegate() = default;
@ -198,8 +206,36 @@ void AwMetricsServiceClient::SetAppPackageNameLoggingRuleLastUpdateTime(
update_time);
}
// Used below in AwMetricsServiceClient::OnMetricsStart.
void RecordAppDataDirectorySize() {
TRACE_EVENT_BEGIN0("android_webview", "RecordAppDataDirectorySize");
base::TimeTicks start_time = base::TimeTicks::Now();
base::FilePath app_data_dir;
base::PathService::Get(base::DIR_ANDROID_APP_DATA, &app_data_dir);
int64_t bytes = base::ComputeDirectorySize(app_data_dir);
// Record size up to 100MB
base::UmaHistogramCounts100000("Android.WebView.AppDataDirectory.Size",
bytes / 1024);
base::UmaHistogramMediumTimes(
"Android.WebView.AppDataDirectory.TimeToComputeSize",
base::TimeTicks::Now() - start_time);
TRACE_EVENT_END0("android_webview", "RecordAppDataDirectorySize");
}
void AwMetricsServiceClient::OnMetricsStart() {
delegate_->AddWebViewAppStateObserver(this);
if (base::FeatureList::IsEnabled(
android_webview::features::kWebViewRecordAppDataDirectorySize) &&
IsReportingEnabled()) {
// Calculating directory size can be fairly expensive, so only do this when
// we are certain that the UMA histogram will be logged to the server.
base::ThreadPool::PostDelayedTask(
FROM_HERE, {base::MayBlock(), base::TaskPriority::BEST_EFFORT},
base::BindOnce(&RecordAppDataDirectorySize),
kRecordAppDataDirectorySizeDelay);
}
}
void AwMetricsServiceClient::OnMetricsNotStarted() {}

@ -39,6 +39,12 @@ enum class BackfillInstallDate {
kMaxValue = kPersistedPackageManagerInstallDate,
};
// The amount of delay before calculating and recording the app data directory
// size, intended for avoiding IO contention when an app is initializing.
//
// Visible for testing.
extern const base::TimeDelta kRecordAppDataDirectorySizeDelay;
// AwMetricsServiceClient is a singleton which manages WebView metrics
// collection.
//

@ -8,14 +8,19 @@
#include "android_webview/common/aw_features.h"
#include "android_webview/common/metrics/app_package_name_logging_rule.h"
#include "base/metrics/histogram.h"
#include "base/metrics/user_metrics.h"
#include "base/test/metrics/histogram_tester.h"
#include "base/test/scoped_feature_list.h"
#include "base/test/task_environment.h"
#include "base/test/test_simple_task_runner.h"
#include "base/time/time.h"
#include "base/version.h"
#include "components/embedder_support/android/metrics/android_metrics_service_client.h"
#include "components/metrics/metrics_switches.h"
#include "components/prefs/testing_pref_service.h"
#include "content/public/test/browser_task_environment.h"
#include "content/public/test/test_content_client_initializer.h"
#include "testing/gtest/include/gtest/gtest.h"
namespace android_webview {
@ -38,6 +43,20 @@ class AwMetricsServiceClientTestDelegate
bool HasAwContentsEverCreated() const override { return false; }
};
// Adds support for setting whether metric reporting is in sample.
class AwMetricsServiceTestClient : public AwMetricsServiceClient {
public:
explicit AwMetricsServiceTestClient(std::unique_ptr<Delegate> delegate)
: AwMetricsServiceClient(std::move(delegate)) {}
void SetInSample(bool in_sample) { in_sample_ = in_sample; }
protected:
bool IsInSample() const override { return in_sample_; }
private:
bool in_sample_ = false;
};
class AwMetricsServiceClientTest : public testing::Test {
AwMetricsServiceClientTest& operator=(const AwMetricsServiceClientTest&) =
delete;
@ -48,21 +67,32 @@ class AwMetricsServiceClientTest : public testing::Test {
AwMetricsServiceClientTest()
: task_runner_(new base::TestSimpleTaskRunner),
prefs_(std::make_unique<TestingPrefServiceSimple>()),
client_(std::make_unique<AwMetricsServiceClient>(
client_(std::make_unique<AwMetricsServiceTestClient>(
std::make_unique<AwMetricsServiceClientTestDelegate>())) {
// Required by MetricsService.
base::SetRecordActionTaskRunner(task_runner_);
AwMetricsServiceClient::RegisterMetricsPrefs(prefs_->registry());
AwMetricsServiceTestClient::RegisterMetricsPrefs(prefs_->registry());
client_->Initialize(prefs_.get());
}
AwMetricsServiceClient* GetClient() { return client_.get(); }
AwMetricsServiceTestClient* GetClient() { return client_.get(); }
TestingPrefServiceSimple* GetPrefs() { return prefs_.get(); }
void TriggerDelayedRecordAppDataDirectorySize() {
task_environment_.FastForwardBy(kRecordAppDataDirectorySizeDelay);
}
private:
// Needed since starting metrics reporting triggers code that uses content::
// objects.
content::TestContentClientInitializer test_content_initializer_;
// Needed since starting metrics reporting triggers code that expects to be
// running on the browser UI thread. Also needed for its FastForwardBy method.
content::BrowserTaskEnvironment task_environment_{
base::test::TaskEnvironment::TimeSource::MOCK_TIME};
scoped_refptr<base::TestSimpleTaskRunner> task_runner_;
std::unique_ptr<TestingPrefServiceSimple> prefs_;
std::unique_ptr<AwMetricsServiceClient> client_;
std::unique_ptr<AwMetricsServiceTestClient> client_;
};
} // namespace
@ -309,4 +339,69 @@ TEST_F(AwMetricsServiceClientTest, TestGetAppPackageNameIfLoggable) {
EXPECT_TRUE(client.GetAppPackageNameIfLoggable().empty());
}
TEST_F(
AwMetricsServiceClientTest,
TestAppDataDirectorySize_RecordedIfFeatureEnabledConsentGrantedAndInSample) {
base::test::ScopedFeatureList scoped_list;
scoped_list.InitAndEnableFeature(
android_webview::features::kWebViewRecordAppDataDirectorySize);
base::HistogramTester histogram_tester;
GetClient()->SetInSample(true);
GetClient()->SetHaveMetricsConsent(true, true);
TriggerDelayedRecordAppDataDirectorySize();
histogram_tester.ExpectTotalCount("Android.WebView.AppDataDirectory.Size", 1);
histogram_tester.ExpectTotalCount(
"Android.WebView.AppDataDirectory.TimeToComputeSize", 1);
}
TEST_F(AwMetricsServiceClientTest,
TestAppDataDirectorySize_NotRecordedIfFeatureDisabled) {
base::test::ScopedFeatureList scoped_list;
scoped_list.InitAndDisableFeature(
android_webview::features::kWebViewRecordAppDataDirectorySize);
base::HistogramTester histogram_tester;
GetClient()->SetInSample(true);
GetClient()->SetHaveMetricsConsent(true, true);
TriggerDelayedRecordAppDataDirectorySize();
histogram_tester.ExpectTotalCount("Android.WebView.AppDataDirectory,Size", 0);
histogram_tester.ExpectTotalCount(
"Android.WebView.AppDataDirectory.TimeToComputeSize", 0);
}
TEST_F(AwMetricsServiceClientTest,
TestAppDataDirectorySize_NotRecordedIfConsentNotGranted) {
base::test::ScopedFeatureList scoped_list;
scoped_list.InitAndEnableFeature(
android_webview::features::kWebViewRecordAppDataDirectorySize);
base::HistogramTester histogram_tester;
GetClient()->SetInSample(true);
GetClient()->SetHaveMetricsConsent(true, false);
TriggerDelayedRecordAppDataDirectorySize();
histogram_tester.ExpectTotalCount("Android.WebView.AppDataDirectory.Size", 0);
histogram_tester.ExpectTotalCount(
"Android.WebView.AppDataDirectory.TimeToComputeSize", 0);
}
TEST_F(AwMetricsServiceClientTest,
TestAppDataDirectorySize_NotRecordedIfNotInSample) {
base::test::ScopedFeatureList scoped_list;
scoped_list.InitAndEnableFeature(
android_webview::features::kWebViewRecordAppDataDirectorySize);
base::HistogramTester histogram_tester;
GetClient()->SetInSample(false);
GetClient()->SetHaveMetricsConsent(true, true);
TriggerDelayedRecordAppDataDirectorySize();
histogram_tester.ExpectTotalCount("Android.WebView.AppDataDirectory.Size", 0);
histogram_tester.ExpectTotalCount(
"Android.WebView.AppDataDirectory.TimeToComputeSize", 0);
}
} // namespace android_webview

@ -89,6 +89,11 @@ const base::Feature kWebViewMeasureScreenCoverage{
const base::Feature kWebViewOriginTrials{"WebViewOriginTrials",
base::FEATURE_DISABLED_BY_DEFAULT};
// Whether to record size of the embedding app's data directory to the UMA
// histogram Android.WebView.AppDataDirectorySize.
const base::Feature kWebViewRecordAppDataDirectorySize{
"WebViewRecordAppDataDirectorySize", base::FEATURE_DISABLED_BY_DEFAULT};
// Whether WebView will send variations headers on URLs where applicable.
const base::Feature kWebViewSendVariationsHeaders{
"WebViewSendVariationsHeaders", base::FEATURE_DISABLED_BY_DEFAULT};

@ -32,6 +32,7 @@ extern const base::Feature kWebViewLegacyTlsSupport;
extern const base::Feature kWebViewMeasureScreenCoverage;
extern const base::Feature kWebViewMixedContentAutoupgrades;
extern const base::Feature kWebViewOriginTrials;
extern const base::Feature kWebViewRecordAppDataDirectorySize;
extern const base::Feature kWebViewSendVariationsHeaders;
extern const base::Feature kWebViewSuppressDifferentOriginSubframeJSDialogs;
extern const base::Feature kWebViewTestFeature;

@ -340,6 +340,8 @@ public final class ProductionSupportedFlagList {
"Run tasks in queue for 8ms before before sending a system message."),
Flag.baseFeature(BlinkFeatures.OFFSET_PARENT_NEW_SPEC_BEHAVIOR,
"Enables new HTMLElement.offsetParent behavior to match other browsers."),
Flag.baseFeature(AwFeatures.WEBVIEW_RECORD_APP_DATA_DIRECTORY_SIZE,
"Record the size of the embedding app's data directory")
// Add new commandline switches and features above. The final entry should have a
// trailing comma for cleaner diffs.
};

@ -220,7 +220,7 @@ class AndroidMetricsServiceClient : public MetricsServiceClient,
// we log metrics. If this returns false, MetricsServiceClient should
// indicate reporting is disabled. Sampling is due to storage/bandwidth
// considerations.
bool IsInSample() const;
virtual bool IsInSample() const;
// Returns the installer type of the app.
virtual InstallerPackageType GetInstallerPackageType();

@ -56239,7 +56239,6 @@ from previous Chrome versions.
<int value="-1151615978" label="BorealisBigGl:disabled"/>
<int value="-1151476162" label="LacrosMergeIcuDataFile:disabled"/>
<int value="-1151014496" label="NearbySharingDeviceContacts:disabled"/>
<int value="-1149544733" label="OffsetparentNewSpecBehavior:enabled"/>
<int value="-1146814438" label="TabbedAppOverflowMenuIcons:enabled"/>
<int value="-1146310028" label="HardwareSecureDecryptionFallback:enabled"/>
<int value="-1145905507" label="SendTabToSelfWhenSignedIn:disabled"/>
@ -57810,7 +57809,6 @@ from previous Chrome versions.
<int value="-92116820" label="InlineUpdateFlow:enabled"/>
<int value="-91767554" label="enable-de-jelly"/>
<int value="-91370149" label="UseSerialBusEnumerator:enabled"/>
<int value="-90799024" label="OffsetparentNewSpecBehavior:disabled"/>
<int value="-90521375" label="PDFTwoUpView:enabled"/>
<int value="-90032223" label="BuiltInModuleInfra:disabled"/>
<int value="-89690053" label="MaterialDesignUserManager:enabled"/>
@ -58625,6 +58623,7 @@ from previous Chrome versions.
<int value="427184788" label="WebFeed:enabled"/>
<int value="427807224" label="IPH_Snooze:disabled"/>
<int value="427945554" label="StrictExtensionIsolation:enabled"/>
<int value="428554364" label="OffsetParentNewSpecBehavior:disabled"/>
<int value="430776375" label="TextureLayerSkipWaitForActivation:disabled"/>
<int value="430959979" label="SyncStandaloneTransport:disabled"/>
<int value="431691805" label="MediaDocumentDownloadButton:enabled"/>
@ -59117,6 +59116,7 @@ from previous Chrome versions.
<int value="749516419" label="DragToSnapInClamshellMode:disabled"/>
<int value="749994865" label="MessagesForAndroidSyncError:enabled"/>
<int value="750028579" label="CommerceCoupons:disabled"/>
<int value="751862578" label="OffsetParentNewSpecBehavior:enabled"/>
<int value="752194066" label="enable-app-window-cycling"/>
<int value="752416911" label="FastPair:disabled"/>
<int value="752939691" label="disable-tab-for-desktop-share"/>
@ -61047,6 +61047,7 @@ from previous Chrome versions.
<int value="2032880973" label="U2FSecurityKeyAPI:disabled"/>
<int value="2034198538" label="TabHoverCards:enabled"/>
<int value="2035415906" label="Win11StyleMenus:enabled"/>
<int value="2035524582" label="WebViewRecordAppDataDirectorySize:disabled"/>
<int value="2037562553" label="OmniboxBubbleUrlSuggestions:disabled"/>
<int value="2037756154" label="enable-impl-side-painting"/>
<int value="2038036881" label="NewShortcutMapping:enabled"/>
@ -61202,6 +61203,7 @@ from previous Chrome versions.
<int value="2142661816" label="AllowRemoteContextForNotifications:disabled"/>
<int value="2142979536" label="EnableManualFallbacksFilling:disabled"/>
<int value="2144581598" label="UpcomingSharingFeatures:enabled"/>
<int value="2145140507" label="WebViewRecordAppDataDirectorySize:enabled"/>
</enum>
<enum name="LoginDatabaseInitError">

@ -3490,6 +3490,26 @@ chromium-metrics-reviews@google.com.
</summary>
</histogram>
<histogram name="Android.WebView.AppDataDirectory.Size" units="KiB"
expires_after="2022-12-01">
<owner>xiaq@chromium.org</owner>
<owner>src/android_webview/OWNERS</owner>
<summary>
Size on disk taken by the embedding app's data directory, recorded once per
WebView startup after a small delay.
</summary>
</histogram>
<histogram name="Android.WebView.AppDataDirectory.TimeToComputeSize" units="ms"
expires_after="2022-12-01">
<owner>xiaq@chromium.org</owner>
<owner>src/android_webview/OWNERS</owner>
<summary>
Time to compute the size on disk taken by the embedding app's data
directory, recorded once per WebView startup after a small delay.
</summary>
</histogram>
<histogram name="Android.WebView.Callback.Counts" enum="WebViewCallbackType"
expires_after="2022-11-13">
<owner>ntfschr@chromium.org</owner>