Commit bca4f583 authored by Kyle Milka's avatar Kyle Milka Committed by Commit Bot

Make GetOrCreateGUID synchronous

This is part 2 of 6 for FieldTrial refactoring for WebView

Part 1: https://chromium-review.googlesource.com/c/562098/
Part 2: https://chromium-review.googlesource.com/c/561920/
Part 3: https://chromium-review.googlesource.com/c/561922/
Part 4: https://chromium-review.googlesource.com/c/561980/
Part 5: https://chromium-review.googlesource.com/c/562417/
Part 6: https://chromium-review.googlesource.com/c/562021/

This CL makes the reading on the client ID happen synchronously
at WebView startup only if the enable-webview-finch command
line flag is provided. This behavior is necessary in order to be
able to set up field trials as early as possible in the WebView
startup process. GetOrCreateGUID() is now a static member of
the AwMetricsServiceClient class.

BUG=678288

Change-Id: I69153f87243fa84f6816785090bfa963e34cf0b2
Reviewed-on: https://chromium-review.googlesource.com/561920
Commit-Queue: Kyle Milka <kmilka@google.com>
Reviewed-by: default avatarAlexei Svitkine <asvitkine@chromium.org>
Reviewed-by: default avatarSelim Gurun <sgurun@chromium.org>
Reviewed-by: default avatarPaul Miller <paulmiller@chromium.org>
Cr-Commit-Position: refs/heads/master@{#485390}
parent 055a634e
...@@ -186,16 +186,10 @@ void AwBrowserContext::PreMainMessageLoopRun() { ...@@ -186,16 +186,10 @@ void AwBrowserContext::PreMainMessageLoopRun() {
blacklist_manager_.reset(CreateURLBlackListManager(user_pref_service_.get())); blacklist_manager_.reset(CreateURLBlackListManager(user_pref_service_.get()));
// UMA uses randomly-generated GUIDs (globally unique identifiers) to
// anonymously identify logs. Every WebView-using app on every device
// is given a GUID, stored in this file in the app's data directory.
const FilePath guid_file_path =
GetPath().Append(FILE_PATH_LITERAL("metrics_guid"));
AwMetricsServiceClient::GetInstance()->Initialize( AwMetricsServiceClient::GetInstance()->Initialize(
user_pref_service_.get(), user_pref_service_.get(),
content::BrowserContext::GetDefaultStoragePartition(this)-> content::BrowserContext::GetDefaultStoragePartition(this)
GetURLRequestContext(), ->GetURLRequestContext());
guid_file_path);
web_restriction_provider_.reset( web_restriction_provider_.reset(
new web_restrictions::WebRestrictionsClient()); new web_restrictions::WebRestrictionsClient());
......
...@@ -7,6 +7,7 @@ ...@@ -7,6 +7,7 @@
#include "android_webview/browser/aw_browser_context.h" #include "android_webview/browser/aw_browser_context.h"
#include "android_webview/browser/aw_browser_terminator.h" #include "android_webview/browser/aw_browser_terminator.h"
#include "android_webview/browser/aw_content_browser_client.h" #include "android_webview/browser/aw_content_browser_client.h"
#include "android_webview/browser/aw_metrics_service_client.h"
#include "android_webview/browser/aw_result_codes.h" #include "android_webview/browser/aw_result_codes.h"
#include "android_webview/browser/aw_safe_browsing_config_helper.h" #include "android_webview/browser/aw_safe_browsing_config_helper.h"
#include "android_webview/browser/deferred_gpu_command_service.h" #include "android_webview/browser/deferred_gpu_command_service.h"
...@@ -150,6 +151,11 @@ int AwBrowserMainParts::PreCreateThreads() { ...@@ -150,6 +151,11 @@ int AwBrowserMainParts::PreCreateThreads() {
base::MakeUnique<AwBrowserTerminator>()); base::MakeUnique<AwBrowserTerminator>());
} }
if (base::CommandLine::ForCurrentProcess()->HasSwitch(
switches::kEnableWebViewFinch)) {
AwMetricsServiceClient::GetOrCreateGUID();
}
return content::RESULT_CODE_NORMAL_EXIT; return content::RESULT_CODE_NORMAL_EXIT;
} }
......
...@@ -5,6 +5,7 @@ ...@@ -5,6 +5,7 @@
#include "android_webview/browser/aw_metrics_service_client.h" #include "android_webview/browser/aw_metrics_service_client.h"
#include "android_webview/browser/aw_metrics_log_uploader.h" #include "android_webview/browser/aw_metrics_log_uploader.h"
#include "android_webview/common/aw_switches.h"
#include "android_webview/common/aw_version_info_values.h" #include "android_webview/common/aw_version_info_values.h"
#include "android_webview/jni/AwMetricsServiceClient_jni.h" #include "android_webview/jni/AwMetricsServiceClient_jni.h"
#include "base/android/build_info.h" #include "base/android/build_info.h"
...@@ -13,6 +14,8 @@ ...@@ -13,6 +14,8 @@
#include "base/files/file_util.h" #include "base/files/file_util.h"
#include "base/guid.h" #include "base/guid.h"
#include "base/i18n/rtl.h" #include "base/i18n/rtl.h"
#include "base/lazy_instance.h"
#include "base/path_service.h"
#include "base/threading/sequenced_worker_pool.h" #include "base/threading/sequenced_worker_pool.h"
#include "components/metrics/call_stack_profile_metrics_provider.h" #include "components/metrics/call_stack_profile_metrics_provider.h"
#include "components/metrics/enabled_state_provider.h" #include "components/metrics/enabled_state_provider.h"
...@@ -38,6 +41,13 @@ namespace { ...@@ -38,6 +41,13 @@ namespace {
const int kUploadIntervalMinutes = 30; const int kUploadIntervalMinutes = 30;
// A GUID in text form is composed of 32 hex digits and 4 hyphens.
const size_t GUID_SIZE = 32 + 4;
// Client ID of the app, read and cached synchronously at startup
base::LazyInstance<std::string>::Leaky g_client_id_guid =
LAZY_INSTANCE_INITIALIZER;
// Callbacks for metrics::MetricsStateManager::Create. Store/LoadClientInfo // Callbacks for metrics::MetricsStateManager::Create. Store/LoadClientInfo
// allow Windows Chrome to back up ClientInfo. They're no-ops for WebView. // allow Windows Chrome to back up ClientInfo. They're no-ops for WebView.
...@@ -48,30 +58,6 @@ std::unique_ptr<metrics::ClientInfo> LoadClientInfo() { ...@@ -48,30 +58,6 @@ std::unique_ptr<metrics::ClientInfo> LoadClientInfo() {
return client_info; return client_info;
} }
// A GUID in text form is composed of 32 hex digits and 4 hyphens.
const size_t GUID_SIZE = 32 + 4;
void GetOrCreateGUID(const base::FilePath guid_file_path, std::string* guid) {
DCHECK_CURRENTLY_ON(content::BrowserThread::FILE);
// Try to read an existing GUID.
if (base::ReadFileToStringWithMaxSize(guid_file_path, guid, GUID_SIZE)) {
if (base::IsValidGUID(*guid))
return;
else
LOG(ERROR) << "Overwriting invalid GUID";
}
// We must write a new GUID.
*guid = base::GenerateGUID();
if (!base::WriteFile(guid_file_path, guid->c_str(), guid->size())) {
// If writing fails, proceed anyway with the new GUID. It won't be persisted
// to the next run, but we can still collect metrics with this 1-time GUID.
LOG(ERROR) << "Failed to write new GUID";
}
return;
}
version_info::Channel GetChannelFromPackageName() { version_info::Channel GetChannelFromPackageName() {
JNIEnv* env = base::android::AttachCurrentThread(); JNIEnv* env = base::android::AttachCurrentThread();
std::string package_name = base::android::ConvertJavaStringToUTF8( std::string package_name = base::android::ConvertJavaStringToUTF8(
...@@ -89,10 +75,47 @@ AwMetricsServiceClient* AwMetricsServiceClient::GetInstance() { ...@@ -89,10 +75,47 @@ AwMetricsServiceClient* AwMetricsServiceClient::GetInstance() {
return g_lazy_instance_.Pointer(); return g_lazy_instance_.Pointer();
} }
void AwMetricsServiceClient::GetOrCreateGUID() {
// Check for cached GUID
if (g_client_id_guid.Get().length() == GUID_SIZE)
return;
// UMA uses randomly-generated GUIDs (globally unique identifiers) to
// anonymously identify logs. Every WebView-using app on every device
// is given a GUID, stored in this file in the app's data directory.
base::FilePath user_data_dir;
if (!PathService::Get(base::DIR_ANDROID_APP_DATA, &user_data_dir)) {
LOG(ERROR) << "Failed to get app data directory for Android WebView";
// Generate a 1-time GUID so metrics can still be collected
g_client_id_guid.Get() = base::GenerateGUID();
return;
}
const base::FilePath guid_file_path =
user_data_dir.Append(FILE_PATH_LITERAL("metrics_guid"));
// Try to read an existing GUID.
if (base::ReadFileToStringWithMaxSize(guid_file_path, &g_client_id_guid.Get(),
GUID_SIZE)) {
if (base::IsValidGUID(g_client_id_guid.Get()))
return;
LOG(ERROR) << "Overwriting invalid GUID";
}
// We must write a new GUID.
g_client_id_guid.Get() = base::GenerateGUID();
if (!base::WriteFile(guid_file_path, g_client_id_guid.Get().c_str(),
g_client_id_guid.Get().size())) {
// If writing fails, proceed anyway with the new GUID. It won't be persisted
// to the next run, but we can still collect metrics with this 1-time GUID.
LOG(ERROR) << "Failed to write new GUID";
}
}
void AwMetricsServiceClient::Initialize( void AwMetricsServiceClient::Initialize(
PrefService* pref_service, PrefService* pref_service,
net::URLRequestContextGetter* request_context, net::URLRequestContextGetter* request_context) {
const base::FilePath guid_file_path) {
DCHECK_CURRENTLY_ON(content::BrowserThread::UI); DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
DCHECK(pref_service_ == nullptr); // Initialize should only happen once. DCHECK(pref_service_ == nullptr); // Initialize should only happen once.
...@@ -101,22 +124,26 @@ void AwMetricsServiceClient::Initialize( ...@@ -101,22 +124,26 @@ void AwMetricsServiceClient::Initialize(
request_context_ = request_context; request_context_ = request_context;
channel_ = GetChannelFromPackageName(); channel_ = GetChannelFromPackageName();
std::string* guid = new std::string; // If Finch is enabled for WebView the GUID will already have been read at
// Initialization happens on the UI thread, but getting the GUID should happen // startup
// on the file I/O thread. So we start to initialize, then post to get the if (base::CommandLine::ForCurrentProcess()->HasSwitch(
// GUID, and then pick up where we left off, back on the UI thread, in switches::kEnableWebViewFinch)) {
// InitializeWithGUID. InitializeWithGUID();
} else {
content::BrowserThread::PostTaskAndReply( content::BrowserThread::PostTaskAndReply(
content::BrowserThread::FILE, FROM_HERE, content::BrowserThread::FILE, FROM_HERE,
base::Bind(&GetOrCreateGUID, guid_file_path, guid), base::Bind(&AwMetricsServiceClient::GetOrCreateGUID),
base::Bind(&AwMetricsServiceClient::InitializeWithGUID, base::Bind(&AwMetricsServiceClient::InitializeWithGUID,
base::Unretained(this), base::Owned(guid))); base::Unretained(this)));
}
} }
void AwMetricsServiceClient::InitializeWithGUID(std::string* guid) { void AwMetricsServiceClient::InitializeWithGUID() {
DCHECK_CURRENTLY_ON(content::BrowserThread::UI); // The guid must have already been initialized at this point, either
// synchronously or asynchronously depending on the kEnableWebViewFinch flag
pref_service_->SetString(metrics::prefs::kMetricsClientID, *guid); DCHECK_EQ(g_client_id_guid.Get().length(), GUID_SIZE);
pref_service_->SetString(metrics::prefs::kMetricsClientID,
g_client_id_guid.Get());
metrics_state_manager_ = metrics::MetricsStateManager::Create( metrics_state_manager_ = metrics::MetricsStateManager::Create(
pref_service_, this, base::Bind(&StoreClientInfo), pref_service_, this, base::Bind(&StoreClientInfo),
......
...@@ -44,9 +44,12 @@ class AwMetricsServiceClient : public metrics::MetricsServiceClient, ...@@ -44,9 +44,12 @@ class AwMetricsServiceClient : public metrics::MetricsServiceClient,
public: public:
static AwMetricsServiceClient* GetInstance(); static AwMetricsServiceClient* GetInstance();
// Retrieve the client ID or generate one if none exists
static void GetOrCreateGUID();
void Initialize(PrefService* pref_service, void Initialize(PrefService* pref_service,
net::URLRequestContextGetter* request_context, net::URLRequestContextGetter* request_context);
const base::FilePath guid_file_path);
// metrics::EnabledStateProvider implementation // metrics::EnabledStateProvider implementation
bool IsConsentGiven() override; bool IsConsentGiven() override;
...@@ -79,7 +82,7 @@ class AwMetricsServiceClient : public metrics::MetricsServiceClient, ...@@ -79,7 +82,7 @@ class AwMetricsServiceClient : public metrics::MetricsServiceClient,
AwMetricsServiceClient(); AwMetricsServiceClient();
~AwMetricsServiceClient() override; ~AwMetricsServiceClient() override;
void InitializeWithGUID(std::string* guid); void InitializeWithGUID();
bool is_enabled_; bool is_enabled_;
PrefService* pref_service_; PrefService* pref_service_;
......
...@@ -6,6 +6,7 @@ ...@@ -6,6 +6,7 @@
namespace switches { namespace switches {
const char kEnableWebViewFinch[] = "enable-webview-finch";
const char kSyncOnDrawHardware[] = "sync-on-draw-hardware"; const char kSyncOnDrawHardware[] = "sync-on-draw-hardware";
const char kWebViewSandboxedRenderer[] = "webview-sandboxed-renderer"; const char kWebViewSandboxedRenderer[] = "webview-sandboxed-renderer";
......
...@@ -7,6 +7,7 @@ ...@@ -7,6 +7,7 @@
namespace switches { namespace switches {
extern const char kEnableWebViewFinch[];
extern const char kSyncOnDrawHardware[]; extern const char kSyncOnDrawHardware[];
extern const char kWebViewSandboxedRenderer[]; extern const char kWebViewSandboxedRenderer[];
extern const char kWebViewEnableSafeBrowsingSupport[]; extern const char kWebViewEnableSafeBrowsingSupport[];
......
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