diff options
author | robertshield <robertshield@chromium.org> | 2015-11-17 09:07:55 -0800 |
---|---|---|
committer | Commit bot <commit-bot@chromium.org> | 2015-11-17 17:08:56 +0000 |
commit | e2f61d09c3f27e5fb3c5ddbb1c313d30ee9201aa (patch) | |
tree | 33063a5c0ebe5ae3a3b1ebd235a0adff8ee339b2 | |
parent | 711497d0138297f221cd7283f313e6254b0409fe (diff) | |
download | chromium_src-e2f61d09c3f27e5fb3c5ddbb1c313d30ee9201aa.zip chromium_src-e2f61d09c3f27e5fb3c5ddbb1c313d30ee9201aa.tar.gz chromium_src-e2f61d09c3f27e5fb3c5ddbb1c313d30ee9201aa.tar.bz2 |
Remove the automatic profile resetter.
BUG=370966
Review URL: https://codereview.chromium.org/1427743010
Cr-Commit-Position: refs/heads/master@{#360096}
71 files changed, 84 insertions, 8279 deletions
@@ -391,7 +391,6 @@ group("both_gn_and_gyp") { "//chrome/test:sync_performance_tests", "//chrome/test/chromedriver:chromedriver", "//chrome/test/chromedriver:chromedriver_tests", - "//chrome/tools/profile_reset:jtl_compiler", "//components:components_perftests", "//content/test:content_gl_tests", "//content/test:content_gl_benchmark", diff --git a/build/all.gyp b/build/all.gyp index ecbe935..176e855 100644 --- a/build/all.gyp +++ b/build/all.gyp @@ -109,7 +109,6 @@ 'dependencies': [ '../third_party/re2/re2.gyp:re2', '../chrome/chrome.gyp:*', - '../chrome/tools/profile_reset/jtl_compiler.gyp:*', '../cc/blink/cc_blink_tests.gyp:*', '../cc/cc_tests.gyp:*', '../device/usb/usb.gyp:*', diff --git a/build/gn_migration.gypi b/build/gn_migration.gypi index 279d4c4..7c8b1a1 100644 --- a/build/gn_migration.gypi +++ b/build/gn_migration.gypi @@ -356,7 +356,6 @@ '../chrome/chrome.gyp:performance_browser_tests', '../chrome/chrome.gyp:sync_integration_tests', '../chrome/chrome.gyp:sync_performance_tests', - '../chrome/tools/profile_reset/jtl_compiler.gyp:jtl_compiler', '../extensions/extensions_tests.gyp:extensions_browsertests', '../extensions/extensions_tests.gyp:extensions_unittests', '../gin/gin.gyp:gin_shell', diff --git a/chrome/app/generated_resources.grd b/chrome/app/generated_resources.grd index f2916db..63ff3ca 100644 --- a/chrome/app/generated_resources.grd +++ b/chrome/app/generated_resources.grd @@ -8259,6 +8259,7 @@ I don't think this site should be blocked! Unusual behavior detected </message> </if> + <!-- Upgrade bubble messages --> <message name="IDS_REENABLE_UPDATES" desc="Text for the button the user clicks to re-enable automatic updates."> Enable autoupdate @@ -10547,9 +10548,6 @@ I don't think this site should be blocked! </message> <!-- Reset Profile Settings strings --> - <message name="IDS_RESET_PROFILE_SETTINGS_BANNER_TEXT" desc="The text to show in a banner at the top of the chrome://settings page. The banner is displayed when Chrome detects that the settings might have been changed without the user's knowledge."> - Some of your settings may have been changed without your knowledge. - </message> <message name="IDS_RESET_PROFILE_SETTINGS_SECTION_TITLE" desc="The title of the section in chrome://settings that allows resetting some settings in a profile"> Reset settings </message> diff --git a/chrome/browser/browser_resources.grd b/chrome/browser/browser_resources.grd index 7e6595a..04e83a7 100644 --- a/chrome/browser/browser_resources.grd +++ b/chrome/browser/browser_resources.grd @@ -403,10 +403,6 @@ </if> <if expr="_google_chrome"> <include name="IDR_PREF_HASH_SEED_BIN" file="resources\settings_internal\pref_hash_seed.bin" type="BINDATA" /> - <include name="IDR_AUTOMATIC_PROFILE_RESET_RULES" file="internal\resources\profile_reset\automatic_profile_reset_rules.dat" type="BINDATA" /> - <include name="IDR_AUTOMATIC_PROFILE_RESET_RULES_DRY" file="internal\resources\profile_reset\automatic_profile_reset_rules_dry.dat" type="BINDATA" /> - <include name="IDR_AUTOMATIC_PROFILE_RESET_HASH_SEED" file="internal\resources\profile_reset\automatic_profile_reset_rules.seed" type="BINDATA" /> - <include name="IDR_AUTOMATIC_PROFILE_RESET_HASH_SEED_DRY" file="internal\resources\profile_reset\automatic_profile_reset_rules_dry.seed" type="BINDATA" /> <include name="IDR_ADDITIONAL_MODULE_IDS" file="${additional_modules_list_file}" use_base_dir="false" type="BINDATA" /> </if> <if expr="chromeos"> diff --git a/chrome/browser/prefs/browser_prefs.cc b/chrome/browser/prefs/browser_prefs.cc index 5fe77e7c..90a7599 100644 --- a/chrome/browser/prefs/browser_prefs.cc +++ b/chrome/browser/prefs/browser_prefs.cc @@ -143,7 +143,6 @@ #include "chrome/browser/android/new_tab_page_prefs.h" #include "chrome/browser/android/popular_sites.h" #else -#include "chrome/browser/profile_resetter/automatic_profile_resetter_factory.h" #include "chrome/browser/ui/startup/startup_browser_creator.h" #include "chrome/browser/upgrade_detector.h" #endif @@ -290,7 +289,6 @@ void RegisterLocalState(PrefRegistrySimple* registry) { #endif // defined(ENABLE_TASK_MANAGER) #if !defined(OS_ANDROID) - AutomaticProfileResetterFactory::RegisterPrefs(registry); BackgroundModeManager::RegisterPrefs(registry); ChromeTracingDelegate::RegisterPrefs(registry); RegisterBrowserPrefs(registry); diff --git a/chrome/browser/prefs/chrome_pref_service_factory.cc b/chrome/browser/prefs/chrome_pref_service_factory.cc index fc2dcc8..4b313f4 100644 --- a/chrome/browser/prefs/chrome_pref_service_factory.cc +++ b/chrome/browser/prefs/chrome_pref_service_factory.cc @@ -166,12 +166,6 @@ const PrefHashFilter::TrackedPreferenceMetadata kTrackedPrefs[] = { PrefHashFilter::TRACKING_STRATEGY_ATOMIC, PrefHashFilter::VALUE_IMPERSONAL }, - { - 13, prefs::kProfileResetPromptMementoInProfilePrefs, - PrefHashFilter::ENFORCE_ON_LOAD, - PrefHashFilter::TRACKING_STRATEGY_ATOMIC, - PrefHashFilter::VALUE_IMPERSONAL - }, #endif { 14, DefaultSearchManager::kDefaultSearchProviderDataPrefName, diff --git a/chrome/browser/profile_resetter/automatic_profile_resetter.cc b/chrome/browser/profile_resetter/automatic_profile_resetter.cc deleted file mode 100644 index 9386b27..0000000 --- a/chrome/browser/profile_resetter/automatic_profile_resetter.cc +++ /dev/null @@ -1,764 +0,0 @@ -// Copyright 2013 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 "chrome/browser/profile_resetter/automatic_profile_resetter.h" - -#include "base/bind.h" -#include "base/bind_helpers.h" -#include "base/logging.h" -#include "base/memory/ref_counted.h" -#include "base/metrics/field_trial.h" -#include "base/metrics/histogram.h" -#include "base/metrics/sparse_histogram.h" -#include "base/prefs/pref_service.h" -#include "base/strings/string_number_conversions.h" -#include "base/strings/string_util.h" -#include "base/task_runner.h" -#include "base/task_runner_util.h" -#include "base/threading/sequenced_worker_pool.h" -#include "base/time/time.h" -#include "base/timer/elapsed_timer.h" -#include "base/values.h" -#include "chrome/browser/browser_process.h" -#include "chrome/browser/profile_resetter/automatic_profile_resetter_delegate.h" -#include "chrome/browser/profile_resetter/jtl_interpreter.h" -#include "chrome/browser/profiles/profile.h" -#include "chrome/browser/search_engines/template_url_service_factory.h" -#include "components/search_engines/template_url_service.h" -#include "components/variations/variations_associated_data.h" -#include "content/public/browser/browser_thread.h" -#include "grit/browser_resources.h" -#include "ui/base/resource/resource_bundle.h" - - -// Helpers ------------------------------------------------------------------- - -namespace { - -// Name constants for the field trial behind which we enable this feature. -const char kAutomaticProfileResetStudyName[] = "AutomaticProfileReset"; -const char kAutomaticProfileResetStudyDryRunGroupName[] = "DryRun"; -const char kAutomaticProfileResetStudyEnabledGroupName[] = "Enabled"; -#if defined(GOOGLE_CHROME_BUILD) -const char kAutomaticProfileResetStudyProgramParameterName[] = "program"; -const char kAutomaticProfileResetStudyHashSeedParameterName[] = "hash_seed"; -#endif - -// How long to wait after start-up before unleashing the evaluation flow. -const int64 kEvaluationFlowDelayInSeconds = 55; - -// Keys used in the input dictionary of the program. -const char kDefaultSearchProviderKey[] = "default_search_provider"; -const char kDefaultSearchProviderIsUserControlledKey[] = - "default_search_provider_iuc"; -const char kLoadedModuleDigestsKey[] = "loaded_modules"; -const char kLocalStateKey[] = "local_state"; -const char kLocalStateIsUserControlledKey[] = "local_state_iuc"; -const char kSearchProvidersKey[] = "search_providers"; -const char kUserPreferencesKey[] = "preferences"; -const char kUserPreferencesIsUserControlledKey[] = "preferences_iuc"; - -// Keys used in the output dictionary of the program. -const char kCombinedStatusMaskKeyPrefix[] = "combined_status_mask_bit"; -const char kHadPromptedAlreadyKey[] = "had_prompted_already"; -const char kShouldPromptKey[] = "should_prompt"; -const char kSatisfiedCriteriaMaskKeyPrefix[] = "satisfied_criteria_mask_bit"; - -// Keys used in both the input and output dictionary of the program. -const char kMementoValueInFileKey[] = "memento_value_in_file"; -const char kMementoValueInLocalStateKey[] = "memento_value_in_local_state"; -const char kMementoValueInPrefsKey[] = "memento_value_in_prefs"; - -// Number of bits, and maximum value (exclusive) for the mask whose bits -// indicate which of reset criteria were satisfied. -const size_t kSatisfiedCriteriaMaskNumberOfBits = 5u; -const uint32 kSatisfiedCriteriaMaskMaximumValue = - (1u << kSatisfiedCriteriaMaskNumberOfBits); - -// Number of bits, and maximum value (exclusive) for the mask whose bits -// indicate if any of reset criteria were satisfied, and which of the mementos -// were already present. -const size_t kCombinedStatusMaskNumberOfBits = 4u; -const uint32 kCombinedStatusMaskMaximumValue = - (1u << kCombinedStatusMaskNumberOfBits); - -// Returns whether or not a dry-run shall be performed. -bool ShouldPerformDryRun() { - return base::StartsWith( - base::FieldTrialList::FindFullName(kAutomaticProfileResetStudyName), - kAutomaticProfileResetStudyDryRunGroupName, base::CompareCase::SENSITIVE); -} - -// Returns whether or not a live-run shall be performed. -bool ShouldPerformLiveRun() { - return base::StartsWith( - base::FieldTrialList::FindFullName(kAutomaticProfileResetStudyName), - kAutomaticProfileResetStudyEnabledGroupName, - base::CompareCase::SENSITIVE); -} - -// If the currently active experiment group prescribes a |program| and -// |hash_seed| to use instead of the baked-in ones, retrieves those and returns -// true. Otherwise, returns false. -bool GetProgramAndHashSeedOverridesFromExperiment(std::string* program, - std::string* hash_seed) { - DCHECK(program); - DCHECK(hash_seed); -#if defined(GOOGLE_CHROME_BUILD) - std::map<std::string, std::string> params; - variations::GetVariationParams(kAutomaticProfileResetStudyName, ¶ms); - if (params.count(kAutomaticProfileResetStudyProgramParameterName) && - params.count(kAutomaticProfileResetStudyHashSeedParameterName)) { - program->swap(params[kAutomaticProfileResetStudyProgramParameterName]); - hash_seed->swap(params[kAutomaticProfileResetStudyHashSeedParameterName]); - return true; - } -#endif - return false; -} - -// Takes |pref_name_to_value_map|, which shall be a deep-copy of all preferences -// in |source| without path expansion; and (1.) creates a sub-tree from it named -// |value_tree_key| in |target_dictionary| with path expansion, and (2.) also -// creates an isomorphic sub-tree under the key |is_user_controlled_tree_key| -// that contains only Boolean values indicating whether or not the corresponding -// preference is coming from the 'user' PrefStore. -void BuildSubTreesFromPreferences( - scoped_ptr<base::DictionaryValue> pref_name_to_value_map, - const PrefService* source, - const char* value_tree_key, - const char* is_user_controlled_tree_key, - base::DictionaryValue* target_dictionary) { - std::vector<std::string> pref_names; - pref_names.reserve(pref_name_to_value_map->size()); - for (base::DictionaryValue::Iterator it(*pref_name_to_value_map); - !it.IsAtEnd(); it.Advance()) - pref_names.push_back(it.key()); - - base::DictionaryValue* value_tree = new base::DictionaryValue; - base::DictionaryValue* is_user_controlled_tree = new base::DictionaryValue; - for (std::vector<std::string>::const_iterator it = pref_names.begin(); - it != pref_names.end(); ++it) { - scoped_ptr<base::Value> pref_value_owned; - if (pref_name_to_value_map->RemoveWithoutPathExpansion(*it, - &pref_value_owned)) { - value_tree->Set(*it, pref_value_owned.release()); - const PrefService::Preference* pref = source->FindPreference(it->c_str()); - is_user_controlled_tree->Set( - *it, new base::FundamentalValue(pref->IsUserControlled())); - } - } - target_dictionary->Set(value_tree_key, value_tree); - target_dictionary->Set(is_user_controlled_tree_key, is_user_controlled_tree); -} - -} // namespace - - -// AutomaticProfileResetter::InputBuilder ------------------------------------ - -// Collects all the information that is required by the evaluator program to -// assess whether or not the conditions for showing the reset prompt are met. -// -// This necessitates a lot of work that has to be performed on the UI thread, -// such as: accessing the Preferences, Local State, and TemplateURLService. -// In order to keep the browser responsive, the UI thread shall not be blocked -// for long consecutive periods of time. Unfortunately, we cannot reduce the -// total amount of work. Instead, what this class does is to split the work into -// shorter tasks that are posted one-at-a-time to the UI thread in a serial -// fashion, so as to give a chance to run other tasks that have accumulated in -// the meantime. -class AutomaticProfileResetter::InputBuilder - : public base::SupportsWeakPtr<InputBuilder> { - public: - typedef base::Callback<void(scoped_ptr<base::DictionaryValue>)> - ProgramInputCallback; - - // The dependencies must have been initialized through |delegate|, i.e. the - // RequestCallback[...] methods must have already fired before calling this. - InputBuilder(Profile* profile, AutomaticProfileResetterDelegate* delegate) - : profile_(profile), - delegate_(delegate), - memento_in_prefs_(profile_), - memento_in_local_state_(profile_), - memento_in_file_(profile_) {} - ~InputBuilder() {} - - // Assembles the data required by the evaluator program into a dictionary - // format, and posts it back to the UI thread with |callback| once ready. In - // order not to block the UI thread for long consecutive periods of time, the - // work is divided into smaller tasks, see class comment above for details. - // It is safe to destroy |this| immediately from within the |callback|. - void BuildEvaluatorProgramInput(const ProgramInputCallback& callback) { - DCHECK(!data_); - DCHECK(!callback.is_null()); - data_.reset(new base::DictionaryValue); - callback_ = callback; - - AddAsyncTask(base::Bind(&InputBuilder::IncludeMementoValues, AsWeakPtr())); - AddTask(base::Bind(&InputBuilder::IncludeUserPreferences, AsWeakPtr())); - AddTask(base::Bind(&InputBuilder::IncludeLocalState, AsWeakPtr())); - AddTask(base::Bind(&InputBuilder::IncludeSearchEngines, AsWeakPtr())); - AddTask(base::Bind(&InputBuilder::IncludeLoadedModules, AsWeakPtr())); - - // Each task will post the next one. Just trigger the chain reaction. - PostNextTask(); - } - - private: - // Asynchronous task that includes memento values (or empty strings in case - // mementos are not there). - void IncludeMementoValues() { - data_->SetString(kMementoValueInPrefsKey, memento_in_prefs_.ReadValue()); - data_->SetString(kMementoValueInLocalStateKey, - memento_in_local_state_.ReadValue()); - memento_in_file_.ReadValue(base::Bind( - &InputBuilder::IncludeFileBasedMementoCallback, AsWeakPtr())); - } - - // Called back by |memento_in_file_| once the |memento_value| has been read. - void IncludeFileBasedMementoCallback(const std::string& memento_value) { - DCHECK_CURRENTLY_ON(content::BrowserThread::UI); - data_->SetString(kMementoValueInFileKey, memento_value); - // As an asynchronous task, we need to take care of posting the next task. - PostNextTask(); - } - - // Task that includes all user (i.e. profile-specific) preferences, along with - // information about whether the value is coming from the 'user' PrefStore. - // This is the most expensive operation, so it is itself split into two parts. - void IncludeUserPreferences() { - PrefService* prefs = profile_->GetPrefs(); - DCHECK(prefs); - scoped_ptr<base::DictionaryValue> pref_name_to_value_map( - prefs->GetPreferenceValuesWithoutPathExpansion()); - AddTask(base::Bind(&InputBuilder::IncludeUserPreferencesPartTwo, - AsWeakPtr(), - base::Passed(&pref_name_to_value_map))); - } - - // Second part to above. - void IncludeUserPreferencesPartTwo( - scoped_ptr<base::DictionaryValue> pref_name_to_value_map) { - PrefService* prefs = profile_->GetPrefs(); - DCHECK(prefs); - BuildSubTreesFromPreferences( - pref_name_to_value_map.Pass(), - prefs, - kUserPreferencesKey, - kUserPreferencesIsUserControlledKey, - data_.get()); - } - - // Task that includes all local state (i.e. shared) preferences, along with - // information about whether the value is coming from the 'user' PrefStore. - void IncludeLocalState() { - PrefService* local_state = g_browser_process->local_state(); - DCHECK(local_state); - scoped_ptr<base::DictionaryValue> pref_name_to_value_map( - local_state->GetPreferenceValuesWithoutPathExpansion()); - BuildSubTreesFromPreferences( - pref_name_to_value_map.Pass(), - local_state, - kLocalStateKey, - kLocalStateIsUserControlledKey, - data_.get()); - } - - // Task that includes all information related to search engines. - void IncludeSearchEngines() { - scoped_ptr<base::DictionaryValue> default_search_provider_details( - delegate_->GetDefaultSearchProviderDetails()); - data_->Set(kDefaultSearchProviderKey, - default_search_provider_details.release()); - - scoped_ptr<base::ListValue> search_providers_details( - delegate_->GetPrepopulatedSearchProvidersDetails()); - data_->Set(kSearchProvidersKey, search_providers_details.release()); - - data_->SetBoolean(kDefaultSearchProviderIsUserControlledKey, - !delegate_->IsDefaultSearchProviderManaged()); - } - - // Task that includes information about loaded modules. - void IncludeLoadedModules() { - scoped_ptr<base::ListValue> loaded_module_digests( - delegate_->GetLoadedModuleNameDigests()); - data_->Set(kLoadedModuleDigestsKey, loaded_module_digests.release()); - } - - // ------------------------------------------------------------------------- - - // Adds a |task| that can do as much asynchronous processing as it wants, but - // will need to finally call PostNextTask() on the UI thread when done. - void AddAsyncTask(const base::Closure& task) { - task_queue_.push(task); - } - - // Convenience wrapper for synchronous tasks. - void SynchronousTaskWrapper(const base::Closure& task) { - base::ElapsedTimer timer; - task.Run(); - UMA_HISTOGRAM_CUSTOM_TIMES( - "AutomaticProfileReset.InputBuilder.TaskDuration", - timer.Elapsed(), - base::TimeDelta::FromMilliseconds(1), - base::TimeDelta::FromSeconds(2), - 50); - PostNextTask(); - } - - // Adds a task that needs to finish synchronously. In exchange, PostNextTask() - // is called automatically when the |task| returns, and execution time is - // measured. - void AddTask(const base::Closure& task) { - task_queue_.push( - base::Bind(&InputBuilder::SynchronousTaskWrapper, AsWeakPtr(), task)); - } - - // Posts the next task from the |task_queue_|, unless it is exhausted, in - // which case it posts |callback_| to return with the results. - void PostNextTask() { - base::Closure next_task; - if (task_queue_.empty()) { - next_task = base::Bind(callback_, base::Passed(&data_)); - } else { - next_task = task_queue_.front(); - task_queue_.pop(); - } - content::BrowserThread::PostTask( - content::BrowserThread::UI, FROM_HERE, next_task); - } - - Profile* profile_; - AutomaticProfileResetterDelegate* delegate_; - ProgramInputCallback callback_; - - PreferenceHostedPromptMemento memento_in_prefs_; - LocalStateHostedPromptMemento memento_in_local_state_; - FileHostedPromptMemento memento_in_file_; - - scoped_ptr<base::DictionaryValue> data_; - std::queue<base::Closure> task_queue_; - - DISALLOW_COPY_AND_ASSIGN(InputBuilder); -}; - - -// AutomaticProfileResetter::EvaluationResults ------------------------------- - -// Encapsulates the output values extracted from the evaluator program. -struct AutomaticProfileResetter::EvaluationResults { - EvaluationResults() - : should_prompt(false), - had_prompted_already(false), - satisfied_criteria_mask(0), - combined_status_mask(0) {} - - std::string memento_value_in_prefs; - std::string memento_value_in_local_state; - std::string memento_value_in_file; - - bool should_prompt; - bool had_prompted_already; - uint32 satisfied_criteria_mask; - uint32 combined_status_mask; -}; - - -// AutomaticProfileResetter -------------------------------------------------- - -AutomaticProfileResetter::AutomaticProfileResetter(Profile* profile) - : profile_(profile), - state_(STATE_UNINITIALIZED), - enumeration_of_loaded_modules_ready_(false), - template_url_service_ready_(false), - has_already_dismissed_prompt_(false), - should_show_reset_banner_(false), - weak_ptr_factory_(this) { - DCHECK(profile_); -} - -AutomaticProfileResetter::~AutomaticProfileResetter() {} - -void AutomaticProfileResetter::Initialize() { - DCHECK_CURRENTLY_ON(content::BrowserThread::UI); - DCHECK_EQ(state_, STATE_UNINITIALIZED); - - if (!ShouldPerformDryRun() && !ShouldPerformLiveRun()) { - state_ = STATE_DISABLED; - return; - } - - if (!GetProgramAndHashSeedOverridesFromExperiment(&program_, &hash_seed_)) { - ui::ResourceBundle& resources(ui::ResourceBundle::GetSharedInstance()); - if (ShouldPerformLiveRun()) { - program_ = resources.GetRawDataResource( - IDR_AUTOMATIC_PROFILE_RESET_RULES).as_string(); - hash_seed_ = resources.GetRawDataResource( - IDR_AUTOMATIC_PROFILE_RESET_HASH_SEED).as_string(); - } else { // ShouldPerformDryRun() - program_ = resources.GetRawDataResource( - IDR_AUTOMATIC_PROFILE_RESET_RULES_DRY).as_string(); - hash_seed_ = resources.GetRawDataResource( - IDR_AUTOMATIC_PROFILE_RESET_HASH_SEED_DRY).as_string(); - } - } - - delegate_.reset(new AutomaticProfileResetterDelegateImpl( - profile_, ProfileResetter::ALL)); - task_runner_for_waiting_ = - content::BrowserThread::GetMessageLoopProxyForThread( - content::BrowserThread::UI); - - state_ = STATE_INITIALIZED; -} - -void AutomaticProfileResetter::Activate() { - DCHECK_CURRENTLY_ON(content::BrowserThread::UI); - DCHECK(state_ == STATE_INITIALIZED || state_ == STATE_DISABLED); - - if (state_ == STATE_INITIALIZED) { - if (!program_.empty()) { - // Some steps in the flow (e.g. loaded modules, file-based memento) are - // IO-intensive, so defer execution until some time later. - task_runner_for_waiting_->PostDelayedTask( - FROM_HERE, - base::Bind(&AutomaticProfileResetter::PrepareEvaluationFlow, - weak_ptr_factory_.GetWeakPtr()), - base::TimeDelta::FromSeconds(kEvaluationFlowDelayInSeconds)); - } else { - // Terminate early if there is no program included (nor set by tests). - state_ = STATE_DISABLED; - } - } -} - -void AutomaticProfileResetter::TriggerProfileReset(bool send_feedback) { - DCHECK_CURRENTLY_ON(content::BrowserThread::UI); - DCHECK_EQ(state_, STATE_HAS_SHOWN_BUBBLE); - - state_ = STATE_PERFORMING_RESET; - should_show_reset_banner_ = false; - - ReportPromptResult(PROMPT_ACTION_RESET); - delegate_->TriggerProfileSettingsReset( - send_feedback, - base::Bind(&AutomaticProfileResetter::OnProfileSettingsResetCompleted, - weak_ptr_factory_.GetWeakPtr())); -} - -void AutomaticProfileResetter::SkipProfileReset() { - DCHECK_CURRENTLY_ON(content::BrowserThread::UI); - DCHECK_EQ(state_, STATE_HAS_SHOWN_BUBBLE); - - should_show_reset_banner_ = false; - - ReportPromptResult(PROMPT_ACTION_NO_RESET); - delegate_->DismissPrompt(); - FinishResetPromptFlow(); -} - -bool AutomaticProfileResetter::IsResetPromptFlowActive() const { - return state_ == STATE_HAS_TRIGGERED_PROMPT || - state_ == STATE_HAS_SHOWN_BUBBLE; -} - -bool AutomaticProfileResetter::ShouldShowResetBanner() const { - DCHECK_CURRENTLY_ON(content::BrowserThread::UI); - return should_show_reset_banner_ && ShouldPerformLiveRun(); -} - -void AutomaticProfileResetter::NotifyDidShowResetBubble() { - DCHECK_CURRENTLY_ON(content::BrowserThread::UI); - DCHECK_EQ(state_, STATE_HAS_TRIGGERED_PROMPT); - - state_ = STATE_HAS_SHOWN_BUBBLE; - - PersistMementos(); - ReportPromptResult(PROMPT_SHOWN_BUBBLE); -} - -void AutomaticProfileResetter::NotifyDidOpenWebUIResetDialog() { - DCHECK_CURRENTLY_ON(content::BrowserThread::UI); - - // This notification is invoked unconditionally by the WebUI, only care about - // it when the prompt flow is currently active (and not yet resetting). - if (state_ == STATE_HAS_TRIGGERED_PROMPT || - state_ == STATE_HAS_SHOWN_BUBBLE) { - has_already_dismissed_prompt_ = true; - delegate_->DismissPrompt(); - } -} - -void AutomaticProfileResetter::NotifyDidCloseWebUIResetDialog( - bool performed_reset) { - DCHECK_CURRENTLY_ON(content::BrowserThread::UI); - - // This notification is invoked unconditionally by the WebUI, only care about - // it when the prompt flow is currently active (and not yet resetting). - if (state_ == STATE_HAS_TRIGGERED_PROMPT || - state_ == STATE_HAS_SHOWN_BUBBLE) { - if (!has_already_dismissed_prompt_) - delegate_->DismissPrompt(); - if (state_ == STATE_HAS_TRIGGERED_PROMPT) { - PersistMementos(); - ReportPromptResult(performed_reset ? - PROMPT_NOT_SHOWN_BUBBLE_BUT_HAD_WEBUI_RESET : - PROMPT_NOT_SHOWN_BUBBLE_BUT_HAD_WEBUI_NO_RESET); - } else { // if (state_ == STATE_HAS_SHOWN_PROMPT) - ReportPromptResult(performed_reset ? - PROMPT_FOLLOWED_BY_WEBUI_RESET : - PROMPT_FOLLOWED_BY_WEBUI_NO_RESET); - } - FinishResetPromptFlow(); - } -} - -void AutomaticProfileResetter::NotifyDidCloseWebUIResetBanner() { - DCHECK_CURRENTLY_ON(content::BrowserThread::UI); - should_show_reset_banner_ = false; -} - -void AutomaticProfileResetter::SetProgramForTesting( - const std::string& program) { - program_ = program; -} - -void AutomaticProfileResetter::SetHashSeedForTesting( - const std::string& hash_key) { - hash_seed_ = hash_key; -} - -void AutomaticProfileResetter::SetDelegateForTesting( - scoped_ptr<AutomaticProfileResetterDelegate> delegate) { - delegate_ = delegate.Pass(); -} - -void AutomaticProfileResetter::SetTaskRunnerForWaitingForTesting( - const scoped_refptr<base::TaskRunner>& task_runner) { - task_runner_for_waiting_ = task_runner; -} - -void AutomaticProfileResetter::Shutdown() { - DCHECK_CURRENTLY_ON(content::BrowserThread::UI); - - // We better not do anything substantial at this point. The metrics service - // has already been shut down; and local state has already been commited to - // file (in the regular fashion) for the last time. - - state_ = STATE_DISABLED; - - weak_ptr_factory_.InvalidateWeakPtrs(); - delegate_.reset(); -} - -void AutomaticProfileResetter::PrepareEvaluationFlow() { - DCHECK_CURRENTLY_ON(content::BrowserThread::UI); - DCHECK_EQ(state_, STATE_INITIALIZED); - - state_ = STATE_WAITING_ON_DEPENDENCIES; - - delegate_->RequestCallbackWhenTemplateURLServiceIsLoaded( - base::Bind(&AutomaticProfileResetter::OnTemplateURLServiceIsLoaded, - weak_ptr_factory_.GetWeakPtr())); - delegate_->RequestCallbackWhenLoadedModulesAreEnumerated( - base::Bind(&AutomaticProfileResetter::OnLoadedModulesAreEnumerated, - weak_ptr_factory_.GetWeakPtr())); - delegate_->LoadTemplateURLServiceIfNeeded(); - delegate_->EnumerateLoadedModulesIfNeeded(); -} - -void AutomaticProfileResetter::OnTemplateURLServiceIsLoaded() { - template_url_service_ready_ = true; - OnDependencyIsReady(); -} - -void AutomaticProfileResetter::OnLoadedModulesAreEnumerated() { - enumeration_of_loaded_modules_ready_ = true; - OnDependencyIsReady(); -} - -void AutomaticProfileResetter::OnDependencyIsReady() { - DCHECK_CURRENTLY_ON(content::BrowserThread::UI); - DCHECK_EQ(state_, STATE_WAITING_ON_DEPENDENCIES); - - if (template_url_service_ready_ && enumeration_of_loaded_modules_ready_) { - state_ = STATE_READY; - content::BrowserThread::PostTask( - content::BrowserThread::UI, - FROM_HERE, - base::Bind(&AutomaticProfileResetter::BeginEvaluationFlow, - weak_ptr_factory_.GetWeakPtr())); - } -} - -void AutomaticProfileResetter::BeginEvaluationFlow() { - DCHECK_CURRENTLY_ON(content::BrowserThread::UI); - DCHECK_EQ(state_, STATE_READY); - DCHECK(!program_.empty()); - DCHECK(!input_builder_); - - state_ = STATE_EVALUATING_CONDITIONS; - - input_builder_.reset(new InputBuilder(profile_, delegate_.get())); - input_builder_->BuildEvaluatorProgramInput( - base::Bind(&AutomaticProfileResetter::ContinueWithEvaluationFlow, - weak_ptr_factory_.GetWeakPtr())); -} - -void AutomaticProfileResetter::ContinueWithEvaluationFlow( - scoped_ptr<base::DictionaryValue> program_input) { - DCHECK_CURRENTLY_ON(content::BrowserThread::UI); - DCHECK_EQ(state_, STATE_EVALUATING_CONDITIONS); - - input_builder_.reset(); - - base::SequencedWorkerPool* blocking_pool = - content::BrowserThread::GetBlockingPool(); - scoped_refptr<base::TaskRunner> task_runner = - blocking_pool->GetTaskRunnerWithShutdownBehavior( - base::SequencedWorkerPool::SKIP_ON_SHUTDOWN); - - base::PostTaskAndReplyWithResult( - task_runner.get(), - FROM_HERE, - base::Bind(&EvaluateConditionsOnWorkerPoolThread, - hash_seed_, - program_, - base::Passed(&program_input)), - base::Bind(&AutomaticProfileResetter::FinishEvaluationFlow, - weak_ptr_factory_.GetWeakPtr())); -} - -// static -scoped_ptr<AutomaticProfileResetter::EvaluationResults> - AutomaticProfileResetter::EvaluateConditionsOnWorkerPoolThread( - const std::string& hash_seed, - const std::string& program, - scoped_ptr<base::DictionaryValue> program_input) { - JtlInterpreter interpreter(hash_seed, program, program_input.get()); - interpreter.Execute(); - UMA_HISTOGRAM_ENUMERATION("AutomaticProfileReset.InterpreterResult", - interpreter.result(), - JtlInterpreter::RESULT_MAX); - UMA_HISTOGRAM_SPARSE_SLOWLY("AutomaticProfileReset.ProgramChecksum", - interpreter.CalculateProgramChecksum()); - - // In each case below, the respective field in result originally contains the - // default, so if the getter fails, we still have the correct value there. - scoped_ptr<EvaluationResults> results(new EvaluationResults); - interpreter.GetOutputBoolean(kShouldPromptKey, &results->should_prompt); - interpreter.GetOutputBoolean(kHadPromptedAlreadyKey, - &results->had_prompted_already); - interpreter.GetOutputString(kMementoValueInPrefsKey, - &results->memento_value_in_prefs); - interpreter.GetOutputString(kMementoValueInLocalStateKey, - &results->memento_value_in_local_state); - interpreter.GetOutputString(kMementoValueInFileKey, - &results->memento_value_in_file); - for (size_t i = 0; i < kCombinedStatusMaskNumberOfBits; ++i) { - bool flag = false; - std::string mask_i_th_bit_key = - kCombinedStatusMaskKeyPrefix + base::SizeTToString(i + 1); - if (interpreter.GetOutputBoolean(mask_i_th_bit_key, &flag) && flag) - results->combined_status_mask |= (1 << i); - } - for (size_t i = 0; i < kSatisfiedCriteriaMaskNumberOfBits; ++i) { - bool flag = false; - std::string mask_i_th_bit_key = - kSatisfiedCriteriaMaskKeyPrefix + base::SizeTToString(i + 1); - if (interpreter.GetOutputBoolean(mask_i_th_bit_key, &flag) && flag) - results->satisfied_criteria_mask |= (1 << i); - } - return results.Pass(); -} - -void AutomaticProfileResetter::ReportStatistics(uint32 satisfied_criteria_mask, - uint32 combined_status_mask) { - UMA_HISTOGRAM_ENUMERATION("AutomaticProfileReset.SatisfiedCriteriaMask", - satisfied_criteria_mask, - kSatisfiedCriteriaMaskMaximumValue); - UMA_HISTOGRAM_ENUMERATION("AutomaticProfileReset.CombinedStatusMask", - combined_status_mask, - kCombinedStatusMaskMaximumValue); -} - -void AutomaticProfileResetter::FinishEvaluationFlow( - scoped_ptr<EvaluationResults> results) { - DCHECK_CURRENTLY_ON(content::BrowserThread::UI); - DCHECK_EQ(state_, STATE_EVALUATING_CONDITIONS); - - ReportStatistics(results->satisfied_criteria_mask, - results->combined_status_mask); - - if (results->should_prompt) - should_show_reset_banner_ = true; - - if (results->should_prompt && !results->had_prompted_already) { - evaluation_results_ = results.Pass(); - BeginResetPromptFlow(); - } else { - state_ = STATE_DONE; - } -} - -void AutomaticProfileResetter::BeginResetPromptFlow() { - DCHECK_CURRENTLY_ON(content::BrowserThread::UI); - DCHECK_EQ(state_, STATE_EVALUATING_CONDITIONS); - - state_ = STATE_HAS_TRIGGERED_PROMPT; - - if (ShouldPerformLiveRun() && delegate_->TriggerPrompt()) { - // Start fetching the brandcoded default settings speculatively in the - // background, so as to reduce waiting time if the user chooses to go - // through with the reset. - delegate_->FetchBrandcodedDefaultSettingsIfNeeded(); - } else { - PersistMementos(); - ReportPromptResult(PROMPT_NOT_TRIGGERED); - FinishResetPromptFlow(); - } -} - -void AutomaticProfileResetter::OnProfileSettingsResetCompleted() { - DCHECK_CURRENTLY_ON(content::BrowserThread::UI); - DCHECK_EQ(state_, STATE_PERFORMING_RESET); - - delegate_->DismissPrompt(); - FinishResetPromptFlow(); -} - -void AutomaticProfileResetter::ReportPromptResult(PromptResult result) { - UMA_HISTOGRAM_ENUMERATION( - "AutomaticProfileReset.PromptResult", result, PROMPT_RESULT_MAX); -} - -void AutomaticProfileResetter::PersistMementos() { - DCHECK_CURRENTLY_ON(content::BrowserThread::UI); - DCHECK(state_ == STATE_HAS_TRIGGERED_PROMPT || - state_ == STATE_HAS_SHOWN_BUBBLE); - DCHECK(evaluation_results_); - - PreferenceHostedPromptMemento memento_in_prefs(profile_); - LocalStateHostedPromptMemento memento_in_local_state(profile_); - FileHostedPromptMemento memento_in_file(profile_); - - memento_in_prefs.StoreValue(evaluation_results_->memento_value_in_prefs); - memento_in_local_state.StoreValue( - evaluation_results_->memento_value_in_local_state); - memento_in_file.StoreValue(evaluation_results_->memento_value_in_file); - - evaluation_results_.reset(); -} - -void AutomaticProfileResetter::FinishResetPromptFlow() { - DCHECK_CURRENTLY_ON(content::BrowserThread::UI); - DCHECK(state_ == STATE_HAS_TRIGGERED_PROMPT || - state_ == STATE_HAS_SHOWN_BUBBLE || - state_ == STATE_PERFORMING_RESET); - DCHECK(!evaluation_results_); - - state_ = STATE_DONE; -} diff --git a/chrome/browser/profile_resetter/automatic_profile_resetter.h b/chrome/browser/profile_resetter/automatic_profile_resetter.h deleted file mode 100644 index 0e43a1b..0000000 --- a/chrome/browser/profile_resetter/automatic_profile_resetter.h +++ /dev/null @@ -1,268 +0,0 @@ -// Copyright 2013 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 CHROME_BROWSER_PROFILE_RESETTER_AUTOMATIC_PROFILE_RESETTER_H_ -#define CHROME_BROWSER_PROFILE_RESETTER_AUTOMATIC_PROFILE_RESETTER_H_ - -#include <string> - -#include "base/basictypes.h" -#include "base/memory/ref_counted.h" -#include "base/memory/scoped_ptr.h" -#include "base/memory/weak_ptr.h" -#include "base/strings/string_piece.h" -#include "base/task_runner.h" -#include "chrome/browser/profile_resetter/automatic_profile_resetter_mementos.h" -#include "components/keyed_service/core/keyed_service.h" - -class AutomaticProfileResetterDelegate; -class Profile; - -namespace base { -class DictionaryValue; -class ListValue; -} - -// This service is responsible for evaluating whether the criteria for showing -// the one-time profile reset prompt are satisfied, and for potentially -// triggering the prompt. To ensure that the prompt only appears at most once -// for any given profile, a "memento" that the prompt has appeared is written to -// the profile on disk; see automatic_profile_resetter_mementos.h for details. -// The service is created automatically with the Profile and is activated right -// away by its factory. To avoid delaying start-up, however, it will only start -// working after a short delay. -// All methods in this class shall be called on the UI thread, except when noted -// otherwise. -class AutomaticProfileResetter : public KeyedService { - public: - // Enumeration listing the possible outcomes of triggering the profile reset - // prompt. - enum PromptResult { - // The reset prompt was not triggered because only a dry-run was performed, - // or because it was not supported on the current platform. - PROMPT_NOT_TRIGGERED, - // The reset bubble actually got shown. In contrast to the wrench menu item - // that can always be shown, the bubble might be delayed or might never be - // shown if another bubble was shown at the time of triggering the prompt. - // This enumeration value is usually recorded in conjunction with another - // PromptResult, the absence of which indicates that the prompt was ignored. - PROMPT_SHOWN_BUBBLE, - // The user selected "Reset" or "No, thanks" (respectively) directly from - // within the bubble. - PROMPT_ACTION_RESET, - PROMPT_ACTION_NO_RESET, - // The reset bubble was shown, then dismissed without taking definitive - // action. Then, however, the user initiated or refrained from doing a reset - // (respectively) from the conventional, WebUI-based reset dialog. - PROMPT_FOLLOWED_BY_WEBUI_RESET, - PROMPT_FOLLOWED_BY_WEBUI_NO_RESET, - // The reset bubble was suppressed (not shown) because another bubble was - // already being shown at the time. Regardless, however, the user initiated - // or refrained from doing a reset (respectively) from the conventional, - // WebUI-based reset dialog. - PROMPT_NOT_SHOWN_BUBBLE_BUT_HAD_WEBUI_RESET, - PROMPT_NOT_SHOWN_BUBBLE_BUT_HAD_WEBUI_NO_RESET, - PROMPT_RESULT_MAX - }; - - explicit AutomaticProfileResetter(Profile* profile); - ~AutomaticProfileResetter() override; - - // Initializes the service if it is enabled in the field trial. Otherwise, - // skips the initialization steps, and also permanently disables the service. - // Called by AutomaticProfileResetterFactory. - void Initialize(); - - // Fires up the service by unleashing the asynchronous evaluation flow, unless - // the service has been already disabled in Initialize() or there is no - // |program_| to run (in which case the service also gets disabled). - // Called by the AutomaticProfileResetterFactory. - void Activate(); - - // Called in case the user chooses to reset their profile settings from inside - // the reset bubble. Will trigger the reset, optionally |send_feedback|, and - // conclude the reset prompt flow. - void TriggerProfileReset(bool send_feedback); - - // Called in case the user chooses from inside the reset bubble that they do - // not want to reset their profile settings. Will conclude the reset prompt - // flow without setting off a reset. - void SkipProfileReset(); - - // Returns whether or not the profile reset prompt flow is currently active, - // that is, we have triggered the prompt and are waiting for the user to take - // definitive action (and we are not yet performing a reset). - bool IsResetPromptFlowActive() const; - - // Returns whether or not the profile reset banner should be shown on the - // WebUI-based settings page. - bool ShouldShowResetBanner() const; - - // Called to give notice that the reset bubble has actually been shown. - void NotifyDidShowResetBubble(); - - // Called to give notice that the conventional, WebUI-based settings reset - // dialog has been opened. This will dismiss the menu item in the wrench menu. - // This should always be followed by a corresponding call to - // NotifyDidCloseWebUIResetDialog(). - void NotifyDidOpenWebUIResetDialog(); - - // Called to give notice that the conventional, WebUI-based settings reset - // dialog has been closed, with |performed_reset| indicating whether or not a - // reset was requested. This is required so that we can record the appropriate - // PromptResult, dismiss the prompt, and conclude the reset prompt flow early - // without setting off any resets in the future. - void NotifyDidCloseWebUIResetDialog(bool performed_reset); - - // Called to give notice that reset banner has been dismissed as a result of - // user action on the WebUI-based settings page itself. - void NotifyDidCloseWebUIResetBanner(); - - base::WeakPtr<AutomaticProfileResetter> AsWeakPtr() { - return weak_ptr_factory_.GetWeakPtr(); - } - - // Should be called before Activate(). - void SetProgramForTesting(const std::string& program); - - // Should be called before Activate(). - void SetHashSeedForTesting(const std::string& hash_seed); - - // Should be called before Activate(). - void SetDelegateForTesting( - scoped_ptr<AutomaticProfileResetterDelegate> delegate); - - // Should be called before Activate(). Sets the task runner to be used to post - // task |PrepareEvaluationFlow| in a delayed manner. - void SetTaskRunnerForWaitingForTesting( - const scoped_refptr<base::TaskRunner>& task_runner); - - // KeyedService: - void Shutdown() override; - - private: - class InputBuilder; - struct EvaluationResults; - - enum State { - STATE_UNINITIALIZED, - STATE_INITIALIZED, - STATE_DISABLED, - STATE_WAITING_ON_DEPENDENCIES, - STATE_READY, - STATE_EVALUATING_CONDITIONS, - // The reset prompt has been triggered; but the reset bubble has not yet - // been shown. - STATE_HAS_TRIGGERED_PROMPT, - // The reset prompt has been triggered; the reset bubble has been shown, and - // potentially already dismissed by the user. - STATE_HAS_SHOWN_BUBBLE, - STATE_PERFORMING_RESET, - STATE_DONE - }; - - // Prepares the asynchronous evaluation flow by requesting services that it - // depends on to make themselves ready. - void PrepareEvaluationFlow(); - - // Called back by |resetter_delegate_| when the template URL service is ready. - void OnTemplateURLServiceIsLoaded(); - - // Called back by |resetter_delegate_| when the loaded modules have been - // enumerated. - void OnLoadedModulesAreEnumerated(); - - // Invoked by the above two methods. Kicks off the actual evaluation flow. - void OnDependencyIsReady(); - - // Begins the asynchronous evaluation flow, which will assess whether the - // criteria for showing the reset prompt are met, whether we have already - // shown the prompt; and, in the end, will potentially trigger the prompt. - void BeginEvaluationFlow(); - - // Called by InputBuilder once it has finished assembling the |program_input|, - // and will continue with the evaluation flow by triggering the evaluator - // program on the worker thread. - void ContinueWithEvaluationFlow( - scoped_ptr<base::DictionaryValue> program_input); - - // Performs the bulk of the work. Invokes the JTL interpreter to run the - // |program| that will evaluate whether the conditions are met for showing the - // reset prompt. The program will make this decision based on the state - // information contained in |input| in the form of key-value pairs. The - // program will only see hashed keys and values that are produced using - // |hash_seed| as a key. - static scoped_ptr<EvaluationResults> EvaluateConditionsOnWorkerPoolThread( - const std::string& hash_seed, - const std::string& program, - scoped_ptr<base::DictionaryValue> program_input); - - // Reports the given metrics through UMA. Virtual, so it can be mocked out in - // tests to verify that the correct value are being reported. - virtual void ReportStatistics(uint32 satisfied_criteria_mask, - uint32 combined_status_mask); - - // Called back when EvaluateConditionsOnWorkerPoolThread completes executing - // the program with |results|. Finishes the evaluation flow, and, based on the - // result, potentially initiates the reset prompt flow. - void FinishEvaluationFlow(scoped_ptr<EvaluationResults> results); - - // Begins the reset prompt flow by triggering the reset prompt, which consists - // of two parts: (1.) the profile reset (pop-up) bubble, and (2.) a menu item - // in the wrench menu (provided by a GlobalError). - // The flow lasts until we receive a clear indication from the user about - // whether or not they wish to reset their settings. This indication can come - // in a variety of flavors: - // * taking definitive action (i.e. selecting either "Reset" or "No, thanks") - // in the pop-up reset bubble itself, - // * dismissing the bubble, but then selecting the wrench menu item, which - // takes them to the WebUI reset dialog in chrome://settings, and then the - // user can make their choice there, - // * the user going to the WebUI reset dialog by themself. - // For the most part, the conclusion of the reset flow coincides with when the - // reset prompt is dismissed, with the one exception being that the prompt is - // closed as soon as the WebUI reset dialog is opened, we do not wait until - // the user actually makes a choice in that dialog. - void BeginResetPromptFlow(); - - // Called back by the ProfileResetter once resetting the profile settings has - // been completed, when requested by the user from inside the reset bubble. - // Will dismiss the prompt and conclude the reset prompt flow. - void OnProfileSettingsResetCompleted(); - - // Reports the result of triggering the prompt through UMA. Virtual, so it can - // be mocked out in tests to verify that the correct value is being reported. - virtual void ReportPromptResult(PromptResult result); - - // Writes the memento values returned by the evaluation program to disk, and - // then destroys |evaluation_results_|. - void PersistMementos(); - - // Concludes the reset prompt flow. - void FinishResetPromptFlow(); - - Profile* profile_; - - State state_; - bool enumeration_of_loaded_modules_ready_; - bool template_url_service_ready_; - bool has_already_dismissed_prompt_; - - scoped_ptr<InputBuilder> input_builder_; - std::string hash_seed_; - std::string program_; - - scoped_ptr<EvaluationResults> evaluation_results_; - - bool should_show_reset_banner_; - - scoped_ptr<AutomaticProfileResetterDelegate> delegate_; - scoped_refptr<base::TaskRunner> task_runner_for_waiting_; - - base::WeakPtrFactory<AutomaticProfileResetter> weak_ptr_factory_; - - DISALLOW_COPY_AND_ASSIGN(AutomaticProfileResetter); -}; - -#endif // CHROME_BROWSER_PROFILE_RESETTER_AUTOMATIC_PROFILE_RESETTER_H_ diff --git a/chrome/browser/profile_resetter/automatic_profile_resetter_delegate.cc b/chrome/browser/profile_resetter/automatic_profile_resetter_delegate.cc deleted file mode 100644 index b74329f..0000000 --- a/chrome/browser/profile_resetter/automatic_profile_resetter_delegate.cc +++ /dev/null @@ -1,393 +0,0 @@ -// Copyright 2013 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 "chrome/browser/profile_resetter/automatic_profile_resetter_delegate.h" - -#include <string> - -#include "base/bind.h" -#include "base/bind_helpers.h" -#include "base/callback.h" -#include "base/logging.h" -#include "base/md5.h" -#include "base/memory/scoped_vector.h" -#include "base/strings/string_number_conversions.h" -#include "base/strings/string_util.h" -#include "base/values.h" -#include "chrome/app/chrome_command_ids.h" -#include "chrome/browser/chrome_notification_types.h" -#include "chrome/browser/google/google_brand.h" -#include "chrome/browser/profile_resetter/brandcode_config_fetcher.h" -#include "chrome/browser/profile_resetter/profile_reset_global_error.h" -#include "chrome/browser/profile_resetter/profile_resetter.h" -#include "chrome/browser/profile_resetter/resettable_settings_snapshot.h" -#include "chrome/browser/profiles/profile.h" -#include "chrome/browser/search_engines/template_url_service_factory.h" -#include "chrome/browser/ui/browser.h" -#include "chrome/browser/ui/browser_finder.h" -#include "chrome/browser/ui/global_error/global_error_service.h" -#include "chrome/browser/ui/global_error/global_error_service_factory.h" -#include "components/search_engines/template_url_prepopulate_data.h" -#include "components/search_engines/template_url_service.h" -#include "content/public/browser/browser_thread.h" -#include "content/public/browser/notification_service.h" - -#if defined(OS_WIN) -#include "chrome/browser/enumerate_modules_model_win.h" -#endif - -namespace { - -scoped_ptr<base::DictionaryValue> BuildSubTreeFromTemplateURL( - const TemplateURL* template_url) { - // If this value contains a placeholder in the pre-populated data, it will - // have been replaced as it was loaded into a TemplateURL. - // BuildSubTreeFromTemplateURL works with TemplateURL (not TemplateURLData) - // in order to maintain this behaviour. - // TODO(engedy): Confirm the expected behaviour and convert to use - // TemplateURLData if possible." - scoped_ptr<base::DictionaryValue> tree(new base::DictionaryValue); - tree->SetString("name", template_url->short_name()); - tree->SetString("short_name", template_url->short_name()); - tree->SetString("keyword", template_url->keyword()); - tree->SetString("search_url", template_url->url()); - tree->SetString("url", template_url->url()); - tree->SetString("suggestions_url", template_url->suggestions_url()); - tree->SetString("instant_url", template_url->instant_url()); - tree->SetString("image_url", template_url->image_url()); - tree->SetString("new_tab_url", template_url->new_tab_url()); - tree->SetString("search_url_post_params", - template_url->search_url_post_params()); - tree->SetString("suggestions_url_post_params", - template_url->suggestions_url_post_params()); - tree->SetString("instant_url_post_params", - template_url->instant_url_post_params()); - tree->SetString("image_url_post_params", - template_url->image_url_post_params()); - base::ListValue* alternate_urls = new base::ListValue; - alternate_urls->AppendStrings(template_url->alternate_urls()); - tree->Set("alternate_urls", alternate_urls); - tree->SetString("favicon_url", template_url->favicon_url().spec()); - tree->SetString("originating_url", template_url->originating_url().spec()); - tree->SetBoolean("safe_for_autoreplace", - template_url->safe_for_autoreplace()); - base::ListValue* input_encodings = new base::ListValue; - input_encodings->AppendStrings(template_url->input_encodings()); - tree->Set("input_encodings", input_encodings); - tree->SetString("id", base::Int64ToString(template_url->id())); - tree->SetString("date_created", - base::Int64ToString( - template_url->date_created().ToInternalValue())); - tree->SetString("last_modified", - base::Int64ToString( - template_url->last_modified().ToInternalValue())); - tree->SetBoolean("created_by_policy", template_url->created_by_policy()); - tree->SetInteger("usage_count", template_url->usage_count()); - tree->SetInteger("prepopulate_id", template_url->prepopulate_id()); - tree->SetString("search_terms_replacement_key", - template_url->search_terms_replacement_key()); - return tree.Pass(); -} - -#if defined(OS_WIN) -void ExtractLoadedModuleNameDigests( - const base::ListValue& module_list, - base::ListValue* module_name_digests) { - DCHECK(module_name_digests); - - // EnumerateModulesModel produces a list of dictionaries. - // Each dictionary corresponds to a module and exposes a number of properties. - // We care only about 'type' and 'name'. - for (size_t i = 0; i < module_list.GetSize(); ++i) { - const base::DictionaryValue* module_dictionary = NULL; - if (!module_list.GetDictionary(i, &module_dictionary)) - continue; - ModuleEnumerator::ModuleType module_type = - ModuleEnumerator::LOADED_MODULE; - if (!module_dictionary->GetInteger( - "type", reinterpret_cast<int*>(&module_type)) || - module_type != ModuleEnumerator::LOADED_MODULE) { - continue; - } - std::string module_name; - if (!module_dictionary->GetString("name", &module_name)) - continue; - module_name = base::ToLowerASCII(module_name); - module_name_digests->AppendString(base::MD5String(module_name)); - } -} -#endif - -} // namespace - - -// AutomaticProfileResetterDelegateImpl -------------------------------------- - -AutomaticProfileResetterDelegateImpl::AutomaticProfileResetterDelegateImpl( - Profile* profile, - ProfileResetter::ResettableFlags resettable_aspects) - : profile_(profile), - global_error_service_(GlobalErrorServiceFactory::GetForProfile(profile_)), - template_url_service_(TemplateURLServiceFactory::GetForProfile(profile_)), - resettable_aspects_(resettable_aspects) { - DCHECK(profile_); - if (template_url_service_) { - template_url_service_->AddObserver(this); - // Needed so that |template_url_service_ready_event_| will be signaled even - // when TemplateURLService had been already initialized before this point. - OnTemplateURLServiceChanged(); - } - -#if defined(OS_WIN) - module_list_.reset(EnumerateModulesModel::GetInstance()->GetModuleList()); -#endif - if (module_list_) { - // Having a non-empty module list proves that enumeration had been already - // performed before this point. - modules_have_been_enumerated_event_.Signal(); - } - registrar_.Add(this, - chrome::NOTIFICATION_MODULE_LIST_ENUMERATED, - content::NotificationService::AllSources()); -} - -AutomaticProfileResetterDelegateImpl::~AutomaticProfileResetterDelegateImpl() { - if (template_url_service_) - template_url_service_->RemoveObserver(this); -} - -void AutomaticProfileResetterDelegateImpl::EnumerateLoadedModulesIfNeeded() { - if (!modules_have_been_enumerated_event_.is_signaled()) { -#if defined(OS_WIN) - EnumerateModulesModel::GetInstance()->ScanNow(); -#else - modules_have_been_enumerated_event_.Signal(); -#endif - } -} - -void AutomaticProfileResetterDelegateImpl:: - RequestCallbackWhenLoadedModulesAreEnumerated( - const base::Closure& ready_callback) const { - DCHECK(!ready_callback.is_null()); - modules_have_been_enumerated_event_.Post(FROM_HERE, ready_callback); -} - -void AutomaticProfileResetterDelegateImpl::LoadTemplateURLServiceIfNeeded() { - DCHECK(template_url_service_); - template_url_service_->Load(); // Safe to call even if it has loaded already. -} - -void AutomaticProfileResetterDelegateImpl:: - RequestCallbackWhenTemplateURLServiceIsLoaded( - const base::Closure& ready_callback) const { - DCHECK(!ready_callback.is_null()); - template_url_service_ready_event_.Post(FROM_HERE, ready_callback); -} - -void AutomaticProfileResetterDelegateImpl:: - FetchBrandcodedDefaultSettingsIfNeeded() { - if (brandcoded_config_fetcher_ || - brandcoded_defaults_fetched_event_.is_signaled()) - return; - - std::string brandcode; - google_brand::GetBrand(&brandcode); - if (brandcode.empty()) { - brandcoded_defaults_.reset(new BrandcodedDefaultSettings); - brandcoded_defaults_fetched_event_.Signal(); - } else { - brandcoded_config_fetcher_.reset(new BrandcodeConfigFetcher( - base::Bind( - &AutomaticProfileResetterDelegateImpl::OnBrandcodedDefaultsFetched, - base::Unretained(this)), - GURL("https://tools.google.com/service/update2"), - brandcode)); - } -} - -void AutomaticProfileResetterDelegateImpl:: - RequestCallbackWhenBrandcodedDefaultsAreFetched( - const base::Closure& ready_callback) const { - DCHECK(!ready_callback.is_null()); - brandcoded_defaults_fetched_event_.Post(FROM_HERE, ready_callback); -} - -scoped_ptr<base::ListValue> AutomaticProfileResetterDelegateImpl:: - GetLoadedModuleNameDigests() const { - DCHECK(modules_have_been_enumerated_event_.is_signaled()); - scoped_ptr<base::ListValue> result(new base::ListValue); -#if defined(OS_WIN) - if (module_list_) - ExtractLoadedModuleNameDigests(*module_list_, result.get()); -#endif - return result.Pass(); -} - -scoped_ptr<base::DictionaryValue> AutomaticProfileResetterDelegateImpl:: - GetDefaultSearchProviderDetails() const { - DCHECK(template_url_service_); - DCHECK(template_url_service_->loaded()); - - const TemplateURL* default_search_provider = - template_url_service_->GetDefaultSearchProvider(); - - // Having a NULL default search provider is due to either: - // 1.) default search providers being disabled by policy, - // 2.) directly tampering with the Preferences and/or the SQLite DBs. - // In this state, Omnibox non-keyword search functionality is disabled. - return default_search_provider ? - BuildSubTreeFromTemplateURL(default_search_provider) : - scoped_ptr<base::DictionaryValue>(new base::DictionaryValue); -} - -bool AutomaticProfileResetterDelegateImpl:: - IsDefaultSearchProviderManaged() const { - DCHECK(template_url_service_); - DCHECK(template_url_service_->loaded()); - return template_url_service_->is_default_search_managed(); -} - -scoped_ptr<base::ListValue> AutomaticProfileResetterDelegateImpl:: - GetPrepopulatedSearchProvidersDetails() const { - size_t default_search_index = 0; - ScopedVector<TemplateURLData> engines( - TemplateURLPrepopulateData::GetPrepopulatedEngines( - profile_->GetPrefs(), &default_search_index)); - scoped_ptr<base::ListValue> engines_details_list(new base::ListValue); - for (ScopedVector<TemplateURLData>::const_iterator it = engines.begin(); - it != engines.end(); ++it) { - TemplateURL template_url(**it); - engines_details_list->Append( - BuildSubTreeFromTemplateURL(&template_url).release()); - } - return engines_details_list.Pass(); -} - -bool AutomaticProfileResetterDelegateImpl::TriggerPrompt() { - DCHECK(global_error_service_); - - Browser* browser = chrome::FindTabbedBrowser( - profile_, false /*match_original_profiles*/, chrome::GetActiveDesktop()); - if (!browser || !ProfileResetGlobalError::IsSupportedOnPlatform(browser)) - return false; - - ProfileResetGlobalError* global_error = new ProfileResetGlobalError(profile_); - global_error_service_->AddGlobalError(global_error); - - // Do not try to show bubble if another GlobalError is already showing one. - const GlobalErrorService::GlobalErrorList& global_errors( - global_error_service_->errors()); - GlobalErrorService::GlobalErrorList::const_iterator it; - for (it = global_errors.begin(); it != global_errors.end(); ++it) { - if ((*it)->GetBubbleView()) - break; - } - if (it == global_errors.end()) - global_error->ShowBubbleView(browser); - return true; -} - -void AutomaticProfileResetterDelegateImpl::TriggerProfileSettingsReset( - bool send_feedback, - const base::Closure& completion) { - DCHECK(!profile_resetter_); - DCHECK(!completion.is_null()); - - profile_resetter_.reset(new ProfileResetter(profile_)); - FetchBrandcodedDefaultSettingsIfNeeded(); - RequestCallbackWhenBrandcodedDefaultsAreFetched(base::Bind( - &AutomaticProfileResetterDelegateImpl::RunProfileSettingsReset, - AsWeakPtr(), - send_feedback, - completion)); -} - -void AutomaticProfileResetterDelegateImpl::OnTemplateURLServiceChanged() { - DCHECK_CURRENTLY_ON(content::BrowserThread::UI); - DCHECK(template_url_service_); - if (template_url_service_->loaded() && - !template_url_service_ready_event_.is_signaled()) - template_url_service_ready_event_.Signal(); -} - -void AutomaticProfileResetterDelegateImpl::DismissPrompt() { - DCHECK(global_error_service_); - GlobalError* global_error = - global_error_service_->GetGlobalErrorByMenuItemCommandID( - IDC_SHOW_SETTINGS_RESET_BUBBLE); - if (global_error) { - // This will also close/destroy the Bubble UI if it is currently shown. - global_error_service_->RemoveGlobalError(global_error); - delete global_error; - } -} - -void AutomaticProfileResetterDelegateImpl::Observe( - int type, - const content::NotificationSource& source, - const content::NotificationDetails& details) { - DCHECK_CURRENTLY_ON(content::BrowserThread::UI); - if (type == chrome::NOTIFICATION_MODULE_LIST_ENUMERATED && - !modules_have_been_enumerated_event_.is_signaled()) { -#if defined(OS_WIN) - module_list_.reset(EnumerateModulesModel::GetInstance()->GetModuleList()); -#endif - modules_have_been_enumerated_event_.Signal(); - } -} - -void AutomaticProfileResetterDelegateImpl::SendFeedback( - const std::string& report) const { - SendSettingsFeedback(report, profile_, PROFILE_RESET_PROMPT); -} - -void AutomaticProfileResetterDelegateImpl::RunProfileSettingsReset( - bool send_feedback, - const base::Closure& completion) { - DCHECK(brandcoded_defaults_); - scoped_ptr<ResettableSettingsSnapshot> old_settings_snapshot; - if (send_feedback) { - old_settings_snapshot.reset(new ResettableSettingsSnapshot(profile_)); - old_settings_snapshot->RequestShortcuts(base::Closure()); - } - profile_resetter_->Reset(resettable_aspects_, - brandcoded_defaults_.Pass(), - send_feedback, - base::Bind(&AutomaticProfileResetterDelegateImpl:: - OnProfileSettingsResetCompleted, - AsWeakPtr(), - completion, - base::Passed(&old_settings_snapshot))); -} - -void AutomaticProfileResetterDelegateImpl:: - OnBrandcodedDefaultsFetched() { - DCHECK_CURRENTLY_ON(content::BrowserThread::UI); - DCHECK(brandcoded_config_fetcher_); - DCHECK(!brandcoded_config_fetcher_->IsActive()); - brandcoded_defaults_ = brandcoded_config_fetcher_->GetSettings(); - if (!brandcoded_defaults_) - brandcoded_defaults_.reset(new BrandcodedDefaultSettings); - brandcoded_defaults_fetched_event_.Signal(); -} - -void AutomaticProfileResetterDelegateImpl::OnProfileSettingsResetCompleted( - const base::Closure& user_callback, - scoped_ptr<ResettableSettingsSnapshot> old_settings_snapshot) { - DCHECK_CURRENTLY_ON(content::BrowserThread::UI); - if (old_settings_snapshot) { - ResettableSettingsSnapshot new_settings_snapshot(profile_); - int difference = - old_settings_snapshot->FindDifferentFields(new_settings_snapshot); - if (difference) { - old_settings_snapshot->Subtract(new_settings_snapshot); - std::string report = - SerializeSettingsReport(*old_settings_snapshot, difference); - SendFeedback(report); - } - } - content::BrowserThread::PostTask( - content::BrowserThread::UI, FROM_HERE, user_callback); -} diff --git a/chrome/browser/profile_resetter/automatic_profile_resetter_delegate.h b/chrome/browser/profile_resetter/automatic_profile_resetter_delegate.h deleted file mode 100644 index 73a660b..0000000 --- a/chrome/browser/profile_resetter/automatic_profile_resetter_delegate.h +++ /dev/null @@ -1,237 +0,0 @@ -// Copyright 2013 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. - -// Declares a delegate that interacts with the rest of the browser on behalf of -// the AutomaticProfileResetter. -// -// The reason for this separation is to facilitate unit testing. Factoring out -// the implementation for each interaction step (encapsulated by one method of -// the delegate) allows it to be tested independently in itself. It also becomes -// easier to verify that the state machine inside AutomaticProfileResetter works -// correctly: by mocking out the interaction methods in the delegate, we can, in -// effect, mock out the entire rest of the browser, allowing us to easily -// simulate scenarios that are interesting for testing the state machine. -// -// The delegate is normally instantiated by AutomaticProfileResetter internally, -// while a mock implementation can be injected during unit tests. - -#ifndef CHROME_BROWSER_PROFILE_RESETTER_AUTOMATIC_PROFILE_RESETTER_DELEGATE_H_ -#define CHROME_BROWSER_PROFILE_RESETTER_AUTOMATIC_PROFILE_RESETTER_DELEGATE_H_ - -#include "base/basictypes.h" -#include "base/callback_forward.h" -#include "base/memory/scoped_ptr.h" -#include "base/memory/weak_ptr.h" -#include "chrome/browser/profile_resetter/profile_resetter.h" -#include "components/search_engines/template_url_service_observer.h" -#include "content/public/browser/notification_observer.h" -#include "content/public/browser/notification_registrar.h" -#include "extensions/common/one_shot_event.h" - -class BrandcodeConfigFetcher; -class GlobalErrorService; -class Profile; -class ResettableSettingsSnapshot; -class TemplateURLService; - -namespace base { -class DictionaryValue; -class ListValue; -} - -// Defines the interface for the delegate that will interact with the rest of -// the browser on behalf of the AutomaticProfileResetter. -class AutomaticProfileResetterDelegate { - public: - virtual ~AutomaticProfileResetterDelegate() {} - - // Requests the module enumerator to start scanning for loaded modules now, if - // it has not done so already. - virtual void EnumerateLoadedModulesIfNeeded() = 0; - - // Requests |ready_callback| to be posted on the UI thread once the module - // enumerator has finished scanning for loaded modules. - virtual void RequestCallbackWhenLoadedModulesAreEnumerated( - const base::Closure& ready_callback) const = 0; - - // Requests the template URL service to load its database (asynchronously). - virtual void LoadTemplateURLServiceIfNeeded() = 0; - - // Requests |ready_callback| to be posted on the UI thread once the template - // URL service has finished loading its database. - virtual void RequestCallbackWhenTemplateURLServiceIsLoaded( - const base::Closure& ready_callback) const = 0; - - // Starts downloading the configuration file that specifies the default - // settings for the current brandcode; or establishes that we are running a - // vanilla (non-branded) build. - virtual void FetchBrandcodedDefaultSettingsIfNeeded() = 0; - - // Requests |ready_callback| to be posted on the UI thread once the brandcoded - // default settings have been downloaded, or once it has been established that - // we are running a vanilla (non-branded) build. - virtual void RequestCallbackWhenBrandcodedDefaultsAreFetched( - const base::Closure& ready_callback) const = 0; - - // Returns a list of loaded module name digests. - virtual scoped_ptr<base::ListValue> GetLoadedModuleNameDigests() const = 0; - - // Returns attributes of the search engine currently set as the default (or - // an empty dictionary if there is none). - // The dictionary is in the same format as persisted to preferences by - // DefaultSearchManager::SetUserSelectedDefaultSearchEngine. - virtual scoped_ptr<base::DictionaryValue> - GetDefaultSearchProviderDetails() const = 0; - - // Returns whether or not the default search provider is set by policy. - virtual bool IsDefaultSearchProviderManaged() const = 0; - - // Returns a list of dictionaries, each containing attributes for each of the - // pre-populated search engines, in the format described above. - virtual scoped_ptr<base::ListValue> - GetPrepopulatedSearchProvidersDetails() const = 0; - - // Triggers showing the one-time profile settings reset prompt, which consists - // of two parts: (1.) the profile reset (pop-up) bubble, and (2.) a menu item - // in the wrench menu. Showing the bubble might be delayed if there is another - // bubble currently shown, in which case the bubble will be shown the first - // time a new browser window is opened. - // Returns true unless the reset prompt is not supported on the current - // platform, in which case it returns false and does nothing. - virtual bool TriggerPrompt() = 0; - - // Triggers the ProfileResetter to reset all supported settings and optionally - // |send_feedback|. Will post |completion| on the UI thread once completed. - // Brandcoded default settings will be fetched if they are not yet available, - // the reset will be performed once the download is complete. - // NOTE: Should only be called at most once during the lifetime of the object. - virtual void TriggerProfileSettingsReset(bool send_feedback, - const base::Closure& completion) = 0; - - // Dismisses the one-time profile settings reset prompt, if it is currently - // triggered. Will synchronously destroy the corresponding GlobalError. - virtual void DismissPrompt() = 0; -}; - -// Implementation for AutomaticProfileResetterDelegate. -class AutomaticProfileResetterDelegateImpl - : public AutomaticProfileResetterDelegate, - public base::SupportsWeakPtr<AutomaticProfileResetterDelegateImpl>, - public TemplateURLServiceObserver, - public content::NotificationObserver { - public: - explicit AutomaticProfileResetterDelegateImpl( - Profile* profile, - ProfileResetter::ResettableFlags resettable_aspects); - ~AutomaticProfileResetterDelegateImpl() override; - - // Returns the brandcoded default settings; empty defaults if this is not a - // branded build; or NULL if FetchBrandcodedDefaultSettingsIfNeeded() has not - // yet been called or not yet finished. Exposed only for unit tests. - const BrandcodedDefaultSettings* brandcoded_defaults() const { - return brandcoded_defaults_.get(); - } - - // AutomaticProfileResetterDelegate: - void EnumerateLoadedModulesIfNeeded() override; - void RequestCallbackWhenLoadedModulesAreEnumerated( - const base::Closure& ready_callback) const override; - void LoadTemplateURLServiceIfNeeded() override; - void RequestCallbackWhenTemplateURLServiceIsLoaded( - const base::Closure& ready_callback) const override; - void FetchBrandcodedDefaultSettingsIfNeeded() override; - void RequestCallbackWhenBrandcodedDefaultsAreFetched( - const base::Closure& ready_callback) const override; - scoped_ptr<base::ListValue> GetLoadedModuleNameDigests() const override; - scoped_ptr<base::DictionaryValue> GetDefaultSearchProviderDetails() - const override; - bool IsDefaultSearchProviderManaged() const override; - scoped_ptr<base::ListValue> GetPrepopulatedSearchProvidersDetails() - const override; - bool TriggerPrompt() override; - void TriggerProfileSettingsReset(bool send_feedback, - const base::Closure& completion) override; - void DismissPrompt() override; - - // TemplateURLServiceObserver: - void OnTemplateURLServiceChanged() override; - - // content::NotificationObserver: - void Observe(int type, - const content::NotificationSource& source, - const content::NotificationDetails& details) override; - - private: - // Sends a feedback |report|, where |report| is supposed to be result of - // ::SerializeSettingsReport(). Virtual, so it can be mocked out for tests. - virtual void SendFeedback(const std::string& report) const; - - // Triggers the ProfileResetter to reset |resettable_aspects_| and optionally - // |send_feedback|. Will invoke |completion| on the UI thread once completed - // The |brandcoded_defaults_| must already be initialized when this is called. - void RunProfileSettingsReset(bool send_feedback, - const base::Closure& completion); - - // Called by |brandcoded_config_fetcher_| when it finishes downloading the - // brandcoded default settings (or the download times out). - void OnBrandcodedDefaultsFetched(); - - // Called back by the ProfileResetter once resetting the profile settings has - // been completed. If |old_settings_snapshot| is non-NULL, will compare it to - // the new settings and send the differences to Google for analysis. Finally, - // will post |user_callback|. - void OnProfileSettingsResetCompleted( - const base::Closure& user_callback, - scoped_ptr<ResettableSettingsSnapshot> old_settings_snapshot); - - // The profile that this delegate operates on. - Profile* profile_; - - // Shortcuts to |profile_| keyed services, to reduce boilerplate. These may be - // NULL in unit tests that do not initialize the respective service(s). - GlobalErrorService* global_error_service_; - TemplateURLService* template_url_service_; - - // Helper to asynchronously download the default settings for the current - // distribution channel (identified by brand code). Instantiated on-demand. - scoped_ptr<BrandcodeConfigFetcher> brandcoded_config_fetcher_; - - // Once |brandcoded_defaults_fetched_event_| has fired, this will contain the - // brandcoded default settings, or empty settings for a non-branded build. - scoped_ptr<BrandcodedDefaultSettings> brandcoded_defaults_; - - // Overwritten to avoid resetting aspects that will not work in unit tests. - const ProfileResetter::ResettableFlags resettable_aspects_; - - // The profile resetter to perform the actual reset. Instantiated on-demand. - scoped_ptr<ProfileResetter> profile_resetter_; - - // Manages registrations/unregistrations for notifications. - content::NotificationRegistrar registrar_; - - // The list of modules found. Even when |modules_have_been_enumerated_event_| - // is signaled, this may still be NULL. - scoped_ptr<base::ListValue> module_list_; - - // This event is signaled once module enumeration has been attempted. If - // during construction, EnumerateModulesModel can supply a non-empty list of - // modules, module enumeration has clearly already happened, so the event will - // be signaled immediately; otherwise, when EnumerateLoadedModulesIfNeeded() - // is called, it will ask the model to scan the modules, and then signal the - // event once this process is completed. - extensions::OneShotEvent modules_have_been_enumerated_event_; - - // This event is signaled once the TemplateURLService has loaded. If the - // TemplateURLService was already loaded prior to the creation of this class, - // the event will be signaled during construction. - extensions::OneShotEvent template_url_service_ready_event_; - - // This event is signaled once brandcoded default settings have been fetched, - // or once it has been established that this is not a branded build. - extensions::OneShotEvent brandcoded_defaults_fetched_event_; - - DISALLOW_COPY_AND_ASSIGN(AutomaticProfileResetterDelegateImpl); -}; - -#endif // CHROME_BROWSER_PROFILE_RESETTER_AUTOMATIC_PROFILE_RESETTER_DELEGATE_H_ diff --git a/chrome/browser/profile_resetter/automatic_profile_resetter_delegate_unittest.cc b/chrome/browser/profile_resetter/automatic_profile_resetter_delegate_unittest.cc deleted file mode 100644 index 9214100..0000000 --- a/chrome/browser/profile_resetter/automatic_profile_resetter_delegate_unittest.cc +++ /dev/null @@ -1,608 +0,0 @@ -// Copyright 2013 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 "chrome/browser/profile_resetter/automatic_profile_resetter_delegate.h" - -#include <algorithm> - -#include "base/bind.h" -#include "base/bind_helpers.h" -#include "base/memory/ref_counted.h" -#include "base/memory/scoped_ptr.h" -#include "base/prefs/pref_service.h" -#include "base/run_loop.h" -#include "base/strings/string_number_conversions.h" -#include "base/strings/string_split.h" -#include "base/strings/string_util.h" -#include "base/strings/utf_string_conversions.h" -#include "base/test/values_test_util.h" -#include "base/values.h" -#include "chrome/app/chrome_command_ids.h" -#include "chrome/browser/chrome_notification_types.h" -#include "chrome/browser/extensions/extension_service.h" -#include "chrome/browser/extensions/extension_service_test_base.h" -#include "chrome/browser/google/google_brand.h" -#include "chrome/browser/profile_resetter/brandcoded_default_settings.h" -#include "chrome/browser/profile_resetter/profile_reset_global_error.h" -#include "chrome/browser/search_engines/template_url_service_factory.h" -#include "chrome/browser/search_engines/template_url_service_factory_test_util.h" -#include "chrome/browser/ui/global_error/global_error.h" -#include "chrome/browser/ui/global_error/global_error_service.h" -#include "chrome/browser/ui/global_error/global_error_service_factory.h" -#include "chrome/common/pref_names.h" -#include "chrome/test/base/testing_profile.h" -#include "components/search_engines/default_search_manager.h" -#include "components/search_engines/template_url_prepopulate_data.h" -#include "components/search_engines/template_url_service.h" -#include "components/syncable_prefs/testing_pref_service_syncable.h" -#include "content/public/browser/notification_service.h" -#include "net/http/http_response_headers.h" -#include "net/url_request/test_url_fetcher_factory.h" -#include "testing/gmock/include/gmock/gmock.h" -#include "testing/gtest/include/gtest/gtest.h" - -#if defined(OS_WIN) -#include "chrome/browser/enumerate_modules_model_win.h" -#endif - -namespace { - -const char kTestBrandcode[] = "FOOBAR"; - -const char kTestHomepage[] = "http://google.com"; -const char kTestBrandedHomepage[] = "http://example.com"; - -const ProfileResetter::ResettableFlags kResettableAspectsForTest = - ProfileResetter::ALL & ~ProfileResetter::COOKIES_AND_SITE_DATA; - -// Helpers ------------------------------------------------------------------- - -// A testing version of the AutomaticProfileResetterDelegate that differs from -// the real one only in that it has its feedback reporting mocked out, and it -// will not reset COOKIES_AND_SITE_DATA, due to difficulties to set up some -// required URLRequestContexts in unit tests. -class AutomaticProfileResetterDelegateUnderTest - : public AutomaticProfileResetterDelegateImpl { - public: - explicit AutomaticProfileResetterDelegateUnderTest(Profile* profile) - : AutomaticProfileResetterDelegateImpl( - profile, kResettableAspectsForTest) {} - virtual ~AutomaticProfileResetterDelegateUnderTest() {} - - MOCK_CONST_METHOD1(SendFeedback, void(const std::string&)); - - private: - DISALLOW_COPY_AND_ASSIGN(AutomaticProfileResetterDelegateUnderTest); -}; - -class MockCallbackTarget { - public: - MockCallbackTarget() {} - ~MockCallbackTarget() {} - - MOCK_CONST_METHOD0(Run, void(void)); - - base::Closure CreateClosure() { - return base::Bind(&MockCallbackTarget::Run, base::Unretained(this)); - } - - private: - DISALLOW_COPY_AND_ASSIGN(MockCallbackTarget); -}; - -// Returns the details of the default search provider from |prefs| in a format -// suitable for usage as |expected_details| in ExpectDetailsMatch(). -const base::DictionaryValue* GetDefaultSearchProviderDetailsFromPrefs( - const PrefService* prefs) { - return prefs->GetDictionary( - DefaultSearchManager::kDefaultSearchProviderDataPrefName); -} - -// Verifies that the |details| of a search engine as provided by the delegate -// are correct in comparison to the |expected_details| coming from the Prefs. -void ExpectDetailsMatch(const base::DictionaryValue& expected_details, - const base::DictionaryValue& details) { - for (base::DictionaryValue::Iterator it(expected_details); !it.IsAtEnd(); - it.Advance()) { - SCOPED_TRACE(testing::Message("Key: ") << it.key()); - if (it.key() == "enabled" || it.key() == "synced_guid") { - // These attributes should not be present. - EXPECT_FALSE(details.HasKey(it.key())); - continue; - } - const base::Value* expected_value = &it.value(); - const base::Value* actual_value = NULL; - ASSERT_TRUE(details.Get(it.key(), &actual_value)); - - // Ignore ID as it is dynamically assigned by the TemplateURLService. - // last_modified may get updated during a run, so ignore value differences. - if (it.key() != "id" && it.key() != "last_modified") { - // Everything else is the same format. - EXPECT_TRUE(actual_value->Equals(expected_value)) - << "Expected: " << *expected_value << ". Actual: " << *actual_value; - } - } -} - -// If |simulate_failure| is false, then replies to the pending request on -// |fetcher| with a brandcoded config that only specifies a home page URL. -// If |simulate_failure| is true, replies with 404. -void ServicePendingBrancodedConfigFetch(net::TestURLFetcher* fetcher, - bool simulate_failure) { - const char kBrandcodedXmlSettings[] = - "<?xml version=\"1.0\" encoding=\"UTF-8\"?>" - "<response protocol=\"3.0\" server=\"prod\">" - "<app appid=\"{8A69D345-D564-463C-AFF1-A69D9E530F96}\" status=\"ok\">" - "<data index=\"skipfirstrunui-importsearch-defaultbrowser\" " - "name=\"install\" status=\"ok\">" - "{\"homepage\" : \"$1\"}" - "</data>" - "</app>" - "</response>"; - - fetcher->set_response_code(simulate_failure ? 404 : 200); - scoped_refptr<net::HttpResponseHeaders> response_headers( - new net::HttpResponseHeaders("")); - response_headers->AddHeader("Content-Type: text/xml"); - fetcher->set_response_headers(response_headers); - if (!simulate_failure) { - std::string response(kBrandcodedXmlSettings); - size_t placeholder_index = response.find("$1"); - ASSERT_NE(std::string::npos, placeholder_index); - response.replace(placeholder_index, 2, kTestBrandedHomepage); - fetcher->SetResponseString(response); - } - fetcher->delegate()->OnURLFetchComplete(fetcher); -} - - -// Test fixture -------------------------------------------------------------- - -// ExtensionServiceTestBase sets up a TestingProfile with the ExtensionService, -// we then add the TemplateURLService, so the ProfileResetter can be exercised. -class AutomaticProfileResetterDelegateTest - : public extensions::ExtensionServiceTestBase { - protected: - AutomaticProfileResetterDelegateTest() {} - ~AutomaticProfileResetterDelegateTest() override {} - - void SetUp() override { - extensions::ExtensionServiceTestBase::SetUp(); - ExtensionServiceInitParams params = CreateDefaultInitParams(); - params.pref_file.clear(); // Prescribes a TestingPrefService to be created. - InitializeExtensionService(params); - template_url_service_test_util_.reset( - new TemplateURLServiceFactoryTestUtil(profile_.get())); - resetter_delegate_.reset( - new AutomaticProfileResetterDelegateUnderTest(profile())); - } - - void TearDown() override { - resetter_delegate_.reset(); - template_url_service_test_util_.reset(); - extensions::ExtensionServiceTestBase::TearDown(); - } - - scoped_ptr<TemplateURL> CreateTestTemplateURL() { - TemplateURLData data; - - data.SetURL("http://example.com/search?q={searchTerms}"); - data.suggestions_url = "http://example.com/suggest?q={searchTerms}"; - data.instant_url = "http://example.com/instant?q={searchTerms}"; - data.image_url = "http://example.com/image?q={searchTerms}"; - data.search_url_post_params = "search-post-params"; - data.suggestions_url_post_params = "suggest-post-params"; - data.instant_url_post_params = "instant-post-params"; - data.image_url_post_params = "image-post-params"; - - data.favicon_url = GURL("http://example.com/favicon.ico"); - data.new_tab_url = "http://example.com/newtab.html"; - data.alternate_urls.push_back("http://example.com/s?q={searchTerms}"); - - data.short_name = base::ASCIIToUTF16("name"); - data.SetKeyword(base::ASCIIToUTF16("keyword")); - data.search_terms_replacement_key = "search-terms-replacment-key"; - data.prepopulate_id = 42; - data.input_encodings.push_back("UTF-8"); - data.safe_for_autoreplace = true; - - return scoped_ptr<TemplateURL>(new TemplateURL(data)); - } - - void ExpectNoPendingBrandcodedConfigFetch() { - EXPECT_FALSE(test_url_fetcher_factory_.GetFetcherByID(0)); - } - - void ExpectAndServicePendingBrandcodedConfigFetch(bool simulate_failure) { - net::TestURLFetcher* fetcher = test_url_fetcher_factory_.GetFetcherByID(0); - ASSERT_TRUE(fetcher); - EXPECT_THAT(fetcher->upload_data(), - testing::HasSubstr(kTestBrandcode)); - ServicePendingBrancodedConfigFetch(fetcher, simulate_failure); - } - - void ExpectResetPromptState(bool active) { - GlobalErrorService* global_error_service = - GlobalErrorServiceFactory::GetForProfile(profile()); - GlobalError* global_error = global_error_service-> - GetGlobalErrorByMenuItemCommandID(IDC_SHOW_SETTINGS_RESET_BUBBLE); - EXPECT_EQ(active, !!global_error); - } - - AutomaticProfileResetterDelegateUnderTest* resetter_delegate() { - return resetter_delegate_.get(); - } - - TemplateURLServiceFactoryTestUtil* template_url_service_test_util() { - return template_url_service_test_util_.get(); - } - - private: - scoped_ptr<TemplateURLServiceFactoryTestUtil> template_url_service_test_util_; - net::TestURLFetcherFactory test_url_fetcher_factory_; - scoped_ptr<AutomaticProfileResetterDelegateUnderTest> resetter_delegate_; - - DISALLOW_COPY_AND_ASSIGN(AutomaticProfileResetterDelegateTest); -}; - - -// Tests --------------------------------------------------------------------- - -TEST_F(AutomaticProfileResetterDelegateTest, - TriggerAndWaitOnModuleEnumeration) { - // Expect ready_callback to be called just after the modules have been - // enumerated. Fail if it is not called. Note: as the EnumerateModulesModel is - // a global singleton, the callback might be invoked immediately if another - // test-case (e.g. the one below) has already performed module enumeration. - testing::StrictMock<MockCallbackTarget> mock_target; - EXPECT_CALL(mock_target, Run()); - resetter_delegate()->RequestCallbackWhenLoadedModulesAreEnumerated( - mock_target.CreateClosure()); - resetter_delegate()->EnumerateLoadedModulesIfNeeded(); - base::RunLoop().RunUntilIdle(); - - testing::Mock::VerifyAndClearExpectations(&mock_target); - - // Expect ready_callback to be posted immediately when the modules have - // already been enumerated. - EXPECT_CALL(mock_target, Run()); - resetter_delegate()->RequestCallbackWhenLoadedModulesAreEnumerated( - mock_target.CreateClosure()); - base::RunLoop().RunUntilIdle(); - -#if defined(OS_WIN) - testing::Mock::VerifyAndClearExpectations(&mock_target); - - // Expect ready_callback to be posted immediately even when the modules had - // already been enumerated when the delegate was constructed. - scoped_ptr<AutomaticProfileResetterDelegate> late_resetter_delegate( - new AutomaticProfileResetterDelegateImpl(profile(), - ProfileResetter::ALL)); - - EXPECT_CALL(mock_target, Run()); - late_resetter_delegate->RequestCallbackWhenLoadedModulesAreEnumerated( - mock_target.CreateClosure()); - base::RunLoop().RunUntilIdle(); -#endif -} - -TEST_F(AutomaticProfileResetterDelegateTest, GetLoadedModuleNameDigests) { - resetter_delegate()->EnumerateLoadedModulesIfNeeded(); - base::RunLoop().RunUntilIdle(); - scoped_ptr<base::ListValue> module_name_digests( - resetter_delegate()->GetLoadedModuleNameDigests()); - - // Just verify that each element looks like an MD5 hash in hexadecimal, and - // also that we have at least one element on Win. - ASSERT_TRUE(module_name_digests); - for (base::ListValue::const_iterator it = module_name_digests->begin(); - it != module_name_digests->end(); ++it) { - std::string digest_hex; - std::vector<uint8> digest_raw; - - ASSERT_TRUE((*it)->GetAsString(&digest_hex)); - ASSERT_TRUE(base::HexStringToBytes(digest_hex, &digest_raw)); - EXPECT_EQ(16u, digest_raw.size()); - } -#if defined(OS_WIN) - EXPECT_LE(1u, module_name_digests->GetSize()); -#endif -} - -TEST_F(AutomaticProfileResetterDelegateTest, LoadAndWaitOnTemplateURLService) { - // Expect ready_callback to be called just after the template URL service gets - // initialized. Fail if it is not called, or called too early. - testing::StrictMock<MockCallbackTarget> mock_target; - resetter_delegate()->RequestCallbackWhenTemplateURLServiceIsLoaded( - mock_target.CreateClosure()); - base::RunLoop().RunUntilIdle(); - - EXPECT_CALL(mock_target, Run()); - resetter_delegate()->LoadTemplateURLServiceIfNeeded(); - base::RunLoop().RunUntilIdle(); - - testing::Mock::VerifyAndClearExpectations(&mock_target); - - // Expect ready_callback to be posted immediately when the template URL - // service is already initialized. - EXPECT_CALL(mock_target, Run()); - resetter_delegate()->RequestCallbackWhenTemplateURLServiceIsLoaded( - mock_target.CreateClosure()); - base::RunLoop().RunUntilIdle(); - - testing::Mock::VerifyAndClearExpectations(&mock_target); - - // Expect ready_callback to be posted immediately even when the template URL - // service had already been initialized when the delegate was constructed. - scoped_ptr<AutomaticProfileResetterDelegate> late_resetter_delegate( - new AutomaticProfileResetterDelegateImpl(profile(), - ProfileResetter::ALL)); - - EXPECT_CALL(mock_target, Run()); - late_resetter_delegate->RequestCallbackWhenTemplateURLServiceIsLoaded( - mock_target.CreateClosure()); - base::RunLoop().RunUntilIdle(); -} - -TEST_F(AutomaticProfileResetterDelegateTest, - DefaultSearchProviderDataWhenNotManaged) { - TemplateURLService* template_url_service = - TemplateURLServiceFactory::GetForProfile(profile()); - template_url_service_test_util()->VerifyLoad(); - - // Check that the "managed state" and the details returned by the delegate are - // correct. We verify the details against the data stored by - // TemplateURLService into Prefs. - scoped_ptr<TemplateURL> owned_custom_dsp(CreateTestTemplateURL()); - TemplateURL* custom_dsp = owned_custom_dsp.get(); - template_url_service->Add(owned_custom_dsp.release()); - template_url_service->SetUserSelectedDefaultSearchProvider(custom_dsp); - - PrefService* prefs = profile()->GetPrefs(); - ASSERT_TRUE(prefs); - scoped_ptr<base::DictionaryValue> dsp_details( - resetter_delegate()->GetDefaultSearchProviderDetails()); - const base::DictionaryValue* expected_dsp_details = - GetDefaultSearchProviderDetailsFromPrefs(prefs); - - ExpectDetailsMatch(*expected_dsp_details, *dsp_details); - EXPECT_FALSE(resetter_delegate()->IsDefaultSearchProviderManaged()); -} - -TEST_F(AutomaticProfileResetterDelegateTest, - DefaultSearchProviderDataWhenManaged) { - const char kTestSearchURL[] = "http://example.com/search?q={searchTerms}"; - const char kTestName[] = "name"; - const char kTestKeyword[] = "keyword"; - - template_url_service_test_util()->VerifyLoad(); - - EXPECT_FALSE(resetter_delegate()->IsDefaultSearchProviderManaged()); - - // Set managed preferences to emulate a default search provider set by policy. - template_url_service_test_util()->SetManagedDefaultSearchPreferences( - true, kTestName, kTestKeyword, kTestSearchURL, std::string(), - std::string(), std::string(), std::string(), std::string()); - - EXPECT_TRUE(resetter_delegate()->IsDefaultSearchProviderManaged()); - scoped_ptr<base::DictionaryValue> dsp_details( - resetter_delegate()->GetDefaultSearchProviderDetails()); - // Checking that all details are correct is already done by the above test. - // Just make sure details are reported about the correct engine. - base::ExpectDictStringValue(kTestSearchURL, *dsp_details, "search_url"); - - // Set managed preferences to emulate that having a default search provider is - // disabled by policy. - template_url_service_test_util()->RemoveManagedDefaultSearchPreferences(); - template_url_service_test_util()->SetManagedDefaultSearchPreferences( - false, std::string(), std::string(), std::string(), std::string(), - std::string(), std::string(), std::string(), std::string()); - - dsp_details = resetter_delegate()->GetDefaultSearchProviderDetails(); - EXPECT_TRUE(resetter_delegate()->IsDefaultSearchProviderManaged()); - EXPECT_TRUE(dsp_details->empty()); -} - -TEST_F(AutomaticProfileResetterDelegateTest, - GetPrepopulatedSearchProvidersDetails) { - TemplateURLService* template_url_service = - TemplateURLServiceFactory::GetForProfile(profile()); - template_url_service_test_util()->VerifyLoad(); - - scoped_ptr<base::ListValue> search_engines_details( - resetter_delegate()->GetPrepopulatedSearchProvidersDetails()); - - // Do the same kind of verification as for GetDefaultSearchEngineDetails: - // subsequently set each pre-populated engine as the default, so we can verify - // that the details returned by the delegate about one particular engine are - // correct in comparison to what has been stored to the Prefs. - std::vector<TemplateURL*> prepopulated_engines = - template_url_service->GetTemplateURLs(); - - ASSERT_EQ(prepopulated_engines.size(), search_engines_details->GetSize()); - - for (size_t i = 0; i < search_engines_details->GetSize(); ++i) { - const base::DictionaryValue* details = NULL; - ASSERT_TRUE(search_engines_details->GetDictionary(i, &details)); - - std::string keyword; - ASSERT_TRUE(details->GetString("keyword", &keyword)); - TemplateURL* search_engine = - template_url_service->GetTemplateURLForKeyword( - base::ASCIIToUTF16(keyword)); - ASSERT_TRUE(search_engine); - template_url_service->SetUserSelectedDefaultSearchProvider( - prepopulated_engines[i]); - - PrefService* prefs = profile()->GetPrefs(); - ASSERT_TRUE(prefs); - const base::DictionaryValue* expected_dsp_details = - GetDefaultSearchProviderDetailsFromPrefs(prefs); - ExpectDetailsMatch(*expected_dsp_details, *details); - } -} - -TEST_F(AutomaticProfileResetterDelegateTest, - FetchAndWaitOnDefaultSettingsVanilla) { - google_brand::BrandForTesting scoped_brand_for_testing((std::string())); - - // Expect ready_callback to be called just after empty brandcoded settings - // are loaded, given this is a vanilla build. Fail if it is not called, or - // called too early. - testing::StrictMock<MockCallbackTarget> mock_target; - resetter_delegate()->RequestCallbackWhenBrandcodedDefaultsAreFetched( - mock_target.CreateClosure()); - base::RunLoop().RunUntilIdle(); - EXPECT_FALSE(resetter_delegate()->brandcoded_defaults()); - - EXPECT_CALL(mock_target, Run()); - resetter_delegate()->FetchBrandcodedDefaultSettingsIfNeeded(); - base::RunLoop().RunUntilIdle(); - ExpectNoPendingBrandcodedConfigFetch(); - - testing::Mock::VerifyAndClearExpectations(&mock_target); - EXPECT_TRUE(resetter_delegate()->brandcoded_defaults()); - - // Expect ready_callback to be posted immediately when the brandcoded settings - // have already been loaded. - EXPECT_CALL(mock_target, Run()); - resetter_delegate()->RequestCallbackWhenBrandcodedDefaultsAreFetched( - mock_target.CreateClosure()); - base::RunLoop().RunUntilIdle(); - - // No test for a new instance of AutomaticProfileResetterDelegate. That will - // need to fetch the brandcoded settings again. -} - -TEST_F(AutomaticProfileResetterDelegateTest, - FetchAndWaitOnDefaultSettingsBranded) { - google_brand::BrandForTesting scoped_brand_for_testing(kTestBrandcode); - - // Expect ready_callback to be called just after the brandcoded settings are - // downloaded. Fail if it is not called, or called too early. - testing::StrictMock<MockCallbackTarget> mock_target; - resetter_delegate()->RequestCallbackWhenBrandcodedDefaultsAreFetched( - mock_target.CreateClosure()); - base::RunLoop().RunUntilIdle(); - EXPECT_FALSE(resetter_delegate()->brandcoded_defaults()); - - EXPECT_CALL(mock_target, Run()); - resetter_delegate()->FetchBrandcodedDefaultSettingsIfNeeded(); - ExpectAndServicePendingBrandcodedConfigFetch(false /*simulate_failure*/); - base::RunLoop().RunUntilIdle(); - - testing::Mock::VerifyAndClearExpectations(&mock_target); - const BrandcodedDefaultSettings* brandcoded_defaults = - resetter_delegate()->brandcoded_defaults(); - ASSERT_TRUE(brandcoded_defaults); - std::string homepage_url; - EXPECT_TRUE(brandcoded_defaults->GetHomepage(&homepage_url)); - EXPECT_EQ(kTestBrandedHomepage, homepage_url); - - // Expect ready_callback to be posted immediately when the brandcoded settings - // have already been downloaded. - EXPECT_CALL(mock_target, Run()); - resetter_delegate()->RequestCallbackWhenBrandcodedDefaultsAreFetched( - mock_target.CreateClosure()); - base::RunLoop().RunUntilIdle(); -} - -TEST_F(AutomaticProfileResetterDelegateTest, - FetchAndWaitOnDefaultSettingsBrandedFailure) { - google_brand::BrandForTesting scoped_brand_for_testing(kTestBrandcode); - - // Expect ready_callback to be called just after the brandcoded settings have - // failed to download. Fail if it is not called, or called too early. - testing::StrictMock<MockCallbackTarget> mock_target; - resetter_delegate()->RequestCallbackWhenBrandcodedDefaultsAreFetched( - mock_target.CreateClosure()); - base::RunLoop().RunUntilIdle(); - - EXPECT_CALL(mock_target, Run()); - resetter_delegate()->FetchBrandcodedDefaultSettingsIfNeeded(); - ExpectAndServicePendingBrandcodedConfigFetch(true /*simulate_failure*/); - base::RunLoop().RunUntilIdle(); - - testing::Mock::VerifyAndClearExpectations(&mock_target); - EXPECT_TRUE(resetter_delegate()->brandcoded_defaults()); - - // Expect ready_callback to be posted immediately when the brandcoded settings - // have already been attempted to be downloaded, but failed. - EXPECT_CALL(mock_target, Run()); - resetter_delegate()->RequestCallbackWhenBrandcodedDefaultsAreFetched( - mock_target.CreateClosure()); - base::RunLoop().RunUntilIdle(); -} - -TEST_F(AutomaticProfileResetterDelegateTest, TriggerReset) { - google_brand::BrandForTesting scoped_brand_for_testing(kTestBrandcode); - - PrefService* prefs = profile()->GetPrefs(); - DCHECK(prefs); - prefs->SetString(prefs::kHomePage, kTestHomepage); - - testing::StrictMock<MockCallbackTarget> mock_target; - EXPECT_CALL(mock_target, Run()); - EXPECT_CALL(*resetter_delegate(), SendFeedback(testing::_)).Times(0); - resetter_delegate()->TriggerProfileSettingsReset( - false /*send_feedback*/, mock_target.CreateClosure()); - ExpectAndServicePendingBrandcodedConfigFetch(false /*simulate_failure*/); - base::RunLoop().RunUntilIdle(); - - EXPECT_EQ(kTestBrandedHomepage, prefs->GetString(prefs::kHomePage)); -} - -TEST_F(AutomaticProfileResetterDelegateTest, - TriggerResetWithDefaultSettingsAlreadyLoaded) { - google_brand::BrandForTesting scoped_brand_for_testing(kTestBrandcode); - - PrefService* prefs = profile()->GetPrefs(); - DCHECK(prefs); - prefs->SetString(prefs::kHomePage, kTestHomepage); - - resetter_delegate()->FetchBrandcodedDefaultSettingsIfNeeded(); - ExpectAndServicePendingBrandcodedConfigFetch(false /*simulate_failure*/); - base::RunLoop().RunUntilIdle(); - - testing::StrictMock<MockCallbackTarget> mock_target; - EXPECT_CALL(mock_target, Run()); - EXPECT_CALL(*resetter_delegate(), SendFeedback(testing::_)).Times(0); - resetter_delegate()->TriggerProfileSettingsReset( - false /*send_feedback*/, mock_target.CreateClosure()); - base::RunLoop().RunUntilIdle(); - - EXPECT_EQ(kTestBrandedHomepage, prefs->GetString(prefs::kHomePage)); -} - -TEST_F(AutomaticProfileResetterDelegateTest, - TriggerResetAndSendFeedback) { - google_brand::BrandForTesting scoped_brand_for_testing(kTestBrandcode); - - PrefService* prefs = profile()->GetPrefs(); - DCHECK(prefs); - prefs->SetString(prefs::kHomePage, kTestHomepage); - - testing::StrictMock<MockCallbackTarget> mock_target; - EXPECT_CALL(mock_target, Run()); - EXPECT_CALL(*resetter_delegate(), - SendFeedback(testing::HasSubstr(kTestHomepage))); - - resetter_delegate()->TriggerProfileSettingsReset( - true /*send_feedback*/, mock_target.CreateClosure()); - ExpectAndServicePendingBrandcodedConfigFetch(false /*simulate_failure*/); - base::RunLoop().RunUntilIdle(); -} - -TEST_F(AutomaticProfileResetterDelegateTest, ShowAndDismissPrompt) { - resetter_delegate()->TriggerPrompt(); - if (ProfileResetGlobalError::IsSupportedOnPlatform()) - ExpectResetPromptState(true /*active*/); - else - ExpectResetPromptState(false /*active*/); - resetter_delegate()->DismissPrompt(); - ExpectResetPromptState(false /*active*/); - resetter_delegate()->DismissPrompt(); -} - -} // namespace diff --git a/chrome/browser/profile_resetter/automatic_profile_resetter_factory.cc b/chrome/browser/profile_resetter/automatic_profile_resetter_factory.cc deleted file mode 100644 index f025ce4..0000000 --- a/chrome/browser/profile_resetter/automatic_profile_resetter_factory.cc +++ /dev/null @@ -1,70 +0,0 @@ -// Copyright 2013 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 "chrome/browser/profile_resetter/automatic_profile_resetter_factory.h" - -#include "base/memory/singleton.h" -#include "base/prefs/pref_registry_simple.h" -#include "chrome/browser/profile_resetter/automatic_profile_resetter.h" -#include "chrome/browser/profiles/profile.h" -#include "chrome/browser/search_engines/template_url_service_factory.h" -#include "chrome/browser/ui/global_error/global_error_service_factory.h" -#include "chrome/common/pref_names.h" -#include "components/keyed_service/content/browser_context_dependency_manager.h" -#include "components/pref_registry/pref_registry_syncable.h" -#include "content/public/browser/browser_context.h" - -// static -AutomaticProfileResetter* AutomaticProfileResetterFactory::GetForBrowserContext( - content::BrowserContext* context) { - return static_cast<AutomaticProfileResetter*>( - GetInstance()->GetServiceForBrowserContext(context, true)); -} - -// static -AutomaticProfileResetterFactory* -AutomaticProfileResetterFactory::GetInstance() { - return base::Singleton<AutomaticProfileResetterFactory>::get(); -} - -// static -void AutomaticProfileResetterFactory::RegisterPrefs( - PrefRegistrySimple* registry) { - registry->RegisterDictionaryPref( - prefs::kProfileResetPromptMementosInLocalState); -} - -AutomaticProfileResetterFactory::AutomaticProfileResetterFactory() - : BrowserContextKeyedServiceFactory( - "AutomaticProfileResetter", - BrowserContextDependencyManager::GetInstance()) { - DependsOn(TemplateURLServiceFactory::GetInstance()); - DependsOn(GlobalErrorServiceFactory::GetInstance()); -} - -AutomaticProfileResetterFactory::~AutomaticProfileResetterFactory() {} - -KeyedService* AutomaticProfileResetterFactory::BuildServiceInstanceFor( - content::BrowserContext* context) const { - Profile* profile = Profile::FromBrowserContext(context); - AutomaticProfileResetter* service = new AutomaticProfileResetter(profile); - service->Initialize(); - service->Activate(); - return service; -} - -void AutomaticProfileResetterFactory::RegisterProfilePrefs( - user_prefs::PrefRegistrySyncable* registry) { - registry->RegisterStringPref(prefs::kProfileResetPromptMementoInProfilePrefs, - ""); -} - -bool AutomaticProfileResetterFactory:: - ServiceIsCreatedWithBrowserContext() const { - return true; -} - -bool AutomaticProfileResetterFactory::ServiceIsNULLWhileTesting() const { - return true; -} diff --git a/chrome/browser/profile_resetter/automatic_profile_resetter_factory.h b/chrome/browser/profile_resetter/automatic_profile_resetter_factory.h deleted file mode 100644 index bbf8012..0000000 --- a/chrome/browser/profile_resetter/automatic_profile_resetter_factory.h +++ /dev/null @@ -1,57 +0,0 @@ -// Copyright 2013 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 CHROME_BROWSER_PROFILE_RESETTER_AUTOMATIC_PROFILE_RESETTER_FACTORY_H_ -#define CHROME_BROWSER_PROFILE_RESETTER_AUTOMATIC_PROFILE_RESETTER_FACTORY_H_ - -#include "base/basictypes.h" -#include "components/keyed_service/content/browser_context_keyed_service_factory.h" - -namespace base { -template <typename T> -struct DefaultSingletonTraits; -} // namespace base - -class PrefRegistrySimple; - -namespace content { -class BrowserContext; -} - -namespace user_prefs { -class PrefRegistrySyncable; -} - -class AutomaticProfileResetter; - -class AutomaticProfileResetterFactory - : public BrowserContextKeyedServiceFactory { - public: - static AutomaticProfileResetter* GetForBrowserContext( - content::BrowserContext* context); - static AutomaticProfileResetterFactory* GetInstance(); - - // Registers Local State preferences. - static void RegisterPrefs(PrefRegistrySimple* registry); - - private: - friend struct base::DefaultSingletonTraits<AutomaticProfileResetterFactory>; - - AutomaticProfileResetterFactory(); - ~AutomaticProfileResetterFactory() override; - - // BrowserContextKeyedServiceFactory: - KeyedService* BuildServiceInstanceFor( - content::BrowserContext* context) const override; - - // BrowserContextKeyedBaseFactory: - void RegisterProfilePrefs( - user_prefs::PrefRegistrySyncable* registry) override; - bool ServiceIsCreatedWithBrowserContext() const override; - bool ServiceIsNULLWhileTesting() const override; - - DISALLOW_COPY_AND_ASSIGN(AutomaticProfileResetterFactory); -}; - -#endif // CHROME_BROWSER_PROFILE_RESETTER_AUTOMATIC_PROFILE_RESETTER_FACTORY_H_ diff --git a/chrome/browser/profile_resetter/automatic_profile_resetter_mementos.cc b/chrome/browser/profile_resetter/automatic_profile_resetter_mementos.cc deleted file mode 100644 index b4e9446..0000000 --- a/chrome/browser/profile_resetter/automatic_profile_resetter_mementos.cc +++ /dev/null @@ -1,129 +0,0 @@ -// Copyright 2013 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 "chrome/browser/profile_resetter/automatic_profile_resetter_mementos.h" - -#include "base/bind.h" -#include "base/bind_helpers.h" -#include "base/files/file_path.h" -#include "base/files/file_util.h" -#include "base/logging.h" -#include "base/prefs/pref_service.h" -#include "base/prefs/scoped_user_pref_update.h" -#include "base/values.h" -#include "chrome/browser/browser_process.h" -#include "chrome/browser/profiles/profile.h" -#include "chrome/common/chrome_constants.h" -#include "chrome/common/pref_names.h" -#include "content/public/browser/browser_thread.h" - -using base::DictionaryValue; - - -// AutomaticProfileResetter::PreferenceHostedPromptMemento ------------------- - -PreferenceHostedPromptMemento::PreferenceHostedPromptMemento(Profile* profile) - : profile_(profile) {} - -PreferenceHostedPromptMemento::~PreferenceHostedPromptMemento() {} - -std::string PreferenceHostedPromptMemento::ReadValue() const { - PrefService* prefs = profile_->GetPrefs(); - DCHECK(prefs); - return prefs->GetString(prefs::kProfileResetPromptMementoInProfilePrefs); -} - -void PreferenceHostedPromptMemento::StoreValue(const std::string& value) { - PrefService* prefs = profile_->GetPrefs(); - DCHECK(prefs); - prefs->SetString(prefs::kProfileResetPromptMementoInProfilePrefs, value); -} - - -// AutomaticProfileResetter::LocalStateHostedPromptMemento ------------------- - -LocalStateHostedPromptMemento::LocalStateHostedPromptMemento(Profile* profile) - : profile_(profile) {} - -LocalStateHostedPromptMemento::~LocalStateHostedPromptMemento() {} - -std::string LocalStateHostedPromptMemento::ReadValue() const { - PrefService* local_state = g_browser_process->local_state(); - DCHECK(local_state); - - const base::DictionaryValue* prompt_shown_dict = local_state->GetDictionary( - prefs::kProfileResetPromptMementosInLocalState); - std::string profile_key = GetProfileKey(); - if (!prompt_shown_dict || profile_key.empty()) { - NOTREACHED(); - return std::string(); - } - std::string value; - return prompt_shown_dict->GetStringWithoutPathExpansion(profile_key, &value) ? - value : std::string(); -} - -void LocalStateHostedPromptMemento::StoreValue(const std::string& value) { - PrefService* local_state = g_browser_process->local_state(); - DCHECK(local_state); - - DictionaryPrefUpdate prompt_shown_dict_update( - local_state, prefs::kProfileResetPromptMementosInLocalState); - std::string profile_key = GetProfileKey(); - if (profile_key.empty()) { - NOTREACHED(); - return; - } - prompt_shown_dict_update.Get()->SetStringWithoutPathExpansion(profile_key, - value); -} - -std::string LocalStateHostedPromptMemento::GetProfileKey() const { - return profile_->GetPath().BaseName().MaybeAsASCII(); -} - - -// AutomaticProfileResetter::FileHostedPromptMemento ------------------------- - -FileHostedPromptMemento::FileHostedPromptMemento(Profile* profile) - : profile_(profile) {} - -FileHostedPromptMemento::~FileHostedPromptMemento() {} - -void FileHostedPromptMemento::ReadValue( - const ReadValueCallback& callback) const { - base::FilePath path = GetMementoFilePath(); - content::BrowserThread::PostTaskAndReplyWithResult( - content::BrowserThread::FILE, - FROM_HERE, - base::Bind(&ReadValueOnFileThread, path), - callback); -} - -void FileHostedPromptMemento::StoreValue(const std::string& value) { - base::FilePath path = GetMementoFilePath(); - content::BrowserThread::PostTask( - content::BrowserThread::FILE, - FROM_HERE, - base::Bind(&StoreValueOnFileThread, path, value)); -} - -std::string FileHostedPromptMemento::ReadValueOnFileThread( - const base::FilePath& memento_file_path) { - std::string value; - base::ReadFileToString(memento_file_path, &value); - return value; -} - -void FileHostedPromptMemento::StoreValueOnFileThread( - const base::FilePath& memento_file_path, - const std::string& value) { - int retval = - base::WriteFile(memento_file_path, value.c_str(), value.size()); - DCHECK_EQ(retval, (int)value.size()); -} - -base::FilePath FileHostedPromptMemento::GetMementoFilePath() const { - return profile_->GetPath().Append(chrome::kResetPromptMementoFilename); -} diff --git a/chrome/browser/profile_resetter/automatic_profile_resetter_mementos.h b/chrome/browser/profile_resetter/automatic_profile_resetter_mementos.h deleted file mode 100644 index 025ffb2..0000000 --- a/chrome/browser/profile_resetter/automatic_profile_resetter_mementos.h +++ /dev/null @@ -1,101 +0,0 @@ -// Copyright 2013 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. - -// The classes in this file are alternative implementations of the concept of a -// "prompt memento", a token of some kind that gets stored when we show the -// one-time profile reset prompt, and which then serves as a reminder that we -// should not show the prompt again. -// -// In an ideal world, a single implementation would suffice, however, we expect -// that third party software might accidentally interfere with some of these -// methods. We need this redundancy because we want to make absolutely sure that -// we do not annoy the user with the prompt multiple times. - -#ifndef CHROME_BROWSER_PROFILE_RESETTER_AUTOMATIC_PROFILE_RESETTER_MEMENTOS_H_ -#define CHROME_BROWSER_PROFILE_RESETTER_AUTOMATIC_PROFILE_RESETTER_MEMENTOS_H_ - -#include <string> - -#include "base/basictypes.h" -#include "base/callback.h" - -namespace base { -class FilePath; -} - -class Profile; - -// This class is a wrapper around the user preference that gets stored when we -// show the one-time profile reset prompt, and which is kept as a reminder that -// we should not show the prompt again. -class PreferenceHostedPromptMemento { - public: - explicit PreferenceHostedPromptMemento(Profile* profile); - ~PreferenceHostedPromptMemento(); - - std::string ReadValue() const; - void StoreValue(const std::string& value); - - private: - Profile* profile_; - - DISALLOW_COPY_AND_ASSIGN(PreferenceHostedPromptMemento); -}; - -// This class is a wrapper around the Local State preference that gets stored -// when we show the one-time profile reset prompt, and which is kept as a -// reminder that we should not show the prompt again. -class LocalStateHostedPromptMemento { - public: - explicit LocalStateHostedPromptMemento(Profile* profile); - ~LocalStateHostedPromptMemento(); - - std::string ReadValue() const; - void StoreValue(const std::string& value); - - private: - // Returns the key that shall be used in the dictionary preference in Local - // State to uniquely identify this profile. - std::string GetProfileKey() const; - - Profile* profile_; - - DISALLOW_COPY_AND_ASSIGN(LocalStateHostedPromptMemento); -}; - -// This class manages a marker file that gets stored when we show the one-time -// profile reset prompt, and which is kept as a reminder that we should not show -// the prompt again. -class FileHostedPromptMemento { - public: - typedef base::Callback<void(const std::string&)> ReadValueCallback; - - explicit FileHostedPromptMemento(Profile* profile); - ~FileHostedPromptMemento(); - - // Posts to the FILE thread to read the value, then returns the value to the - // calling thread. It is safe to destroy this object as soon as this method - // (synchronously) returns. - void ReadValue(const ReadValueCallback& callback) const; - - // Asynchronously stores the value on the FILE thread. However, it is safe to - // destroy this object as soon as this method (synchronously) returns. - void StoreValue(const std::string& value); - - private: - static std::string ReadValueOnFileThread( - const base::FilePath& memento_file_path); - static void StoreValueOnFileThread(const base::FilePath& memento_file_path, - const std::string& value); - - // Returns the path to the file that shall be used to store this kind of - // memento for this profile. - base::FilePath GetMementoFilePath() const; - - Profile* profile_; - - DISALLOW_COPY_AND_ASSIGN(FileHostedPromptMemento); -}; - -#endif // CHROME_BROWSER_PROFILE_RESETTER_AUTOMATIC_PROFILE_RESETTER_MEMENTOS_H_ diff --git a/chrome/browser/profile_resetter/automatic_profile_resetter_unittest.cc b/chrome/browser/profile_resetter/automatic_profile_resetter_unittest.cc deleted file mode 100644 index 046d7de..0000000 --- a/chrome/browser/profile_resetter/automatic_profile_resetter_unittest.cc +++ /dev/null @@ -1,1377 +0,0 @@ -// Copyright 2013 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 "chrome/browser/profile_resetter/automatic_profile_resetter.h" - -#include <string> - -#include "base/bind.h" -#include "base/bind_helpers.h" -#include "base/metrics/field_trial.h" -#include "base/prefs/pref_registry_simple.h" -#include "base/prefs/testing_pref_service.h" -#include "base/run_loop.h" -#include "base/test/test_simple_task_runner.h" -#include "base/threading/sequenced_worker_pool.h" -#include "base/values.h" -#include "chrome/browser/profile_resetter/automatic_profile_resetter_delegate.h" -#include "chrome/browser/profile_resetter/automatic_profile_resetter_factory.h" -#include "chrome/browser/profile_resetter/automatic_profile_resetter_mementos.h" -#include "chrome/browser/profile_resetter/jtl_foundation.h" -#include "chrome/browser/profile_resetter/jtl_instructions.h" -#include "chrome/test/base/scoped_testing_local_state.h" -#include "chrome/test/base/testing_browser_process.h" -#include "chrome/test/base/testing_profile.h" -#include "components/pref_registry/pref_registry_syncable.h" -#include "components/syncable_prefs/testing_pref_service_syncable.h" -#include "components/variations/variations_associated_data.h" -#include "content/public/browser/browser_thread.h" -#include "content/public/test/test_browser_thread_bundle.h" -#include "testing/gmock/include/gmock/gmock.h" -#include "testing/gtest/include/gtest/gtest.h" - -using testing::_; - -namespace { - -const char kAutomaticProfileResetStudyName[] = "AutomaticProfileReset"; -const char kStudyDisabledGroupName[] = "Disabled"; -const char kStudyDryRunGroupName[] = "DryRun"; -const char kStudyEnabledGroupName[] = "Enabled"; - -const char kTestHashSeed[] = "testing-hash-seed"; -const char kTestMementoValue[] = "01234567890123456789012345678901"; -const char kTestInvalidMementoValue[] = "12345678901234567890123456789012"; - -const char kTestPreferencePath[] = "testing.preference"; -const char kTestPreferenceValue[] = "testing-preference-value"; - -const char kSearchURLAttributeKey[] = "search_url"; -const char kTestSearchURL[] = "http://example.com/search?q={searchTerms}"; -const char kTestSearchURL2[] = "http://google.com/?q={searchTerms}"; - -const char kTestModuleDigest[] = "01234567890123456789012345678901"; -const char kTestModuleDigest2[] = "12345678901234567890123456789012"; - -// Helpers ------------------------------------------------------------------ - -// A testing version of the AutomaticProfileResetter that differs from the real -// one only in that it has its statistics reporting mocked out for verification. -class AutomaticProfileResetterUnderTest : public AutomaticProfileResetter { - public: - explicit AutomaticProfileResetterUnderTest(Profile* profile) - : AutomaticProfileResetter(profile) {} - ~AutomaticProfileResetterUnderTest() override {} - - MOCK_METHOD2(ReportStatistics, void(uint32, uint32)); - MOCK_METHOD1(ReportPromptResult, - void(AutomaticProfileResetter::PromptResult)); - - private: - DISALLOW_COPY_AND_ASSIGN(AutomaticProfileResetterUnderTest); -}; - -class MockProfileResetterDelegate : public AutomaticProfileResetterDelegate { - public: - MockProfileResetterDelegate() - : emulated_is_default_search_provider_managed_(false) {} - ~MockProfileResetterDelegate() override {} - - MOCK_METHOD0(EnumerateLoadedModulesIfNeeded, void()); - MOCK_CONST_METHOD1(RequestCallbackWhenLoadedModulesAreEnumerated, - void(const base::Closure&)); - - MOCK_METHOD0(LoadTemplateURLServiceIfNeeded, void()); - MOCK_CONST_METHOD1(RequestCallbackWhenTemplateURLServiceIsLoaded, - void(const base::Closure&)); - - MOCK_METHOD0(FetchBrandcodedDefaultSettingsIfNeeded, void()); - MOCK_CONST_METHOD1(RequestCallbackWhenBrandcodedDefaultsAreFetched, - void(const base::Closure&)); - - MOCK_CONST_METHOD0(OnGetLoadedModuleNameDigestsCalled, void()); - MOCK_CONST_METHOD0(OnGetDefaultSearchProviderDetailsCalled, void()); - MOCK_CONST_METHOD0(OnIsDefaultSearchProviderManagedCalled, void()); - MOCK_CONST_METHOD0(OnGetPrepopulatedSearchProvidersDetailsCalled, void()); - - MOCK_METHOD0(TriggerPrompt, bool()); - MOCK_METHOD2(TriggerProfileSettingsReset, void(bool, const base::Closure&)); - MOCK_METHOD0(DismissPrompt, void()); - - scoped_ptr<base::ListValue> GetLoadedModuleNameDigests() const override { - OnGetLoadedModuleNameDigestsCalled(); - return scoped_ptr<base::ListValue>( - emulated_loaded_module_digests_.DeepCopy()); - } - - scoped_ptr<base::DictionaryValue> - GetDefaultSearchProviderDetails() const override { - OnGetDefaultSearchProviderDetailsCalled(); - return scoped_ptr<base::DictionaryValue>( - emulated_default_search_provider_details_.DeepCopy()); - } - - bool IsDefaultSearchProviderManaged() const override { - OnIsDefaultSearchProviderManagedCalled(); - return emulated_is_default_search_provider_managed_; - } - - scoped_ptr<base::ListValue> - GetPrepopulatedSearchProvidersDetails() const override { - OnGetPrepopulatedSearchProvidersDetailsCalled(); - return scoped_ptr<base::ListValue>( - emulated_search_providers_details_.DeepCopy()); - } - - static void ClosureInvoker(const base::Closure& closure) { closure.Run(); } - - void ExpectCallsToDependenciesSetUpMethods() { - EXPECT_CALL(*this, EnumerateLoadedModulesIfNeeded()); - EXPECT_CALL(*this, LoadTemplateURLServiceIfNeeded()); - EXPECT_CALL(*this, RequestCallbackWhenLoadedModulesAreEnumerated(_)) - .WillOnce(testing::Invoke(ClosureInvoker)); - EXPECT_CALL(*this, RequestCallbackWhenTemplateURLServiceIsLoaded(_)) - .WillOnce(testing::Invoke(ClosureInvoker)); - } - - void ExpectCallsToGetterMethods() { - EXPECT_CALL(*this, OnGetLoadedModuleNameDigestsCalled()); - EXPECT_CALL(*this, OnGetDefaultSearchProviderDetailsCalled()); - EXPECT_CALL(*this, OnIsDefaultSearchProviderManagedCalled()); - EXPECT_CALL(*this, OnGetPrepopulatedSearchProvidersDetailsCalled()); - } - - void ExpectCallToShowPrompt() { - EXPECT_CALL(*this, TriggerPrompt()).WillOnce(testing::Return(true)); - EXPECT_CALL(*this, FetchBrandcodedDefaultSettingsIfNeeded()); - } - - void ExpectCallToTriggerReset(bool send_feedback) { - EXPECT_CALL(*this, TriggerProfileSettingsReset(send_feedback, _)) - .WillOnce(testing::SaveArg<1>(&reset_completion_)); - } - - base::DictionaryValue& emulated_default_search_provider_details() { - return emulated_default_search_provider_details_; - } - - base::ListValue& emulated_search_providers_details() { - return emulated_search_providers_details_; - } - - base::ListValue& emulated_loaded_module_digests() { - return emulated_loaded_module_digests_; - } - - void set_emulated_is_default_search_provider_managed(bool value) { - emulated_is_default_search_provider_managed_ = value; - } - - void EmulateProfileResetCompleted() { - reset_completion_.Run(); - } - - private: - base::DictionaryValue emulated_default_search_provider_details_; - base::ListValue emulated_search_providers_details_; - base::ListValue emulated_loaded_module_digests_; - bool emulated_is_default_search_provider_managed_; - base::Closure reset_completion_; - - DISALLOW_COPY_AND_ASSIGN(MockProfileResetterDelegate); -}; - -class FileHostedPromptMementoSynchronous : protected FileHostedPromptMemento { - public: - explicit FileHostedPromptMementoSynchronous(Profile* profile) - : FileHostedPromptMemento(profile) {} - - std::string ReadValue() const { - std::string result; - FileHostedPromptMemento::ReadValue(base::Bind(&AssignArgumentTo, &result)); - base::RunLoop().RunUntilIdle(); - return result; - } - - void StoreValue(const std::string& value) { - FileHostedPromptMemento::StoreValue(value); - base::RunLoop().RunUntilIdle(); - } - - private: - static void AssignArgumentTo(std::string* target, const std::string& value) { - *target = value; - } - - DISALLOW_COPY_AND_ASSIGN(FileHostedPromptMementoSynchronous); -}; - -std::string GetHash(const std::string& input) { - return jtl_foundation::Hasher(kTestHashSeed).GetHash(input); -} - -// Encodes a Boolean argument value into JTL bytecode. -std::string EncodeBool(bool value) { return value ? VALUE_TRUE : VALUE_FALSE; } - -// Constructs a simple evaluation program to test that basic input/output works -// well. It will emulate a scenario in which the reset criteria are satisfied as -// prescribed by |emulate_satisfied_criterion_{1|2}|, and the reset is triggered -// when either of them is true. The bits in the combined status mask will be set -// according to whether or not the memento values received in the input were as -// expected. -// -// More specifically, the output of the program will be as follows: -// { -// "satisfied_criteria_mask_bit1": emulate_satisfied_criterion_1, -// "satisfied_criteria_mask_bit2": emulate_satisfied_criterion_2, -// "combined_status_mask_bit1": -// (emulate_satisfied_criterion_1 || emulate_satisfied_criterion_2), -// "combined_status_mask_bit2": -// (input["memento_value_in_prefs"] == kTestMementoValue), -// "combined_status_mask_bit3": -// (input["memento_value_in_local_state"] == kTestMementoValue), -// "combined_status_mask_bit4": -// (input["memento_value_in_file"] == kTestMementoValue), -// "should_prompt": -// (emulate_satisfied_criterion_1 || emulate_satisfied_criterion_2), -// "had_prompted_already": <OR-combination of above three>, -// "memento_value_in_prefs": kTestMementoValue, -// "memento_value_in_local_state": kTestMementoValue, -// "memento_value_in_file": kTestMementoValue -// } -std::string ConstructProgram(bool emulate_satisfied_criterion_1, - bool emulate_satisfied_criterion_2) { - std::string bytecode; - bytecode += OP_STORE_BOOL(GetHash("satisfied_criteria_mask_bit1"), - EncodeBool(emulate_satisfied_criterion_1)); - bytecode += OP_END_OF_SENTENCE; - bytecode += OP_STORE_BOOL(GetHash("satisfied_criteria_mask_bit2"), - EncodeBool(emulate_satisfied_criterion_2)); - bytecode += OP_END_OF_SENTENCE; - bytecode += OP_STORE_BOOL(GetHash("should_prompt"), - EncodeBool(emulate_satisfied_criterion_1 || - emulate_satisfied_criterion_2)); - bytecode += OP_END_OF_SENTENCE; - bytecode += OP_STORE_BOOL(GetHash("combined_status_mask_bit1"), - EncodeBool(emulate_satisfied_criterion_1 || - emulate_satisfied_criterion_2)); - bytecode += OP_END_OF_SENTENCE; - bytecode += OP_NAVIGATE(GetHash("memento_value_in_prefs")); - bytecode += OP_COMPARE_NODE_HASH(GetHash(kTestMementoValue)); - bytecode += OP_STORE_BOOL(GetHash("combined_status_mask_bit2"), VALUE_TRUE); - bytecode += OP_STORE_BOOL(GetHash("had_prompted_already"), VALUE_TRUE); - bytecode += OP_END_OF_SENTENCE; - bytecode += OP_NAVIGATE(GetHash("memento_value_in_local_state")); - bytecode += OP_COMPARE_NODE_HASH(GetHash(kTestMementoValue)); - bytecode += OP_STORE_BOOL(GetHash("combined_status_mask_bit3"), VALUE_TRUE); - bytecode += OP_STORE_BOOL(GetHash("had_prompted_already"), VALUE_TRUE); - bytecode += OP_END_OF_SENTENCE; - bytecode += OP_NAVIGATE(GetHash("memento_value_in_file")); - bytecode += OP_COMPARE_NODE_HASH(GetHash(kTestMementoValue)); - bytecode += OP_STORE_BOOL(GetHash("combined_status_mask_bit4"), VALUE_TRUE); - bytecode += OP_STORE_BOOL(GetHash("had_prompted_already"), VALUE_TRUE); - bytecode += OP_END_OF_SENTENCE; - bytecode += OP_STORE_HASH(GetHash("memento_value_in_prefs"), - kTestMementoValue); - bytecode += OP_END_OF_SENTENCE; - bytecode += OP_STORE_HASH(GetHash("memento_value_in_local_state"), - kTestMementoValue); - bytecode += OP_END_OF_SENTENCE; - bytecode += OP_STORE_HASH(GetHash("memento_value_in_file"), - kTestMementoValue); - bytecode += OP_END_OF_SENTENCE; - return bytecode; -} - -// Constructs another evaluation program to specifically test that bits of the -// "satisfied_criteria_mask" are correctly assigned, and so is "should_prompt"; -// and that reset is triggered iff the latter is true, regardless of the bits -// in the mask (so as to allow for a non-disjunctive compound criterion). -// -// More specifically, the output of the program will be as follows: -// { -// "satisfied_criteria_mask_bitN": emulate_satisfied_odd_criteria, -// "satisfied_criteria_mask_bitM": emulate_satisfied_even_criteria, -// "combined_status_mask_bit1": emulate_should_prompt, -// "should_prompt": emulate_should_prompt, -// "memento_value_in_prefs": kTestMementoValue, -// "memento_value_in_local_state": kTestMementoValue, -// "memento_value_in_file": kTestMementoValue -// } -// ... such that N is {1,3,5} and M is {2,4}. -std::string ConstructProgramToExerciseCriteria( - bool emulate_should_prompt, - bool emulate_satisfied_odd_criteria, - bool emulate_satisfied_even_criteria) { - std::string bytecode; - bytecode += OP_STORE_BOOL(GetHash("satisfied_criteria_mask_bit1"), - EncodeBool(emulate_satisfied_odd_criteria)); - bytecode += OP_END_OF_SENTENCE; - bytecode += OP_STORE_BOOL(GetHash("satisfied_criteria_mask_bit3"), - EncodeBool(emulate_satisfied_odd_criteria)); - bytecode += OP_END_OF_SENTENCE; - bytecode += OP_STORE_BOOL(GetHash("satisfied_criteria_mask_bit5"), - EncodeBool(emulate_satisfied_odd_criteria)); - bytecode += OP_END_OF_SENTENCE; - bytecode += OP_STORE_BOOL(GetHash("satisfied_criteria_mask_bit2"), - EncodeBool(emulate_satisfied_even_criteria)); - bytecode += OP_END_OF_SENTENCE; - bytecode += OP_STORE_BOOL(GetHash("satisfied_criteria_mask_bit4"), - EncodeBool(emulate_satisfied_even_criteria)); - bytecode += OP_END_OF_SENTENCE; - bytecode += OP_STORE_BOOL(GetHash("should_prompt"), - EncodeBool(emulate_should_prompt)); - bytecode += OP_END_OF_SENTENCE; - bytecode += OP_STORE_BOOL(GetHash("combined_status_mask_bit1"), - EncodeBool(emulate_should_prompt)); - bytecode += OP_END_OF_SENTENCE; - bytecode += OP_STORE_HASH(GetHash("memento_value_in_prefs"), - kTestMementoValue); - bytecode += OP_END_OF_SENTENCE; - bytecode += OP_STORE_HASH(GetHash("memento_value_in_local_state"), - kTestMementoValue); - bytecode += OP_END_OF_SENTENCE; - bytecode += OP_STORE_HASH(GetHash("memento_value_in_file"), - kTestMementoValue); - bytecode += OP_END_OF_SENTENCE; - return bytecode; -} - -// Constructs another evaluation program to specifically test that local state -// and user preference values are included in the input as expected. We will -// re-purpose the output bitmasks to channel out information about the outcome -// of the checks. -// -// More specifically, the output of the program will be as follows: -// { -// "combined_status_mask_bit1": -// (input["preferences.testing.preference"] == kTestPreferenceValue) -// "combined_status_mask_bit2": -// (input["local_state.testing.preference"] == kTestPreferenceValue) -// "combined_status_mask_bit3": input["preferences_iuc.testing.preference"] -// "combined_status_mask_bit4": input["local_state_iuc.testing.preference"] -// } -std::string ConstructProgramToCheckPreferences() { - std::string bytecode; - bytecode += OP_NAVIGATE(GetHash("preferences")); - bytecode += OP_NAVIGATE(GetHash("testing")); - bytecode += OP_NAVIGATE(GetHash("preference")); - bytecode += OP_COMPARE_NODE_HASH(GetHash(kTestPreferenceValue)); - bytecode += OP_STORE_BOOL(GetHash("combined_status_mask_bit1"), - EncodeBool(true)); - bytecode += OP_END_OF_SENTENCE; - bytecode += OP_NAVIGATE(GetHash("local_state")); - bytecode += OP_NAVIGATE(GetHash("testing")); - bytecode += OP_NAVIGATE(GetHash("preference")); - bytecode += OP_COMPARE_NODE_HASH(GetHash(kTestPreferenceValue)); - bytecode += OP_STORE_BOOL(GetHash("combined_status_mask_bit2"), - EncodeBool(true)); - bytecode += OP_END_OF_SENTENCE; - bytecode += OP_NAVIGATE(GetHash("preferences_iuc")); - bytecode += OP_NAVIGATE(GetHash("testing")); - bytecode += OP_NAVIGATE(GetHash("preference")); - bytecode += OP_COMPARE_NODE_BOOL(EncodeBool(true)); - bytecode += OP_STORE_BOOL(GetHash("combined_status_mask_bit3"), - EncodeBool(true)); - bytecode += OP_END_OF_SENTENCE; - bytecode += OP_NAVIGATE(GetHash("local_state_iuc")); - bytecode += OP_NAVIGATE(GetHash("testing")); - bytecode += OP_NAVIGATE(GetHash("preference")); - bytecode += OP_COMPARE_NODE_BOOL(EncodeBool(true)); - bytecode += OP_STORE_BOOL(GetHash("combined_status_mask_bit4"), - EncodeBool(true)); - bytecode += OP_END_OF_SENTENCE; - return bytecode; -} - -// Legend for the bitmask returned by the above program. -enum CombinedStatusMaskLegendForCheckingPreferences { - HAS_EXPECTED_USER_PREFERENCE = 1 << 0, - HAS_EXPECTED_LOCAL_STATE_PREFERENCE = 1 << 1, - USER_PREFERENCE_IS_USER_CONTROLLED = 1 << 2, - LOCAL_STATE_IS_USER_CONTROLLED = 1 << 3, -}; - -// Constructs yet another evaluation program to specifically test that default -// and pre-populated search engines are included in the input as expected. We -// will re-purpose the output bitmasks to channel out information about the -// outcome of the checks. -// -// More specifically, the output of the program will be as follows: -// { -// "combined_status_mask_bit1": -// (input["default_search_provider.search_url"] == kTestSearchURL) -// "combined_status_mask_bit2": input["default_search_provider_iuc"] -// "combined_status_mask_bit3": -// (input["search_providers.*.search_url"] == kTestSearchURL) -// "combined_status_mask_bit4": -// (input["search_providers.*.search_url"] == kTestSearchURL2) -// } -std::string ConstructProgramToCheckSearchEngines() { - std::string bytecode; - bytecode += OP_NAVIGATE(GetHash("default_search_provider")); - bytecode += OP_NAVIGATE(GetHash("search_url")); - bytecode += OP_COMPARE_NODE_HASH(GetHash(kTestSearchURL)); - bytecode += OP_STORE_BOOL(GetHash("combined_status_mask_bit1"), - EncodeBool(true)); - bytecode += OP_END_OF_SENTENCE; - bytecode += OP_NAVIGATE(GetHash("default_search_provider_iuc")); - bytecode += OP_COMPARE_NODE_BOOL(EncodeBool(true)); - bytecode += OP_STORE_BOOL(GetHash("combined_status_mask_bit2"), - EncodeBool(true)); - bytecode += OP_END_OF_SENTENCE; - bytecode += OP_NAVIGATE(GetHash("search_providers")); - bytecode += OP_NAVIGATE_ANY; - bytecode += OP_NAVIGATE(GetHash("search_url")); - bytecode += OP_COMPARE_NODE_HASH(GetHash(kTestSearchURL)); - bytecode += OP_STORE_BOOL(GetHash("combined_status_mask_bit3"), - EncodeBool(true)); - bytecode += OP_END_OF_SENTENCE; - bytecode += OP_NAVIGATE(GetHash("search_providers")); - bytecode += OP_NAVIGATE_ANY; - bytecode += OP_NAVIGATE(GetHash("search_url")); - bytecode += OP_COMPARE_NODE_HASH(GetHash(kTestSearchURL2)); - bytecode += OP_STORE_BOOL(GetHash("combined_status_mask_bit4"), - EncodeBool(true)); - bytecode += OP_END_OF_SENTENCE; - return bytecode; -} - -// Legend for the bitmask returned by the above program. -enum CombinedStatusMaskLegendForCheckingSearchEngines { - HAS_EXPECTED_DEFAULT_SEARCH_PROVIDER = 1 << 0, - DEFAULT_SEARCH_PROVIDER_IS_USER_CONTROLLED = 1 << 1, - HAS_EXPECTED_PREPOPULATED_SEARCH_PROVIDER_1 = 1 << 2, - HAS_EXPECTED_PREPOPULATED_SEARCH_PROVIDER_2 = 1 << 3, -}; - -// Constructs yet another evaluation program to specifically test that loaded -// module digests are included in the input as expected. We will re-purpose the -// output bitmasks to channel out information about the outcome of the checks. -// -// More specifically, the output of the program will be as follows: -// { -// "combined_status_mask_bit1": -// (input["loaded_modules.*"] == kTestModuleDigest) -// "combined_status_mask_bit2": -// (input["loaded_modules.*"] == kTestModuleDigest2) -// } -std::string ConstructProgramToCheckLoadedModuleDigests() { - std::string bytecode; - bytecode += OP_NAVIGATE(GetHash("loaded_modules")); - bytecode += OP_NAVIGATE_ANY; - bytecode += OP_COMPARE_NODE_HASH(GetHash(kTestModuleDigest)); - bytecode += OP_STORE_BOOL(GetHash("combined_status_mask_bit1"), - EncodeBool(true)); - bytecode += OP_END_OF_SENTENCE; - bytecode += OP_NAVIGATE(GetHash("loaded_modules")); - bytecode += OP_NAVIGATE_ANY; - bytecode += OP_COMPARE_NODE_HASH(GetHash(kTestModuleDigest2)); - bytecode += OP_STORE_BOOL(GetHash("combined_status_mask_bit2"), - EncodeBool(true)); - bytecode += OP_END_OF_SENTENCE; - return bytecode; -} - -// Legend for the bitmask returned by the above program. -enum CombinedStatusMaskLegendForCheckingLoadedModules { - HAS_EXPECTED_MODULE_DIGEST_1 = 1 << 0, - HAS_EXPECTED_MODULE_DIGEST_2 = 1 << 1, -}; - -// Test fixtures ------------------------------------------------------------- - -class AutomaticProfileResetterTestBase : public testing::Test { - protected: - explicit AutomaticProfileResetterTestBase( - const std::string& experiment_group_name) - : waiting_task_runner_(new base::TestSimpleTaskRunner), - local_state_(TestingBrowserProcess::GetGlobal()), - profile_(new TestingProfile()), - field_trials_(new base::FieldTrialList(NULL)), - memento_in_prefs_(new PreferenceHostedPromptMemento(profile())), - memento_in_local_state_(new LocalStateHostedPromptMemento(profile())), - memento_in_file_(new FileHostedPromptMementoSynchronous(profile())), - experiment_group_name_(experiment_group_name), - inject_data_through_variation_params_(false), - mock_delegate_(NULL) { - // Make sure the factory is not optimized away, so whatever preferences it - // wants to register will actually get registered. - AutomaticProfileResetterFactory::GetInstance(); - - // Register some additional local state preferences for testing purposes. - PrefRegistrySimple* local_state_registry = local_state_.Get()->registry(); - DCHECK(local_state_registry); - local_state_registry->RegisterStringPref(kTestPreferencePath, ""); - - // Register some additional user preferences for testing purposes. - user_prefs::PrefRegistrySyncable* user_prefs_registry = - profile_->GetTestingPrefService()->registry(); - DCHECK(user_prefs_registry); - user_prefs_registry->RegisterStringPref(kTestPreferencePath, std::string()); - } - - void SetUp() override { - variations::testing::ClearAllVariationParams(); - base::FieldTrialList::CreateFieldTrial(kAutomaticProfileResetStudyName, - experiment_group_name_); - resetter_.reset( - new testing::StrictMock<AutomaticProfileResetterUnderTest>(profile())); - mock_delegate_owned_.reset( - new testing::StrictMock<MockProfileResetterDelegate>()); - mock_delegate_ = mock_delegate_owned_.get(); - - ExpectAllMementoValuesEqualTo(std::string()); - } - - void SetTestingHashSeed(const std::string& hash_seed) { - testing_hash_seed_ = hash_seed; - } - - void SetTestingProgram(const std::string& source_code) { - testing_program_ = source_code; - } - - void AllowInjectingTestDataThroughVariationParams(bool value) { - inject_data_through_variation_params_ = value; - } - - void ExpectAllMementoValuesEqualTo(const std::string& value) { - EXPECT_EQ(value, memento_in_prefs_->ReadValue()); - EXPECT_EQ(value, memento_in_local_state_->ReadValue()); - EXPECT_EQ(value, memento_in_file_->ReadValue()); - } - - void UnleashResetterAndWait() { - if (inject_data_through_variation_params_) { - std::map<std::string, std::string> variation_params; - variation_params["program"] = testing_program_; - variation_params["hash_seed"] = testing_hash_seed_; - ASSERT_TRUE(variations::AssociateVariationParams( - kAutomaticProfileResetStudyName, - experiment_group_name_, - variation_params)); - } - resetter_->Initialize(); - resetter_->SetDelegateForTesting(mock_delegate_owned_.Pass()); - resetter_->SetTaskRunnerForWaitingForTesting(waiting_task_runner_); - if (!inject_data_through_variation_params_) { - resetter_->SetProgramForTesting(testing_program_); - resetter_->SetHashSeedForTesting(testing_hash_seed_); - } - resetter_->Activate(); - - if (waiting_task_runner_->HasPendingTask()) { - ASSERT_EQ(base::TimeDelta::FromSeconds(55), - waiting_task_runner_->NextPendingTaskDelay()); - waiting_task_runner_->RunPendingTasks(); - } - base::RunLoop().RunUntilIdle(); - content::BrowserThread::GetBlockingPool()->FlushForTesting(); - base::RunLoop().RunUntilIdle(); - } - - // Goes through an evaluation flow such that the reset criteria are satisfied. - // Used to reduce boilerplate for tests that need to verify behavior during - // the reset prompt flow. - void OrchestrateThroughEvaluationFlow() { - SetTestingProgram(ConstructProgram(true, true)); - SetTestingHashSeed(kTestHashSeed); - - mock_delegate().ExpectCallsToDependenciesSetUpMethods(); - mock_delegate().ExpectCallsToGetterMethods(); - mock_delegate().ExpectCallToShowPrompt(); - EXPECT_CALL(resetter(), ReportStatistics(0x03u, 0x01u)); - - UnleashResetterAndWait(); - - EXPECT_TRUE(resetter().ShouldShowResetBanner()); - testing::Mock::VerifyAndClearExpectations(&resetter()); - testing::Mock::VerifyAndClearExpectations(&mock_delegate()); - } - - // Explicitly shut down the service to double-check that nothing explodes, but - // first, verify expectations to make sure the service makes no more calls to - // any mocked functions during or after shutdown. - void VerifyExpectationsThenShutdownResetter() { - testing::Mock::VerifyAndClearExpectations(&resetter()); - testing::Mock::VerifyAndClearExpectations(&mock_delegate()); - - resetter_->Shutdown(); - resetter_.reset(); - } - - TestingProfile* profile() { return profile_.get(); } - TestingPrefServiceSimple* local_state() { return local_state_.Get(); } - - PreferenceHostedPromptMemento& memento_in_prefs() { - return *memento_in_prefs_; - } - - LocalStateHostedPromptMemento& memento_in_local_state() { - return *memento_in_local_state_; - } - - FileHostedPromptMementoSynchronous& memento_in_file() { - return *memento_in_file_; - } - - MockProfileResetterDelegate& mock_delegate() { return *mock_delegate_; } - AutomaticProfileResetterUnderTest& resetter() { return *resetter_; } - - private: - content::TestBrowserThreadBundle thread_bundle_; - scoped_refptr<base::TestSimpleTaskRunner> waiting_task_runner_; - ScopedTestingLocalState local_state_; - scoped_ptr<TestingProfile> profile_; - scoped_ptr<base::FieldTrialList> field_trials_; - scoped_ptr<PreferenceHostedPromptMemento> memento_in_prefs_; - scoped_ptr<LocalStateHostedPromptMemento> memento_in_local_state_; - scoped_ptr<FileHostedPromptMementoSynchronous> memento_in_file_; - - std::string experiment_group_name_; - std::string testing_program_; - std::string testing_hash_seed_; - bool inject_data_through_variation_params_; - - scoped_ptr<AutomaticProfileResetterUnderTest> resetter_; - scoped_ptr<MockProfileResetterDelegate> mock_delegate_owned_; - MockProfileResetterDelegate* mock_delegate_; - - DISALLOW_COPY_AND_ASSIGN(AutomaticProfileResetterTestBase); -}; - -class AutomaticProfileResetterTest : public AutomaticProfileResetterTestBase { - protected: - AutomaticProfileResetterTest() - : AutomaticProfileResetterTestBase(kStudyEnabledGroupName) {} -}; - -class AutomaticProfileResetterTestDryRun - : public AutomaticProfileResetterTestBase { - protected: - AutomaticProfileResetterTestDryRun() - : AutomaticProfileResetterTestBase(kStudyDryRunGroupName) {} -}; - -class AutomaticProfileResetterTestDisabled - : public AutomaticProfileResetterTestBase { - protected: - AutomaticProfileResetterTestDisabled() - : AutomaticProfileResetterTestBase(kStudyDisabledGroupName) {} -}; - -// Tests --------------------------------------------------------------------- - -TEST_F(AutomaticProfileResetterTestDisabled, NothingIsDoneWhenDisabled) { - SetTestingProgram(ConstructProgram(true, true)); - SetTestingHashSeed(kTestHashSeed); - - // No calls are expected to the delegate. - - UnleashResetterAndWait(); - - EXPECT_FALSE(resetter().ShouldShowResetBanner()); - VerifyExpectationsThenShutdownResetter(); - - ExpectAllMementoValuesEqualTo(std::string()); -} - -TEST_F(AutomaticProfileResetterTestDryRun, CriteriaNotSatisfied) { - SetTestingProgram(ConstructProgramToExerciseCriteria(false, true, true)); - SetTestingHashSeed(kTestHashSeed); - - mock_delegate().ExpectCallsToDependenciesSetUpMethods(); - mock_delegate().ExpectCallsToGetterMethods(); - EXPECT_CALL(resetter(), ReportStatistics(0x1fu, 0x00u)); - - UnleashResetterAndWait(); - - EXPECT_FALSE(resetter().ShouldShowResetBanner()); - VerifyExpectationsThenShutdownResetter(); - - ExpectAllMementoValuesEqualTo(std::string()); -} - -TEST_F(AutomaticProfileResetterTestDryRun, OddCriteriaSatisfied) { - SetTestingProgram(ConstructProgramToExerciseCriteria(true, true, false)); - SetTestingHashSeed(kTestHashSeed); - - mock_delegate().ExpectCallsToDependenciesSetUpMethods(); - mock_delegate().ExpectCallsToGetterMethods(); - EXPECT_CALL(resetter(), ReportStatistics(0x15u, 0x01u)); - EXPECT_CALL(resetter(), ReportPromptResult( - AutomaticProfileResetter::PROMPT_NOT_TRIGGERED)); - - UnleashResetterAndWait(); - - ExpectAllMementoValuesEqualTo(kTestMementoValue); - EXPECT_FALSE(resetter().ShouldShowResetBanner()); - VerifyExpectationsThenShutdownResetter(); -} - -TEST_F(AutomaticProfileResetterTestDryRun, EvenCriteriaSatisfied) { - SetTestingProgram(ConstructProgramToExerciseCriteria(true, false, true)); - SetTestingHashSeed(kTestHashSeed); - - mock_delegate().ExpectCallsToDependenciesSetUpMethods(); - mock_delegate().ExpectCallsToGetterMethods(); - EXPECT_CALL(resetter(), ReportStatistics(0x0au, 0x01u)); - EXPECT_CALL(resetter(), ReportPromptResult( - AutomaticProfileResetter::PROMPT_NOT_TRIGGERED)); - - UnleashResetterAndWait(); - - ExpectAllMementoValuesEqualTo(kTestMementoValue); - EXPECT_FALSE(resetter().ShouldShowResetBanner()); - VerifyExpectationsThenShutdownResetter(); -} - -#if defined(GOOGLE_CHROME_BUILD) -TEST_F(AutomaticProfileResetterTestDryRun, ProgramSetThroughVariationParams) { - SetTestingProgram(ConstructProgram(true, true)); - SetTestingHashSeed(kTestHashSeed); - AllowInjectingTestDataThroughVariationParams(true); - - mock_delegate().ExpectCallsToDependenciesSetUpMethods(); - mock_delegate().ExpectCallsToGetterMethods(); - EXPECT_CALL(resetter(), ReportStatistics(0x03u, 0x01u)); - EXPECT_CALL(resetter(), ReportPromptResult( - AutomaticProfileResetter::PROMPT_NOT_TRIGGERED)); - - UnleashResetterAndWait(); - - ExpectAllMementoValuesEqualTo(kTestMementoValue); - EXPECT_FALSE(resetter().ShouldShowResetBanner()); - VerifyExpectationsThenShutdownResetter(); -} -#endif - -TEST_F(AutomaticProfileResetterTestDryRun, - ConditionsSatisfiedAndInvalidMementos) { - memento_in_prefs().StoreValue(kTestInvalidMementoValue); - memento_in_local_state().StoreValue(kTestInvalidMementoValue); - memento_in_file().StoreValue(kTestInvalidMementoValue); - - SetTestingProgram(ConstructProgram(true, true)); - SetTestingHashSeed(kTestHashSeed); - - mock_delegate().ExpectCallsToDependenciesSetUpMethods(); - mock_delegate().ExpectCallsToGetterMethods(); - EXPECT_CALL(resetter(), ReportStatistics(0x03u, 0x01u)); - EXPECT_CALL(resetter(), ReportPromptResult( - AutomaticProfileResetter::PROMPT_NOT_TRIGGERED)); - - UnleashResetterAndWait(); - - ExpectAllMementoValuesEqualTo(kTestMementoValue); - EXPECT_FALSE(resetter().ShouldShowResetBanner()); - VerifyExpectationsThenShutdownResetter(); -} - -TEST_F(AutomaticProfileResetterTestDryRun, AlreadyHadPrefHostedMemento) { - memento_in_prefs().StoreValue(kTestMementoValue); - - SetTestingProgram(ConstructProgram(true, true)); - SetTestingHashSeed(kTestHashSeed); - - mock_delegate().ExpectCallsToDependenciesSetUpMethods(); - mock_delegate().ExpectCallsToGetterMethods(); - EXPECT_CALL(resetter(), ReportStatistics(0x03u, 0x03u)); - - UnleashResetterAndWait(); - - EXPECT_FALSE(resetter().ShouldShowResetBanner()); - VerifyExpectationsThenShutdownResetter(); - - EXPECT_EQ(kTestMementoValue, memento_in_prefs().ReadValue()); - EXPECT_EQ(std::string(), memento_in_local_state().ReadValue()); - EXPECT_EQ(std::string(), memento_in_file().ReadValue()); -} - -TEST_F(AutomaticProfileResetterTestDryRun, AlreadyHadLocalStateHostedMemento) { - memento_in_local_state().StoreValue(kTestMementoValue); - - SetTestingProgram(ConstructProgram(true, true)); - SetTestingHashSeed(kTestHashSeed); - - mock_delegate().ExpectCallsToDependenciesSetUpMethods(); - mock_delegate().ExpectCallsToGetterMethods(); - EXPECT_CALL(resetter(), ReportStatistics(0x03u, 0x05u)); - - UnleashResetterAndWait(); - - EXPECT_FALSE(resetter().ShouldShowResetBanner()); - VerifyExpectationsThenShutdownResetter(); - - EXPECT_EQ(std::string(), memento_in_prefs().ReadValue()); - EXPECT_EQ(kTestMementoValue, memento_in_local_state().ReadValue()); - EXPECT_EQ(std::string(), memento_in_file().ReadValue()); -} - -TEST_F(AutomaticProfileResetterTestDryRun, AlreadyHadFileHostedMemento) { - memento_in_file().StoreValue(kTestMementoValue); - - SetTestingProgram(ConstructProgram(true, true)); - SetTestingHashSeed(kTestHashSeed); - - mock_delegate().ExpectCallsToDependenciesSetUpMethods(); - mock_delegate().ExpectCallsToGetterMethods(); - EXPECT_CALL(resetter(), ReportStatistics(0x03u, 0x09u)); - - UnleashResetterAndWait(); - - EXPECT_FALSE(resetter().ShouldShowResetBanner()); - VerifyExpectationsThenShutdownResetter(); - - EXPECT_EQ(std::string(), memento_in_prefs().ReadValue()); - EXPECT_EQ(std::string(), memento_in_local_state().ReadValue()); - EXPECT_EQ(kTestMementoValue, memento_in_file().ReadValue()); -} - -TEST_F(AutomaticProfileResetterTestDryRun, DoNothingWhenResourcesAreMissing) { - SetTestingProgram(std::string()); - SetTestingHashSeed(std::string()); - - // No calls are expected to the delegate. - - UnleashResetterAndWait(); - - EXPECT_FALSE(resetter().ShouldShowResetBanner()); - VerifyExpectationsThenShutdownResetter(); - - ExpectAllMementoValuesEqualTo(std::string()); -} - -TEST_F(AutomaticProfileResetterTest, CriteriaNotSatisfied) { - SetTestingProgram(ConstructProgramToExerciseCriteria(false, true, true)); - SetTestingHashSeed(kTestHashSeed); - - mock_delegate().ExpectCallsToDependenciesSetUpMethods(); - mock_delegate().ExpectCallsToGetterMethods(); - EXPECT_CALL(resetter(), ReportStatistics(0x1fu, 0x00u)); - - UnleashResetterAndWait(); - - EXPECT_FALSE(resetter().ShouldShowResetBanner()); - VerifyExpectationsThenShutdownResetter(); - - ExpectAllMementoValuesEqualTo(std::string()); -} - -TEST_F(AutomaticProfileResetterTest, OddCriteriaSatisfied) { - SetTestingProgram(ConstructProgramToExerciseCriteria(true, true, false)); - SetTestingHashSeed(kTestHashSeed); - - mock_delegate().ExpectCallsToDependenciesSetUpMethods(); - mock_delegate().ExpectCallsToGetterMethods(); - mock_delegate().ExpectCallToShowPrompt(); - EXPECT_CALL(resetter(), ReportStatistics(0x15u, 0x01u)); - - UnleashResetterAndWait(); - - EXPECT_TRUE(resetter().ShouldShowResetBanner()); - VerifyExpectationsThenShutdownResetter(); -} - -TEST_F(AutomaticProfileResetterTest, EvenCriteriaSatisfied) { - SetTestingProgram(ConstructProgramToExerciseCriteria(true, false, true)); - SetTestingHashSeed(kTestHashSeed); - - mock_delegate().ExpectCallsToDependenciesSetUpMethods(); - mock_delegate().ExpectCallsToGetterMethods(); - mock_delegate().ExpectCallToShowPrompt(); - EXPECT_CALL(resetter(), ReportStatistics(0x0au, 0x01u)); - - UnleashResetterAndWait(); - - EXPECT_TRUE(resetter().ShouldShowResetBanner()); - VerifyExpectationsThenShutdownResetter(); -} - -#if defined(GOOGLE_CHROME_BUILD) -TEST_F(AutomaticProfileResetterTest, ProgramSetThroughVariationParams) { - SetTestingProgram(ConstructProgram(true, true)); - SetTestingHashSeed(kTestHashSeed); - AllowInjectingTestDataThroughVariationParams(true); - - mock_delegate().ExpectCallsToDependenciesSetUpMethods(); - mock_delegate().ExpectCallsToGetterMethods(); - mock_delegate().ExpectCallToShowPrompt(); - EXPECT_CALL(resetter(), ReportStatistics(0x03u, 0x01u)); - EXPECT_CALL(resetter(), ReportPromptResult( - AutomaticProfileResetter::PROMPT_SHOWN_BUBBLE)); - - UnleashResetterAndWait(); - resetter().NotifyDidShowResetBubble(); - - ExpectAllMementoValuesEqualTo(kTestMementoValue); - EXPECT_TRUE(resetter().ShouldShowResetBanner()); - VerifyExpectationsThenShutdownResetter(); -} -#endif - -TEST_F(AutomaticProfileResetterTest, ConditionsSatisfiedAndInvalidMementos) { - memento_in_prefs().StoreValue(kTestInvalidMementoValue); - memento_in_local_state().StoreValue(kTestInvalidMementoValue); - memento_in_file().StoreValue(kTestInvalidMementoValue); - - SetTestingProgram(ConstructProgram(true, true)); - SetTestingHashSeed(kTestHashSeed); - - mock_delegate().ExpectCallsToDependenciesSetUpMethods(); - mock_delegate().ExpectCallsToGetterMethods(); - mock_delegate().ExpectCallToShowPrompt(); - EXPECT_CALL(resetter(), ReportStatistics(0x03u, 0x01u)); - EXPECT_CALL(resetter(), ReportPromptResult( - AutomaticProfileResetter::PROMPT_SHOWN_BUBBLE)); - - UnleashResetterAndWait(); - resetter().NotifyDidShowResetBubble(); - - ExpectAllMementoValuesEqualTo(kTestMementoValue); - EXPECT_TRUE(resetter().ShouldShowResetBanner()); - VerifyExpectationsThenShutdownResetter(); -} - -TEST_F(AutomaticProfileResetterTest, PrefHostedMementoPreventsPrompt) { - memento_in_prefs().StoreValue(kTestMementoValue); - - SetTestingProgram(ConstructProgram(true, true)); - SetTestingHashSeed(kTestHashSeed); - - mock_delegate().ExpectCallsToDependenciesSetUpMethods(); - mock_delegate().ExpectCallsToGetterMethods(); - EXPECT_CALL(resetter(), ReportStatistics(0x03u, 0x03u)); - - UnleashResetterAndWait(); - - EXPECT_TRUE(resetter().ShouldShowResetBanner()); - VerifyExpectationsThenShutdownResetter(); - - EXPECT_EQ(kTestMementoValue, memento_in_prefs().ReadValue()); - EXPECT_EQ(std::string(), memento_in_local_state().ReadValue()); - EXPECT_EQ(std::string(), memento_in_file().ReadValue()); -} - -TEST_F(AutomaticProfileResetterTest, LocalStateHostedMementoPreventsPrompt) { - memento_in_local_state().StoreValue(kTestMementoValue); - - SetTestingProgram(ConstructProgram(true, true)); - SetTestingHashSeed(kTestHashSeed); - - mock_delegate().ExpectCallsToDependenciesSetUpMethods(); - mock_delegate().ExpectCallsToGetterMethods(); - EXPECT_CALL(resetter(), ReportStatistics(0x03u, 0x05u)); - - UnleashResetterAndWait(); - - EXPECT_TRUE(resetter().ShouldShowResetBanner()); - VerifyExpectationsThenShutdownResetter(); - - EXPECT_EQ(std::string(), memento_in_prefs().ReadValue()); - EXPECT_EQ(kTestMementoValue, memento_in_local_state().ReadValue()); - EXPECT_EQ(std::string(), memento_in_file().ReadValue()); -} - -TEST_F(AutomaticProfileResetterTest, FileHostedMementoPreventsPrompt) { - memento_in_file().StoreValue(kTestMementoValue); - - SetTestingProgram(ConstructProgram(true, true)); - SetTestingHashSeed(kTestHashSeed); - - mock_delegate().ExpectCallsToDependenciesSetUpMethods(); - mock_delegate().ExpectCallsToGetterMethods(); - EXPECT_CALL(resetter(), ReportStatistics(0x03u, 0x09u)); - - UnleashResetterAndWait(); - - EXPECT_TRUE(resetter().ShouldShowResetBanner()); - VerifyExpectationsThenShutdownResetter(); - - EXPECT_EQ(std::string(), memento_in_prefs().ReadValue()); - EXPECT_EQ(std::string(), memento_in_local_state().ReadValue()); - EXPECT_EQ(kTestMementoValue, memento_in_file().ReadValue()); -} - -TEST_F(AutomaticProfileResetterTest, DoNothingWhenResourcesAreMissing) { - SetTestingProgram(std::string()); - SetTestingHashSeed(std::string()); - - // No calls are expected to the delegate. - - UnleashResetterAndWait(); - - EXPECT_FALSE(resetter().ShouldShowResetBanner()); - VerifyExpectationsThenShutdownResetter(); - - ExpectAllMementoValuesEqualTo(std::string()); -} - -TEST_F(AutomaticProfileResetterTest, PromptSuppressed) { - OrchestrateThroughEvaluationFlow(); - - VerifyExpectationsThenShutdownResetter(); - - ExpectAllMementoValuesEqualTo(std::string()); -} - -TEST_F(AutomaticProfileResetterTest, PromptNotSupported) { - SetTestingProgram(ConstructProgram(true, true)); - SetTestingHashSeed(kTestHashSeed); - - mock_delegate().ExpectCallsToDependenciesSetUpMethods(); - mock_delegate().ExpectCallsToGetterMethods(); - EXPECT_CALL(mock_delegate(), TriggerPrompt()) - .WillOnce(testing::Return(false)); - EXPECT_CALL(resetter(), ReportStatistics(0x03u, 0x01u)); - EXPECT_CALL(resetter(), ReportPromptResult( - AutomaticProfileResetter::PROMPT_NOT_TRIGGERED)); - - UnleashResetterAndWait(); - - ExpectAllMementoValuesEqualTo(kTestMementoValue); - EXPECT_TRUE(resetter().ShouldShowResetBanner()); - VerifyExpectationsThenShutdownResetter(); -} - -TEST_F(AutomaticProfileResetterTest, PromptIgnored) { - OrchestrateThroughEvaluationFlow(); - - EXPECT_CALL(resetter(), ReportPromptResult( - AutomaticProfileResetter::PROMPT_SHOWN_BUBBLE)); - resetter().NotifyDidShowResetBubble(); - ExpectAllMementoValuesEqualTo(kTestMementoValue); - VerifyExpectationsThenShutdownResetter(); -} - -TEST_F(AutomaticProfileResetterTest, PromptActionReset) { - OrchestrateThroughEvaluationFlow(); - - EXPECT_CALL(resetter(), ReportPromptResult( - AutomaticProfileResetter::PROMPT_SHOWN_BUBBLE)); - resetter().NotifyDidShowResetBubble(); - ExpectAllMementoValuesEqualTo(kTestMementoValue); - testing::Mock::VerifyAndClearExpectations(&resetter()); - - mock_delegate().ExpectCallToTriggerReset(false); - EXPECT_CALL(resetter(), ReportPromptResult( - AutomaticProfileResetter::PROMPT_ACTION_RESET)); - resetter().TriggerProfileReset(false /*send_feedback*/); - testing::Mock::VerifyAndClearExpectations(&resetter()); - testing::Mock::VerifyAndClearExpectations(&mock_delegate()); - - EXPECT_CALL(mock_delegate(), DismissPrompt()); - mock_delegate().EmulateProfileResetCompleted(); - EXPECT_FALSE(resetter().ShouldShowResetBanner()); - VerifyExpectationsThenShutdownResetter(); -} - -TEST_F(AutomaticProfileResetterTest, PromptActionResetWithFeedback) { - OrchestrateThroughEvaluationFlow(); - - EXPECT_CALL(resetter(), ReportPromptResult( - AutomaticProfileResetter::PROMPT_SHOWN_BUBBLE)); - resetter().NotifyDidShowResetBubble(); - ExpectAllMementoValuesEqualTo(kTestMementoValue); - testing::Mock::VerifyAndClearExpectations(&resetter()); - - mock_delegate().ExpectCallToTriggerReset(true); - EXPECT_CALL(resetter(), ReportPromptResult( - AutomaticProfileResetter::PROMPT_ACTION_RESET)); - resetter().TriggerProfileReset(true /*send_feedback*/); - testing::Mock::VerifyAndClearExpectations(&resetter()); - testing::Mock::VerifyAndClearExpectations(&mock_delegate()); - - EXPECT_CALL(mock_delegate(), DismissPrompt()); - mock_delegate().EmulateProfileResetCompleted(); - EXPECT_FALSE(resetter().ShouldShowResetBanner()); - VerifyExpectationsThenShutdownResetter(); -} - -TEST_F(AutomaticProfileResetterTest, PromptActionNoReset) { - OrchestrateThroughEvaluationFlow(); - - EXPECT_CALL(resetter(), ReportPromptResult( - AutomaticProfileResetter::PROMPT_SHOWN_BUBBLE)); - resetter().NotifyDidShowResetBubble(); - ExpectAllMementoValuesEqualTo(kTestMementoValue); - testing::Mock::VerifyAndClearExpectations(&resetter()); - - EXPECT_CALL(mock_delegate(), DismissPrompt()); - EXPECT_CALL(resetter(), ReportPromptResult( - AutomaticProfileResetter::PROMPT_ACTION_NO_RESET)); - resetter().SkipProfileReset(); - EXPECT_FALSE(resetter().ShouldShowResetBanner()); - VerifyExpectationsThenShutdownResetter(); -} - -TEST_F(AutomaticProfileResetterTest, PromptFollowedByWebUIReset) { - OrchestrateThroughEvaluationFlow(); - - EXPECT_CALL(resetter(), ReportPromptResult( - AutomaticProfileResetter::PROMPT_SHOWN_BUBBLE)); - resetter().NotifyDidShowResetBubble(); - ExpectAllMementoValuesEqualTo(kTestMementoValue); - testing::Mock::VerifyAndClearExpectations(&resetter()); - - EXPECT_CALL(mock_delegate(), DismissPrompt()); - resetter().NotifyDidOpenWebUIResetDialog(); - testing::Mock::VerifyAndClearExpectations(&mock_delegate()); - - EXPECT_CALL(resetter(), ReportPromptResult( - AutomaticProfileResetter::PROMPT_FOLLOWED_BY_WEBUI_RESET)); - resetter().NotifyDidCloseWebUIResetDialog(true); - EXPECT_TRUE(resetter().ShouldShowResetBanner()); - VerifyExpectationsThenShutdownResetter(); -} - -TEST_F(AutomaticProfileResetterTest, PromptFollowedByWebUINoReset) { - OrchestrateThroughEvaluationFlow(); - - EXPECT_CALL(resetter(), ReportPromptResult( - AutomaticProfileResetter::PROMPT_SHOWN_BUBBLE)); - resetter().NotifyDidShowResetBubble(); - ExpectAllMementoValuesEqualTo(kTestMementoValue); - testing::Mock::VerifyAndClearExpectations(&resetter()); - - EXPECT_CALL(mock_delegate(), DismissPrompt()); - resetter().NotifyDidOpenWebUIResetDialog(); - testing::Mock::VerifyAndClearExpectations(&mock_delegate()); - - EXPECT_CALL(resetter(), ReportPromptResult( - AutomaticProfileResetter::PROMPT_FOLLOWED_BY_WEBUI_NO_RESET)); - resetter().NotifyDidCloseWebUIResetDialog(false); - EXPECT_TRUE(resetter().ShouldShowResetBanner()); - VerifyExpectationsThenShutdownResetter(); -} - -TEST_F(AutomaticProfileResetterTest, PromptFollowedByIncidentalWebUIReset) { - OrchestrateThroughEvaluationFlow(); - - EXPECT_CALL(resetter(), ReportPromptResult( - AutomaticProfileResetter::PROMPT_SHOWN_BUBBLE)); - resetter().NotifyDidShowResetBubble(); - ExpectAllMementoValuesEqualTo(kTestMementoValue); - testing::Mock::VerifyAndClearExpectations(&resetter()); - - // Missing NotifyDidOpenWebUIResetDialog(). - // This can arise if a settings page was already opened at the time the prompt - // was triggered, and this already opened dialog was used to initiate a reset - // after having dismissed the prompt. - - EXPECT_CALL(mock_delegate(), DismissPrompt()); - EXPECT_CALL(resetter(), ReportPromptResult( - AutomaticProfileResetter::PROMPT_FOLLOWED_BY_WEBUI_RESET)); - resetter().NotifyDidCloseWebUIResetDialog(true); - EXPECT_TRUE(resetter().ShouldShowResetBanner()); - VerifyExpectationsThenShutdownResetter(); -} - -TEST_F(AutomaticProfileResetterTest, PromptSuppressedButHadWebUIReset) { - OrchestrateThroughEvaluationFlow(); - - EXPECT_CALL(mock_delegate(), DismissPrompt()); - resetter().NotifyDidOpenWebUIResetDialog(); - testing::Mock::VerifyAndClearExpectations(&mock_delegate()); - - EXPECT_CALL(resetter(), ReportPromptResult( - AutomaticProfileResetter::PROMPT_NOT_SHOWN_BUBBLE_BUT_HAD_WEBUI_RESET)); - resetter().NotifyDidCloseWebUIResetDialog(true); - ExpectAllMementoValuesEqualTo(kTestMementoValue); - EXPECT_TRUE(resetter().ShouldShowResetBanner()); - VerifyExpectationsThenShutdownResetter(); -} - -TEST_F(AutomaticProfileResetterTest, PromptSuppressedButHadWebUINoReset) { - OrchestrateThroughEvaluationFlow(); - - EXPECT_CALL(mock_delegate(), DismissPrompt()); - resetter().NotifyDidOpenWebUIResetDialog(); - testing::Mock::VerifyAndClearExpectations(&mock_delegate()); - - EXPECT_CALL(resetter(), ReportPromptResult(AutomaticProfileResetter:: - PROMPT_NOT_SHOWN_BUBBLE_BUT_HAD_WEBUI_NO_RESET)); - resetter().NotifyDidCloseWebUIResetDialog(false); - ExpectAllMementoValuesEqualTo(kTestMementoValue); - EXPECT_TRUE(resetter().ShouldShowResetBanner()); - VerifyExpectationsThenShutdownResetter(); -} - -TEST_F(AutomaticProfileResetterTest, BannerDismissed) { - OrchestrateThroughEvaluationFlow(); - - EXPECT_CALL(resetter(), ReportPromptResult( - AutomaticProfileResetter::PROMPT_SHOWN_BUBBLE)); - resetter().NotifyDidShowResetBubble(); - ExpectAllMementoValuesEqualTo(kTestMementoValue); - testing::Mock::VerifyAndClearExpectations(&resetter()); - - resetter().NotifyDidCloseWebUIResetBanner(); - - EXPECT_TRUE(resetter().IsResetPromptFlowActive()); - EXPECT_FALSE(resetter().ShouldShowResetBanner()); - - // Note: we use strict mocks, so this also checks the bubble is not closed. - VerifyExpectationsThenShutdownResetter(); -} - -TEST_F(AutomaticProfileResetterTest, BannerDismissedWhilePromptSuppressed) { - OrchestrateThroughEvaluationFlow(); - - resetter().NotifyDidCloseWebUIResetBanner(); - - EXPECT_TRUE(resetter().IsResetPromptFlowActive()); - EXPECT_FALSE(resetter().ShouldShowResetBanner()); - VerifyExpectationsThenShutdownResetter(); - - ExpectAllMementoValuesEqualTo(std::string()); -} - -// Please see comments above ConstructProgramToCheckPreferences() to understand -// how the following tests work. - -TEST_F(AutomaticProfileResetterTest, InputUserPreferencesCorrect) { - SetTestingProgram(ConstructProgramToCheckPreferences()); - SetTestingHashSeed(kTestHashSeed); - - PrefService* prefs = profile()->GetPrefs(); - prefs->SetString(kTestPreferencePath, kTestPreferenceValue); - - mock_delegate().ExpectCallsToDependenciesSetUpMethods(); - mock_delegate().ExpectCallsToGetterMethods(); - uint32 expected_mask = HAS_EXPECTED_USER_PREFERENCE | - USER_PREFERENCE_IS_USER_CONTROLLED; - EXPECT_CALL(resetter(), ReportStatistics(0x00u, expected_mask)); - - UnleashResetterAndWait(); -} - -TEST_F(AutomaticProfileResetterTest, InputLocalStateCorrect) { - SetTestingProgram(ConstructProgramToCheckPreferences()); - SetTestingHashSeed(kTestHashSeed); - - PrefService* prefs = local_state(); - prefs->SetString(kTestPreferencePath, kTestPreferenceValue); - - mock_delegate().ExpectCallsToDependenciesSetUpMethods(); - mock_delegate().ExpectCallsToGetterMethods(); - uint32 expected_mask = HAS_EXPECTED_LOCAL_STATE_PREFERENCE | - LOCAL_STATE_IS_USER_CONTROLLED; - EXPECT_CALL(resetter(), ReportStatistics(0x00u, expected_mask)); - - UnleashResetterAndWait(); -} - -TEST_F(AutomaticProfileResetterTest, InputManagedUserPreferencesCorrect) { - SetTestingProgram(ConstructProgramToCheckPreferences()); - SetTestingHashSeed(kTestHashSeed); - - syncable_prefs::TestingPrefServiceSyncable* prefs = - profile()->GetTestingPrefService(); - prefs->SetManagedPref(kTestPreferencePath, - new base::StringValue(kTestPreferenceValue)); - - mock_delegate().ExpectCallsToDependenciesSetUpMethods(); - mock_delegate().ExpectCallsToGetterMethods(); - uint32 expected_mask = HAS_EXPECTED_USER_PREFERENCE; - EXPECT_CALL(resetter(), ReportStatistics(0x00u, expected_mask)); - - UnleashResetterAndWait(); -} - -TEST_F(AutomaticProfileResetterTest, InputManagedLocalStateCorrect) { - SetTestingProgram(ConstructProgramToCheckPreferences()); - SetTestingHashSeed(kTestHashSeed); - - TestingPrefServiceSimple* prefs = local_state(); - prefs->SetManagedPref(kTestPreferencePath, - new base::StringValue(kTestPreferenceValue)); - - mock_delegate().ExpectCallsToDependenciesSetUpMethods(); - mock_delegate().ExpectCallsToGetterMethods(); - uint32 expected_mask = HAS_EXPECTED_LOCAL_STATE_PREFERENCE; - EXPECT_CALL(resetter(), ReportStatistics(0x00u, expected_mask)); - - UnleashResetterAndWait(); -} - -// Please see comments above ConstructProgramToCheckSearchEngines() to -// understand how the following tests work. - -TEST_F(AutomaticProfileResetterTest, InputDefaultSearchProviderCorrect) { - SetTestingProgram(ConstructProgramToCheckSearchEngines()); - SetTestingHashSeed(kTestHashSeed); - - mock_delegate().emulated_default_search_provider_details().SetString( - kSearchURLAttributeKey, kTestSearchURL); - - mock_delegate().ExpectCallsToDependenciesSetUpMethods(); - mock_delegate().ExpectCallsToGetterMethods(); - uint32 expected_mask = HAS_EXPECTED_DEFAULT_SEARCH_PROVIDER | - DEFAULT_SEARCH_PROVIDER_IS_USER_CONTROLLED; - EXPECT_CALL(resetter(), ReportStatistics(0x00u, expected_mask)); - - UnleashResetterAndWait(); -} - -TEST_F(AutomaticProfileResetterTest, InputSearchProviderManagedCorrect) { - SetTestingProgram(ConstructProgramToCheckSearchEngines()); - SetTestingHashSeed(kTestHashSeed); - - mock_delegate().emulated_default_search_provider_details().SetString( - kSearchURLAttributeKey, kTestSearchURL); - mock_delegate().set_emulated_is_default_search_provider_managed(true); - - mock_delegate().ExpectCallsToDependenciesSetUpMethods(); - mock_delegate().ExpectCallsToGetterMethods(); - uint32 expected_mask = HAS_EXPECTED_DEFAULT_SEARCH_PROVIDER; - EXPECT_CALL(resetter(), ReportStatistics(0x00u, expected_mask)); - - UnleashResetterAndWait(); -} - -TEST_F(AutomaticProfileResetterTest, InputSearchProvidersCorrect) { - SetTestingProgram(ConstructProgramToCheckSearchEngines()); - SetTestingHashSeed(kTestHashSeed); - - base::DictionaryValue* search_provider_1 = new base::DictionaryValue; - base::DictionaryValue* search_provider_2 = new base::DictionaryValue; - search_provider_1->SetString(kSearchURLAttributeKey, kTestSearchURL); - search_provider_2->SetString(kSearchURLAttributeKey, kTestSearchURL2); - mock_delegate().emulated_search_providers_details().Append(search_provider_1); - mock_delegate().emulated_search_providers_details().Append(search_provider_2); - - mock_delegate().ExpectCallsToDependenciesSetUpMethods(); - mock_delegate().ExpectCallsToGetterMethods(); - uint32 expected_mask = DEFAULT_SEARCH_PROVIDER_IS_USER_CONTROLLED | - HAS_EXPECTED_PREPOPULATED_SEARCH_PROVIDER_1 | - HAS_EXPECTED_PREPOPULATED_SEARCH_PROVIDER_2; - EXPECT_CALL(resetter(), ReportStatistics(0x00u, expected_mask)); - - UnleashResetterAndWait(); -} - -// Please see comments above ConstructProgramToCheckLoadedModuleDigests() to -// understand how the following tests work. - -TEST_F(AutomaticProfileResetterTest, InputModuleDigestsCorrect) { - SetTestingProgram(ConstructProgramToCheckLoadedModuleDigests()); - SetTestingHashSeed(kTestHashSeed); - - mock_delegate().emulated_loaded_module_digests().AppendString( - kTestModuleDigest); - mock_delegate().emulated_loaded_module_digests().AppendString( - kTestModuleDigest2); - - mock_delegate().ExpectCallsToDependenciesSetUpMethods(); - mock_delegate().ExpectCallsToGetterMethods(); - uint32 expected_mask = - HAS_EXPECTED_MODULE_DIGEST_1 | HAS_EXPECTED_MODULE_DIGEST_2; - EXPECT_CALL(resetter(), ReportStatistics(0x00u, expected_mask)); - - UnleashResetterAndWait(); -} - -} // namespace diff --git a/chrome/browser/profile_resetter/jtl_foundation.cc b/chrome/browser/profile_resetter/jtl_foundation.cc deleted file mode 100644 index a2a2007..0000000 --- a/chrome/browser/profile_resetter/jtl_foundation.cc +++ /dev/null @@ -1,48 +0,0 @@ -// Copyright 2013 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 "chrome/browser/profile_resetter/jtl_foundation.h" - -#include "base/logging.h" -#include "base/strings/string_number_conversions.h" -#include "base/strings/string_util.h" - -namespace jtl_foundation { - -Hasher::Hasher(const std::string& seed) : hmac_(crypto::HMAC::SHA256) { - if (!hmac_.Init(seed)) - NOTREACHED(); -} - -Hasher::~Hasher() {} - -std::string Hasher::GetHash(const std::string& input) const { - if (cached_hashes_.find(input) == cached_hashes_.end()) { - // Calculate value. - unsigned char digest[kHashSizeInBytes]; - if (!hmac_.Sign(input, digest, arraysize(digest))) { - NOTREACHED(); - return std::string(); - } - // Instead of using the full SHA256, we only use the hex encoding of the - // first 16 bytes. - cached_hashes_[input] = base::HexEncode(digest, kHashSizeInBytes / 2); - DCHECK_EQ(kHashSizeInBytes, cached_hashes_[input].size()); - } - return cached_hashes_[input]; -} - -// static -bool Hasher::IsHash(const std::string& maybe_hash) { - if (maybe_hash.size() != kHashSizeInBytes) - return false; - for (std::string::const_iterator it = maybe_hash.begin(); - it != maybe_hash.end(); ++it) { - if (!base::IsHexDigit(*it)) - return false; - } - return true; -} - -} // namespace jtl_foundation diff --git a/chrome/browser/profile_resetter/jtl_foundation.h b/chrome/browser/profile_resetter/jtl_foundation.h deleted file mode 100644 index cc4a5f4..0000000 --- a/chrome/browser/profile_resetter/jtl_foundation.h +++ /dev/null @@ -1,193 +0,0 @@ -// Copyright 2013 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 CHROME_BROWSER_PROFILE_RESETTER_JTL_FOUNDATION_H_ -#define CHROME_BROWSER_PROFILE_RESETTER_JTL_FOUNDATION_H_ - -#include <map> -#include <string> - -#include "base/basictypes.h" -#include "crypto/hmac.h" - -namespace jtl_foundation { - -// A JTL (JSON Traversal Language) program is composed of one or more -// sentences. Each sentence consists of a sequence of operations. The input of -// the program is a hierarchical JSON data structure. -// -// The execution of each sentence starts at the root of an input dictionary. The -// operations include navigation in the JSON data structure, as well as -// comparing the current (leaf) node to fixed values. The program also has a -// separate dictionary as working memory, into which it can memorize data, then -// later recall it for comparisons. -// -// Example program: -// NAVIGATE_ANY -// NAVIGATE(hash("bar")) -// COMPARE_NODE_BOOL(1) -// STORE_BOOL(hash("found_foo"), 1) -// STOP_EXECUTING_SENTENCE -// -// Example input: -// { -// 'key1': 1, -// 'key2': {'foo': 0, 'bar': false, 'baz': 2} -// 'key3': {'foo': 0, 'bar': true, 'baz': 2} -// 'key4': {'foo': 0, 'bar': true, 'baz': 2} -// } -// -// This program navigates from the root of the dictionary to all children -// ("key1", "key2", "key3", "key4") and executes the remaining program on each -// of the children. The navigation happens in depth-first pre-order. On each of -// the children it tries to navigate into the child "bar", which fails for -// "key1", so execution stops for this sub-branch. On key2 the program navigates -// to "bar" and moves the execution context to this node which has the value -// "false". Therefore, the following COMPARE_NODE_BOOL is not fulfilled and the -// execution does not continue on this branch, so we back track and proceed with -// "key3" and its "bar" child. For this node, COMPARE_NODE_BOOL is fulfilled and -// the execution continues to store "found_foo = true" into the working memory -// of the interpreter. Next the interpreter executes STOP_EXECUTING_SENTENCE -// which prevents the traversal from descending into the "key4" branch from the -// NAVIGATE_ANY operation and can therefore speedup the processing. -// -// All node names, and node values of type string, integer and double are hashed -// before being compared to hash values listed in |program|. - -// JTL byte code consists of uint8 opcodes followed by parameters. Parameters -// are either boolean (uint8 with value \x00 or \x01), uint32 (in little-endian -// notation), or hash string of 32 bytes. -// The following opcodes are defined: -enum OpCodes { - // Continues execution with the next operation on the element of a - // dictionary that matches the passed key parameter. If no such element - // exists, the command execution returns from the current instruction. - // Parameters: - // - a 32 byte hash of the target dictionary key. - NAVIGATE = 0x00, - // Continues execution with the next operation on each element of a - // dictionary or list. If no such element exists or the current element is - // neither a dictionary or list, the command execution returns from the - // current instruction. - NAVIGATE_ANY = 0x01, - // Continues execution with the next operation on the parent node of the - // current node. If the current node is the root of the input dictionary, the - // program execution fails with a runtime error. - NAVIGATE_BACK = 0x02, - // Stores a boolean value in the working memory. - // Parameters: - // - a 32 byte hash of the parameter name, - // - the value to store (\x00 or \x01) - STORE_BOOL = 0x10, - // Checks whether a boolean stored in working memory matches the expected - // value and continues execution with the next operation in case of a match. - // Parameters: - // - a 32 byte hash of the parameter name, - // - the expected value (\x00 or \x01), - // - the default value in case the working memory contains no corresponding - // entry (\x00 or\x01). - COMPARE_STORED_BOOL = 0x11, - // Same as STORE_BOOL but takes a hash instead of a boolean value as - // parameter. - STORE_HASH = 0x12, - // Same as COMPARE_STORED_BOOL but takes a hash instead of two boolean values - // as parameters. - COMPARE_STORED_HASH = 0x13, - // Stores the current node into the working memory. If the current node is not - // a boolean value, the program execution returns from the current - // instruction. - // Parameters: - // - a 32 byte hash of the parameter name. - STORE_NODE_BOOL = 0x14, - // Stores the hashed value of the current node into the working memory. If - // the current node is not a string, integer or double, the program execution - // returns from the current instruction. - // Parameters: - // - a 32 byte hash of the parameter name. - STORE_NODE_HASH = 0x15, - // Parses the value of the current node as a URL, extracts the subcomponent of - // the domain name that is immediately below the registrar-controlled portion, - // and stores the hash of this subcomponent into working memory. In case the - // domain name ends in a suffix not on the Public Suffix List (i.e. is neither - // an ICANN, nor a private domain suffix), the last subcomponent is assumed to - // be the registry, and the second-to-last subcomponent is extracted. - // If the current node is not a string that represents a URL, or if this URL - // does not have a domain component as described above, the program execution - // returns from the current instruction. - // For example, "foo.com", "www.foo.co.uk", "foo.appspot.com", and "foo.bar" - // will all yield (the hash of) "foo" as a result. - // See the unit test for more details. - // Parameters: - // - a 32 byte hash of the parameter name. - STORE_NODE_REGISTERABLE_DOMAIN_HASH = 0x16, - // Compares the current node against a boolean value and continues execution - // with the next operation in case of a match. If the current node does not - // match or is not a boolean value, the program execution returns from the - // current instruction. - // Parameters: - // - a boolean value (\x00 or \x01). - COMPARE_NODE_BOOL = 0x20, - // Compares the hashed value of the current node against the given hash, and - // continues execution with the next operation in case of a match. If the - // current node is not a string, integer or double, or if it is either, but - // its hash does not match, the program execution returns from the current - // instruction. - // Parameters: - // - a 32 byte hash of the expected value. - COMPARE_NODE_HASH = 0x21, - // The negation of the above. - COMPARE_NODE_HASH_NOT = 0x22, - // Compares the current node against a boolean value stored in working memory, - // and continues with the next operation in case of a match. If the current - // node is not a boolean value, the working memory contains no corresponding - // boolean value, or if they do not match, the program execution returns from - // the current instruction. - // Parameters: - // - a 32 byte hash of the parameter name. - COMPARE_NODE_TO_STORED_BOOL = 0x23, - // Compares the hashed value of the current node against a hash value stored - // in working memory, and continues with the next operation in case of a - // match. If the current node is not a string, integer or double, or if the - // working memory contains no corresponding hash string, or if the hashes do - // not match, the program execution returns from the current instruction. - // Parameters: - // - a 32 byte hash of the parameter name. - COMPARE_NODE_TO_STORED_HASH = 0x24, - // Checks whether the current node is a string value that contains the given - // pattern as a substring, and continues execution with the next operation in - // case it does. If the current node is not a string, or if does not match the - // pattern, the program execution returns from the current instruction. - // Parameters: - // - a 32 byte hash of the pattern, - // - a 4 byte unsigned integer: the length (>0) of the pattern in bytes, - // - a 4 byte unsigned integer: the sum of all bytes in the pattern, serving - // as a heuristic to reduce the number of actual SHA-256 calculations. - COMPARE_NODE_SUBSTRING = 0x25, - // Stop execution in this specific sentence. - STOP_EXECUTING_SENTENCE = 0x30, - // Separator between sentences, starts a new sentence. - END_OF_SENTENCE = 0x31 -}; - -const size_t kHashSizeInBytes = 32u; - -// A class that provides SHA256 hash values for strings using a fixed hash seed. -class Hasher { - public: - explicit Hasher(const std::string& seed); - ~Hasher(); - - std::string GetHash(const std::string& input) const; - - static bool IsHash(const std::string& maybe_hash); - - private: - crypto::HMAC hmac_; - mutable std::map<std::string, std::string> cached_hashes_; - DISALLOW_COPY_AND_ASSIGN(Hasher); -}; - -} // namespace jtl_foundation - -#endif // CHROME_BROWSER_PROFILE_RESETTER_JTL_FOUNDATION_H_ diff --git a/chrome/browser/profile_resetter/jtl_instructions.h b/chrome/browser/profile_resetter/jtl_instructions.h deleted file mode 100644 index 76b57a6..0000000 --- a/chrome/browser/profile_resetter/jtl_instructions.h +++ /dev/null @@ -1,38 +0,0 @@ -// Copyright 2013 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 CHROME_BROWSER_PROFILE_RESETTER_JTL_INSTRUCTIONS_H_ -#define CHROME_BROWSER_PROFILE_RESETTER_JTL_INSTRUCTIONS_H_ - -#include <string> - -// These are instructions to generate binary code for JTL programs. - -#define VALUE_FALSE std::string(1, '\x00') -#define VALUE_TRUE std::string(1, '\x01') - -#define OP_NAVIGATE(key) std::string(1, '\x00') + key -#define OP_NAVIGATE_ANY std::string(1, '\x01') -#define OP_NAVIGATE_BACK std::string(1, '\x02') -#define OP_STORE_BOOL(name, value) std::string(1, '\x10') + name + value -#define OP_COMPARE_STORED_BOOL(name, value, default_value) \ - std::string(1, '\x11') + name + value + default_value -#define OP_STORE_HASH(name, value) std::string(1, '\x12') + name + value -#define OP_COMPARE_STORED_HASH(name, value, default_value) \ - std::string(1, '\x13') + name + value + default_value -#define OP_STORE_NODE_BOOL(name) std::string(1, '\x14') + name -#define OP_STORE_NODE_HASH(name) std::string(1, '\x15') + name -#define OP_STORE_NODE_REGISTERABLE_DOMAIN_HASH(name) \ - std::string(1, '\x16') + name -#define OP_COMPARE_NODE_BOOL(value) std::string(1, '\x20') + value -#define OP_COMPARE_NODE_HASH(value) std::string(1, '\x21') + value -#define OP_COMPARE_NODE_HASH_NOT(value) std::string(1, '\x22') + value -#define OP_COMPARE_NODE_TO_STORED_BOOL(name) std::string(1, '\x23') + name -#define OP_COMPARE_NODE_TO_STORED_HASH(name) std::string(1, '\x24') + name -#define OP_COMPARE_NODE_SUBSTRING(pattern, pattern_length, pattern_sum) \ - std::string(1, '\x25') + pattern + pattern_length + pattern_sum -#define OP_STOP_EXECUTING_SENTENCE std::string(1, '\x30') -#define OP_END_OF_SENTENCE std::string(1, '\x31') - -#endif // CHROME_BROWSER_PROFILE_RESETTER_JTL_INSTRUCTIONS_H_ diff --git a/chrome/browser/profile_resetter/jtl_interpreter.cc b/chrome/browser/profile_resetter/jtl_interpreter.cc deleted file mode 100644 index be0b368..0000000 --- a/chrome/browser/profile_resetter/jtl_interpreter.cc +++ /dev/null @@ -1,746 +0,0 @@ -// Copyright 2013 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 "chrome/browser/profile_resetter/jtl_interpreter.h" - -#include <numeric> - -#include "base/memory/scoped_vector.h" -#include "base/strings/string_number_conversions.h" -#include "base/strings/string_util.h" -#include "chrome/browser/profile_resetter/jtl_foundation.h" -#include "crypto/hmac.h" -#include "crypto/sha2.h" -#include "net/base/registry_controlled_domains/registry_controlled_domain.h" -#include "url/gurl.h" - -namespace { - -class ExecutionContext; - -// An operation in an interpreted program. -class Operation { - public: - virtual ~Operation() {} - // Executes the operation on the specified context and instructs the context - // to continue execution with the next instruction if appropriate. - // Returns true if we should continue with any potential backtracking that - // needs to be done. - virtual bool Execute(ExecutionContext* context) = 0; -}; - -// An execution context of operations. -class ExecutionContext { - public: - // |input| is the root of a dictionary that stores the information the - // sentence is evaluated on. - ExecutionContext(const jtl_foundation::Hasher* hasher, - const std::vector<Operation*>& sentence, - const base::DictionaryValue* input, - base::DictionaryValue* working_memory) - : hasher_(hasher), - sentence_(sentence), - next_instruction_index_(0u), - working_memory_(working_memory), - error_(false) { - stack_.push_back(input); - } - ~ExecutionContext() {} - - // Returns true in case of success. - bool ContinueExecution() { - if (error_ || stack_.empty()) { - error_ = true; - return false; - } - if (next_instruction_index_ >= sentence_.size()) - return true; - - Operation* op = sentence_[next_instruction_index_]; - next_instruction_index_++; - bool continue_traversal = op->Execute(this); - next_instruction_index_--; - return continue_traversal; - } - - std::string GetHash(const std::string& input) { - return hasher_->GetHash(input); - } - - // Calculates the |hash| of a string, integer or double |value|, and returns - // true. Returns false otherwise. - bool GetValueHash(const base::Value& value, std::string* hash) { - DCHECK(hash); - std::string value_as_string; - int tmp_int = 0; - double tmp_double = 0.0; - if (value.GetAsInteger(&tmp_int)) - value_as_string = base::IntToString(tmp_int); - else if (value.GetAsDouble(&tmp_double)) - value_as_string = base::DoubleToString(tmp_double); - else if (!value.GetAsString(&value_as_string)) - return false; - *hash = GetHash(value_as_string); - return true; - } - - const base::Value* current_node() const { return stack_.back(); } - std::vector<const base::Value*>* stack() { return &stack_; } - base::DictionaryValue* working_memory() { return working_memory_; } - bool error() const { return error_; } - - private: - // A hasher used to hash node names in a dictionary. - const jtl_foundation::Hasher* hasher_; - // The sentence to be executed. - const std::vector<Operation*> sentence_; - // Position in |sentence_|. - size_t next_instruction_index_; - // A stack of Values, indicating a navigation path from the root node of - // |input| (see constructor) to the current node on which the - // sentence_[next_instruction_index_] is evaluated. - std::vector<const base::Value*> stack_; - // Memory into which values can be stored by the program. - base::DictionaryValue* working_memory_; - // Whether a runtime error occurred. - bool error_; - DISALLOW_COPY_AND_ASSIGN(ExecutionContext); -}; - -class NavigateOperation : public Operation { - public: - explicit NavigateOperation(const std::string& hashed_key) - : hashed_key_(hashed_key) {} - ~NavigateOperation() override {} - bool Execute(ExecutionContext* context) override { - const base::DictionaryValue* dict = NULL; - if (!context->current_node()->GetAsDictionary(&dict)) { - // Just ignore this node gracefully as this navigation is a dead end. - // If this NavigateOperation occurred after a NavigateAny operation, those - // may still be fulfillable, so we allow continuing the execution of the - // sentence on other nodes. - return true; - } - for (base::DictionaryValue::Iterator i(*dict); !i.IsAtEnd(); i.Advance()) { - if (context->GetHash(i.key()) != hashed_key_) - continue; - context->stack()->push_back(&i.value()); - bool continue_traversal = context->ContinueExecution(); - context->stack()->pop_back(); - if (!continue_traversal) - return false; - } - return true; - } - - private: - std::string hashed_key_; - DISALLOW_COPY_AND_ASSIGN(NavigateOperation); -}; - -class NavigateAnyOperation : public Operation { - public: - NavigateAnyOperation() {} - ~NavigateAnyOperation() override {} - bool Execute(ExecutionContext* context) override { - const base::DictionaryValue* dict = NULL; - const base::ListValue* list = NULL; - if (context->current_node()->GetAsDictionary(&dict)) { - for (base::DictionaryValue::Iterator i(*dict); - !i.IsAtEnd(); i.Advance()) { - context->stack()->push_back(&i.value()); - bool continue_traversal = context->ContinueExecution(); - context->stack()->pop_back(); - if (!continue_traversal) - return false; - } - } else if (context->current_node()->GetAsList(&list)) { - for (base::ListValue::const_iterator i = list->begin(); - i != list->end(); ++i) { - context->stack()->push_back(*i); - bool continue_traversal = context->ContinueExecution(); - context->stack()->pop_back(); - if (!continue_traversal) - return false; - } - } else { - // Do nothing, just ignore this node. - } - return true; - } - - private: - DISALLOW_COPY_AND_ASSIGN(NavigateAnyOperation); -}; - -class NavigateBackOperation : public Operation { - public: - NavigateBackOperation() {} - ~NavigateBackOperation() override {} - bool Execute(ExecutionContext* context) override { - const base::Value* current_node = context->current_node(); - context->stack()->pop_back(); - bool continue_traversal = context->ContinueExecution(); - context->stack()->push_back(current_node); - return continue_traversal; - } - - private: - DISALLOW_COPY_AND_ASSIGN(NavigateBackOperation); -}; - -class StoreValue : public Operation { - public: - StoreValue(const std::string& hashed_name, scoped_ptr<base::Value> value) - : hashed_name_(hashed_name), - value_(value.Pass()) { - DCHECK(base::IsStringUTF8(hashed_name)); - DCHECK(value_); - } - ~StoreValue() override {} - bool Execute(ExecutionContext* context) override { - context->working_memory()->Set(hashed_name_, value_->DeepCopy()); - return context->ContinueExecution(); - } - - private: - std::string hashed_name_; - scoped_ptr<base::Value> value_; - DISALLOW_COPY_AND_ASSIGN(StoreValue); -}; - -class CompareStoredValue : public Operation { - public: - CompareStoredValue(const std::string& hashed_name, - scoped_ptr<base::Value> value, - scoped_ptr<base::Value> default_value) - : hashed_name_(hashed_name), - value_(value.Pass()), - default_value_(default_value.Pass()) { - DCHECK(base::IsStringUTF8(hashed_name)); - DCHECK(value_); - DCHECK(default_value_); - } - ~CompareStoredValue() override {} - bool Execute(ExecutionContext* context) override { - const base::Value* actual_value = NULL; - if (!context->working_memory()->Get(hashed_name_, &actual_value)) - actual_value = default_value_.get(); - if (!value_->Equals(actual_value)) - return true; - return context->ContinueExecution(); - } - - private: - std::string hashed_name_; - scoped_ptr<base::Value> value_; - scoped_ptr<base::Value> default_value_; - DISALLOW_COPY_AND_ASSIGN(CompareStoredValue); -}; - -template<bool ExpectedTypeIsBooleanNotHashable> -class StoreNodeValue : public Operation { - public: - explicit StoreNodeValue(const std::string& hashed_name) - : hashed_name_(hashed_name) { - DCHECK(base::IsStringUTF8(hashed_name)); - } - ~StoreNodeValue() override {} - bool Execute(ExecutionContext* context) override { - scoped_ptr<base::Value> value; - if (ExpectedTypeIsBooleanNotHashable) { - if (!context->current_node()->IsType(base::Value::TYPE_BOOLEAN)) - return true; - value.reset(context->current_node()->DeepCopy()); - } else { - std::string hash; - if (!context->GetValueHash(*context->current_node(), &hash)) - return true; - value.reset(new base::StringValue(hash)); - } - context->working_memory()->Set(hashed_name_, value.release()); - return context->ContinueExecution(); - } - - private: - std::string hashed_name_; - DISALLOW_COPY_AND_ASSIGN(StoreNodeValue); -}; - -// Stores the hash of the registerable domain name -- as in, the portion of the -// domain that is registerable, as opposed to controlled by a registrar; without -// subdomains -- of the URL represented by the current node into working memory. -class StoreNodeRegisterableDomain : public Operation { - public: - explicit StoreNodeRegisterableDomain(const std::string& hashed_name) - : hashed_name_(hashed_name) { - DCHECK(base::IsStringUTF8(hashed_name)); - } - ~StoreNodeRegisterableDomain() override {} - bool Execute(ExecutionContext* context) override { - std::string possibly_invalid_url; - std::string domain; - if (!context->current_node()->GetAsString(&possibly_invalid_url) || - !GetRegisterableDomain(possibly_invalid_url, &domain)) - return true; - context->working_memory()->Set( - hashed_name_, new base::StringValue(context->GetHash(domain))); - return context->ContinueExecution(); - } - - private: - // If |possibly_invalid_url| is a valid URL having a registerable domain name - // part, outputs that in |registerable_domain| and returns true. Otherwise, - // returns false. - static bool GetRegisterableDomain(const std::string& possibly_invalid_url, - std::string* registerable_domain) { - namespace domains = net::registry_controlled_domains; - DCHECK(registerable_domain); - GURL url(possibly_invalid_url); - if (!url.is_valid()) - return false; - std::string registry_plus_one = domains::GetDomainAndRegistry( - url.host(), domains::INCLUDE_PRIVATE_REGISTRIES); - size_t registry_length = domains::GetRegistryLength( - url.host(), - domains::INCLUDE_UNKNOWN_REGISTRIES, - domains::INCLUDE_PRIVATE_REGISTRIES); - // Fail unless (1.) the URL has a host part; and (2.) that host part is a - // well-formed domain name consisting of at least one subcomponent; followed - // by either a recognized registry identifier, or exactly one subcomponent, - // which is then assumed to be the unknown registry identifier. - if (registry_length == std::string::npos || registry_length == 0) - return false; - DCHECK_LT(registry_length, registry_plus_one.size()); - // Subtract one to cut off the dot separating the SLD and the registry. - registerable_domain->assign( - registry_plus_one, 0, registry_plus_one.size() - registry_length - 1); - return true; - } - - std::string hashed_name_; - DISALLOW_COPY_AND_ASSIGN(StoreNodeRegisterableDomain); -}; - -class CompareNodeBool : public Operation { - public: - explicit CompareNodeBool(bool value) : value_(value) {} - ~CompareNodeBool() override {} - bool Execute(ExecutionContext* context) override { - bool actual_value = false; - if (!context->current_node()->GetAsBoolean(&actual_value)) - return true; - if (actual_value != value_) - return true; - return context->ContinueExecution(); - } - - private: - bool value_; - DISALLOW_COPY_AND_ASSIGN(CompareNodeBool); -}; - -class CompareNodeHash : public Operation { - public: - explicit CompareNodeHash(const std::string& hashed_value) - : hashed_value_(hashed_value) {} - ~CompareNodeHash() override {} - bool Execute(ExecutionContext* context) override { - std::string actual_hash; - if (!context->GetValueHash(*context->current_node(), &actual_hash) || - actual_hash != hashed_value_) - return true; - return context->ContinueExecution(); - } - - private: - std::string hashed_value_; - DISALLOW_COPY_AND_ASSIGN(CompareNodeHash); -}; - -class CompareNodeHashNot : public Operation { - public: - explicit CompareNodeHashNot(const std::string& hashed_value) - : hashed_value_(hashed_value) {} - ~CompareNodeHashNot() override {} - bool Execute(ExecutionContext* context) override { - std::string actual_hash; - if (context->GetValueHash(*context->current_node(), &actual_hash) && - actual_hash == hashed_value_) - return true; - return context->ContinueExecution(); - } - - private: - std::string hashed_value_; - DISALLOW_COPY_AND_ASSIGN(CompareNodeHashNot); -}; - -template<bool ExpectedTypeIsBooleanNotHashable> -class CompareNodeToStored : public Operation { - public: - explicit CompareNodeToStored(const std::string& hashed_name) - : hashed_name_(hashed_name) {} - ~CompareNodeToStored() override {} - bool Execute(ExecutionContext* context) override { - const base::Value* stored_value = NULL; - if (!context->working_memory()->Get(hashed_name_, &stored_value)) - return true; - if (ExpectedTypeIsBooleanNotHashable) { - if (!context->current_node()->IsType(base::Value::TYPE_BOOLEAN) || - !context->current_node()->Equals(stored_value)) - return true; - } else { - std::string actual_hash; - std::string stored_hash; - if (!context->GetValueHash(*context->current_node(), &actual_hash) || - !stored_value->GetAsString(&stored_hash) || - actual_hash != stored_hash) - return true; - } - return context->ContinueExecution(); - } - - private: - std::string hashed_name_; - DISALLOW_COPY_AND_ASSIGN(CompareNodeToStored); -}; - -class CompareNodeSubstring : public Operation { - public: - explicit CompareNodeSubstring(const std::string& hashed_pattern, - size_t pattern_length, - uint32 pattern_sum) - : hashed_pattern_(hashed_pattern), - pattern_length_(pattern_length), - pattern_sum_(pattern_sum) { - DCHECK(pattern_length_); - } - ~CompareNodeSubstring() override {} - bool Execute(ExecutionContext* context) override { - std::string value_as_string; - if (!context->current_node()->GetAsString(&value_as_string) || - !pattern_length_ || value_as_string.size() < pattern_length_) - return true; - // Go over the string with a sliding window. Meanwhile, maintain the sum in - // an incremental fashion, and only calculate the SHA-256 hash when the sum - // checks out so as to improve performance. - std::string::const_iterator window_begin = value_as_string.begin(); - std::string::const_iterator window_end = window_begin + pattern_length_ - 1; - uint32 window_sum = - std::accumulate(window_begin, window_end, static_cast<uint32>(0u)); - while (window_end != value_as_string.end()) { - window_sum += *window_end++; - if (window_sum == pattern_sum_ && context->GetHash(std::string( - window_begin, window_end)) == hashed_pattern_) - return context->ContinueExecution(); - window_sum -= *window_begin++; - } - return true; - } - - private: - std::string hashed_pattern_; - size_t pattern_length_; - uint32 pattern_sum_; - DISALLOW_COPY_AND_ASSIGN(CompareNodeSubstring); -}; - -class StopExecutingSentenceOperation : public Operation { - public: - StopExecutingSentenceOperation() {} - ~StopExecutingSentenceOperation() override {} - bool Execute(ExecutionContext* context) override { return false; } - - private: - DISALLOW_COPY_AND_ASSIGN(StopExecutingSentenceOperation); -}; - -class Parser { - public: - explicit Parser(const std::string& program) - : program_(program), - next_instruction_index_(0u) {} - ~Parser() {} - bool ParseNextSentence(ScopedVector<Operation>* output) { - ScopedVector<Operation> operators; - bool sentence_ended = false; - while (next_instruction_index_ < program_.size() && !sentence_ended) { - uint8 op_code = 0; - if (!ReadOpCode(&op_code)) - return false; - switch (static_cast<jtl_foundation::OpCodes>(op_code)) { - case jtl_foundation::NAVIGATE: { - std::string hashed_key; - if (!ReadHash(&hashed_key)) - return false; - operators.push_back(new NavigateOperation(hashed_key)); - break; - } - case jtl_foundation::NAVIGATE_ANY: - operators.push_back(new NavigateAnyOperation); - break; - case jtl_foundation::NAVIGATE_BACK: - operators.push_back(new NavigateBackOperation); - break; - case jtl_foundation::STORE_BOOL: { - std::string hashed_name; - if (!ReadHash(&hashed_name) || !base::IsStringUTF8(hashed_name)) - return false; - bool value = false; - if (!ReadBool(&value)) - return false; - operators.push_back(new StoreValue( - hashed_name, - scoped_ptr<base::Value>(new base::FundamentalValue(value)))); - break; - } - case jtl_foundation::COMPARE_STORED_BOOL: { - std::string hashed_name; - if (!ReadHash(&hashed_name) || !base::IsStringUTF8(hashed_name)) - return false; - bool value = false; - if (!ReadBool(&value)) - return false; - bool default_value = false; - if (!ReadBool(&default_value)) - return false; - operators.push_back(new CompareStoredValue( - hashed_name, - scoped_ptr<base::Value>(new base::FundamentalValue(value)), - scoped_ptr<base::Value>( - new base::FundamentalValue(default_value)))); - break; - } - case jtl_foundation::STORE_HASH: { - std::string hashed_name; - if (!ReadHash(&hashed_name) || !base::IsStringUTF8(hashed_name)) - return false; - std::string hashed_value; - if (!ReadHash(&hashed_value)) - return false; - operators.push_back(new StoreValue( - hashed_name, - scoped_ptr<base::Value>(new base::StringValue(hashed_value)))); - break; - } - case jtl_foundation::COMPARE_STORED_HASH: { - std::string hashed_name; - if (!ReadHash(&hashed_name) || !base::IsStringUTF8(hashed_name)) - return false; - std::string hashed_value; - if (!ReadHash(&hashed_value)) - return false; - std::string hashed_default_value; - if (!ReadHash(&hashed_default_value)) - return false; - operators.push_back(new CompareStoredValue( - hashed_name, - scoped_ptr<base::Value>(new base::StringValue(hashed_value)), - scoped_ptr<base::Value>( - new base::StringValue(hashed_default_value)))); - break; - } - case jtl_foundation::STORE_NODE_BOOL: { - std::string hashed_name; - if (!ReadHash(&hashed_name) || !base::IsStringUTF8(hashed_name)) - return false; - operators.push_back(new StoreNodeValue<true>(hashed_name)); - break; - } - case jtl_foundation::STORE_NODE_HASH: { - std::string hashed_name; - if (!ReadHash(&hashed_name) || !base::IsStringUTF8(hashed_name)) - return false; - operators.push_back(new StoreNodeValue<false>(hashed_name)); - break; - } - case jtl_foundation::STORE_NODE_REGISTERABLE_DOMAIN_HASH: { - std::string hashed_name; - if (!ReadHash(&hashed_name) || !base::IsStringUTF8(hashed_name)) - return false; - operators.push_back(new StoreNodeRegisterableDomain(hashed_name)); - break; - } - case jtl_foundation::COMPARE_NODE_BOOL: { - bool value = false; - if (!ReadBool(&value)) - return false; - operators.push_back(new CompareNodeBool(value)); - break; - } - case jtl_foundation::COMPARE_NODE_HASH: { - std::string hashed_value; - if (!ReadHash(&hashed_value)) - return false; - operators.push_back(new CompareNodeHash(hashed_value)); - break; - } - case jtl_foundation::COMPARE_NODE_HASH_NOT: { - std::string hashed_value; - if (!ReadHash(&hashed_value)) - return false; - operators.push_back(new CompareNodeHashNot(hashed_value)); - break; - } - case jtl_foundation::COMPARE_NODE_TO_STORED_BOOL: { - std::string hashed_name; - if (!ReadHash(&hashed_name) || !base::IsStringUTF8(hashed_name)) - return false; - operators.push_back(new CompareNodeToStored<true>(hashed_name)); - break; - } - case jtl_foundation::COMPARE_NODE_TO_STORED_HASH: { - std::string hashed_name; - if (!ReadHash(&hashed_name) || !base::IsStringUTF8(hashed_name)) - return false; - operators.push_back(new CompareNodeToStored<false>(hashed_name)); - break; - } - case jtl_foundation::COMPARE_NODE_SUBSTRING: { - std::string hashed_pattern; - uint32 pattern_length = 0, pattern_sum = 0; - if (!ReadHash(&hashed_pattern)) - return false; - if (!ReadUint32(&pattern_length) || pattern_length == 0) - return false; - if (!ReadUint32(&pattern_sum)) - return false; - operators.push_back(new CompareNodeSubstring( - hashed_pattern, pattern_length, pattern_sum)); - break; - } - case jtl_foundation::STOP_EXECUTING_SENTENCE: - operators.push_back(new StopExecutingSentenceOperation); - break; - case jtl_foundation::END_OF_SENTENCE: - sentence_ended = true; - break; - default: - return false; - } - } - output->swap(operators); - return true; - } - - bool HasNextSentence() const { - return next_instruction_index_ < program_.size(); - } - - private: - // Reads an uint8 and returns whether this operation was successful. - bool ReadUint8(uint8* out) { - DCHECK(out); - if (next_instruction_index_ + 1u > program_.size()) - return false; - *out = static_cast<uint8>(program_[next_instruction_index_]); - ++next_instruction_index_; - return true; - } - - // Reads an uint32 and returns whether this operation was successful. - bool ReadUint32(uint32* out) { - DCHECK(out); - if (next_instruction_index_ + 4u > program_.size()) - return false; - *out = 0u; - for (int i = 0; i < 4; ++i) { - *out >>= 8; - *out |= static_cast<uint8>(program_[next_instruction_index_]) << 24; - ++next_instruction_index_; - } - return true; - } - - // Reads an operator code and returns whether this operation was successful. - bool ReadOpCode(uint8* out) { return ReadUint8(out); } - - bool ReadHash(std::string* out) { - DCHECK(out); - if (next_instruction_index_ + jtl_foundation::kHashSizeInBytes > - program_.size()) - return false; - *out = program_.substr(next_instruction_index_, - jtl_foundation::kHashSizeInBytes); - next_instruction_index_ += jtl_foundation::kHashSizeInBytes; - DCHECK(jtl_foundation::Hasher::IsHash(*out)); - return true; - } - - bool ReadBool(bool* out) { - DCHECK(out); - uint8 value = 0; - if (!ReadUint8(&value)) - return false; - if (value == 0) - *out = false; - else if (value == 1) - *out = true; - else - return false; - return true; - } - - std::string program_; - size_t next_instruction_index_; - DISALLOW_COPY_AND_ASSIGN(Parser); -}; - -} // namespace - -JtlInterpreter::JtlInterpreter( - const std::string& hasher_seed, - const std::string& program, - const base::DictionaryValue* input) - : hasher_seed_(hasher_seed), - program_(program), - input_(input), - working_memory_(new base::DictionaryValue), - result_(OK) { - DCHECK(input->IsType(base::Value::TYPE_DICTIONARY)); -} - -JtlInterpreter::~JtlInterpreter() {} - -void JtlInterpreter::Execute() { - jtl_foundation::Hasher hasher(hasher_seed_); - Parser parser(program_); - while (parser.HasNextSentence()) { - ScopedVector<Operation> sentence; - if (!parser.ParseNextSentence(&sentence)) { - result_ = PARSE_ERROR; - return; - } - ExecutionContext context( - &hasher, sentence.get(), input_, working_memory_.get()); - context.ContinueExecution(); - if (context.error()) { - result_ = RUNTIME_ERROR; - return; - } - } -} - -bool JtlInterpreter::GetOutputBoolean(const std::string& unhashed_key, - bool* output) const { - std::string hashed_key = - jtl_foundation::Hasher(hasher_seed_).GetHash(unhashed_key); - return working_memory_->GetBoolean(hashed_key, output); -} - -bool JtlInterpreter::GetOutputString(const std::string& unhashed_key, - std::string* output) const { - std::string hashed_key = - jtl_foundation::Hasher(hasher_seed_).GetHash(unhashed_key); - return working_memory_->GetString(hashed_key, output); -} - -int JtlInterpreter::CalculateProgramChecksum() const { - uint8 digest[3] = {}; - crypto::SHA256HashString(program_, digest, arraysize(digest)); - return static_cast<uint32>(digest[0]) << 16 | - static_cast<uint32>(digest[1]) << 8 | - static_cast<uint32>(digest[2]); -} diff --git a/chrome/browser/profile_resetter/jtl_interpreter.h b/chrome/browser/profile_resetter/jtl_interpreter.h deleted file mode 100644 index cafb7fd..0000000 --- a/chrome/browser/profile_resetter/jtl_interpreter.h +++ /dev/null @@ -1,61 +0,0 @@ -// Copyright 2013 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 CHROME_BROWSER_PROFILE_RESETTER_JTL_INTERPRETER_H_ -#define CHROME_BROWSER_PROFILE_RESETTER_JTL_INTERPRETER_H_ - -#include <string> - -#include "base/basictypes.h" -#include "base/values.h" - -// Executes a JTL program on a given dictionary. -// -// JTL (Json Traversal Language) programs are defined in jtl_foundation.h -class JtlInterpreter { - public: - enum Result { - OK, - PARSE_ERROR, - RUNTIME_ERROR, - RESULT_MAX, - }; - - // |hasher_seed| is a value used in jtl_foundation::Hasher. All node names, - // strings, integers and doubles are hashed before being compared to hash - // values listed in |program|. - // |program| is a byte array containing a JTL program. - // |input| is a dictionary on which the program is evaluated. - JtlInterpreter(const std::string& hasher_seed, - const std::string& program, - const base::DictionaryValue* input); - ~JtlInterpreter(); - - void Execute(); - - Result result() const { return result_; } - const base::DictionaryValue* working_memory() const { - return working_memory_.get(); - } - bool GetOutputBoolean(const std::string& unhashed_key, bool* output) const; - bool GetOutputString(const std::string& unhashed_key, - std::string* output) const; - - // Generates a checksum of the loaded program, defined as the first 3 bytes of - // the program's SHA-256 hash interpreted as a big-endian integer. - int CalculateProgramChecksum() const; - - private: - // Input. - std::string hasher_seed_; - std::string program_; - const base::DictionaryValue* input_; - // Output. - scoped_ptr<base::DictionaryValue> working_memory_; - Result result_; - - DISALLOW_COPY_AND_ASSIGN(JtlInterpreter); -}; - -#endif // CHROME_BROWSER_PROFILE_RESETTER_JTL_INTERPRETER_H_ diff --git a/chrome/browser/profile_resetter/jtl_interpreter_unittest.cc b/chrome/browser/profile_resetter/jtl_interpreter_unittest.cc deleted file mode 100644 index 8457264..0000000 --- a/chrome/browser/profile_resetter/jtl_interpreter_unittest.cc +++ /dev/null @@ -1,689 +0,0 @@ -// Copyright 2011 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 "chrome/browser/profile_resetter/jtl_interpreter.h" - -#include <numeric> - -#include "base/strings/string_util.h" -#include "base/test/values_test_util.h" -#include "chrome/browser/profile_resetter/jtl_foundation.h" -#include "chrome/browser/profile_resetter/jtl_instructions.h" -#include "crypto/hmac.h" -#include "testing/gtest/include/gtest/gtest.h" - -namespace { - -const char seed[] = "foobar"; - -#define KEY_HASH_1 GetHash("KEY_HASH_1") -#define KEY_HASH_2 GetHash("KEY_HASH_2") -#define KEY_HASH_3 GetHash("KEY_HASH_3") -#define KEY_HASH_4 GetHash("KEY_HASH_4") - -#define VALUE_HASH_1 GetHash("VALUE_HASH_1") -#define VALUE_HASH_2 GetHash("VALUE_HASH_2") - -#define VAR_HASH_1 "01234567890123456789012345678901" -#define VAR_HASH_2 "12345678901234567890123456789012" - -std::string GetHash(const std::string& input) { - return jtl_foundation::Hasher(seed).GetHash(input); -} - -std::string EncodeUint32(uint32 value) { - std::string bytecode; - for (int i = 0; i < 4; ++i) { - bytecode.push_back(static_cast<char>(value & 0xFFu)); - value >>= 8; - } - return bytecode; -} - -// escaped_json_param may contain ' characters that are replaced with ". This -// makes the code more readable because we need less escaping. -#define INIT_INTERPRETER(program_param, escaped_json_param) \ - const char* escaped_json = escaped_json_param; \ - std::string json; \ - base::ReplaceChars(escaped_json, "'", "\"", &json); \ - scoped_ptr<base::Value> json_value(ParseJson(json)); \ - JtlInterpreter interpreter( \ - seed, \ - program_param, \ - static_cast<const base::DictionaryValue*>(json_value.get())); \ - interpreter.Execute() - -using base::test::ParseJson; - -TEST(JtlInterpreter, Store) { - INIT_INTERPRETER( - OP_STORE_BOOL(VAR_HASH_1, VALUE_TRUE), - "{ 'KEY_HASH_1': 'VALUE_HASH_1' }"); - EXPECT_EQ(JtlInterpreter::OK, interpreter.result()); - base::ExpectDictBooleanValue(true, *interpreter.working_memory(), VAR_HASH_1); -} - -TEST(JtlInterpreter, NavigateAndStore) { - INIT_INTERPRETER( - OP_NAVIGATE(KEY_HASH_1) + - OP_STORE_BOOL(VAR_HASH_1, VALUE_TRUE), - "{ 'KEY_HASH_1': 'VALUE_HASH_1' }"); - EXPECT_EQ(JtlInterpreter::OK, interpreter.result()); - base::ExpectDictBooleanValue(true, *interpreter.working_memory(), VAR_HASH_1); -} - -TEST(JtlInterpreter, FailNavigate) { - INIT_INTERPRETER( - OP_NAVIGATE(KEY_HASH_2) + - OP_STORE_BOOL(VAR_HASH_1, VALUE_TRUE), - "{ 'KEY_HASH_1': 'VALUE_HASH_1' }"); - EXPECT_EQ(JtlInterpreter::OK, interpreter.result()); - EXPECT_FALSE(interpreter.working_memory()->HasKey(VAR_HASH_1)); -} - -TEST(JtlInterpreter, ConsecutiveNavigate) { - INIT_INTERPRETER( - OP_NAVIGATE(KEY_HASH_1) + - OP_NAVIGATE(KEY_HASH_2) + - OP_STORE_BOOL(VAR_HASH_1, VALUE_TRUE), - "{ 'KEY_HASH_1': { 'KEY_HASH_2': 'VALUE_HASH_1' } }"); - EXPECT_EQ(JtlInterpreter::OK, interpreter.result()); - base::ExpectDictBooleanValue(true, *interpreter.working_memory(), VAR_HASH_1); -} - -TEST(JtlInterpreter, FailConsecutiveNavigate) { - INIT_INTERPRETER( - OP_NAVIGATE(KEY_HASH_1) + - OP_NAVIGATE(KEY_HASH_2) + - OP_STORE_BOOL(VAR_HASH_1, VALUE_TRUE), - "{ 'KEY_HASH_1': 'foo' }"); - EXPECT_EQ(JtlInterpreter::OK, interpreter.result()); - EXPECT_FALSE(interpreter.working_memory()->HasKey(VAR_HASH_1)); -} - -TEST(JtlInterpreter, NavigateAnyInDictionary) { - INIT_INTERPRETER( - OP_NAVIGATE(KEY_HASH_1) + - OP_NAVIGATE_ANY + - OP_NAVIGATE(KEY_HASH_4) + - OP_STORE_BOOL(VAR_HASH_1, VALUE_TRUE), - "{ 'KEY_HASH_1':" - " { 'KEY_HASH_2': {'KEY_HASH_3': 'VALUE_HASH_1' }," - " 'KEY_HASH_3': {'KEY_HASH_4': 'VALUE_HASH_1' }" - " } }"); - EXPECT_EQ(JtlInterpreter::OK, interpreter.result()); - base::ExpectDictBooleanValue(true, *interpreter.working_memory(), VAR_HASH_1); -} - -TEST(JtlInterpreter, NavigateAnyInList) { - INIT_INTERPRETER( - OP_NAVIGATE(KEY_HASH_1) + - OP_NAVIGATE_ANY + - OP_NAVIGATE(KEY_HASH_4) + - OP_STORE_BOOL(VAR_HASH_1, VALUE_TRUE), - "{ 'KEY_HASH_1':" - " [ {'KEY_HASH_3': 'VALUE_HASH_1' }," - " {'KEY_HASH_4': 'VALUE_HASH_1' }" - " ] }"); - EXPECT_EQ(JtlInterpreter::OK, interpreter.result()); - base::ExpectDictBooleanValue(true, *interpreter.working_memory(), VAR_HASH_1); -} - -TEST(JtlInterpreter, NavigateBack) { - INIT_INTERPRETER( - OP_NAVIGATE(KEY_HASH_1) + - OP_NAVIGATE(KEY_HASH_2) + - OP_NAVIGATE_BACK + - OP_NAVIGATE(KEY_HASH_3) + - OP_NAVIGATE(KEY_HASH_4) + - OP_STORE_BOOL(VAR_HASH_1, VALUE_TRUE), - "{ 'KEY_HASH_1':" - " { 'KEY_HASH_2': {'KEY_HASH_3': 'VALUE_HASH_1' }," - " 'KEY_HASH_3': {'KEY_HASH_4': 'VALUE_HASH_1' }" - " } }"); - EXPECT_EQ(JtlInterpreter::OK, interpreter.result()); - base::ExpectDictBooleanValue(true, *interpreter.working_memory(), VAR_HASH_1); -} - -TEST(JtlInterpreter, StoreTwoValues) { - INIT_INTERPRETER( - OP_NAVIGATE(KEY_HASH_1) + - OP_NAVIGATE(KEY_HASH_2) + - OP_STORE_BOOL(VAR_HASH_1, VALUE_TRUE) + - OP_STORE_HASH(VAR_HASH_2, VALUE_HASH_1), - "{ 'KEY_HASH_1': { 'KEY_HASH_2': 'VALUE_HASH_1' } }"); - EXPECT_EQ(JtlInterpreter::OK, interpreter.result()); - base::ExpectDictBooleanValue(true, *interpreter.working_memory(), VAR_HASH_1); - base::ExpectDictStringValue(VALUE_HASH_1, *interpreter.working_memory(), - VAR_HASH_2); -} - -TEST(JtlInterpreter, CompareStoredMatch) { - INIT_INTERPRETER( - OP_NAVIGATE(KEY_HASH_1) + - OP_STORE_BOOL(VAR_HASH_1, VALUE_TRUE) + - OP_NAVIGATE(KEY_HASH_2) + - OP_COMPARE_STORED_BOOL(VAR_HASH_1, VALUE_TRUE, VALUE_FALSE) + - OP_STORE_BOOL(VAR_HASH_2, VALUE_TRUE), - "{ 'KEY_HASH_1': { 'KEY_HASH_2': 'VALUE_HASH_1' } }"); - EXPECT_EQ(JtlInterpreter::OK, interpreter.result()); - base::ExpectDictBooleanValue(true, *interpreter.working_memory(), VAR_HASH_1); - base::ExpectDictBooleanValue(true, *interpreter.working_memory(), VAR_HASH_2); -} - -TEST(JtlInterpreter, CompareStoredMismatch) { - INIT_INTERPRETER( - OP_NAVIGATE(KEY_HASH_1) + - OP_STORE_BOOL(VAR_HASH_1, VALUE_TRUE) + - OP_NAVIGATE(KEY_HASH_2) + - OP_COMPARE_STORED_BOOL(VAR_HASH_1, VALUE_FALSE, VALUE_TRUE) + - OP_STORE_BOOL(VAR_HASH_2, VALUE_TRUE), - "{ 'KEY_HASH_1': { 'KEY_HASH_2': 'VALUE_HASH_1' } }"); - EXPECT_EQ(JtlInterpreter::OK, interpreter.result()); - base::ExpectDictBooleanValue(true, *interpreter.working_memory(), VAR_HASH_1); - EXPECT_FALSE(interpreter.working_memory()->HasKey(VAR_HASH_2)); -} - -TEST(JtlInterpreter, CompareStoredNoValueMatchingDefault) { - INIT_INTERPRETER( - OP_NAVIGATE(KEY_HASH_1) + - OP_NAVIGATE(KEY_HASH_2) + - OP_COMPARE_STORED_BOOL(VAR_HASH_1, VALUE_TRUE, VALUE_TRUE) + - OP_STORE_BOOL(VAR_HASH_2, VALUE_TRUE), - "{ 'KEY_HASH_1': { 'KEY_HASH_2': 'VALUE_HASH_1' } }"); - EXPECT_EQ(JtlInterpreter::OK, interpreter.result()); - base::ExpectDictBooleanValue(true, *interpreter.working_memory(), VAR_HASH_2); -} - -TEST(JtlInterpreter, CompareStoredNoValueMismatchingDefault) { - INIT_INTERPRETER( - OP_NAVIGATE(KEY_HASH_1) + - OP_NAVIGATE(KEY_HASH_2) + - OP_COMPARE_STORED_BOOL(VAR_HASH_1, VALUE_TRUE, VALUE_FALSE) + - OP_STORE_BOOL(VAR_HASH_2, VALUE_TRUE), - "{ 'KEY_HASH_1': { 'KEY_HASH_2': 'VALUE_HASH_1' } }"); - EXPECT_EQ(JtlInterpreter::OK, interpreter.result()); - EXPECT_FALSE(interpreter.working_memory()->HasKey(VAR_HASH_2)); -} - -TEST(JtlInterpreter, CompareBool) { - struct TestCase { - std::string expected_value; - const char* json; - bool expected_success; - } cases[] = { - { VALUE_TRUE, "{ 'KEY_HASH_1': true }", true }, - { VALUE_FALSE, "{ 'KEY_HASH_1': false }", true }, - { VALUE_TRUE, "{ 'KEY_HASH_1': false }", false }, - { VALUE_TRUE, "{ 'KEY_HASH_1': 'abc' }", false }, - { VALUE_TRUE, "{ 'KEY_HASH_1': 1 }", false }, - { VALUE_TRUE, "{ 'KEY_HASH_1': 1.2 }", false }, - { VALUE_TRUE, "{ 'KEY_HASH_1': [1] }", false }, - { VALUE_TRUE, "{ 'KEY_HASH_1': {'a': 'b'} }", false }, - }; - - for (size_t i = 0; i < arraysize(cases); ++i) { - SCOPED_TRACE(testing::Message() << "Iteration " << i); - INIT_INTERPRETER( - OP_NAVIGATE(KEY_HASH_1) + - OP_COMPARE_NODE_BOOL(cases[i].expected_value) + - OP_STORE_BOOL(VAR_HASH_1, VALUE_TRUE), - cases[i].json); - EXPECT_EQ(JtlInterpreter::OK, interpreter.result()); - if (cases[i].expected_success) { - base::ExpectDictBooleanValue( - true, *interpreter.working_memory(), VAR_HASH_1); - } else { - EXPECT_FALSE(interpreter.working_memory()->HasKey(VAR_HASH_1)); - } - } -} - -TEST(JtlInterpreter, CompareHashString) { - struct TestCase { - std::string expected_value; - const char* json; - bool expected_success; - } cases[] = { - { VALUE_HASH_1, "{ 'KEY_HASH_1': 'VALUE_HASH_1' }", true }, - { VALUE_HASH_1, "{ 'KEY_HASH_1': 'VALUE_HASH_2' }", false }, - { VALUE_HASH_1, "{ 'KEY_HASH_1': true }", false }, - { VALUE_HASH_1, "{ 'KEY_HASH_1': 1 }", false }, - { VALUE_HASH_1, "{ 'KEY_HASH_1': 1.1 }", false }, - { VALUE_HASH_1, "{ 'KEY_HASH_1': [1] }", false }, - { VALUE_HASH_1, "{ 'KEY_HASH_1': {'a': 'b'} }", false }, - - { GetHash("1.2"), "{ 'KEY_HASH_1': 1.2 }", true }, - { GetHash("1.2"), "{ 'KEY_HASH_1': 'VALUE_HASH_1' }", false }, - { GetHash("1.2"), "{ 'KEY_HASH_1': true }", false }, - { GetHash("1.2"), "{ 'KEY_HASH_1': 1 }", false }, - { GetHash("1.2"), "{ 'KEY_HASH_1': 1.3 }", false }, - { GetHash("1.2"), "{ 'KEY_HASH_1': [1] }", false }, - { GetHash("1.2"), "{ 'KEY_HASH_1': {'a': 'b'} }", false }, - - { GetHash("1"), "{ 'KEY_HASH_1': 1 }", true }, - { GetHash("1"), "{ 'KEY_HASH_1': 'VALUE_HASH_1' }", false }, - { GetHash("1"), "{ 'KEY_HASH_1': true }", false }, - { GetHash("1"), "{ 'KEY_HASH_1': 2 }", false }, - { GetHash("1"), "{ 'KEY_HASH_1': 1.1 }", false }, - { GetHash("1"), "{ 'KEY_HASH_1': [1] }", false }, - { GetHash("1"), "{ 'KEY_HASH_1': {'a': 'b'} }", false }, - }; - - for (size_t i = 0; i < arraysize(cases); ++i) { - SCOPED_TRACE(testing::Message() << "Iteration " << i); - INIT_INTERPRETER( - OP_NAVIGATE(KEY_HASH_1) + - OP_COMPARE_NODE_HASH(cases[i].expected_value) + - OP_STORE_BOOL(VAR_HASH_1, VALUE_TRUE), - cases[i].json); - EXPECT_EQ(JtlInterpreter::OK, interpreter.result()); - if (cases[i].expected_success) { - base::ExpectDictBooleanValue( - true, *interpreter.working_memory(), VAR_HASH_1); - } else { - EXPECT_FALSE(interpreter.working_memory()->HasKey(VAR_HASH_1)); - } - } - - for (size_t i = 0; i < arraysize(cases); ++i) { - SCOPED_TRACE(testing::Message() << "Negated, Iteration " << i); - INIT_INTERPRETER( - OP_NAVIGATE(KEY_HASH_1) + - OP_COMPARE_NODE_HASH_NOT(cases[i].expected_value) + - OP_STORE_BOOL(VAR_HASH_1, VALUE_TRUE), - cases[i].json); - EXPECT_EQ(JtlInterpreter::OK, interpreter.result()); - if (!cases[i].expected_success) { - base::ExpectDictBooleanValue( - true, *interpreter.working_memory(), VAR_HASH_1); - } else { - EXPECT_FALSE(interpreter.working_memory()->HasKey(VAR_HASH_1)); - } - } -} - -TEST(JtlInterpreter, StoreNodeBool) { - struct TestCase { - bool expected_value; - const char* json; - bool expected_success; - } cases[] = { - { true, "{ 'KEY_HASH_1': true }", true }, - { false, "{ 'KEY_HASH_1': false }", true }, - { false, "{ 'KEY_HASH_1': 'abc' }", false }, - { false, "{ 'KEY_HASH_1': 1 }", false }, - { false, "{ 'KEY_HASH_1': 1.2 }", false }, - { false, "{ 'KEY_HASH_1': [1] }", false }, - { false, "{ 'KEY_HASH_1': {'a': 'b'} }", false }, - }; - - for (size_t i = 0; i < arraysize(cases); ++i) { - SCOPED_TRACE(testing::Message() << "Iteration " << i); - INIT_INTERPRETER( - OP_NAVIGATE(KEY_HASH_1) + - OP_STORE_NODE_BOOL(VAR_HASH_1) + - OP_STORE_BOOL(VAR_HASH_2, VALUE_TRUE), - cases[i].json); - EXPECT_EQ(JtlInterpreter::OK, interpreter.result()); - if (cases[i].expected_success) { - base::ExpectDictBooleanValue( - cases[i].expected_value, *interpreter.working_memory(), VAR_HASH_1); - base::ExpectDictBooleanValue( - true, *interpreter.working_memory(), VAR_HASH_2); - } else { - EXPECT_FALSE(interpreter.working_memory()->HasKey(VAR_HASH_1)); - EXPECT_FALSE(interpreter.working_memory()->HasKey(VAR_HASH_2)); - } - } -} - -TEST(JtlInterpreter, CompareNodeToStoredBool) { - struct TestCase { - std::string stored_value; - const char* json; - bool expected_success; - } cases[] = { - { VALUE_TRUE, "{ 'KEY_HASH_1': true }", true }, - { VALUE_FALSE, "{ 'KEY_HASH_1': false }", true }, - { VALUE_FALSE, "{ 'KEY_HASH_1': true }", false }, - { std::string(), "{ 'KEY_HASH_1': true }", false }, - - { VALUE_HASH_1, "{ 'KEY_HASH_1': 'VALUE_HASH_1' }", false }, - { GetHash("1"), "{ 'KEY_HASH_1': 1 }", false }, - { GetHash("1.2"), "{ 'KEY_HASH_1': 1.2 }", false }, - - { VALUE_HASH_1, "{ 'KEY_HASH_1': true }", false }, - { GetHash("1"), "{ 'KEY_HASH_1': true }", false }, - { GetHash("1.2"), "{ 'KEY_HASH_1': true }", false }, - - { VALUE_TRUE, "{ 'KEY_HASH_1': 'VALUE_HASH_1' }", false }, - { VALUE_TRUE, "{ 'KEY_HASH_1': 1 }", false }, - { VALUE_TRUE, "{ 'KEY_HASH_1': 1.2 }", false }, - { VALUE_TRUE, "{ 'KEY_HASH_1': [1] }", false }, - { VALUE_TRUE, "{ 'KEY_HASH_1': {'a': 'b'} }", false }, - }; - - for (size_t i = 0; i < arraysize(cases); ++i) { - SCOPED_TRACE(testing::Message() << "Iteration " << i); - std::string store_op; - if (cases[i].stored_value == VALUE_TRUE || - cases[i].stored_value == VALUE_FALSE) - store_op = OP_STORE_BOOL(VAR_HASH_1, cases[i].stored_value); - else if (!cases[i].stored_value.empty()) - store_op = OP_STORE_HASH(VAR_HASH_1, cases[i].stored_value); - INIT_INTERPRETER( - store_op + - OP_NAVIGATE(KEY_HASH_1) + - OP_COMPARE_NODE_TO_STORED_BOOL(VAR_HASH_1) + - OP_STORE_BOOL(VAR_HASH_2, VALUE_TRUE), - cases[i].json); - EXPECT_EQ(JtlInterpreter::OK, interpreter.result()); - if (cases[i].expected_success) { - base::ExpectDictBooleanValue( - true, *interpreter.working_memory(), VAR_HASH_2); - } else { - EXPECT_FALSE(interpreter.working_memory()->HasKey(VAR_HASH_2)); - } - } -} - -TEST(JtlInterpreter, StoreNodeHash) { - struct TestCase { - std::string expected_value; - const char* json; - bool expected_success; - } cases[] = { - { VALUE_HASH_1, "{ 'KEY_HASH_1': 'VALUE_HASH_1' }", true }, - { VALUE_HASH_2, "{ 'KEY_HASH_1': 'VALUE_HASH_2' }", true }, - { GetHash("1"), "{ 'KEY_HASH_1': 1 }", true }, - { GetHash("1.2"), "{ 'KEY_HASH_1': 1.2 }", true }, - { std::string(), "{ 'KEY_HASH_1': true }", false }, - { std::string(), "{ 'KEY_HASH_1': [1] }", false }, - { std::string(), "{ 'KEY_HASH_1': {'a': 'b'} }", false }, - }; - - for (size_t i = 0; i < arraysize(cases); ++i) { - SCOPED_TRACE(testing::Message() << "Iteration " << i); - INIT_INTERPRETER( - OP_NAVIGATE(KEY_HASH_1) + - OP_STORE_NODE_HASH(VAR_HASH_1) + - OP_STORE_BOOL(VAR_HASH_2, VALUE_TRUE), - cases[i].json); - EXPECT_EQ(JtlInterpreter::OK, interpreter.result()); - if (cases[i].expected_success) { - base::ExpectDictStringValue( - cases[i].expected_value, *interpreter.working_memory(), VAR_HASH_1); - base::ExpectDictBooleanValue( - true, *interpreter.working_memory(), VAR_HASH_2); - } else { - EXPECT_FALSE(interpreter.working_memory()->HasKey(VAR_HASH_1)); - EXPECT_FALSE(interpreter.working_memory()->HasKey(VAR_HASH_2)); - } - } -} - -TEST(JtlInterpreter, CompareNodeToStoredHash) { - struct TestCase { - std::string stored_value; - const char* json; - bool expected_success; - } cases[] = { - { VALUE_HASH_1, "{ 'KEY_HASH_1': 'VALUE_HASH_1' }", true }, - { VALUE_HASH_2, "{ 'KEY_HASH_1': 'VALUE_HASH_2' }", true }, - { std::string(), "{ 'KEY_HASH_1': 'VALUE_HASH_2' }", false }, - { VALUE_HASH_1, "{ 'KEY_HASH_1': 'VALUE_HASH_2' }", false }, - { VALUE_HASH_1, "{ 'KEY_HASH_1': true }", false }, - { VALUE_HASH_1, "{ 'KEY_HASH_1': 1 }", false }, - { VALUE_HASH_1, "{ 'KEY_HASH_1': 1.1 }", false }, - { VALUE_HASH_1, "{ 'KEY_HASH_1': [1] }", false }, - { VALUE_HASH_1, "{ 'KEY_HASH_1': {'a': 'b'} }", false }, - - { GetHash("1.2"), "{ 'KEY_HASH_1': 1.2 }", true }, - { GetHash("1.3"), "{ 'KEY_HASH_1': 1.3 }", true }, - { std::string(), "{ 'KEY_HASH_1': 1.2 }", false }, - { GetHash("1.2"), "{ 'KEY_HASH_1': 'VALUE_HASH_1' }", false }, - { GetHash("1.2"), "{ 'KEY_HASH_1': true }", false }, - { GetHash("1.2"), "{ 'KEY_HASH_1': 1 }", false }, - { GetHash("1.2"), "{ 'KEY_HASH_1': 1.3 }", false }, - { GetHash("1.2"), "{ 'KEY_HASH_1': [1] }", false }, - { GetHash("1.2"), "{ 'KEY_HASH_1': {'a': 'b'} }", false }, - - { GetHash("1"), "{ 'KEY_HASH_1': 1 }", true }, - { GetHash("2"), "{ 'KEY_HASH_1': 2 }", true }, - { std::string(), "{ 'KEY_HASH_1': 2 }", false }, - { GetHash("1"), "{ 'KEY_HASH_1': 'VALUE_HASH_1' }", false }, - { GetHash("1"), "{ 'KEY_HASH_1': true }", false }, - { GetHash("1"), "{ 'KEY_HASH_1': 2 }", false }, - { GetHash("1"), "{ 'KEY_HASH_1': 1.1 }", false }, - { GetHash("1"), "{ 'KEY_HASH_1': [1] }", false }, - { GetHash("1"), "{ 'KEY_HASH_1': {'a': 'b'} }", false }, - - { VALUE_TRUE, "{ 'KEY_HASH_1': 'VALUE_HASH_1' }", false }, - { VALUE_TRUE, "{ 'KEY_HASH_1': 1 }", false }, - { VALUE_TRUE, "{ 'KEY_HASH_1': 1.3 }", false }, - { VALUE_TRUE, "{ 'KEY_HASH_1': [1] }", false }, - { VALUE_TRUE, "{ 'KEY_HASH_1': {'a': 'b'} }", false }, - - { VALUE_TRUE, "{ 'KEY_HASH_1': true }", false }, - { VALUE_FALSE, "{ 'KEY_HASH_1': false }", false }, - }; - - for (size_t i = 0; i < arraysize(cases); ++i) { - SCOPED_TRACE(testing::Message() << "Iteration " << i); - std::string store_op; - if (cases[i].stored_value == VALUE_TRUE || - cases[i].stored_value == VALUE_FALSE) - store_op = OP_STORE_BOOL(VAR_HASH_1, cases[i].stored_value); - else if (!cases[i].stored_value.empty()) - store_op = OP_STORE_HASH(VAR_HASH_1, cases[i].stored_value); - INIT_INTERPRETER( - store_op + - OP_NAVIGATE(KEY_HASH_1) + - OP_COMPARE_NODE_TO_STORED_HASH(VAR_HASH_1) + - OP_STORE_BOOL(VAR_HASH_2, VALUE_TRUE), - cases[i].json); - EXPECT_EQ(JtlInterpreter::OK, interpreter.result()); - if (cases[i].expected_success) { - base::ExpectDictBooleanValue( - true, *interpreter.working_memory(), VAR_HASH_2); - } else { - EXPECT_FALSE(interpreter.working_memory()->HasKey(VAR_HASH_2)); - } - } -} - -TEST(JtlInterpreter, CompareSubstring) { - struct TestCase { - std::string pattern; - const char* json; - bool expected_success; - } cases[] = { - { "abc", "{ 'KEY_HASH_1': 'abcdefghijklmnopqrstuvwxyz' }", true }, - { "xyz", "{ 'KEY_HASH_1': 'abcdefghijklmnopqrstuvwxyz' }", true }, - { "m", "{ 'KEY_HASH_1': 'abcdefghijklmnopqrstuvwxyz' }", true }, - { "abc", "{ 'KEY_HASH_1': 'abc' }", true }, - { "cba", "{ 'KEY_HASH_1': 'abcdefghijklmnopqrstuvwxyz' }", false }, - { "acd", "{ 'KEY_HASH_1': 'abcdefghijklmnopqrstuvwxyz' }", false }, - { "waaaaaaay_too_long", "{ 'KEY_HASH_1': 'abc' }", false }, - - { VALUE_HASH_1, "{ 'KEY_HASH_1': true }", false }, - { VALUE_HASH_1, "{ 'KEY_HASH_1': 1 }", false }, - { VALUE_HASH_1, "{ 'KEY_HASH_1': 1.1 }", false }, - { VALUE_HASH_1, "{ 'KEY_HASH_1': [1] }", false }, - { VALUE_HASH_1, "{ 'KEY_HASH_1': {'a': 'b'} }", false }, - }; - - for (size_t i = 0; i < arraysize(cases); ++i) { - SCOPED_TRACE(testing::Message() << "Iteration " << i); - std::string pattern = cases[i].pattern; - uint32 pattern_sum = std::accumulate( - pattern.begin(), pattern.end(), static_cast<uint32>(0u)); - INIT_INTERPRETER( - OP_NAVIGATE(KEY_HASH_1) + - OP_COMPARE_NODE_SUBSTRING(GetHash(pattern), - EncodeUint32(pattern.size()), - EncodeUint32(pattern_sum)) + - OP_STORE_BOOL(VAR_HASH_1, VALUE_TRUE), - cases[i].json); - EXPECT_EQ(JtlInterpreter::OK, interpreter.result()); - if (cases[i].expected_success) { - base::ExpectDictBooleanValue( - true, *interpreter.working_memory(), VAR_HASH_1); - } else { - EXPECT_FALSE(interpreter.working_memory()->HasKey(VAR_HASH_1)); - } - } -} - -TEST(JtlInterpreter, StoreNodeRegisterableDomainHash) { - struct TestCase { - std::string expected_value; - const char* json; - bool expected_success; - } cases[] = { - { GetHash("google"), "{ 'KEY_HASH_1': 'http://google.com/path' }", true }, - { GetHash("google"), "{ 'KEY_HASH_1': 'http://mail.google.com/' }", true }, - { GetHash("google"), "{ 'KEY_HASH_1': 'http://google.co.uk/' }", true }, - { GetHash("google"), "{ 'KEY_HASH_1': 'http://google.com./' }", true }, - { GetHash("google"), "{ 'KEY_HASH_1': 'http://..google.com/' }", true }, - - { GetHash("foo"), "{ 'KEY_HASH_1': 'http://foo.bar/path' }", true }, - { GetHash("foo"), "{ 'KEY_HASH_1': 'http://sub.foo.bar' }", true }, - { GetHash("foo"), "{ 'KEY_HASH_1': 'http://foo.appspot.com/' }", true }, - { GetHash("foo"), "{ 'KEY_HASH_1': 'http://sub.foo.appspot.com' }", true }, - - { std::string(), "{ 'KEY_HASH_1': 'http://google.com../' }", false }, - - { std::string(), "{ 'KEY_HASH_1': 'http://bar/path' }", false }, - { std::string(), "{ 'KEY_HASH_1': 'http://co.uk/path' }", false }, - { std::string(), "{ 'KEY_HASH_1': 'http://appspot.com/path' }", false }, - { std::string(), "{ 'KEY_HASH_1': 'http://127.0.0.1/path' }", false }, - { std::string(), "{ 'KEY_HASH_1': 'file:///C:/bar.html' }", false }, - - { std::string(), "{ 'KEY_HASH_1': 1 }", false }, - { std::string(), "{ 'KEY_HASH_1': 1.2 }", false }, - { std::string(), "{ 'KEY_HASH_1': true }", false }, - { std::string(), "{ 'KEY_HASH_1': [1] }", false }, - { std::string(), "{ 'KEY_HASH_1': {'a': 'b'} }", false }, - }; - - for (size_t i = 0; i < arraysize(cases); ++i) { - SCOPED_TRACE(testing::Message() << "Iteration " << i); - INIT_INTERPRETER( - OP_NAVIGATE(KEY_HASH_1) + - OP_STORE_NODE_REGISTERABLE_DOMAIN_HASH(VAR_HASH_1) + - OP_STORE_BOOL(VAR_HASH_2, VALUE_TRUE), - cases[i].json); - EXPECT_EQ(JtlInterpreter::OK, interpreter.result()); - if (cases[i].expected_success) { - base::ExpectDictStringValue( - cases[i].expected_value, *interpreter.working_memory(), VAR_HASH_1); - base::ExpectDictBooleanValue( - true, *interpreter.working_memory(), VAR_HASH_2); - } else { - EXPECT_FALSE(interpreter.working_memory()->HasKey(VAR_HASH_1)); - EXPECT_FALSE(interpreter.working_memory()->HasKey(VAR_HASH_2)); - } - } -} - -TEST(JtlInterpreter, Stop) { - INIT_INTERPRETER( - OP_NAVIGATE(KEY_HASH_1) + - OP_NAVIGATE(KEY_HASH_2) + - OP_STORE_BOOL(VAR_HASH_1, VALUE_TRUE) + - OP_STOP_EXECUTING_SENTENCE + - OP_STORE_BOOL(VAR_HASH_2, VALUE_TRUE), - "{ 'KEY_HASH_1': { 'KEY_HASH_2': 'VALUE_HASH_1' } }"); - EXPECT_EQ(JtlInterpreter::OK, interpreter.result()); - base::ExpectDictBooleanValue(true, *interpreter.working_memory(), VAR_HASH_1); - EXPECT_FALSE(interpreter.working_memory()->HasKey(VAR_HASH_2)); -} - -TEST(JtlInterpreter, EndOfSentence) { - INIT_INTERPRETER( - OP_NAVIGATE(KEY_HASH_1) + - OP_NAVIGATE(KEY_HASH_2) + - OP_STORE_BOOL(VAR_HASH_1, VALUE_TRUE) + - OP_END_OF_SENTENCE + - OP_STORE_BOOL(VAR_HASH_2, VALUE_TRUE), - "{ 'KEY_HASH_1': { 'KEY_HASH_2': 'VALUE_HASH_1' } }"); - EXPECT_EQ(JtlInterpreter::OK, interpreter.result()); - base::ExpectDictBooleanValue(true, *interpreter.working_memory(), VAR_HASH_1); - base::ExpectDictBooleanValue(true, *interpreter.working_memory(), VAR_HASH_2); -} - -TEST(JtlInterpreter, InvalidBack) { - INIT_INTERPRETER( - OP_NAVIGATE(KEY_HASH_1) + - OP_NAVIGATE_BACK + - OP_NAVIGATE_BACK, - "{ 'KEY_HASH_1': { 'KEY_HASH_2': 'VALUE_HASH_1' } }"); - EXPECT_EQ(JtlInterpreter::RUNTIME_ERROR, interpreter.result()); -} - -TEST(JtlInterpreter, IncorrectPrograms) { - std::string missing_hash; - std::string missing_bool; - std::string invalid_hash("123"); - std::string invalid_bool("\x02", 1); - std::string invalid_operation("\x99", 1); - std::string programs[] = { - OP_NAVIGATE(missing_hash), - OP_NAVIGATE(invalid_hash), - OP_STORE_BOOL(VAR_HASH_1, invalid_bool), - OP_STORE_BOOL(missing_hash, VALUE_TRUE), - OP_STORE_BOOL(invalid_hash, VALUE_TRUE), - OP_COMPARE_STORED_BOOL(invalid_hash, VALUE_TRUE, VALUE_TRUE), - OP_COMPARE_STORED_BOOL(VAR_HASH_1, invalid_bool, VALUE_TRUE), - OP_COMPARE_STORED_BOOL(VAR_HASH_1, VALUE_TRUE, invalid_bool), - OP_COMPARE_STORED_BOOL(VAR_HASH_1, VALUE_TRUE, missing_bool), - OP_STORE_NODE_BOOL(missing_hash), - OP_STORE_NODE_BOOL(invalid_hash), - OP_STORE_NODE_HASH(missing_hash), - OP_STORE_NODE_HASH(invalid_hash), - OP_COMPARE_NODE_BOOL(missing_bool), - OP_COMPARE_NODE_BOOL(invalid_bool), - OP_COMPARE_NODE_HASH(missing_hash), - OP_COMPARE_NODE_HASH(invalid_hash), - OP_COMPARE_NODE_TO_STORED_BOOL(missing_hash), - OP_COMPARE_NODE_TO_STORED_BOOL(invalid_hash), - OP_COMPARE_NODE_TO_STORED_HASH(missing_hash), - OP_COMPARE_NODE_TO_STORED_HASH(invalid_hash), - invalid_operation, - }; - for (size_t i = 0; i < arraysize(programs); ++i) { - SCOPED_TRACE(testing::Message() << "Iteration " << i); - INIT_INTERPRETER(programs[i], - "{ 'KEY_HASH_1': { 'KEY_HASH_2': 'VALUE_HASH_1' } }"); - EXPECT_EQ(JtlInterpreter::PARSE_ERROR, interpreter.result()); - } -} - -TEST(JtlInterpreter, GetOutput) { - INIT_INTERPRETER( - OP_STORE_BOOL(GetHash("output1"), VALUE_TRUE) + - OP_STORE_HASH(GetHash("output2"), VALUE_HASH_1), - "{}"); - bool output1 = false; - std::string output2; - EXPECT_TRUE(interpreter.GetOutputBoolean("output1", &output1)); - EXPECT_EQ(true, output1); - EXPECT_TRUE(interpreter.GetOutputString("output2", &output2)); - EXPECT_EQ(VALUE_HASH_1, output2); - EXPECT_FALSE(interpreter.GetOutputBoolean("outputxx", &output1)); - EXPECT_FALSE(interpreter.GetOutputString("outputxx", &output2)); -} - -TEST(JtlInterpreter, CalculateProgramChecksum) { - const char kTestSeed[] = "Irrelevant seed value."; - const char kTestProgram[] = "The quick brown fox jumps over the lazy dog."; - // This program is invalid, but we are not actually executing it. - base::DictionaryValue input; - JtlInterpreter interpreter(kTestSeed, kTestProgram, &input); - EXPECT_EQ(0xef537f, interpreter.CalculateProgramChecksum()); -} - -} // namespace diff --git a/chrome/browser/profile_resetter/profile_reset_global_error.cc b/chrome/browser/profile_resetter/profile_reset_global_error.cc deleted file mode 100644 index a355b64..0000000 --- a/chrome/browser/profile_resetter/profile_reset_global_error.cc +++ /dev/null @@ -1,110 +0,0 @@ -// Copyright 2013 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 "chrome/browser/profile_resetter/profile_reset_global_error.h" - -#include "base/metrics/histogram.h" -#include "chrome/app/chrome_command_ids.h" -#include "chrome/browser/profile_resetter/automatic_profile_resetter.h" -#include "chrome/browser/profile_resetter/automatic_profile_resetter_factory.h" -#include "chrome/browser/profiles/profile.h" -#include "chrome/browser/ui/browser.h" -#include "chrome/browser/ui/browser_window.h" -#include "chrome/browser/ui/chrome_pages.h" -#include "chrome/browser/ui/global_error/global_error_service.h" -#include "chrome/browser/ui/global_error/global_error_service_factory.h" -#include "chrome/common/url_constants.h" -#include "grit/chromium_strings.h" -#include "grit/generated_resources.h" -#include "ui/base/l10n/l10n_util.h" - -namespace { - -base::TimeDelta GetPromptDelayHistogramMaximum() { - return base::TimeDelta::FromDays(7); -} - -// Records the delay between when the reset prompt is triggered and when the -// bubble can actually be shown. -void RecordPromptDelay(const base::TimeDelta& delay) { - UMA_HISTOGRAM_CUSTOM_TIMES( - "AutomaticProfileReset.PromptDelay", delay, - base::TimeDelta::FromSeconds(1), GetPromptDelayHistogramMaximum(), 50); -} - -} // namespace - - -// ProfileResetGlobalError --------------------------------------------------- - -ProfileResetGlobalError::ProfileResetGlobalError(Profile* profile) - : profile_(profile), has_shown_bubble_view_(false), bubble_view_(NULL) { - AutomaticProfileResetter* automatic_profile_resetter = - AutomaticProfileResetterFactory::GetForBrowserContext(profile_); - if (automatic_profile_resetter) - automatic_profile_resetter_ = automatic_profile_resetter->AsWeakPtr(); -} - -ProfileResetGlobalError::~ProfileResetGlobalError() { - if (!has_shown_bubble_view_) - RecordPromptDelay(GetPromptDelayHistogramMaximum()); -} - -// static -bool ProfileResetGlobalError::IsSupportedOnPlatform(Browser* browser) { - return browser->window()->IsProfileResetBubbleSupported(); -} - -bool ProfileResetGlobalError::HasMenuItem() { return true; } - -int ProfileResetGlobalError::MenuItemCommandID() { - return IDC_SHOW_SETTINGS_RESET_BUBBLE; -} - -base::string16 ProfileResetGlobalError::MenuItemLabel() { - return l10n_util::GetStringFUTF16( - IDS_RESET_SETTINGS_MENU_ITEM, - l10n_util::GetStringUTF16(IDS_SHORT_PRODUCT_NAME)); -} - -void ProfileResetGlobalError::ExecuteMenuItem(Browser* browser) { - chrome::ShowSettingsSubPage(browser, chrome::kResetProfileSettingsSubPage); -} - -bool ProfileResetGlobalError::HasBubbleView() { return true; } - -bool ProfileResetGlobalError::HasShownBubbleView() { - return has_shown_bubble_view_; -} - -void ProfileResetGlobalError::ShowBubbleView(Browser* browser) { - if (has_shown_bubble_view_) - return; - - has_shown_bubble_view_ = true; - bubble_view_ = browser->window()->ShowProfileResetBubble(AsWeakPtr()); - - if (automatic_profile_resetter_) - automatic_profile_resetter_->NotifyDidShowResetBubble(); - RecordPromptDelay(timer_.Elapsed()); -} - -void ProfileResetGlobalError::OnBubbleViewDidClose() { - bubble_view_ = NULL; -} - -void ProfileResetGlobalError::OnBubbleViewResetButtonPressed( - bool send_feedback) { - if (automatic_profile_resetter_) - automatic_profile_resetter_->TriggerProfileReset(send_feedback); -} - -void ProfileResetGlobalError::OnBubbleViewNoThanksButtonPressed() { - if (automatic_profile_resetter_) - automatic_profile_resetter_->SkipProfileReset(); -} - -GlobalErrorBubbleViewBase* ProfileResetGlobalError::GetBubbleView() { - return bubble_view_; -} diff --git a/chrome/browser/profile_resetter/profile_reset_global_error.h b/chrome/browser/profile_resetter/profile_reset_global_error.h deleted file mode 100644 index e3031fc..0000000 --- a/chrome/browser/profile_resetter/profile_reset_global_error.h +++ /dev/null @@ -1,72 +0,0 @@ -// Copyright 2013 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 CHROME_BROWSER_PROFILE_RESETTER_PROFILE_RESET_GLOBAL_ERROR_H_ -#define CHROME_BROWSER_PROFILE_RESETTER_PROFILE_RESET_GLOBAL_ERROR_H_ - -#include "base/basictypes.h" -#include "base/memory/weak_ptr.h" -#include "base/timer/elapsed_timer.h" -#include "chrome/browser/ui/global_error/global_error.h" - -class AutomaticProfileResetter; -class GlobalErrorBubbleViewBase; -class Profile; - -// Encapsulates UI-related functionality for the one-time profile settings reset -// prompt. The UI consists of two parts: (1.) the profile reset (pop-up) bubble, -// and (2.) a menu item in the wrench menu (provided by us being a GlobalError). -class ProfileResetGlobalError - : public GlobalError, - public base::SupportsWeakPtr<ProfileResetGlobalError> { - public: - explicit ProfileResetGlobalError(Profile* profile); - ~ProfileResetGlobalError() override; - - // Returns whether or not the reset prompt is supported on this platform. - static bool IsSupportedOnPlatform(Browser* browser); - - // Called by the bubble view when it is closed. - void OnBubbleViewDidClose(); - - // Called when the user clicks on the 'Reset' button. The user can choose to - // send feedback containing the old settings that are now being reset, this is - // indicated by |send_feedback|. - void OnBubbleViewResetButtonPressed(bool send_feedback); - - // Called when the user clicks the 'No, thanks' button. - void OnBubbleViewNoThanksButtonPressed(); - - // GlobalError: - bool HasMenuItem() override; - int MenuItemCommandID() override; - base::string16 MenuItemLabel() override; - void ExecuteMenuItem(Browser* browser) override; - bool HasBubbleView() override; - bool HasShownBubbleView() override; - void ShowBubbleView(Browser* browser) override; - GlobalErrorBubbleViewBase* GetBubbleView() override; - - private: - Profile* profile_; - - // GlobalErrorService owns us, on which AutomaticProfileResetter depends, so - // during shutdown, it may get destroyed before we are. - // Note: the AutomaticProfileResetter expects call-backs from us to always be - // synchronous, so that there will be no call-backs once we are destroyed. - base::WeakPtr<AutomaticProfileResetter> automatic_profile_resetter_; - - // Used to measure the delay before the bubble actually gets shown. - base::ElapsedTimer timer_; - - // Whether or not we have already shown the bubble. - bool has_shown_bubble_view_; - - // The reset bubble, if we're currently showing one. - GlobalErrorBubbleViewBase* bubble_view_; - - DISALLOW_COPY_AND_ASSIGN(ProfileResetGlobalError); -}; - -#endif // CHROME_BROWSER_PROFILE_RESETTER_PROFILE_RESET_GLOBAL_ERROR_H_ diff --git a/chrome/browser/profile_resetter/resettable_settings_snapshot.cc b/chrome/browser/profile_resetter/resettable_settings_snapshot.cc index 42c6f59..504876b 100644 --- a/chrome/browser/profile_resetter/resettable_settings_snapshot.cc +++ b/chrome/browser/profile_resetter/resettable_settings_snapshot.cc @@ -31,8 +31,7 @@ using feedback::FeedbackData; namespace { -// Feedback bucket labels. -const char kProfileResetPromptBucket[] = "SamplingOfSettingsResetPrompt"; +// Feedback bucket label. const char kProfileResetWebUIBucket[] = "ProfileResetReport"; // Dictionary keys for feedback report. @@ -222,19 +221,9 @@ std::string SerializeSettingsReport(const ResettableSettingsSnapshot& snapshot, } void SendSettingsFeedback(const std::string& report, - Profile* profile, - SnapshotCaller caller) { + Profile* profile) { scoped_refptr<FeedbackData> feedback_data = new FeedbackData(); - std::string bucket; - switch (caller) { - case PROFILE_RESET_WEBUI: - bucket = kProfileResetWebUIBucket; - break; - case PROFILE_RESET_PROMPT: - bucket = kProfileResetPromptBucket; - break; - } - feedback_data->set_category_tag(bucket); + feedback_data->set_category_tag(kProfileResetWebUIBucket); feedback_data->set_description(report); feedback_data->set_image(make_scoped_ptr(new std::string)); diff --git a/chrome/browser/profile_resetter/resettable_settings_snapshot.h b/chrome/browser/profile_resetter/resettable_settings_snapshot.h index 2022e97..e602cef 100644 --- a/chrome/browser/profile_resetter/resettable_settings_snapshot.h +++ b/chrome/browser/profile_resetter/resettable_settings_snapshot.h @@ -115,12 +115,6 @@ class ResettableSettingsSnapshot { DISALLOW_COPY_AND_ASSIGN(ResettableSettingsSnapshot); }; -// The caller of ResettableSettingsSnapshot. -enum SnapshotCaller { - PROFILE_RESET_WEBUI = 0, - PROFILE_RESET_PROMPT, -}; - // Serializes specified |snapshot| members to JSON format. |field_mask| is a bit // mask of ResettableSettingsSnapshot::Field values. std::string SerializeSettingsReport(const ResettableSettingsSnapshot& snapshot, @@ -129,8 +123,7 @@ std::string SerializeSettingsReport(const ResettableSettingsSnapshot& snapshot, // Sends |report| as a feedback. |report| is supposed to be result of // SerializeSettingsReport(). void SendSettingsFeedback(const std::string& report, - Profile* profile, - SnapshotCaller caller); + Profile* profile); // Returns list of key/value pairs for all available reported information // from the |profile| and some additional fields. diff --git a/chrome/browser/profiles/chrome_browser_main_extra_parts_profiles.cc b/chrome/browser/profiles/chrome_browser_main_extra_parts_profiles.cc index d5f51d6..bb7784e 100644 --- a/chrome/browser/profiles/chrome_browser_main_extra_parts_profiles.cc +++ b/chrome/browser/profiles/chrome_browser_main_extra_parts_profiles.cc @@ -123,7 +123,6 @@ #endif #if !defined(OS_ANDROID) -#include "chrome/browser/profile_resetter/automatic_profile_resetter_factory.h" #include "chrome/browser/ui/global_error/global_error_service_factory.h" #include "chrome/browser/usb/usb_chooser_context_factory.h" #endif @@ -184,9 +183,6 @@ EnsureBrowserContextKeyedServiceFactoriesBuilt() { AccountTrackerServiceFactory::GetInstance(); AccountFetcherServiceFactory::GetInstance(); autofill::PersonalDataManagerFactory::GetInstance(); -#if !defined(OS_ANDROID) - AutomaticProfileResetterFactory::GetInstance(); -#endif #if defined(ENABLE_BACKGROUND) BackgroundContentsServiceFactory::GetInstance(); #endif diff --git a/chrome/browser/resources/options/settings_banner.css b/chrome/browser/resources/options/automatic_settings_reset_banner.css index c4290ef..a62408f 100644 --- a/chrome/browser/resources/options/settings_banner.css +++ b/chrome/browser/resources/options/automatic_settings_reset_banner.css @@ -2,9 +2,6 @@ * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ -/* These styles are used by both reset_profile_settings_banner.html and - * automatic_settings_reset_banner.html. */ - .settings-banner { background-color: #f5f5f5; border-color: #c8c8c8; @@ -43,8 +40,8 @@ html[dir='rtl'] .settings-banner > .close-button { } .settings-banner .content-area { - -webkit-box-align: center; - display: -webkit-box; + align-items: center; + display: flex; padding: 17px; } @@ -57,8 +54,8 @@ html[dir='rtl'] .settings-banner > .close-button { } .settings-banner .content-area .text { - -webkit-box-flex: 1.0; -webkit-margin-start: 18px; + flex: 1.0; } .settings-banner .content-area .text p { diff --git a/chrome/browser/resources/options/automatic_settings_reset_banner.js b/chrome/browser/resources/options/automatic_settings_reset_banner.js index e0747c5..bdd9090 100644 --- a/chrome/browser/resources/options/automatic_settings_reset_banner.js +++ b/chrome/browser/resources/options/automatic_settings_reset_banner.js @@ -5,7 +5,6 @@ // Note: the native-side handler for this is AutomaticSettingsResetHandler. cr.define('options', function() { - /** @const */ var SettingsBannerBase = options.SettingsBannerBase; /** @const */ var PageManager = cr.ui.pageManager.PageManager; /** @@ -19,7 +18,38 @@ cr.define('options', function() { cr.addSingletonGetter(AutomaticSettingsResetBanner); AutomaticSettingsResetBanner.prototype = { - __proto__: SettingsBannerBase.prototype, + /** + * Whether or not the banner has already been dismissed. + * + * This is needed because of the surprising ordering of asynchronous + * JS<->native calls when the settings page is opened with specifying a + * given sub-page, e.g. chrome://settings/AutomaticSettingsReset. + * + * In such a case, AutomaticSettingsResetOverlay's didShowPage(), which + * calls our dismiss() method, would be called before the native Handlers' + * InitalizePage() methods have an effect in the JS, which includes calling + * our show() method. This would mean that the banner would be first + * dismissed, then shown. We want to prevent this. + * + * @type {boolean} + * @private + */ + hadBeenDismissed_: false, + + /** + * Metric name to send when a show event occurs. + */ + showMetricName_: '', + + /** + * Name of the native callback invoked when the banner is dismised. + */ + dismissNativeCallbackName_: '', + + /** + * DOM element whose visibility is set when setVisibility_ is called. + */ + setVisibilibyDomElement_: null, /** * Initializes the banner's event handlers. @@ -31,12 +61,12 @@ cr.define('options', function() { * private implementations using cr.makePublic(). */ initialize: function() { - this.showMetricName = 'AutomaticSettingsReset_WebUIBanner_BannerShown'; + this.showMetricName_ = 'AutomaticSettingsReset_WebUIBanner_BannerShown'; - this.dismissNativeCallbackName = + this.dismissNativeCallbackName_ = 'onDismissedAutomaticSettingsResetBanner'; - this.visibilityDomElement = $('automatic-settings-reset-banner'); + this.setVisibilibyDomElement_ = $('automatic-settings-reset-banner'); $('automatic-settings-reset-banner-close').onclick = function(event) { chrome.send('metricsHandler:recordAction', @@ -54,18 +84,45 @@ cr.define('options', function() { PageManager.showPageByName('resetProfileSettings'); }; }, + + /** + * Sets whether or not the reset profile settings banner shall be visible. + * @param {boolean} show Whether or not to show the banner. + * @protected + */ + setVisibility: function(show) { + this.setVisibilibyDomElement_.hidden = !show; + }, + + /** + * Called by the native code to show the banner if needed. + * @private + */ + show_: function() { + if (!this.hadBeenDismissed_) { + chrome.send('metricsHandler:recordAction', [this.showMetricName_]); + this.setVisibility(true); + } + }, + + /** + * Called when the banner should be closed as a result of something taking + * place on the WebUI page, i.e. when its close button is pressed, or when + * the confirmation dialog for the profile settings reset feature is opened. + * @private + */ + dismiss_: function() { + chrome.send(this.dismissNativeCallbackName_); + this.hadBeenDismissed_ = true; + this.setVisibility(false); + }, }; - // Forward public APIs to protected implementations. - [ + // Forward public APIs to private implementations. + cr.makePublic(AutomaticSettingsResetBanner, [ 'show', 'dismiss', - ].forEach(function(name) { - AutomaticSettingsResetBanner[name] = function() { - var instance = AutomaticSettingsResetBanner.getInstance(); - return instance[name].apply(instance, arguments); - }; - }); + ]); // Export return { diff --git a/chrome/browser/resources/options/browser_options.html b/chrome/browser/resources/options/browser_options.html index 3dd0fdd..9733e77 100644 --- a/chrome/browser/resources/options/browser_options.html +++ b/chrome/browser/resources/options/browser_options.html @@ -2,7 +2,6 @@ <header> <h1 i18n-content="settingsTitle"></h1> </header> - <include src="reset_profile_settings_banner.html"> <include src="automatic_settings_reset_banner.html"> <if expr="chromeos"> <link rel="import" href="chrome://resources/cr_elements/network/cr_network_icon.html"> diff --git a/chrome/browser/resources/options/options.html b/chrome/browser/resources/options/options.html index 14196b3..e6e1ee2 100644 --- a/chrome/browser/resources/options/options.html +++ b/chrome/browser/resources/options/options.html @@ -17,6 +17,7 @@ <link rel="stylesheet" href="alert_overlay.css"> <link rel="stylesheet" href="autofill_edit_overlay.css"> <link rel="stylesheet" href="autofill_options.css"> +<link rel="stylesheet" href="automatic_settings_reset_banner.css"> <link rel="stylesheet" href="browser_options.css"> <if expr="chromeos"> <link rel="stylesheet" href="chromeos/browser_options.css"> @@ -41,7 +42,6 @@ <link rel="stylesheet" href="reset_profile_settings_overlay.css"> <link rel="stylesheet" href="search_engine_manager.css"> <link rel="stylesheet" href="search_page.css"> -<link rel="stylesheet" href="settings_banner.css"> <link rel="stylesheet" href="spelling_confirm_overlay.css"> <link rel="stylesheet" href="startup_overlay.css"> <link rel="stylesheet" href="subpages_tab_controls.css"> diff --git a/chrome/browser/resources/options/options.js b/chrome/browser/resources/options/options.js index ab78887..d331855 100644 --- a/chrome/browser/resources/options/options.js +++ b/chrome/browser/resources/options/options.js @@ -35,7 +35,6 @@ var PageManager = cr.ui.pageManager.PageManager; var PasswordManager = options.PasswordManager; var Preferences = options.Preferences; var PreferredNetworks = options.PreferredNetworks; -var ResetProfileSettingsBanner = options.ResetProfileSettingsBanner; var ResetProfileSettingsOverlay = options.ResetProfileSettingsOverlay; var SearchEngineManager = options.SearchEngineManager; var SearchPage = options.SearchPage; @@ -240,7 +239,6 @@ function load() { OptionsFocusManager.getInstance().initialize(); Preferences.getInstance().initialize(); - ResetProfileSettingsBanner.getInstance().initialize(); AutomaticSettingsResetBanner.getInstance().initialize(); OptionsPage.initialize(); PageManager.initialize(BrowserOptions.getInstance()); diff --git a/chrome/browser/resources/options/options_bundle.js b/chrome/browser/resources/options/options_bundle.js index 27502bf..8a72e0d 100644 --- a/chrome/browser/resources/options/options_bundle.js +++ b/chrome/browser/resources/options/options_bundle.js @@ -14,7 +14,6 @@ <include src="options_page.js"> <include src="pref_ui.js"> <include src="settings_dialog.js"> -<include src="settings_banner.js"> <if expr="chromeos"> <include src="../chromeos/user_images_grid.js"> <include src="../help/channel_change_page.js"> @@ -104,7 +103,6 @@ var CertificateImportErrorOverlay = options.CertificateImportErrorOverlay; <include src="password_manager.js"> <include src="password_manager_list.js"> <include src="profiles_icon_grid.js"> -<include src="reset_profile_settings_banner.js"> <include src="reset_profile_settings_overlay.js"> <include src="search_engine_manager.js"> <include src="search_engine_manager_engine_list.js"> diff --git a/chrome/browser/resources/options/reset_profile_settings_banner.html b/chrome/browser/resources/options/reset_profile_settings_banner.html deleted file mode 100644 index fd95c3c..0000000 --- a/chrome/browser/resources/options/reset_profile_settings_banner.html +++ /dev/null @@ -1,18 +0,0 @@ -<div id="reset-profile-settings-banner" class="settings-banner" hidden> - <div id="reset-profile-settings-banner-close" class="close-button"></div> - <div class="content-area"> - <div class="badge"></div> - <div class="text"> - <p> - <span i18n-values=".innerHTML:resetProfileSettingsBannerText"> - </span> - <a class="nowrap" i18n-values="href:resetProfileSettingsLearnMoreUrl" - i18n-content="learnMore" target="_blank"></a> - </p> - </div> - <div class="button-area"> - <button id="reset-profile-settings-banner-activate" - i18n-content="resetProfileSettings"></button> - </div> - </div> -</div> diff --git a/chrome/browser/resources/options/reset_profile_settings_banner.js b/chrome/browser/resources/options/reset_profile_settings_banner.js deleted file mode 100644 index 4785113..0000000 --- a/chrome/browser/resources/options/reset_profile_settings_banner.js +++ /dev/null @@ -1,66 +0,0 @@ -// Copyright 2013 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. - -// Note: the native-side handler for this is ResetProfileSettingsHandler. - -cr.define('options', function() { - /** @const */ var PageManager = cr.ui.pageManager.PageManager; - /** @const */ var SettingsBannerBase = options.SettingsBannerBase; - - /** - * ResetProfileSettingsBanner class - * Provides encapsulated handling of the Reset Profile Settings banner. - * @constructor - * @extends {options.SettingsBannerBase} - */ - function ResetProfileSettingsBanner() {} - - cr.addSingletonGetter(ResetProfileSettingsBanner); - - ResetProfileSettingsBanner.prototype = { - __proto__: SettingsBannerBase.prototype, - - /** - * Initializes the banner's event handlers. - * @suppress {checkTypes} - * TODO(vitalyp): remove the suppression. See the explanation in - * chrome/browser/resources/options/automatic_settings_reset_banner.js. - */ - initialize: function() { - this.showMetricName = 'AutomaticReset_WebUIBanner_BannerShown'; - - this.dismissNativeCallbackName = - 'onDismissedResetProfileSettingsBanner'; - - this.visibilityDomElement = $('reset-profile-settings-banner'); - - $('reset-profile-settings-banner-close').onclick = function(event) { - chrome.send('metricsHandler:recordAction', - ['AutomaticReset_WebUIBanner_ManuallyClosed']); - ResetProfileSettingsBanner.dismiss(); - }; - $('reset-profile-settings-banner-activate').onclick = function(event) { - chrome.send('metricsHandler:recordAction', - ['AutomaticReset_WebUIBanner_ResetClicked']); - PageManager.showPageByName('resetProfileSettings'); - }; - }, - }; - - // Forward public APIs to protected implementations. - [ - 'show', - 'dismiss', - ].forEach(function(name) { - ResetProfileSettingsBanner[name] = function() { - var instance = ResetProfileSettingsBanner.getInstance(); - return instance[name].apply(instance, arguments); - }; - }); - - // Export - return { - ResetProfileSettingsBanner: ResetProfileSettingsBanner - }; -}); diff --git a/chrome/browser/resources/options/reset_profile_settings_overlay.js b/chrome/browser/resources/options/reset_profile_settings_overlay.js index 2c247dc..7da9e29 100644 --- a/chrome/browser/resources/options/reset_profile_settings_overlay.js +++ b/chrome/browser/resources/options/reset_profile_settings_overlay.js @@ -6,7 +6,6 @@ cr.define('options', function() { var Page = cr.ui.pageManager.Page; var AutomaticSettingsResetBanner = options.AutomaticSettingsResetBanner; - var ResetProfileSettingsBanner = options.ResetProfileSettingsBanner; /** * ResetProfileSettingsOverlay class @@ -57,7 +56,6 @@ cr.define('options', function() { $('reset-profile-settings-explanation').textContent = loadTimeData.getString('resetProfileSettingsExplanation'); - ResetProfileSettingsBanner.dismiss(); chrome.send('onShowResetProfileDialog'); }, diff --git a/chrome/browser/resources/options/settings_banner.js b/chrome/browser/resources/options/settings_banner.js deleted file mode 100644 index 666aaf2..0000000 --- a/chrome/browser/resources/options/settings_banner.js +++ /dev/null @@ -1,89 +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. - -cr.define('options', function() { - - /** - * Base class for banners that appear at the top of the settings page. - * @constructor - */ - function SettingsBannerBase() {} - - cr.addSingletonGetter(SettingsBannerBase); - - SettingsBannerBase.prototype = { - /** - * Whether or not the banner has already been dismissed. - * - * This is needed because of the surprising ordering of asynchronous - * JS<->native calls when the settings page is opened with specifying a - * given sub-page, e.g. chrome://settings/AutomaticSettingsReset. - * - * In such a case, AutomaticSettingsResetOverlay's didShowPage(), which - * calls our dismiss() method, would be called before the native Handlers' - * InitalizePage() methods have an effect in the JS, which includes calling - * our show() method. This would mean that the banner would be first - * dismissed, then shown. We want to prevent this. - * - * @type {boolean} - * @private - */ - hadBeenDismissed_: false, - - /** - * Metric name to send when a show event occurs. - * @protected - */ - showMetricName: '', - - /** - * Name of the native callback invoked when the banner is dismised. - * @protected - */ - dismissNativeCallbackName: '', - - /** - * DOM element whose visibility is set when setVisibility_ is called. - * @protected - */ - visibilityDomElement: null, - - /** - * Called by the native code to show the banner if needed. - * @protected - */ - show: function() { - if (!this.hadBeenDismissed_) { - chrome.send('metricsHandler:recordAction', [this.showMetricName]); - this.setVisibility_(true); - } - }, - - /** - * Called when the banner should be closed as a result of something taking - * place on the WebUI page, i.e. when its close button is pressed, or when - * the confirmation dialog for the profile settings reset feature is opened. - * @protected - */ - dismiss: function() { - chrome.send(this.dismissNativeCallbackName); - this.hadBeenDismissed_ = true; - this.setVisibility_(false); - }, - - /** - * Sets whether or not the reset profile settings banner shall be visible. - * @param {boolean} show Whether or not to show the banner. - * @private - */ - setVisibility_: function(show) { - this.visibilityDomElement.hidden = !show; - }, - }; - - // Export - return { - SettingsBannerBase: SettingsBannerBase - }; -}); diff --git a/chrome/browser/resources/options/triggered_reset_profile_settings_overlay.js b/chrome/browser/resources/options/triggered_reset_profile_settings_overlay.js index 9ed58cb..35cd029 100644 --- a/chrome/browser/resources/options/triggered_reset_profile_settings_overlay.js +++ b/chrome/browser/resources/options/triggered_reset_profile_settings_overlay.js @@ -6,7 +6,6 @@ cr.define('options', function() { var Page = cr.ui.pageManager.Page; var ResetProfileSettingsOverlay = options.ResetProfileSettingsOverlay; - var ResetProfileSettingsBanner = options.ResetProfileSettingsBanner; /** * TriggeredResetProfileSettingsOverlay class @@ -37,7 +36,6 @@ cr.define('options', function() { loadTimeData.getString('triggeredResetProfileSettingsOverlay'); $('reset-profile-settings-explanation').textContent = loadTimeData.getString('triggeredResetProfileSettingsExplanation'); - ResetProfileSettingsBanner.dismiss(); chrome.send('onShowResetProfileDialog'); }, }; diff --git a/chrome/browser/ui/browser_window.h b/chrome/browser/ui/browser_window.h index 7f4d216..b41962f 100644 --- a/chrome/browser/ui/browser_window.h +++ b/chrome/browser/ui/browser_window.h @@ -268,11 +268,6 @@ class BrowserWindow : public ui::BaseWindow { translate::TranslateErrors::Type error_type, bool is_user_gesture) = 0; - // Shows the profile reset bubble on the platforms that support it. - virtual bool IsProfileResetBubbleSupported() const = 0; - virtual GlobalErrorBubbleViewBase* ShowProfileResetBubble( - const base::WeakPtr<ProfileResetGlobalError>& global_error) = 0; - #if defined(ENABLE_ONE_CLICK_SIGNIN) enum OneClickSigninBubbleType { ONE_CLICK_SIGNIN_BUBBLE_TYPE_BUBBLE, diff --git a/chrome/browser/ui/cocoa/browser_window_cocoa.h b/chrome/browser/ui/cocoa/browser_window_cocoa.h index c58e1be..43f633c 100644 --- a/chrome/browser/ui/cocoa/browser_window_cocoa.h +++ b/chrome/browser/ui/cocoa/browser_window_cocoa.h @@ -124,9 +124,6 @@ class BrowserWindowCocoa translate::TranslateStep step, translate::TranslateErrors::Type error_type, bool is_user_gesture) override; - bool IsProfileResetBubbleSupported() const override; - GlobalErrorBubbleViewBase* ShowProfileResetBubble( - const base::WeakPtr<ProfileResetGlobalError>& global_error) override; #if defined(ENABLE_ONE_CLICK_SIGNIN) void ShowOneClickSigninBubble( OneClickSigninBubbleType type, diff --git a/chrome/browser/ui/cocoa/browser_window_cocoa.mm b/chrome/browser/ui/cocoa/browser_window_cocoa.mm index d98c565..0c70306 100644 --- a/chrome/browser/ui/cocoa/browser_window_cocoa.mm +++ b/chrome/browser/ui/cocoa/browser_window_cocoa.mm @@ -661,16 +661,6 @@ void BrowserWindowCocoa::ShowTranslateBubble( errorType:error_type]; } -bool BrowserWindowCocoa::IsProfileResetBubbleSupported() const { - return false; -} - -GlobalErrorBubbleViewBase* BrowserWindowCocoa::ShowProfileResetBubble( - const base::WeakPtr<ProfileResetGlobalError>& global_error) { - NOTREACHED(); - return nullptr; -} - #if defined(ENABLE_ONE_CLICK_SIGNIN) void BrowserWindowCocoa::ShowOneClickSigninBubble( OneClickSigninBubbleType type, diff --git a/chrome/browser/ui/views/frame/browser_view.cc b/chrome/browser/ui/views/frame/browser_view.cc index 810d9f0..1271b2f 100644 --- a/chrome/browser/ui/views/frame/browser_view.cc +++ b/chrome/browser/ui/views/frame/browser_view.cc @@ -80,7 +80,6 @@ #include "chrome/browser/ui/views/omnibox/omnibox_view_views.h" #include "chrome/browser/ui/views/profiles/avatar_menu_button.h" #include "chrome/browser/ui/views/profiles/profile_chooser_view.h" -#include "chrome/browser/ui/views/profiles/profile_reset_bubble_view.h" #include "chrome/browser/ui/views/session_crashed_bubble_view.h" #include "chrome/browser/ui/views/settings_api_bubble_helper_views.h" #include "chrome/browser/ui/views/status_bubble_views.h" @@ -1330,15 +1329,6 @@ void BrowserView::ShowTranslateBubble( : TranslateBubbleView::AUTOMATIC); } -bool BrowserView::IsProfileResetBubbleSupported() const { - return true; -} - -GlobalErrorBubbleViewBase* BrowserView::ShowProfileResetBubble( - const base::WeakPtr<ProfileResetGlobalError>& global_error) { - return ProfileResetBubbleView::ShowBubble(global_error, browser_.get()); -} - #if defined(ENABLE_ONE_CLICK_SIGNIN) void BrowserView::ShowOneClickSigninBubble( OneClickSigninBubbleType type, diff --git a/chrome/browser/ui/views/frame/browser_view.h b/chrome/browser/ui/views/frame/browser_view.h index 1f0e6c0..5b1490c 100644 --- a/chrome/browser/ui/views/frame/browser_view.h +++ b/chrome/browser/ui/views/frame/browser_view.h @@ -326,9 +326,6 @@ class BrowserView : public BrowserWindow, translate::TranslateStep step, translate::TranslateErrors::Type error_type, bool is_user_gesture) override; - bool IsProfileResetBubbleSupported() const override; - GlobalErrorBubbleViewBase* ShowProfileResetBubble( - const base::WeakPtr<ProfileResetGlobalError>& global_error) override; #if defined(ENABLE_ONE_CLICK_SIGNIN) void ShowOneClickSigninBubble( OneClickSigninBubbleType type, diff --git a/chrome/browser/ui/views/profiles/profile_reset_bubble_view.cc b/chrome/browser/ui/views/profiles/profile_reset_bubble_view.cc deleted file mode 100644 index 8aaed74..0000000 --- a/chrome/browser/ui/views/profiles/profile_reset_bubble_view.cc +++ /dev/null @@ -1,438 +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 "chrome/browser/ui/views/profiles/profile_reset_bubble_view.h" - -#include "chrome/app/chrome_command_ids.h" -#include "chrome/browser/profile_resetter/profile_reset_global_error.h" -#include "chrome/browser/profile_resetter/resettable_settings_snapshot.h" -#include "chrome/browser/ui/global_error/global_error_service.h" -#include "chrome/browser/ui/global_error/global_error_service_factory.h" -#include "chrome/browser/ui/views/frame/browser_view.h" -#include "chrome/browser/ui/views/toolbar/app_menu_button.h" -#include "chrome/browser/ui/views/toolbar/toolbar_view.h" -#include "chrome/common/url_constants.h" -#include "components/google/core/browser/google_util.h" -#include "content/public/browser/page_navigator.h" -#include "content/public/browser/user_metrics.h" -#include "grit/chromium_strings.h" -#include "grit/components_strings.h" -#include "grit/generated_resources.h" -#include "grit/theme_resources.h" -#include "ui/base/l10n/l10n_util.h" -#include "ui/base/resource/resource_bundle.h" -#include "ui/gfx/image/image_skia_operations.h" -#include "ui/views/background.h" -#include "ui/views/controls/button/checkbox.h" -#include "ui/views/controls/button/image_button.h" -#include "ui/views/controls/button/label_button.h" -#include "ui/views/controls/label.h" -#include "ui/views/controls/link.h" -#include "ui/views/controls/scroll_view.h" -#include "ui/views/controls/separator.h" -#include "ui/views/layout/grid_layout.h" -#include "ui/views/layout/layout_constants.h" - -using views::GridLayout; - -namespace { - -// Fixed width of the column holding the description label of the bubble. -const int kWidthOfDescriptionText = 370; - -// Margins width for the top rows to compensate for the bottom panel for which -// we don't want any margin. -const int kMarginWidth = 12; -const int kMarginHeight = kMarginWidth; - -// Width of a colum in the FeedbackView. -const int kFeedbackViewColumnWidth = kWidthOfDescriptionText / 2 + kMarginWidth; - -// Width of the column used to disaplay the help button. -const int kHelpButtonColumnWidth = 30; - -// Width of the reporting checkbox column. -const int kReportingCheckboxColumnWidth = - kWidthOfDescriptionText + 2 * kMarginWidth; - -// Full width including all columns. -const int kAllColumnsWidth = - kReportingCheckboxColumnWidth + kHelpButtonColumnWidth; - -// Maximum height of the scrollable feedback view. -const int kMaxFeedbackViewHeight = 450; - -// The vertical padding between two values in the feedback view. -const int kInterFeedbackValuePadding = 4; - -// We subtract 2 to account for the natural button padding, and -// to bring the separation visually in line with the row separation -// height. -const int kButtonPadding = views::kRelatedButtonHSpacing - 2; - -// The color of the background of the sub panel to report current settings. -const SkColor kLightGrayBackgroundColor = 0xFFF5F5F5; - -// This view is used to contain the scrollable contents that are shown the user -// to expose what feedback will be sent back to Google. -class FeedbackView : public views::View { - public: - FeedbackView() {} - - // Setup the layout manager of the Feedback view using the content of the - // |feedback| ListValue which contains a list of key/value pairs stored in - // DictionaryValues. The key is to be displayed right aligned on the left, and - // the value as a left aligned multiline text on the right. - void SetupLayoutManager(const base::ListValue& feedback) { - RemoveAllChildViews(true); - set_background(views::Background::CreateSolidBackground( - kLightGrayBackgroundColor)); - - GridLayout* layout = new GridLayout(this); - SetLayoutManager(layout); - - // We only need a single column set for left/right text and middle margin. - views::ColumnSet* cs = layout->AddColumnSet(0); - cs->AddColumn(GridLayout::FILL, GridLayout::LEADING, 1, - GridLayout::FIXED, kFeedbackViewColumnWidth, 0); - cs->AddPaddingColumn(0, kMarginWidth); - cs->AddColumn(GridLayout::FILL, GridLayout::FILL, 1, - GridLayout::FIXED, kFeedbackViewColumnWidth, 0); - for (size_t i = 0; i < feedback.GetSize(); ++i) { - const base::DictionaryValue* dictionary = NULL; - if (!feedback.GetDictionary(i, &dictionary) || !dictionary) - continue; - - base::string16 key; - if (!dictionary->GetString("key", &key)) - continue; - - base::string16 value; - if (!dictionary->GetString("value", &value)) - continue; - - // The key is shown on the left, multi-line (required to allow wrapping in - // case the key name does not fit), and right-aligned. - views::Label* left_text_label = new views::Label(key); - left_text_label->SetMultiLine(true); - left_text_label->SetEnabledColor(SK_ColorGRAY); - left_text_label->SetHorizontalAlignment(gfx::ALIGN_RIGHT); - - // The value is shown on the right, multi-line, left-aligned. - views::Label* right_text_label = new views::Label(value); - right_text_label->SetMultiLine(true); - right_text_label->SetEnabledColor(SK_ColorDKGRAY); - right_text_label->SetHorizontalAlignment(gfx::ALIGN_LEFT); - - layout->StartRow(0, 0); - layout->AddView(left_text_label); - layout->AddView(right_text_label); - layout->AddPaddingRow(0, kInterFeedbackValuePadding); - } - - // We need to set our size to our preferred size because our parent is a - // scroll view and doesn't know which size to set us to. Also since our - // parent scrolls, we are not bound to its size. So our size is based on the - // size computed by the our layout manager, which is what - // SizeToPreferredSize() does. - SizeToPreferredSize(); - } - - private: - DISALLOW_COPY_AND_ASSIGN(FeedbackView); -}; - -} // namespace - -// ProfileResetBubbleView --------------------------------------------------- - -// static -ProfileResetBubbleView* ProfileResetBubbleView::ShowBubble( - const base::WeakPtr<ProfileResetGlobalError>& global_error, - Browser* browser) { - views::View* anchor_view = BrowserView::GetBrowserViewForBrowser(browser) - ->toolbar() - ->app_menu_button(); - ProfileResetBubbleView* reset_bubble = new ProfileResetBubbleView( - global_error, anchor_view, browser, browser->profile()); - views::BubbleDelegateView::CreateBubble(reset_bubble)->Show(); - content::RecordAction(base::UserMetricsAction("SettingsResetBubble.Show")); - return reset_bubble; -} - -ProfileResetBubbleView::~ProfileResetBubbleView() {} - -views::View* ProfileResetBubbleView::GetInitiallyFocusedView() { - return controls_.reset_button; -} - -void ProfileResetBubbleView::WindowClosing() { - if (global_error_) - global_error_->OnBubbleViewDidClose(); -} - -ProfileResetBubbleView::ProfileResetBubbleView( - const base::WeakPtr<ProfileResetGlobalError>& global_error, - views::View* anchor_view, - content::PageNavigator* navigator, - Profile* profile) - : BubbleDelegateView(anchor_view, views::BubbleBorder::TOP_RIGHT), - navigator_(navigator), - profile_(profile), - global_error_(global_error), - resetting_(false), - chose_to_reset_(false), - show_help_pane_(false), - weak_factory_(this) { -} - -void ProfileResetBubbleView::ResetAllChildren() { - controls_.Reset(); - SetLayoutManager(NULL); - RemoveAllChildViews(true); -} - -void ProfileResetBubbleView::Init() { - set_margins(gfx::Insets(kMarginHeight, 0, 0, 0)); - // Start requesting the feedback data. - snapshot_.reset(new ResettableSettingsSnapshot(profile_)); - snapshot_->RequestShortcuts( - base::Bind(&ProfileResetBubbleView::UpdateFeedbackDetails, - weak_factory_.GetWeakPtr())); - SetupLayoutManager(true); -} - -void ProfileResetBubbleView::SetupLayoutManager(bool report_checked) { - ResetAllChildren(); - - base::string16 product_name( - l10n_util::GetStringUTF16(IDS_SHORT_PRODUCT_NAME)); - ui::ResourceBundle& rb = ui::ResourceBundle::GetSharedInstance(); - - // Bubble title label. - views::Label* title_label = new views::Label( - l10n_util::GetStringFUTF16(IDS_RESET_BUBBLE_TITLE, product_name), - rb.GetFontList(ui::ResourceBundle::BoldFont)); - title_label->SetHorizontalAlignment(gfx::ALIGN_LEFT); - - // Description text label. - views::Label* text_label = new views::Label( - l10n_util::GetStringFUTF16(IDS_RESET_BUBBLE_TEXT, product_name)); - text_label->SetMultiLine(true); - text_label->SetLineHeight(20); - text_label->SetEnabledColor(SK_ColorDKGRAY); - text_label->SetHorizontalAlignment(gfx::ALIGN_LEFT); - - // Learn more link. - views::Link* learn_more_link = new views::Link( - l10n_util::GetStringUTF16(IDS_LEARN_MORE)); - learn_more_link->SetHorizontalAlignment(gfx::ALIGN_LEFT); - learn_more_link->set_listener(this); - learn_more_link->SetUnderline(false); - - // Reset button's name is based on |resetting_| state. - int reset_button_string_id = IDS_RESET_PROFILE_SETTINGS_COMMIT_BUTTON; - if (resetting_) - reset_button_string_id = IDS_RESETTING; - controls_.reset_button = new views::LabelButton( - this, l10n_util::GetStringUTF16(reset_button_string_id)); - controls_.reset_button->SetStyle(views::Button::STYLE_BUTTON); - controls_.reset_button->SetIsDefault(true); - controls_.reset_button->SetFontList( - rb.GetFontList(ui::ResourceBundle::BoldFont)); - controls_.reset_button->SetEnabled(!resetting_); - // For the Resetting... text to fit. - gfx::Size reset_button_size = controls_.reset_button->GetPreferredSize(); - reset_button_size.set_width(100); - controls_.reset_button->SetMinSize(reset_button_size); - - // No thanks button. - controls_.no_thanks_button = new views::LabelButton( - this, l10n_util::GetStringUTF16(IDS_NO_THANKS)); - controls_.no_thanks_button->SetStyle(views::Button::STYLE_BUTTON); - controls_.no_thanks_button->SetEnabled(!resetting_); - - // Checkbox for reporting settings or not. - controls_.report_settings_checkbox = new views::Checkbox( - l10n_util::GetStringUTF16(IDS_REPORT_BUBBLE_TEXT)); - controls_.report_settings_checkbox->SetTextColor( - views::Button::STATE_NORMAL, SK_ColorGRAY); - controls_.report_settings_checkbox->SetChecked(report_checked); - controls_.report_settings_checkbox->SetTextMultiLine(true); - controls_.report_settings_checkbox->set_background( - views::Background::CreateSolidBackground(kLightGrayBackgroundColor)); - // Have a smaller margin on the right, to have the |controls_.help_button| - // closer to the edge. - controls_.report_settings_checkbox->SetBorder( - views::Border::CreateSolidSidedBorder(kMarginWidth, - kMarginWidth, - kMarginWidth, - kMarginWidth / 2, - kLightGrayBackgroundColor)); - - // Help button to toggle the bottom panel on or off. - controls_.help_button = new views::ImageButton(this); - const gfx::ImageSkia* help_image = rb.GetImageSkiaNamed(IDR_QUESTION_MARK); - color_utils::HSL hsl_shift = { -1, 0, 0.8 }; - brighter_help_image_ = gfx::ImageSkiaOperations::CreateHSLShiftedImage( - *help_image, hsl_shift); - controls_.help_button->SetImage( - views::Button::STATE_NORMAL, &brighter_help_image_); - controls_.help_button->SetImage(views::Button::STATE_HOVERED, help_image); - controls_.help_button->SetImage(views::Button::STATE_PRESSED, help_image); - controls_.help_button->set_background( - views::Background::CreateSolidBackground(kLightGrayBackgroundColor)); - controls_.help_button->SetImageAlignment(views::ImageButton::ALIGN_CENTER, - views::ImageButton::ALIGN_MIDDLE); - - GridLayout* layout = new GridLayout(this); - SetLayoutManager(layout); - - // Title row. - const int kTitleColumnSetId = 0; - views::ColumnSet* cs = layout->AddColumnSet(kTitleColumnSetId); - cs->AddPaddingColumn(0, kMarginWidth); - cs->AddColumn(GridLayout::LEADING, GridLayout::CENTER, 0, - GridLayout::USE_PREF, 0, 0); - cs->AddPaddingColumn(0, kMarginWidth); - - // Text row. - const int kTextColumnSetId = 1; - cs = layout->AddColumnSet(kTextColumnSetId); - cs->AddPaddingColumn(0, kMarginWidth); - cs->AddColumn(GridLayout::FILL, GridLayout::FILL, 0, - GridLayout::FIXED, kWidthOfDescriptionText, 0); - cs->AddPaddingColumn(0, kMarginWidth); - - // Learn more link & buttons row. - const int kButtonsColumnSetId = 2; - cs = layout->AddColumnSet(kButtonsColumnSetId); - cs->AddPaddingColumn(0, kMarginWidth); - cs->AddColumn(GridLayout::LEADING, GridLayout::CENTER, 0, - GridLayout::USE_PREF, 0, 0); - cs->AddPaddingColumn(1, views::kRelatedControlHorizontalSpacing); - cs->AddColumn(GridLayout::LEADING, GridLayout::TRAILING, 0, - GridLayout::USE_PREF, 0, 0); - cs->AddPaddingColumn(0, kButtonPadding); - cs->AddColumn(GridLayout::LEADING, GridLayout::TRAILING, 0, - GridLayout::USE_PREF, 0, 0); - cs->AddPaddingColumn(0, kMarginWidth); - - // Separator. - const int kSeparatorColumnSetId = 3; - cs = layout->AddColumnSet(kSeparatorColumnSetId); - cs->AddColumn(GridLayout::FILL, GridLayout::FILL, 0, - GridLayout::FIXED, kAllColumnsWidth, 0); - - // Reporting row. - const int kReportColumnSetId = 4; - cs = layout->AddColumnSet(kReportColumnSetId); - cs->AddColumn(GridLayout::FILL, GridLayout::FILL, 0, - GridLayout::FIXED, kReportingCheckboxColumnWidth, 0); - cs->AddColumn(GridLayout::FILL, GridLayout::FILL, 0, - GridLayout::FIXED, kHelpButtonColumnWidth, 0); - - layout->StartRow(0, kTitleColumnSetId); - layout->AddView(title_label); - layout->AddPaddingRow(0, kMarginHeight); - - layout->StartRow(0, kTextColumnSetId); - layout->AddView(text_label); - layout->AddPaddingRow(0, kMarginHeight); - - layout->StartRow(0, kButtonsColumnSetId); - layout->AddView(learn_more_link); - layout->AddView(controls_.reset_button); - layout->AddView(controls_.no_thanks_button); - layout->AddPaddingRow(0, kMarginHeight); - - layout->StartRow(0, kSeparatorColumnSetId); - layout->AddView(new views::Separator(views::Separator::HORIZONTAL)); - - layout->StartRow(0, kReportColumnSetId); - layout->AddView(controls_.report_settings_checkbox); - layout->AddView(controls_.help_button); - - if (show_help_pane_ && snapshot_) { - // We need a single row to add the scroll view containing the feedback. - const int kReportDetailsColumnSetId = 5; - cs = layout->AddColumnSet(kReportDetailsColumnSetId); - cs->AddColumn(GridLayout::FILL, GridLayout::FILL, 1, - GridLayout::USE_PREF, 0, 0); - - FeedbackView* feedback_view = new FeedbackView(); - scoped_ptr<base::ListValue> feedback_data = - GetReadableFeedbackForSnapshot(profile_, *snapshot_); - feedback_view->SetupLayoutManager(*feedback_data); - - views::ScrollView* scroll_view = new views::ScrollView(); - scroll_view->set_background(views::Background::CreateSolidBackground( - kLightGrayBackgroundColor)); - scroll_view->SetContents(feedback_view); - - layout->StartRow(1, kReportDetailsColumnSetId); - layout->AddView(scroll_view, 1, 1, GridLayout::FILL, - GridLayout::FILL, kAllColumnsWidth, - std::min(feedback_view->height() + kMarginHeight, - kMaxFeedbackViewHeight)); - } - - Layout(); - AddAccelerator(ui::Accelerator(ui::VKEY_RETURN, ui::EF_NONE)); -} - -void ProfileResetBubbleView::ButtonPressed(views::Button* sender, - const ui::Event& event) { - if (sender == controls_.reset_button) { - DCHECK(!resetting_); - content::RecordAction( - base::UserMetricsAction("SettingsResetBubble.Reset")); - - // Remember that the user chose to reset, and that resetting is underway. - chose_to_reset_ = true; - resetting_ = true; - - controls_.reset_button->SetText(l10n_util::GetStringUTF16(IDS_RESETTING)); - controls_.reset_button->SetEnabled(false); - controls_.no_thanks_button->SetEnabled(false); - SchedulePaint(); - - if (global_error_) { - global_error_->OnBubbleViewResetButtonPressed( - controls_.report_settings_checkbox->checked()); - } - } else if (sender == controls_.no_thanks_button) { - DCHECK(!resetting_); - content::RecordAction( - base::UserMetricsAction("SettingsResetBubble.NoThanks")); - - if (global_error_) - global_error_->OnBubbleViewNoThanksButtonPressed(); - GetWidget()->Close(); - return; - } else if (sender == controls_.help_button) { - show_help_pane_ = !show_help_pane_; - - SetupLayoutManager(controls_.report_settings_checkbox->checked()); - SizeToContents(); - } -} - -void ProfileResetBubbleView::LinkClicked(views::Link* source, int flags) { - content::RecordAction( - base::UserMetricsAction("SettingsResetBubble.LearnMore")); - navigator_->OpenURL(content::OpenURLParams( - GURL(chrome::kResetProfileSettingsLearnMoreURL), content::Referrer(), - NEW_FOREGROUND_TAB, ui::PAGE_TRANSITION_LINK, false)); -} - -void ProfileResetBubbleView::CloseBubbleView() { - resetting_ = false; - GetWidget()->Close(); -} - -void ProfileResetBubbleView::UpdateFeedbackDetails() { - if (show_help_pane_) - SetupLayoutManager(controls_.report_settings_checkbox->checked()); -} diff --git a/chrome/browser/ui/views/profiles/profile_reset_bubble_view.h b/chrome/browser/ui/views/profiles/profile_reset_bubble_view.h deleted file mode 100644 index 771822a..0000000 --- a/chrome/browser/ui/views/profiles/profile_reset_bubble_view.h +++ /dev/null @@ -1,137 +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 CHROME_BROWSER_UI_VIEWS_PROFILES_PROFILE_RESET_BUBBLE_VIEW_H_ -#define CHROME_BROWSER_UI_VIEWS_PROFILES_PROFILE_RESET_BUBBLE_VIEW_H_ - -#include "base/callback.h" -#include "base/memory/scoped_ptr.h" -#include "base/memory/weak_ptr.h" -#include "base/values.h" -#include "chrome/browser/ui/global_error/global_error_bubble_view_base.h" -#include "ui/gfx/image/image_skia.h" -#include "ui/views/bubble/bubble_delegate.h" -#include "ui/views/controls/button/button.h" -#include "ui/views/controls/link_listener.h" - -namespace content { -class PageNavigator; -} - -namespace views { -class Checkbox; -class ImageButton; -class LabelButton; -class Link; -} - -class Browser; -class Profile; -class ProfileResetGlobalError; -class ResettableSettingsSnapshot; - -// ProfileResetBubbleView warns the user that a settings reset might be needed. -// It is intended to be used as the content of a bubble anchored off of the -// Chrome toolbar. -class ProfileResetBubbleView : public views::BubbleDelegateView, - public views::ButtonListener, - public views::LinkListener, - public GlobalErrorBubbleViewBase { - public: - static ProfileResetBubbleView* ShowBubble( - const base::WeakPtr<ProfileResetGlobalError>& global_error, - Browser* browser); - - // views::BubbleDelegateView methods. - views::View* GetInitiallyFocusedView() override; - void Init() override; - - // views::WidgetDelegate method. - void WindowClosing() override; - - // GlobalErrorBubbleViewBase: - void CloseBubbleView() override; - - private: - ProfileResetBubbleView( - const base::WeakPtr<ProfileResetGlobalError>& global_error, - views::View* anchor_view, - content::PageNavigator* navigator, - Profile* profile); - - ~ProfileResetBubbleView() override; - - // Reset all child views members and remove children from view hierarchy. - void ResetAllChildren(); - - // Sets up the layout manager and set the report checkbox to the value passed - // in |report_checked|. - void SetupLayoutManager(bool report_checked); - - // views::ButtonListener method. - void ButtonPressed(views::Button* sender, const ui::Event& event) override; - - // views::LinkListener method. - void LinkClicked(views::Link* source, int event_flags) override; - - // Sets the fully populated feedback data. - void UpdateFeedbackDetails(); - - struct Controls { - Controls() { - Reset(); - } - void Reset() { - reset_button = NULL; - no_thanks_button = NULL; - help_button = NULL; - report_settings_checkbox = NULL; - } - - // Button for the user to confirm a settings reset. - views::LabelButton* reset_button; - - // Button for the user to refuse a settings reset. - views::LabelButton* no_thanks_button; - - // Button for the user to get more info about reporting settings. - views::ImageButton* help_button; - - // Checkbox for the user to choose to report the settings or not. - views::Checkbox* report_settings_checkbox; - } controls_; - - // The snapshot is used to show user feedback information. - scoped_ptr<ResettableSettingsSnapshot> snapshot_; - - // A version of the help image that is brighter. - gfx::ImageSkia brighter_help_image_; - - // Used for opening the learn more link. - content::PageNavigator* navigator_; - - // Used to access profile specific stuff like the global error or readable - // feedback. - Profile* profile_; - - // The GlobalError this Bubble belongs to. - base::WeakPtr<ProfileResetGlobalError> global_error_; - - // Remembers if we are currently resetting or not. - bool resetting_; - - // Remembers if the reset button was hit before closing the bubble. - bool chose_to_reset_; - - // Toggles when the user clicks on the |help_button_| to identify if we should - // show the help pane or not. - bool show_help_pane_; - - // To cancel pending callbacks after destruction. - base::WeakPtrFactory<ProfileResetBubbleView> weak_factory_; - - DISALLOW_COPY_AND_ASSIGN(ProfileResetBubbleView); -}; - -#endif // CHROME_BROWSER_UI_VIEWS_PROFILES_PROFILE_RESET_BUBBLE_VIEW_H_ diff --git a/chrome/browser/ui/webui/options/reset_profile_settings_handler.cc b/chrome/browser/ui/webui/options/reset_profile_settings_handler.cc index 1d69d5f..5b115ff 100644 --- a/chrome/browser/ui/webui/options/reset_profile_settings_handler.cc +++ b/chrome/browser/ui/webui/options/reset_profile_settings_handler.cc @@ -11,8 +11,6 @@ #include "base/strings/string16.h" #include "base/values.h" #include "chrome/browser/google/google_brand.h" -#include "chrome/browser/profile_resetter/automatic_profile_resetter.h" -#include "chrome/browser/profile_resetter/automatic_profile_resetter_factory.h" #include "chrome/browser/profile_resetter/brandcode_config_fetcher.h" #include "chrome/browser/profile_resetter/brandcoded_default_settings.h" #include "chrome/browser/profile_resetter/profile_resetter.h" @@ -32,9 +30,7 @@ namespace options { -ResetProfileSettingsHandler::ResetProfileSettingsHandler() - : automatic_profile_resetter_(NULL), - has_shown_confirmation_dialog_(false) { +ResetProfileSettingsHandler::ResetProfileSettingsHandler() { google_brand::GetBrand(&brandcode_); } @@ -43,25 +39,12 @@ ResetProfileSettingsHandler::~ResetProfileSettingsHandler() {} void ResetProfileSettingsHandler::InitializeHandler() { Profile* profile = Profile::FromWebUI(web_ui()); resetter_.reset(new ProfileResetter(profile)); - automatic_profile_resetter_ = - AutomaticProfileResetterFactory::GetForBrowserContext(profile); } void ResetProfileSettingsHandler::InitializePage() { web_ui()->CallJavascriptFunction( "ResetProfileSettingsOverlay.setResettingState", base::FundamentalValue(resetter_->IsActive())); - if (automatic_profile_resetter_ && - automatic_profile_resetter_->ShouldShowResetBanner()) { - web_ui()->CallJavascriptFunction("ResetProfileSettingsBanner.show"); - } -} - -void ResetProfileSettingsHandler::Uninitialize() { - if (has_shown_confirmation_dialog_ && automatic_profile_resetter_) { - automatic_profile_resetter_->NotifyDidCloseWebUIResetDialog( - false /*performed_reset*/); - } } void ResetProfileSettingsHandler::GetLocalizedValues( @@ -69,8 +52,6 @@ void ResetProfileSettingsHandler::GetLocalizedValues( DCHECK(localized_strings); static OptionsStringResource resources[] = { - { "resetProfileSettingsBannerText", - IDS_RESET_PROFILE_SETTINGS_BANNER_TEXT }, { "resetProfileSettingsCommit", IDS_RESET_PROFILE_SETTINGS_COMMIT_BUTTON }, { "resetProfileSettingsExplanation", IDS_RESET_PROFILE_SETTINGS_EXPLANATION }, @@ -131,10 +112,6 @@ void ResetProfileSettingsHandler::RegisterMessages() { web_ui()->RegisterMessageCallback("onHideResetProfileDialog", base::Bind(&ResetProfileSettingsHandler::OnHideResetProfileDialog, base::Unretained(this))); - web_ui()->RegisterMessageCallback("onDismissedResetProfileSettingsBanner", - base::Bind(&ResetProfileSettingsHandler:: - OnDismissedResetProfileSettingsBanner, - base::Unretained(this))); } void ResetProfileSettingsHandler::HandleResetProfileSettings( @@ -166,17 +143,10 @@ void ResetProfileSettingsHandler::OnResetProfileSettingsDone( setting_snapshot_->Subtract(current_snapshot); std::string report = SerializeSettingsReport(*setting_snapshot_, difference); - bool is_reset_prompt_active = automatic_profile_resetter_ && - automatic_profile_resetter_->IsResetPromptFlowActive(); - SendSettingsFeedback(report, profile, is_reset_prompt_active ? - PROFILE_RESET_PROMPT : PROFILE_RESET_WEBUI); + SendSettingsFeedback(report, profile); } } setting_snapshot_.reset(); - if (automatic_profile_resetter_) { - automatic_profile_resetter_->NotifyDidCloseWebUIResetDialog( - true /*performed_reset*/); - } } void ResetProfileSettingsHandler::OnShowResetProfileDialog( @@ -189,10 +159,6 @@ void ResetProfileSettingsHandler::OnShowResetProfileDialog( UpdateFeedbackUI(); } - if (automatic_profile_resetter_) - automatic_profile_resetter_->NotifyDidOpenWebUIResetDialog(); - has_shown_confirmation_dialog_ = true; - if (brandcode_.empty()) return; config_fetcher_.reset(new BrandcodeConfigFetcher( @@ -208,12 +174,6 @@ void ResetProfileSettingsHandler::OnHideResetProfileDialog( setting_snapshot_.reset(); } -void ResetProfileSettingsHandler::OnDismissedResetProfileSettingsBanner( - const base::ListValue* args) { - if (automatic_profile_resetter_) - automatic_profile_resetter_->NotifyDidCloseWebUIResetBanner(); -} - void ResetProfileSettingsHandler::OnSettingsFetched() { DCHECK(config_fetcher_); DCHECK(!config_fetcher_->IsActive()); diff --git a/chrome/browser/ui/webui/options/reset_profile_settings_handler.h b/chrome/browser/ui/webui/options/reset_profile_settings_handler.h index e4e3440..5c1bf2d 100644 --- a/chrome/browser/ui/webui/options/reset_profile_settings_handler.h +++ b/chrome/browser/ui/webui/options/reset_profile_settings_handler.h @@ -17,7 +17,6 @@ class DictionaryValue; class ListValue; } // namespace base -class AutomaticProfileResetter; class BrandcodeConfigFetcher; class ProfileResetter; class ResettableSettingsSnapshot; @@ -37,7 +36,6 @@ class ResetProfileSettingsHandler void GetLocalizedValues(base::DictionaryValue* localized_strings) override; void InitializeHandler() override; void InitializePage() override; - void Uninitialize() override; // WebUIMessageHandler implementation. void RegisterMessages() override; @@ -55,9 +53,6 @@ class ResetProfileSettingsHandler // Called when the confirmation box disappears. void OnHideResetProfileDialog(const base::ListValue* value); - // Called when the reset banner is dismissed from the WebUI. - void OnDismissedResetProfileSettingsBanner(const base::ListValue* args); - // Called when BrandcodeConfigFetcher completed fetching settings. void OnSettingsFetched(); @@ -68,14 +63,6 @@ class ResetProfileSettingsHandler // Sets new values for the feedback area. void UpdateFeedbackUI(); - // Destroyed with the Profile, thus it should outlive us. This will be NULL if - // the underlying profile is off-the-record (e.g. in Guest mode on Chrome OS). - AutomaticProfileResetter* automatic_profile_resetter_; - - // Records whether or not the Profile Reset confirmation dialog was opened at - // least once during the lifetime of the settings page. - bool has_shown_confirmation_dialog_; - scoped_ptr<ProfileResetter> resetter_; scoped_ptr<BrandcodeConfigFetcher> config_fetcher_; diff --git a/chrome/browser/ui/webui/settings/reset_settings_handler.cc b/chrome/browser/ui/webui/settings/reset_settings_handler.cc index 73a0783e..53b19a9 100644 --- a/chrome/browser/ui/webui/settings/reset_settings_handler.cc +++ b/chrome/browser/ui/webui/settings/reset_settings_handler.cc @@ -11,8 +11,6 @@ #include "base/strings/string16.h" #include "base/values.h" #include "chrome/browser/google/google_brand.h" -#include "chrome/browser/profile_resetter/automatic_profile_resetter.h" -#include "chrome/browser/profile_resetter/automatic_profile_resetter_factory.h" #include "chrome/browser/profile_resetter/brandcode_config_fetcher.h" #include "chrome/browser/profile_resetter/brandcoded_default_settings.h" #include "chrome/browser/profile_resetter/profile_resetter.h" @@ -49,8 +47,6 @@ ResetSettingsHandler::ResetSettingsHandler( google_brand::GetBrand(&brandcode_); Profile* profile = Profile::FromWebUI(web_ui); resetter_.reset(new ProfileResetter(profile)); - automatic_profile_resetter_ = - AutomaticProfileResetterFactory::GetForBrowserContext(profile); #if defined(OS_CHROMEOS) policy::BrowserPolicyConnectorChromeOS* connector = @@ -62,12 +58,7 @@ ResetSettingsHandler::ResetSettingsHandler( #endif // defined(OS_CHROMEOS) } -ResetSettingsHandler::~ResetSettingsHandler() { - if (has_shown_confirmation_dialog_ && automatic_profile_resetter_) { - automatic_profile_resetter_->NotifyDidCloseWebUIResetDialog( - false /*performed_reset*/); - } -} +ResetSettingsHandler::~ResetSettingsHandler() {} void ResetSettingsHandler::RegisterMessages() { web_ui()->RegisterMessageCallback("performResetProfileSettings", @@ -120,17 +111,10 @@ void ResetSettingsHandler::OnResetProfileSettingsDone( setting_snapshot_->Subtract(current_snapshot); std::string report = SerializeSettingsReport(*setting_snapshot_, difference); - bool is_reset_prompt_active = automatic_profile_resetter_ && - automatic_profile_resetter_->IsResetPromptFlowActive(); - SendSettingsFeedback(report, profile, is_reset_prompt_active ? - PROFILE_RESET_PROMPT : PROFILE_RESET_WEBUI); + SendSettingsFeedback(report, profile); } } setting_snapshot_.reset(); - if (automatic_profile_resetter_) { - automatic_profile_resetter_->NotifyDidCloseWebUIResetDialog( - true /*performed_reset*/); - } } void ResetSettingsHandler::OnShowResetProfileDialog( @@ -143,10 +127,6 @@ void ResetSettingsHandler::OnShowResetProfileDialog( UpdateFeedbackUI(); } - if (automatic_profile_resetter_) - automatic_profile_resetter_->NotifyDidOpenWebUIResetDialog(); - has_shown_confirmation_dialog_ = true; - if (brandcode_.empty()) return; config_fetcher_.reset(new BrandcodeConfigFetcher( diff --git a/chrome/browser/ui/webui/settings/reset_settings_handler.h b/chrome/browser/ui/webui/settings/reset_settings_handler.h index 2f615b5..0407947 100644 --- a/chrome/browser/ui/webui/settings/reset_settings_handler.h +++ b/chrome/browser/ui/webui/settings/reset_settings_handler.h @@ -22,7 +22,6 @@ namespace content { class WebUIDataSource; } -class AutomaticProfileResetter; class BrandcodeConfigFetcher; class ProfileResetter; class ResettableSettingsSnapshot; @@ -78,14 +77,6 @@ class ResetSettingsHandler bool allow_powerwash_ = false; #endif // defined(OS_CHROMEOS) - // Destroyed with the Profile, thus it should outlive us. This will be NULL if - // the underlying profile is off-the-record (e.g. in Guest mode on Chrome OS). - AutomaticProfileResetter* automatic_profile_resetter_ = nullptr; - - // Records whether or not the Profile Reset confirmation dialog was opened at - // least once during the lifetime of the settings page. - bool has_shown_confirmation_dialog_ = false; - scoped_ptr<ProfileResetter> resetter_; scoped_ptr<BrandcodeConfigFetcher> config_fetcher_; diff --git a/chrome/chrome_browser.gypi b/chrome/chrome_browser.gypi index ffc7bf3..62e9b11 100644 --- a/chrome/chrome_browser.gypi +++ b/chrome/chrome_browser.gypi @@ -1253,25 +1253,10 @@ 'browser/process_singleton_posix.cc', 'browser/process_singleton_startup_lock.cc', 'browser/process_singleton_startup_lock.h', - 'browser/profile_resetter/automatic_profile_resetter.cc', - 'browser/profile_resetter/automatic_profile_resetter.h', - 'browser/profile_resetter/automatic_profile_resetter_delegate.cc', - 'browser/profile_resetter/automatic_profile_resetter_delegate.h', - 'browser/profile_resetter/automatic_profile_resetter_factory.cc', - 'browser/profile_resetter/automatic_profile_resetter_factory.h', - 'browser/profile_resetter/automatic_profile_resetter_mementos.cc', - 'browser/profile_resetter/automatic_profile_resetter_mementos.h', 'browser/profile_resetter/brandcode_config_fetcher.cc', 'browser/profile_resetter/brandcode_config_fetcher.h', 'browser/profile_resetter/brandcoded_default_settings.cc', 'browser/profile_resetter/brandcoded_default_settings.h', - 'browser/profile_resetter/jtl_foundation.cc', - 'browser/profile_resetter/jtl_foundation.h', - 'browser/profile_resetter/jtl_instructions.h', - 'browser/profile_resetter/jtl_interpreter.cc', - 'browser/profile_resetter/jtl_interpreter.h', - 'browser/profile_resetter/profile_reset_global_error.cc', - 'browser/profile_resetter/profile_reset_global_error.h', 'browser/profile_resetter/profile_resetter.cc', 'browser/profile_resetter/profile_resetter.h', 'browser/profile_resetter/resettable_settings_snapshot.cc', diff --git a/chrome/chrome_browser_ui.gypi b/chrome/chrome_browser_ui.gypi index 03b508f..fdddd1c 100644 --- a/chrome/chrome_browser_ui.gypi +++ b/chrome/chrome_browser_ui.gypi @@ -2347,8 +2347,6 @@ 'browser/ui/views/profiles/avatar_menu_button.h', 'browser/ui/views/profiles/profile_chooser_view.cc', 'browser/ui/views/profiles/profile_chooser_view.h', - 'browser/ui/views/profiles/profile_reset_bubble_view.cc', - 'browser/ui/views/profiles/profile_reset_bubble_view.h', 'browser/ui/views/profiles/supervised_user_avatar_label.cc', 'browser/ui/views/profiles/supervised_user_avatar_label.h', 'browser/ui/views/profiles/user_manager_view.cc', diff --git a/chrome/chrome_tests_unit.gypi b/chrome/chrome_tests_unit.gypi index eb28aa8..8cec80c 100644 --- a/chrome/chrome_tests_unit.gypi +++ b/chrome/chrome_tests_unit.gypi @@ -2680,7 +2680,6 @@ }, { # 'OS!="android" and OS!="ios"' 'dependencies': [ '../components/components.gyp:bubble_test_support', - 'tools/profile_reset/jtl_compiler.gyp:jtl_compiler_lib', ], }], ['OS != "android" and chromeos == 0', { diff --git a/chrome/common/chrome_constants.cc b/chrome/common/chrome_constants.cc index 49e4009..ab1c7e3 100644 --- a/chrome/common/chrome_constants.cc +++ b/chrome/common/chrome_constants.cc @@ -159,8 +159,6 @@ const base::FilePath::CharType kPreferencesFilename[] = FPL("Preferences"); const base::FilePath::CharType kProtectedPreferencesFilenameDeprecated[] = FPL("Protected Preferences"); const base::FilePath::CharType kReadmeFilename[] = FPL("README"); -const base::FilePath::CharType kResetPromptMementoFilename[] = - FPL("Reset Prompt Memento"); const base::FilePath::CharType kSafeBrowsingBaseFilename[] = FPL("Safe Browsing"); const base::FilePath::CharType kSecurePreferencesFilename[] = diff --git a/chrome/common/chrome_constants.h b/chrome/common/chrome_constants.h index 933a3c3..33b4008 100644 --- a/chrome/common/chrome_constants.h +++ b/chrome/common/chrome_constants.h @@ -72,7 +72,6 @@ extern const base::FilePath::CharType kOfflinePageMetadataDirname[]; extern const base::FilePath::CharType kPreferencesFilename[]; extern const base::FilePath::CharType kProtectedPreferencesFilenameDeprecated[]; extern const base::FilePath::CharType kReadmeFilename[]; -extern const base::FilePath::CharType kResetPromptMementoFilename[]; extern const base::FilePath::CharType kSafeBrowsingBaseFilename[]; extern const base::FilePath::CharType kSecurePreferencesFilename[]; extern const base::FilePath::CharType kServiceStateFileName[]; diff --git a/chrome/common/pref_names.cc b/chrome/common/pref_names.cc index 94952ba..442529f 100644 --- a/chrome/common/pref_names.cc +++ b/chrome/common/pref_names.cc @@ -1121,11 +1121,6 @@ const char kSupervisedUserCreationAllowed[] = // List pref containing the users supervised by this user. const char kSupervisedUsers[] = "profile.managed_users"; -// String that indicates that the profile reset prompt has already been shown to -// the user (profile). -const char kProfileResetPromptMementoInProfilePrefs[] = - "profile.reset_prompt_memento"; - // List pref containing the extension ids which are not allowed to send // notifications to the message center. const char kMessageCenterDisabledExtensionIds[] = @@ -1246,14 +1241,6 @@ const char kProfileCreatedByVersion[] = "profile.created_by_version"; // them. const char kProfileInfoCache[] = "profile.info_cache"; -// Dictionary that maps profile keys to strings that indicate that the profile -// reset prompt has already been shown to the corresponding user (profile). -// This is semantically similar to kProfileResetPromptMementoInProfilePrefs, see -// chrome/browser/profile_resetter/automatic_profile_resetter_mementos.h for an -// explanation of why this redundancy is needed. -const char kProfileResetPromptMementosInLocalState[] = - "profile.reset_prompt_mementos"; - // Boolean that specifies whether or not crash reports are sent // over the network for analysis. #if defined(OS_ANDROID) diff --git a/chrome/common/pref_names.h b/chrome/common/pref_names.h index 7c200ed..0f8d51a 100644 --- a/chrome/common/pref_names.h +++ b/chrome/common/pref_names.h @@ -379,8 +379,6 @@ extern const char kDefaultSupervisedUserFilteringBehavior[]; extern const char kSupervisedUserCreationAllowed[]; extern const char kSupervisedUsers[]; -extern const char kProfileResetPromptMementoInProfilePrefs[]; - extern const char kMessageCenterDisabledExtensionIds[]; extern const char kMessageCenterDisabledSystemComponentIds[]; extern const char kWelcomeNotificationDismissed[]; @@ -430,7 +428,6 @@ extern const char kProfilesLastActive[]; extern const char kProfilesNumCreated[]; extern const char kProfileInfoCache[]; extern const char kProfileCreatedByVersion[]; -extern const char kProfileResetPromptMementosInLocalState[]; extern const char kStabilityOtherUserCrashCount[]; extern const char kStabilityKernelCrashCount[]; diff --git a/chrome/test/BUILD.gn b/chrome/test/BUILD.gn index df501b2..85dddc4 100644 --- a/chrome/test/BUILD.gn +++ b/chrome/test/BUILD.gn @@ -2006,8 +2006,6 @@ test("unit_tests") { "../browser/ui/bookmarks/bookmark_ui_utils_desktop_unittest.cc", "../browser/ui/sync/sync_promo_ui_unittest.cc", ] - } else { - deps += [ "//chrome/tools/profile_reset:jtl_compiler_lib" ] } if (!is_android && !is_chromeos) { sources += rebase_path( @@ -2104,7 +2102,6 @@ if (is_win || (is_linux && !is_chromeos)) { "../common/crash_keys.cc", "../common/crash_keys.h", ] - deps = [ ":test_support", "//breakpad:client", diff --git a/chrome/test/base/test_browser_window.cc b/chrome/test/base/test_browser_window.cc index 41dbb5c..3175183 100644 --- a/chrome/test/base/test_browser_window.cc +++ b/chrome/test/base/test_browser_window.cc @@ -177,15 +177,6 @@ autofill::SaveCardBubbleView* TestBrowserWindow::ShowSaveCreditCardBubble( return nullptr; } -bool TestBrowserWindow::IsProfileResetBubbleSupported() const { - return false; -} - -GlobalErrorBubbleViewBase* TestBrowserWindow::ShowProfileResetBubble( - const base::WeakPtr<ProfileResetGlobalError>& global_error) { - return nullptr; -} - bool TestBrowserWindow::IsDownloadShelfVisible() const { return false; } diff --git a/chrome/test/base/test_browser_window.h b/chrome/test/base/test_browser_window.h index 0bce5fa..0e4bfcd 100644 --- a/chrome/test/base/test_browser_window.h +++ b/chrome/test/base/test_browser_window.h @@ -119,9 +119,6 @@ class TestBrowserWindow : public BrowserWindow { translate::TranslateStep step, translate::TranslateErrors::Type error_type, bool is_user_gesture) override {} - bool IsProfileResetBubbleSupported() const override; - GlobalErrorBubbleViewBase* ShowProfileResetBubble( - const base::WeakPtr<ProfileResetGlobalError>& global_error) override; #if defined(ENABLE_ONE_CLICK_SIGNIN) void ShowOneClickSigninBubble( OneClickSigninBubbleType type, diff --git a/chrome/tools/profile_reset/BUILD.gn b/chrome/tools/profile_reset/BUILD.gn deleted file mode 100644 index 1cebad1..0000000 --- a/chrome/tools/profile_reset/BUILD.gn +++ /dev/null @@ -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. - -executable("jtl_compiler") { - sources = [ - "//chrome/browser/profile_resetter/jtl_foundation.cc", - "//chrome/browser/profile_resetter/jtl_foundation.h", - "jtl_compiler_frontend.cc", - ] - deps = [ - ":jtl_compiler_lib", - "//base", - "//build/config/sanitizers:deps", - "//crypto", - ] -} - -source_set("jtl_compiler_lib") { - sources = [ - "//chrome/browser/profile_resetter/jtl_foundation.h", - "//chrome/browser/profile_resetter/jtl_instructions.h", - "jtl_compiler.cc", - "jtl_compiler.h", - "jtl_parser.cc", - "jtl_parser.h", - ] - deps = [ - "//base", - "//third_party/re2", - ] -} diff --git a/chrome/tools/profile_reset/OWNERS b/chrome/tools/profile_reset/OWNERS deleted file mode 100644 index de6863e..0000000 --- a/chrome/tools/profile_reset/OWNERS +++ /dev/null @@ -1,3 +0,0 @@ -battre@chromium.org -engedy@chromium.org - diff --git a/chrome/tools/profile_reset/jtl_compiler.cc b/chrome/tools/profile_reset/jtl_compiler.cc deleted file mode 100644 index ffa5ec2..0000000 --- a/chrome/tools/profile_reset/jtl_compiler.cc +++ /dev/null @@ -1,252 +0,0 @@ -// Copyright 2013 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 "chrome/tools/profile_reset/jtl_compiler.h" - -#include <limits> -#include <map> -#include <numeric> - -#include "base/logging.h" -#include "chrome/browser/profile_resetter/jtl_foundation.h" -#include "chrome/tools/profile_reset/jtl_parser.h" - -namespace jtl = jtl_foundation; - -namespace { - -// Serializes symbols into byte-code in a streaming manner. -class ByteCodeWriter { - public: - explicit ByteCodeWriter(std::string* output) : output_(output) {} - ~ByteCodeWriter() {} - - void WriteUint8(uint8 value) { output_->push_back(static_cast<char>(value)); } - void WriteUint32(uint32 value) { - for (int i = 0; i < 4; ++i) { - output_->push_back(static_cast<char>(value & 0xFFu)); - value >>= 8; - } - } - void WriteOpCode(uint8 op_code) { WriteUint8(op_code); } - void WriteHash(const std::string& hash) { - CHECK(jtl::Hasher::IsHash(hash)); - *output_ += hash; - } - void WriteBool(bool value) { WriteUint8(value ? 1u : 0u); } - - private: - std::string* output_; - - DISALLOW_COPY_AND_ASSIGN(ByteCodeWriter); -}; - -// Encapsulates meta-data about all instructions, and is capable of transcoding -// each instruction from a parsed text-based format to byte-code. -class InstructionSet { - public: - InstructionSet() { - // Define each instruction in this list. - // Note: - // - Instructions ending in "hash" will write their 'HashString' arguments - // directly into the byte-code. - // - Instructions ending in "hashed" will first hash their 'String' - // arguments, and will write this hash to the byte-code. - Add(Instruction("go", jtl::NAVIGATE, Arguments(String))); - Add(Instruction("any", jtl::NAVIGATE_ANY, Arguments())); - Add(Instruction("back", jtl::NAVIGATE_BACK, Arguments())); - Add(Instruction("store_bool", jtl::STORE_BOOL, Arguments(String, Bool))); - Add(Instruction("store_hash", - jtl::STORE_HASH, Arguments(String, HashString))); - Add(Instruction("store_hashed", - jtl::STORE_HASH, Arguments(String, String))); - Add(Instruction("store_node_bool", - jtl::STORE_NODE_BOOL, Arguments(String))); - Add(Instruction("store_node_hash", - jtl::STORE_NODE_HASH, Arguments(String))); - Add(Instruction("store_node_registerable_domain_hash", - jtl::STORE_NODE_REGISTERABLE_DOMAIN_HASH, - Arguments(String))); - Add(Instruction("compare_bool", jtl::COMPARE_NODE_BOOL, Arguments(Bool))); - Add(Instruction("compare_hashed", - jtl::COMPARE_NODE_HASH, Arguments(String))); - Add(Instruction("compare_hashed_not", - jtl::COMPARE_NODE_HASH_NOT, Arguments(String))); - Add(Instruction("compare_stored_bool", - jtl::COMPARE_STORED_BOOL, - Arguments(String, Bool, Bool))); - Add(Instruction("compare_stored_hashed", - jtl::COMPARE_STORED_HASH, - Arguments(String, String, String))); - Add(Instruction("compare_to_stored_bool", - jtl::COMPARE_NODE_TO_STORED_BOOL, - Arguments(String))); - Add(Instruction("compare_to_stored_hash", - jtl::COMPARE_NODE_TO_STORED_HASH, - Arguments(String))); - Add(Instruction("compare_substring_hashed", - jtl::COMPARE_NODE_SUBSTRING, - Arguments(StringPattern))); - Add(Instruction("break", jtl::STOP_EXECUTING_SENTENCE, Arguments())); - } - - JtlCompiler::CompileError::ErrorCode TranscodeInstruction( - const std::string& name, - const base::ListValue& arguments, - bool ends_sentence, - const jtl::Hasher& hasher, - ByteCodeWriter* target) const { - if (instruction_map_.count(name) == 0) - return JtlCompiler::CompileError::INVALID_OPERATION_NAME; - const Instruction& instruction(instruction_map_.at(name)); - if (instruction.argument_types.size() != arguments.GetSize()) - return JtlCompiler::CompileError::INVALID_ARGUMENT_COUNT; - target->WriteOpCode(instruction.op_code); - for (size_t i = 0; i < arguments.GetSize(); ++i) { - switch (instruction.argument_types[i]) { - case Bool: { - bool value = false; - if (!arguments.GetBoolean(i, &value)) - return JtlCompiler::CompileError::INVALID_ARGUMENT_TYPE; - target->WriteBool(value); - break; - } - case String: { - std::string value; - if (!arguments.GetString(i, &value)) - return JtlCompiler::CompileError::INVALID_ARGUMENT_TYPE; - target->WriteHash(hasher.GetHash(value)); - break; - } - case StringPattern: { - std::string value; - if (!arguments.GetString(i, &value)) - return JtlCompiler::CompileError::INVALID_ARGUMENT_TYPE; - if (value.empty() || - value.size() > std::numeric_limits<uint32>::max()) - return JtlCompiler::CompileError::INVALID_ARGUMENT_VALUE; - target->WriteHash(hasher.GetHash(value)); - target->WriteUint32(static_cast<uint32>(value.size())); - uint32 pattern_sum = std::accumulate( - value.begin(), value.end(), static_cast<uint32>(0u)); - target->WriteUint32(pattern_sum); - break; - } - case HashString: { - std::string hash_value; - if (!arguments.GetString(i, &hash_value) || - !jtl::Hasher::IsHash(hash_value)) - return JtlCompiler::CompileError::INVALID_ARGUMENT_TYPE; - target->WriteHash(hash_value); - break; - } - default: - NOTREACHED(); - return JtlCompiler::CompileError::INVALID_ARGUMENT_TYPE; - } - } - if (ends_sentence) - target->WriteOpCode(jtl::END_OF_SENTENCE); - return JtlCompiler::CompileError::ERROR_NONE; - } - - private: - // The possible types of an operation's argument. - enum ArgumentType { - None, - Bool, - String, - StringPattern, - HashString - }; - - // Encapsulates meta-data about one instruction. - struct Instruction { - Instruction() : op_code(jtl::END_OF_SENTENCE) {} - Instruction(const char* name, - jtl_foundation::OpCodes op_code, - const std::vector<ArgumentType>& argument_types) - : name(name), op_code(op_code), argument_types(argument_types) {} - - std::string name; - jtl::OpCodes op_code; - std::vector<ArgumentType> argument_types; - }; - - static std::vector<ArgumentType> Arguments(ArgumentType arg1_type = None, - ArgumentType arg2_type = None, - ArgumentType arg3_type = None) { - std::vector<ArgumentType> result; - if (arg1_type != None) - result.push_back(arg1_type); - if (arg2_type != None) - result.push_back(arg2_type); - if (arg3_type != None) - result.push_back(arg3_type); - return result; - } - - void Add(const Instruction& instruction) { - instruction_map_[instruction.name] = instruction; - } - - std::map<std::string, Instruction> instruction_map_; - - DISALLOW_COPY_AND_ASSIGN(InstructionSet); -}; - -} // namespace - -bool JtlCompiler::Compile(const std::string& source_code, - const std::string& hash_seed, - std::string* output_bytecode, - CompileError* error_details) { - DCHECK(output_bytecode); - InstructionSet instruction_set; - ByteCodeWriter bytecode_writer(output_bytecode); - jtl::Hasher hasher(hash_seed); - - std::string compacted_source_code; - std::vector<size_t> newline_indices; - size_t mismatched_quotes_line; - if (!JtlParser::RemoveCommentsAndAllWhitespace(source_code, - &compacted_source_code, - &newline_indices, - &mismatched_quotes_line)) { - if (error_details) { - error_details->context = ""; // No meaningful intra-line context here. - error_details->line_number = mismatched_quotes_line; - error_details->error_code = CompileError::MISMATCHED_DOUBLE_QUOTES; - } - return false; - } - - JtlParser parser(compacted_source_code, newline_indices); - while (!parser.HasFinished()) { - std::string operation_name; - base::ListValue arguments; - bool ends_sentence = false; - if (!parser.ParseNextOperation( - &operation_name, &arguments, &ends_sentence)) { - if (error_details) { - error_details->context = parser.GetLastContext(); - error_details->line_number = parser.GetLastLineNumber(); - error_details->error_code = CompileError::PARSING_ERROR; - } - return false; - } - CompileError::ErrorCode error_code = instruction_set.TranscodeInstruction( - operation_name, arguments, ends_sentence, hasher, &bytecode_writer); - if (error_code != CompileError::ERROR_NONE) { - if (error_details) { - error_details->context = parser.GetLastContext(); - error_details->line_number = parser.GetLastLineNumber(); - error_details->error_code = error_code; - } - return false; - } - } - - return true; -} diff --git a/chrome/tools/profile_reset/jtl_compiler.gyp b/chrome/tools/profile_reset/jtl_compiler.gyp deleted file mode 100644 index 40dca37..0000000 --- a/chrome/tools/profile_reset/jtl_compiler.gyp +++ /dev/null @@ -1,40 +0,0 @@ -{ - 'variables': { - 'chromium_code': 1, - }, - 'targets': [ - { - # GN version: //chrome/tools/profile_reset:jtl_compiler - 'target_name': 'jtl_compiler', - 'type': 'executable', - 'dependencies': [ - '../../../base/base.gyp:base', - '../../../crypto/crypto.gyp:crypto', - 'jtl_compiler_lib', - ], - 'sources': [ - '../../browser/profile_resetter/jtl_foundation.cc', - '../../browser/profile_resetter/jtl_foundation.h', - 'jtl_compiler_frontend.cc', - ], - }, - { - # GN version: //chrome/tools/profile_reset:jtl_compiler_lib - 'target_name': 'jtl_compiler_lib', - 'type': 'static_library', - 'product_name': 'jtl_compiler', - 'dependencies': [ - '../../../third_party/re2/re2.gyp:re2', - '../../../base/base.gyp:base', - ], - 'sources': [ - '../../browser/profile_resetter/jtl_foundation.h', - '../../browser/profile_resetter/jtl_instructions.h', - 'jtl_compiler.cc', - 'jtl_compiler.h', - 'jtl_parser.cc', - 'jtl_parser.h', - ], - }, - ], -} diff --git a/chrome/tools/profile_reset/jtl_compiler.h b/chrome/tools/profile_reset/jtl_compiler.h deleted file mode 100644 index cd81b81..0000000 --- a/chrome/tools/profile_reset/jtl_compiler.h +++ /dev/null @@ -1,74 +0,0 @@ -// Copyright 2013 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 CHROME_TOOLS_PROFILE_RESET_JTL_COMPILER_H_ -#define CHROME_TOOLS_PROFILE_RESET_JTL_COMPILER_H_ - -#include <string> - -#include "base/basictypes.h" - -// Compiles text-based JTL source code into JTL byte-code. -// -// For an overview of JTL (JSON Traversal Language), and the exhaustive list of -// instructions, please see "chrome/browser/profile_resetter/jtl_foundation.h". -// -// The text-based JTL syntax itself much resembles C/C++. A program consists of -// zero or more sentences. Each sentence is terminated by a semi-colon (;), and -// is composed of *one* or more operations, separated by periods (.). -// -// Each operation resembles a C/C++ function call and consists of an instruction -// name, and an optional argument list, which takes Boolean values and/or string -// literals. The text-based instruction names are defined in "jtl_compiler.cc". -// -// Whitespace does not matter, except for inside string literals. C++-style, -// double-slash-introduced comments are also supported. -// -// Example source code: -// -// // Store "x"=true if path "foo.bar" is found. -// go("foo").go("bar").store_bool("x", true); -// -// // Store "y"="1" if the above value is set. -// compare_stored_bool("x", true, false).store_hash("y", "1"); -// -class JtlCompiler { - public: - struct CompileError { - enum ErrorCode { - ERROR_NONE, - MISMATCHED_DOUBLE_QUOTES, - PARSING_ERROR, - INVALID_OPERATION_NAME, - INVALID_ARGUMENT_COUNT, - INVALID_ARGUMENT_TYPE, - INVALID_ARGUMENT_VALUE - }; - - CompileError() : line_number(0), error_code(ERROR_NONE) {} - CompileError(size_t line_number, - const std::string& context, - ErrorCode error_code) - : line_number(line_number), context(context), error_code(error_code) {} - - size_t line_number; // 0-based. - std::string context; - ErrorCode error_code; - }; - - // Compiles text-based JTL source code contained in |source_code| into JTL - // byte-code to |output_bytecode|. Variable, node names, and string literals - // will be hashed using the seed in |hash_seed|. - // On success, returns true. Otherwise, returns false and fills |error| with - // more information (if it is non-NULL). - static bool Compile(const std::string& source_code, - const std::string& hash_seed, - std::string* output_bytecode, - CompileError* error); - - private: - DISALLOW_IMPLICIT_CONSTRUCTORS(JtlCompiler); -}; - -#endif // CHROME_TOOLS_PROFILE_RESET_JTL_COMPILER_H_ diff --git a/chrome/tools/profile_reset/jtl_compiler_frontend.cc b/chrome/tools/profile_reset/jtl_compiler_frontend.cc deleted file mode 100644 index 634d3a7..0000000 --- a/chrome/tools/profile_reset/jtl_compiler_frontend.cc +++ /dev/null @@ -1,112 +0,0 @@ -// Copyright 2013 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. -// -// A simple command-line compiler for JTL (JSON Traversal Language). -// -// Translates rules from a text-based, human-readable format to an easy-to-parse -// byte-code format, which then can be interpreted by JtlInterpreter. -// -// Example usage: -// jtl_compiler --input=blah.txt --hash-seed="foobar" --output=blah.dat - -#include <iostream> -#include <string> - -#include "base/command_line.h" -#include "base/files/file_path.h" -#include "base/files/file_util.h" -#include "chrome/tools/profile_reset/jtl_compiler.h" - -namespace { - -// Command-line argument name: path to the input text-based JTL source code. -const char kInputPath[] = "input"; - -// Command-line argument name: path to the output byte-code. -const char kOutputPath[] = "output"; - -// Command-line argument name: the hash seed to use. -const char kHashSeed[] = "hash-seed"; - -// Error codes. -const char kMismatchedDoubleQuotes[] = "Mismatched double-quotes before EOL."; -const char kParsingError[] = "Parsing error. Input is ill-formed."; -const char kArgumentCountError[] = "Wrong number of arguments for operation."; -const char kArgumentTypeError[] = "Wrong argument type(s) for operation."; -const char kArgumentValueError[] = "Wrong argument value(s) for operation."; -const char kUnknownOperationError[] = "No operation by this name."; -const char kUnknownError[] = "Unknown error."; - -const char* ResolveErrorCode(JtlCompiler::CompileError::ErrorCode code) { - switch (code) { - case JtlCompiler::CompileError::MISMATCHED_DOUBLE_QUOTES: - return kMismatchedDoubleQuotes; - case JtlCompiler::CompileError::PARSING_ERROR: - return kParsingError; - case JtlCompiler::CompileError::INVALID_ARGUMENT_COUNT: - return kArgumentCountError; - case JtlCompiler::CompileError::INVALID_ARGUMENT_TYPE: - return kArgumentTypeError; - case JtlCompiler::CompileError::INVALID_ARGUMENT_VALUE: - return kArgumentValueError; - case JtlCompiler::CompileError::INVALID_OPERATION_NAME: - return kUnknownOperationError; - default: - return kUnknownError; - } -} - -} // namespace - -int main(int argc, char* argv[]) { - base::CommandLine::Init(argc, argv); - base::CommandLine* cmd_line = base::CommandLine::ForCurrentProcess(); - if (!cmd_line->HasSwitch(kInputPath) || !cmd_line->HasSwitch(kHashSeed) || - !cmd_line->HasSwitch(kOutputPath)) { - std::cerr << "Usage: " << argv[0] << " <required switches>" << std::endl; - std::cerr << "\nRequired switches are:" << std::endl; - std::cerr << " --" << kInputPath << "=<file>" - << "\t\tPath to the input text-based JTL source code." - << std::endl; - std::cerr << " --" << kOutputPath << "=<file>" - << "\t\tPath to the output byte-code." << std::endl; - std::cerr << " --" << kHashSeed << "=<value>" - << "\t\tThe hash seed to use." << std::endl; - return -1; - } - - base::FilePath source_code_path = - MakeAbsoluteFilePath(cmd_line->GetSwitchValuePath(kInputPath)); - std::string source_code; - if (!base::ReadFileToString(source_code_path, &source_code)) { - std::cerr << "ERROR: Cannot read input file." << std::endl; - return -3; - } - - std::string bytecode; - JtlCompiler::CompileError error; - std::string hash_seed = cmd_line->GetSwitchValueASCII(kHashSeed); - if (!JtlCompiler::Compile(source_code, hash_seed, &bytecode, &error)) { - std::cerr << "COMPILE ERROR: " << ResolveErrorCode(error.error_code) - << std::endl; - std::cerr << " Line number: " << (error.line_number + 1) << std::endl; - std::cerr << " Context: " << (error.context.size() > 63 - ? error.context.substr(0, 60) + "..." - : error.context) << std::endl; - return -2; - } - - base::FilePath bytecode_path = - MakeAbsoluteFilePath(cmd_line->GetSwitchValuePath(kOutputPath)); - int bytes_written = - base::WriteFile(cmd_line->GetSwitchValuePath(kOutputPath), - bytecode.data(), - static_cast<int>(bytecode.size())); - if (bytes_written != static_cast<int>(bytecode.size())) { - std::cerr << "ERROR: Cannot write output file." << std::endl; - return -3; - } - - return 0; -} diff --git a/chrome/tools/profile_reset/jtl_compiler_unittest.cc b/chrome/tools/profile_reset/jtl_compiler_unittest.cc deleted file mode 100644 index c39e59a..0000000 --- a/chrome/tools/profile_reset/jtl_compiler_unittest.cc +++ /dev/null @@ -1,218 +0,0 @@ -// Copyright 2013 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 "chrome/tools/profile_reset/jtl_compiler.h" - -#include <string> - -#include "base/values.h" -#include "chrome/browser/profile_resetter/jtl_foundation.h" -#include "chrome/browser/profile_resetter/jtl_instructions.h" -#include "testing/gmock/include/gmock/gmock.h" -#include "testing/gtest/include/gtest/gtest.h" - -namespace { - -const char kTestHashSeed[] = "test-hash-seed"; - -// Helpers ------------------------------------------------------------------- - -std::string GetHash(const std::string& input) { - return jtl_foundation::Hasher(kTestHashSeed).GetHash(input); -} - -static std::string EncodeUint32(uint32 value) { - std::string bytecode; - for (int i = 0; i < 4; ++i) { - bytecode.push_back(static_cast<char>(value & 0xFFu)); - value >>= 8; - } - return bytecode; -} - -// Tests --------------------------------------------------------------------- - -// Note: Parsing and parsing-related errors are unit-tested separately in more -// detail in "jtl_parser_unittest.cc". Here, most of the time, we assume that -// creating the parse tree works. - -TEST(JtlCompiler, CompileSingleInstructions) { - struct TestCase { - std::string source_code; - std::string expected_bytecode; - } cases[] = { - {"go(\"foo\").", OP_NAVIGATE(GetHash("foo"))}, - {"go(\"has whitespace\t\").", OP_NAVIGATE(GetHash("has whitespace\t"))}, - {"any.", OP_NAVIGATE_ANY}, - {"back.", OP_NAVIGATE_BACK}, - {"store_bool(\"name\", true).", - OP_STORE_BOOL(GetHash("name"), VALUE_TRUE)}, - {"compare_stored_bool(\"name\", true, false).", - OP_COMPARE_STORED_BOOL(GetHash("name"), VALUE_TRUE, VALUE_FALSE)}, - {"store_hash(\"name\", \"" + GetHash("value") + "\").", - OP_STORE_HASH(GetHash("name"), GetHash("value"))}, - {"store_hashed(\"name\", \"value\").", - OP_STORE_HASH(GetHash("name"), GetHash("value"))}, - {"store_node_bool(\"name\").", OP_STORE_NODE_BOOL(GetHash("name"))}, - {"store_node_hash(\"name\").", OP_STORE_NODE_HASH(GetHash("name"))}, - {"store_node_registerable_domain_hash(\"name\").", - OP_STORE_NODE_REGISTERABLE_DOMAIN_HASH(GetHash("name"))}, - {"compare_stored_hashed(\"name\", \"value\", \"default\").", - OP_COMPARE_STORED_HASH( - GetHash("name"), GetHash("value"), GetHash("default"))}, - {"compare_bool(false).", OP_COMPARE_NODE_BOOL(VALUE_FALSE)}, - {"compare_bool(true).", OP_COMPARE_NODE_BOOL(VALUE_TRUE)}, - {"compare_hashed(\"foo\").", OP_COMPARE_NODE_HASH(GetHash("foo"))}, - {"compare_hashed_not(\"foo\").", - OP_COMPARE_NODE_HASH_NOT(GetHash("foo"))}, - {"compare_to_stored_bool(\"name\").", - OP_COMPARE_NODE_TO_STORED_BOOL(GetHash("name"))}, - {"compare_to_stored_hash(\"name\").", - OP_COMPARE_NODE_TO_STORED_HASH(GetHash("name"))}, - {"compare_substring_hashed(\"pattern\").", - OP_COMPARE_NODE_SUBSTRING( - GetHash("pattern"), EncodeUint32(7), EncodeUint32(766))}, - {"break.", OP_STOP_EXECUTING_SENTENCE}, - {"break;", OP_STOP_EXECUTING_SENTENCE + OP_END_OF_SENTENCE}}; - - for (size_t i = 0; i < arraysize(cases); ++i) { - SCOPED_TRACE(cases[i].source_code); - std::string bytecode; - EXPECT_TRUE(JtlCompiler::Compile( - cases[i].source_code, kTestHashSeed, &bytecode, NULL)); - EXPECT_EQ(cases[i].expected_bytecode, bytecode); - } -} - -TEST(JtlCompiler, CompileEntireProgram) { - const char kSourceCode[] = - "// Store \"x\"=true if path is found.\n" - "go(\"foo\").go(\"bar\").store_bool(\"x\", true);\n" - "// ...\n" - "// Store \"y\"=\"1\" if above value is set.\n" - "compare_stored_bool(\"x\", true, false).store_hashed(\"y\", \"1\");\n"; - - std::string expected_bytecode = - OP_NAVIGATE(GetHash("foo")) + - OP_NAVIGATE(GetHash("bar")) + - OP_STORE_BOOL(GetHash("x"), VALUE_TRUE) + OP_END_OF_SENTENCE + - OP_COMPARE_STORED_BOOL(GetHash("x"), VALUE_TRUE, VALUE_FALSE) + - OP_STORE_HASH(GetHash("y"), GetHash("1")) + OP_END_OF_SENTENCE; - - std::string bytecode; - EXPECT_TRUE( - JtlCompiler::Compile(kSourceCode, kTestHashSeed, &bytecode, NULL)); - EXPECT_EQ(expected_bytecode, bytecode); -} - -TEST(JtlCompiler, InvalidOperationName) { - const char kSourceCode[] = "any()\n.\nnon_existent_instruction\n(\n)\n;\n"; - - std::string bytecode; - JtlCompiler::CompileError error; - EXPECT_FALSE( - JtlCompiler::Compile(kSourceCode, kTestHashSeed, &bytecode, &error)); - EXPECT_THAT(error.context, - testing::base::StartsWith("non_existent_instruction")); - EXPECT_EQ(2u, error.line_number); - EXPECT_EQ(JtlCompiler::CompileError::INVALID_OPERATION_NAME, - error.error_code); -} - -TEST(JtlCompiler, InvalidArgumentsCount) { - const char* const kSourceCodes[] = { - "any().\nstore_bool(\"name\", true, \"superfluous argument\");\n", - "any().\nstore_bool(\"name\");"}; // missing argument - - for (size_t i = 0; i < arraysize(kSourceCodes); ++i) { - SCOPED_TRACE(kSourceCodes[i]); - std::string bytecode; - JtlCompiler::CompileError error; - EXPECT_FALSE(JtlCompiler::Compile( - kSourceCodes[i], kTestHashSeed, &bytecode, &error)); - EXPECT_THAT(error.context, testing::base::StartsWith("store_bool")); - EXPECT_EQ(1u, error.line_number); - EXPECT_EQ(JtlCompiler::CompileError::INVALID_ARGUMENT_COUNT, - error.error_code); - } -} - -TEST(JtlCompiler, InvalidArgumentType) { - struct TestCase { - std::string expected_context_prefix; - std::string source_code; - } cases[] = { - {"compare_bool", "any()\n.\ncompare_bool(\"foo\");"}, - {"compare_bool", - "any()\n.\ncompare_bool(\"01234567890123456789012345678901\");"}, - {"compare_hashed", "any()\n.\ncompare_hashed(false);"}, - {"store_hash", "any()\n.\nstore_hash(\"name\", false);"}, - {"store_hash", "any()\n.\nstore_hash(\"name\", \"foo\");"}, - {"compare_stored_bool", - "any()\n.\ncompare_stored_bool(\"name\", \"need a bool\", false);"}, - {"compare_stored_bool", - "any()\n.\ncompare_stored_bool(\"name\", false, \"need a bool\");"}, - {"compare_substring_hashed", - "any()\n.\ncompare_substring_hashed(true);"}}; - - for (size_t i = 0; i < arraysize(cases); ++i) { - SCOPED_TRACE(cases[i].source_code); - std::string bytecode; - JtlCompiler::CompileError error; - EXPECT_FALSE(JtlCompiler::Compile( - cases[i].source_code, kTestHashSeed, &bytecode, &error)); - EXPECT_THAT(error.context, - testing::base::StartsWith(cases[i].expected_context_prefix)); - EXPECT_EQ(2u, error.line_number); - EXPECT_EQ(JtlCompiler::CompileError::INVALID_ARGUMENT_TYPE, - error.error_code); - } -} - -TEST(JtlCompiler, InvalidArgumentValue) { - struct TestCase { - std::string expected_context_prefix; - std::string source_code; - } cases[] = { - {"compare_substring_hashed", "compare_substring_hashed(\"\");"}}; - - for (size_t i = 0; i < arraysize(cases); ++i) { - SCOPED_TRACE(cases[i].source_code); - std::string bytecode; - JtlCompiler::CompileError error; - EXPECT_FALSE(JtlCompiler::Compile( - cases[i].source_code, kTestHashSeed, &bytecode, &error)); - EXPECT_THAT(error.context, - testing::base::StartsWith(cases[i].expected_context_prefix)); - EXPECT_EQ(0u, error.line_number); - EXPECT_EQ(JtlCompiler::CompileError::INVALID_ARGUMENT_VALUE, - error.error_code); - } -} - -TEST(JtlCompiler, MistmatchedDoubleQuotes) { - const char kSourceCode[] = "any().\ngo(\"ok\", \"stray quote).break();"; - - std::string bytecode; - JtlCompiler::CompileError error; - EXPECT_FALSE( - JtlCompiler::Compile(kSourceCode, kTestHashSeed, &bytecode, &error)); - EXPECT_EQ(1u, error.line_number); - EXPECT_EQ(JtlCompiler::CompileError::MISMATCHED_DOUBLE_QUOTES, - error.error_code); -} - -TEST(JtlCompiler, ParsingError) { - const char kSourceCode[] = "any().\ngo()missing_separator();"; - - std::string bytecode; - JtlCompiler::CompileError error; - EXPECT_FALSE( - JtlCompiler::Compile(kSourceCode, kTestHashSeed, &bytecode, &error)); - EXPECT_THAT(error.context, testing::base::StartsWith("go")); - EXPECT_EQ(1u, error.line_number); - EXPECT_EQ(JtlCompiler::CompileError::PARSING_ERROR, error.error_code); -} - -} // namespace diff --git a/chrome/tools/profile_reset/jtl_parser.cc b/chrome/tools/profile_reset/jtl_parser.cc deleted file mode 100644 index c1d9c15..0000000 --- a/chrome/tools/profile_reset/jtl_parser.cc +++ /dev/null @@ -1,167 +0,0 @@ -// Copyright 2013 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 "chrome/tools/profile_reset/jtl_parser.h" - -#include <algorithm> - -#include "base/logging.h" -#include "third_party/re2/re2/re2.h" - -namespace { - -// RegEx that matches the first line of a text. Will throw away any potential -// double-slash-introduced comments and the potential trailing EOL character. -// Note: will fail in case the first line contains an unmatched double-quote -// outside of comments. -const char kSingleLineWithMaybeCommentsRE[] = - // Non-greedily match and capture sequences of 1.) string literals inside - // correctly matched double-quotes, or 2.) any other character. - "^((?:\"[^\"\\n]*\"|[^\"\\n])*?)" - // Greedily match and throw away the potential comment. - "(?://.*)?" - // Match and throw away EOL, or match end-of-string. - "(?:\n|$)"; - -// RegEx to match either a double-quote-enclosed string literal or a whitespace. -// Applied repeatedly and without overlapping, can be used to remove whitespace -// outside of string literals. -const char kRemoveWhitespaceRE[] = "(\"[^\"]*\")|\\s"; - -// The substitution pattern to use together with the above when replacing. As -// the whitespace is not back-referenced here, it will get removed. -const char kRemoveWhitespaceRewrite[] = "\\1"; - -// Separator to terminate a sentence. -const char kEndOfSentenceSeparator[] = ";"; - -// The 'true' Boolean keyword. -const char kTrueKeyword[] = "true"; - -// RegEx that matches and captures one argument, which is either a double-quote -// enclosed string, or a Boolean value. Will throw away a trailing comma. -const char kSingleArgumentRE[] = "(?:(?:\"([^\"]*)\"|(true|false))(?:,|$))"; - -// RegEx-es that, when concatenated, will match a single operation, and capture -// the: operation name, the optional arguments, and the separator that follows. -const char kOperationNameRE[] = "([[:word:]]+)"; -const char kMaybeArgumentListRE[] = - "(?:\\(" // Opening parenthesis. - "((?:\"[^\"]*\"|[^\")])*)" // Capture: anything inside, quote-aware. - "\\))?"; // Closing parenthesis + everything optional. -const char kOperationSeparatorRE[] = "(;|\\.)"; - -} // namespace - -struct JtlParser::ParsingState { - explicit ParsingState(const re2::StringPiece& compacted_source) - : single_operation_regex(std::string(kOperationNameRE) + - kMaybeArgumentListRE + - kOperationSeparatorRE), - single_argument_regex(kSingleArgumentRE), - remaining_compacted_source(compacted_source), - last_line_number(0) {} - - RE2 single_operation_regex; - RE2 single_argument_regex; - re2::StringPiece remaining_compacted_source; - re2::StringPiece last_context; - size_t last_line_number; -}; - -JtlParser::JtlParser(const std::string& compacted_source_code, - const std::vector<size_t>& newline_indices) - : compacted_source_(compacted_source_code), - newline_indices_(newline_indices) { - state_.reset(new ParsingState(compacted_source_)); -} - -JtlParser::~JtlParser() {} - -// static -bool JtlParser::RemoveCommentsAndAllWhitespace( - const std::string& verbose_text, - std::string* compacted_text, - std::vector<size_t>* newline_indices, - size_t* error_line_number) { - DCHECK(compacted_text); - DCHECK(newline_indices); - std::string line; - RE2 single_line_regex(kSingleLineWithMaybeCommentsRE); - RE2 remove_whitespace_regex(kRemoveWhitespaceRE); - re2::StringPiece verbose_text_piece(verbose_text); - compacted_text->clear(); - newline_indices->clear(); - while (!verbose_text_piece.empty()) { - if (!RE2::Consume(&verbose_text_piece, single_line_regex, &line)) { - if (error_line_number) - *error_line_number = newline_indices->size(); - return false; - } - RE2::GlobalReplace( - &line, remove_whitespace_regex, kRemoveWhitespaceRewrite); - *compacted_text += line; - newline_indices->push_back(compacted_text->size()); - } - return true; -} - -bool JtlParser::HasFinished() { - return state_->remaining_compacted_source.empty(); -} - -bool JtlParser::ParseNextOperation(std::string* name, - base::ListValue* argument_list, - bool* ends_sentence) { - DCHECK(name); - DCHECK(argument_list); - DCHECK(ends_sentence); - - state_->last_context = state_->remaining_compacted_source; - state_->last_line_number = GetOriginalLineNumber( - compacted_source_.size() - state_->remaining_compacted_source.length()); - - std::string arguments, separator; - if (!RE2::Consume(&state_->remaining_compacted_source, - state_->single_operation_regex, - name, - &arguments, - &separator)) - return false; - - *ends_sentence = (separator == kEndOfSentenceSeparator); - state_->last_context.remove_suffix(state_->remaining_compacted_source.size()); - - re2::StringPiece arguments_piece(arguments); - std::string string_value, boolean_value; - while (!arguments_piece.empty()) { - if (!RE2::Consume(&arguments_piece, - state_->single_argument_regex, - &string_value, - &boolean_value)) - return false; - - if (!boolean_value.empty()) { - argument_list->Append( - new base::FundamentalValue(boolean_value == kTrueKeyword)); - } else { - // |string_value| might be empty for an empty string - argument_list->Append(new base::StringValue(string_value)); - } - } - return true; -} - -size_t JtlParser::GetOriginalLineNumber(size_t compacted_index) const { - return static_cast<size_t>(std::upper_bound(newline_indices_.begin(), - newline_indices_.end(), - compacted_index) - - newline_indices_.begin()); -} - -size_t JtlParser::GetLastLineNumber() const { return state_->last_line_number; } - -std::string JtlParser::GetLastContext() const { - return state_->last_context.ToString(); -} diff --git a/chrome/tools/profile_reset/jtl_parser.h b/chrome/tools/profile_reset/jtl_parser.h deleted file mode 100644 index e758211..0000000 --- a/chrome/tools/profile_reset/jtl_parser.h +++ /dev/null @@ -1,83 +0,0 @@ -// Copyright 2013 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 CHROME_TOOLS_PROFILE_RESET_JTL_PARSER_H_ -#define CHROME_TOOLS_PROFILE_RESET_JTL_PARSER_H_ - -#include <string> -#include <vector> - -#include "base/basictypes.h" -#include "base/memory/scoped_ptr.h" -#include "base/values.h" - -// Parses text-based JTL source code into a stream of operation names, arguments -// and separator kinds. -class JtlParser { - public: - // Creates a new parser to parse |compacted_source_code|, which should already - // be stripped of all comments and whitespace (except inside string literals). - // Use RemoveCommentsAndAllWhitespace() to manufacture these arguments, also - // see its comments for a description of |newline_indices|. - JtlParser(const std::string& compacted_source_code, - const std::vector<size_t>& newline_indices); - ~JtlParser(); - - // Removes comments from |verbose_text| and compacts it into whitespace-free - // format (except inside string literals). Elements in |newline_indices| will - // be monotonically increasing and will refer to positions in |compacted_text| - // such that a new line has been removed before that position. - // Example: - // verbose_text = "H e l l o // my\n" - // " dear \n" - // "\n" - // "world\" ! \"" - // compacted_text = "Hellodearworld\" ! \"" - // 01234567890123... - // newline_indices = {5, 9, 9} - // Returns true on success, false if there were unmatched quotes in a line, in - // which case |error_line_number| will be set accordingly if it is non-NULL. - static bool RemoveCommentsAndAllWhitespace( - const std::string& verbose_text, - std::string* compacted_text, - std::vector<size_t>* newline_indices, - size_t* error_line_number); - - // Returns true if the entire input has been successfully consumed. Note that - // even when this returns false, a subsequent call to ParseNextOperation() - // might still fail if the next operation cannot be parsed. - bool HasFinished(); - - // Fetches the |name| and the |argument_list| of the next operation, and also - // whether or not it |ends_the_sentence|, i.e. it is followed by the - // end-of-sentence separator. - // Returns false if there is a parsing error, in which case the values for the - // output parameters are undefined, and |this| parser shall no longer be used. - bool ParseNextOperation(std::string* name, - base::ListValue* argument_list, - bool* ends_the_sentence); - - // Returns the compacted source code that was passed in to the constructor. - const std::string& compacted_source() const { return compacted_source_; } - - // Returns at which line the character at position |compacted_index| in the - // |compacted_source()| was originally located. - size_t GetOriginalLineNumber(size_t compacted_index) const; - - size_t GetLastLineNumber() const; - std::string GetLastContext() const; - - private: - // Contains pre-compiled regular expressions and related state. Factored out - // to avoid this header depending on RE2 headers. - struct ParsingState; - - std::string compacted_source_; - std::vector<size_t> newline_indices_; - scoped_ptr<ParsingState> state_; - - DISALLOW_COPY_AND_ASSIGN(JtlParser); -}; - -#endif // CHROME_TOOLS_PROFILE_RESET_JTL_PARSER_H_ diff --git a/chrome/tools/profile_reset/jtl_parser_unittest.cc b/chrome/tools/profile_reset/jtl_parser_unittest.cc deleted file mode 100644 index 87b7ebc..0000000 --- a/chrome/tools/profile_reset/jtl_parser_unittest.cc +++ /dev/null @@ -1,346 +0,0 @@ -// Copyright 2013 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 "chrome/tools/profile_reset/jtl_parser.h" - -#include "base/json/json_writer.h" -#include "base/memory/scoped_ptr.h" -#include "base/values.h" -#include "testing/gmock/include/gmock/gmock.h" -#include "testing/gtest/include/gtest/gtest.h" - -namespace { - -// Helpers ------------------------------------------------------------------- - -void ExpectNextOperation(JtlParser* parser, - const char* expected_name, - const char* expected_args_json, - bool expected_ends_sentence) { - std::string actual_name; - base::ListValue actual_args; - std::string actual_args_json; - bool actual_ends_sentence; - - EXPECT_FALSE(parser->HasFinished()); - EXPECT_TRUE(parser->ParseNextOperation( - &actual_name, &actual_args, &actual_ends_sentence)); - EXPECT_EQ(expected_name, actual_name); - base::JSONWriter::Write(&actual_args, &actual_args_json); - EXPECT_EQ(expected_args_json, actual_args_json); - EXPECT_EQ(expected_ends_sentence, actual_ends_sentence); -} - -void ExpectNextOperationToFail(JtlParser* parser, - size_t expected_line_number, - const char* expected_context_prefix) { - std::string actual_name; - base::ListValue actual_args; - bool actual_ends_sentence; - - EXPECT_FALSE(parser->HasFinished()); - EXPECT_FALSE(parser->ParseNextOperation( - &actual_name, &actual_args, &actual_ends_sentence)); - EXPECT_THAT(parser->GetLastContext(), - testing::base::StartsWith(expected_context_prefix)); - EXPECT_EQ(expected_line_number, parser->GetLastLineNumber()); -} - -JtlParser* CreateParserFromVerboseText(const std::string& verbose_text) { - std::string compacted_source_code; - std::vector<size_t> newline_indices; - EXPECT_TRUE(JtlParser::RemoveCommentsAndAllWhitespace( - verbose_text, &compacted_source_code, &newline_indices, NULL)); - return new JtlParser(compacted_source_code, newline_indices); -} - -// Tests --------------------------------------------------------------------- - -TEST(JtlParser, CompactingEmpty) { - const char kSourceCode[] = ""; - const char kCompactedSourceCode[] = ""; - - scoped_ptr<JtlParser> parser(CreateParserFromVerboseText(kSourceCode)); - EXPECT_EQ(kCompactedSourceCode, parser->compacted_source()); -} - -TEST(JtlParser, CompactingTrivial) { - const char kSourceCode[] = "foo"; - const char kCompactedSourceCode[] = "foo"; - - scoped_ptr<JtlParser> parser(CreateParserFromVerboseText(kSourceCode)); - EXPECT_EQ(kCompactedSourceCode, parser->compacted_source()); -} - -TEST(JtlParser, CompactingOneLine) { - const char kSourceCode[] = " \r f\to o ( true ) "; - const char kCompactedSourceCode[] = "foo(true)"; - - scoped_ptr<JtlParser> parser(CreateParserFromVerboseText(kSourceCode)); - EXPECT_EQ(kCompactedSourceCode, parser->compacted_source()); - for (size_t i = 0; i < arraysize(kCompactedSourceCode) - 1; ++i) { - SCOPED_TRACE(testing::Message("Position ") << i); - EXPECT_EQ(0u, parser->GetOriginalLineNumber(i)); - } -} - -TEST(JtlParser, CompactingMultipleLines) { - const char kSourceCode[] = "a\nbb\n \nccc \n\n d( \n e \n )"; - const char kCompactedSourceCode[] = "abbcccd(e)"; - const size_t kLineNumbers[] = {0u, 1u, 1u, 3u, 3u, 3u, 5u, 5u, 6u, 7u}; - static_assert(arraysize(kCompactedSourceCode) == arraysize(kLineNumbers) + 1, - "mismatched test data"); - - scoped_ptr<JtlParser> parser(CreateParserFromVerboseText(kSourceCode)); - EXPECT_EQ(kCompactedSourceCode, parser->compacted_source()); - for (size_t i = 0; i < arraysize(kLineNumbers); ++i) { - SCOPED_TRACE(testing::Message("Position ") << i); - EXPECT_EQ(kLineNumbers[i], parser->GetOriginalLineNumber(i)); - } -} - -TEST(JtlParser, CompactingMultipleLinesWithComments) { - const char kSourceCode[] = - "a/ /b//Comment \n" - "//\n" - "// Full line comment\n" - " cd //"; - const char kCompactedSourceCode[] = "a//bcd"; - const size_t kLineNumbers[] = {0u, 0u, 0u, 0u, 3u, 3u}; - static_assert(arraysize(kCompactedSourceCode) == arraysize(kLineNumbers) + 1, - "mismatched test data"); - - scoped_ptr<JtlParser> parser(CreateParserFromVerboseText(kSourceCode)); - EXPECT_EQ(kCompactedSourceCode, parser->compacted_source()); - for (size_t i = 0; i < arraysize(kLineNumbers); ++i) { - SCOPED_TRACE(testing::Message("Position ") << i); - EXPECT_EQ(kLineNumbers[i], parser->GetOriginalLineNumber(i)); - } -} - -TEST(JtlParser, HandlingCommentsAndStringLiterals) { - struct TestCase { - const char* source_code; - const char* compacted_source_code; - } cases[] = { - {"//", ""}, - {"//comment", ""}, - {"foo // comment", "foo"}, - {"foo // // comment", "foo"}, - {"foo //", "foo"}, - {"\"literal\"", "\"literal\""}, - {"\"literal with space\"", "\"literal with space\""}, - {"\"\"", "\"\""}, - {"\"\"\"\"", "\"\"\"\""}, - {"\"\" // comment", "\"\""}, - {"\"literal\" // comment", "\"literal\""}, - {"\"literal\" \"literal\" // comment", "\"literal\"\"literal\""}, - {"foo // \"not a literal\"", "foo"}, - {"foo // \"not even matched", "foo"}, - {"foo // \"not a literal\" \"not even matched", "foo"}, - {"\"literal\" // \"not a literal\"", "\"literal\""}, - {"\"literal\" // \"not even matched", "\"literal\""}, - {"\"//not a comment//\"", "\"//not a comment//\""}, - {"\"//not a comment//\" // comment", "\"//not a comment//\""}, - {"// \"//not a literal//\" // comment", ""}, - {"\"literal\" // \"//not a literal//\" // comment", "\"literal\""}, - {"\"//not a comment//\" // \"//not a literal//\" // comment", - "\"//not a comment//\""}, - {"\"literal // \"not a literal nor a comment", - "\"literal // \"notaliteralnoracomment"}, - {"\"literal // \"not a literal nor a comment//\"", - "\"literal // \"notaliteralnoracomment"} - }; - - for (size_t i = 0; i < arraysize(cases); ++i) { - SCOPED_TRACE(cases[i].source_code); - scoped_ptr<JtlParser> parser( - CreateParserFromVerboseText(cases[i].source_code)); - EXPECT_EQ(cases[i].compacted_source_code, parser->compacted_source()); - } -} - -TEST(JtlParser, MismatchedDoubleQuotesBeforeEndOfLine) { - struct TestCase { - const char* source_code; - size_t error_line_number; - } cases[] = { - {"\"", 0}, - {"\"mismatched literal", 0}, - {"\n\"", 1}, - {"\"\n\"", 0}, - {"\"\"\"", 0}, - {"\"\"\n\"", 1}, - {"\"\"\n\"\n\"", 1}, - {"\" // not a comment", 0}, - {"\" // not a comment\n\"", 0}, - {"\"\" // comment\n\"", 1}, - {"\"\"\" // not a comment\n\"", 0}, - {"\"\"\" // \" neither a literal nor a comment\"\n\"", 0}, - {"\"\" // comment\n\"// not a comment", 1}, - {"\" // not a comment\"\n\"// not a comment", 1}, - {"foo(\"bar\");\nfoo(\"mismatched);", 1}, - {"foo(\n\"bar\", \"mismatched);", 1}, - {"foo(\n\"bar\", \"mismatched); //comment", 1}, - {"foo(\n\"bar\", \"mismatched);\ngood(\"bar\")", 1} - }; - - for (size_t i = 0; i < arraysize(cases); ++i) { - SCOPED_TRACE(cases[i].source_code); - std::string compacted_source_code; - std::vector<size_t> newline_indices; - size_t error_line_number; - EXPECT_FALSE(JtlParser::RemoveCommentsAndAllWhitespace( - cases[i].source_code, - &compacted_source_code, - &newline_indices, - &error_line_number)); - EXPECT_EQ(cases[i].error_line_number, error_line_number); - } -} - -TEST(JtlParser, ParsingEmpty) { - const char kSourceCode[] = ""; - - scoped_ptr<JtlParser> parser(CreateParserFromVerboseText(kSourceCode)); - EXPECT_TRUE(parser->HasFinished()); -} - -TEST(JtlParser, ParsingOneWellFormedOperation) { - struct TestCase { - const char* source_code; - const char* expected_name; - const char* expected_args; - const bool expected_ends_sentence; - } cases[] = { - {"foo1;", "foo1", "[]", true}, - {"foo2().", "foo2", "[]", false}, - {"foo3(true);", "foo3", "[true]", true}, - {"foo4(false).", "foo4", "[false]", false}, - {"foo5(\"bar\").", "foo5", "[\"bar\"]", false}, - {"foo6(\" b a r \").", "foo6", "[\" b a r \"]", false}, - {"foo7(true, \"bar\").", "foo7", "[true,\"bar\"]", false}, - {"foo8(\"bar\", false, true);", "foo8", "[\"bar\",false,true]", true}, - {"foo9(\"bar\", \" b a r \");", "foo9", "[\"bar\",\" b a r \"]", true} - }; - - for (size_t i = 0; i < arraysize(cases); ++i) { - SCOPED_TRACE(cases[i].expected_name); - scoped_ptr<JtlParser> parser( - CreateParserFromVerboseText(cases[i].source_code)); - ExpectNextOperation(parser.get(), - cases[i].expected_name, - cases[i].expected_args, - cases[i].expected_ends_sentence); - EXPECT_TRUE(parser->HasFinished()); - } -} - -TEST(JtlParser, ParsingMultipleWellFormedOperations) { - const char kSourceCode[] = - "foo1(true).foo2.foo3(\"bar\");" - "foo4(\"bar\", false);"; - - scoped_ptr<JtlParser> parser(CreateParserFromVerboseText(kSourceCode)); - ExpectNextOperation(parser.get(), "foo1", "[true]", false); - ExpectNextOperation(parser.get(), "foo2", "[]", false); - ExpectNextOperation(parser.get(), "foo3", "[\"bar\"]", true); - ExpectNextOperation(parser.get(), "foo4", "[\"bar\",false]", true); - EXPECT_TRUE(parser->HasFinished()); -} - -TEST(JtlParser, ParsingTrickyStringLiterals) { - struct TestCase { - const char* source_code; - const char* expected_name; - const char* expected_args; - const bool expected_ends_sentence; - } cases[] = { - {"prev().foo1(\"\");next(true);", "foo1", "[\"\"]", true}, - {"prev().foo2(\" \");next(true);", "foo2", "[\" \"]", true}, - {"prev().foo3(\",\",true);next(true);", "foo3", "[\",\",true]", true}, - {"prev().foo4(\")\",true);next(true);", "foo4", "[\")\",true]", true}, - {"prev().foo5(\";\",true);next(true);", "foo5", "[\";\",true]", true}, - {"prev().foo6(\"/\",true).next(true);", "foo6", "[\"/\",true]", false}, - {"prev().foo7(\"//\",true).next(true);", "foo7", "[\"//\",true]", false}, - {"prev().foo8(\".\",true).next(true);", "foo8", "[\".\",true]", false}, - }; - - for (size_t i = 0; i < arraysize(cases); ++i) { - SCOPED_TRACE(cases[i].expected_name); - scoped_ptr<JtlParser> parser( - CreateParserFromVerboseText(cases[i].source_code)); - ExpectNextOperation(parser.get(), "prev", "[]", false); - ExpectNextOperation(parser.get(), - cases[i].expected_name, - cases[i].expected_args, - cases[i].expected_ends_sentence); - ExpectNextOperation(parser.get(), "next", "[true]", true); - EXPECT_TRUE(parser->HasFinished()); - } -} - -TEST(JtlParser, FirstOperationIsIllFormed) { - struct TestCase { - const char* source_code; - const char* operation_name; - } cases[] = { - {";;", ";"}, - {"bad_args1(not a boolean value);", "bad_args1"}, - {"bad_args2(,);", "bad_args2"}, - {"bad_args3(...);", "bad_args3"}, - {"bad_args4(1);", "bad_args4"}, - {"bad_args5(1.2);", "bad_args5"}, - {"bad_args6([\"bar\"]);", "bad_args6"}, - {"bad_args7(False);", "bad_args7"}, - {"bad_args8(True);", "bad_args8"}, - {"bad_quotes1(missing both, true).good();", "bad_quotes1"}, - {"bad_quotes2(true, \"missing one).good(); //\"", "bad_quotes2"}, - {"bad_quotes3(\"too\" \"much\", true).good();", "bad_quotes3"}, - {"bad_missing_separator1", "bad_missing_separator1"}, - {"bad_missing_separator2()good();", "bad_missing_separator2"}, - {"bad_parenthesis1(true.good();", "bad_parenthesis1"}, - {"bad_parenthesis2(true.good());", "bad_parenthesis2"}, - {"bad_parenthesis3).good();", "bad_parenthesis3"} - }; - - for (size_t i = 0; i < arraysize(cases); ++i) { - SCOPED_TRACE(cases[i].operation_name); - scoped_ptr<JtlParser> parser( - CreateParserFromVerboseText(cases[i].source_code)); - ExpectNextOperationToFail(parser.get(), 0, cases[i].operation_name); - } -} - -TEST(JtlParser, SecondOperationIsIllFormed) { - struct TestCase { - const char* source_code; - const char* bad_operation_name; - } cases[] = { - {"\ngood(true,false)\n.bad_args(,);", "bad_args"}, - {"\ngood(true,false)\n.bad_quotes1(missing both, true).good();", - "bad_quotes1"}, - {"\ngood(true,false)\n.bad_quotes2(\"missing one, true).good(); //\"", - "bad_quotes2"}, - {"\ngood(true,false)\n.bad_quotes3(\"too\" \"many\", true).good();", - "bad_quotes3"}, - {"\ngood(true,false)\n.bad_separator1()/good();", "bad_separator1"}, - {"\ngood(true,false)\n.missing_separator1", "missing_separator1"}, - {"\ngood(true,false)\n.missing_separator2()good();", - "missing_separator2"}, - {"\ngood(true,false)\n.bad_parens1(true.good();", "bad_parens1"}, - {"\ngood(true,false)\n.bad_parens2(true.good());", "bad_parens2"}, - {"\ngood(true,false)\n.bad_parens3).good();", "bad_parens3"} - }; - - for (size_t i = 0; i < arraysize(cases); ++i) { - SCOPED_TRACE(cases[i].bad_operation_name); - scoped_ptr<JtlParser> parser( - CreateParserFromVerboseText(cases[i].source_code)); - ExpectNextOperation(parser.get(), "good", "[true,false]", false); - ExpectNextOperationToFail(parser.get(), 2, cases[i].bad_operation_name); - } -} - -} // namespace diff --git a/tools/metrics/histograms/histograms.xml b/tools/metrics/histograms/histograms.xml index 91055f0..a5df54b 100644 --- a/tools/metrics/histograms/histograms.xml +++ b/tools/metrics/histograms/histograms.xml @@ -75843,7 +75843,7 @@ To add a new entry, add it with any value and run test to compute valid value. <int value="10" label="kDefaultSearchProviderName"/> <int value="11" label="kPinnedTabs"/> <int value="12" label="kKnownDisabled (Obsolete 07/2014)"/> - <int value="13" label="kProfileResetPromptMemento"/> + <int value="13" label="kProfileResetPromptMemento (Obsolete 11/2015)"/> <int value="14" label="kDefaultSearchProviderDataPrefName"/> <int value="15" label="kPreferenceResetTime"/> <int value="16" label="kSafeBrowsingIncidentReportSent"/> |