Remove RAPPOR reporting infrastructure.
Only a handful of metrics were still reported using this, which are have been confirmed to be OK to remove. Includes code to clear the obsolete rappor prefs. Bug: 1016906 Change-Id: I8765494bcf6730107e585e8a244195b29d61f42e Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2672923 Reviewed-by: Martin Šrámek <msramek@chromium.org> Reviewed-by: Steven Holte <holte@chromium.org> Reviewed-by: Jochen Eisinger <jochen@chromium.org> Commit-Queue: Alexei Svitkine <asvitkine@chromium.org> Cr-Commit-Position: refs/heads/master@{#850848}
This commit is contained in:

committed by
Chromium LUCI CQ

parent
8f8e1306c0
commit
2d96608b43
.gitignoreBUILD.gnWATCHLISTS
chrome
android
browser
BUILD.gnDEPS
android
browser_process.hbrowser_process_impl.ccbrowser_process_impl.hchrome_browser_main.ccchromeos
extensions
metrics
page_load_metrics
prefs
safe_browsing
chrome_cleaner
ui
vr
renderer
test
tools
build
win
components
BUILD.gn
metrics
metrics_services_manager
ntp_tiles
rappor
BUILD.gnDEPSDIR_METADATAOWNERSREADME.mdbloom_filter.ccbloom_filter.hbloom_filter_unittest.ccbyte_vector_utils.ccbyte_vector_utils.hbyte_vector_utils_unittest.cclog_uploader.cclog_uploader.hlog_uploader_interface.hlog_uploader_unittest.cc
proto
public
rappor_metric.ccrappor_metric.hrappor_metric_unittest.ccrappor_parameters.ccrappor_pref_names.ccrappor_pref_names.hrappor_prefs.ccrappor_prefs.hrappor_prefs_unittest.ccrappor_service_impl.ccrappor_service_impl.hrappor_service_unittest.ccrappor_utils.ccrappor_utils_unittest.ccreports.ccreports.hreports_unittest.ccsample.ccsampler.ccsampler.hsampler_unittest.cctest_log_uploader.cctest_log_uploader.htest_rappor_service.cctest_rappor_service.hsecurity_interstitials
content
ios
chrome
browser
BUILD.gnDEPSapplication_context.happlication_context_impl.happlication_context_impl.mmios_chrome_main_parts.mm
metrics
prefs
ui
ntp
test
components
security_interstitials
tools
1
.gitignore
vendored
1
.gitignore
vendored
@ -188,7 +188,6 @@ vs-chromium-project.txt
|
||||
/components/gcm_driver.xml
|
||||
/components/leveldb_proto_test_support.xml
|
||||
/components/ntp_tiles/resources/internal
|
||||
/components/rappor.xml
|
||||
/components/resources/default_100_percent/google_chrome
|
||||
/components/resources/default_200_percent/google_chrome
|
||||
/components/resources/default_300_percent/google_chrome
|
||||
|
1
BUILD.gn
1
BUILD.gn
@ -718,7 +718,6 @@ group("gn_all") {
|
||||
"//chrome/tools/convert_dict",
|
||||
"//components/constrained_window:unit_tests",
|
||||
"//components/metrics:serialization",
|
||||
"//components/rappor:unit_tests",
|
||||
"//components/services/filesystem:filesystem_service_unittests",
|
||||
"//components/sessions:unit_tests",
|
||||
"//media/blink:media_blink_unittests",
|
||||
|
@ -1301,7 +1301,6 @@
|
||||
'|chromecast/browser/metrics/'\
|
||||
'|components/metrics/'\
|
||||
'|components/metrics_services_manager/'\
|
||||
'|components/rappor/'\
|
||||
'|components/variations/'\
|
||||
# Exclude XML files; in particular, histograms.xml.
|
||||
'|tools/metrics/[^.]*([.](?!xml$).*)?$',
|
||||
|
@ -3444,7 +3444,6 @@ generate_jni("chrome_jni_headers") {
|
||||
"java/src/org/chromium/chrome/browser/provider/ChromeBrowserProviderImpl.java",
|
||||
"java/src/org/chromium/chrome/browser/push_messaging/PushMessagingServiceObserver.java",
|
||||
"java/src/org/chromium/chrome/browser/query_tiles/TileProviderFactory.java",
|
||||
"java/src/org/chromium/chrome/browser/rappor/RapporServiceBridge.java",
|
||||
"java/src/org/chromium/chrome/browser/read_later/ReadingListBridge.java",
|
||||
"java/src/org/chromium/chrome/browser/resources/ResourceMapper.java",
|
||||
"java/src/org/chromium/chrome/browser/rlz/RevenueStats.java",
|
||||
|
@ -1190,7 +1190,6 @@ chrome_java_sources = [
|
||||
"java/src/org/chromium/chrome/browser/query_tiles/QueryTileSection.java",
|
||||
"java/src/org/chromium/chrome/browser/query_tiles/QueryTileUtils.java",
|
||||
"java/src/org/chromium/chrome/browser/query_tiles/TileProviderFactory.java",
|
||||
"java/src/org/chromium/chrome/browser/rappor/RapporServiceBridge.java",
|
||||
"java/src/org/chromium/chrome/browser/read_later/ReadLaterIPHController.java",
|
||||
"java/src/org/chromium/chrome/browser/read_later/ReadingListBridge.java",
|
||||
"java/src/org/chromium/chrome/browser/read_later/ReadingListUtils.java",
|
||||
|
@ -4,24 +4,18 @@
|
||||
|
||||
package org.chromium.chrome.browser.customtabs;
|
||||
|
||||
import android.text.TextUtils;
|
||||
|
||||
import org.chromium.base.metrics.RecordHistogram;
|
||||
import org.chromium.base.metrics.RecordUserAction;
|
||||
import org.chromium.base.task.PostTask;
|
||||
import org.chromium.chrome.browser.IntentHandler;
|
||||
import org.chromium.chrome.browser.app.ChromeActivity;
|
||||
import org.chromium.chrome.browser.browserservices.BrowserServicesIntentDataProvider;
|
||||
import org.chromium.chrome.browser.dependency_injection.ActivityScope;
|
||||
import org.chromium.chrome.browser.gsa.GSAState;
|
||||
import org.chromium.chrome.browser.lifecycle.ActivityLifecycleDispatcher;
|
||||
import org.chromium.chrome.browser.lifecycle.NativeInitObserver;
|
||||
import org.chromium.chrome.browser.lifecycle.PauseResumeWithNativeObserver;
|
||||
import org.chromium.chrome.browser.preferences.ChromePreferenceKeys;
|
||||
import org.chromium.chrome.browser.preferences.SharedPreferencesManager;
|
||||
import org.chromium.chrome.browser.rappor.RapporServiceBridge;
|
||||
import org.chromium.chrome.browser.webapps.WebappCustomTabTimeSpentLogger;
|
||||
import org.chromium.content_public.browser.UiThreadTaskTraits;
|
||||
|
||||
import javax.inject.Inject;
|
||||
|
||||
@ -98,19 +92,8 @@ public class CustomTabActivityLifecycleUmaTracker implements PauseResumeWithNati
|
||||
|
||||
@Override
|
||||
public void onFinishNativeInitialization() {
|
||||
String clientName =
|
||||
mConnection.getClientPackageNameForSession(mIntentDataProvider.getSession());
|
||||
if (TextUtils.isEmpty(clientName)) clientName = mIntentDataProvider.getClientPackageName();
|
||||
final String packageName = clientName;
|
||||
if (TextUtils.isEmpty(packageName) || packageName.contains(mActivity.getPackageName())) {
|
||||
return;
|
||||
if (mWebappTimeSpentLogger != null) {
|
||||
mWebappTimeSpentLogger.onPause();
|
||||
}
|
||||
|
||||
PostTask.postTask(UiThreadTaskTraits.DEFAULT, () -> {
|
||||
RapporServiceBridge.sampleString("CustomTabs.ServiceClient.PackageName", packageName);
|
||||
if (GSAState.isGsaPackageName(packageName)) return;
|
||||
RapporServiceBridge.sampleString(
|
||||
"CustomTabs.ServiceClient.PackageNameThirdParty", packageName);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
@ -1,32 +0,0 @@
|
||||
// Copyright 2015 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.
|
||||
|
||||
package org.chromium.chrome.browser.rappor;
|
||||
|
||||
import org.chromium.base.annotations.JNINamespace;
|
||||
import org.chromium.base.annotations.NativeMethods;
|
||||
|
||||
/**
|
||||
* JNI bridge to the native Rappor service from Java.
|
||||
*/
|
||||
@JNINamespace("rappor")
|
||||
public final class RapporServiceBridge {
|
||||
private RapporServiceBridge() {
|
||||
// Only for static use.
|
||||
}
|
||||
|
||||
public static void sampleString(String metric, String sampleValue) {
|
||||
RapporServiceBridgeJni.get().sampleString(metric, sampleValue);
|
||||
}
|
||||
|
||||
public static void sampleDomainAndRegistryFromURL(String metric, String url) {
|
||||
RapporServiceBridgeJni.get().sampleDomainAndRegistryFromURL(metric, url);
|
||||
}
|
||||
|
||||
@NativeMethods
|
||||
interface Natives {
|
||||
void sampleDomainAndRegistryFromURL(String metric, String url);
|
||||
void sampleString(String metric, String sampleValue);
|
||||
}
|
||||
}
|
@ -2150,7 +2150,6 @@ static_library("browser") {
|
||||
"//components/proxy_config",
|
||||
"//components/query_parser",
|
||||
"//components/query_tiles",
|
||||
"//components/rappor",
|
||||
"//components/reading_list/core",
|
||||
"//components/reading_list/features:flags",
|
||||
"//components/renderer_context_menu",
|
||||
@ -2827,7 +2826,6 @@ static_library("browser") {
|
||||
"android/provider/chrome_browser_provider.cc",
|
||||
"android/provider/chrome_browser_provider.h",
|
||||
"android/provider/run_on_ui_thread_blocking.h",
|
||||
"android/rappor/rappor_service_bridge.cc",
|
||||
"android/reading_list/reading_list_bridge.cc",
|
||||
"android/reading_list/reading_list_bridge.h",
|
||||
"android/reading_list/reading_list_manager_factory.cc",
|
||||
|
@ -244,7 +244,6 @@ include_rules = [
|
||||
"+components/query_parser",
|
||||
"+components/query_tiles",
|
||||
"+components/quirks",
|
||||
"+components/rappor",
|
||||
"+components/reading_list/core",
|
||||
"+components/reading_list/features",
|
||||
"+components/remote_cocoa/app_shim",
|
||||
|
@ -1,38 +0,0 @@
|
||||
// Copyright 2015 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 "base/android/jni_string.h"
|
||||
#include "chrome/android/chrome_jni_headers/RapporServiceBridge_jni.h"
|
||||
#include "chrome/browser/browser_process.h"
|
||||
#include "components/rappor/public/rappor_utils.h"
|
||||
#include "components/rappor/rappor_service_impl.h"
|
||||
#include "url/gurl.h"
|
||||
|
||||
using base::android::JavaParamRef;
|
||||
|
||||
namespace rappor {
|
||||
|
||||
void JNI_RapporServiceBridge_SampleDomainAndRegistryFromURL(
|
||||
JNIEnv* env,
|
||||
const JavaParamRef<jstring>& j_metric,
|
||||
const JavaParamRef<jstring>& j_url) {
|
||||
// TODO(knn): UMA metrics hash the string to prevent frequent re-encoding,
|
||||
// perhaps we should do that as well.
|
||||
std::string metric(base::android::ConvertJavaStringToUTF8(env, j_metric));
|
||||
GURL gurl(base::android::ConvertJavaStringToUTF8(env, j_url));
|
||||
rappor::SampleDomainAndRegistryFromGURL(g_browser_process->rappor_service(),
|
||||
metric, gurl);
|
||||
}
|
||||
|
||||
void JNI_RapporServiceBridge_SampleString(
|
||||
JNIEnv* env,
|
||||
const JavaParamRef<jstring>& j_metric,
|
||||
const JavaParamRef<jstring>& j_value) {
|
||||
std::string metric(base::android::ConvertJavaStringToUTF8(env, j_metric));
|
||||
std::string value(base::android::ConvertJavaStringToUTF8(env, j_value));
|
||||
rappor::SampleString(g_browser_process->rappor_service(),
|
||||
metric, rappor::UMA_RAPPOR_TYPE, value);
|
||||
}
|
||||
|
||||
} // namespace rappor
|
@ -78,7 +78,6 @@ static_library("vr_android") {
|
||||
"//components/omnibox/browser",
|
||||
"//components/page_info",
|
||||
"//components/permissions",
|
||||
"//components/rappor",
|
||||
"//components/search_engines:search_engines",
|
||||
"//components/webxr:webxr",
|
||||
"//components/webxr/android",
|
||||
|
@ -101,10 +101,6 @@ class PrintJobManager;
|
||||
class PrintPreviewDialogController;
|
||||
}
|
||||
|
||||
namespace rappor {
|
||||
class RapporServiceImpl;
|
||||
}
|
||||
|
||||
namespace resource_coordinator {
|
||||
class ResourceCoordinatorParts;
|
||||
class TabManager;
|
||||
@ -134,7 +130,6 @@ class BrowserProcess {
|
||||
|
||||
// Services: any of these getters may return NULL
|
||||
virtual metrics::MetricsService* metrics_service() = 0;
|
||||
virtual rappor::RapporServiceImpl* rappor_service() = 0;
|
||||
virtual ProfileManager* profile_manager() = 0;
|
||||
virtual PrefService* local_state() = 0;
|
||||
virtual scoped_refptr<network::SharedURLLoaderFactory>
|
||||
|
@ -105,8 +105,6 @@
|
||||
#include "components/prefs/json_pref_store.h"
|
||||
#include "components/prefs/pref_registry_simple.h"
|
||||
#include "components/prefs/pref_service.h"
|
||||
#include "components/rappor/public/rappor_utils.h"
|
||||
#include "components/rappor/rappor_service_impl.h"
|
||||
#include "components/safe_browsing/core/safe_browsing_service_interface.h"
|
||||
#include "components/sessions/core/session_id_generator.h"
|
||||
#include "components/subresource_filter/content/browser/ruleset_service.h"
|
||||
@ -218,12 +216,6 @@ static constexpr base::TimeDelta kEndSessionTimeout =
|
||||
using content::BrowserThread;
|
||||
using content::ChildProcessSecurityPolicy;
|
||||
|
||||
rappor::RapporService* GetBrowserRapporService() {
|
||||
if (g_browser_process != nullptr)
|
||||
return g_browser_process->rappor_service();
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
BrowserProcessImpl::BrowserProcessImpl(StartupData* startup_data)
|
||||
: startup_data_(startup_data),
|
||||
browser_policy_connector_(startup_data->chrome_feature_list_creator()
|
||||
@ -256,8 +248,6 @@ void BrowserProcessImpl::Init() {
|
||||
|
||||
download_status_updater_ = std::make_unique<DownloadStatusUpdater>();
|
||||
|
||||
rappor::SetDefaultServiceAccessor(&GetBrowserRapporService);
|
||||
|
||||
#if BUILDFLAG(ENABLE_PRINTING)
|
||||
// Must be created after the NotificationService.
|
||||
print_job_manager_ = std::make_unique<printing::PrintJobManager>();
|
||||
@ -656,11 +646,6 @@ metrics::MetricsService* BrowserProcessImpl::metrics_service() {
|
||||
return GetMetricsServicesManager()->GetMetricsService();
|
||||
}
|
||||
|
||||
rappor::RapporServiceImpl* BrowserProcessImpl::rappor_service() {
|
||||
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
|
||||
return GetMetricsServicesManager()->GetRapporServiceImpl();
|
||||
}
|
||||
|
||||
SystemNetworkContextManager*
|
||||
BrowserProcessImpl::system_network_context_manager() {
|
||||
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
|
||||
|
@ -133,7 +133,6 @@ class BrowserProcessImpl : public BrowserProcess,
|
||||
metrics_services_manager::MetricsServicesManager* GetMetricsServicesManager()
|
||||
override;
|
||||
metrics::MetricsService* metrics_service() override;
|
||||
rappor::RapporServiceImpl* rappor_service() override;
|
||||
// TODO(qinmin): Remove this method as callers can retrieve the global
|
||||
// instance from SystemNetworkContextManager directly.
|
||||
SystemNetworkContextManager* system_network_context_manager() override;
|
||||
|
@ -136,7 +136,6 @@
|
||||
#include "components/prefs/pref_service.h"
|
||||
#include "components/prefs/pref_value_store.h"
|
||||
#include "components/prefs/scoped_user_pref_update.h"
|
||||
#include "components/rappor/rappor_service_impl.h"
|
||||
#include "components/site_isolation/site_isolation_policy.h"
|
||||
#include "components/spellcheck/spellcheck_buildflags.h"
|
||||
#include "components/startup_metric_utils/browser/startup_metric_utils.h"
|
||||
|
@ -300,7 +300,6 @@ source_set("chromeos") {
|
||||
"//components/printing/common:mojo_interfaces",
|
||||
"//components/proxy_config",
|
||||
"//components/quirks",
|
||||
"//components/rappor",
|
||||
"//components/renderer_context_menu",
|
||||
"//components/reporting/util:status",
|
||||
"//components/reporting/util:task_runner_context",
|
||||
|
@ -846,7 +846,6 @@ static_library("extensions") {
|
||||
"//components/pref_registry",
|
||||
"//components/privacy_sandbox:privacy_sandbox_prefs",
|
||||
"//components/proxy_config",
|
||||
"//components/rappor",
|
||||
"//components/resources",
|
||||
"//components/safe_browsing:buildflags",
|
||||
"//components/safe_browsing/content/web_ui:web_ui",
|
||||
|
@ -28,7 +28,6 @@
|
||||
#include "components/metrics/enabled_state_provider.h"
|
||||
#include "components/metrics/metrics_state_manager.h"
|
||||
#include "components/prefs/pref_service.h"
|
||||
#include "components/rappor/rappor_service_impl.h"
|
||||
#include "components/variations/service/variations_service.h"
|
||||
#include "components/variations/variations_associated_data.h"
|
||||
#include "components/version_info/version_info.h"
|
||||
@ -232,13 +231,6 @@ ChromeMetricsServicesManagerClient::GetEnabledStateProviderForTesting() {
|
||||
return *enabled_state_provider_;
|
||||
}
|
||||
|
||||
std::unique_ptr<rappor::RapporServiceImpl>
|
||||
ChromeMetricsServicesManagerClient::CreateRapporServiceImpl() {
|
||||
DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
|
||||
return std::make_unique<rappor::RapporServiceImpl>(
|
||||
local_state_, base::BindRepeating(&chrome::IsOffTheRecordSessionActive));
|
||||
}
|
||||
|
||||
std::unique_ptr<variations::VariationsService>
|
||||
ChromeMetricsServicesManagerClient::CreateVariationsService() {
|
||||
DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
|
||||
|
@ -76,7 +76,6 @@ class ChromeMetricsServicesManagerClient
|
||||
class ChromeEnabledStateProvider;
|
||||
|
||||
// metrics_services_manager::MetricsServicesManagerClient:
|
||||
std::unique_ptr<rappor::RapporServiceImpl> CreateRapporServiceImpl() override;
|
||||
std::unique_ptr<variations::VariationsService> CreateVariationsService()
|
||||
override;
|
||||
std::unique_ptr<metrics::MetricsServiceClient> CreateMetricsServiceClient()
|
||||
|
@ -46,7 +46,6 @@
|
||||
#include "components/page_load_metrics/browser/metrics_web_contents_observer.h"
|
||||
#include "components/page_load_metrics/browser/page_load_metrics_embedder_base.h"
|
||||
#include "components/page_load_metrics/browser/page_load_tracker.h"
|
||||
#include "components/rappor/rappor_service_impl.h"
|
||||
#include "content/public/browser/web_contents.h"
|
||||
#include "extensions/buildflags/buildflags.h"
|
||||
#include "url/gurl.h"
|
||||
|
@ -135,7 +135,6 @@
|
||||
#include "components/prefs/pref_service.h"
|
||||
#include "components/privacy_sandbox/privacy_sandbox_prefs.h"
|
||||
#include "components/proxy_config/pref_proxy_config_tracker_impl.h"
|
||||
#include "components/rappor/rappor_service_impl.h"
|
||||
#include "components/safe_browsing/core/common/safe_browsing_prefs.h"
|
||||
#include "components/search_engines/template_url_prepopulate_data.h"
|
||||
#include "components/security_interstitials/content/insecure_form_blocking_page.h"
|
||||
@ -538,6 +537,11 @@ const char kDataReductionProxyLastConfigRetrievalTime[] =
|
||||
"data_reduction.last_config_retrieval_time";
|
||||
const char kDataReductionProxyConfig[] = "data_reduction.config";
|
||||
|
||||
// Deprecated 2/2021.
|
||||
const char kRapporCohortSeed[] = "rappor.cohort_seed";
|
||||
const char kRapporLastDailySample[] = "rappor.last_daily_sample";
|
||||
const char kRapporSecret[] = "rappor.secret";
|
||||
|
||||
// Register local state used only for migration (clearing or moving to a new
|
||||
// key).
|
||||
void RegisterLocalStatePrefsForMigration(PrefRegistrySimple* registry) {
|
||||
@ -565,6 +569,10 @@ void RegisterLocalStatePrefsForMigration(PrefRegistrySimple* registry) {
|
||||
registry->RegisterListPref(enterprise_connectors::kOnBulkDataEntryPref);
|
||||
registry->RegisterListPref(enterprise_connectors::kOnSecurityEventPref);
|
||||
#endif // !defined(OS_ANDROID)
|
||||
|
||||
registry->RegisterIntegerPref(kRapporCohortSeed, -1);
|
||||
registry->RegisterInt64Pref(kRapporLastDailySample, 0);
|
||||
registry->RegisterStringPref(kRapporSecret, std::string());
|
||||
}
|
||||
|
||||
// Register prefs used only for migration (clearing or moving to a new key).
|
||||
@ -674,7 +682,6 @@ void RegisterLocalState(PrefRegistrySimple* registry) {
|
||||
ProfileInfoCache::RegisterPrefs(registry);
|
||||
ProfileNetworkContextService::RegisterLocalStatePrefs(registry);
|
||||
profiles::RegisterPrefs(registry);
|
||||
rappor::RapporServiceImpl::RegisterPrefs(registry);
|
||||
RegisterScreenshotPrefs(registry);
|
||||
safe_browsing::RegisterLocalStatePrefs(registry);
|
||||
secure_origin_allowlist::RegisterPrefs(registry);
|
||||
@ -1194,6 +1201,11 @@ void MigrateObsoleteLocalStatePrefs(PrefService* local_state) {
|
||||
local_state->ClearPref(enterprise_connectors::kOnSecurityEventPref);
|
||||
#endif // !defined(OS_ANDROID)
|
||||
|
||||
// Added 2/2021.
|
||||
local_state->ClearPref(kRapporCohortSeed);
|
||||
local_state->ClearPref(kRapporLastDailySample);
|
||||
local_state->ClearPref(kRapporSecret);
|
||||
|
||||
// Please don't delete the following line. It is used by PRESUBMIT.py.
|
||||
// END_MIGRATE_OBSOLETE_LOCAL_STATE_PREFS
|
||||
}
|
||||
|
@ -13,7 +13,6 @@
|
||||
#include "components/bookmarks/common/bookmark_pref_names.h"
|
||||
#include "components/content_settings/core/common/pref_names.h"
|
||||
#include "components/metrics/metrics_pref_names.h"
|
||||
#include "components/rappor/rappor_pref_names.h"
|
||||
#include "components/reading_list/core/reading_list_pref_names.h"
|
||||
#include "components/ukm/ukm_pref_names.h"
|
||||
|
||||
@ -144,12 +143,6 @@ const char* const kPersistentPrefNames[] = {
|
||||
prefs::kUseCustomChromeFrame,
|
||||
#endif
|
||||
|
||||
// Rappor preferences are not used in incognito mode, but they are written
|
||||
// in startup if they don't exist. So if the startup would be in incognito,
|
||||
// they need to be persisted.
|
||||
rappor::prefs::kRapporCohortSeed,
|
||||
rappor::prefs::kRapporSecret,
|
||||
|
||||
// Reading list preferences are common between incognito and regular mode.
|
||||
reading_list::prefs::kReadingListHasUnseenEntries,
|
||||
|
||||
|
@ -98,7 +98,7 @@ const char kEngineErrorCodeMetricName[] = "SoftwareReporter.EngineErrorCode";
|
||||
// SoftwareReporterLogsUploadResult enum defined in the histograms.xml file.
|
||||
const int kSwReporterLogsUploadResultMax = 30;
|
||||
|
||||
// Reports metrics about the software reporter via UMA (and sometimes Rappor).
|
||||
// Reports metrics about the software reporter via UMA.
|
||||
class UMAHistogramReporter {
|
||||
public:
|
||||
UMAHistogramReporter() : UMAHistogramReporter(std::string()) {}
|
||||
@ -171,7 +171,7 @@ class UMAHistogramReporter {
|
||||
reporter_key.DeleteValue(chrome_cleaner::kEngineErrorCodeValueName);
|
||||
}
|
||||
|
||||
// Reports UwS found by the software reporter tool via UMA and RAPPOR.
|
||||
// Reports UwS found by the software reporter tool via UMA.
|
||||
void ReportFoundUwS() const {
|
||||
base::win::RegKey reporter_key;
|
||||
std::vector<base::string16> found_uws_strings;
|
||||
|
@ -482,7 +482,6 @@ static_library("ui") {
|
||||
"//components/previews/core",
|
||||
"//components/proxy_config",
|
||||
"//components/query_parser",
|
||||
"//components/rappor",
|
||||
"//components/reading_list/core",
|
||||
"//components/reading_list/features:flags",
|
||||
"//components/renderer_context_menu",
|
||||
|
@ -370,7 +370,6 @@ void ContentSettingMixedScriptBubbleModel::OnLearnMoreClicked() {
|
||||
}
|
||||
|
||||
void ContentSettingMixedScriptBubbleModel::OnCustomLinkClicked() {
|
||||
DCHECK(rappor_service());
|
||||
MixedContentSettingsTabHelper* mixed_content_settings =
|
||||
MixedContentSettingsTabHelper::FromWebContents(web_contents());
|
||||
if (mixed_content_settings) {
|
||||
@ -1677,10 +1676,7 @@ ContentSettingBubbleModel::CreateContentSettingBubbleModel(
|
||||
|
||||
ContentSettingBubbleModel::ContentSettingBubbleModel(Delegate* delegate,
|
||||
WebContents* web_contents)
|
||||
: web_contents_(web_contents),
|
||||
owner_(nullptr),
|
||||
delegate_(delegate),
|
||||
rappor_service_(g_browser_process->rappor_service()) {
|
||||
: web_contents_(web_contents), owner_(nullptr), delegate_(delegate) {
|
||||
DCHECK(web_contents_);
|
||||
}
|
||||
|
||||
|
@ -37,10 +37,6 @@ namespace content {
|
||||
class WebContents;
|
||||
}
|
||||
|
||||
namespace rappor {
|
||||
class RapporServiceImpl;
|
||||
}
|
||||
|
||||
namespace ui {
|
||||
class Event;
|
||||
}
|
||||
@ -223,12 +219,6 @@ class ContentSettingBubbleModel {
|
||||
// Cast this bubble into ContentSettingNotificationsBubbleModel if possible.
|
||||
virtual ContentSettingNotificationsBubbleModel* AsNotificationsBubbleModel();
|
||||
|
||||
// Sets the Rappor service used for testing.
|
||||
void SetRapporServiceImplForTesting(
|
||||
rappor::RapporServiceImpl* rappor_service) {
|
||||
rappor_service_ = rappor_service;
|
||||
}
|
||||
|
||||
protected:
|
||||
// |web_contents| must outlive this.
|
||||
ContentSettingBubbleModel(Delegate* delegate,
|
||||
@ -281,15 +271,12 @@ class ContentSettingBubbleModel {
|
||||
void set_cancel_button_text(const base::string16& cancel_button_text) {
|
||||
bubble_content_.cancel_button_text = cancel_button_text;
|
||||
}
|
||||
rappor::RapporServiceImpl* rappor_service() const { return rappor_service_; }
|
||||
|
||||
private:
|
||||
content::WebContents* web_contents_;
|
||||
Owner* owner_;
|
||||
Delegate* delegate_;
|
||||
BubbleContent bubble_content_;
|
||||
// The service used to record Rappor metrics. Can be set for testing.
|
||||
rappor::RapporServiceImpl* rappor_service_;
|
||||
|
||||
DISALLOW_COPY_AND_ASSIGN(ContentSettingBubbleModel);
|
||||
};
|
||||
|
@ -259,7 +259,6 @@ component("vr_common") {
|
||||
"//chrome/common:constants",
|
||||
"//components/omnibox/browser",
|
||||
"//components/omnibox/browser",
|
||||
"//components/rappor/public:public",
|
||||
"//components/ukm/content",
|
||||
"//content/public/browser",
|
||||
"//device/base",
|
||||
@ -386,7 +385,6 @@ component("vr_base") {
|
||||
deps = [
|
||||
"//base",
|
||||
"//chrome/app:generated_resources",
|
||||
"//components/rappor:rappor",
|
||||
"//components/security_state/core",
|
||||
"//components/ukm/content",
|
||||
"//components/url_formatter",
|
||||
|
@ -40,7 +40,6 @@ include_rules = [
|
||||
"+components/plugins/renderer",
|
||||
"+components/printing/common",
|
||||
"+components/printing/renderer",
|
||||
"+components/rappor/public/mojom",
|
||||
"+components/safe_browsing/buildflags.h",
|
||||
"+components/safe_browsing/content/renderer",
|
||||
"+components/safe_browsing/content/common",
|
||||
|
@ -233,7 +233,6 @@ static_library("test_support") {
|
||||
"//components/performance_manager/test_support",
|
||||
"//components/permissions:test_support",
|
||||
"//components/prefs:test_support",
|
||||
"//components/rappor:test_support",
|
||||
"//components/safe_browsing/core/db:v4_test_util",
|
||||
"//components/search_engines:test_support",
|
||||
"//components/sessions:test_support",
|
||||
|
@ -155,10 +155,6 @@ metrics::MetricsService* TestingBrowserProcess::metrics_service() {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
rappor::RapporServiceImpl* TestingBrowserProcess::rappor_service() {
|
||||
return rappor_service_;
|
||||
}
|
||||
|
||||
SystemNetworkContextManager*
|
||||
TestingBrowserProcess::system_network_context_manager() {
|
||||
return nullptr;
|
||||
@ -510,11 +506,6 @@ void TestingBrowserProcess::SetFlocSortingLshClustersService(
|
||||
floc_sorting_lsh_clusters_service_.swap(service);
|
||||
}
|
||||
|
||||
void TestingBrowserProcess::SetRapporServiceImpl(
|
||||
rappor::RapporServiceImpl* rappor_service) {
|
||||
rappor_service_ = rappor_service;
|
||||
}
|
||||
|
||||
void TestingBrowserProcess::SetShuttingDown(bool is_shutting_down) {
|
||||
is_shutting_down_ = is_shutting_down;
|
||||
}
|
||||
|
@ -81,7 +81,6 @@ class TestingBrowserProcess : public BrowserProcess {
|
||||
metrics_services_manager::MetricsServicesManager* GetMetricsServicesManager()
|
||||
override;
|
||||
metrics::MetricsService* metrics_service() override;
|
||||
rappor::RapporServiceImpl* rappor_service() override;
|
||||
SystemNetworkContextManager* system_network_context_manager() override;
|
||||
scoped_refptr<network::SharedURLLoaderFactory> shared_url_loader_factory()
|
||||
override;
|
||||
@ -165,7 +164,6 @@ class TestingBrowserProcess : public BrowserProcess {
|
||||
std::unique_ptr<NotificationPlatformBridge> notification_platform_bridge);
|
||||
void SetSystemNotificationHelper(
|
||||
std::unique_ptr<SystemNotificationHelper> system_notification_helper);
|
||||
void SetRapporServiceImpl(rappor::RapporServiceImpl* rappor_service);
|
||||
void SetShuttingDown(bool is_shutting_down);
|
||||
void ShutdownBrowserPolicyConnector();
|
||||
TestingBrowserProcessPlatformPart* GetTestPlatformPart();
|
||||
@ -214,7 +212,6 @@ class TestingBrowserProcess : public BrowserProcess {
|
||||
// The following objects are not owned by TestingBrowserProcess:
|
||||
PrefService* local_state_ = nullptr;
|
||||
scoped_refptr<network::SharedURLLoaderFactory> shared_url_loader_factory_;
|
||||
rappor::RapporServiceImpl* rappor_service_ = nullptr;
|
||||
|
||||
std::unique_ptr<TestingBrowserProcessPlatformPart> platform_part_;
|
||||
std::unique_ptr<network::TestNetworkConnectionTracker>
|
||||
|
@ -814,12 +814,6 @@ FILES = [
|
||||
'archive': 'metrics-metadata.zip',
|
||||
'optional': ['dev', 'official'],
|
||||
},
|
||||
{
|
||||
'filename': 'rappor.xml',
|
||||
'buildtype': ['dev', 'official'],
|
||||
'archive': 'metrics-metadata.zip',
|
||||
'optional': ['dev', 'official'],
|
||||
},
|
||||
{
|
||||
'filename': 'ukm.xml',
|
||||
'buildtype': ['dev', 'official'],
|
||||
|
@ -131,7 +131,6 @@ test("components_unittests") {
|
||||
"//components/proxy_config:unit_tests",
|
||||
"//components/qr_code_generator:unit_tests",
|
||||
"//components/query_parser:unit_tests",
|
||||
"//components/rappor:unit_tests",
|
||||
"//components/reading_list/core:unit_tests",
|
||||
"//components/reporting/encryption:unit_tests",
|
||||
"//components/reporting/storage:unit_tests",
|
||||
|
@ -40,9 +40,6 @@ const base::Feature kHttpRetryFeature{"UMAHttpRetry",
|
||||
// ablate a clients upload of all logs that use |metrics::ReportingService|
|
||||
// to upload logs. This include |metrics::MetricsReportingService| for uploading
|
||||
// UMA logs. |ukm::UKMReportionService| for uploading UKM logs.
|
||||
// Rappor service use |rappor::LogUploader| which is not a
|
||||
// |metrics::ReportingService| so, it won't be ablated.
|
||||
// similar frequency.
|
||||
// To restrict the study to UMA or UKM, set the "service-affected" param.
|
||||
const base::Feature kAblateMetricsLogUploadFeature{
|
||||
"AblateMetricsLogUpload", base::FEATURE_DISABLED_BY_DEFAULT};
|
||||
|
@ -12,7 +12,6 @@ static_library("metrics_services_manager") {
|
||||
deps = [
|
||||
"//base",
|
||||
"//components/metrics",
|
||||
"//components/rappor",
|
||||
"//components/ukm",
|
||||
"//components/variations",
|
||||
"//components/variations/service",
|
||||
|
@ -2,7 +2,6 @@ include_rules = [
|
||||
"-components",
|
||||
"+components/metrics",
|
||||
"+components/metrics_services_manager",
|
||||
"+components/rappor",
|
||||
"+components/ukm",
|
||||
"+components/variations",
|
||||
"+services/network",
|
||||
|
@ -15,7 +15,6 @@
|
||||
#include "components/metrics/metrics_state_manager.h"
|
||||
#include "components/metrics/metrics_switches.h"
|
||||
#include "components/metrics_services_manager/metrics_services_manager_client.h"
|
||||
#include "components/rappor/rappor_service_impl.h"
|
||||
#include "components/ukm/ukm_service.h"
|
||||
#include "components/variations/service/variations_service.h"
|
||||
#include "services/network/public/cpp/shared_url_loader_factory.h"
|
||||
@ -43,15 +42,6 @@ metrics::MetricsService* MetricsServicesManager::GetMetricsService() {
|
||||
return GetMetricsServiceClient()->GetMetricsService();
|
||||
}
|
||||
|
||||
rappor::RapporServiceImpl* MetricsServicesManager::GetRapporServiceImpl() {
|
||||
DCHECK(thread_checker_.CalledOnValidThread());
|
||||
if (!rappor_service_) {
|
||||
rappor_service_ = client_->CreateRapporServiceImpl();
|
||||
rappor_service_->Initialize(client_->GetURLLoaderFactory());
|
||||
}
|
||||
return rappor_service_.get();
|
||||
}
|
||||
|
||||
ukm::UkmService* MetricsServicesManager::GetUkmService() {
|
||||
DCHECK(thread_checker_.CalledOnValidThread());
|
||||
return GetMetricsServiceClient()->GetUkmService();
|
||||
@ -100,8 +90,8 @@ void MetricsServicesManager::UpdatePermissions(bool current_may_record,
|
||||
}
|
||||
}
|
||||
|
||||
// Stash the current permissions so that we can update the RapporServiceImpl
|
||||
// correctly when the Rappor preference changes.
|
||||
// Stash the current permissions so that we can update the services correctly
|
||||
// when preferences change.
|
||||
may_record_ = current_may_record;
|
||||
consent_given_ = current_consent_given;
|
||||
may_upload_ = current_may_upload;
|
||||
@ -115,7 +105,6 @@ void MetricsServicesManager::UpdateRunningServices() {
|
||||
const base::CommandLine* cmdline = base::CommandLine::ForCurrentProcess();
|
||||
if (cmdline->HasSwitch(metrics::switches::kMetricsRecordingOnly)) {
|
||||
metrics->StartRecordingForTests();
|
||||
GetRapporServiceImpl()->Update(true, false);
|
||||
return;
|
||||
}
|
||||
|
||||
@ -133,8 +122,6 @@ void MetricsServicesManager::UpdateRunningServices() {
|
||||
}
|
||||
|
||||
UpdateUkmService();
|
||||
|
||||
GetRapporServiceImpl()->Update(may_record_, may_upload_);
|
||||
}
|
||||
|
||||
void MetricsServicesManager::UpdateUkmService() {
|
||||
|
@ -20,10 +20,6 @@ class MetricsService;
|
||||
class MetricsServiceClient;
|
||||
}
|
||||
|
||||
namespace rappor {
|
||||
class RapporServiceImpl;
|
||||
}
|
||||
|
||||
namespace ukm {
|
||||
class UkmService;
|
||||
}
|
||||
@ -38,7 +34,7 @@ class MetricsServicesManagerClient;
|
||||
|
||||
// MetricsServicesManager is a helper class for embedders that use the various
|
||||
// metrics-related services in a Chrome-like fashion: MetricsService (via its
|
||||
// client), RapporServiceImpl and VariationsService.
|
||||
// client) and VariationsService.
|
||||
class MetricsServicesManager {
|
||||
public:
|
||||
// Creates the MetricsServicesManager with the given client.
|
||||
@ -60,9 +56,6 @@ class MetricsServicesManager {
|
||||
// additionally creating the MetricsServiceClient in that case).
|
||||
metrics::MetricsService* GetMetricsService();
|
||||
|
||||
// Returns the RapporServiceImpl, creating it if it hasn't been created yet.
|
||||
rappor::RapporServiceImpl* GetRapporServiceImpl();
|
||||
|
||||
// Returns the UkmService, creating it if it hasn't been created yet.
|
||||
ukm::UkmService* GetUkmService();
|
||||
|
||||
@ -86,10 +79,6 @@ class MetricsServicesManager {
|
||||
bool IsMetricsConsentGiven() const;
|
||||
|
||||
private:
|
||||
// Update the managed services when permissions for recording/uploading
|
||||
// metrics change.
|
||||
void UpdateRapporServiceImpl();
|
||||
|
||||
// Returns the MetricsServiceClient, creating it if it hasn't been
|
||||
// created yet (and additionally creating the MetricsService in that case).
|
||||
metrics::MetricsServiceClient* GetMetricsServiceClient();
|
||||
@ -124,9 +113,6 @@ class MetricsServicesManager {
|
||||
// The MetricsServiceClient. Owns the MetricsService.
|
||||
std::unique_ptr<metrics::MetricsServiceClient> metrics_service_client_;
|
||||
|
||||
// The RapporServiceImpl, for RAPPOR metric uploads.
|
||||
std::unique_ptr<rappor::RapporServiceImpl> rappor_service_;
|
||||
|
||||
// The VariationsService, for server-side experiments infrastructure.
|
||||
std::unique_ptr<variations::VariationsService> variations_service_;
|
||||
|
||||
|
@ -19,10 +19,6 @@ namespace network {
|
||||
class SharedURLLoaderFactory;
|
||||
}
|
||||
|
||||
namespace rappor {
|
||||
class RapporServiceImpl;
|
||||
}
|
||||
|
||||
namespace variations {
|
||||
class VariationsService;
|
||||
}
|
||||
@ -36,8 +32,6 @@ class MetricsServicesManagerClient {
|
||||
virtual ~MetricsServicesManagerClient() {}
|
||||
|
||||
// Methods that create the various services in the context of the embedder.
|
||||
virtual std::unique_ptr<rappor::RapporServiceImpl>
|
||||
CreateRapporServiceImpl() = 0;
|
||||
virtual std::unique_ptr<variations::VariationsService>
|
||||
CreateVariationsService() = 0;
|
||||
virtual std::unique_ptr<metrics::MetricsServiceClient>
|
||||
|
@ -58,7 +58,6 @@ static_library("ntp_tiles") {
|
||||
"//components/image_fetcher/core",
|
||||
"//components/pref_registry",
|
||||
"//components/prefs",
|
||||
"//components/rappor/public",
|
||||
"//components/resources",
|
||||
"//components/search",
|
||||
"//components/search_engines",
|
||||
@ -101,7 +100,6 @@ source_set("unit_tests") {
|
||||
"//components/image_fetcher/core",
|
||||
"//components/image_fetcher/core:test_support",
|
||||
"//components/pref_registry:pref_registry",
|
||||
"//components/rappor:test_support",
|
||||
"//components/sync_preferences:test_support",
|
||||
"//net:test_support",
|
||||
"//services/data_decoder/public/cpp:test_support",
|
||||
|
@ -8,7 +8,6 @@ include_rules = [
|
||||
"+components/image_fetcher",
|
||||
"+components/pref_registry",
|
||||
"+components/prefs",
|
||||
"+components/rappor",
|
||||
"+components/search_engines",
|
||||
"+components/search",
|
||||
"+components/strings/grit/components_strings.h",
|
||||
|
@ -1,101 +0,0 @@
|
||||
# Copyright 2014 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.
|
||||
|
||||
import("//testing/test.gni")
|
||||
|
||||
static_library("rappor") {
|
||||
sources = [
|
||||
"bloom_filter.cc",
|
||||
"bloom_filter.h",
|
||||
"byte_vector_utils.cc",
|
||||
"byte_vector_utils.h",
|
||||
"log_uploader.cc",
|
||||
"log_uploader.h",
|
||||
"log_uploader_interface.h",
|
||||
"rappor_metric.cc",
|
||||
"rappor_metric.h",
|
||||
"rappor_parameters.cc",
|
||||
"rappor_pref_names.cc",
|
||||
"rappor_pref_names.h",
|
||||
"rappor_prefs.cc",
|
||||
"rappor_prefs.h",
|
||||
"rappor_service_impl.cc",
|
||||
"rappor_service_impl.h",
|
||||
"rappor_utils.cc",
|
||||
"reports.cc",
|
||||
"reports.h",
|
||||
"sample.cc",
|
||||
"sampler.cc",
|
||||
"sampler.h",
|
||||
]
|
||||
|
||||
public_deps = [
|
||||
"//components/rappor/proto",
|
||||
"//components/rappor/public",
|
||||
]
|
||||
|
||||
deps = [
|
||||
"//base",
|
||||
"//components/metrics",
|
||||
"//components/prefs",
|
||||
"//components/variations",
|
||||
"//crypto",
|
||||
"//net",
|
||||
"//services/network/public/cpp:cpp",
|
||||
]
|
||||
}
|
||||
|
||||
static_library("test_support") {
|
||||
testonly = true
|
||||
sources = [
|
||||
"test_log_uploader.cc",
|
||||
"test_log_uploader.h",
|
||||
"test_rappor_service.cc",
|
||||
"test_rappor_service.h",
|
||||
]
|
||||
|
||||
public_deps = [ ":rappor" ]
|
||||
deps = [
|
||||
"//base",
|
||||
"//components/prefs:test_support",
|
||||
]
|
||||
}
|
||||
|
||||
source_set("unit_tests") {
|
||||
testonly = true
|
||||
sources = [
|
||||
"bloom_filter_unittest.cc",
|
||||
"byte_vector_utils_unittest.cc",
|
||||
"log_uploader_unittest.cc",
|
||||
"rappor_metric_unittest.cc",
|
||||
"rappor_prefs_unittest.cc",
|
||||
"rappor_service_unittest.cc",
|
||||
"rappor_utils_unittest.cc",
|
||||
"reports_unittest.cc",
|
||||
"sampler_unittest.cc",
|
||||
]
|
||||
|
||||
deps = [
|
||||
":rappor",
|
||||
":test_support",
|
||||
"//base",
|
||||
"//base/test:test_support",
|
||||
"//components/metrics",
|
||||
"//components/prefs:test_support",
|
||||
"//net:test_support",
|
||||
"//services/network:test_support",
|
||||
"//services/network/public/cpp:cpp",
|
||||
"//testing/gtest",
|
||||
"//url",
|
||||
]
|
||||
}
|
||||
|
||||
# Convenience testing target
|
||||
test("rappor_unittests") {
|
||||
sources = [ "//components/test/run_all_unittests.cc" ]
|
||||
deps = [
|
||||
":unit_tests",
|
||||
"//components/test:test_support",
|
||||
]
|
||||
}
|
@ -1,10 +0,0 @@
|
||||
include_rules = [
|
||||
"+components/metrics",
|
||||
"+components/prefs",
|
||||
"+components/variations",
|
||||
"+crypto",
|
||||
"+mojo/public/cpp",
|
||||
"+net",
|
||||
"+services/network",
|
||||
"+third_party/smhasher",
|
||||
]
|
@ -1,3 +0,0 @@
|
||||
monorail {
|
||||
component: "Internals>Metrics"
|
||||
}
|
@ -1,2 +0,0 @@
|
||||
asvitkine@chromium.org
|
||||
holte@chromium.org
|
@ -1,9 +0,0 @@
|
||||
# Rappor (Randomized Aggregatable Privacy Preserving Ordinal Responses)
|
||||
|
||||
RAPPOR reports consist of randomly generated data that is biased based on data
|
||||
collected from the user. Data from many users can be aggregated to learn
|
||||
information about the population, but little or nothing can be concluded about
|
||||
individual users from their reports.
|
||||
|
||||
Documentation:
|
||||
http://www.chromium.org/developers/design-documents/rappor
|
@ -1,71 +0,0 @@
|
||||
// Copyright 2014 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/rappor/bloom_filter.h"
|
||||
|
||||
#include <stddef.h>
|
||||
|
||||
#include "base/check_op.h"
|
||||
#include "base/containers/span.h"
|
||||
#include "base/hash/legacy_hash.h"
|
||||
#include "base/numerics/safe_conversions.h"
|
||||
|
||||
namespace rappor {
|
||||
|
||||
namespace {
|
||||
|
||||
uint32_t ComputeHash(const std::string& str, uint32_t seed) {
|
||||
// Using CityHash here because we have support for it in Dremel. Many hash
|
||||
// functions, such as MD5, SHA1, or Murmur, would probably also work.
|
||||
return base::legacy::CityHash64WithSeed(
|
||||
base::as_bytes(base::make_span(str)), seed);
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
BloomFilter::BloomFilter(size_t bytes_size,
|
||||
uint32_t hash_function_count,
|
||||
uint32_t hash_seed_offset)
|
||||
: bytes_(bytes_size),
|
||||
hash_function_count_(hash_function_count),
|
||||
hash_seed_offset_(hash_seed_offset) {
|
||||
DCHECK_GT(bytes_size, 0u);
|
||||
}
|
||||
|
||||
BloomFilter::~BloomFilter() {}
|
||||
|
||||
void BloomFilter::SetString(const std::string& str) {
|
||||
for (size_t i = 0; i < bytes_.size(); ++i) {
|
||||
bytes_[i] = 0;
|
||||
}
|
||||
for (size_t i = 0; i < hash_function_count_; ++i) {
|
||||
uint32_t index = ComputeHash(str, hash_seed_offset_ + i);
|
||||
// Note that the "bytes" are uint8_t, so they are always 8-bits.
|
||||
uint32_t byte_index = (index / 8) % bytes_.size();
|
||||
uint32_t bit_index = index % 8;
|
||||
bytes_[byte_index] |= 1 << bit_index;
|
||||
}
|
||||
}
|
||||
|
||||
namespace internal {
|
||||
|
||||
uint64_t GetBloomBits(size_t bytes_size,
|
||||
uint32_t hash_function_count,
|
||||
uint32_t hash_seed_offset,
|
||||
const std::string& str) {
|
||||
// Make sure result fits in uint64_t.
|
||||
DCHECK_LE(bytes_size, 8u);
|
||||
uint64_t output = 0;
|
||||
const uint64_t bits_size = base::strict_cast<uint64_t>(bytes_size) * 8;
|
||||
for (size_t i = 0; i < hash_function_count; ++i) {
|
||||
uint64_t index = base::strict_cast<uint64_t>(
|
||||
ComputeHash(str, hash_seed_offset + i));
|
||||
output |= 1ULL << (index % bits_size);
|
||||
}
|
||||
return output;
|
||||
}
|
||||
|
||||
} // namespace internal
|
||||
|
||||
} // namespace rappor
|
@ -1,61 +0,0 @@
|
||||
// Copyright 2014 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.
|
||||
|
||||
#ifndef COMPONENTS_RAPPOR_BLOOM_FILTER_H_
|
||||
#define COMPONENTS_RAPPOR_BLOOM_FILTER_H_
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
#include <string>
|
||||
|
||||
#include "base/macros.h"
|
||||
#include "components/rappor/byte_vector_utils.h"
|
||||
|
||||
namespace rappor {
|
||||
|
||||
// BloomFilter is a simple Bloom filter for keeping track of a set of strings.
|
||||
class BloomFilter {
|
||||
public:
|
||||
// Constructs a BloomFilter using |bytes_size| bytes of Bloom filter bits,
|
||||
// and |hash_function_count| hash functions to set bits in the filter. The
|
||||
// hash functions will be generated by using seeds in the range
|
||||
// |hash_seed_offset| to (|hash_seed_offset| + |hash_function_count|).
|
||||
BloomFilter(size_t bytes_size,
|
||||
uint32_t hash_function_count,
|
||||
uint32_t hash_seed_offset);
|
||||
~BloomFilter();
|
||||
|
||||
// Sets the Bloom filter bits to contain a single string.
|
||||
void SetString(const std::string& str);
|
||||
|
||||
// Returns the current value of the Bloom filter's bit array.
|
||||
const ByteVector& bytes() const { return bytes_; }
|
||||
|
||||
private:
|
||||
// Stores the byte array of the Bloom filter.
|
||||
ByteVector bytes_;
|
||||
|
||||
// The number of bits to set for each string added.
|
||||
uint32_t hash_function_count_;
|
||||
|
||||
// A number add to a hash function index to get a seed for that hash function.
|
||||
uint32_t hash_seed_offset_;
|
||||
|
||||
DISALLOW_COPY_AND_ASSIGN(BloomFilter);
|
||||
};
|
||||
|
||||
|
||||
namespace internal {
|
||||
|
||||
// A function for getting bloom filters less than or equal to 64 bits.
|
||||
uint64_t GetBloomBits(size_t bytes_size,
|
||||
uint32_t hash_function_count,
|
||||
uint32_t hash_seed_offset,
|
||||
const std::string& str);
|
||||
|
||||
} // namespace internal
|
||||
|
||||
} // namespace rappor
|
||||
|
||||
#endif // COMPONENTS_RAPPOR_BLOOM_FILTER_H_
|
@ -1,67 +0,0 @@
|
||||
// Copyright 2014 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/rappor/bloom_filter.h"
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
#include "components/rappor/byte_vector_utils.h"
|
||||
#include "testing/gtest/include/gtest/gtest.h"
|
||||
|
||||
namespace rappor {
|
||||
|
||||
TEST(BloomFilterTest, TinyFilter) {
|
||||
BloomFilter filter(1u, 4u, 0u);
|
||||
|
||||
// Size is 1 and it's initially empty
|
||||
EXPECT_EQ(1u, filter.bytes().size());
|
||||
EXPECT_EQ(0x00, filter.bytes()[0]);
|
||||
|
||||
// "Test" has a self-collision, and only sets 3 bits.
|
||||
filter.SetString("Test");
|
||||
EXPECT_EQ(0x2a, filter.bytes()[0]);
|
||||
|
||||
// Setting the same value shouldn't change anything.
|
||||
filter.SetString("Test");
|
||||
EXPECT_EQ(0x2a, filter.bytes()[0]);
|
||||
|
||||
BloomFilter filter2(1u, 4u, 0u);
|
||||
EXPECT_EQ(0x00, filter2.bytes()[0]);
|
||||
filter2.SetString("Bar");
|
||||
EXPECT_EQ(0xa8, filter2.bytes()[0]);
|
||||
|
||||
// The new string should replace the old one.
|
||||
filter.SetString("Bar");
|
||||
EXPECT_EQ(0xa8, filter.bytes()[0]);
|
||||
}
|
||||
|
||||
TEST(BloomFilterTest, HugeFilter) {
|
||||
// Create a 500 bit filter, and use a large seed offset to see if anything
|
||||
// breaks.
|
||||
BloomFilter filter(500u, 1u, 0xabdef123);
|
||||
|
||||
// Size is 500 and it's initially empty
|
||||
EXPECT_EQ(500u, filter.bytes().size());
|
||||
EXPECT_EQ(0, CountBits(filter.bytes()));
|
||||
|
||||
filter.SetString("Bar");
|
||||
EXPECT_EQ(1, CountBits(filter.bytes()));
|
||||
|
||||
// Adding the same value shouldn't change anything.
|
||||
filter.SetString("Bar");
|
||||
EXPECT_EQ(1, CountBits(filter.bytes()));
|
||||
}
|
||||
|
||||
TEST(BloomFilterTest, GetBloomBitsSmall) {
|
||||
uint64_t bytes_from_get = internal::GetBloomBits(1u, 4u, 0u, "Bar");
|
||||
EXPECT_EQ(0xa8u, bytes_from_get);
|
||||
}
|
||||
|
||||
TEST(BloomFilterTest, GetBloomBitsLarge) {
|
||||
// Make sure that a 64-bit bloom filter can set the full range of bits.
|
||||
uint64_t bytes_from_get = internal::GetBloomBits(8u, 1024u, 0u, "Bar");
|
||||
EXPECT_EQ(0xffffffffffffffffu, bytes_from_get);
|
||||
}
|
||||
|
||||
} // namespace rappor
|
@ -1,249 +0,0 @@
|
||||
// Copyright 2014 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/rappor/byte_vector_utils.h"
|
||||
|
||||
#include <string.h>
|
||||
#include <algorithm>
|
||||
#include <string>
|
||||
|
||||
#include "base/check_op.h"
|
||||
#include "base/notreached.h"
|
||||
#include "base/rand_util.h"
|
||||
#include "base/strings/strcat.h"
|
||||
#include "base/strings/string_number_conversions.h"
|
||||
#include "crypto/random.h"
|
||||
|
||||
namespace rappor {
|
||||
|
||||
namespace {
|
||||
|
||||
// Reinterpets a ByteVector as a StringPiece.
|
||||
base::StringPiece ByteVectorAsStringPiece(const ByteVector& lhs) {
|
||||
return base::StringPiece(reinterpret_cast<const char *>(&lhs[0]), lhs.size());
|
||||
}
|
||||
|
||||
// Concatenates parameters together as a string.
|
||||
std::string Concat(const ByteVector& value, char c, base::StringPiece data) {
|
||||
return base::StrCat(
|
||||
{ByteVectorAsStringPiece(value), base::StringPiece(&c, 1), data});
|
||||
}
|
||||
|
||||
// Performs the operation: K = HMAC(K, data)
|
||||
// The input "K" is passed by initializing |hmac| with it.
|
||||
// The output "K" is returned by initializing |result| with it.
|
||||
// Returns false on an error.
|
||||
bool HMAC_Rotate(const crypto::HMAC& hmac,
|
||||
const std::string& data,
|
||||
crypto::HMAC* result) {
|
||||
ByteVector key(hmac.DigestLength());
|
||||
if (!hmac.Sign(data, &key[0], key.size()))
|
||||
return false;
|
||||
return result->Init(ByteVectorAsStringPiece(key));
|
||||
}
|
||||
|
||||
// Performs the operation: V = HMAC(K, V)
|
||||
// The input "K" is passed by initializing |hmac| with it.
|
||||
// "V" is read from and written to |value|.
|
||||
// Returns false on an error.
|
||||
bool HMAC_Rehash(const crypto::HMAC& hmac, ByteVector* value) {
|
||||
return hmac.Sign(ByteVectorAsStringPiece(*value),
|
||||
&(*value)[0], value->size());
|
||||
}
|
||||
|
||||
// Implements (Key, V) = HMAC_DRBG_Update(provided_data, Key, V)
|
||||
// See: http://csrc.nist.gov/publications/nistpubs/800-90A/SP800-90A.pdf
|
||||
// "V" is read from and written to |value|.
|
||||
// The input "Key" is passed by initializing |hmac1| with it.
|
||||
// The output "Key" is returned by initializing |out_hmac| with it.
|
||||
// Returns false on an error.
|
||||
bool HMAC_DRBG_Update(base::StringPiece provided_data,
|
||||
const crypto::HMAC& hmac1,
|
||||
ByteVector* value,
|
||||
crypto::HMAC* out_hmac) {
|
||||
// HMAC_DRBG Update Process
|
||||
crypto::HMAC temp_hmac(crypto::HMAC::SHA256);
|
||||
crypto::HMAC* hmac2 = provided_data.size() > 0 ? &temp_hmac : out_hmac;
|
||||
// 1. K = HMAC(K, V || 0x00 || provided_data)
|
||||
if (!HMAC_Rotate(hmac1, Concat(*value, 0x00, provided_data), hmac2))
|
||||
return false;
|
||||
// 2. V = HMAC(K, V)
|
||||
if (!HMAC_Rehash(*hmac2, value))
|
||||
return false;
|
||||
// 3. If (provided_data = Null), then return K and V.
|
||||
if (hmac2 == out_hmac)
|
||||
return true;
|
||||
// 4. K = HMAC(K, V || 0x01 || provided_data)
|
||||
if (!HMAC_Rotate(*hmac2, Concat(*value, 0x01, provided_data), out_hmac))
|
||||
return false;
|
||||
// 5. V = HMAC(K, V)
|
||||
return HMAC_Rehash(*out_hmac, value);
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
void Uint64ToByteVector(uint64_t value, size_t size, ByteVector* output) {
|
||||
DCHECK_LE(size, 8u);
|
||||
DCHECK_EQ(size, output->size());
|
||||
for (size_t i = 0; i < size; i++) {
|
||||
// Get the value of the i-th smallest byte and copy it to the byte vector.
|
||||
uint64_t shift = i * 8;
|
||||
uint64_t byte_mask = static_cast<uint64_t>(0xff) << shift;
|
||||
(*output)[i] = (value & byte_mask) >> shift;
|
||||
}
|
||||
}
|
||||
|
||||
ByteVector* ByteVectorAnd(const ByteVector& lhs, ByteVector* rhs) {
|
||||
DCHECK_EQ(lhs.size(), rhs->size());
|
||||
for (size_t i = 0; i < lhs.size(); ++i) {
|
||||
(*rhs)[i] = lhs[i] & (*rhs)[i];
|
||||
}
|
||||
return rhs;
|
||||
}
|
||||
|
||||
ByteVector* ByteVectorOr(const ByteVector& lhs, ByteVector* rhs) {
|
||||
DCHECK_EQ(lhs.size(), rhs->size());
|
||||
for (size_t i = 0; i < lhs.size(); ++i) {
|
||||
(*rhs)[i] = lhs[i] | (*rhs)[i];
|
||||
}
|
||||
return rhs;
|
||||
}
|
||||
|
||||
ByteVector* ByteVectorMerge(const ByteVector& mask,
|
||||
const ByteVector& lhs,
|
||||
ByteVector* rhs) {
|
||||
DCHECK_EQ(lhs.size(), rhs->size());
|
||||
for (size_t i = 0; i < lhs.size(); ++i) {
|
||||
(*rhs)[i] = (lhs[i] & ~mask[i]) | ((*rhs)[i] & mask[i]);
|
||||
}
|
||||
return rhs;
|
||||
}
|
||||
|
||||
int CountBits(const ByteVector& vector) {
|
||||
int bit_count = 0;
|
||||
for (size_t i = 0; i < vector.size(); ++i) {
|
||||
uint8_t byte = vector[i];
|
||||
for (int j = 0; j < 8 ; ++j) {
|
||||
if (byte & (1 << j))
|
||||
bit_count++;
|
||||
}
|
||||
}
|
||||
return bit_count;
|
||||
}
|
||||
|
||||
ByteVectorGenerator::ByteVectorGenerator(size_t byte_count)
|
||||
: byte_count_(byte_count) {}
|
||||
|
||||
ByteVectorGenerator::~ByteVectorGenerator() {}
|
||||
|
||||
ByteVector ByteVectorGenerator::GetRandomByteVector() {
|
||||
ByteVector bytes(byte_count_);
|
||||
crypto::RandBytes(&bytes[0], bytes.size());
|
||||
return bytes;
|
||||
}
|
||||
|
||||
ByteVector ByteVectorGenerator::GetWeightedRandomByteVector(
|
||||
Probability probability) {
|
||||
switch (probability) {
|
||||
case PROBABILITY_100:
|
||||
return ByteVector(byte_count_, 0xff);
|
||||
case PROBABILITY_75: {
|
||||
ByteVector bytes = GetRandomByteVector();
|
||||
return *ByteVectorOr(GetRandomByteVector(), &bytes);
|
||||
}
|
||||
case PROBABILITY_50:
|
||||
return GetRandomByteVector();
|
||||
case PROBABILITY_25: {
|
||||
ByteVector bytes = GetRandomByteVector();
|
||||
return *ByteVectorAnd(GetRandomByteVector(), &bytes);
|
||||
}
|
||||
case PROBABILITY_0:
|
||||
return ByteVector(byte_count_);
|
||||
}
|
||||
NOTREACHED();
|
||||
return ByteVector(byte_count_);
|
||||
}
|
||||
|
||||
HmacByteVectorGenerator::HmacByteVectorGenerator(
|
||||
size_t byte_count,
|
||||
const std::string& entropy_input,
|
||||
base::StringPiece personalization_string)
|
||||
: ByteVectorGenerator(byte_count),
|
||||
hmac_(crypto::HMAC::SHA256),
|
||||
value_(hmac_.DigestLength(), 0x01),
|
||||
generated_bytes_(0) {
|
||||
// HMAC_DRBG Instantiate Process
|
||||
// See: http://csrc.nist.gov/publications/nistpubs/800-90A/SP800-90A.pdf
|
||||
// 1. seed_material = entropy_input + nonce + personalization_string
|
||||
// Note: We are using the 8.6.7 interpretation, where the entropy_input and
|
||||
// nonce are acquired at the same time from the same source.
|
||||
DCHECK_EQ(kEntropyInputSize, entropy_input.size());
|
||||
std::string seed_material =
|
||||
base::StrCat({entropy_input, personalization_string});
|
||||
// 2. Key = 0x00 00...00
|
||||
crypto::HMAC hmac1(crypto::HMAC::SHA256);
|
||||
if (!hmac1.Init(std::string(hmac_.DigestLength(), 0x00)))
|
||||
NOTREACHED();
|
||||
// 3. V = 0x01 01...01
|
||||
// (value_ in initializer list)
|
||||
|
||||
// 4. (Key, V) = HMAC_DRBG_Update(seed_material, Key, V)
|
||||
if (!HMAC_DRBG_Update(seed_material, hmac1, &value_, &hmac_))
|
||||
NOTREACHED();
|
||||
}
|
||||
|
||||
HmacByteVectorGenerator::~HmacByteVectorGenerator() {}
|
||||
|
||||
HmacByteVectorGenerator::HmacByteVectorGenerator(
|
||||
const HmacByteVectorGenerator& prev_request)
|
||||
: ByteVectorGenerator(prev_request.byte_count()),
|
||||
hmac_(crypto::HMAC::SHA256),
|
||||
value_(prev_request.value_),
|
||||
generated_bytes_(0) {
|
||||
if (!HMAC_DRBG_Update("", prev_request.hmac_, &value_, &hmac_))
|
||||
NOTREACHED();
|
||||
}
|
||||
|
||||
// HMAC_DRBG requires entropy input to be security_strength bits long,
|
||||
// and nonce to be at least 1/2 security_strength bits long. We
|
||||
// generate them both as a single "extra strong" entropy input.
|
||||
// max_security_strength for SHA256 is 256 bits.
|
||||
// See: http://csrc.nist.gov/publications/nistpubs/800-90A/SP800-90A.pdf
|
||||
const size_t HmacByteVectorGenerator::kEntropyInputSize = (256 / 8) * 3 / 2;
|
||||
|
||||
// static
|
||||
std::string HmacByteVectorGenerator::GenerateEntropyInput() {
|
||||
return base::RandBytesAsString(kEntropyInputSize);
|
||||
}
|
||||
|
||||
ByteVector HmacByteVectorGenerator::GetRandomByteVector() {
|
||||
// Streams bytes from HMAC_DRBG_Generate
|
||||
// See: http://csrc.nist.gov/publications/nistpubs/800-90A/SP800-90A.pdf
|
||||
const size_t digest_length = hmac_.DigestLength();
|
||||
DCHECK_EQ(value_.size(), digest_length);
|
||||
ByteVector bytes(byte_count());
|
||||
uint8_t* data = &bytes[0];
|
||||
size_t bytes_to_go = byte_count();
|
||||
while (bytes_to_go > 0) {
|
||||
size_t requested_byte_in_digest = generated_bytes_ % digest_length;
|
||||
if (requested_byte_in_digest == 0) {
|
||||
// Do step 4.1 of the HMAC_DRBG Generate Process for more bits.
|
||||
// V = HMAC(Key, V)
|
||||
if (!HMAC_Rehash(hmac_, &value_))
|
||||
NOTREACHED();
|
||||
}
|
||||
size_t n = std::min(bytes_to_go,
|
||||
digest_length - requested_byte_in_digest);
|
||||
memcpy(data, &value_[requested_byte_in_digest], n);
|
||||
data += n;
|
||||
bytes_to_go -= n;
|
||||
generated_bytes_ += n;
|
||||
// Check max_number_of_bits_per_request from 10.1 Table 2
|
||||
// max_number_of_bits_per_request == 2^19 bits == 2^16 bytes
|
||||
DCHECK_LT(generated_bytes_, 1U << 16);
|
||||
}
|
||||
return bytes;
|
||||
}
|
||||
|
||||
} // namespace rappor
|
@ -1,121 +0,0 @@
|
||||
// Copyright 2014 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.
|
||||
|
||||
#ifndef COMPONENTS_RAPPOR_BYTE_VECTOR_UTILS_H_
|
||||
#define COMPONENTS_RAPPOR_BYTE_VECTOR_UTILS_H_
|
||||
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
|
||||
#include <vector>
|
||||
|
||||
#include "base/macros.h"
|
||||
#include "base/strings/string_piece.h"
|
||||
#include "components/rappor/public/rappor_parameters.h"
|
||||
#include "crypto/hmac.h"
|
||||
|
||||
namespace rappor {
|
||||
|
||||
// A vector of 8-bit integers used to store a set of binary bits.
|
||||
typedef std::vector<uint8_t> ByteVector;
|
||||
|
||||
// Converts the lowest |size| bytes of |value| into a ByteVector.
|
||||
void Uint64ToByteVector(uint64_t value, size_t size, ByteVector* output);
|
||||
|
||||
// Computes a bitwise AND of byte vectors and stores the result in rhs.
|
||||
// Returns rhs for chaining.
|
||||
ByteVector* ByteVectorAnd(const ByteVector& lhs, ByteVector* rhs);
|
||||
|
||||
// Computes a bitwise OR of byte vectors and stores the result in rhs.
|
||||
// Returns rhs for chaining.
|
||||
ByteVector* ByteVectorOr(const ByteVector& lhs, ByteVector* rhs);
|
||||
|
||||
// Merges the contents of lhs and rhs vectors according to a mask vector.
|
||||
// The i-th bit of the result vector will be the i-th bit of either the lhs
|
||||
// or rhs vector, based on the i-th bit of the mask vector.
|
||||
// Equivalent to (lhs & ~mask) | (rhs & mask). Stores the result in rhs.
|
||||
// Returns rhs for chaining.
|
||||
ByteVector* ByteVectorMerge(const ByteVector& mask,
|
||||
const ByteVector& lhs,
|
||||
ByteVector* rhs);
|
||||
|
||||
// Counts the number of bits set in the byte vector.
|
||||
int CountBits(const ByteVector& vector);
|
||||
|
||||
// A utility object for generating random binary data with different
|
||||
// likelihood of bits being true, using entropy from crypto::RandBytes().
|
||||
class ByteVectorGenerator {
|
||||
public:
|
||||
explicit ByteVectorGenerator(size_t byte_count);
|
||||
|
||||
virtual ~ByteVectorGenerator();
|
||||
|
||||
// Generates a random byte vector where the bits are independent random
|
||||
// variables which are true with the given |probability|.
|
||||
ByteVector GetWeightedRandomByteVector(Probability probability);
|
||||
|
||||
protected:
|
||||
// Size of vectors to be generated.
|
||||
size_t byte_count() const { return byte_count_; }
|
||||
|
||||
// Generates a random vector of bytes from a uniform distribution.
|
||||
virtual ByteVector GetRandomByteVector();
|
||||
|
||||
private:
|
||||
size_t byte_count_;
|
||||
|
||||
DISALLOW_COPY_AND_ASSIGN(ByteVectorGenerator);
|
||||
};
|
||||
|
||||
// A ByteVectorGenerator that uses a pseudo-random function to generate a
|
||||
// deterministically random bits. This class only implements a single request
|
||||
// from HMAC_DRBG and streams up to 2^19 bits from that request.
|
||||
// Ref: http://csrc.nist.gov/publications/nistpubs/800-90A/SP800-90A.pdf
|
||||
// We're using our own PRNG instead of crypto::RandBytes because we need to
|
||||
// generate a repeatable sequence of bits from the same seed. Conservatively,
|
||||
// we're choosing to use HMAC_DRBG here, as it is one of the best studied
|
||||
// and standardized ways of generating deterministic, unpredictable sequences
|
||||
// based on a secret seed.
|
||||
class HmacByteVectorGenerator : public ByteVectorGenerator {
|
||||
public:
|
||||
// Constructor takes the size of the vector to generate, along with a
|
||||
// |entropy_input| and |personalization_string| to seed the pseudo-random
|
||||
// number generator. The string parameters are treated as byte arrays.
|
||||
HmacByteVectorGenerator(size_t byte_count,
|
||||
const std::string& entropy_input,
|
||||
base::StringPiece personalization_string);
|
||||
|
||||
~HmacByteVectorGenerator() override;
|
||||
|
||||
// Generates a random string suitable for passing to the constructor as
|
||||
// |entropy_input|.
|
||||
static std::string GenerateEntropyInput();
|
||||
|
||||
// Key size required for 128-bit security strength (including nonce).
|
||||
static const size_t kEntropyInputSize;
|
||||
|
||||
protected:
|
||||
// Generate byte vector generator that streams from the next request instead
|
||||
// of the current one. For testing against NIST test vectors only.
|
||||
explicit HmacByteVectorGenerator(const HmacByteVectorGenerator& prev_request);
|
||||
|
||||
// ByteVector implementation:
|
||||
ByteVector GetRandomByteVector() override;
|
||||
|
||||
private:
|
||||
// HMAC initalized with the value of "Key" HMAC_DRBG_Initialize.
|
||||
crypto::HMAC hmac_;
|
||||
|
||||
// The "V" value from HMAC_DRBG.
|
||||
ByteVector value_;
|
||||
|
||||
// Total number of bytes streamed from the HMAC_DRBG Generate Process.
|
||||
size_t generated_bytes_;
|
||||
|
||||
DISALLOW_ASSIGN(HmacByteVectorGenerator);
|
||||
};
|
||||
|
||||
} // namespace rappor
|
||||
|
||||
#endif // COMPONENTS_RAPPOR_BYTE_VECTOR_UTILS_H_
|
@ -1,166 +0,0 @@
|
||||
// Copyright 2014 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/rappor/byte_vector_utils.h"
|
||||
|
||||
#include "base/rand_util.h"
|
||||
#include "base/strings/string_number_conversions.h"
|
||||
#include "testing/gtest/include/gtest/gtest.h"
|
||||
|
||||
namespace rappor {
|
||||
|
||||
namespace {
|
||||
|
||||
class SecondRequest : public HmacByteVectorGenerator {
|
||||
public:
|
||||
SecondRequest(const HmacByteVectorGenerator& first_request)
|
||||
: HmacByteVectorGenerator(first_request) {}
|
||||
};
|
||||
|
||||
std::string HexToString(const char* hex) {
|
||||
ByteVector bv;
|
||||
base::HexStringToBytes(hex, &bv);
|
||||
return std::string(bv.begin(), bv.end());
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
TEST(ByteVectorTest, Uint64ToByteVectorSmall) {
|
||||
ByteVector bytes(1);
|
||||
Uint64ToByteVector(0x10, 1, &bytes);
|
||||
EXPECT_EQ(1u, bytes.size());
|
||||
EXPECT_EQ(0x10, bytes[0]);
|
||||
}
|
||||
|
||||
TEST(ByteVectorTest, Uint64ToByteVectorLarge) {
|
||||
ByteVector bytes(8);
|
||||
Uint64ToByteVector(0xfedcba9876543210, 8, &bytes);
|
||||
EXPECT_EQ(8u, bytes.size());
|
||||
EXPECT_EQ(0x10, bytes[0]);
|
||||
EXPECT_EQ(0xfe, bytes[7]);
|
||||
}
|
||||
|
||||
TEST(ByteVectorTest, ByteVectorAnd) {
|
||||
ByteVector lhs(2);
|
||||
lhs[1] = 0x12;
|
||||
ByteVector rhs(2);
|
||||
rhs[1] = 0x03;
|
||||
|
||||
EXPECT_EQ(0x02, (*ByteVectorAnd(lhs, &rhs))[1]);
|
||||
}
|
||||
|
||||
TEST(ByteVectorTest, ByteVectorOr) {
|
||||
ByteVector lhs(2);
|
||||
lhs[1] = 0x12;
|
||||
ByteVector rhs(2);
|
||||
rhs[1] = 0x03;
|
||||
|
||||
EXPECT_EQ(0x13, (*ByteVectorOr(lhs, &rhs))[1]);
|
||||
}
|
||||
|
||||
TEST(ByteVectorTest, ByteVectorMerge) {
|
||||
ByteVector lhs(2);
|
||||
lhs[1] = 0x33;
|
||||
ByteVector rhs(2);
|
||||
rhs[1] = 0x55;
|
||||
ByteVector mask(2);
|
||||
mask[1] = 0x0f;
|
||||
|
||||
EXPECT_EQ(0x35, (*ByteVectorMerge(mask, lhs, &rhs))[1]);
|
||||
}
|
||||
|
||||
TEST(ByteVectorTest, ByteVectorGenerator) {
|
||||
ByteVectorGenerator generator(2u);
|
||||
ByteVector random_50 = generator.GetWeightedRandomByteVector(PROBABILITY_50);
|
||||
EXPECT_EQ(random_50.size(), 2u);
|
||||
ByteVector random_75 = generator.GetWeightedRandomByteVector(PROBABILITY_75);
|
||||
EXPECT_EQ(random_75.size(), 2u);
|
||||
}
|
||||
|
||||
TEST(ByteVectorTest, HmacByteVectorGenerator) {
|
||||
HmacByteVectorGenerator generator(1u,
|
||||
std::string(HmacByteVectorGenerator::kEntropyInputSize, 0x00), "");
|
||||
ByteVector random_50 = generator.GetWeightedRandomByteVector(PROBABILITY_50);
|
||||
EXPECT_EQ(random_50.size(), 1u);
|
||||
EXPECT_EQ(random_50[0], 0x0B);
|
||||
ByteVector random_75 = generator.GetWeightedRandomByteVector(PROBABILITY_75);
|
||||
EXPECT_EQ(random_75.size(), 1u);
|
||||
EXPECT_EQ(random_75[0], 0xdf);
|
||||
}
|
||||
|
||||
TEST(ByteVectorTest, HmacNist) {
|
||||
// Test case 0 for SHA-256 HMAC_DRBG no reseed tests from
|
||||
// http://csrc.nist.gov/groups/STM/cavp/
|
||||
const char entropy[] =
|
||||
"ca851911349384bffe89de1cbdc46e6831e44d34a4fb935ee285dd14b71a7488";
|
||||
const char nonce[] = "659ba96c601dc69fc902940805ec0ca8";
|
||||
const char expected[] =
|
||||
"e528e9abf2dece54d47c7e75e5fe302149f817ea9fb4bee6f4199697d04d5b89"
|
||||
"d54fbb978a15b5c443c9ec21036d2460b6f73ebad0dc2aba6e624abf07745bc1"
|
||||
"07694bb7547bb0995f70de25d6b29e2d3011bb19d27676c07162c8b5ccde0668"
|
||||
"961df86803482cb37ed6d5c0bb8d50cf1f50d476aa0458bdaba806f48be9dcb8";
|
||||
|
||||
std::string entropy_input = HexToString(entropy) + HexToString(nonce);
|
||||
HmacByteVectorGenerator generator(1024u / 8, entropy_input, "");
|
||||
generator.GetWeightedRandomByteVector(PROBABILITY_50);
|
||||
SecondRequest generator2(generator);
|
||||
ByteVector random_50 = generator2.GetWeightedRandomByteVector(PROBABILITY_50);
|
||||
|
||||
EXPECT_EQ(HexToString(expected),
|
||||
std::string(random_50.begin(), random_50.end()));
|
||||
}
|
||||
|
||||
TEST(ByteVectorTest, WeightedRandomStatistics0) {
|
||||
ByteVectorGenerator generator(50u);
|
||||
ByteVector random = generator.GetWeightedRandomByteVector(PROBABILITY_0);
|
||||
int bit_count = CountBits(random);
|
||||
EXPECT_EQ(bit_count, 0);
|
||||
}
|
||||
|
||||
TEST(ByteVectorTest, WeightedRandomStatistics100) {
|
||||
ByteVectorGenerator generator(50u);
|
||||
ByteVector random = generator.GetWeightedRandomByteVector(PROBABILITY_100);
|
||||
int bit_count = CountBits(random);
|
||||
EXPECT_EQ(bit_count, 50 * 8);
|
||||
}
|
||||
|
||||
TEST(ByteVectorTest, WeightedRandomStatistics50) {
|
||||
ByteVectorGenerator generator(50u);
|
||||
ByteVector random = generator.GetWeightedRandomByteVector(PROBABILITY_50);
|
||||
int bit_count = CountBits(random);
|
||||
// Check bounds on bit counts that are true with 99.999% probability.
|
||||
EXPECT_GT(bit_count, 155); // Binomial(400, .5) CDF(155) ~= 0.000004
|
||||
EXPECT_LE(bit_count, 244); // Binomial(400, .5) CDF(244) ~= 0.999996
|
||||
}
|
||||
|
||||
TEST(ByteVectorTest, WeightedRandomStatistics75) {
|
||||
ByteVectorGenerator generator(50u);
|
||||
ByteVector random = generator.GetWeightedRandomByteVector(PROBABILITY_75);
|
||||
int bit_count = CountBits(random);
|
||||
// Check bounds on bit counts that are true with 99.999% probability.
|
||||
EXPECT_GT(bit_count, 259); // Binomial(400, .75) CDF(259) ~= 0.000003
|
||||
EXPECT_LE(bit_count, 337); // Binomial(400, .75) CDF(337) ~= 0.999997
|
||||
}
|
||||
|
||||
TEST(ByteVectorTest, HmacWeightedRandomStatistics50) {
|
||||
HmacByteVectorGenerator generator(50u,
|
||||
HmacByteVectorGenerator::GenerateEntropyInput(), "");
|
||||
ByteVector random = generator.GetWeightedRandomByteVector(PROBABILITY_50);
|
||||
int bit_count = CountBits(random);
|
||||
// Check bounds on bit counts that are true with 99.999% probability.
|
||||
EXPECT_GT(bit_count, 155); // Binomial(400, .5) CDF(155) ~= 0.000004
|
||||
EXPECT_LE(bit_count, 244); // Binomial(400, .5) CDF(244) ~= 0.999996
|
||||
}
|
||||
|
||||
TEST(ByteVectorTest, HmacWeightedRandomStatistics75) {
|
||||
HmacByteVectorGenerator generator(50u,
|
||||
HmacByteVectorGenerator::GenerateEntropyInput(), "");
|
||||
ByteVector random = generator.GetWeightedRandomByteVector(PROBABILITY_75);
|
||||
int bit_count = CountBits(random);
|
||||
// Check bounds on bit counts that are true with 99.999% probability.
|
||||
EXPECT_GT(bit_count, 259); // Binomial(400, .75) CDF(259) ~= 0.000003
|
||||
EXPECT_LE(bit_count, 337); // Binomial(400, .75) CDF(337) ~= 0.999997
|
||||
}
|
||||
|
||||
} // namespace rappor
|
@ -1,231 +0,0 @@
|
||||
// Copyright 2014 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/rappor/log_uploader.h"
|
||||
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
#include <utility>
|
||||
|
||||
#include "base/bind.h"
|
||||
#include "base/metrics/histogram_functions.h"
|
||||
#include "base/metrics/histogram_macros.h"
|
||||
#include "net/base/load_flags.h"
|
||||
#include "net/base/net_errors.h"
|
||||
#include "net/traffic_annotation/network_traffic_annotation.h"
|
||||
#include "services/network/public/cpp/resource_request.h"
|
||||
#include "services/network/public/cpp/shared_url_loader_factory.h"
|
||||
#include "services/network/public/cpp/simple_url_loader.h"
|
||||
|
||||
namespace {
|
||||
|
||||
// The delay, in seconds, between uploading when there are queued logs to send.
|
||||
const int kUnsentLogsIntervalSeconds = 3;
|
||||
|
||||
// When uploading metrics to the server fails, we progressively wait longer and
|
||||
// longer before sending the next log. This backoff process helps reduce load
|
||||
// on a server that is having issues.
|
||||
// The following is the multiplier we use to expand that inter-log duration.
|
||||
const double kBackoffMultiplier = 1.1;
|
||||
|
||||
// The maximum backoff multiplier.
|
||||
const int kMaxBackoffIntervalSeconds = 60 * 60;
|
||||
|
||||
// The maximum number of unsent logs we will keep.
|
||||
// TODO(holte): Limit based on log size instead.
|
||||
const size_t kMaxQueuedLogs = 10;
|
||||
|
||||
enum DiscardReason {
|
||||
UPLOAD_SUCCESS,
|
||||
UPLOAD_REJECTED,
|
||||
QUEUE_OVERFLOW,
|
||||
NUM_DISCARD_REASONS
|
||||
};
|
||||
|
||||
void RecordDiscardReason(DiscardReason reason) {
|
||||
UMA_HISTOGRAM_ENUMERATION("Rappor.DiscardReason",
|
||||
reason,
|
||||
NUM_DISCARD_REASONS);
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
namespace rappor {
|
||||
|
||||
LogUploader::LogUploader(
|
||||
const GURL& server_url,
|
||||
const std::string& mime_type,
|
||||
scoped_refptr<network::SharedURLLoaderFactory> url_loader_factory)
|
||||
: server_url_(server_url),
|
||||
mime_type_(mime_type),
|
||||
url_loader_factory_(std::move(url_loader_factory)),
|
||||
is_running_(false),
|
||||
has_callback_pending_(false),
|
||||
upload_interval_(
|
||||
base::TimeDelta::FromSeconds(kUnsentLogsIntervalSeconds)) {}
|
||||
|
||||
LogUploader::~LogUploader() {}
|
||||
|
||||
void LogUploader::Start() {
|
||||
is_running_ = true;
|
||||
StartScheduledUpload();
|
||||
}
|
||||
|
||||
void LogUploader::Stop() {
|
||||
is_running_ = false;
|
||||
// Rather than interrupting the current upload, just let it finish/fail and
|
||||
// then inhibit any retry attempts.
|
||||
}
|
||||
|
||||
void LogUploader::QueueLog(const std::string& log) {
|
||||
queued_logs_.push(log);
|
||||
// Don't drop logs yet if an upload is in progress. They will be dropped
|
||||
// when it finishes.
|
||||
if (!has_callback_pending_)
|
||||
DropExcessLogs();
|
||||
StartScheduledUpload();
|
||||
}
|
||||
|
||||
void LogUploader::DropExcessLogs() {
|
||||
while (queued_logs_.size() > kMaxQueuedLogs) {
|
||||
DVLOG(2) << "Dropping excess log.";
|
||||
RecordDiscardReason(QUEUE_OVERFLOW);
|
||||
queued_logs_.pop();
|
||||
}
|
||||
}
|
||||
|
||||
bool LogUploader::IsUploadScheduled() const {
|
||||
return upload_timer_.IsRunning();
|
||||
}
|
||||
|
||||
void LogUploader::ScheduleNextUpload(base::TimeDelta interval) {
|
||||
upload_timer_.Start(
|
||||
FROM_HERE, interval, this, &LogUploader::StartScheduledUpload);
|
||||
}
|
||||
|
||||
bool LogUploader::CanStartUpload() const {
|
||||
return is_running_ &&
|
||||
!queued_logs_.empty() &&
|
||||
!IsUploadScheduled() &&
|
||||
!has_callback_pending_;
|
||||
}
|
||||
|
||||
void LogUploader::StartScheduledUpload() {
|
||||
if (!CanStartUpload())
|
||||
return;
|
||||
DVLOG(2) << "Upload to " << server_url_.spec() << " starting.";
|
||||
has_callback_pending_ = true;
|
||||
net::NetworkTrafficAnnotationTag traffic_annotation =
|
||||
net::DefineNetworkTrafficAnnotation("rappor_report", R"(
|
||||
semantics {
|
||||
sender: "RAPPOR"
|
||||
description:
|
||||
"This service sends RAPPOR anonymous usage statistics to Google."
|
||||
trigger:
|
||||
"Reports are automatically generated on startup and at intervals "
|
||||
"while Chromium is running."
|
||||
data: "A protocol buffer with RAPPOR anonymous usage statistics."
|
||||
destination: GOOGLE_OWNED_SERVICE
|
||||
}
|
||||
policy {
|
||||
cookies_allowed: NO
|
||||
setting:
|
||||
"Users can enable or disable this feature by stopping "
|
||||
"'Automatically send usage statistics and crash reports to Google'"
|
||||
"in Chromium's settings under Advanced Settings, Privacy. The "
|
||||
"feature is enabled by default."
|
||||
chrome_policy {
|
||||
MetricsReportingEnabled {
|
||||
policy_options {mode: MANDATORY}
|
||||
MetricsReportingEnabled: false
|
||||
}
|
||||
}
|
||||
})");
|
||||
|
||||
auto resource_request = std::make_unique<network::ResourceRequest>();
|
||||
resource_request->url = server_url_;
|
||||
// We already drop cookies server-side, but we might as well strip them out
|
||||
// client-side as well.
|
||||
resource_request->credentials_mode = network::mojom::CredentialsMode::kOmit;
|
||||
resource_request->method = "POST";
|
||||
simple_url_loader_ = network::SimpleURLLoader::Create(
|
||||
std::move(resource_request), traffic_annotation);
|
||||
simple_url_loader_->AttachStringForUpload(queued_logs_.front(), mime_type_);
|
||||
// TODO re-add data use measurement once SimpleURLLoader supports it.
|
||||
// ID=data_use_measurement::DataUseUserData::RAPPOR
|
||||
simple_url_loader_->DownloadToStringOfUnboundedSizeUntilCrashAndDie(
|
||||
url_loader_factory_.get(),
|
||||
base::BindOnce(&LogUploader::OnSimpleLoaderComplete,
|
||||
base::Unretained(this)));
|
||||
}
|
||||
|
||||
// static
|
||||
base::TimeDelta LogUploader::BackOffUploadInterval(base::TimeDelta interval) {
|
||||
DCHECK_GT(kBackoffMultiplier, 1.0);
|
||||
interval = base::TimeDelta::FromMicroseconds(
|
||||
static_cast<int64_t>(kBackoffMultiplier * interval.InMicroseconds()));
|
||||
|
||||
base::TimeDelta max_interval =
|
||||
base::TimeDelta::FromSeconds(kMaxBackoffIntervalSeconds);
|
||||
return interval > max_interval ? max_interval : interval;
|
||||
}
|
||||
|
||||
void LogUploader::OnSimpleLoaderComplete(
|
||||
std::unique_ptr<std::string> response_body) {
|
||||
int response_code = -1;
|
||||
if (simple_url_loader_->ResponseInfo() &&
|
||||
simple_url_loader_->ResponseInfo()->headers) {
|
||||
response_code =
|
||||
simple_url_loader_->ResponseInfo()->headers->response_code();
|
||||
}
|
||||
DVLOG(2) << "Upload fetch complete response code: " << response_code;
|
||||
|
||||
int net_error = simple_url_loader_->NetError();
|
||||
if (net_error != net::OK && (response_code == -1 || response_code == 200)) {
|
||||
base::UmaHistogramSparse("Rappor.FailedUploadErrorCode", -net_error);
|
||||
DVLOG(1) << "Rappor server upload failed with error: " << net_error << ": "
|
||||
<< net::ErrorToString(net_error);
|
||||
} else {
|
||||
// Log a histogram to track response success vs. failure rates.
|
||||
base::UmaHistogramSparse("Rappor.UploadResponseCode", response_code);
|
||||
}
|
||||
|
||||
const bool upload_succeeded = !!response_body;
|
||||
|
||||
// Determine whether this log should be retransmitted.
|
||||
DiscardReason reason = NUM_DISCARD_REASONS;
|
||||
if (upload_succeeded) {
|
||||
reason = UPLOAD_SUCCESS;
|
||||
} else if (response_code == 400) {
|
||||
reason = UPLOAD_REJECTED;
|
||||
}
|
||||
|
||||
if (reason != NUM_DISCARD_REASONS) {
|
||||
DVLOG(2) << "Log discarded.";
|
||||
RecordDiscardReason(reason);
|
||||
queued_logs_.pop();
|
||||
}
|
||||
|
||||
DropExcessLogs();
|
||||
|
||||
// Error 400 indicates a problem with the log, not with the server, so
|
||||
// don't consider that a sign that the server is in trouble.
|
||||
const bool server_is_healthy = upload_succeeded || response_code == 400;
|
||||
OnUploadFinished(server_is_healthy);
|
||||
}
|
||||
|
||||
void LogUploader::OnUploadFinished(bool server_is_healthy) {
|
||||
DCHECK(has_callback_pending_);
|
||||
has_callback_pending_ = false;
|
||||
// If the server is having issues, back off. Otherwise, reset to default.
|
||||
if (!server_is_healthy)
|
||||
upload_interval_ = BackOffUploadInterval(upload_interval_);
|
||||
else
|
||||
upload_interval_ = base::TimeDelta::FromSeconds(kUnsentLogsIntervalSeconds);
|
||||
|
||||
if (CanStartUpload())
|
||||
ScheduleNextUpload(upload_interval_);
|
||||
}
|
||||
|
||||
} // namespace rappor
|
@ -1,112 +0,0 @@
|
||||
// Copyright 2014 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.
|
||||
|
||||
#ifndef COMPONENTS_RAPPOR_LOG_UPLOADER_H_
|
||||
#define COMPONENTS_RAPPOR_LOG_UPLOADER_H_
|
||||
|
||||
#include <memory>
|
||||
#include <string>
|
||||
|
||||
#include "base/compiler_specific.h"
|
||||
#include "base/containers/queue.h"
|
||||
#include "base/macros.h"
|
||||
#include "base/memory/scoped_refptr.h"
|
||||
#include "base/time/time.h"
|
||||
#include "base/timer/timer.h"
|
||||
#include "components/rappor/log_uploader_interface.h"
|
||||
#include "url/gurl.h"
|
||||
|
||||
namespace network {
|
||||
class SimpleURLLoader;
|
||||
class SharedURLLoaderFactory;
|
||||
} // namespace network
|
||||
|
||||
namespace rappor {
|
||||
|
||||
// Uploads logs from RapporServiceImpl. Logs are passed in via QueueLog(),
|
||||
// stored internally, and uploaded one at a time. A queued log will be uploaded
|
||||
// at a fixed interval after the successful upload of the previous logs. If an
|
||||
// upload fails, the uploader will keep retrying the upload with an exponential
|
||||
// backoff interval.
|
||||
class LogUploader : public LogUploaderInterface {
|
||||
public:
|
||||
// Constructor takes the |server_url| that logs should be uploaded to, the
|
||||
// |mime_type| of the uploaded data, and |request_context| to create uploads
|
||||
// with.
|
||||
LogUploader(
|
||||
const GURL& server_url,
|
||||
const std::string& mime_type,
|
||||
scoped_refptr<network::SharedURLLoaderFactory> url_loader_factory);
|
||||
|
||||
// If the object is destroyed (or the program terminates) while logs are
|
||||
// queued, the logs are lost.
|
||||
~LogUploader() override;
|
||||
|
||||
// LogUploaderInterface:
|
||||
void Start() override;
|
||||
void Stop() override;
|
||||
void QueueLog(const std::string& log) override;
|
||||
|
||||
protected:
|
||||
// Checks if an upload has been scheduled.
|
||||
virtual bool IsUploadScheduled() const;
|
||||
|
||||
// Schedules a future call to StartScheduledUpload if one isn't already
|
||||
// pending. Can be overridden for testing.
|
||||
virtual void ScheduleNextUpload(base::TimeDelta interval);
|
||||
|
||||
// Starts transmission of the next log. Exposed for tests.
|
||||
void StartScheduledUpload();
|
||||
|
||||
// Increases the upload interval each time it's called, to handle the case
|
||||
// where the server is having issues. Exposed for tests.
|
||||
static base::TimeDelta BackOffUploadInterval(base::TimeDelta);
|
||||
|
||||
private:
|
||||
// Returns true if the uploader is allowed to start another upload.
|
||||
bool CanStartUpload() const;
|
||||
|
||||
// Drops excess logs until we are under the size limit.
|
||||
void DropExcessLogs();
|
||||
|
||||
// Called after transmission completes (whether successful or not).
|
||||
void OnSimpleLoaderComplete(std::unique_ptr<std::string> response_body);
|
||||
|
||||
// Called when the upload is completed.
|
||||
void OnUploadFinished(bool server_is_healthy);
|
||||
|
||||
// The server URL to upload logs to.
|
||||
const GURL server_url_;
|
||||
|
||||
// The mime type to specify on uploaded logs.
|
||||
const std::string mime_type_;
|
||||
|
||||
// The URL loader factory used to send uploads.
|
||||
scoped_refptr<network::SharedURLLoaderFactory> url_loader_factory_;
|
||||
|
||||
// True if the uploader is currently running.
|
||||
bool is_running_;
|
||||
|
||||
// The outstanding transmission.
|
||||
std::unique_ptr<network::SimpleURLLoader> simple_url_loader_;
|
||||
|
||||
// The logs that still need to be uploaded.
|
||||
base::queue<std::string> queued_logs_;
|
||||
|
||||
// A timer used to delay before attempting another upload.
|
||||
base::OneShotTimer upload_timer_;
|
||||
|
||||
// Indicates that the last triggered upload hasn't resolved yet.
|
||||
bool has_callback_pending_;
|
||||
|
||||
// The interval to wait after an upload's URLFetcher completion before
|
||||
// starting the next upload attempt.
|
||||
base::TimeDelta upload_interval_;
|
||||
|
||||
DISALLOW_COPY_AND_ASSIGN(LogUploader);
|
||||
};
|
||||
|
||||
} // namespace rappor
|
||||
|
||||
#endif // COMPONENTS_RAPPOR_LOG_UPLOADER_H_
|
@ -1,29 +0,0 @@
|
||||
// Copyright 2014 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.
|
||||
|
||||
#ifndef COMPONENTS_RAPPOR_LOG_UPLOADER_INTERFACE_H_
|
||||
#define COMPONENTS_RAPPOR_LOG_UPLOADER_INTERFACE_H_
|
||||
|
||||
namespace rappor {
|
||||
|
||||
class LogUploaderInterface {
|
||||
public:
|
||||
LogUploaderInterface() {}
|
||||
virtual ~LogUploaderInterface() {}
|
||||
|
||||
// Begin uploading logs.
|
||||
virtual void Start() = 0;
|
||||
|
||||
// Stops uploading logs.
|
||||
virtual void Stop() = 0;
|
||||
|
||||
// Adds an entry to the queue of logs to be uploaded to the server. The
|
||||
// uploader makes no assumptions about the format of |log| and simply sends
|
||||
// it verbatim to the server.
|
||||
virtual void QueueLog(const std::string& log) = 0;
|
||||
};
|
||||
|
||||
} // namespace rappor
|
||||
|
||||
#endif // COMPONENTS_RAPPOR_LOG_UPLOADER_INTERFACE_H_
|
@ -1,164 +0,0 @@
|
||||
// Copyright 2014 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/rappor/log_uploader.h"
|
||||
|
||||
#include "base/compiler_specific.h"
|
||||
#include "base/macros.h"
|
||||
#include "base/run_loop.h"
|
||||
#include "base/test/task_environment.h"
|
||||
#include "base/threading/thread_task_runner_handle.h"
|
||||
#include "net/http/http_response_headers.h"
|
||||
#include "net/http/http_status_code.h"
|
||||
#include "net/http/http_util.h"
|
||||
#include "services/network/public/cpp/weak_wrapper_shared_url_loader_factory.h"
|
||||
#include "services/network/test/test_url_loader_factory.h"
|
||||
#include "testing/gtest/include/gtest/gtest.h"
|
||||
|
||||
namespace rappor {
|
||||
|
||||
namespace {
|
||||
|
||||
const char kTestServerURL[] = "http://a.com/";
|
||||
const char kTestMimeType[] = "text/plain";
|
||||
|
||||
class TestLogUploader : public LogUploader {
|
||||
public:
|
||||
explicit TestLogUploader(
|
||||
scoped_refptr<network::SharedURLLoaderFactory> url_loader_factory)
|
||||
: LogUploader(GURL(kTestServerURL), kTestMimeType, url_loader_factory) {
|
||||
Start();
|
||||
}
|
||||
|
||||
base::TimeDelta last_interval_set() const { return last_interval_set_; }
|
||||
|
||||
void StartUpload() {
|
||||
last_interval_set_ = base::TimeDelta();
|
||||
StartScheduledUpload();
|
||||
}
|
||||
|
||||
static base::TimeDelta BackOff(base::TimeDelta t) {
|
||||
return LogUploader::BackOffUploadInterval(t);
|
||||
}
|
||||
|
||||
protected:
|
||||
bool IsUploadScheduled() const override {
|
||||
return !last_interval_set().is_zero();
|
||||
}
|
||||
|
||||
// Schedules a future call to StartScheduledUpload if one isn't already
|
||||
// pending.
|
||||
void ScheduleNextUpload(base::TimeDelta interval) override {
|
||||
EXPECT_EQ(last_interval_set(), base::TimeDelta());
|
||||
last_interval_set_ = interval;
|
||||
}
|
||||
|
||||
base::TimeDelta last_interval_set_;
|
||||
|
||||
private:
|
||||
DISALLOW_COPY_AND_ASSIGN(TestLogUploader);
|
||||
};
|
||||
|
||||
} // namespace
|
||||
|
||||
class LogUploaderTest : public testing::Test {
|
||||
public:
|
||||
LogUploaderTest()
|
||||
: task_environment_(
|
||||
base::test::SingleThreadTaskEnvironment::MainThreadType::UI) {}
|
||||
|
||||
protected:
|
||||
// Required for base::ThreadTaskRunnerHandle::Get().
|
||||
base::test::SingleThreadTaskEnvironment task_environment_;
|
||||
network::TestURLLoaderFactory test_url_loader_factory_;
|
||||
|
||||
private:
|
||||
DISALLOW_COPY_AND_ASSIGN(LogUploaderTest);
|
||||
};
|
||||
|
||||
TEST_F(LogUploaderTest, Success) {
|
||||
TestLogUploader uploader(test_url_loader_factory_.GetSafeWeakWrapper());
|
||||
test_url_loader_factory_.AddResponse(kTestServerURL, "");
|
||||
|
||||
uploader.QueueLog("log1");
|
||||
base::RunLoop().RunUntilIdle();
|
||||
// Log should be discarded instead of retransmitted.
|
||||
EXPECT_EQ(uploader.last_interval_set(), base::TimeDelta());
|
||||
}
|
||||
|
||||
TEST_F(LogUploaderTest, Rejection) {
|
||||
TestLogUploader uploader(test_url_loader_factory_.GetSafeWeakWrapper());
|
||||
|
||||
auto response_head = network::mojom::URLResponseHead::New();
|
||||
std::string headers("HTTP/1.1 400 Bad Request\nContent-type: text/html\n\n");
|
||||
response_head->headers = base::MakeRefCounted<net::HttpResponseHeaders>(
|
||||
net::HttpUtil::AssembleRawHeaders(headers));
|
||||
response_head->mime_type = "text/html";
|
||||
test_url_loader_factory_.AddResponse(GURL(kTestServerURL),
|
||||
std::move(response_head), "",
|
||||
network::URLLoaderCompletionStatus());
|
||||
|
||||
uploader.QueueLog("log1");
|
||||
base::RunLoop().RunUntilIdle();
|
||||
// Log should be discarded instead of retransmitted.
|
||||
EXPECT_EQ(uploader.last_interval_set(), base::TimeDelta());
|
||||
}
|
||||
|
||||
TEST_F(LogUploaderTest, Failure) {
|
||||
TestLogUploader uploader(test_url_loader_factory_.GetSafeWeakWrapper());
|
||||
|
||||
auto response_head = network::mojom::URLResponseHead::New();
|
||||
std::string headers(
|
||||
"HTTP/1.1 500 Internal Server Error\nContent-type: text/html\n\n");
|
||||
response_head->headers = base::MakeRefCounted<net::HttpResponseHeaders>(
|
||||
net::HttpUtil::AssembleRawHeaders(headers));
|
||||
response_head->mime_type = "text/html";
|
||||
test_url_loader_factory_.AddResponse(GURL(kTestServerURL),
|
||||
std::move(response_head), "",
|
||||
network::URLLoaderCompletionStatus());
|
||||
|
||||
uploader.QueueLog("log1");
|
||||
base::RunLoop().RunUntilIdle();
|
||||
// Log should be scheduled for retransmission.
|
||||
base::TimeDelta error_interval = uploader.last_interval_set();
|
||||
EXPECT_GT(error_interval, base::TimeDelta());
|
||||
|
||||
for (int i = 0; i < 10; i++) {
|
||||
uploader.QueueLog("logX");
|
||||
}
|
||||
|
||||
// A second failure should lead to a longer interval, and the log should
|
||||
// be discarded due to full queue.
|
||||
uploader.StartUpload();
|
||||
base::RunLoop().RunUntilIdle();
|
||||
EXPECT_GT(uploader.last_interval_set(), error_interval);
|
||||
|
||||
test_url_loader_factory_.AddResponse(kTestServerURL, "");
|
||||
|
||||
// A success should revert to base interval while queue is not empty.
|
||||
for (int i = 0; i < 9; i++) {
|
||||
uploader.StartUpload();
|
||||
base::RunLoop().RunUntilIdle();
|
||||
EXPECT_LT(uploader.last_interval_set(), error_interval);
|
||||
}
|
||||
|
||||
// Queue should be empty.
|
||||
uploader.StartUpload();
|
||||
base::RunLoop().RunUntilIdle();
|
||||
EXPECT_EQ(uploader.last_interval_set(), base::TimeDelta());
|
||||
}
|
||||
|
||||
TEST_F(LogUploaderTest, Backoff) {
|
||||
base::TimeDelta current = base::TimeDelta();
|
||||
base::TimeDelta next = base::TimeDelta::FromSeconds(1);
|
||||
// Backoff until the maximum is reached.
|
||||
while (next > current) {
|
||||
current = next;
|
||||
next = TestLogUploader::BackOff(current);
|
||||
}
|
||||
// Maximum backoff should have been reached.
|
||||
EXPECT_EQ(next, current);
|
||||
}
|
||||
|
||||
} // namespace rappor
|
@ -1,9 +0,0 @@
|
||||
# Copyright 2014 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.
|
||||
|
||||
import("//third_party/protobuf/proto_library.gni")
|
||||
|
||||
proto_library("proto") {
|
||||
sources = [ "rappor_metric.proto" ]
|
||||
}
|
@ -1,40 +0,0 @@
|
||||
// Copyright 2014 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.
|
||||
//
|
||||
// Contains information collected by the RAPPOR (Randomized Aggregatable
|
||||
// Privacy-Preserving Ordinal Responses) system.
|
||||
//
|
||||
// For a full description of the rappor metrics, see
|
||||
// http://www.chromium.org/developers/design-documents/rappor
|
||||
|
||||
syntax = "proto2";
|
||||
|
||||
option optimize_for = LITE_RUNTIME;
|
||||
|
||||
package rappor;
|
||||
|
||||
// Next tag: 3
|
||||
message RapporReports {
|
||||
// Which cohort these reports belong to. The RAPPOR participants are
|
||||
// partioned into cohorts in different ways, to allow better statistics and
|
||||
// increased coverage. In particular, the cohort will serve to choose the
|
||||
// hash functions used for Bloom-filter-based reports. The cohort is
|
||||
// generated randomly by the client and is currently in the range [0,512).
|
||||
// Was in range [0,32) in chrome versions before M37.
|
||||
optional int32 cohort = 1;
|
||||
|
||||
// Each Report contains the values generated by the RAPPOR process for one
|
||||
// metric.
|
||||
message Report {
|
||||
// The name of the metric, hashed (first 8 bytes of MD5 hash).
|
||||
optional fixed64 name_hash = 1;
|
||||
|
||||
// The sequence of bits produced by random coin flips in
|
||||
// RapporMetric::GetReport(). For a complete description of RAPPOR
|
||||
// metrics, refer to the design document at:
|
||||
// http://www.chromium.org/developers/design-documents/rappor
|
||||
optional bytes bits = 2;
|
||||
}
|
||||
repeated Report report = 2;
|
||||
}
|
@ -1,14 +0,0 @@
|
||||
# Copyright 2016 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.
|
||||
|
||||
source_set("public") {
|
||||
sources = [
|
||||
"rappor_parameters.h",
|
||||
"rappor_service.h",
|
||||
"rappor_utils.h",
|
||||
"sample.h",
|
||||
]
|
||||
|
||||
deps = [ "//base" ]
|
||||
}
|
@ -1,159 +0,0 @@
|
||||
// Copyright 2016 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.
|
||||
|
||||
#ifndef COMPONENTS_RAPPOR_PUBLIC_RAPPOR_PARAMETERS_H_
|
||||
#define COMPONENTS_RAPPOR_PUBLIC_RAPPOR_PARAMETERS_H_
|
||||
|
||||
#include <string>
|
||||
|
||||
namespace rappor {
|
||||
|
||||
// Levels of noise added to a sample.
|
||||
enum NoiseLevel {
|
||||
NO_NOISE = 0,
|
||||
NORMAL_NOISE,
|
||||
SPARSE_NOISE,
|
||||
NUM_NOISE_LEVELS,
|
||||
};
|
||||
|
||||
// The type of data stored in a metric.
|
||||
// Any use of the LOW_FREQUENCY types must be approved by Chrome Privacy and
|
||||
// the rappor-dev team.
|
||||
enum RapporType {
|
||||
// Generic metrics from UMA opt-in users.
|
||||
UMA_RAPPOR_TYPE = 0,
|
||||
// Deprecated: Use UMA_RAPPOR_TYPE for new metrics
|
||||
ETLD_PLUS_ONE_RAPPOR_TYPE,
|
||||
// Type for low-frequency metrics from UMA opt-in users.
|
||||
LOW_FREQUENCY_UMA_RAPPOR_TYPE,
|
||||
// Type for low-frequency metrics from UMA opt-in users. Do not use for new
|
||||
// metrics.
|
||||
LOW_FREQUENCY_ETLD_PLUS_ONE_RAPPOR_TYPE,
|
||||
NUM_RAPPOR_TYPES,
|
||||
};
|
||||
|
||||
enum Probability {
|
||||
PROBABILITY_100, // 100%
|
||||
PROBABILITY_75, // 75%
|
||||
PROBABILITY_50, // 50%
|
||||
PROBABILITY_25, // 25%
|
||||
PROBABILITY_0, // 0%
|
||||
};
|
||||
|
||||
// A metric is reported when its reporting group is in the set of groups
|
||||
// passed in to RapporServiceImpl::Start()
|
||||
enum RecordingGroup {
|
||||
// Metrics for UMA users.
|
||||
UMA_RAPPOR_GROUP = 1 << 0,
|
||||
};
|
||||
|
||||
// An object describing noise probabilities for a noise level
|
||||
struct NoiseParameters {
|
||||
// The probability that a bit will be redacted with fake data. This
|
||||
// corresponds to the F privacy parameter.
|
||||
Probability fake_prob;
|
||||
// The probability that a fake bit will be a one.
|
||||
Probability fake_one_prob;
|
||||
// The probability that a one bit in the redacted data reports as one. This
|
||||
// corresponds to the Q privacy parameter
|
||||
Probability one_coin_prob;
|
||||
// The probability that a zero bit in the redacted data reports as one. This
|
||||
// corresponds to the P privacy parameter.
|
||||
Probability zero_coin_prob;
|
||||
};
|
||||
|
||||
// An object describing a rappor metric and the parameters used to generate it.
|
||||
//
|
||||
// For a full description of the rappor metrics, see
|
||||
// http://www.chromium.org/developers/design-documents/rappor
|
||||
struct RapporParameters {
|
||||
// Get a string representing the parameters, for DCHECK_EQ.
|
||||
std::string ToString() const;
|
||||
|
||||
// The maximum number of cohorts we divide clients into.
|
||||
static const int kMaxCohorts;
|
||||
|
||||
// The number of cohorts to divide the reports for this metric into.
|
||||
// This should divide kMaxCohorts evenly so that each cohort has an equal
|
||||
// probability of being assigned users.
|
||||
int num_cohorts;
|
||||
|
||||
// The number of bytes stored in the Bloom filter.
|
||||
size_t bloom_filter_size_bytes;
|
||||
// The number of hash functions used in the Bloom filter.
|
||||
int bloom_filter_hash_function_count;
|
||||
|
||||
// The level of noise to use.
|
||||
NoiseLevel noise_level;
|
||||
|
||||
// The reporting level this metric is reported at.
|
||||
RecordingGroup recording_group;
|
||||
};
|
||||
|
||||
namespace internal {
|
||||
|
||||
const NoiseParameters kNoiseParametersForLevel[NUM_NOISE_LEVELS] = {
|
||||
// NO_NOISE
|
||||
{
|
||||
rappor::PROBABILITY_0 /* Fake data probability */,
|
||||
rappor::PROBABILITY_0 /* Fake one probability */,
|
||||
rappor::PROBABILITY_100 /* One coin probability */,
|
||||
rappor::PROBABILITY_0 /* Zero coin probability */,
|
||||
},
|
||||
// NORMAL_NOISE
|
||||
{
|
||||
rappor::PROBABILITY_50 /* Fake data probability */,
|
||||
rappor::PROBABILITY_50 /* Fake one probability */,
|
||||
rappor::PROBABILITY_75 /* One coin probability */,
|
||||
rappor::PROBABILITY_25 /* Zero coin probability */,
|
||||
},
|
||||
// SPARSE_NOISE
|
||||
{
|
||||
rappor::PROBABILITY_25 /* Fake data probability */,
|
||||
rappor::PROBABILITY_50 /* Fake one probability */,
|
||||
rappor::PROBABILITY_75 /* One coin probability */,
|
||||
rappor::PROBABILITY_25 /* Zero coin probability */,
|
||||
},
|
||||
};
|
||||
|
||||
const RapporParameters kRapporParametersForType[NUM_RAPPOR_TYPES] = {
|
||||
// UMA_RAPPOR_TYPE
|
||||
{
|
||||
128 /* Num cohorts */,
|
||||
4 /* Bloom filter size bytes */,
|
||||
2 /* Bloom filter hash count */,
|
||||
rappor::NORMAL_NOISE /* Noise level */,
|
||||
UMA_RAPPOR_GROUP /* Recording group */
|
||||
},
|
||||
// ETLD_PLUS_ONE_RAPPOR_TYPE
|
||||
{
|
||||
128 /* Num cohorts */,
|
||||
16 /* Bloom filter size bytes */,
|
||||
2 /* Bloom filter hash count */,
|
||||
rappor::NORMAL_NOISE /* Noise level */,
|
||||
UMA_RAPPOR_GROUP /* Recording group */
|
||||
},
|
||||
// LOW_FREQUENCY_UMA_RAPPOR_TYPE
|
||||
{
|
||||
128 /* Num cohorts */,
|
||||
4 /* Bloom filter size bytes */,
|
||||
2 /* Bloom filter hash count */,
|
||||
rappor::SPARSE_NOISE /* Noise level */,
|
||||
UMA_RAPPOR_GROUP /* Recording group */
|
||||
},
|
||||
// LOW_FREQUENCY_ETLD_PLUS_ONE_RAPPOR_TYPE
|
||||
{
|
||||
128 /* Num cohorts */,
|
||||
16 /* Bloom filter size bytes */,
|
||||
2 /* Bloom filter hash count */,
|
||||
rappor::SPARSE_NOISE /* Noise level */,
|
||||
UMA_RAPPOR_GROUP /* Recording group */
|
||||
},
|
||||
};
|
||||
|
||||
} // namespace internal
|
||||
|
||||
} // namespace rappor
|
||||
|
||||
#endif // COMPONENTS_RAPPOR_PUBLIC_RAPPOR_PARAMETERS_H_
|
@ -1,44 +0,0 @@
|
||||
// Copyright 2016 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.
|
||||
|
||||
#ifndef COMPONENTS_RAPPOR_PUBLIC_RAPPOR_SERVICE_H_
|
||||
#define COMPONENTS_RAPPOR_PUBLIC_RAPPOR_SERVICE_H_
|
||||
|
||||
#include <memory>
|
||||
#include <string>
|
||||
|
||||
#include "base/memory/weak_ptr.h"
|
||||
#include "components/rappor/public/rappor_parameters.h"
|
||||
#include "components/rappor/public/sample.h"
|
||||
|
||||
namespace rappor {
|
||||
|
||||
// This class provides a public interface for recording samples for rappor
|
||||
// metrics, which other components can be depended on.
|
||||
class RapporService : public base::SupportsWeakPtr<RapporService> {
|
||||
public:
|
||||
// Constructs a Sample object for the caller to record fields in.
|
||||
virtual std::unique_ptr<Sample> CreateSample(RapporType) = 0;
|
||||
|
||||
// Records a Sample of rappor metric specified by |metric_name|.
|
||||
//
|
||||
// example:
|
||||
// std::unique_ptr<Sample> sample =
|
||||
// rappor_service->CreateSample(MY_METRIC_TYPE);
|
||||
// sample->SetStringField("Field1", "some string");
|
||||
// sample->SetFlagsValue("Field2", SOME|FLAGS);
|
||||
// rappor_service->RecordSample("MyMetric", std::move(sample));
|
||||
virtual void RecordSample(const std::string& metric_name,
|
||||
std::unique_ptr<Sample> sample) = 0;
|
||||
|
||||
// Records a sample of the rappor metric specified by |metric_name|.
|
||||
// Creates and initializes the metric, if it doesn't yet exist.
|
||||
virtual void RecordSampleString(const std::string& metric_name,
|
||||
RapporType type,
|
||||
const std::string& sample) = 0;
|
||||
};
|
||||
|
||||
} // namespace rappor
|
||||
|
||||
#endif // COMPONENTS_RAPPOR_PUBLIC_RAPPOR_SERVICE_H_
|
@ -1,41 +0,0 @@
|
||||
// Copyright 2016 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.
|
||||
|
||||
#ifndef COMPONENTS_RAPPOR_PUBLIC_RAPPOR_UTILS_H_
|
||||
#define COMPONENTS_RAPPOR_PUBLIC_RAPPOR_UTILS_H_
|
||||
|
||||
#include <string>
|
||||
|
||||
#include "components/rappor/public/rappor_service.h"
|
||||
|
||||
class GURL;
|
||||
|
||||
namespace rappor {
|
||||
|
||||
// Records a string to a Rappor metric.
|
||||
// If |rappor_service| is NULL, this call does nothing.
|
||||
void SampleString(RapporService* rappor_service,
|
||||
const std::string& metric,
|
||||
RapporType type,
|
||||
const std::string& sample);
|
||||
|
||||
// Extract the domain and registry for a sample from a GURL.
|
||||
// For file:// urls this will just return "file://" and for other special
|
||||
// schemes like chrome-extension will return the scheme and host.
|
||||
std::string GetDomainAndRegistrySampleFromGURL(const GURL& gurl);
|
||||
|
||||
// Records the domain and registry of a url to a Rappor metric.
|
||||
// If |rappor_service| is NULL, this call does nothing.
|
||||
void SampleDomainAndRegistryFromGURL(RapporService* rappor_service,
|
||||
const std::string& metric,
|
||||
const GURL& gurl);
|
||||
|
||||
// Returns NULL if there is no default service.
|
||||
RapporService* GetDefaultService();
|
||||
|
||||
void SetDefaultServiceAccessor(RapporService* (*getDefaultService)());
|
||||
|
||||
} // namespace rappor
|
||||
|
||||
#endif // COMPONENTS_RAPPOR_PUBLIC_RAPPOR_UTILS_H_
|
@ -1,92 +0,0 @@
|
||||
// Copyright 2016 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.
|
||||
|
||||
#ifndef COMPONENTS_RAPPOR_PUBLIC_SAMPLE_H_
|
||||
#define COMPONENTS_RAPPOR_PUBLIC_SAMPLE_H_
|
||||
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
|
||||
#include <map>
|
||||
#include <string>
|
||||
|
||||
#include "base/macros.h"
|
||||
#include "components/rappor/public/rappor_parameters.h"
|
||||
|
||||
namespace rappor {
|
||||
|
||||
class RapporReports;
|
||||
class RapporServiceImpl;
|
||||
class TestSamplerFactory;
|
||||
|
||||
// Sample is a container for information about a single instance of some event
|
||||
// we are sending Rappor data about. It may contain multiple different fields,
|
||||
// which describe different details of the event, and they will be sent in the
|
||||
// same Rappor report, enabling analysis of correlations between those fields.
|
||||
class Sample {
|
||||
public:
|
||||
virtual ~Sample();
|
||||
|
||||
// Sets a string value field in this sample.
|
||||
virtual void SetStringField(const std::string& field_name,
|
||||
const std::string& value);
|
||||
|
||||
// TODO(holte): Move all callers to the version with NoiseLevel.
|
||||
virtual void SetFlagsField(const std::string& field_name,
|
||||
uint64_t flags,
|
||||
size_t num_flags);
|
||||
|
||||
// Sets a group of boolean flags as a field in this sample, with the
|
||||
// specified noise level.
|
||||
// |flags| should be a set of boolean flags stored in the lowest |num_flags|
|
||||
// bits of |flags|.
|
||||
virtual void SetFlagsField(const std::string& field_name,
|
||||
uint64_t flags,
|
||||
size_t num_flags,
|
||||
NoiseLevel noise_level);
|
||||
|
||||
// Sets an integer value field in this sample, at the given noise level.
|
||||
virtual void SetUInt64Field(const std::string& field_name,
|
||||
uint64_t value,
|
||||
NoiseLevel noise_level);
|
||||
|
||||
// Generate randomized reports and store them in |reports|.
|
||||
virtual void ExportMetrics(const std::string& secret,
|
||||
const std::string& metric_name,
|
||||
RapporReports* reports) const;
|
||||
|
||||
const RapporParameters& parameters() { return parameters_; }
|
||||
|
||||
private:
|
||||
friend class TestSamplerFactory;
|
||||
friend class RapporServiceImpl;
|
||||
friend class TestSample;
|
||||
|
||||
// Constructs a sample. Instead of calling this directly, call
|
||||
// RapporService::MakeSampleObj to create a sample.
|
||||
Sample(int32_t cohort_seed, const RapporParameters& parameters);
|
||||
|
||||
const RapporParameters parameters_;
|
||||
|
||||
// Offset used for bloom filter hash functions.
|
||||
uint32_t bloom_offset_;
|
||||
|
||||
struct FieldInfo {
|
||||
// Size of the field, in bytes.
|
||||
size_t size;
|
||||
// The non-randomized report value for the field.
|
||||
uint64_t value;
|
||||
// The noise level to use when creating a report for the field.
|
||||
NoiseLevel noise_level;
|
||||
};
|
||||
|
||||
// Information about all recorded fields.
|
||||
std::map<std::string, FieldInfo> field_info_;
|
||||
|
||||
DISALLOW_COPY_AND_ASSIGN(Sample);
|
||||
};
|
||||
|
||||
} // namespace rappor
|
||||
|
||||
#endif // COMPONENTS_RAPPOR_PUBLIC_SAMPLE_H_
|
@ -1,49 +0,0 @@
|
||||
// Copyright 2014 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/rappor/rappor_metric.h"
|
||||
|
||||
#include "base/check_op.h"
|
||||
#include "base/rand_util.h"
|
||||
#include "components/rappor/public/rappor_parameters.h"
|
||||
#include "components/rappor/reports.h"
|
||||
|
||||
namespace rappor {
|
||||
|
||||
RapporMetric::RapporMetric(const std::string& metric_name,
|
||||
const RapporParameters& parameters,
|
||||
int32_t cohort_seed)
|
||||
: metric_name_(metric_name),
|
||||
parameters_(parameters),
|
||||
sample_count_(0),
|
||||
bloom_filter_(parameters.bloom_filter_size_bytes,
|
||||
parameters.bloom_filter_hash_function_count,
|
||||
(cohort_seed % parameters.num_cohorts) *
|
||||
parameters.bloom_filter_hash_function_count) {
|
||||
DCHECK_GE(cohort_seed, 0);
|
||||
DCHECK_LT(cohort_seed, RapporParameters::kMaxCohorts);
|
||||
// Since cohort_seed is in the range [0, kMaxCohorts), num_cohorts should
|
||||
// divide kMaxCohorts for each cohort to have equal weight.
|
||||
DCHECK_EQ(0, RapporParameters::kMaxCohorts % parameters.num_cohorts);
|
||||
}
|
||||
|
||||
RapporMetric::~RapporMetric() {}
|
||||
|
||||
void RapporMetric::AddSample(const std::string& str) {
|
||||
++sample_count_;
|
||||
// Replace the previous sample with a 1 in sample_count_ chance so that each
|
||||
// sample has equal probability of being reported.
|
||||
if (base::RandGenerator(sample_count_) == 0) {
|
||||
bloom_filter_.SetString(str);
|
||||
}
|
||||
}
|
||||
|
||||
ByteVector RapporMetric::GetReport(const std::string& secret) const {
|
||||
return internal::GenerateReport(
|
||||
secret,
|
||||
internal::kNoiseParametersForLevel[parameters().noise_level],
|
||||
bytes());
|
||||
}
|
||||
|
||||
} // namespace rappor
|
@ -1,65 +0,0 @@
|
||||
// Copyright 2014 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.
|
||||
|
||||
#ifndef COMPONENTS_RAPPOR_RAPPOR_METRIC_H_
|
||||
#define COMPONENTS_RAPPOR_RAPPOR_METRIC_H_
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
#include <string>
|
||||
|
||||
#include "base/macros.h"
|
||||
#include "components/rappor/bloom_filter.h"
|
||||
#include "components/rappor/byte_vector_utils.h"
|
||||
#include "components/rappor/public/rappor_parameters.h"
|
||||
|
||||
namespace rappor {
|
||||
|
||||
// A RapporMetric is an object that collects string samples into a Bloom filter,
|
||||
// and generates randomized reports about the collected data.
|
||||
//
|
||||
// This class should not be used directly by metrics clients. Record metrics
|
||||
// using RapporServiceImpl::RecordSample or RapporService::RecordSample instead.
|
||||
//
|
||||
// For a full description of the rappor metrics, see
|
||||
// http://www.chromium.org/developers/design-documents/rappor
|
||||
class RapporMetric {
|
||||
public:
|
||||
// Takes the |metric_name| that this will be reported to the server with,
|
||||
// a |parameters| describing size and probability weights used in recording
|
||||
// this metric, and a |cohort| value, which determines the hash functions
|
||||
// used in the Bloom filter.
|
||||
RapporMetric(const std::string& metric_name,
|
||||
const RapporParameters& parameters,
|
||||
int32_t cohort);
|
||||
~RapporMetric();
|
||||
|
||||
// Records an additional sample in the Bloom filter.
|
||||
// A random sample will be used when reporting this metric when more than one
|
||||
// sample is collected in the same reporting interval.
|
||||
void AddSample(const std::string& str);
|
||||
|
||||
// Retrieves the current Bloom filter bits.
|
||||
const ByteVector& bytes() const { return bloom_filter_.bytes(); }
|
||||
|
||||
// Gets the parameter values this metric was constructed with.
|
||||
const RapporParameters& parameters() const { return parameters_; }
|
||||
|
||||
// Generates the bits to report for this metric. Using the secret as a seed,
|
||||
// randomly selects bits for redaction. Then flips coins to generate the
|
||||
// final report bits.
|
||||
ByteVector GetReport(const std::string& secret) const;
|
||||
|
||||
private:
|
||||
const std::string metric_name_;
|
||||
const RapporParameters parameters_;
|
||||
uint32_t sample_count_;
|
||||
BloomFilter bloom_filter_;
|
||||
|
||||
DISALLOW_COPY_AND_ASSIGN(RapporMetric);
|
||||
};
|
||||
|
||||
} // namespace rappor
|
||||
|
||||
#endif // COMPONENTS_RAPPOR_RAPPOR_METRIC_H_
|
@ -1,38 +0,0 @@
|
||||
// Copyright 2014 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/rappor/rappor_metric.h"
|
||||
|
||||
#include <stdlib.h>
|
||||
|
||||
#include "base/rand_util.h"
|
||||
#include "base/strings/stringprintf.h"
|
||||
#include "testing/gtest/include/gtest/gtest.h"
|
||||
|
||||
namespace rappor {
|
||||
|
||||
const RapporParameters kRapporMetricTestParameters = {
|
||||
1 /* Num cohorts */,
|
||||
16 /* Bloom filter size bytes */,
|
||||
4 /* Bloom filter hash count */,
|
||||
NORMAL_NOISE /* Noise level */,
|
||||
UMA_RAPPOR_GROUP /* Recording group (not used) */,
|
||||
};
|
||||
|
||||
// Check for basic syntax and use.
|
||||
TEST(RapporMetricTest, BasicMetric) {
|
||||
RapporMetric testMetric("MyRappor", kRapporMetricTestParameters, 0);
|
||||
testMetric.AddSample("Bar");
|
||||
EXPECT_EQ(0x80, testMetric.bytes()[1]);
|
||||
}
|
||||
|
||||
TEST(RapporMetricTest, GetReport) {
|
||||
RapporMetric metric("MyRappor", kRapporMetricTestParameters, 0);
|
||||
|
||||
const ByteVector report = metric.GetReport(
|
||||
HmacByteVectorGenerator::GenerateEntropyInput());
|
||||
EXPECT_EQ(16u, report.size());
|
||||
}
|
||||
|
||||
} // namespace rappor
|
@ -1,24 +0,0 @@
|
||||
// Copyright 2014 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/rappor/public/rappor_parameters.h"
|
||||
|
||||
#include "base/compiler_specific.h"
|
||||
#include "base/format_macros.h"
|
||||
#include "base/strings/stringprintf.h"
|
||||
|
||||
namespace rappor {
|
||||
|
||||
std::string RapporParameters::ToString() const {
|
||||
return base::StringPrintf("{ %d, %" PRIuS ", %d, %d, %d }",
|
||||
num_cohorts,
|
||||
bloom_filter_size_bytes,
|
||||
bloom_filter_hash_function_count,
|
||||
noise_level,
|
||||
recording_group);
|
||||
}
|
||||
|
||||
const int RapporParameters::kMaxCohorts = 512;
|
||||
|
||||
} // namespace rappor
|
@ -1,26 +0,0 @@
|
||||
// Copyright 2014 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/rappor/rappor_pref_names.h"
|
||||
|
||||
namespace rappor {
|
||||
namespace prefs {
|
||||
|
||||
// Deprecated: Old cohort selection pref, should be cleared.
|
||||
const char kRapporCohortDeprecated[] = "rappor.cohort";
|
||||
|
||||
// A randomly generated number, which determines cohorts data is reported for.
|
||||
const char kRapporCohortSeed[] = "rappor.cohort_seed";
|
||||
|
||||
// Timestamp of the last time we sampled daily metrics.
|
||||
const char kRapporLastDailySample[] = "rappor.last_daily_sample";
|
||||
|
||||
// A base-64 encoded, randomly generated byte string, which is used as a seed
|
||||
// for redacting collected data.
|
||||
// Important: This value should remain secret at the client, and never be
|
||||
// reported on the network, or to the server.
|
||||
const char kRapporSecret[] = "rappor.secret";
|
||||
|
||||
} // namespace prefs
|
||||
} // namespace rappor
|
@ -1,21 +0,0 @@
|
||||
// Copyright 2014 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.
|
||||
|
||||
#ifndef COMPONENTS_RAPPOR_RAPPOR_PREF_NAMES_H_
|
||||
#define COMPONENTS_RAPPOR_RAPPOR_PREF_NAMES_H_
|
||||
|
||||
namespace rappor {
|
||||
namespace prefs {
|
||||
|
||||
// Alphabetical list of preference names specific to the Rappor
|
||||
// component. Keep alphabetized, and document each in the .cc file.
|
||||
extern const char kRapporCohortDeprecated[];
|
||||
extern const char kRapporCohortSeed[];
|
||||
extern const char kRapporLastDailySample[];
|
||||
extern const char kRapporSecret[];
|
||||
|
||||
} // namespace prefs
|
||||
} // namespace rappor
|
||||
|
||||
#endif // COMPONENTS_RAPPOR_RAPPOR_PREF_NAMES_H_
|
@ -1,99 +0,0 @@
|
||||
// Copyright 2015 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/rappor/rappor_prefs.h"
|
||||
|
||||
#include "base/base64.h"
|
||||
#include "base/logging.h"
|
||||
#include "base/metrics/histogram_macros.h"
|
||||
#include "base/rand_util.h"
|
||||
#include "components/metrics/daily_event.h"
|
||||
#include "components/prefs/pref_registry_simple.h"
|
||||
#include "components/prefs/pref_service.h"
|
||||
#include "components/rappor/byte_vector_utils.h"
|
||||
#include "components/rappor/public/rappor_parameters.h"
|
||||
#include "components/rappor/rappor_pref_names.h"
|
||||
|
||||
namespace rappor {
|
||||
|
||||
namespace internal {
|
||||
|
||||
const char kLoadCohortHistogramName[] = "Rappor.LoadCohortResult";
|
||||
const char kLoadSecretHistogramName[] = "Rappor.LoadSecretResult";
|
||||
|
||||
namespace {
|
||||
|
||||
void RecordLoadCohortResult(LoadResult reason) {
|
||||
UMA_HISTOGRAM_ENUMERATION(kLoadCohortHistogramName,
|
||||
reason,
|
||||
NUM_LOAD_RESULTS);
|
||||
}
|
||||
|
||||
void RecordLoadSecretResult(LoadResult reason) {
|
||||
UMA_HISTOGRAM_ENUMERATION(kLoadSecretHistogramName,
|
||||
reason,
|
||||
NUM_LOAD_RESULTS);
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
void RegisterPrefs(PrefRegistrySimple* registry) {
|
||||
registry->RegisterStringPref(prefs::kRapporSecret, std::string());
|
||||
registry->RegisterIntegerPref(prefs::kRapporCohortDeprecated, -1);
|
||||
registry->RegisterIntegerPref(prefs::kRapporCohortSeed, -1);
|
||||
metrics::DailyEvent::RegisterPref(registry, prefs::kRapporLastDailySample);
|
||||
}
|
||||
|
||||
int32_t LoadCohort(PrefService* pref_service) {
|
||||
// Ignore and delete old cohort parameter.
|
||||
pref_service->ClearPref(prefs::kRapporCohortDeprecated);
|
||||
|
||||
int32_t cohort = pref_service->GetInteger(prefs::kRapporCohortSeed);
|
||||
// If the user is already assigned to a valid cohort, we're done.
|
||||
if (cohort >= 0 && cohort < RapporParameters::kMaxCohorts) {
|
||||
RecordLoadCohortResult(LOAD_SUCCESS);
|
||||
DVLOG(2) << "Rappor cohort loaded.";
|
||||
return cohort;
|
||||
}
|
||||
|
||||
// This is the first time the client has started the service (or their
|
||||
// preferences were corrupted). Randomly assign them to a cohort.
|
||||
RecordLoadCohortResult(cohort == -1 ? LOAD_EMPTY_VALUE : LOAD_CORRUPT_VALUE);
|
||||
cohort = base::RandGenerator(RapporParameters::kMaxCohorts);
|
||||
DVLOG(2) << "Selected a new Rappor cohort: " << cohort;
|
||||
pref_service->SetInteger(prefs::kRapporCohortSeed, cohort);
|
||||
return cohort;
|
||||
}
|
||||
|
||||
std::string LoadSecret(PrefService* pref_service) {
|
||||
std::string secret;
|
||||
std::string secret_base64 = pref_service->GetString(prefs::kRapporSecret);
|
||||
if (!secret_base64.empty()) {
|
||||
bool decoded = base::Base64Decode(secret_base64, &secret);
|
||||
if (decoded &&
|
||||
secret.size() == HmacByteVectorGenerator::kEntropyInputSize) {
|
||||
DVLOG(2) << "Rappor secret loaded.";
|
||||
RecordLoadSecretResult(LOAD_SUCCESS);
|
||||
return secret;
|
||||
}
|
||||
// If the preference fails to decode, or is the wrong size, it must be
|
||||
// corrupt, so continue as though it didn't exist yet and generate a new
|
||||
// one.
|
||||
DVLOG(2) << "Corrupt Rappor secret found.";
|
||||
RecordLoadSecretResult(LOAD_CORRUPT_VALUE);
|
||||
} else {
|
||||
DVLOG(2) << "No Rappor secret found.";
|
||||
RecordLoadSecretResult(LOAD_EMPTY_VALUE);
|
||||
}
|
||||
|
||||
DVLOG(2) << "Generated a new Rappor secret.";
|
||||
secret = HmacByteVectorGenerator::GenerateEntropyInput();
|
||||
base::Base64Encode(secret, &secret_base64);
|
||||
pref_service->SetString(prefs::kRapporSecret, secret_base64);
|
||||
return secret;
|
||||
}
|
||||
|
||||
} // namespace internal
|
||||
|
||||
} // namespace rappor
|
@ -1,46 +0,0 @@
|
||||
// Copyright 2015 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.
|
||||
|
||||
#ifndef COMPONENTS_RAPPOR_RAPPOR_PREFS_H_
|
||||
#define COMPONENTS_RAPPOR_RAPPOR_PREFS_H_
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
#include <string>
|
||||
|
||||
|
||||
class PrefService;
|
||||
class PrefRegistrySimple;
|
||||
|
||||
namespace rappor {
|
||||
|
||||
namespace internal {
|
||||
|
||||
enum LoadResult {
|
||||
LOAD_SUCCESS = 0,
|
||||
LOAD_EMPTY_VALUE,
|
||||
LOAD_CORRUPT_VALUE,
|
||||
NUM_LOAD_RESULTS,
|
||||
};
|
||||
|
||||
extern const char kLoadCohortHistogramName[];
|
||||
extern const char kLoadSecretHistogramName[];
|
||||
|
||||
// Registers all rappor preferences.
|
||||
void RegisterPrefs(PrefRegistrySimple* registry);
|
||||
|
||||
// Retrieves the cohort number this client was assigned to, generating it if
|
||||
// doesn't already exist. The cohort should be persistent.
|
||||
int32_t LoadCohort(PrefService* pref_service);
|
||||
|
||||
// Retrieves the value for secret from preferences, generating it if doesn't
|
||||
// already exist. The secret should be persistent, so that additional bits
|
||||
// from the client do not get exposed over time.
|
||||
std::string LoadSecret(PrefService* pref_service);
|
||||
|
||||
} // namespace internal
|
||||
|
||||
} // namespace rappor
|
||||
|
||||
#endif // COMPONENTS_RAPPOR_RAPPOR_PREFS_H_
|
@ -1,139 +0,0 @@
|
||||
// Copyright 2015 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/rappor/rappor_prefs.h"
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
#include "base/base64.h"
|
||||
#include "base/macros.h"
|
||||
#include "base/test/metrics/histogram_tester.h"
|
||||
#include "components/prefs/testing_pref_service.h"
|
||||
#include "components/rappor/byte_vector_utils.h"
|
||||
#include "components/rappor/proto/rappor_metric.pb.h"
|
||||
#include "components/rappor/rappor_pref_names.h"
|
||||
#include "testing/gtest/include/gtest/gtest.h"
|
||||
|
||||
namespace rappor {
|
||||
|
||||
namespace internal {
|
||||
|
||||
namespace {
|
||||
|
||||
// Convert a secret to base 64 and store it in preferences.
|
||||
void StoreSecret(const std::string& secret,
|
||||
TestingPrefServiceSimple* test_prefs) {
|
||||
std::string secret_base64;
|
||||
base::Base64Encode(secret, &secret_base64);
|
||||
test_prefs->SetString(prefs::kRapporSecret, secret_base64);
|
||||
}
|
||||
|
||||
// Verify that the current value of the secret pref matches the loaded secret.
|
||||
void ExpectConsistentSecret(const TestingPrefServiceSimple& test_prefs,
|
||||
const std::string& loaded_secret) {
|
||||
std::string pref = test_prefs.GetString(prefs::kRapporSecret);
|
||||
std::string decoded_pref;
|
||||
EXPECT_TRUE(base::Base64Decode(pref, &decoded_pref));
|
||||
EXPECT_EQ(loaded_secret, decoded_pref);
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
class RapporPrefsTest : public testing::Test {
|
||||
public:
|
||||
RapporPrefsTest() {
|
||||
RegisterPrefs(test_prefs_.registry());
|
||||
}
|
||||
|
||||
protected:
|
||||
base::HistogramTester tester_;
|
||||
TestingPrefServiceSimple test_prefs_;
|
||||
|
||||
DISALLOW_COPY_AND_ASSIGN(RapporPrefsTest);
|
||||
};
|
||||
|
||||
TEST_F(RapporPrefsTest, EmptyCohort) {
|
||||
test_prefs_.ClearPref(prefs::kRapporCohortSeed);
|
||||
// Loaded cohort should have been rerolled into a valid number.
|
||||
int32_t cohort = LoadCohort(&test_prefs_);
|
||||
tester_.ExpectUniqueSample(kLoadCohortHistogramName, LOAD_EMPTY_VALUE, 1);
|
||||
EXPECT_GE(cohort, 0);
|
||||
EXPECT_LT(cohort, RapporParameters::kMaxCohorts);
|
||||
// The preferences should be consistent with the loaded value.
|
||||
int32_t pref = test_prefs_.GetInteger(prefs::kRapporCohortSeed);
|
||||
EXPECT_EQ(pref, cohort);
|
||||
}
|
||||
|
||||
TEST_F(RapporPrefsTest, LoadCohort) {
|
||||
test_prefs_.SetInteger(prefs::kRapporCohortSeed, 1);
|
||||
// Loading the valid cohort should just retrieve it.
|
||||
int32_t cohort = LoadCohort(&test_prefs_);
|
||||
tester_.ExpectUniqueSample(kLoadCohortHistogramName, LOAD_SUCCESS, 1);
|
||||
EXPECT_EQ(1, cohort);
|
||||
// The preferences should be consistent with the loaded value.
|
||||
int32_t pref = test_prefs_.GetInteger(prefs::kRapporCohortSeed);
|
||||
EXPECT_EQ(pref, cohort);
|
||||
}
|
||||
|
||||
TEST_F(RapporPrefsTest, CorruptCohort) {
|
||||
// Set an invalid cohort value in the preference.
|
||||
test_prefs_.SetInteger(prefs::kRapporCohortSeed, -10);
|
||||
// Loaded cohort should have been rerolled into a valid number.
|
||||
int32_t cohort = LoadCohort(&test_prefs_);
|
||||
tester_.ExpectUniqueSample(kLoadCohortHistogramName, LOAD_CORRUPT_VALUE, 1);
|
||||
EXPECT_GE(cohort, 0);
|
||||
EXPECT_LT(cohort, RapporParameters::kMaxCohorts);
|
||||
// The preferences should be consistent with the loaded value.
|
||||
int32_t pref = test_prefs_.GetInteger(prefs::kRapporCohortSeed);
|
||||
EXPECT_EQ(pref, cohort);
|
||||
}
|
||||
|
||||
TEST_F(RapporPrefsTest, EmptySecret) {
|
||||
test_prefs_.ClearPref(prefs::kRapporSecret);
|
||||
// Loaded secret should be rerolled from empty.
|
||||
std::string secret2 = LoadSecret(&test_prefs_);
|
||||
tester_.ExpectUniqueSample(kLoadSecretHistogramName, LOAD_EMPTY_VALUE, 1);
|
||||
EXPECT_EQ(HmacByteVectorGenerator::kEntropyInputSize, secret2.size());
|
||||
// The stored preference should also be updated.
|
||||
ExpectConsistentSecret(test_prefs_, secret2);
|
||||
}
|
||||
|
||||
TEST_F(RapporPrefsTest, LoadSecret) {
|
||||
std::string secret1 = HmacByteVectorGenerator::GenerateEntropyInput();
|
||||
StoreSecret(secret1, &test_prefs_);
|
||||
// Secret should load successfully.
|
||||
std::string secret2 = LoadSecret(&test_prefs_);
|
||||
tester_.ExpectUniqueSample(kLoadSecretHistogramName, LOAD_SUCCESS, 1);
|
||||
EXPECT_EQ(secret1, secret2);
|
||||
// The stored preference should also be unchanged.
|
||||
ExpectConsistentSecret(test_prefs_, secret2);
|
||||
}
|
||||
|
||||
TEST_F(RapporPrefsTest, CorruptSecret) {
|
||||
// Store an invalid secret in the preferences that won't decode as base64.
|
||||
test_prefs_.SetString(prefs::kRapporSecret, "!!INVALID!!");
|
||||
// We should have rerolled a new secret.
|
||||
std::string secret2 = LoadSecret(&test_prefs_);
|
||||
tester_.ExpectUniqueSample(kLoadSecretHistogramName, LOAD_CORRUPT_VALUE, 1);
|
||||
EXPECT_EQ(HmacByteVectorGenerator::kEntropyInputSize, secret2.size());
|
||||
// The stored preference should also be updated.
|
||||
ExpectConsistentSecret(test_prefs_, secret2);
|
||||
}
|
||||
|
||||
TEST_F(RapporPrefsTest, DecodableCorruptSecret) {
|
||||
// Store an invalid secret in the preferences that will decode as base64.
|
||||
std::string secret1 = "!!INVALID!!";
|
||||
StoreSecret(secret1, &test_prefs_);
|
||||
// We should have rerolled a new secret.
|
||||
std::string secret2 = LoadSecret(&test_prefs_);
|
||||
tester_.ExpectUniqueSample(kLoadSecretHistogramName, LOAD_CORRUPT_VALUE, 1);
|
||||
EXPECT_NE(secret1, secret2);
|
||||
EXPECT_EQ(HmacByteVectorGenerator::kEntropyInputSize, secret2.size());
|
||||
// The stored preference should also be updated.
|
||||
ExpectConsistentSecret(test_prefs_, secret2);
|
||||
}
|
||||
|
||||
} // namespace internal
|
||||
|
||||
} // namespace rappor
|
@ -1,240 +0,0 @@
|
||||
// Copyright 2014 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/rappor/rappor_service_impl.h"
|
||||
|
||||
#include <memory>
|
||||
#include <utility>
|
||||
|
||||
#include "base/memory/ptr_util.h"
|
||||
#include "base/metrics/metrics_hashes.h"
|
||||
#include "base/time/time.h"
|
||||
#include "components/rappor/log_uploader.h"
|
||||
#include "components/rappor/proto/rappor_metric.pb.h"
|
||||
#include "components/rappor/rappor_metric.h"
|
||||
#include "components/rappor/rappor_pref_names.h"
|
||||
#include "components/rappor/rappor_prefs.h"
|
||||
#include "components/variations/variations_associated_data.h"
|
||||
#include "services/network/public/cpp/shared_url_loader_factory.h"
|
||||
|
||||
namespace rappor {
|
||||
|
||||
namespace {
|
||||
|
||||
// Seconds before the initial log is generated.
|
||||
const int kInitialLogIntervalSeconds = 15;
|
||||
// Interval between ongoing logs.
|
||||
const int kLogIntervalSeconds = 30 * 60;
|
||||
|
||||
const char kMimeType[] = "application/vnd.chrome.rappor";
|
||||
|
||||
const char kRapporDailyEventHistogram[] = "Rappor.DailyEvent.IntervalType";
|
||||
|
||||
// The rappor server's URL.
|
||||
const char kDefaultServerUrl[] = "https://clients4.google.com/rappor";
|
||||
|
||||
} // namespace
|
||||
|
||||
RapporServiceImpl::RapporServiceImpl(
|
||||
PrefService* pref_service,
|
||||
base::RepeatingCallback<bool(void)> is_incognito_callback)
|
||||
: pref_service_(pref_service),
|
||||
is_incognito_callback_(std::move(is_incognito_callback)),
|
||||
cohort_(-1),
|
||||
daily_event_(pref_service,
|
||||
prefs::kRapporLastDailySample,
|
||||
kRapporDailyEventHistogram),
|
||||
recording_enabled_(false) {}
|
||||
|
||||
RapporServiceImpl::~RapporServiceImpl() {}
|
||||
|
||||
void RapporServiceImpl::AddDailyObserver(
|
||||
std::unique_ptr<metrics::DailyEvent::Observer> observer) {
|
||||
daily_event_.AddObserver(std::move(observer));
|
||||
}
|
||||
|
||||
void RapporServiceImpl::Initialize(
|
||||
scoped_refptr<network::SharedURLLoaderFactory> url_loader_factory) {
|
||||
DCHECK(thread_checker_.CalledOnValidThread());
|
||||
DCHECK(!IsInitialized());
|
||||
const GURL server_url = GURL(kDefaultServerUrl);
|
||||
if (!server_url.is_valid()) {
|
||||
DVLOG(1) << server_url.spec() << " is invalid. "
|
||||
<< "RapporServiceImpl not started.";
|
||||
return;
|
||||
}
|
||||
DVLOG(1) << "RapporServiceImpl reporting to " << server_url.spec();
|
||||
InitializeInternal(
|
||||
std::make_unique<LogUploader>(server_url, kMimeType, url_loader_factory),
|
||||
internal::LoadCohort(pref_service_), internal::LoadSecret(pref_service_));
|
||||
}
|
||||
|
||||
void RapporServiceImpl::Update(bool may_record, bool may_upload) {
|
||||
DCHECK(thread_checker_.CalledOnValidThread());
|
||||
DCHECK(IsInitialized());
|
||||
if (recording_enabled_ != may_record) {
|
||||
recording_enabled_ = may_record;
|
||||
if (!may_record) {
|
||||
DVLOG(1) << "Rappor service stopped because all groups were disabled.";
|
||||
CancelNextLogRotation();
|
||||
} else {
|
||||
DVLOG(1) << "RapporServiceImpl started.";
|
||||
ScheduleNextLogRotation(
|
||||
base::TimeDelta::FromSeconds(kInitialLogIntervalSeconds));
|
||||
}
|
||||
}
|
||||
|
||||
DVLOG(1) << "RapporServiceImpl recording_groups=" << recording_enabled_
|
||||
<< " may_upload=" << may_upload;
|
||||
if (may_upload) {
|
||||
uploader_->Start();
|
||||
} else {
|
||||
uploader_->Stop();
|
||||
}
|
||||
}
|
||||
|
||||
// static
|
||||
void RapporServiceImpl::RegisterPrefs(PrefRegistrySimple* registry) {
|
||||
internal::RegisterPrefs(registry);
|
||||
}
|
||||
|
||||
void RapporServiceImpl::InitializeInternal(
|
||||
std::unique_ptr<LogUploaderInterface> uploader,
|
||||
int32_t cohort,
|
||||
const std::string& secret) {
|
||||
DCHECK(thread_checker_.CalledOnValidThread());
|
||||
DCHECK(!IsInitialized());
|
||||
DCHECK(secret_.empty());
|
||||
uploader_.swap(uploader);
|
||||
cohort_ = cohort;
|
||||
secret_ = secret;
|
||||
}
|
||||
|
||||
void RapporServiceImpl::CancelNextLogRotation() {
|
||||
DCHECK(thread_checker_.CalledOnValidThread());
|
||||
metrics_map_.clear();
|
||||
log_rotation_timer_.Stop();
|
||||
}
|
||||
|
||||
void RapporServiceImpl::ScheduleNextLogRotation(base::TimeDelta interval) {
|
||||
log_rotation_timer_.Start(FROM_HERE, interval, this,
|
||||
&RapporServiceImpl::OnLogInterval);
|
||||
}
|
||||
|
||||
void RapporServiceImpl::OnLogInterval() {
|
||||
DCHECK(thread_checker_.CalledOnValidThread());
|
||||
DCHECK(uploader_);
|
||||
DVLOG(2) << "RapporServiceImpl::OnLogInterval";
|
||||
daily_event_.CheckInterval();
|
||||
RapporReports reports;
|
||||
if (ExportMetrics(&reports)) {
|
||||
std::string log_text;
|
||||
bool success = reports.SerializeToString(&log_text);
|
||||
DCHECK(success);
|
||||
DVLOG(1) << "RapporServiceImpl sending a report of "
|
||||
<< reports.report_size() << " value(s).";
|
||||
uploader_->QueueLog(log_text);
|
||||
}
|
||||
ScheduleNextLogRotation(base::TimeDelta::FromSeconds(kLogIntervalSeconds));
|
||||
}
|
||||
|
||||
bool RapporServiceImpl::ExportMetrics(RapporReports* reports) {
|
||||
DCHECK(thread_checker_.CalledOnValidThread());
|
||||
DCHECK_GE(cohort_, 0);
|
||||
reports->set_cohort(cohort_);
|
||||
|
||||
for (const auto& kv : metrics_map_) {
|
||||
const RapporMetric* metric = kv.second.get();
|
||||
RapporReports::Report* report = reports->add_report();
|
||||
report->set_name_hash(base::HashMetricName(kv.first));
|
||||
ByteVector bytes = metric->GetReport(secret_);
|
||||
report->set_bits(std::string(bytes.begin(), bytes.end()));
|
||||
DVLOG(2) << "Exporting metric " << kv.first;
|
||||
}
|
||||
metrics_map_.clear();
|
||||
|
||||
sampler_.ExportMetrics(secret_, reports);
|
||||
|
||||
DVLOG(2) << "Generated a report with " << reports->report_size()
|
||||
<< " metrics.";
|
||||
return reports->report_size() > 0;
|
||||
}
|
||||
|
||||
bool RapporServiceImpl::IsInitialized() const {
|
||||
return cohort_ >= 0;
|
||||
}
|
||||
|
||||
bool RapporServiceImpl::RecordingAllowed(const RapporParameters& parameters) {
|
||||
// Skip recording in incognito mode.
|
||||
if (is_incognito_callback_.Run()) {
|
||||
DVLOG(2) << "Metric not logged due to incognito mode.";
|
||||
return false;
|
||||
}
|
||||
// Skip this metric if its recording_group is not enabled.
|
||||
if (!recording_enabled_) {
|
||||
DVLOG(2) << "Metric not logged due to recording_enabled_ = false.";
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
void RapporServiceImpl::RecordSampleString(const std::string& metric_name,
|
||||
RapporType type,
|
||||
const std::string& sample) {
|
||||
DCHECK(thread_checker_.CalledOnValidThread());
|
||||
// Ignore the sample if the service hasn't started yet.
|
||||
if (!IsInitialized())
|
||||
return;
|
||||
DCHECK_LT(type, NUM_RAPPOR_TYPES);
|
||||
const RapporParameters& parameters = internal::kRapporParametersForType[type];
|
||||
DVLOG(2) << "Recording sample \"" << sample << "\" for metric \""
|
||||
<< metric_name << "\" of type: " << type;
|
||||
RecordSampleInternal(metric_name, parameters, sample);
|
||||
}
|
||||
|
||||
void RapporServiceImpl::RecordSampleInternal(const std::string& metric_name,
|
||||
const RapporParameters& parameters,
|
||||
const std::string& sample) {
|
||||
DCHECK(thread_checker_.CalledOnValidThread());
|
||||
DCHECK(IsInitialized());
|
||||
if (!RecordingAllowed(parameters))
|
||||
return;
|
||||
RapporMetric* metric = LookUpMetric(metric_name, parameters);
|
||||
metric->AddSample(sample);
|
||||
}
|
||||
|
||||
RapporMetric* RapporServiceImpl::LookUpMetric(
|
||||
const std::string& metric_name,
|
||||
const RapporParameters& parameters) {
|
||||
DCHECK(thread_checker_.CalledOnValidThread());
|
||||
DCHECK(IsInitialized());
|
||||
auto it = metrics_map_.find(metric_name);
|
||||
if (it != metrics_map_.end()) {
|
||||
RapporMetric* metric = it->second.get();
|
||||
DCHECK_EQ(parameters.ToString(), metric->parameters().ToString());
|
||||
return metric;
|
||||
}
|
||||
|
||||
RapporMetric* new_metric = new RapporMetric(metric_name, parameters, cohort_);
|
||||
metrics_map_[metric_name] = base::WrapUnique(new_metric);
|
||||
return new_metric;
|
||||
}
|
||||
|
||||
std::unique_ptr<Sample> RapporServiceImpl::CreateSample(RapporType type) {
|
||||
DCHECK(thread_checker_.CalledOnValidThread());
|
||||
DCHECK(IsInitialized());
|
||||
return base::WrapUnique(
|
||||
new Sample(cohort_, internal::kRapporParametersForType[type]));
|
||||
}
|
||||
|
||||
void RapporServiceImpl::RecordSample(const std::string& metric_name,
|
||||
std::unique_ptr<Sample> sample) {
|
||||
DCHECK(thread_checker_.CalledOnValidThread());
|
||||
if (!RecordingAllowed(sample->parameters()))
|
||||
return;
|
||||
DVLOG(1) << "Recording sample of metric \"" << metric_name << "\"";
|
||||
sampler_.AddSample(metric_name, std::move(sample));
|
||||
}
|
||||
|
||||
} // namespace rappor
|
@ -1,172 +0,0 @@
|
||||
// Copyright 2014 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.
|
||||
|
||||
#ifndef COMPONENTS_RAPPOR_RAPPOR_SERVICE_IMPL_H_
|
||||
#define COMPONENTS_RAPPOR_RAPPOR_SERVICE_IMPL_H_
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
#include <map>
|
||||
#include <memory>
|
||||
#include <string>
|
||||
|
||||
#include "base/callback.h"
|
||||
#include "base/macros.h"
|
||||
#include "base/memory/scoped_refptr.h"
|
||||
#include "base/threading/thread_checker.h"
|
||||
#include "base/timer/timer.h"
|
||||
#include "components/metrics/daily_event.h"
|
||||
#include "components/rappor/public/rappor_parameters.h"
|
||||
#include "components/rappor/public/rappor_service.h"
|
||||
#include "components/rappor/public/sample.h"
|
||||
#include "components/rappor/sampler.h"
|
||||
|
||||
class PrefRegistrySimple;
|
||||
class PrefService;
|
||||
|
||||
namespace network {
|
||||
class SharedURLLoaderFactory;
|
||||
}
|
||||
|
||||
namespace rappor {
|
||||
|
||||
class LogUploaderInterface;
|
||||
class RapporMetric;
|
||||
class RapporReports;
|
||||
|
||||
// This class provides an interface for recording samples for rappor metrics,
|
||||
// and periodically generates and uploads reports based on the collected data.
|
||||
class RapporServiceImpl : public RapporService {
|
||||
public:
|
||||
// Constructs a RapporServiceImpl.
|
||||
// Calling code is responsible for ensuring that the lifetime of
|
||||
// |pref_service| is longer than the lifetime of RapporServiceImpl.
|
||||
// |is_incognito_callback| will be called to test if incognito mode is active.
|
||||
RapporServiceImpl(PrefService* pref_service,
|
||||
base::RepeatingCallback<bool(void)> is_incognito_callback);
|
||||
virtual ~RapporServiceImpl();
|
||||
|
||||
// Add an observer for collecting daily metrics.
|
||||
void AddDailyObserver(
|
||||
std::unique_ptr<metrics::DailyEvent::Observer> observer);
|
||||
|
||||
// Initializes the rappor service, including loading the cohort and secret
|
||||
// preferences from disk.
|
||||
void Initialize(
|
||||
scoped_refptr<network::SharedURLLoaderFactory> url_loader_factory);
|
||||
|
||||
// Updates the settings for metric recording and uploading.
|
||||
// The RapporServiceImpl must be initialized before this method is called.
|
||||
// If |may_record| is true, data will be recorded and periodic reports will
|
||||
// be generated and queued for upload.
|
||||
// If |may_upload| is true, reports will be uploaded from the queue.
|
||||
void Update(bool may_record, bool may_upload);
|
||||
|
||||
// Constructs a Sample object for the caller to record fields in.
|
||||
std::unique_ptr<Sample> CreateSample(RapporType) override;
|
||||
|
||||
// Records a Sample of rappor metric specified by |metric_name|.
|
||||
//
|
||||
// example:
|
||||
// std::unique_ptr<Sample> sample =
|
||||
// rappor_service->CreateSample(MY_METRIC_TYPE);
|
||||
// sample->SetStringField("Field1", "some string");
|
||||
// sample->SetFlagsValue("Field2", SOME|FLAGS);
|
||||
// rappor_service->RecordSample("MyMetric", std::move(sample));
|
||||
//
|
||||
// This will result in a report setting two metrics "MyMetric.Field1" and
|
||||
// "MyMetric.Field2", and they will both be generated from the same sample,
|
||||
// to allow for correlations to be computed.
|
||||
void RecordSample(const std::string& metric_name,
|
||||
std::unique_ptr<Sample> sample) override;
|
||||
|
||||
// Records a sample of the rappor metric specified by |metric_name|.
|
||||
// Creates and initializes the metric, if it doesn't yet exist.
|
||||
void RecordSampleString(const std::string& metric_name,
|
||||
RapporType type,
|
||||
const std::string& sample) override;
|
||||
|
||||
// Registers the names of all of the preferences used by RapporServiceImpl in
|
||||
// the provided PrefRegistry. This should be called before calling Start().
|
||||
static void RegisterPrefs(PrefRegistrySimple* registry);
|
||||
|
||||
protected:
|
||||
// Initializes the state of the RapporServiceImpl.
|
||||
void InitializeInternal(std::unique_ptr<LogUploaderInterface> uploader,
|
||||
int32_t cohort,
|
||||
const std::string& secret);
|
||||
|
||||
// Cancels the next call to OnLogInterval.
|
||||
virtual void CancelNextLogRotation();
|
||||
|
||||
// Schedules the next call to OnLogInterval.
|
||||
virtual void ScheduleNextLogRotation(base::TimeDelta interval);
|
||||
|
||||
// Logs all of the collected metrics to the reports proto message and clears
|
||||
// the internal map. Exposed for tests. Returns true if any metrics were
|
||||
// recorded.
|
||||
bool ExportMetrics(RapporReports* reports);
|
||||
|
||||
private:
|
||||
// Records a sample of the rappor metric specified by |parameters|.
|
||||
// Creates and initializes the metric, if it doesn't yet exist.
|
||||
// Exposed for tests.
|
||||
void RecordSampleInternal(const std::string& metric_name,
|
||||
const RapporParameters& parameters,
|
||||
const std::string& sample);
|
||||
|
||||
// Checks if the service has been started successfully.
|
||||
bool IsInitialized() const;
|
||||
|
||||
// Called whenever the logging interval elapses to generate a new log of
|
||||
// reports and pass it to the uploader.
|
||||
void OnLogInterval();
|
||||
|
||||
// Check if recording of the metric is allowed, given it's parameters.
|
||||
// This will check that we are not in incognito mode, and that the
|
||||
// appropriate recording group is enabled.
|
||||
bool RecordingAllowed(const RapporParameters& parameters);
|
||||
|
||||
// Finds a metric in the metrics_map_, creating it if it doesn't already
|
||||
// exist.
|
||||
RapporMetric* LookUpMetric(const std::string& metric_name,
|
||||
const RapporParameters& parameters);
|
||||
|
||||
// A weak pointer to the PrefService used to read and write preferences.
|
||||
PrefService* pref_service_;
|
||||
|
||||
// A callback for testing if incognito mode is active;
|
||||
const base::RepeatingCallback<bool(void)> is_incognito_callback_;
|
||||
|
||||
// Client-side secret used to generate fake bits.
|
||||
std::string secret_;
|
||||
|
||||
// The cohort this client is assigned to. -1 is uninitialized.
|
||||
int32_t cohort_;
|
||||
|
||||
// Timer which schedules calls to OnLogInterval().
|
||||
base::OneShotTimer log_rotation_timer_;
|
||||
|
||||
// A daily event for collecting metrics once a day.
|
||||
metrics::DailyEvent daily_event_;
|
||||
|
||||
// A private LogUploader instance for sending reports to the server.
|
||||
std::unique_ptr<LogUploaderInterface> uploader_;
|
||||
|
||||
// Whether new data can be recorded.
|
||||
bool recording_enabled_;
|
||||
|
||||
// We keep all registered metrics in a map, from name to metric.
|
||||
std::map<std::string, std::unique_ptr<RapporMetric>> metrics_map_;
|
||||
|
||||
internal::Sampler sampler_;
|
||||
|
||||
base::ThreadChecker thread_checker_;
|
||||
|
||||
DISALLOW_COPY_AND_ASSIGN(RapporServiceImpl);
|
||||
};
|
||||
|
||||
} // namespace rappor
|
||||
|
||||
#endif // COMPONENTS_RAPPOR_RAPPOR_SERVICE_IMPL_H_
|
@ -1,134 +0,0 @@
|
||||
// Copyright 2014 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/rappor/rappor_service_impl.h"
|
||||
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
|
||||
#include <memory>
|
||||
#include <utility>
|
||||
|
||||
#include "base/base64.h"
|
||||
#include "base/metrics/metrics_hashes.h"
|
||||
#include "components/prefs/testing_pref_service.h"
|
||||
#include "components/rappor/byte_vector_utils.h"
|
||||
#include "components/rappor/proto/rappor_metric.pb.h"
|
||||
#include "components/rappor/public/rappor_parameters.h"
|
||||
#include "components/rappor/rappor_pref_names.h"
|
||||
#include "components/rappor/test_log_uploader.h"
|
||||
#include "components/rappor/test_rappor_service.h"
|
||||
#include "testing/gtest/include/gtest/gtest.h"
|
||||
|
||||
namespace rappor {
|
||||
|
||||
TEST(RapporServiceImplTest, Update) {
|
||||
// Test rappor service initially has uploading and reporting enabled.
|
||||
TestRapporServiceImpl rappor_service;
|
||||
EXPECT_LT(base::TimeDelta(), rappor_service.next_rotation());
|
||||
EXPECT_TRUE(rappor_service.test_uploader()->is_running());
|
||||
|
||||
// Disabling both should stop both uploads and reports.
|
||||
rappor_service.Update(false, false);
|
||||
EXPECT_EQ(base::TimeDelta(), rappor_service.next_rotation());
|
||||
EXPECT_FALSE(rappor_service.test_uploader()->is_running());
|
||||
|
||||
// Recording, but no reporting.
|
||||
rappor_service.Update(true, false);
|
||||
// Reports generation should still be scheduled.
|
||||
EXPECT_LT(base::TimeDelta(), rappor_service.next_rotation());
|
||||
EXPECT_FALSE(rappor_service.test_uploader()->is_running());
|
||||
|
||||
// Recording and reporting enabled.
|
||||
rappor_service.Update(true, true);
|
||||
EXPECT_LT(base::TimeDelta(), rappor_service.next_rotation());
|
||||
EXPECT_TRUE(rappor_service.test_uploader()->is_running());
|
||||
}
|
||||
|
||||
// Check that samples can be recorded and exported.
|
||||
TEST(RapporServiceImplTest, RecordAndExportMetrics) {
|
||||
TestRapporServiceImpl rappor_service;
|
||||
|
||||
// Multiple samples for the same metric should only generate one report.
|
||||
rappor_service.RecordSampleString("MyMetric", ETLD_PLUS_ONE_RAPPOR_TYPE,
|
||||
"foo");
|
||||
rappor_service.RecordSampleString("MyMetric", ETLD_PLUS_ONE_RAPPOR_TYPE,
|
||||
"bar");
|
||||
|
||||
RapporReports reports;
|
||||
rappor_service.GetReports(&reports);
|
||||
EXPECT_EQ(1, reports.report_size());
|
||||
|
||||
const RapporReports::Report& report = reports.report(0);
|
||||
EXPECT_TRUE(report.name_hash());
|
||||
// ETLD_PLUS_ONE_RAPPOR_TYPE has 128 bits
|
||||
EXPECT_EQ(16u, report.bits().size());
|
||||
}
|
||||
|
||||
// Check that reporting_enabled_ is respected.
|
||||
TEST(RapporServiceImplTest, UmaRecordingGroup) {
|
||||
TestRapporServiceImpl rappor_service;
|
||||
rappor_service.Update(false, false);
|
||||
|
||||
// Reporting disabled.
|
||||
rappor_service.RecordSampleString("UmaMetric", UMA_RAPPOR_TYPE, "foo");
|
||||
|
||||
RapporReports reports;
|
||||
rappor_service.GetReports(&reports);
|
||||
EXPECT_EQ(0, reports.report_size());
|
||||
}
|
||||
|
||||
// Check that GetRecordedSampleForMetric works as expected.
|
||||
TEST(RapporServiceImplTest, GetRecordedSampleForMetric) {
|
||||
TestRapporServiceImpl rappor_service;
|
||||
|
||||
// Multiple samples for the same metric; only the latest is remembered.
|
||||
rappor_service.RecordSampleString("MyMetric", ETLD_PLUS_ONE_RAPPOR_TYPE,
|
||||
"foo");
|
||||
rappor_service.RecordSampleString("MyMetric", ETLD_PLUS_ONE_RAPPOR_TYPE,
|
||||
"bar");
|
||||
|
||||
std::string sample;
|
||||
RapporType type;
|
||||
EXPECT_FALSE(
|
||||
rappor_service.GetRecordedSampleForMetric("WrongMetric", &sample, &type));
|
||||
EXPECT_TRUE(
|
||||
rappor_service.GetRecordedSampleForMetric("MyMetric", &sample, &type));
|
||||
EXPECT_EQ("bar", sample);
|
||||
EXPECT_EQ(ETLD_PLUS_ONE_RAPPOR_TYPE, type);
|
||||
}
|
||||
|
||||
// Check that the incognito is respected.
|
||||
TEST(RapporServiceImplTest, Incognito) {
|
||||
TestRapporServiceImpl rappor_service;
|
||||
rappor_service.set_is_incognito(true);
|
||||
|
||||
rappor_service.RecordSampleString("MyMetric", UMA_RAPPOR_TYPE, "foo");
|
||||
|
||||
RapporReports reports;
|
||||
rappor_service.GetReports(&reports);
|
||||
EXPECT_EQ(0, reports.report_size());
|
||||
}
|
||||
|
||||
// Check that Sample objects record correctly.
|
||||
TEST(RapporServiceImplTest, RecordSample) {
|
||||
TestRapporServiceImpl rappor_service;
|
||||
std::unique_ptr<Sample> sample = rappor_service.CreateSample(UMA_RAPPOR_TYPE);
|
||||
sample->SetStringField("Url", "example.com");
|
||||
sample->SetFlagsField("Flags1", 0xbcd, 12);
|
||||
rappor_service.RecordSample("ObjMetric", std::move(sample));
|
||||
uint64_t url_hash = base::HashMetricName("ObjMetric.Url");
|
||||
uint64_t flags_hash = base::HashMetricName("ObjMetric.Flags1");
|
||||
RapporReports reports;
|
||||
rappor_service.GetReports(&reports);
|
||||
EXPECT_EQ(2, reports.report_size());
|
||||
size_t url_index = reports.report(0).name_hash() == url_hash ? 0 : 1;
|
||||
size_t flags_index = url_index == 0 ? 1 : 0;
|
||||
EXPECT_EQ(url_hash, reports.report(url_index).name_hash());
|
||||
EXPECT_EQ(4u, reports.report(url_index).bits().size());
|
||||
EXPECT_EQ(flags_hash, reports.report(flags_index).name_hash());
|
||||
EXPECT_EQ(2u, reports.report(flags_index).bits().size());
|
||||
}
|
||||
|
||||
} // namespace rappor
|
@ -1,56 +0,0 @@
|
||||
// Copyright 2015 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/rappor/public/rappor_utils.h"
|
||||
|
||||
#include "net/base/registry_controlled_domains/registry_controlled_domain.h"
|
||||
#include "net/base/url_util.h"
|
||||
#include "url/gurl.h"
|
||||
|
||||
namespace rappor {
|
||||
|
||||
void SampleString(RapporService* rappor_service,
|
||||
const std::string& metric,
|
||||
RapporType type,
|
||||
const std::string& sample) {
|
||||
if (!rappor_service)
|
||||
return;
|
||||
rappor_service->RecordSampleString(metric, type, sample);
|
||||
}
|
||||
|
||||
std::string GetDomainAndRegistrySampleFromGURL(const GURL& gurl) {
|
||||
if (gurl.SchemeIsHTTPOrHTTPS()) {
|
||||
if (net::IsLocalhost(gurl))
|
||||
return "localhost";
|
||||
if (gurl.HostIsIPAddress())
|
||||
return "ip_address";
|
||||
return net::registry_controlled_domains::GetDomainAndRegistry(
|
||||
gurl, net::registry_controlled_domains::INCLUDE_PRIVATE_REGISTRIES);
|
||||
}
|
||||
if (gurl.SchemeIsFile())
|
||||
return gurl.scheme() + "://";
|
||||
return gurl.scheme() + "://" + gurl.host();
|
||||
}
|
||||
|
||||
void SampleDomainAndRegistryFromGURL(RapporService* rappor_service,
|
||||
const std::string& metric,
|
||||
const GURL& gurl) {
|
||||
if (!rappor_service)
|
||||
return;
|
||||
rappor_service->RecordSampleString(metric, rappor::ETLD_PLUS_ONE_RAPPOR_TYPE,
|
||||
GetDomainAndRegistrySampleFromGURL(gurl));
|
||||
}
|
||||
|
||||
RapporService* (*g_GetDefaultService)() = nullptr;
|
||||
|
||||
RapporService* GetDefaultService() {
|
||||
return (g_GetDefaultService != nullptr) ? g_GetDefaultService() : nullptr;
|
||||
}
|
||||
|
||||
void SetDefaultServiceAccessor(RapporService* (*getDefaultService)()) {
|
||||
DCHECK(g_GetDefaultService == nullptr);
|
||||
g_GetDefaultService = getDefaultService;
|
||||
}
|
||||
|
||||
} // namespace rappor
|
@ -1,44 +0,0 @@
|
||||
// Copyright 2015 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/rappor/public/rappor_utils.h"
|
||||
|
||||
#include "testing/gtest/include/gtest/gtest.h"
|
||||
#include "url/gurl.h"
|
||||
|
||||
namespace rappor {
|
||||
|
||||
// Test that extracting the sample works correctly for different schemes.
|
||||
TEST(RapporSamplingTest, GetDomainAndRegistrySampleFromGURLTest) {
|
||||
EXPECT_EQ("google.com", GetDomainAndRegistrySampleFromGURL(
|
||||
GURL("https://www.GoOgLe.com:80/blah")));
|
||||
EXPECT_EQ("file://", GetDomainAndRegistrySampleFromGURL(
|
||||
GURL("file://foo/bar/baz")));
|
||||
EXPECT_EQ("chrome-extension://abc1234", GetDomainAndRegistrySampleFromGURL(
|
||||
GURL("chrome-extension://abc1234/foo.html")));
|
||||
EXPECT_EQ("chrome-search://local-ntp", GetDomainAndRegistrySampleFromGURL(
|
||||
GURL("chrome-search://local-ntp/local-ntp.html")));
|
||||
EXPECT_EQ("localhost", GetDomainAndRegistrySampleFromGURL(
|
||||
GURL("http://localhost:8000/foo.html")));
|
||||
EXPECT_EQ("localhost", GetDomainAndRegistrySampleFromGURL(
|
||||
GURL("http://127.0.0.1/foo.html")));
|
||||
EXPECT_EQ("localhost",
|
||||
GetDomainAndRegistrySampleFromGURL(GURL("http://[::1]/foo.html")));
|
||||
EXPECT_EQ("ip_address", GetDomainAndRegistrySampleFromGURL(
|
||||
GURL("http://192.168.0.1/foo.html")));
|
||||
EXPECT_EQ("ip_address", GetDomainAndRegistrySampleFromGURL(
|
||||
GURL("http://[2001:db8::1]/")));
|
||||
EXPECT_EQ("", GetDomainAndRegistrySampleFromGURL(
|
||||
GURL("http://www/")));
|
||||
EXPECT_EQ("www.corp", GetDomainAndRegistrySampleFromGURL(
|
||||
GURL("http://www.corp/")));
|
||||
}
|
||||
|
||||
// Make sure recording a sample during tests, when the Rappor service is NULL,
|
||||
// doesn't cause a crash.
|
||||
TEST(RapporSamplingTest, SmokeTest) {
|
||||
SampleDomainAndRegistryFromGURL(nullptr, std::string(), GURL());
|
||||
}
|
||||
|
||||
} // namespace rappor
|
@ -1,52 +0,0 @@
|
||||
// Copyright 2015 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/rappor/reports.h"
|
||||
|
||||
#include "base/rand_util.h"
|
||||
#include "base/strings/string_piece.h"
|
||||
#include "components/rappor/byte_vector_utils.h"
|
||||
#include "components/rappor/public/rappor_parameters.h"
|
||||
|
||||
namespace rappor {
|
||||
|
||||
namespace internal {
|
||||
|
||||
ByteVector GenerateReport(const std::string& secret,
|
||||
const NoiseParameters& parameters,
|
||||
const ByteVector& value) {
|
||||
// Generate a deterministically random mask of fake data using the
|
||||
// client's secret key + real data as a seed. The inclusion of the secret
|
||||
// in the seed avoids correlations between real and fake data.
|
||||
// The seed isn't a human-readable string.
|
||||
const base::StringPiece personalization_string(
|
||||
reinterpret_cast<const char*>(&value[0]), value.size());
|
||||
HmacByteVectorGenerator hmac_generator(value.size(), secret,
|
||||
personalization_string);
|
||||
const ByteVector fake_mask =
|
||||
hmac_generator.GetWeightedRandomByteVector(parameters.fake_prob);
|
||||
ByteVector fake_bits =
|
||||
hmac_generator.GetWeightedRandomByteVector(parameters.fake_one_prob);
|
||||
|
||||
// Redact most of the real data by replacing it with the fake data, hiding
|
||||
// and limiting the amount of information an individual client reports on.
|
||||
const ByteVector* fake_and_redacted_bits =
|
||||
ByteVectorMerge(fake_mask, value, &fake_bits);
|
||||
|
||||
// Generate biased coin flips for each bit.
|
||||
ByteVectorGenerator coin_generator(value.size());
|
||||
const ByteVector zero_coins =
|
||||
coin_generator.GetWeightedRandomByteVector(parameters.zero_coin_prob);
|
||||
ByteVector one_coins =
|
||||
coin_generator.GetWeightedRandomByteVector(parameters.one_coin_prob);
|
||||
|
||||
// Create a randomized response report on the fake and redacted data, sending
|
||||
// the outcome of flipping a zero coin for the zero bits in that data, and of
|
||||
// flipping a one coin for the one bits in that data, as the final report.
|
||||
return *ByteVectorMerge(*fake_and_redacted_bits, zero_coins, &one_coins);
|
||||
}
|
||||
|
||||
} // namespace internal
|
||||
|
||||
} // namespace rappor
|
@ -1,25 +0,0 @@
|
||||
// Copyright 2015 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.
|
||||
|
||||
#ifndef COMPONENTS_RAPPOR_REPORTS_H_
|
||||
#define COMPONENTS_RAPPOR_REPORTS_H_
|
||||
|
||||
#include "components/rappor/reports.h"
|
||||
|
||||
#include "components/rappor/byte_vector_utils.h"
|
||||
|
||||
namespace rappor {
|
||||
|
||||
namespace internal {
|
||||
|
||||
// Generate a randomized report for a single metric/field.
|
||||
ByteVector GenerateReport(const std::string& secret,
|
||||
const NoiseParameters& parameters,
|
||||
const ByteVector& value);
|
||||
|
||||
} // namespace internal
|
||||
|
||||
} // namespace rappor
|
||||
|
||||
#endif // COMPONENTS_RAPPOR_REPORTS_H_
|
@ -1,72 +0,0 @@
|
||||
// Copyright 2014 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/rappor/reports.h"
|
||||
|
||||
#include <stdlib.h>
|
||||
|
||||
#include "base/rand_util.h"
|
||||
#include "base/strings/stringprintf.h"
|
||||
#include "testing/gtest/include/gtest/gtest.h"
|
||||
|
||||
namespace rappor {
|
||||
|
||||
const NoiseParameters kTestNoiseParameters = {
|
||||
PROBABILITY_75 /* Fake data probability */,
|
||||
PROBABILITY_50 /* Fake one probability */,
|
||||
PROBABILITY_75 /* One coin probability */,
|
||||
PROBABILITY_50 /* Zero coin probability */,
|
||||
};
|
||||
|
||||
TEST(RapporMetricTest, GetReportStatistics) {
|
||||
ByteVector real_bits(50);
|
||||
// Set 152 bits (19 bytes)
|
||||
for (char i = 0; i < 19; i++) {
|
||||
real_bits[i] = 0xff;
|
||||
}
|
||||
|
||||
const int real_bit_count = CountBits(real_bits);
|
||||
EXPECT_EQ(real_bit_count, 152);
|
||||
|
||||
const std::string secret = HmacByteVectorGenerator::GenerateEntropyInput();
|
||||
const ByteVector report =
|
||||
internal::GenerateReport(secret, kTestNoiseParameters, real_bits);
|
||||
|
||||
// For the bits we actually set in the Bloom filter, get a count of how
|
||||
// many of them reported true.
|
||||
ByteVector from_true_reports = report;
|
||||
// Real bits AND report bits.
|
||||
ByteVectorMerge(real_bits, real_bits, &from_true_reports);
|
||||
const int true_from_true_count = CountBits(from_true_reports);
|
||||
|
||||
// For the bits we didn't set in the Bloom filter, get a count of how
|
||||
// many of them reported true.
|
||||
ByteVector from_false_reports = report;
|
||||
ByteVectorOr(real_bits, &from_false_reports);
|
||||
const int true_from_false_count =
|
||||
CountBits(from_false_reports) - real_bit_count;
|
||||
|
||||
// The probability of a true bit being true after redaction =
|
||||
// [fake_prob]*[fake_true_prob] + (1-[fake_prob]) =
|
||||
// .75 * .5 + (1-.75) = .625
|
||||
// The probablity of a false bit being true after redaction =
|
||||
// [fake_prob]*[fake_true_prob] = .375
|
||||
// The probability of a bit reporting true =
|
||||
// [redacted_prob] * [one_coin_prob:.75] +
|
||||
// (1-[redacted_prob]) * [zero_coin_prob:.5] =
|
||||
// 0.65625 for true bits
|
||||
// 0.59375 for false bits
|
||||
|
||||
// stats.binom(152, 0.65625).ppf(0.000005) = 73
|
||||
EXPECT_GT(true_from_true_count, 73);
|
||||
// stats.binom(152, 0.65625).ppf(0.999995) = 124
|
||||
EXPECT_LE(true_from_true_count, 124);
|
||||
|
||||
// stats.binom(248, 0.59375).ppf(.000005) = 113
|
||||
EXPECT_GT(true_from_false_count, 113);
|
||||
// stats.binom(248, 0.59375).ppf(.999995) = 181
|
||||
EXPECT_LE(true_from_false_count, 181);
|
||||
}
|
||||
|
||||
} // namespace rappor
|
@ -1,113 +0,0 @@
|
||||
// Copyright 2015 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/rappor/public/sample.h"
|
||||
|
||||
#include <map>
|
||||
#include <string>
|
||||
|
||||
#include "base/logging.h"
|
||||
#include "base/metrics/metrics_hashes.h"
|
||||
#include "components/rappor/bloom_filter.h"
|
||||
#include "components/rappor/byte_vector_utils.h"
|
||||
#include "components/rappor/proto/rappor_metric.pb.h"
|
||||
#include "components/rappor/reports.h"
|
||||
|
||||
namespace rappor {
|
||||
|
||||
Sample::Sample(int32_t cohort_seed, const RapporParameters& parameters)
|
||||
: parameters_(parameters),
|
||||
bloom_offset_((cohort_seed % parameters_.num_cohorts) *
|
||||
parameters_.bloom_filter_hash_function_count) {
|
||||
// Must use bloom filter size that fits in uint64_t.
|
||||
DCHECK_LE(parameters_.bloom_filter_size_bytes, 8u);
|
||||
}
|
||||
|
||||
Sample::~Sample() {
|
||||
}
|
||||
|
||||
void Sample::SetStringField(const std::string& field_name,
|
||||
const std::string& value) {
|
||||
DVLOG(2) << "Recording sample \"" << value
|
||||
<< "\" for sample metric field \"" << field_name << "\"";
|
||||
DCHECK_EQ(0u, field_info_[field_name].size);
|
||||
uint64_t bloom_bits = internal::GetBloomBits(
|
||||
parameters_.bloom_filter_size_bytes,
|
||||
parameters_.bloom_filter_hash_function_count,
|
||||
bloom_offset_,
|
||||
value);
|
||||
field_info_[field_name] = Sample::FieldInfo{
|
||||
parameters_.bloom_filter_size_bytes /* size */,
|
||||
bloom_bits /* value */,
|
||||
parameters_.noise_level,
|
||||
};
|
||||
}
|
||||
|
||||
void Sample::SetFlagsField(const std::string& field_name,
|
||||
uint64_t flags,
|
||||
size_t num_flags) {
|
||||
SetFlagsField(field_name, flags, num_flags, parameters_.noise_level);
|
||||
}
|
||||
|
||||
void Sample::SetFlagsField(const std::string& field_name,
|
||||
uint64_t flags,
|
||||
size_t num_flags,
|
||||
NoiseLevel noise_level) {
|
||||
if (noise_level == NO_NOISE) {
|
||||
// Non-noised fields can only be recorded for UMA rappor metrics.
|
||||
DCHECK_EQ(UMA_RAPPOR_GROUP, parameters_.recording_group);
|
||||
if (parameters_.recording_group != UMA_RAPPOR_GROUP)
|
||||
return;
|
||||
}
|
||||
DVLOG(2) << "Recording flags " << flags
|
||||
<< " for sample metric field \"" << field_name << "\"";
|
||||
DCHECK_EQ(0u, field_info_[field_name].size);
|
||||
DCHECK_GT(num_flags, 0u);
|
||||
DCHECK_LE(num_flags, 64u);
|
||||
DCHECK(num_flags == 64u || flags >> num_flags == 0);
|
||||
field_info_[field_name] = Sample::FieldInfo{
|
||||
(num_flags + 7) / 8 /* size */,
|
||||
flags /* value */,
|
||||
noise_level,
|
||||
};
|
||||
}
|
||||
|
||||
void Sample::SetUInt64Field(const std::string& field_name,
|
||||
uint64_t value,
|
||||
NoiseLevel noise_level) {
|
||||
// Noised integers not supported yet.
|
||||
DCHECK_EQ(NO_NOISE, noise_level);
|
||||
// Non-noised fields can only be recorded for UMA rappor metrics.
|
||||
DCHECK_EQ(UMA_RAPPOR_GROUP, parameters_.recording_group);
|
||||
if (parameters_.recording_group != UMA_RAPPOR_GROUP)
|
||||
return;
|
||||
DCHECK_EQ(0u, field_info_[field_name].size);
|
||||
field_info_[field_name] = Sample::FieldInfo{
|
||||
8,
|
||||
value,
|
||||
noise_level,
|
||||
};
|
||||
}
|
||||
|
||||
void Sample::ExportMetrics(const std::string& secret,
|
||||
const std::string& metric_name,
|
||||
RapporReports* reports) const {
|
||||
for (const auto& kv : field_info_) {
|
||||
FieldInfo field_info = kv.second;
|
||||
ByteVector value_bytes(field_info.size);
|
||||
Uint64ToByteVector(field_info.value, field_info.size, &value_bytes);
|
||||
ByteVector report_bytes = internal::GenerateReport(
|
||||
secret,
|
||||
internal::kNoiseParametersForLevel[field_info.noise_level],
|
||||
value_bytes);
|
||||
|
||||
RapporReports::Report* report = reports->add_report();
|
||||
report->set_name_hash(base::HashMetricName(
|
||||
metric_name + "." + kv.first));
|
||||
report->set_bits(std::string(report_bytes.begin(), report_bytes.end()));
|
||||
DVLOG(2) << "Exporting sample " << metric_name << "." << kv.first;
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace rappor
|
@ -1,40 +0,0 @@
|
||||
// Copyright 2015 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/rappor/sampler.h"
|
||||
|
||||
#include <map>
|
||||
#include <string>
|
||||
#include <utility>
|
||||
|
||||
#include "base/rand_util.h"
|
||||
|
||||
namespace rappor {
|
||||
|
||||
namespace internal {
|
||||
|
||||
Sampler::Sampler() {}
|
||||
|
||||
Sampler::~Sampler() {}
|
||||
|
||||
void Sampler::AddSample(const std::string& metric_name,
|
||||
std::unique_ptr<Sample> sample) {
|
||||
++sample_counts_[metric_name];
|
||||
// Replace the previous sample with a 1 in sample_count_ chance so that each
|
||||
// sample has equal probability of being reported.
|
||||
if (base::RandGenerator(sample_counts_[metric_name]) == 0)
|
||||
samples_[metric_name] = std::move(sample);
|
||||
}
|
||||
|
||||
void Sampler::ExportMetrics(const std::string& secret, RapporReports* reports) {
|
||||
for (const auto& kv : samples_) {
|
||||
kv.second->ExportMetrics(secret, kv.first, reports);
|
||||
}
|
||||
samples_.clear();
|
||||
sample_counts_.clear();
|
||||
}
|
||||
|
||||
} // namespace internal
|
||||
|
||||
} // namespace rappor
|
@ -1,54 +0,0 @@
|
||||
// Copyright 2015 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.
|
||||
|
||||
#ifndef COMPONENTS_RAPPOR_SAMPLER_H_
|
||||
#define COMPONENTS_RAPPOR_SAMPLER_H_
|
||||
|
||||
#include <map>
|
||||
#include <memory>
|
||||
#include <string>
|
||||
#include <unordered_map>
|
||||
|
||||
#include "base/macros.h"
|
||||
#include "components/rappor/public/rappor_parameters.h"
|
||||
#include "components/rappor/public/sample.h"
|
||||
|
||||
namespace rappor {
|
||||
|
||||
class RapporReports;
|
||||
|
||||
namespace internal {
|
||||
|
||||
// Sampler manages the collection and storage of Sample objects.
|
||||
// For each metric name, it will randomly select one Sample to store and
|
||||
// use when generating RapporReports.
|
||||
class Sampler {
|
||||
public:
|
||||
Sampler();
|
||||
~Sampler();
|
||||
|
||||
// Store this sample for metric name, randomly selecting a sample if
|
||||
// others have already been recorded.
|
||||
void AddSample(const std::string& metric_name,
|
||||
std::unique_ptr<Sample> sample);
|
||||
|
||||
// Generate randomized reports for all stored samples and store them
|
||||
// in |reports|, then discard the samples.
|
||||
void ExportMetrics(const std::string& secret, RapporReports* reports);
|
||||
|
||||
private:
|
||||
// The number of samples recorded for each metric since the last export.
|
||||
std::map<std::string, int> sample_counts_;
|
||||
|
||||
// Stores a Sample for each metric, by metric name.
|
||||
std::unordered_map<std::string, std::unique_ptr<Sample>> samples_;
|
||||
|
||||
DISALLOW_COPY_AND_ASSIGN(Sampler);
|
||||
};
|
||||
|
||||
} // namespace internal
|
||||
|
||||
} // namespace rappor
|
||||
|
||||
#endif // COMPONENTS_RAPPOR_SAMPLER_H_
|
@ -1,81 +0,0 @@
|
||||
// Copyright 2015 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/rappor/sampler.h"
|
||||
|
||||
#include <memory>
|
||||
#include <utility>
|
||||
|
||||
#include "base/metrics/metrics_hashes.h"
|
||||
#include "components/rappor/byte_vector_utils.h"
|
||||
#include "components/rappor/proto/rappor_metric.pb.h"
|
||||
#include "testing/gtest/include/gtest/gtest.h"
|
||||
|
||||
namespace rappor {
|
||||
|
||||
const RapporParameters kRapporSamplerTestParameters = {
|
||||
1 /* Num cohorts */, 1 /* Bloom filter size bytes */,
|
||||
4 /* Bloom filter hash count */, NORMAL_NOISE /* Noise level */,
|
||||
UMA_RAPPOR_GROUP /* Recording group (not used) */};
|
||||
|
||||
class TestSamplerFactory {
|
||||
public:
|
||||
static std::unique_ptr<Sample> CreateSample() {
|
||||
return std::unique_ptr<Sample>(new Sample(0, kRapporSamplerTestParameters));
|
||||
}
|
||||
};
|
||||
|
||||
namespace internal {
|
||||
|
||||
// Test that exporting deletes samples.
|
||||
TEST(RapporSamplerTest, TestExport) {
|
||||
Sampler sampler;
|
||||
|
||||
std::unique_ptr<Sample> sample1 = TestSamplerFactory::CreateSample();
|
||||
sample1->SetStringField("Foo", "Junk");
|
||||
sampler.AddSample("Metric1", std::move(sample1));
|
||||
|
||||
std::unique_ptr<Sample> sample2 = TestSamplerFactory::CreateSample();
|
||||
sample2->SetStringField("Foo", "Junk2");
|
||||
sampler.AddSample("Metric1", std::move(sample2));
|
||||
|
||||
// Since the two samples were for one metric, we should randomly get one
|
||||
// of the two.
|
||||
RapporReports reports;
|
||||
std::string secret = HmacByteVectorGenerator::GenerateEntropyInput();
|
||||
sampler.ExportMetrics(secret, &reports);
|
||||
EXPECT_EQ(1, reports.report_size());
|
||||
EXPECT_EQ(1u, reports.report(0).bits().size());
|
||||
|
||||
// First export should clear the metric.
|
||||
RapporReports reports2;
|
||||
sampler.ExportMetrics(secret, &reports2);
|
||||
EXPECT_EQ(0, reports2.report_size());
|
||||
}
|
||||
|
||||
// Test exporting fields with NO_NOISE.
|
||||
TEST(RapporSamplerTest, TestNoNoise) {
|
||||
Sampler sampler;
|
||||
|
||||
std::unique_ptr<Sample> sample1 = TestSamplerFactory::CreateSample();
|
||||
sample1->SetFlagsField("Foo", 0xde, 8, NO_NOISE);
|
||||
sample1->SetUInt64Field("Bar", 0x0011223344aabbccdd, NO_NOISE);
|
||||
sampler.AddSample("Metric1", std::move(sample1));
|
||||
|
||||
RapporReports reports;
|
||||
std::string secret = HmacByteVectorGenerator::GenerateEntropyInput();
|
||||
sampler.ExportMetrics(secret, &reports);
|
||||
EXPECT_EQ(2, reports.report_size());
|
||||
|
||||
uint64_t hash1 = base::HashMetricName("Metric1.Foo");
|
||||
bool order = reports.report(0).name_hash() == hash1;
|
||||
const RapporReports::Report& report1 = reports.report(order ? 0 : 1);
|
||||
EXPECT_EQ("\xde", report1.bits());
|
||||
const RapporReports::Report& report2 = reports.report(order ? 1 : 0);
|
||||
EXPECT_EQ("\xdd\xcc\xbb\xaa\x44\x33\x22\x11\x00", report2.bits());
|
||||
}
|
||||
|
||||
} // namespace internal
|
||||
|
||||
} // namespace rappor
|
@ -1,24 +0,0 @@
|
||||
// Copyright 2014 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/rappor/test_log_uploader.h"
|
||||
|
||||
namespace rappor {
|
||||
|
||||
TestLogUploader::TestLogUploader() : is_running_(false) {}
|
||||
|
||||
TestLogUploader::~TestLogUploader() {}
|
||||
|
||||
void TestLogUploader::Start() {
|
||||
is_running_ = true;
|
||||
}
|
||||
|
||||
void TestLogUploader::Stop() {
|
||||
is_running_ = false;
|
||||
}
|
||||
|
||||
void TestLogUploader::QueueLog(const std::string& string) {
|
||||
}
|
||||
|
||||
} // namespace rappor
|
@ -1,37 +0,0 @@
|
||||
// Copyright 2014 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.
|
||||
|
||||
#ifndef COMPONENTS_RAPPOR_TEST_LOG_UPLOADER_H_
|
||||
#define COMPONENTS_RAPPOR_TEST_LOG_UPLOADER_H_
|
||||
|
||||
#include <string>
|
||||
|
||||
#include "base/macros.h"
|
||||
#include "components/rappor/log_uploader_interface.h"
|
||||
|
||||
namespace rappor {
|
||||
|
||||
class TestLogUploader : public LogUploaderInterface {
|
||||
public:
|
||||
TestLogUploader();
|
||||
~TestLogUploader() override;
|
||||
|
||||
// LogUploaderInterface:
|
||||
void Start() override;
|
||||
void Stop() override;
|
||||
void QueueLog(const std::string& log) override;
|
||||
|
||||
// Get if the uploader is running.
|
||||
bool is_running() { return is_running_; }
|
||||
|
||||
private:
|
||||
// True if Start was called since the last Stop.
|
||||
bool is_running_;
|
||||
|
||||
DISALLOW_COPY_AND_ASSIGN(TestLogUploader);
|
||||
};
|
||||
|
||||
} // namespace rappor
|
||||
|
||||
#endif // COMPONENTS_RAPPOR_LOG_UPLOADER_INTERFACE_H_
|
@ -1,147 +0,0 @@
|
||||
// Copyright 2014 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/rappor/test_rappor_service.h"
|
||||
|
||||
#include <utility>
|
||||
|
||||
#include "base/bind.h"
|
||||
#include "base/memory/ptr_util.h"
|
||||
#include "components/rappor/byte_vector_utils.h"
|
||||
#include "components/rappor/proto/rappor_metric.pb.h"
|
||||
#include "components/rappor/public/rappor_parameters.h"
|
||||
#include "components/rappor/rappor_prefs.h"
|
||||
#include "components/rappor/test_log_uploader.h"
|
||||
|
||||
namespace rappor {
|
||||
|
||||
namespace {
|
||||
|
||||
bool MockIsIncognito(bool* is_incognito) {
|
||||
return *is_incognito;
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
TestSample::TestSample(RapporType type)
|
||||
: Sample(0, internal::kRapporParametersForType[type]), shadow_(type) {}
|
||||
|
||||
TestSample::~TestSample() {}
|
||||
|
||||
void TestSample::SetStringField(const std::string& field_name,
|
||||
const std::string& value) {
|
||||
shadow_.string_fields[field_name] = value;
|
||||
Sample::SetStringField(field_name, value);
|
||||
}
|
||||
|
||||
void TestSample::SetFlagsField(const std::string& field_name,
|
||||
uint64_t flags,
|
||||
size_t num_flags) {
|
||||
shadow_.flag_fields[field_name] = flags;
|
||||
Sample::SetFlagsField(field_name, flags, num_flags);
|
||||
}
|
||||
|
||||
void TestSample::SetUInt64Field(const std::string& field_name,
|
||||
uint64_t value,
|
||||
NoiseLevel noise_level) {
|
||||
shadow_.uint64_fields[field_name] =
|
||||
std::pair<std::uint64_t, NoiseLevel>(value, noise_level);
|
||||
Sample::SetUInt64Field(field_name, value, noise_level);
|
||||
}
|
||||
|
||||
TestSample::Shadow::Shadow(RapporType type) : type(type) {}
|
||||
|
||||
TestSample::Shadow::Shadow(const TestSample::Shadow& other) {
|
||||
type = other.type;
|
||||
flag_fields = other.flag_fields;
|
||||
string_fields = other.string_fields;
|
||||
uint64_fields = other.uint64_fields;
|
||||
}
|
||||
|
||||
TestSample::Shadow::~Shadow() = default;
|
||||
|
||||
TestRapporServiceImpl::TestRapporServiceImpl()
|
||||
: RapporServiceImpl(&test_prefs_,
|
||||
base::BindRepeating(&MockIsIncognito, &is_incognito_)),
|
||||
next_rotation_(base::TimeDelta()),
|
||||
is_incognito_(false) {
|
||||
RegisterPrefs(test_prefs_.registry());
|
||||
test_uploader_ = new TestLogUploader();
|
||||
InitializeInternal(base::WrapUnique(test_uploader_), 0,
|
||||
HmacByteVectorGenerator::GenerateEntropyInput());
|
||||
Update(true, true);
|
||||
}
|
||||
|
||||
TestRapporServiceImpl::~TestRapporServiceImpl() {}
|
||||
|
||||
std::unique_ptr<Sample> TestRapporServiceImpl::CreateSample(RapporType type) {
|
||||
std::unique_ptr<TestSample> test_sample(new TestSample(type));
|
||||
return std::move(test_sample);
|
||||
}
|
||||
|
||||
// Intercepts the sample being recorded and saves it in a test structure.
|
||||
void TestRapporServiceImpl::RecordSample(const std::string& metric_name,
|
||||
std::unique_ptr<Sample> sample) {
|
||||
TestSample* test_sample = static_cast<TestSample*>(sample.get());
|
||||
// Erase the previous sample if we logged one.
|
||||
shadows_.erase(metric_name);
|
||||
shadows_.insert(std::pair<std::string, TestSample::Shadow>(
|
||||
metric_name, test_sample->GetShadow()));
|
||||
// Original version is still called.
|
||||
RapporServiceImpl::RecordSample(metric_name, std::move(sample));
|
||||
}
|
||||
|
||||
void TestRapporServiceImpl::RecordSampleString(const std::string& metric_name,
|
||||
RapporType type,
|
||||
const std::string& sample) {
|
||||
// Save the recorded sample to the local structure.
|
||||
RapporSample rappor_sample;
|
||||
rappor_sample.type = type;
|
||||
rappor_sample.value = sample;
|
||||
samples_[metric_name] = rappor_sample;
|
||||
// Original version is still called.
|
||||
RapporServiceImpl::RecordSampleString(metric_name, type, sample);
|
||||
}
|
||||
|
||||
int TestRapporServiceImpl::GetReportsCount() {
|
||||
RapporReports reports;
|
||||
ExportMetrics(&reports);
|
||||
return reports.report_size();
|
||||
}
|
||||
|
||||
void TestRapporServiceImpl::GetReports(RapporReports* reports) {
|
||||
ExportMetrics(reports);
|
||||
}
|
||||
|
||||
TestSample::Shadow* TestRapporServiceImpl::GetRecordedSampleForMetric(
|
||||
const std::string& metric_name) {
|
||||
auto it = shadows_.find(metric_name);
|
||||
if (it == shadows_.end())
|
||||
return nullptr;
|
||||
return &it->second;
|
||||
}
|
||||
|
||||
bool TestRapporServiceImpl::GetRecordedSampleForMetric(
|
||||
const std::string& metric_name,
|
||||
std::string* sample,
|
||||
RapporType* type) {
|
||||
auto it = samples_.find(metric_name);
|
||||
if (it == samples_.end())
|
||||
return false;
|
||||
*sample = it->second.value;
|
||||
*type = it->second.type;
|
||||
return true;
|
||||
}
|
||||
|
||||
// Cancel the next call to OnLogInterval.
|
||||
void TestRapporServiceImpl::CancelNextLogRotation() {
|
||||
next_rotation_ = base::TimeDelta();
|
||||
}
|
||||
|
||||
// Schedule the next call to OnLogInterval.
|
||||
void TestRapporServiceImpl::ScheduleNextLogRotation(base::TimeDelta interval) {
|
||||
next_rotation_ = interval;
|
||||
}
|
||||
|
||||
} // namespace rappor
|
@ -1,142 +0,0 @@
|
||||
// Copyright 2014 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.
|
||||
|
||||
#ifndef COMPONENTS_RAPPOR_TEST_RAPPOR_SERVICE_H_
|
||||
#define COMPONENTS_RAPPOR_TEST_RAPPOR_SERVICE_H_
|
||||
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
|
||||
#include <map>
|
||||
#include <string>
|
||||
|
||||
#include "base/macros.h"
|
||||
#include "components/prefs/testing_pref_service.h"
|
||||
#include "components/rappor/rappor_service_impl.h"
|
||||
#include "components/rappor/test_log_uploader.h"
|
||||
|
||||
namespace rappor {
|
||||
|
||||
// This class duplicates the functionality of Sample, with a cohort initialized
|
||||
// always to 0. It keeps a shadow object around which copies every flag field
|
||||
// and string field set on the Sample.
|
||||
class TestSample : public Sample {
|
||||
public:
|
||||
TestSample(RapporType type);
|
||||
~TestSample() override;
|
||||
|
||||
// Sample:
|
||||
void SetStringField(const std::string& field_name,
|
||||
const std::string& value) override;
|
||||
void SetFlagsField(const std::string& field_name,
|
||||
uint64_t flags,
|
||||
size_t num_flags) override;
|
||||
|
||||
void SetUInt64Field(const std::string& field_name,
|
||||
uint64_t value,
|
||||
NoiseLevel noise_level) override;
|
||||
|
||||
struct Shadow {
|
||||
explicit Shadow(RapporType type);
|
||||
Shadow(const Shadow& other);
|
||||
~Shadow();
|
||||
RapporType type;
|
||||
std::map<std::string, uint64_t> flag_fields;
|
||||
std::map<std::string, std::string> string_fields;
|
||||
std::map<std::string, std::pair<std::uint64_t, NoiseLevel>> uint64_fields;
|
||||
};
|
||||
|
||||
Shadow GetShadow() { return shadow_; }
|
||||
|
||||
private:
|
||||
Shadow shadow_;
|
||||
};
|
||||
|
||||
// This class provides a simple instance that can be instantiated by tests
|
||||
// and examined to check that metrics were recorded. It assumes the most
|
||||
// permissive settings so that any metric can be recorded.
|
||||
class TestRapporServiceImpl : public RapporServiceImpl {
|
||||
public:
|
||||
TestRapporServiceImpl();
|
||||
|
||||
~TestRapporServiceImpl() override;
|
||||
|
||||
// RapporServiceImpl:
|
||||
std::unique_ptr<Sample> CreateSample(RapporType type) override;
|
||||
void RecordSample(const std::string& metric_name,
|
||||
std::unique_ptr<Sample> sample) override;
|
||||
void RecordSampleString(const std::string& metric_name,
|
||||
RapporType type,
|
||||
const std::string& sample) override;
|
||||
|
||||
// Gets the number of reports that would be uploaded by this service.
|
||||
// This also clears the internal map of metrics as a biproduct, so if
|
||||
// comparing numbers of reports, the comparison should be from the last time
|
||||
// GetReportsCount() was called (not from the beginning of the test).
|
||||
int GetReportsCount();
|
||||
|
||||
// Gets the reports proto that would be uploaded.
|
||||
// This clears the internal map of metrics.
|
||||
void GetReports(RapporReports* reports);
|
||||
|
||||
// Gets the recorded sample for |metric_name|. This returns the shadow object
|
||||
// for the sample, which contains the string fields, flag fields, and type.
|
||||
// Limitation: if the metric was logged more than once, this will return the
|
||||
// latest sample that was logged.
|
||||
TestSample::Shadow* GetRecordedSampleForMetric(
|
||||
const std::string& metric_name);
|
||||
|
||||
// Gets the recorded sample/type for a |metric_name|, and returns whether the
|
||||
// recorded metric was found. Limitation: if the metric was logged more than
|
||||
// once, this will return the latest sample that was logged.
|
||||
bool GetRecordedSampleForMetric(const std::string& metric_name,
|
||||
std::string* sample,
|
||||
RapporType* type);
|
||||
|
||||
void set_is_incognito(bool is_incognito) { is_incognito_ = is_incognito; }
|
||||
|
||||
TestingPrefServiceSimple* test_prefs() { return &test_prefs_; }
|
||||
|
||||
rappor::TestLogUploader* test_uploader() { return test_uploader_; }
|
||||
|
||||
base::TimeDelta next_rotation() { return next_rotation_; }
|
||||
|
||||
protected:
|
||||
// Cancels the next call to OnLogInterval.
|
||||
void CancelNextLogRotation() override;
|
||||
|
||||
// Schedules the next call to OnLogInterval.
|
||||
void ScheduleNextLogRotation(base::TimeDelta interval) override;
|
||||
|
||||
private:
|
||||
// Used to keep track of recorded RAPPOR samples.
|
||||
struct RapporSample {
|
||||
RapporType type;
|
||||
std::string value;
|
||||
};
|
||||
typedef std::map<std::string, RapporSample> SamplesMap;
|
||||
SamplesMap samples_;
|
||||
|
||||
// Recording a TestSample inserts its shadow into this map, which has all of
|
||||
// its fields copied.
|
||||
typedef std::map<std::string, TestSample::Shadow> ShadowMap;
|
||||
ShadowMap shadows_;
|
||||
|
||||
TestingPrefServiceSimple test_prefs_;
|
||||
|
||||
// Holds a weak ref to the uploader_ object.
|
||||
rappor::TestLogUploader* test_uploader_;
|
||||
|
||||
// The last scheduled log rotation.
|
||||
base::TimeDelta next_rotation_;
|
||||
|
||||
// Sets this to true to mock incognito state.
|
||||
bool is_incognito_;
|
||||
|
||||
DISALLOW_COPY_AND_ASSIGN(TestRapporServiceImpl);
|
||||
};
|
||||
|
||||
} // namespace rappor
|
||||
|
||||
#endif // COMPONENTS_RAPPOR_TEST_RAPPOR_SERVICE_H_
|
@ -3,7 +3,6 @@ include_rules = [
|
||||
"+components/history/core/browser",
|
||||
"+components/metrics",
|
||||
"+components/prefs",
|
||||
"+components/rappor",
|
||||
"+components/safe_browsing/core/common",
|
||||
"+components/safe_browsing/core/db",
|
||||
"+components/ssl_errors",
|
||||
|
@ -78,7 +78,6 @@ source_set("browser") {
|
||||
"//components/payments/core:error_strings",
|
||||
"//components/payments/mojom",
|
||||
"//components/power_scheduler",
|
||||
"//components/rappor",
|
||||
"//components/services/filesystem:lib",
|
||||
"//components/services/quarantine:quarantine",
|
||||
"//components/services/storage",
|
||||
|
@ -28,7 +28,6 @@ include_rules = [
|
||||
"+components/offline_pages/buildflags/buildflags.h",
|
||||
"+components/offline_pages/core/request_header",
|
||||
"+components/payments",
|
||||
"+components/rappor/public",
|
||||
"+components/services/heap_profiling/public",
|
||||
"+components/system_media_controls",
|
||||
"+components/tracing",
|
||||
|
@ -19,7 +19,6 @@ include_rules = [
|
||||
|
||||
specific_include_rules = {
|
||||
".*_(unit|browser)test\.(cc|mm)": [
|
||||
"+components/rappor/test_rappor_service.h",
|
||||
"+content/browser/web_contents",
|
||||
"+content/public/browser/web_contents.h",
|
||||
"+content/public/browser/web_contents_delegate.h",
|
||||
|
@ -5,7 +5,6 @@
|
||||
#include "content/browser/renderer_host/render_widget_host_delegate.h"
|
||||
|
||||
#include "build/build_config.h"
|
||||
#include "components/rappor/public/sample.h"
|
||||
#include "content/browser/renderer_host/render_view_host_delegate_view.h"
|
||||
#include "content/public/browser/keyboard_event_processing_result.h"
|
||||
#include "services/metrics/public/cpp/ukm_source_id.h"
|
||||
@ -126,12 +125,6 @@ bool RenderWidgetHostDelegate::IsWidgetForMainFrame(RenderWidgetHostImpl*) {
|
||||
return false;
|
||||
}
|
||||
|
||||
bool RenderWidgetHostDelegate::AddDomainInfoToRapporSample(
|
||||
rappor::Sample* sample) {
|
||||
sample->SetStringField("Domain", "Unknown");
|
||||
return false;
|
||||
}
|
||||
|
||||
ukm::SourceId RenderWidgetHostDelegate::GetCurrentPageUkmSourceId() {
|
||||
return ukm::kInvalidSourceId;
|
||||
}
|
||||
|
@ -34,10 +34,6 @@ class Rect;
|
||||
class Size;
|
||||
}
|
||||
|
||||
namespace rappor {
|
||||
class Sample;
|
||||
}
|
||||
|
||||
namespace content {
|
||||
|
||||
class BrowserAccessibilityManager;
|
||||
@ -287,11 +283,6 @@ class CONTENT_EXPORT RenderWidgetHostDelegate {
|
||||
virtual void FocusOwningWebContents(
|
||||
RenderWidgetHostImpl* render_widget_host) {}
|
||||
|
||||
// Augment a Rappor sample with eTLD+1 context. The caller is still
|
||||
// responsible for logging the sample to the RapporService. Returns false
|
||||
// if the eTLD+1 is not known for |render_widget_host|.
|
||||
virtual bool AddDomainInfoToRapporSample(rappor::Sample* sample);
|
||||
|
||||
// Return this object cast to a WebContents, if it is one. If the object is
|
||||
// not a WebContents, returns nullptr.
|
||||
virtual WebContents* GetAsWebContents();
|
||||
|
@ -47,7 +47,6 @@
|
||||
#include "build/build_config.h"
|
||||
#include "build/chromeos_buildflags.h"
|
||||
#include "components/download/public/common/download_stats.h"
|
||||
#include "components/rappor/public/rappor_utils.h"
|
||||
#include "components/url_formatter/url_formatter.h"
|
||||
#include "content/browser/accessibility/browser_accessibility.h"
|
||||
#include "content/browser/bad_message.h"
|
||||
@ -8408,16 +8407,6 @@ void WebContentsImpl::RemoveReceiverSet(const std::string& interface_name) {
|
||||
receiver_sets_.erase(it);
|
||||
}
|
||||
|
||||
bool WebContentsImpl::AddDomainInfoToRapporSample(rappor::Sample* sample) {
|
||||
OPTIONAL_TRACE_EVENT0("content",
|
||||
"WebContentsImpl::AddDomainInfoToRapporSample");
|
||||
// Here we associate this metric to the main frame URL regardless of what
|
||||
// caused it.
|
||||
sample->SetStringField("Domain", ::rappor::GetDomainAndRegistrySampleFromGURL(
|
||||
GetLastCommittedURL()));
|
||||
return true;
|
||||
}
|
||||
|
||||
void WebContentsImpl::ShowInsecureLocalhostWarningIfNeeded() {
|
||||
OPTIONAL_TRACE_EVENT0(
|
||||
"content", "WebContentsImpl::ShowInsecureLocalhostWarningIfNeeded");
|
||||
|
@ -961,7 +961,6 @@ class CONTENT_EXPORT WebContentsImpl : public WebContents,
|
||||
void SendScreenRects() override;
|
||||
TextInputManager* GetTextInputManager() override;
|
||||
bool IsWidgetForMainFrame(RenderWidgetHostImpl* render_widget_host) override;
|
||||
bool AddDomainInfoToRapporSample(rappor::Sample* sample) override;
|
||||
bool IsShowingContextMenuOnPage() const override;
|
||||
void DidChangeScreenOrientation() override;
|
||||
// The following function is already listed under RenderViewHostDelegate
|
||||
|
@ -2203,7 +2203,6 @@ test("content_unittests") {
|
||||
"//components/network_session_configurator/common",
|
||||
"//components/offline_pages/buildflags",
|
||||
"//components/payments/mojom",
|
||||
"//components/rappor:test_support",
|
||||
"//components/services/quarantine/public/mojom",
|
||||
"//components/services/storage",
|
||||
"//components/services/storage:test_support",
|
||||
|
@ -203,7 +203,6 @@ source_set("browser_impl") {
|
||||
"//components/network_time",
|
||||
"//components/open_from_clipboard",
|
||||
"//components/prefs",
|
||||
"//components/rappor",
|
||||
"//components/safe_browsing/core:features",
|
||||
"//components/sessions",
|
||||
"//components/translate/core/browser",
|
||||
|
@ -71,7 +71,6 @@ include_rules = [
|
||||
"+components/profile_metrics",
|
||||
"+components/proxy_config",
|
||||
"+components/query_parser",
|
||||
"+components/rappor",
|
||||
"+components/reading_list",
|
||||
"+components/rlz",
|
||||
"+components/safe_browsing",
|
||||
|
@ -51,10 +51,6 @@ namespace network_time {
|
||||
class NetworkTimeTracker;
|
||||
}
|
||||
|
||||
namespace rappor {
|
||||
class RapporServiceImpl;
|
||||
}
|
||||
|
||||
namespace ukm {
|
||||
class UkmRecorder;
|
||||
}
|
||||
@ -125,9 +121,6 @@ class ApplicationContext {
|
||||
// Gets the VariationsService used by this application.
|
||||
virtual variations::VariationsService* GetVariationsService() = 0;
|
||||
|
||||
// Gets the RapporServiceImpl. May return null.
|
||||
virtual rappor::RapporServiceImpl* GetRapporServiceImpl() = 0;
|
||||
|
||||
// Gets the NetLog.
|
||||
virtual net::NetLog* GetNetLog() = 0;
|
||||
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user