diff options
author | Allan Sandfeld Jensen <allan.jensen@qt.io> | 2017-09-18 14:34:04 +0200 |
---|---|---|
committer | Allan Sandfeld Jensen <allan.jensen@qt.io> | 2017-10-04 11:15:27 +0000 |
commit | e6430e577f105ad8813c92e75c54660c4985026e (patch) | |
tree | 88115e5d1fb471fea807111924dcccbeadbf9e4f /chromium/components/signin | |
parent | 53d399fe6415a96ea6986ec0d402a9c07da72453 (diff) | |
download | qtwebengine-chromium-e6430e577f105ad8813c92e75c54660c4985026e.tar.gz |
BASELINE: Update Chromium to 61.0.3163.99
Change-Id: I8452f34574d88ca2b27af9bd56fc9ff3f16b1367
Reviewed-by: Alexandru Croitor <alexandru.croitor@qt.io>
Diffstat (limited to 'chromium/components/signin')
59 files changed, 1304 insertions, 469 deletions
diff --git a/chromium/components/signin/core/account_id/account_id.cc b/chromium/components/signin/core/account_id/account_id.cc index 1ffac80db1e..e232ecb965c 100644 --- a/chromium/components/signin/core/account_id/account_id.cc +++ b/chromium/components/signin/core/account_id/account_id.cc @@ -319,6 +319,16 @@ bool AccountId::Deserialize(const std::string& serialized, return false; } +std::ostream& operator<<(std::ostream& stream, const AccountId& account_id) { + stream << "{id: " << account_id.id_ << ", email: " << account_id.user_email_ + << ", type: " + << static_cast< + std::underlying_type<decltype(account_id.account_type_)>::type>( + account_id.account_type_) + << "}"; + return stream; +} + const AccountId& EmptyAccountId() { return AccountId::EmptyAccountId::GetInstance()->user_id; } diff --git a/chromium/components/signin/core/account_id/account_id.h b/chromium/components/signin/core/account_id/account_id.h index 81082b5fe04..a263178d13d 100644 --- a/chromium/components/signin/core/account_id/account_id.h +++ b/chromium/components/signin/core/account_id/account_id.h @@ -7,7 +7,9 @@ #include <stddef.h> +#include <ostream> #include <string> + #include "base/containers/hash_tables.h" enum class AccountType { UNKNOWN, GOOGLE, ACTIVE_DIRECTORY }; @@ -97,6 +99,8 @@ class AccountId { AccountId* out_account_id); private: + friend std::ostream& operator<<(std::ostream&, const AccountId&); + AccountId(const std::string& id, const std::string& user_email, const AccountType& account_type); @@ -106,6 +110,9 @@ class AccountId { AccountType account_type_ = AccountType::UNKNOWN; }; +// Overload << operator to allow logging of AccountIds. +std::ostream& operator<<(std::ostream& stream, const AccountId& account_id); + // Returns a reference to a singleton. const AccountId& EmptyAccountId(); diff --git a/chromium/components/signin/core/browser/BUILD.gn b/chromium/components/signin/core/browser/BUILD.gn index 5265026b314..b900638e0cf 100644 --- a/chromium/components/signin/core/browser/BUILD.gn +++ b/chromium/components/signin/core/browser/BUILD.gn @@ -2,10 +2,23 @@ # Use of this source code is governed by a BSD-style license that can be # found in the LICENSE file. +import("//components/signin/features.gni") + if (is_android) { import("//build/config/android/rules.gni") } +# Split into its own target to allow the Identity Service to depend on it in +# typemaps without introducing a dependency on all of +# //components/signin/core/browser, which is undesirable. In the long term +# this file will move to be part of the Identity Service client library. +static_library("account_info") { + sources = [ + "account_info.cc", + "account_info.h", + ] +} + static_library("browser") { sources = [ "about_signin_internals.cc", @@ -14,8 +27,6 @@ static_library("browser") { "access_token_fetcher.h", "account_fetcher_service.cc", "account_fetcher_service.h", - "account_info.cc", - "account_info.h", "account_info_fetcher.cc", "account_info_fetcher.h", "account_investigator.cc", @@ -24,14 +35,16 @@ static_library("browser") { "account_reconcilor.h", "account_tracker_service.cc", "account_tracker_service.h", - "android/component_jni_registrar.cc", - "android/component_jni_registrar.h", "child_account_info_fetcher.cc", "child_account_info_fetcher.h", "child_account_info_fetcher_android.cc", "child_account_info_fetcher_android.h", "child_account_info_fetcher_impl.cc", "child_account_info_fetcher_impl.h", + "chrome_connected_header_helper.cc", + "chrome_connected_header_helper.h", + "dice_header_helper.cc", + "dice_header_helper.h", "gaia_cookie_manager_service.cc", "gaia_cookie_manager_service.h", "profile_identity_provider.cc", @@ -75,26 +88,29 @@ static_library("browser") { configs += [ "//build/config/compiler:no_size_t_to_int_warning" ] public_deps = [ + ":account_info", + "//base", + "//components/content_settings/core/browser", + "//components/content_settings/core/common", + "//components/invalidation/public", + "//components/keyed_service/core", + "//components/prefs", "//components/signin/core/account_id", "//components/signin/core/common", + "//components/signin/core/common:signin_features", + "//google_apis", + "//net", + "//url", ] deps = [ - "//base", "//base:i18n", - "//components/content_settings/core/browser", - "//components/content_settings/core/common", "//components/data_use_measurement/core", "//components/google/core/browser", - "//components/invalidation/public", - "//components/keyed_service/core", "//components/metrics", "//components/os_crypt", "//components/pref_registry", - "//components/prefs", "//components/webdata/common", "//crypto", - "//google_apis", - "//net", "//sql", "//third_party/icu", ] @@ -107,6 +123,13 @@ static_library("browser") { ] } + if (!enable_dice_support) { + sources -= [ + "dice_header_helper.cc", + "dice_header_helper.h", + ] + } + if (is_android) { sources -= [ "child_account_info_fetcher_impl.cc", @@ -167,6 +190,7 @@ source_set("unit_tests") { "//components/os_crypt:test_support", "//components/pref_registry:pref_registry", "//components/signin/core/common", + "//components/signin/core/common:signin_features", "//components/sync_preferences:test_support", "//testing/gmock", ] diff --git a/chromium/components/signin/core/browser/about_signin_internals.cc b/chromium/components/signin/core/browser/about_signin_internals.cc index da7be07b13c..fca6fbe2507 100644 --- a/chromium/components/signin/core/browser/about_signin_internals.cc +++ b/chromium/components/signin/core/browser/about_signin_internals.cc @@ -42,11 +42,11 @@ std::string GetTimeStr(base::Time time) { base::ListValue* AddSection(base::ListValue* parent_list, const std::string& title) { - std::unique_ptr<base::DictionaryValue> section(new base::DictionaryValue()); - base::ListValue* section_contents = new base::ListValue(); + auto section = base::MakeUnique<base::DictionaryValue>(); section->SetString("title", title); - section->Set("data", section_contents); + base::ListValue* section_contents = + section->SetList("data", base::MakeUnique<base::ListValue>()); parent_list->Append(std::move(section)); return section_contents; } @@ -393,8 +393,7 @@ void AboutSigninInternals::GoogleSigninFailed( } void AboutSigninInternals::GoogleSigninSucceeded(const std::string& account_id, - const std::string& username, - const std::string& password) { + const std::string& username) { NotifyObservers(); } @@ -410,24 +409,21 @@ void AboutSigninInternals::OnGaiaAccountsInCookieUpdated( if (error.state() != GoogleServiceAuthError::NONE) return; - base::DictionaryValue cookie_status; - base::ListValue* cookie_info = new base::ListValue(); - cookie_status.Set("cookie_info", cookie_info); + auto cookie_info = base::MakeUnique<base::ListValue>(); for (size_t i = 0; i < gaia_accounts.size(); ++i) { - AddCookieEntry(cookie_info, - gaia_accounts[i].raw_email, + AddCookieEntry(cookie_info.get(), gaia_accounts[i].raw_email, gaia_accounts[i].gaia_id, gaia_accounts[i].valid ? "Valid" : "Invalid"); } if (gaia_accounts.size() == 0) { - AddCookieEntry(cookie_info, - "No Accounts Present.", - std::string(), + AddCookieEntry(cookie_info.get(), "No Accounts Present.", std::string(), std::string()); } + base::DictionaryValue cookie_status; + cookie_status.Set("cookie_info", std::move(cookie_info)); // Update the observers that the cookie's accounts are updated. for (auto& observer : signin_observers_) observer.OnCookieAccountsFetched(&cookie_status); @@ -529,16 +525,16 @@ AboutSigninInternals::SigninStatus::ToValue( FROM_HERE_WITH_EXPLICIT_FUNCTION( "422460 AboutSigninInternals::SigninStatus::ToValue1")); - std::unique_ptr<base::DictionaryValue> signin_status( - new base::DictionaryValue()); - base::ListValue* signin_info = new base::ListValue(); - signin_status->Set("signin_info", signin_info); + auto signin_status = base::MakeUnique<base::DictionaryValue>(); + auto signin_info = base::MakeUnique<base::ListValue>(); // A summary of signin related info first. - base::ListValue* basic_info = AddSection(signin_info, "Basic Information"); + base::ListValue* basic_info = + AddSection(signin_info.get(), "Basic Information"); AddSectionEntry(basic_info, "Chrome Version", product_version); - AddSectionEntry(basic_info, "Account Consistency?", - switches::IsEnableAccountConsistency() == true ? "On" : "Off"); + AddSectionEntry( + basic_info, "Account Consistency?", + switches::IsAccountConsistencyMirrorEnabled() == true ? "On" : "Off"); AddSectionEntry(basic_info, "Signin Status", signin_manager->IsAuthenticated() ? "Signed In" : "Not Signed In"); OAuth2TokenServiceDelegate::LoadCredentialsState load_tokens_state = @@ -589,7 +585,8 @@ AboutSigninInternals::SigninStatus::ToValue( // Time and status information of the possible sign in types. base::ListValue* detailed_info = - AddSection(signin_info, "Last Signin Details"); + AddSection(signin_info.get(), "Last Signin Details"); + signin_status->Set("signin_info", std::move(signin_info)); for (int i = TIMED_FIELDS_BEGIN; i < TIMED_FIELDS_END; ++i) { const std::string status_field_label = SigninStatusFieldToLabel(static_cast<TimedSigninStatusField>(i)); @@ -644,8 +641,7 @@ AboutSigninInternals::SigninStatus::ToValue( "422460 AboutSigninInternals::SigninStatus::ToValue4")); // Token information for all services. - base::ListValue* token_info = new base::ListValue(); - signin_status->Set("token_info", token_info); + auto token_info = base::MakeUnique<base::ListValue>(); for (auto it = token_info_map.begin(); it != token_info_map.end(); ++it) { // TODO(robliao): Remove ScopedTracker below once https://crbug.com/422460 // is fixed. @@ -653,7 +649,7 @@ AboutSigninInternals::SigninStatus::ToValue( FROM_HERE_WITH_EXPLICIT_FUNCTION( "422460 AboutSigninInternals::SigninStatus::ToValue41")); - base::ListValue* token_details = AddSection(token_info, it->first); + base::ListValue* token_details = AddSection(token_info.get(), it->first); // TODO(robliao): Remove ScopedTracker below once https://crbug.com/422460 // is fixed. @@ -674,24 +670,24 @@ AboutSigninInternals::SigninStatus::ToValue( token_details->Append(token->ToValue()); } } + signin_status->Set("token_info", std::move(token_info)); - base::ListValue* account_info = new base::ListValue(); - signin_status->Set("accountInfo", account_info); + auto account_info = base::MakeUnique<base::ListValue>(); const std::vector<std::string>& accounts_in_token_service = token_service->GetAccounts(); - if(accounts_in_token_service.size() == 0) { - std::unique_ptr<base::DictionaryValue> no_token_entry( - new base::DictionaryValue()); + if (accounts_in_token_service.size() == 0) { + auto no_token_entry = base::MakeUnique<base::DictionaryValue>(); no_token_entry->SetString("accountId", "No token in Token Service."); account_info->Append(std::move(no_token_entry)); } - for(const std::string& account_id : accounts_in_token_service) { - std::unique_ptr<base::DictionaryValue> entry(new base::DictionaryValue()); + for (const std::string& account_id : accounts_in_token_service) { + auto entry = base::MakeUnique<base::DictionaryValue>(); entry->SetString("accountId", account_id); account_info->Append(std::move(entry)); } + signin_status->Set("accountInfo", std::move(account_info)); return signin_status; } diff --git a/chromium/components/signin/core/browser/about_signin_internals.h b/chromium/components/signin/core/browser/about_signin_internals.h index 8e42feab409..46d11da5fe1 100644 --- a/chromium/components/signin/core/browser/about_signin_internals.h +++ b/chromium/components/signin/core/browser/about_signin_internals.h @@ -191,8 +191,7 @@ class AboutSigninInternals // SigninManagerBase::Observer implementations. void GoogleSigninFailed(const GoogleServiceAuthError& error) override; void GoogleSigninSucceeded(const std::string& account_id, - const std::string& username, - const std::string& password) override; + const std::string& username) override; void GoogleSignedOut(const std::string& account_id, const std::string& username) override; diff --git a/chromium/components/signin/core/browser/access_token_fetcher.cc b/chromium/components/signin/core/browser/access_token_fetcher.cc index d301d3708da..de834072eed 100644 --- a/chromium/components/signin/core/browser/access_token_fetcher.cc +++ b/chromium/components/signin/core/browser/access_token_fetcher.cc @@ -76,8 +76,7 @@ void AccessTokenFetcher::StartAccessTokenRequest() { } void AccessTokenFetcher::GoogleSigninSucceeded(const std::string& account_id, - const std::string& username, - const std::string& password) { + const std::string& username) { DCHECK(waiting_for_sign_in_); DCHECK(!waiting_for_refresh_token_); DCHECK(signin_manager_->IsAuthenticated()); diff --git a/chromium/components/signin/core/browser/access_token_fetcher.h b/chromium/components/signin/core/browser/access_token_fetcher.h index 2963ab8b797..cfa84724e48 100644 --- a/chromium/components/signin/core/browser/access_token_fetcher.h +++ b/chromium/components/signin/core/browser/access_token_fetcher.h @@ -51,8 +51,7 @@ class AccessTokenFetcher : public SigninManagerBase::Observer, // SigninManagerBase::Observer implementation. void GoogleSigninSucceeded(const std::string& account_id, - const std::string& username, - const std::string& password) override; + const std::string& username) override; void GoogleSigninFailed(const GoogleServiceAuthError& error) override; // OAuth2TokenService::Observer implementation. diff --git a/chromium/components/signin/core/browser/account_fetcher_service.cc b/chromium/components/signin/core/browser/account_fetcher_service.cc index 7f25b2d377c..6203942dac4 100644 --- a/chromium/components/signin/core/browser/account_fetcher_service.cc +++ b/chromium/components/signin/core/browser/account_fetcher_service.cc @@ -65,6 +65,7 @@ AccountFetcherService::AccountFetcherService() child_info_request_(nullptr) {} AccountFetcherService::~AccountFetcherService() { + DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); DCHECK(shutdown_called_); } @@ -142,7 +143,7 @@ void AccountFetcherService::RefreshAllAccountInfo(bool only_fetch_if_invalid) { // account. This is possible since we only support a single account to be a // child anyway. void AccountFetcherService::UpdateChildInfo() { - DCHECK(CalledOnValidThread()); + DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); std::vector<std::string> accounts = token_service_->GetAccounts(); if (accounts.size() == 1) { const std::string& candidate = accounts[0]; @@ -160,7 +161,7 @@ void AccountFetcherService::UpdateChildInfo() { } void AccountFetcherService::MaybeEnableNetworkFetches() { - DCHECK(CalledOnValidThread()); + DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); if (!profile_loaded_ || !refresh_tokens_loaded_) return; if (!network_fetches_enabled_) { @@ -199,7 +200,7 @@ void AccountFetcherService::ScheduleNextRefresh() { // Starts fetching user information. This is called periodically to refresh. void AccountFetcherService::StartFetchingUserInfo( const std::string& account_id) { - DCHECK(CalledOnValidThread()); + DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); DCHECK(network_fetches_enabled_); std::unique_ptr<AccountInfoFetcher>& request = @@ -341,7 +342,7 @@ void AccountFetcherService::OnRefreshTokenRevoked( } void AccountFetcherService::OnRefreshTokensLoaded() { - DCHECK(CalledOnValidThread()); + DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); refresh_tokens_loaded_ = true; MaybeEnableNetworkFetches(); } diff --git a/chromium/components/signin/core/browser/account_fetcher_service.h b/chromium/components/signin/core/browser/account_fetcher_service.h index 5ca34f1fc8a..aefdcdd3a92 100644 --- a/chromium/components/signin/core/browser/account_fetcher_service.h +++ b/chromium/components/signin/core/browser/account_fetcher_service.h @@ -11,7 +11,7 @@ #include <unordered_map> #include "base/macros.h" -#include "base/threading/non_thread_safe.h" +#include "base/sequence_checker.h" #include "base/timer/timer.h" #include "components/keyed_service/core/keyed_service.h" #include "google_apis/gaia/oauth2_token_service.h" @@ -32,8 +32,7 @@ class PrefRegistrySyncable; } class AccountFetcherService : public KeyedService, - public OAuth2TokenService::Observer, - public base::NonThreadSafe { + public OAuth2TokenService::Observer { public: // Name of the preference that tracks the int64_t representation of the last // time the AccountTrackerService was updated. @@ -139,6 +138,8 @@ class AccountFetcherService : public KeyedService, std::unique_ptr<RefreshTokenAnnotationRequest>> refresh_token_annotation_requests_; + SEQUENCE_CHECKER(sequence_checker_); + DISALLOW_COPY_AND_ASSIGN(AccountFetcherService); }; diff --git a/chromium/components/signin/core/browser/account_reconcilor.cc b/chromium/components/signin/core/browser/account_reconcilor.cc index 5a0170eb3f6..3393ef7333e 100644 --- a/chromium/components/signin/core/browser/account_reconcilor.cc +++ b/chromium/components/signin/core/browser/account_reconcilor.cc @@ -222,8 +222,7 @@ void AccountReconcilor::OnEndBatchChanges() { } void AccountReconcilor::GoogleSigninSucceeded(const std::string& account_id, - const std::string& username, - const std::string& password) { + const std::string& username) { VLOG(1) << "AccountReconcilor::GoogleSigninSucceeded: signed in"; RegisterWithCookieManagerService(); RegisterWithContentSettings(); @@ -241,7 +240,7 @@ void AccountReconcilor::GoogleSignedOut(const std::string& account_id, } void AccountReconcilor::PerformMergeAction(const std::string& account_id) { - if (!switches::IsEnableAccountConsistency()) { + if (!switches::IsAccountConsistencyMirrorEnabled()) { MarkAccountAsAddedToCookie(account_id); return; } @@ -250,7 +249,7 @@ void AccountReconcilor::PerformMergeAction(const std::string& account_id) { } void AccountReconcilor::PerformLogoutAllAccountsAction() { - if (!switches::IsEnableAccountConsistency()) + if (!switches::IsAccountConsistencyMirrorEnabled()) return; VLOG(1) << "AccountReconcilor::PerformLogoutAllAccountsAction"; cookie_manager_service_->LogOutAllAccounts(kSource); diff --git a/chromium/components/signin/core/browser/account_reconcilor.h b/chromium/components/signin/core/browser/account_reconcilor.h index 6217588d974..285e6f51cf1 100644 --- a/chromium/components/signin/core/browser/account_reconcilor.h +++ b/chromium/components/signin/core/browser/account_reconcilor.h @@ -151,8 +151,7 @@ class AccountReconcilor : public KeyedService, // Overriden from SigninManagerBase::Observer. void GoogleSigninSucceeded(const std::string& account_id, - const std::string& username, - const std::string& password) override; + const std::string& username) override; void GoogleSignedOut(const std::string& account_id, const std::string& username) override; diff --git a/chromium/components/signin/core/browser/account_tracker_service.cc b/chromium/components/signin/core/browser/account_tracker_service.cc index 129b124288c..dc4dba0b394 100644 --- a/chromium/components/signin/core/browser/account_tracker_service.cc +++ b/chromium/components/signin/core/browser/account_tracker_service.cc @@ -60,6 +60,7 @@ const char AccountTrackerService::kNoPictureURLFound[] = "NO_PICTURE_URL"; AccountTrackerService::AccountTrackerService() : signin_client_(nullptr) {} AccountTrackerService::~AccountTrackerService() { + DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); } // static diff --git a/chromium/components/signin/core/browser/account_tracker_service.h b/chromium/components/signin/core/browser/account_tracker_service.h index b92e0a9515d..cc4035c4db4 100644 --- a/chromium/components/signin/core/browser/account_tracker_service.h +++ b/chromium/components/signin/core/browser/account_tracker_service.h @@ -13,13 +13,12 @@ #include "base/macros.h" #include "base/memory/ref_counted.h" #include "base/observer_list.h" -#include "base/threading/non_thread_safe.h" +#include "base/sequence_checker.h" #include "base/timer/timer.h" #include "components/keyed_service/core/keyed_service.h" #include "components/signin/core/browser/account_info.h" #include "google_apis/gaia/gaia_auth_util.h" - class PrefService; class SigninClient; @@ -33,8 +32,7 @@ class PrefRegistrySyncable; // AccountTrackerService is a KeyedService that retrieves and caches GAIA // information about Google Accounts. -class AccountTrackerService : public KeyedService, - public base::NonThreadSafe { +class AccountTrackerService : public KeyedService { public: // Name of the preference property that persists the account information // tracked by this service. @@ -157,6 +155,8 @@ class AccountTrackerService : public KeyedService, std::map<std::string, AccountState> accounts_; base::ObserverList<Observer> observer_list_; + SEQUENCE_CHECKER(sequence_checker_); + DISALLOW_COPY_AND_ASSIGN(AccountTrackerService); }; diff --git a/chromium/components/signin/core/browser/android/BUILD.gn b/chromium/components/signin/core/browser/android/BUILD.gn index f9f482b6a91..d7d0c958299 100644 --- a/chromium/components/signin/core/browser/android/BUILD.gn +++ b/chromium/components/signin/core/browser/android/BUILD.gn @@ -21,10 +21,13 @@ android_library("java") { java_files = [ "java/src/org/chromium/components/signin/AccountManagerDelegate.java", + "java/src/org/chromium/components/signin/AccountManagerFacade.java", "java/src/org/chromium/components/signin/AccountManagerHelper.java", + "java/src/org/chromium/components/signin/AccountsChangeObserver.java", "java/src/org/chromium/components/signin/AuthException.java", "java/src/org/chromium/components/signin/ChildAccountInfoFetcher.java", "java/src/org/chromium/components/signin/ChromeSigninController.java", + "java/src/org/chromium/components/signin/AccountManagerDelegateException.java", "java/src/org/chromium/components/signin/SystemAccountManagerDelegate.java", ] } @@ -39,7 +42,7 @@ android_library("javatests") { "//third_party/android_support_test_runner:runner_java", ] - java_files = [ "javatests/src/org/chromium/components/signin/test/AccountManagerHelperTest.java" ] + java_files = [ "javatests/src/org/chromium/components/signin/test/AccountManagerFacadeTest.java" ] } android_library("signin_java_test_support") { @@ -50,6 +53,7 @@ android_library("signin_java_test_support") { "//base:base_java_test_support", "//third_party/android_tools:android_support_annotations_java", "//third_party/jsr-305:jsr_305_javalib", + "//third_party/junit", ] java_files = [ diff --git a/chromium/components/signin/core/browser/child_account_info_fetcher_android.cc b/chromium/components/signin/core/browser/child_account_info_fetcher_android.cc index 34446dad77e..2fbdd2a0076 100644 --- a/chromium/components/signin/core/browser/child_account_info_fetcher_android.cc +++ b/chromium/components/signin/core/browser/child_account_info_fetcher_android.cc @@ -50,11 +50,6 @@ ChildAccountInfoFetcherAndroid::~ChildAccountInfoFetcherAndroid() { j_child_account_info_fetcher_.obj()); } -// static -bool ChildAccountInfoFetcherAndroid::Register(JNIEnv* env) { - return RegisterNativesImpl(env); -} - void SetIsChildAccount(JNIEnv* env, const JavaParamRef<jclass>& caller, jlong native_service, diff --git a/chromium/components/signin/core/browser/child_account_info_fetcher_android.h b/chromium/components/signin/core/browser/child_account_info_fetcher_android.h index 05f30a177fc..aee7ed9a473 100644 --- a/chromium/components/signin/core/browser/child_account_info_fetcher_android.h +++ b/chromium/components/signin/core/browser/child_account_info_fetcher_android.h @@ -22,9 +22,6 @@ class ChildAccountInfoFetcherAndroid : public ChildAccountInfoFetcher { static void InitializeForTests(); - // Register JNI methods. - static bool Register(JNIEnv* env); - private: ChildAccountInfoFetcherAndroid(AccountFetcherService* service, const std::string& account_id, diff --git a/chromium/components/signin/core/browser/chrome_connected_header_helper.cc b/chromium/components/signin/core/browser/chrome_connected_header_helper.cc new file mode 100644 index 00000000000..12486b67317 --- /dev/null +++ b/chromium/components/signin/core/browser/chrome_connected_header_helper.cc @@ -0,0 +1,171 @@ +// Copyright 2017 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "components/signin/core/browser/chrome_connected_header_helper.h" + +#include <vector> + +#include "base/logging.h" +#include "base/strings/string_number_conversions.h" +#include "base/strings/string_util.h" +#include "base/strings/stringprintf.h" +#include "components/google/core/browser/google_util.h" +#include "components/signin/core/common/profile_management_switches.h" +#include "google_apis/gaia/gaia_auth_util.h" +#include "net/base/registry_controlled_domains/registry_controlled_domain.h" +#include "url/gurl.h" + +namespace signin { + +namespace { + +const char kContinueUrlAttrName[] = "continue_url"; +const char kEmailAttrName[] = "email"; +const char kEnableAccountConsistencyAttrName[] = "enable_account_consistency"; +const char kGaiaIdAttrName[] = "id"; +const char kIsSameTabAttrName[] = "is_same_tab"; +const char kIsSamlAttrName[] = "is_saml"; +const char kProfileModeAttrName[] = "mode"; +const char kServiceTypeAttrName[] = "action"; + +// Determines the service type that has been passed from Gaia in the header. +GAIAServiceType GetGAIAServiceTypeFromHeader(const std::string& header_value) { + if (header_value == "SIGNOUT") + return GAIA_SERVICE_TYPE_SIGNOUT; + else if (header_value == "INCOGNITO") + return GAIA_SERVICE_TYPE_INCOGNITO; + else if (header_value == "ADDSESSION") + return GAIA_SERVICE_TYPE_ADDSESSION; + else if (header_value == "REAUTH") + return GAIA_SERVICE_TYPE_REAUTH; + else if (header_value == "SIGNUP") + return GAIA_SERVICE_TYPE_SIGNUP; + else if (header_value == "DEFAULT") + return GAIA_SERVICE_TYPE_DEFAULT; + else + return GAIA_SERVICE_TYPE_NONE; +} + +} // namespace + +// static +std::string ChromeConnectedHeaderHelper::BuildRequestCookieIfPossible( + const GURL& url, + const std::string& account_id, + const content_settings::CookieSettings* cookie_settings, + int profile_mode_mask) { + ChromeConnectedHeaderHelper chrome_connected_helper; + if (!chrome_connected_helper.ShouldBuildRequestHeader(url, cookie_settings)) + return ""; + return chrome_connected_helper.BuildRequestHeader( + false /* is_header_request */, url, account_id, profile_mode_mask); +} + +// static +ManageAccountsParams ChromeConnectedHeaderHelper::BuildManageAccountsParams( + const std::string& header_value) { + DCHECK(!header_value.empty()); + ManageAccountsParams params; + ResponseHeaderDictionary header_dictionary = + ParseAccountConsistencyResponseHeader(header_value); + ResponseHeaderDictionary::const_iterator it = header_dictionary.begin(); + for (; it != header_dictionary.end(); ++it) { + const std::string key_name(it->first); + const std::string value(it->second); + if (key_name == kServiceTypeAttrName) { + params.service_type = GetGAIAServiceTypeFromHeader(value); + } else if (key_name == kEmailAttrName) { + params.email = value; + } else if (key_name == kIsSamlAttrName) { + params.is_saml = value == "true"; + } else if (key_name == kContinueUrlAttrName) { + params.continue_url = value; + } else if (key_name == kIsSameTabAttrName) { + params.is_same_tab = value == "true"; + } else { + DLOG(WARNING) << "Unexpected Gaia header attribute '" << key_name << "'."; + } + } + return params; +} + +bool ChromeConnectedHeaderHelper::IsUrlEligibleToIncludeGaiaId( + const GURL& url, + bool is_header_request) { + if (is_header_request) { + // Gaia ID is only necessary for Drive. Don't set it otherwise. + return IsDriveOrigin(url.GetOrigin()); + } + + // Cookie requests don't have the granularity to only include the Gaia ID for + // Drive origin. Set it on all google.com instead. + if (!url.SchemeIsCryptographic()) + return false; + + const std::string kGoogleDomain = "google.com"; + std::string domain = net::registry_controlled_domains::GetDomainAndRegistry( + url, net::registry_controlled_domains::EXCLUDE_PRIVATE_REGISTRIES); + return domain == kGoogleDomain; +} + +bool ChromeConnectedHeaderHelper::IsDriveOrigin(const GURL& url) { + if (!url.SchemeIsCryptographic()) + return false; + + const GURL kGoogleDriveURL("https://drive.google.com"); + const GURL kGoogleDocsURL("https://docs.google.com"); + return url == kGoogleDriveURL || url == kGoogleDocsURL; +} + +bool ChromeConnectedHeaderHelper::IsUrlEligibleForRequestHeader( + const GURL& url) { + // Only set the header for Drive and Gaia always, and other Google properties + // if account consistency is enabled. Vasquette, which is integrated with most + // Google properties, needs the header to redirect certain user actions to + // Chrome native UI. Drive and Gaia need the header to tell if the current + // user is connected. + + // Consider the account ID sensitive and limit it to secure domains. + if (!url.SchemeIsCryptographic()) + return false; + + GURL origin(url.GetOrigin()); + bool is_enable_account_consistency = + switches::IsAccountConsistencyMirrorEnabled(); + bool is_google_url = is_enable_account_consistency && + (google_util::IsGoogleDomainUrl( + url, google_util::ALLOW_SUBDOMAIN, + google_util::DISALLOW_NON_STANDARD_PORTS) || + google_util::IsYoutubeDomainUrl( + url, google_util::ALLOW_SUBDOMAIN, + google_util::DISALLOW_NON_STANDARD_PORTS)); + return is_google_url || IsDriveOrigin(origin) || + gaia::IsGaiaSignonRealm(origin); +} + +std::string ChromeConnectedHeaderHelper::BuildRequestHeader( + bool is_header_request, + const GURL& url, + const std::string& account_id, + int profile_mode_mask) { + if (account_id.empty()) + return std::string(); + + std::vector<std::string> parts; + if (IsUrlEligibleToIncludeGaiaId(url, is_header_request)) { + // Only set the Gaia ID on domains that actually requires it. + parts.push_back( + base::StringPrintf("%s=%s", kGaiaIdAttrName, account_id.c_str())); + } + parts.push_back( + base::StringPrintf("%s=%s", kProfileModeAttrName, + base::IntToString(profile_mode_mask).c_str())); + parts.push_back(base::StringPrintf( + "%s=%s", kEnableAccountConsistencyAttrName, + switches::IsAccountConsistencyMirrorEnabled() ? "true" : "false")); + + return base::JoinString(parts, is_header_request ? "," : ":"); +} + +} // namespace signin diff --git a/chromium/components/signin/core/browser/chrome_connected_header_helper.h b/chromium/components/signin/core/browser/chrome_connected_header_helper.h new file mode 100644 index 00000000000..72ea404e3e0 --- /dev/null +++ b/chromium/components/signin/core/browser/chrome_connected_header_helper.h @@ -0,0 +1,55 @@ +// Copyright 2017 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef COMPONENTS_SIGNIN_CORE_BROWSER_CHROME_CONNECTED_HEADER_HELPER_H_ +#define COMPONENTS_SIGNIN_CORE_BROWSER_CHROME_CONNECTED_HEADER_HELPER_H_ + +#include <string> + +#include "components/signin/core/browser/signin_header_helper.h" + +class GURL; + +namespace signin { + +// SigninHeaderHelper implementation managing the "X-Chrome-Connected" header. +class ChromeConnectedHeaderHelper : public SigninHeaderHelper { + public: + ChromeConnectedHeaderHelper() {} + ~ChromeConnectedHeaderHelper() override {} + + // Returns the Chrome-Connected cookie, or an empty string if it should not be + // added to the request to |url|. + static std::string BuildRequestCookieIfPossible( + const GURL& url, + const std::string& account_id, + const content_settings::CookieSettings* cookie_settings, + int profile_mode_mask); + + // Returns the parameters contained in the X-Chrome-Manage-Accounts response + // header. + static ManageAccountsParams BuildManageAccountsParams( + const std::string& header_value); + + // Returns the value for the Chrome-Connected request header. May return the + // empty string, in this case the header must not be added. + std::string BuildRequestHeader(bool is_header_request, + const GURL& url, + const std::string& account_id, + int profile_mode_mask); + + private: + // Returns whether the URL is eligible for the Gaia ID parameter. + bool IsUrlEligibleToIncludeGaiaId(const GURL& url, bool is_header_request); + + // Returns whether the URL has a Google Drive origin. + bool IsDriveOrigin(const GURL& url); + + // SigninHeaderHelper implementation: + bool IsUrlEligibleForRequestHeader(const GURL& url) override; +}; + +} // namespace signin + +#endif // COMPONENTS_SIGNIN_CORE_BROWSER_CHROME_CONNECTED_HEADER_HELPER_H_ diff --git a/chromium/components/signin/core/browser/dice_header_helper.cc b/chromium/components/signin/core/browser/dice_header_helper.cc new file mode 100644 index 00000000000..4d8aade04f2 --- /dev/null +++ b/chromium/components/signin/core/browser/dice_header_helper.cc @@ -0,0 +1,147 @@ +// Copyright 2017 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "components/signin/core/browser/dice_header_helper.h" + +#include <vector> + +#include "base/strings/string_number_conversions.h" +#include "base/strings/string_util.h" +#include "components/signin/core/common/profile_management_switches.h" +#include "google_apis/gaia/gaia_auth_util.h" +#include "google_apis/gaia/gaia_urls.h" + +namespace signin { + +namespace { + +const char kSigninActionAttrName[] = "action"; +const char kSigninAuthUserAttrName[] = "authuser"; +const char kSigninAuthorizationCodeAttrName[] = "authorization_code"; +const char kSigninEmailAttrName[] = "email"; +const char kSigninIdAttrName[] = "id"; +const char kSignoutEmailAttrName[] = "email"; +const char kSignoutSessionIndexAttrName[] = "sessionindex"; +const char kSignoutObfuscatedIDAttrName[] = "obfuscatedid"; + +// Determines the Dice action that has been passed from Gaia in the header. +DiceAction GetDiceActionFromHeader(const std::string& value) { + if (value == "SIGNIN") + return DiceAction::SIGNIN; + else if (value == "SIGNOUT") + return DiceAction::SIGNOUT; + else + return DiceAction::NONE; +} + +} // namespace + +// static +DiceResponseParams DiceHeaderHelper::BuildDiceSigninResponseParams( + const std::string& header_value) { + DCHECK(!header_value.empty()); + DiceResponseParams params; + DiceResponseParams::SigninInfo& info = params.signin_info; + ResponseHeaderDictionary header_dictionary = + ParseAccountConsistencyResponseHeader(header_value); + ResponseHeaderDictionary::const_iterator it = header_dictionary.begin(); + for (; it != header_dictionary.end(); ++it) { + const std::string key_name(it->first); + const std::string value(it->second); + if (key_name == kSigninActionAttrName) { + params.user_intention = GetDiceActionFromHeader(value); + } else if (key_name == kSigninIdAttrName) { + info.gaia_id = value; + } else if (key_name == kSigninEmailAttrName) { + info.email = value; + } else if (key_name == kSigninAuthUserAttrName) { + bool parse_success = base::StringToInt(value, &info.session_index); + if (!parse_success) + info.session_index = -1; + } else if (key_name == kSigninAuthorizationCodeAttrName) { + info.authorization_code = value; + } else { + DLOG(WARNING) << "Unexpected Gaia header attribute '" << key_name << "'."; + } + } + + if (params.user_intention != DiceAction::SIGNIN) { + DLOG(WARNING) + << "Only SIGNIN is supported through X-Chrome-ID-Consistency-Response :" + << header_value; + params.user_intention = DiceAction::NONE; + } + + if (info.gaia_id.empty() || info.email.empty() || info.session_index == -1 || + info.authorization_code.empty()) { + DLOG(WARNING) << "Missing header parameters for Dice SIGNIN: " + << header_value; + params.user_intention = DiceAction::NONE; + } + + return params; +} + +// static +DiceResponseParams DiceHeaderHelper::BuildDiceSignoutResponseParams( + const std::string& header_value) { + // Google internal documentation of this header at: + // http://go/gaia-response-headers + DCHECK(!header_value.empty()); + DiceResponseParams params; + params.user_intention = DiceAction::SIGNOUT; + DiceResponseParams::SignoutInfo& info = params.signout_info; + ResponseHeaderDictionary header_dictionary = + ParseAccountConsistencyResponseHeader(header_value); + ResponseHeaderDictionary::const_iterator it = header_dictionary.begin(); + for (; it != header_dictionary.end(); ++it) { + const std::string key_name(it->first); + const std::string value(it->second); + if (key_name == kSignoutObfuscatedIDAttrName) { + info.gaia_id.push_back(value); + // The Gaia ID is wrapped in quotes. + base::TrimString(value, "\"", &info.gaia_id.back()); + } else if (key_name == kSignoutEmailAttrName) { + // The email is wrapped in quotes. + info.email.push_back(value); + base::TrimString(value, "\"", &info.email.back()); + } else if (key_name == kSignoutSessionIndexAttrName) { + int session_index = -1; + bool parse_success = base::StringToInt(value, &session_index); + if (parse_success) + info.session_index.push_back(session_index); + } else { + DLOG(WARNING) << "Unexpected Gaia header attribute '" << key_name << "'."; + } + } + + if ((info.gaia_id.size() != info.email.size()) || + (info.gaia_id.size() != info.session_index.size())) { + DLOG(WARNING) << "Invalid parameter count for Dice SIGNOUT header: " + << header_value; + params.user_intention = DiceAction::NONE; + } + + return params; +} + +bool DiceHeaderHelper::IsUrlEligibleForRequestHeader(const GURL& url) { + if (switches::GetAccountConsistencyMethod() != + switches::AccountConsistencyMethod::kDice) { + return false; + } + return gaia::IsGaiaSignonRealm(url.GetOrigin()); +} + +std::string DiceHeaderHelper::BuildRequestHeader(const std::string& account_id, + bool sync_enabled) { + std::vector<std::string> parts; + parts.push_back("client_id=" + + GaiaUrls::GetInstance()->oauth2_chrome_client_id()); + if (sync_enabled) + parts.push_back("sync_account_id=" + account_id); + return base::JoinString(parts, ","); +} + +} // namespace signin diff --git a/chromium/components/signin/core/browser/dice_header_helper.h b/chromium/components/signin/core/browser/dice_header_helper.h new file mode 100644 index 00000000000..d83fa037693 --- /dev/null +++ b/chromium/components/signin/core/browser/dice_header_helper.h @@ -0,0 +1,44 @@ +// Copyright 2017 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef COMPONENTS_SIGNIN_CORE_BROWSER_DICE_HEADER_HELPER_H_ +#define COMPONENTS_SIGNIN_CORE_BROWSER_DICE_HEADER_HELPER_H_ + +#include <string> + +#include "components/signin/core/browser/signin_header_helper.h" + +class GURL; + +namespace signin { + +// SigninHeaderHelper implementation managing the Dice header. +class DiceHeaderHelper : public SigninHeaderHelper { + public: + DiceHeaderHelper() {} + ~DiceHeaderHelper() override {} + + // Returns the parameters contained in the X-Chrome-ID-Consistency-Response + // response header. + static DiceResponseParams BuildDiceSigninResponseParams( + const std::string& header_value); + + // Returns the parameters contained in the Google-Accounts-SignOut response + // header. + static DiceResponseParams BuildDiceSignoutResponseParams( + const std::string& header_value); + + // Returns the header value for Dice requests. Returns the empty string when + // the header must not be added. + std::string BuildRequestHeader(const std::string& account_id, + bool sync_enabled); + + private: + // SigninHeaderHelper implementation: + bool IsUrlEligibleForRequestHeader(const GURL& url) override; +}; + +} // namespace signin + +#endif // COMPONENTS_SIGNIN_CORE_BROWSER_DICE_HEADER_HELPER_H_ diff --git a/chromium/components/signin/core/browser/fake_signin_manager.cc b/chromium/components/signin/core/browser/fake_signin_manager.cc index 32caba99d7b..104d8ea429c 100644 --- a/chromium/components/signin/core/browser/fake_signin_manager.cc +++ b/chromium/components/signin/core/browser/fake_signin_manager.cc @@ -31,7 +31,8 @@ FakeSigninManager::FakeSigninManager( : SigninManager(client, token_service, account_tracker_service, - cookie_manager_service) {} + cookie_manager_service), + token_service_(token_service) {} FakeSigninManager::~FakeSigninManager() {} @@ -57,8 +58,9 @@ void FakeSigninManager::CompletePendingSignin() { SetAuthenticatedAccountId(GetAccountIdForAuthInProgress()); set_auth_in_progress(std::string()); for (auto& observer : observer_list_) { - observer.GoogleSigninSucceeded(authenticated_account_id_, username_, - password_); + observer.GoogleSigninSucceeded(authenticated_account_id_, username_); + observer.GoogleSigninSucceededWithPassword(authenticated_account_id_, + username_, password_); } } @@ -91,6 +93,8 @@ void FakeSigninManager::SignOut( const std::string account_id = GetAuthenticatedAccountId(); const std::string username = GetAuthenticatedAccountInfo().email; authenticated_account_id_.clear(); + if (token_service_) + token_service_->RevokeAllCredentials(); for (auto& observer : observer_list_) observer.GoogleSignedOut(account_id, username); diff --git a/chromium/components/signin/core/browser/fake_signin_manager.h b/chromium/components/signin/core/browser/fake_signin_manager.h index 5ba63b81e53..b3943e0f256 100644 --- a/chromium/components/signin/core/browser/fake_signin_manager.h +++ b/chromium/components/signin/core/browser/fake_signin_manager.h @@ -13,9 +13,7 @@ #include "components/signin/core/browser/signin_manager.h" #include "components/signin/core/browser/signin_metrics.h" -// SigninManager to use for testing. Tests should use the type -// SigninManagerForTesting to ensure that the right type for their platform is -// used. +// SigninManager to use for testing. class FakeSigninManagerBase : public SigninManagerBase { public: @@ -44,7 +42,7 @@ class FakeSigninManager : public SigninManager { void set_password(const std::string& password) { password_ = password; } - void SignIn(const std::string& account_id, + void SignIn(const std::string& gaia_id, const std::string& username, const std::string& password); @@ -66,6 +64,8 @@ class FakeSigninManager : public SigninManager { // Username specified in StartSignInWithRefreshToken() call. std::string username_; + + ProfileOAuth2TokenService* token_service_; }; #endif // !defined (OS_CHROMEOS) diff --git a/chromium/components/signin/core/browser/profile_identity_provider.cc b/chromium/components/signin/core/browser/profile_identity_provider.cc index 3be796e2d64..a537d4b718a 100644 --- a/chromium/components/signin/core/browser/profile_identity_provider.cc +++ b/chromium/components/signin/core/browser/profile_identity_provider.cc @@ -42,8 +42,7 @@ bool ProfileIdentityProvider::RequestLogin() { void ProfileIdentityProvider::GoogleSigninSucceeded( const std::string& account_id, - const std::string& username, - const std::string& password) { + const std::string& username) { FireOnActiveAccountLogin(); } diff --git a/chromium/components/signin/core/browser/profile_identity_provider.h b/chromium/components/signin/core/browser/profile_identity_provider.h index ca3e1a590a3..eef7e346787 100644 --- a/chromium/components/signin/core/browser/profile_identity_provider.h +++ b/chromium/components/signin/core/browser/profile_identity_provider.h @@ -32,8 +32,7 @@ class ProfileIdentityProvider : public IdentityProvider, // SigninManagerBase::Observer: void GoogleSigninSucceeded(const std::string& account_id, - const std::string& username, - const std::string& password) override; + const std::string& username) override; void GoogleSignedOut(const std::string& account_id, const std::string& username) override; diff --git a/chromium/components/signin/core/browser/profile_oauth2_token_service.cc b/chromium/components/signin/core/browser/profile_oauth2_token_service.cc index 7e8eb2a22c9..8cf2fd90b28 100644 --- a/chromium/components/signin/core/browser/profile_oauth2_token_service.cc +++ b/chromium/components/signin/core/browser/profile_oauth2_token_service.cc @@ -6,7 +6,7 @@ ProfileOAuth2TokenService::ProfileOAuth2TokenService( std::unique_ptr<OAuth2TokenServiceDelegate> delegate) - : OAuth2TokenService(std::move(delegate)) { + : OAuth2TokenService(std::move(delegate)), all_credentials_loaded_(false) { AddObserver(this); } @@ -24,6 +24,10 @@ void ProfileOAuth2TokenService::LoadCredentials( GetDelegate()->LoadCredentials(primary_account_id); } +bool ProfileOAuth2TokenService::AreAllCredentialsLoaded() { + return all_credentials_loaded_; +} + void ProfileOAuth2TokenService::UpdateCredentials( const std::string& account_id, const std::string& refresh_token) { @@ -50,3 +54,7 @@ void ProfileOAuth2TokenService::OnRefreshTokenRevoked( CancelRequestsForAccount(account_id); ClearCacheForAccount(account_id); } + +void ProfileOAuth2TokenService::OnRefreshTokensLoaded() { + all_credentials_loaded_ = true; +} diff --git a/chromium/components/signin/core/browser/profile_oauth2_token_service.h b/chromium/components/signin/core/browser/profile_oauth2_token_service.h index fadf1417bd1..3372a924c99 100644 --- a/chromium/components/signin/core/browser/profile_oauth2_token_service.h +++ b/chromium/components/signin/core/browser/profile_oauth2_token_service.h @@ -42,13 +42,13 @@ class ProfileOAuth2TokenService : public OAuth2TokenService, // Loads credentials from a backing persistent store to make them available // after service is used between profile restarts. // - // Only call this method if there is at least one account connected to the - // profile, otherwise startup will cause unneeded work on the IO thread. The - // primary account is specified with the |primary_account_id| argument. If - // empty, no credentials will be loaded. For a regular profile, the primary - // account id comes from SigninManager. For a supervised user, the id comes - // from SupervisedUserService. - virtual void LoadCredentials(const std::string& primary_account_id); + // The primary account is specified with the |primary_account_id| argument. + // For a regular profile, the primary account id comes from SigninManager. + // For a supervised user, the id comes from SupervisedUserService. + void LoadCredentials(const std::string& primary_account_id); + + // Returns true iff all credentials have been loaded from disk. + bool AreAllCredentialsLoaded(); // Updates a |refresh_token| for an |account_id|. Credentials are persisted, // and available through |LoadCredentials| after service is restarted. @@ -64,6 +64,10 @@ class ProfileOAuth2TokenService : public OAuth2TokenService, private: void OnRefreshTokenAvailable(const std::string& account_id) override; void OnRefreshTokenRevoked(const std::string& account_id) override; + void OnRefreshTokensLoaded() override; + + // Whether all credentials have been loaded. + bool all_credentials_loaded_; DISALLOW_COPY_AND_ASSIGN(ProfileOAuth2TokenService); }; diff --git a/chromium/components/signin/core/browser/refresh_token_annotation_request.cc b/chromium/components/signin/core/browser/refresh_token_annotation_request.cc index 191dab8ebf4..15c43148f56 100644 --- a/chromium/components/signin/core/browser/refresh_token_annotation_request.cc +++ b/chromium/components/signin/core/browser/refresh_token_annotation_request.cc @@ -17,6 +17,7 @@ #include "google_apis/gaia/gaia_constants.h" #include "google_apis/gaia/gaia_urls.h" #include "net/base/escape.h" +#include "net/traffic_annotation/network_traffic_annotation.h" #include "net/url_request/url_request_context_getter.h" namespace { @@ -41,7 +42,7 @@ RefreshTokenAnnotationRequest::RefreshTokenAnnotationRequest( } RefreshTokenAnnotationRequest::~RefreshTokenAnnotationRequest() { - DCHECK(CalledOnValidThread()); + DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); } // static @@ -102,7 +103,7 @@ bool RefreshTokenAnnotationRequest::ShouldSendNow(PrefService* pref_service) { void RefreshTokenAnnotationRequest::RequestAccessToken( OAuth2TokenService* token_service, const std::string& account_id) { - DCHECK(CalledOnValidThread()); + DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); OAuth2TokenService::ScopeSet scopes; scopes.insert(GaiaConstants::kOAuth1LoginScope); access_token_request_ = token_service->StartRequest(account_id, scopes, this); @@ -112,7 +113,7 @@ void RefreshTokenAnnotationRequest::OnGetTokenSuccess( const OAuth2TokenService::Request* request, const std::string& access_token, const base::Time& expiration_time) { - DCHECK(CalledOnValidThread()); + DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); DVLOG(2) << "Got access token"; Start(request_context_getter_.get(), access_token); } @@ -120,7 +121,7 @@ void RefreshTokenAnnotationRequest::OnGetTokenSuccess( void RefreshTokenAnnotationRequest::OnGetTokenFailure( const OAuth2TokenService::Request* request, const GoogleServiceAuthError& error) { - DCHECK(CalledOnValidThread()); + DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); DVLOG(2) << "Failed to get access token"; RecordRequestStatusHistogram(false); base::ThreadTaskRunnerHandle::Get()->PostTask(FROM_HERE, request_callback_); @@ -156,7 +157,7 @@ std::string RefreshTokenAnnotationRequest::CreateApiCallBody() { void RefreshTokenAnnotationRequest::ProcessApiCallSuccess( const net::URLFetcher* source) { - DCHECK(CalledOnValidThread()); + DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); DVLOG(2) << "Request succeeded"; RecordRequestStatusHistogram(true); base::ThreadTaskRunnerHandle::Get()->PostTask(FROM_HERE, request_callback_); @@ -165,9 +166,40 @@ void RefreshTokenAnnotationRequest::ProcessApiCallSuccess( void RefreshTokenAnnotationRequest::ProcessApiCallFailure( const net::URLFetcher* source) { - DCHECK(CalledOnValidThread()); + DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); DVLOG(2) << "Request failed"; RecordRequestStatusHistogram(false); base::ThreadTaskRunnerHandle::Get()->PostTask(FROM_HERE, request_callback_); request_callback_.Reset(); } + +net::PartialNetworkTrafficAnnotationTag +RefreshTokenAnnotationRequest::GetNetworkTrafficAnnotationTag() { + return net::DefinePartialNetworkTrafficAnnotation( + "refresh_token_annotation_request", "oauth2_api_call_flow", R"( + semantics { + sender: "Account Fetcher Service" + description: + "Sends request to /IssueToken endpoint with device_id to backfill " + "device info for refresh tokens issued pre-M38." + trigger: + "When refreshing account information in AccountFetcherService. On " + "chrome startup and at most once per day." + data: + "OAuth 2.0 access token, Chrome's client id and version number, and " + "a single signin scoped, randomly generated device id for Chrome " + "profile." + destination: GOOGLE_OWNED_SERVICE + } + policy { + setting: + "This feature cannot be disabled by settings, however the request is " + "made only for signed-in users." + chrome_policy { + SigninAllowed { + policy_options {mode: MANDATORY} + SigninAllowed: false + } + } + })"); +} diff --git a/chromium/components/signin/core/browser/refresh_token_annotation_request.h b/chromium/components/signin/core/browser/refresh_token_annotation_request.h index 483830bfea4..2e0868c43ca 100644 --- a/chromium/components/signin/core/browser/refresh_token_annotation_request.h +++ b/chromium/components/signin/core/browser/refresh_token_annotation_request.h @@ -10,7 +10,7 @@ #include "base/callback.h" #include "base/gtest_prod_util.h" #include "base/macros.h" -#include "base/threading/non_thread_safe.h" +#include "base/sequence_checker.h" #include "google_apis/gaia/oauth2_api_call_flow.h" #include "google_apis/gaia/oauth2_token_service.h" @@ -22,8 +22,7 @@ class SigninClient; // important to keep server QPS low therefore this request is sent on average // once per 10 days per profile. // This code shold be removed once majority of refresh tokens are updated. -class RefreshTokenAnnotationRequest : public base::NonThreadSafe, - public OAuth2TokenService::Consumer, +class RefreshTokenAnnotationRequest : public OAuth2TokenService::Consumer, public OAuth2ApiCallFlow { public: ~RefreshTokenAnnotationRequest() override; @@ -59,6 +58,8 @@ class RefreshTokenAnnotationRequest : public base::NonThreadSafe, std::string CreateApiCallBody() override; void ProcessApiCallSuccess(const net::URLFetcher* source) override; void ProcessApiCallFailure(const net::URLFetcher* source) override; + net::PartialNetworkTrafficAnnotationTag GetNetworkTrafficAnnotationTag() + override; private: FRIEND_TEST_ALL_PREFIXES(RefreshTokenAnnotationRequestTest, ShouldSendNow); @@ -84,6 +85,8 @@ class RefreshTokenAnnotationRequest : public base::NonThreadSafe, std::unique_ptr<OAuth2TokenService::Request> access_token_request_; + SEQUENCE_CHECKER(sequence_checker_); + DISALLOW_COPY_AND_ASSIGN(RefreshTokenAnnotationRequest); }; diff --git a/chromium/components/signin/core/browser/resources/signin_index.html b/chromium/components/signin/core/browser/resources/signin_index.html index 7965ffe6e38..513a934658d 100644 --- a/chromium/components/signin/core/browser/resources/signin_index.html +++ b/chromium/components/signin/core/browser/resources/signin_index.html @@ -1,5 +1,5 @@ <!doctype html> -<html i18n-values="dir:textdirection;lang:language"> +<html dir="$i18n{textdirection}" lang="$i18n{language}"> <head> <meta charset="utf-8"> <title>Signin Internals</title> diff --git a/chromium/components/signin/core/browser/signin_header_helper.cc b/chromium/components/signin/core/browser/signin_header_helper.cc index 668d25d4492..0a326c1f807 100644 --- a/chromium/components/signin/core/browser/signin_header_helper.cc +++ b/chromium/components/signin/core/browser/signin_header_helper.cc @@ -6,143 +6,26 @@ #include <stddef.h> +#include "base/logging.h" #include "base/macros.h" -#include "base/strings/string_number_conversions.h" #include "base/strings/string_split.h" -#include "base/strings/string_util.h" -#include "base/strings/stringprintf.h" -#include "build/build_config.h" #include "components/content_settings/core/browser/cookie_settings.h" #include "components/google/core/browser/google_util.h" +#include "components/signin/core/browser/chrome_connected_header_helper.h" #include "components/signin/core/common/profile_management_switches.h" #include "google_apis/gaia/gaia_auth_util.h" #include "google_apis/gaia/gaia_urls.h" #include "net/base/escape.h" -#include "net/base/registry_controlled_domains/registry_controlled_domain.h" -#include "net/http/http_response_headers.h" #include "net/url_request/url_request.h" -#include "url/gurl.h" -namespace { - -// Dictionary of fields in a mirror response header. -typedef std::map<std::string, std::string> MirrorResponseHeaderDictionary; - -const char kChromeManageAccountsHeader[] = "X-Chrome-Manage-Accounts"; -const char kContinueUrlAttrName[] = "continue_url"; -const char kEmailAttrName[] = "email"; -const char kEnableAccountConsistencyAttrName[] = "enable_account_consistency"; -const char kGaiaIdAttrName[] = "id"; -const char kProfileModeAttrName[] = "mode"; -const char kIsSameTabAttrName[] = "is_same_tab"; -const char kIsSamlAttrName[] = "is_saml"; -const char kServiceTypeAttrName[] = "action"; - -bool IsDriveOrigin(const GURL& url) { - if (!url.SchemeIsCryptographic()) - return false; - - const GURL kGoogleDriveURL("https://drive.google.com"); - const GURL kGoogleDocsURL("https://docs.google.com"); - return url == kGoogleDriveURL || url == kGoogleDocsURL; -} - -bool IsUrlEligibleToIncludeGaiaId(const GURL& url, bool is_header_request) { - if (is_header_request) { - // GAIA Id is only necessary for Drive. Don't set it otherwise. - return IsDriveOrigin(url.GetOrigin()); - } - - // Cookie requests don't have the granularity to only include the GAIA Id for - // Drive origin. Set it on all google.com instead. - if (!url.SchemeIsCryptographic()) - return false; - - const std::string kGoogleDomain = "google.com"; - std::string domain = net::registry_controlled_domains::GetDomainAndRegistry( - url, net::registry_controlled_domains::EXCLUDE_PRIVATE_REGISTRIES); - return domain == kGoogleDomain; -} - -// Determines the service type that has been passed from GAIA in the header. -signin::GAIAServiceType GetGAIAServiceTypeFromHeader( - const std::string& header_value) { - if (header_value == "SIGNOUT") - return signin::GAIA_SERVICE_TYPE_SIGNOUT; - else if (header_value == "INCOGNITO") - return signin::GAIA_SERVICE_TYPE_INCOGNITO; - else if (header_value == "ADDSESSION") - return signin::GAIA_SERVICE_TYPE_ADDSESSION; - else if (header_value == "REAUTH") - return signin::GAIA_SERVICE_TYPE_REAUTH; - else if (header_value == "SIGNUP") - return signin::GAIA_SERVICE_TYPE_SIGNUP; - else if (header_value == "DEFAULT") - return signin::GAIA_SERVICE_TYPE_DEFAULT; - else - return signin::GAIA_SERVICE_TYPE_NONE; -} - -// Parses the mirror response header. Its expected format is -// "key1=value1,key2=value2,...". -MirrorResponseHeaderDictionary ParseMirrorResponseHeader( - const std::string& header_value) { - MirrorResponseHeaderDictionary dictionary; - for (const base::StringPiece& field : - base::SplitStringPiece(header_value, ",", base::KEEP_WHITESPACE, - base::SPLIT_WANT_NONEMPTY)) { - size_t delim = field.find_first_of('='); - if (delim == std::string::npos) { - DLOG(WARNING) << "Unexpected GAIA header field '" << field << "'."; - continue; - } - dictionary[field.substr(0, delim).as_string()] = net::UnescapeURLComponent( - field.substr(delim + 1).as_string(), - net::UnescapeRule::PATH_SEPARATORS | - net::UnescapeRule::URL_SPECIAL_CHARS_EXCEPT_PATH_SEPARATORS); - } - return dictionary; -} - -std::string BuildMirrorRequestIfPossible( - bool is_header_request, - const GURL& url, - const std::string& account_id, - const content_settings::CookieSettings* cookie_settings, - int profile_mode_mask) { - if (account_id.empty()) - return std::string(); - - // If signin cookies are not allowed, don't add the header. - if (!signin::SettingsAllowSigninCookies(cookie_settings)) { - return std::string(); - } - - // Check if url is elligible for the header. - if (!signin::IsUrlEligibleForXChromeConnectedHeader(url)) - return std::string(); - - std::vector<std::string> parts; - if (IsUrlEligibleToIncludeGaiaId(url, is_header_request)) { - // Only set the GAIA Id on domains that actually requires it. - parts.push_back( - base::StringPrintf("%s=%s", kGaiaIdAttrName, account_id.c_str())); - } - parts.push_back( - base::StringPrintf("%s=%s", kProfileModeAttrName, - base::IntToString(profile_mode_mask).c_str())); - parts.push_back(base::StringPrintf( - "%s=%s", kEnableAccountConsistencyAttrName, - switches::IsEnableAccountConsistency() ? "true" : "false")); - - return base::JoinString(parts, is_header_request ? "," : ":"); -} - -} // namespace +#if BUILDFLAG(ENABLE_DICE_SUPPORT) +#include "components/signin/core/browser/dice_header_helper.h" +#endif namespace signin { extern const char kChromeConnectedHeader[] = "X-Chrome-Connected"; +extern const char kDiceRequestHeader[] = "X-Chrome-ID-Consistency-Request"; ManageAccountsParams::ManageAccountsParams() : service_type(GAIA_SERVICE_TYPE_NONE), @@ -150,15 +33,22 @@ ManageAccountsParams::ManageAccountsParams() is_saml(false), continue_url(""), is_same_tab(false) { -#if !defined(OS_IOS) - child_id = 0; - route_id = 0; -#endif // !defined(OS_IOS) } -ManageAccountsParams::ManageAccountsParams(const ManageAccountsParams& other) = +ManageAccountsParams::ManageAccountsParams(const ManageAccountsParams&) = default; +// Trivial constructors and destructors. +DiceResponseParams::DiceResponseParams() : user_intention(DiceAction::NONE) {} +DiceResponseParams::~DiceResponseParams() {} +DiceResponseParams::DiceResponseParams(const DiceResponseParams&) = default; +DiceResponseParams::SigninInfo::SigninInfo() {} +DiceResponseParams::SigninInfo::~SigninInfo() {} +DiceResponseParams::SigninInfo::SigninInfo(const SigninInfo&) = default; +DiceResponseParams::SignoutInfo::SignoutInfo() {} +DiceResponseParams::SignoutInfo::~SignoutInfo() {} +DiceResponseParams::SignoutInfo::SignoutInfo(const SignoutInfo&) = default; + bool SettingsAllowSigninCookies( const content_settings::CookieSettings* cookie_settings) { GURL gaia_url = GaiaUrls::GetInstance()->gaia_url(); @@ -173,110 +63,113 @@ std::string BuildMirrorRequestCookieIfPossible( const std::string& account_id, const content_settings::CookieSettings* cookie_settings, int profile_mode_mask) { - return BuildMirrorRequestIfPossible(false /* is_header_request */, url, - account_id, cookie_settings, - profile_mode_mask); + return signin::ChromeConnectedHeaderHelper::BuildRequestCookieIfPossible( + url, account_id, cookie_settings, profile_mode_mask); } -bool AppendOrRemoveMirrorRequestHeaderIfPossible( +bool SigninHeaderHelper::AppendOrRemoveRequestHeader( net::URLRequest* request, const GURL& redirect_url, - const std::string& account_id, - const content_settings::CookieSettings* cookie_settings, - int profile_mode_mask) { - const GURL& url = redirect_url.is_empty() ? request->url() : redirect_url; - std::string header_value = BuildMirrorRequestIfPossible( - true /* is_header_request */, url, account_id, cookie_settings, - profile_mode_mask); + const char* header_name, + const std::string& header_value) { if (header_value.empty()) { - // If the request is being redirected, and it has the x-chrome-connected + // If the request is being redirected, and it has the account consistency // header, and current url is a Google URL, and the redirected one is not, // remove the header. if (!redirect_url.is_empty() && - request->extra_request_headers().HasHeader( - signin::kChromeConnectedHeader) && - signin::IsUrlEligibleForXChromeConnectedHeader(request->url()) && - !signin::IsUrlEligibleForXChromeConnectedHeader(redirect_url)) { - request->RemoveRequestHeaderByName(signin::kChromeConnectedHeader); + request->extra_request_headers().HasHeader(header_name) && + IsUrlEligibleForRequestHeader(request->url()) && + !IsUrlEligibleForRequestHeader(redirect_url)) { + request->RemoveRequestHeaderByName(header_name); } return false; } - request->SetExtraRequestHeaderByName(kChromeConnectedHeader, header_value, - false); + request->SetExtraRequestHeaderByName(header_name, header_value, false); return true; } -ManageAccountsParams BuildManageAccountsParams( +// static +SigninHeaderHelper::ResponseHeaderDictionary +SigninHeaderHelper::ParseAccountConsistencyResponseHeader( const std::string& header_value) { - signin::ManageAccountsParams params; - MirrorResponseHeaderDictionary header_dictionary = - ParseMirrorResponseHeader(header_value); - MirrorResponseHeaderDictionary::const_iterator it = header_dictionary.begin(); - for (; it != header_dictionary.end(); ++it) { - const std::string key_name(it->first); - if (key_name == kServiceTypeAttrName) { - params.service_type = - GetGAIAServiceTypeFromHeader(header_dictionary[kServiceTypeAttrName]); - } else if (key_name == kEmailAttrName) { - params.email = header_dictionary[kEmailAttrName]; - } else if (key_name == kIsSamlAttrName) { - params.is_saml = header_dictionary[kIsSamlAttrName] == "true"; - } else if (key_name == kContinueUrlAttrName) { - params.continue_url = header_dictionary[kContinueUrlAttrName]; - } else if (key_name == kIsSameTabAttrName) { - params.is_same_tab = header_dictionary[kIsSameTabAttrName] == "true"; - } else { - DLOG(WARNING) << "Unexpected GAIA header attribute '" << key_name << "'."; + ResponseHeaderDictionary dictionary; + for (const base::StringPiece& field : + base::SplitStringPiece(header_value, ",", base::TRIM_WHITESPACE, + base::SPLIT_WANT_NONEMPTY)) { + size_t delim = field.find_first_of('='); + if (delim == std::string::npos) { + DLOG(WARNING) << "Unexpected Gaia header field '" << field << "'."; + continue; } + dictionary.insert( + {field.substr(0, delim).as_string(), + net::UnescapeURLComponent( + field.substr(delim + 1).as_string(), + net::UnescapeRule::PATH_SEPARATORS | + net::UnescapeRule::URL_SPECIAL_CHARS_EXCEPT_PATH_SEPARATORS)}); } - return params; + return dictionary; } -ManageAccountsParams BuildManageAccountsParamsIfExists(net::URLRequest* request, - bool is_off_the_record) { - ManageAccountsParams empty_params; - empty_params.service_type = GAIA_SERVICE_TYPE_NONE; - if (!gaia::IsGaiaSignonRealm(request->url().GetOrigin())) - return empty_params; +bool SigninHeaderHelper::ShouldBuildRequestHeader( + const GURL& url, + const content_settings::CookieSettings* cookie_settings) { + // If signin cookies are not allowed, don't add the header. + if (!SettingsAllowSigninCookies(cookie_settings)) + return false; - std::string header_value; - net::HttpResponseHeaders* response_headers = request->response_headers(); - if (!response_headers || - !response_headers->GetNormalizedHeader( - kChromeManageAccountsHeader, &header_value)) { - return empty_params; - } + // Check if url is eligible for the header. + if (!IsUrlEligibleForRequestHeader(url)) + return false; - DCHECK(switches::IsEnableAccountConsistency() && !is_off_the_record); - return BuildManageAccountsParams(header_value); + return true; } -// Checks if the url has the required properties to have an -// X-Chrome-Connected header. -bool IsUrlEligibleForXChromeConnectedHeader(const GURL& url) { - // Only set the header for Drive and Gaia always, and other Google properties - // if account consistency is enabled. - // Vasquette, which is integrated with most Google properties, needs the - // header to redirect certain user actions to Chrome native UI. Drive and Gaia - // need the header to tell if the current user is connected. The drive path is - // a temporary workaround until the more generic chrome.principals API is - // available. +void AppendOrRemoveAccountConsistentyRequestHeader( + net::URLRequest* request, + const GURL& redirect_url, + const std::string& account_id, + bool sync_enabled, + const content_settings::CookieSettings* cookie_settings, + int profile_mode_mask) { + const GURL& url = redirect_url.is_empty() ? request->url() : redirect_url; +#if BUILDFLAG(ENABLE_DICE_SUPPORT) + DiceHeaderHelper dice_helper; + std::string dice_header_value; + if (dice_helper.ShouldBuildRequestHeader(url, cookie_settings)) { + dice_header_value = + dice_helper.BuildRequestHeader(account_id, sync_enabled); + } + dice_helper.AppendOrRemoveRequestHeader( + request, redirect_url, kDiceRequestHeader, dice_header_value); +#endif + + ChromeConnectedHeaderHelper chrome_connected_helper; + std::string chrome_connected_header_value; + if (chrome_connected_helper.ShouldBuildRequestHeader(url, cookie_settings)) { + chrome_connected_header_value = chrome_connected_helper.BuildRequestHeader( + true /* is_header_request */, url, account_id, profile_mode_mask); + } + chrome_connected_helper.AppendOrRemoveRequestHeader( + request, redirect_url, kChromeConnectedHeader, + chrome_connected_header_value); +} - // Consider the account id sensitive and limit it to secure domains. - if (!url.SchemeIsCryptographic()) - return false; +ManageAccountsParams BuildManageAccountsParams( + const std::string& header_value) { + return ChromeConnectedHeaderHelper::BuildManageAccountsParams(header_value); +} - GURL origin(url.GetOrigin()); - bool is_enable_account_consistency = switches::IsEnableAccountConsistency(); - bool is_google_url = is_enable_account_consistency && - (google_util::IsGoogleDomainUrl( - url, google_util::ALLOW_SUBDOMAIN, - google_util::DISALLOW_NON_STANDARD_PORTS) || - google_util::IsYoutubeDomainUrl( - url, google_util::ALLOW_SUBDOMAIN, - google_util::DISALLOW_NON_STANDARD_PORTS)); - return is_google_url || IsDriveOrigin(origin) || - gaia::IsGaiaSignonRealm(origin); +#if BUILDFLAG(ENABLE_DICE_SUPPORT) +DiceResponseParams BuildDiceSigninResponseParams( + const std::string& header_value) { + return DiceHeaderHelper::BuildDiceSigninResponseParams(header_value); +} + +DiceResponseParams BuildDiceSignoutResponseParams( + const std::string& header_value) { + return DiceHeaderHelper::BuildDiceSignoutResponseParams(header_value); } +#endif } // namespace signin diff --git a/chromium/components/signin/core/browser/signin_header_helper.h b/chromium/components/signin/core/browser/signin_header_helper.h index 9f000bc6411..06b72cb3ad6 100644 --- a/chromium/components/signin/core/browser/signin_header_helper.h +++ b/chromium/components/signin/core/browser/signin_header_helper.h @@ -5,9 +5,12 @@ #ifndef COMPONENTS_SIGNIN_CORE_BROWSER_SIGNIN_HEADER_HELPER_H_ #define COMPONENTS_SIGNIN_CORE_BROWSER_SIGNIN_HEADER_HELPER_H_ +#include <map> #include <string> +#include <vector> -#include "build/build_config.h" // For OS_IOS +#include "components/signin/core/common/signin_features.h" +#include "url/gurl.h" namespace content_settings { class CookieSettings; @@ -17,8 +20,6 @@ namespace net { class URLRequest; } -class GURL; - namespace signin { // Profile mode flags. @@ -31,12 +32,13 @@ enum ProfileMode { }; extern const char kChromeConnectedHeader[]; +extern const char kDiceRequestHeader[]; -// The ServiceType specified by GAIA in the response header accompanying the 204 +// The ServiceType specified by Gaia in the response header accompanying the 204 // response. This indicates the action Chrome is supposed to lead the user to // perform. enum GAIAServiceType { - GAIA_SERVICE_TYPE_NONE = 0, // No GAIA response header. + GAIA_SERVICE_TYPE_NONE = 0, // No Gaia response header. GAIA_SERVICE_TYPE_SIGNOUT, // Logout all existing sessions. GAIA_SERVICE_TYPE_INCOGNITO, // Open an incognito tab. GAIA_SERVICE_TYPE_ADDSESSION, // Add a secondary account. @@ -45,7 +47,13 @@ enum GAIAServiceType { GAIA_SERVICE_TYPE_DEFAULT, // All other cases. }; -// Struct describing the paramters received in the manage account header. +enum class DiceAction { + NONE, + SIGNIN, // Sign in an account. + SIGNOUT, // Sign out of all sessions. +}; + +// Struct describing the parameters received in the manage account header. struct ManageAccountsParams { // The requested service type such as "ADDSESSION". GAIAServiceType service_type; @@ -59,26 +67,87 @@ struct ManageAccountsParams { // Whether the continue URL should be loaded in the same tab. bool is_same_tab; -// iOS has no notion of route and child IDs. -#if !defined(OS_IOS) - // The child id associated with the web content of the request. - int child_id; - // The route id associated with the web content of the request. - int route_id; -#endif // !defined(OS_IOS) - ManageAccountsParams(); ManageAccountsParams(const ManageAccountsParams& other); }; +// Struct describing the parameters received in the Dice response header. +struct DiceResponseParams { + struct SigninInfo { + SigninInfo(); + SigninInfo(const SigninInfo&); + ~SigninInfo(); + // Gaia ID of the account signed in. + std::string gaia_id; + // Email of the account signed in. + std::string email; + // Session index for the account signed in. + int session_index; + // Authorization code to fetch a refresh token. + std::string authorization_code; + }; + + struct SignoutInfo { + SignoutInfo(); + SignoutInfo(const SignoutInfo&); + ~SignoutInfo(); + // Gaia IDs of the accounts signed out. + std::vector<std::string> gaia_id; + // Emails of the accounts signed out. + std::vector<std::string> email; + // Session indices for the accounts signed out. + std::vector<int> session_index; + }; + + DiceResponseParams(); + ~DiceResponseParams(); + DiceResponseParams(const DiceResponseParams& other); + + DiceAction user_intention; + + // Populated when |user_intention| is SIGNIN. + SigninInfo signin_info; + + // Populated when |user_intention| is SIGNOUT. + SignoutInfo signout_info; +}; + +// Base class for managing the signin headers (Dice and Chrome-Connected). +class SigninHeaderHelper { + public: + // Appends or remove the header to a network request if necessary. + bool AppendOrRemoveRequestHeader(net::URLRequest* request, + const GURL& redirect_url, + const char* header_name, + const std::string& header_value); + + // Returns wether an account consistency header should be built for this + // request. + bool ShouldBuildRequestHeader( + const GURL& url, + const content_settings::CookieSettings* cookie_settings); + + protected: + SigninHeaderHelper() {} + virtual ~SigninHeaderHelper() {} + + // Dictionary of fields in a account consistency response header. + using ResponseHeaderDictionary = std::multimap<std::string, std::string>; + + // Parses the account consistency response header. Its expected format is + // "key1=value1,key2=value2,...". + static ResponseHeaderDictionary ParseAccountConsistencyResponseHeader( + const std::string& header_value); + + private: + // Returns whether the url is eligible for the request header. + virtual bool IsUrlEligibleForRequestHeader(const GURL& url) = 0; +}; + // Returns true if signin cookies are allowed. bool SettingsAllowSigninCookies( const content_settings::CookieSettings* cookie_settings); -// Checks if the url has the required properties to have an -// X-Chrome-Connected header. -bool IsUrlEligibleForXChromeConnectedHeader(const GURL& url); - // Returns the CHROME_CONNECTED cookie, or an empty string if it should not be // added to the request to |url|. std::string BuildMirrorRequestCookieIfPossible( @@ -87,13 +156,14 @@ std::string BuildMirrorRequestCookieIfPossible( const content_settings::CookieSettings* cookie_settings, int profile_mode_mask); -// Adds X-Chrome-Connected header to all Gaia requests from a connected profile, -// with the exception of requests from gaia webview. +// Adds account consistency header to all Gaia requests from a connected +// profile, with the exception of requests from gaia webview. // Removes the header in case it should not be transfered to a redirected url. -bool AppendOrRemoveMirrorRequestHeaderIfPossible( +void AppendOrRemoveAccountConsistentyRequestHeader( net::URLRequest* request, const GURL& redirect_url, const std::string& account_id, + bool sync_enabled, const content_settings::CookieSettings* cookie_settings, int profile_mode_mask); @@ -101,12 +171,21 @@ bool AppendOrRemoveMirrorRequestHeaderIfPossible( // header. ManageAccountsParams BuildManageAccountsParams(const std::string& header_value); -// Returns the parameters contained in the X-Chrome-Manage-Accounts response +#if BUILDFLAG(ENABLE_DICE_SUPPORT) +// Returns the parameters contained in the X-Chrome-ID-Consistency-Response +// response header. +// Returns DiceAction::NONE in case of error (such as missing or malformed +// parameters). +DiceResponseParams BuildDiceSigninResponseParams( + const std::string& header_value); + +// Returns the parameters contained in the Google-Accounts-SignOut response // header. -// If the request does not have a response header or if the header contains -// garbage, then |service_type| is set to |GAIA_SERVICE_TYPE_NONE|. -ManageAccountsParams BuildManageAccountsParamsIfExists(net::URLRequest* request, - bool is_off_the_record); +// Returns DiceAction::NONE in case of error (such as missing or malformed +// parameters). +DiceResponseParams BuildDiceSignoutResponseParams( + const std::string& header_value); +#endif } // namespace signin diff --git a/chromium/components/signin/core/browser/signin_header_helper_unittest.cc b/chromium/components/signin/core/browser/signin_header_helper_unittest.cc index 5141e3d3f0b..bade766e6fb 100644 --- a/chromium/components/signin/core/browser/signin_header_helper_unittest.cc +++ b/chromium/components/signin/core/browser/signin_header_helper_unittest.cc @@ -2,19 +2,31 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. +#include "components/signin/core/browser/signin_header_helper.h" + #include <memory> +#include <string> #include "base/command_line.h" #include "base/message_loop/message_loop.h" +#include "base/strings/stringprintf.h" #include "components/content_settings/core/browser/cookie_settings.h" -#include "components/signin/core/browser/signin_header_helper.h" +#include "components/signin/core/browser/chrome_connected_header_helper.h" #include "components/signin/core/common/profile_management_switches.h" +#include "components/signin/core/common/signin_features.h" #include "components/sync_preferences/testing_pref_service_syncable.h" +#include "google_apis/gaia/gaia_urls.h" #include "net/traffic_annotation/network_traffic_annotation_test_helper.h" #include "net/url_request/url_request_test_util.h" #include "testing/gtest/include/gtest/gtest.h" #include "url/gurl.h" +#if BUILDFLAG(ENABLE_DICE_SUPPORT) +#include "components/signin/core/browser/dice_header_helper.h" +#endif + +namespace signin { + class SigninHeaderHelperTest : public testing::Test { protected: void SetUp() override { @@ -33,32 +45,62 @@ class SigninHeaderHelperTest : public testing::Test { void CheckMirrorCookieRequest(const GURL& url, const std::string& account_id, const std::string& expected_request) { - EXPECT_EQ(signin::BuildMirrorRequestCookieIfPossible( - url, account_id, cookie_settings_.get(), - signin::PROFILE_MODE_DEFAULT), - expected_request); + EXPECT_EQ( + BuildMirrorRequestCookieIfPossible( + url, account_id, cookie_settings_.get(), PROFILE_MODE_DEFAULT), + expected_request); } - void CheckMirrorHeaderRequest(const GURL& url, - const std::string& account_id, - const std::string& expected_request) { - bool expected_result = !expected_request.empty(); + std::unique_ptr<net::URLRequest> CreateRequest(const GURL& url, + const std::string& account_id, + bool sync_enabled) { std::unique_ptr<net::URLRequest> url_request = url_request_context_.CreateRequest(url, net::DEFAULT_PRIORITY, nullptr, TRAFFIC_ANNOTATION_FOR_TESTS); - EXPECT_EQ(signin::AppendOrRemoveMirrorRequestHeaderIfPossible( - url_request.get(), GURL(), account_id, cookie_settings_.get(), - signin::PROFILE_MODE_DEFAULT), - expected_result); + AppendOrRemoveAccountConsistentyRequestHeader( + url_request.get(), GURL(), account_id, sync_enabled, + cookie_settings_.get(), PROFILE_MODE_DEFAULT); + return url_request; + } + + void CheckAccountConsistencyHeaderRequest( + net::URLRequest* url_request, + const char* header_name, + const std::string& expected_request) { + bool expected_result = !expected_request.empty(); std::string request; - EXPECT_EQ(url_request->extra_request_headers().GetHeader( - signin::kChromeConnectedHeader, &request), - expected_result); + EXPECT_EQ( + url_request->extra_request_headers().GetHeader(header_name, &request), + expected_result); if (expected_result) { EXPECT_EQ(expected_request, request); } } + void CheckMirrorHeaderRequest(const GURL& url, + const std::string& account_id, + const std::string& expected_request) { + std::unique_ptr<net::URLRequest> url_request = + CreateRequest(url, account_id, false /* sync_enabled */); + CheckAccountConsistencyHeaderRequest( + url_request.get(), kChromeConnectedHeader, expected_request); + } + +#if BUILDFLAG(ENABLE_DICE_SUPPORT) + void CheckDiceHeaderRequest(const GURL& url, + const std::string& account_id, + bool sync_enabled, + const std::string& expected_mirror_request, + const std::string& expected_dice_request) { + std::unique_ptr<net::URLRequest> url_request = + CreateRequest(url, account_id, sync_enabled); + CheckAccountConsistencyHeaderRequest( + url_request.get(), kChromeConnectedHeader, expected_mirror_request); + CheckAccountConsistencyHeaderRequest(url_request.get(), kDiceRequestHeader, + expected_dice_request); + } +#endif + base::MessageLoop loop_; sync_preferences::TestingPrefServiceSyncable prefs_; @@ -71,7 +113,7 @@ class SigninHeaderHelperTest : public testing::Test { // Tests that no Mirror request is returned when the user is not signed in (no // account id). TEST_F(SigninHeaderHelperTest, TestNoMirrorRequestNoAccountId) { - switches::EnableAccountConsistencyForTesting( + switches::EnableAccountConsistencyMirrorForTesting( base::CommandLine::ForCurrentProcess()); CheckMirrorHeaderRequest(GURL("https://docs.google.com"), "", ""); CheckMirrorCookieRequest(GURL("https://docs.google.com"), "", ""); @@ -80,7 +122,7 @@ TEST_F(SigninHeaderHelperTest, TestNoMirrorRequestNoAccountId) { // Tests that no Mirror request is returned when the cookies aren't allowed to // be set. TEST_F(SigninHeaderHelperTest, TestNoMirrorRequestCookieSettingBlocked) { - switches::EnableAccountConsistencyForTesting( + switches::EnableAccountConsistencyMirrorForTesting( base::CommandLine::ForCurrentProcess()); cookie_settings_->SetDefaultCookieSetting(CONTENT_SETTING_BLOCK); CheckMirrorHeaderRequest(GURL("https://docs.google.com"), "0123456789", ""); @@ -89,7 +131,7 @@ TEST_F(SigninHeaderHelperTest, TestNoMirrorRequestCookieSettingBlocked) { // Tests that no Mirror request is returned when the target is a non-Google URL. TEST_F(SigninHeaderHelperTest, TestNoMirrorRequestExternalURL) { - switches::EnableAccountConsistencyForTesting( + switches::EnableAccountConsistencyMirrorForTesting( base::CommandLine::ForCurrentProcess()); CheckMirrorHeaderRequest(GURL("https://foo.com"), "0123456789", ""); CheckMirrorCookieRequest(GURL("https://foo.com"), "0123456789", ""); @@ -98,7 +140,7 @@ TEST_F(SigninHeaderHelperTest, TestNoMirrorRequestExternalURL) { // Tests that the Mirror request is returned without the GAIA Id when the target // is a google TLD domain. TEST_F(SigninHeaderHelperTest, TestMirrorRequestGoogleTLD) { - switches::EnableAccountConsistencyForTesting( + switches::EnableAccountConsistencyMirrorForTesting( base::CommandLine::ForCurrentProcess()); CheckMirrorHeaderRequest(GURL("https://google.fr"), "0123456789", "mode=0,enable_account_consistency=true"); @@ -109,7 +151,7 @@ TEST_F(SigninHeaderHelperTest, TestMirrorRequestGoogleTLD) { // Tests that the Mirror request is returned when the target is the domain // google.com, and that the GAIA Id is only attached for the cookie. TEST_F(SigninHeaderHelperTest, TestMirrorRequestGoogleCom) { - switches::EnableAccountConsistencyForTesting( + switches::EnableAccountConsistencyMirrorForTesting( base::CommandLine::ForCurrentProcess()); CheckMirrorHeaderRequest(GURL("https://www.google.com"), "0123456789", "mode=0,enable_account_consistency=true"); @@ -118,14 +160,63 @@ TEST_F(SigninHeaderHelperTest, TestMirrorRequestGoogleCom) { "id=0123456789:mode=0:enable_account_consistency=true"); } +// Mirror is always enabled on Android and iOS, so these tests are only relevant +// on Desktop. +#if BUILDFLAG(ENABLE_DICE_SUPPORT) + +// Tests that the Mirror request is returned when the target is a Gaia URL, even +// if account consistency is disabled. +TEST_F(SigninHeaderHelperTest, TestMirrorRequestGaiaURL) { + ASSERT_FALSE(switches::IsAccountConsistencyMirrorEnabled()); + CheckMirrorHeaderRequest(GURL("https://accounts.google.com"), "0123456789", + "mode=0,enable_account_consistency=false"); + CheckMirrorCookieRequest( + GURL("https://accounts.google.com"), "0123456789", + "id=0123456789:mode=0:enable_account_consistency=false"); +} + +// Tests Dice requests. +TEST_F(SigninHeaderHelperTest, TestDiceRequest) { + switches::EnableAccountConsistencyDiceForTesting( + base::CommandLine::ForCurrentProcess()); + // ChromeConnected but no Dice for Docs URLs. + CheckDiceHeaderRequest( + GURL("https://docs.google.com"), "0123456789", false /* sync_enabled */, + "id=0123456789,mode=0,enable_account_consistency=false", ""); + + // ChromeConnected and Dice for Gaia URLs. + // Sync disabled. + std::string client_id = GaiaUrls::GetInstance()->oauth2_chrome_client_id(); + ASSERT_FALSE(client_id.empty()); + CheckDiceHeaderRequest(GURL("https://accounts.google.com"), "0123456789", + false /* sync_enabled */, + "mode=0,enable_account_consistency=false", + "client_id=" + client_id); + // Sync enabled: check that the Dice header has the Sync account ID and that + // the mirror header is not modified. + CheckDiceHeaderRequest( + GURL("https://accounts.google.com"), "0123456789", + true /* sync_enabled */, "mode=0,enable_account_consistency=false", + "client_id=" + client_id + ",sync_account_id=0123456789"); + + // No ChromeConnected and no Dice for other URLs. + CheckDiceHeaderRequest(GURL("https://www.google.com"), "0123456789", + false /* sync_enabled */, "", ""); +} + +// Tests that no Dice request is returned when Dice is not enabled. +TEST_F(SigninHeaderHelperTest, TestNoDiceRequestWhenDisabled) { + switches::EnableAccountConsistencyMirrorForTesting( + base::CommandLine::ForCurrentProcess()); + CheckDiceHeaderRequest(GURL("https://accounts.google.com"), "0123456789", + false /* sync_enabled */, + "mode=0,enable_account_consistency=true", ""); +} + // Tests that the Mirror request is returned with the GAIA Id on Drive origin, // even if account consistency is disabled. -// -// Account consistency if always enabled on Android and iOS, so this test is -// only relevant on Desktop. -#if !defined(OS_ANDROID) && !defined(OS_IOS) TEST_F(SigninHeaderHelperTest, TestMirrorRequestDrive) { - DCHECK(!switches::IsEnableAccountConsistency()); + ASSERT_FALSE(switches::IsAccountConsistencyMirrorEnabled()); CheckMirrorHeaderRequest( GURL("https://docs.google.com/document"), "0123456789", "id=0123456789,mode=0,enable_account_consistency=false"); @@ -134,7 +225,7 @@ TEST_F(SigninHeaderHelperTest, TestMirrorRequestDrive) { "id=0123456789:mode=0:enable_account_consistency=false"); // Enable Account Consistency will override the disable. - switches::EnableAccountConsistencyForTesting( + switches::EnableAccountConsistencyMirrorForTesting( base::CommandLine::ForCurrentProcess()); CheckMirrorHeaderRequest( GURL("https://docs.google.com/document"), "0123456789", @@ -143,12 +234,102 @@ TEST_F(SigninHeaderHelperTest, TestMirrorRequestDrive) { GURL("https://drive.google.com/drive"), "0123456789", "id=0123456789:mode=0:enable_account_consistency=true"); } -#endif + +TEST_F(SigninHeaderHelperTest, TestDiceInvalidResponseParams) { + DiceResponseParams params = BuildDiceSigninResponseParams("blah"); + EXPECT_EQ(DiceAction::NONE, params.user_intention); +} + +TEST_F(SigninHeaderHelperTest, TestBuildDiceResponseParams) { + const char kAuthorizationCode[] = "authorization_code"; + const char kEmail[] = "foo@example.com"; + const char kGaiaID[] = "gaia_id"; + const int kSessionIndex = 42; + + { + // Signin response. + DiceResponseParams params = + BuildDiceSigninResponseParams(base::StringPrintf( + "action=SIGNIN,id=%s,email=%s,authuser=%i,authorization_code=%s", + kGaiaID, kEmail, kSessionIndex, kAuthorizationCode)); + EXPECT_EQ(DiceAction::SIGNIN, params.user_intention); + EXPECT_EQ(kGaiaID, params.signin_info.gaia_id); + EXPECT_EQ(kEmail, params.signin_info.email); + EXPECT_EQ(kSessionIndex, params.signin_info.session_index); + EXPECT_EQ(kAuthorizationCode, params.signin_info.authorization_code); + } + + { + // Signout response. + // Note: Gaia responses typically have a whitespace after the commas, and + // some fields are wrapped in quotes. + DiceResponseParams params = BuildDiceSignoutResponseParams( + base::StringPrintf("email=\"%s\", sessionindex=%i, obfuscatedid=\"%s\"", + kEmail, kSessionIndex, kGaiaID)); + ASSERT_EQ(DiceAction::SIGNOUT, params.user_intention); + EXPECT_EQ(1u, params.signout_info.gaia_id.size()); + EXPECT_EQ(1u, params.signout_info.email.size()); + EXPECT_EQ(1u, params.signout_info.session_index.size()); + EXPECT_EQ(kGaiaID, params.signout_info.gaia_id[0]); + EXPECT_EQ(kEmail, params.signout_info.email[0]); + EXPECT_EQ(kSessionIndex, params.signout_info.session_index[0]); + } + + { + // Multi-Signout response. + const char kEmail2[] = "bar@example.com"; + const char kGaiaID2[] = "gaia_id_2"; + const int kSessionIndex2 = 2; + DiceResponseParams params = + BuildDiceSignoutResponseParams(base::StringPrintf( + "email=\"%s\", sessionindex=%i, obfuscatedid=\"%s\", " + "email=\"%s\", sessionindex=%i, obfuscatedid=\"%s\"", + kEmail, kSessionIndex, kGaiaID, kEmail2, kSessionIndex2, kGaiaID2)); + ASSERT_EQ(DiceAction::SIGNOUT, params.user_intention); + EXPECT_EQ(2u, params.signout_info.gaia_id.size()); + EXPECT_EQ(2u, params.signout_info.email.size()); + EXPECT_EQ(2u, params.signout_info.session_index.size()); + EXPECT_EQ(kGaiaID, params.signout_info.gaia_id[0]); + EXPECT_EQ(kEmail, params.signout_info.email[0]); + EXPECT_EQ(kSessionIndex, params.signout_info.session_index[0]); + EXPECT_EQ(kGaiaID2, params.signout_info.gaia_id[1]); + EXPECT_EQ(kEmail2, params.signout_info.email[1]); + EXPECT_EQ(kSessionIndex2, params.signout_info.session_index[1]); + } + + { + // Missing authorization code. + DiceResponseParams params = BuildDiceSigninResponseParams( + base::StringPrintf("action=SIGNIN,id=%s,email=%s,authuser=%i", kGaiaID, + kEmail, kSessionIndex)); + EXPECT_EQ(DiceAction::NONE, params.user_intention); + } + + { + // Missing email in SIGNIN. + DiceResponseParams params = + BuildDiceSigninResponseParams(base::StringPrintf( + "action=SIGNIN,id=%s,authuser=%i,authorization_code=%s", kGaiaID, + kSessionIndex, kAuthorizationCode)); + EXPECT_EQ(DiceAction::NONE, params.user_intention); + } + + { + // Missing email in signout. + DiceResponseParams params = BuildDiceSignoutResponseParams( + base::StringPrintf("email=%s, sessionindex=%i, obfuscatedid=%s, " + "sessionindex=2, obfuscatedid=bar", + kEmail, kSessionIndex, kGaiaID)); + EXPECT_EQ(DiceAction::NONE, params.user_intention); + } +} + +#endif // BUILDFLAG(ENABLE_DICE_SUPPORT) // Tests that the Mirror header request is returned normally when the redirect // URL is eligible. TEST_F(SigninHeaderHelperTest, TestMirrorHeaderEligibleRedirectURL) { - switches::EnableAccountConsistencyForTesting( + switches::EnableAccountConsistencyMirrorForTesting( base::CommandLine::ForCurrentProcess()); const GURL url("https://docs.google.com/document"); const GURL redirect_url("https://www.google.com"); @@ -156,17 +337,17 @@ TEST_F(SigninHeaderHelperTest, TestMirrorHeaderEligibleRedirectURL) { std::unique_ptr<net::URLRequest> url_request = url_request_context_.CreateRequest(url, net::DEFAULT_PRIORITY, nullptr, TRAFFIC_ANNOTATION_FOR_TESTS); - EXPECT_TRUE(signin::AppendOrRemoveMirrorRequestHeaderIfPossible( - url_request.get(), redirect_url, account_id, cookie_settings_.get(), - signin::PROFILE_MODE_DEFAULT)); - EXPECT_TRUE(url_request->extra_request_headers().HasHeader( - signin::kChromeConnectedHeader)); + AppendOrRemoveAccountConsistentyRequestHeader( + url_request.get(), redirect_url, account_id, false /* sync_enabled */, + cookie_settings_.get(), PROFILE_MODE_DEFAULT); + EXPECT_TRUE( + url_request->extra_request_headers().HasHeader(kChromeConnectedHeader)); } // Tests that the Mirror header request is stripped when the redirect URL is not // eligible. TEST_F(SigninHeaderHelperTest, TestMirrorHeaderNonEligibleRedirectURL) { - switches::EnableAccountConsistencyForTesting( + switches::EnableAccountConsistencyMirrorForTesting( base::CommandLine::ForCurrentProcess()); const GURL url("https://docs.google.com/document"); const GURL redirect_url("http://www.foo.com"); @@ -174,17 +355,17 @@ TEST_F(SigninHeaderHelperTest, TestMirrorHeaderNonEligibleRedirectURL) { std::unique_ptr<net::URLRequest> url_request = url_request_context_.CreateRequest(url, net::DEFAULT_PRIORITY, nullptr, TRAFFIC_ANNOTATION_FOR_TESTS); - EXPECT_FALSE(signin::AppendOrRemoveMirrorRequestHeaderIfPossible( - url_request.get(), redirect_url, account_id, cookie_settings_.get(), - signin::PROFILE_MODE_DEFAULT)); - EXPECT_FALSE(url_request->extra_request_headers().HasHeader( - signin::kChromeConnectedHeader)); + AppendOrRemoveAccountConsistentyRequestHeader( + url_request.get(), redirect_url, account_id, false /* sync_enabled */, + cookie_settings_.get(), PROFILE_MODE_DEFAULT); + EXPECT_FALSE( + url_request->extra_request_headers().HasHeader(kChromeConnectedHeader)); } // Tests that the Mirror header, whatever its value is, is untouched when both // the current and the redirect URL are non-eligible. TEST_F(SigninHeaderHelperTest, TestIgnoreMirrorHeaderNonEligibleURLs) { - switches::EnableAccountConsistencyForTesting( + switches::EnableAccountConsistencyMirrorForTesting( base::CommandLine::ForCurrentProcess()); const GURL url("https://www.bar.com"); const GURL redirect_url("http://www.foo.com"); @@ -193,13 +374,34 @@ TEST_F(SigninHeaderHelperTest, TestIgnoreMirrorHeaderNonEligibleURLs) { std::unique_ptr<net::URLRequest> url_request = url_request_context_.CreateRequest(url, net::DEFAULT_PRIORITY, nullptr, TRAFFIC_ANNOTATION_FOR_TESTS); - url_request->SetExtraRequestHeaderByName(signin::kChromeConnectedHeader, - fake_header, false); - EXPECT_FALSE(signin::AppendOrRemoveMirrorRequestHeaderIfPossible( - url_request.get(), redirect_url, account_id, cookie_settings_.get(), - signin::PROFILE_MODE_DEFAULT)); + url_request->SetExtraRequestHeaderByName(kChromeConnectedHeader, fake_header, + false); + AppendOrRemoveAccountConsistentyRequestHeader( + url_request.get(), redirect_url, account_id, false /* sync_enabled */, + cookie_settings_.get(), PROFILE_MODE_DEFAULT); std::string header; EXPECT_TRUE(url_request->extra_request_headers().GetHeader( - signin::kChromeConnectedHeader, &header)); + kChromeConnectedHeader, &header)); EXPECT_EQ(fake_header, header); } + +TEST_F(SigninHeaderHelperTest, TestInvalidManageAccountsParams) { + ManageAccountsParams params = BuildManageAccountsParams("blah"); + EXPECT_EQ(GAIA_SERVICE_TYPE_NONE, params.service_type); +} + +TEST_F(SigninHeaderHelperTest, TestBuildManageAccountsParams) { + const char kContinueURL[] = "https://www.example.com/continue"; + const char kEmail[] = "foo@example.com"; + + ManageAccountsParams params = BuildManageAccountsParams(base::StringPrintf( + "action=REAUTH,email=%s,is_saml=true,is_same_tab=true,continue_url=%s", + kEmail, kContinueURL)); + EXPECT_EQ(GAIA_SERVICE_TYPE_REAUTH, params.service_type); + EXPECT_EQ(kEmail, params.email); + EXPECT_EQ(true, params.is_saml); + EXPECT_EQ(true, params.is_same_tab); + EXPECT_EQ(GURL(kContinueURL), params.continue_url); +} + +} // namespace signin diff --git a/chromium/components/signin/core/browser/signin_manager.cc b/chromium/components/signin/core/browser/signin_manager.cc index 9e588dc9879..5ced3207823 100644 --- a/chromium/components/signin/core/browser/signin_manager.cc +++ b/chromium/components/signin/core/browser/signin_manager.cc @@ -54,6 +54,8 @@ std::string SigninManager::SigninTypeToString(SigninManager::SigninType type) { return "No Signin"; case SIGNIN_TYPE_WITH_REFRESH_TOKEN: return "With refresh token"; + case SIGNIN_TYPE_WITHOUT_REFRESH_TOKEN: + return "Without refresh token"; } NOTREACHED(); @@ -66,9 +68,9 @@ bool SigninManager::PrepareForSignin(SigninType type, const std::string& password) { std::string account_id = account_tracker_service()->PickAccountIdForAccount(gaia_id, username); + DCHECK(!account_id.empty()); DCHECK(possibly_invalid_account_id_.empty() || possibly_invalid_account_id_ == account_id); - DCHECK(!account_id.empty()); if (!IsAllowedUsername(username)) { // Account is not allowed by admin policy. @@ -101,19 +103,21 @@ void SigninManager::StartSignInWithRefreshToken( const std::string& password, const OAuthTokenFetchedCallback& callback) { DCHECK(!IsAuthenticated()); - - if (!PrepareForSignin(SIGNIN_TYPE_WITH_REFRESH_TOKEN, gaia_id, username, - password)) { + SigninType signin_type = refresh_token.empty() + ? SIGNIN_TYPE_WITHOUT_REFRESH_TOKEN + : SIGNIN_TYPE_WITH_REFRESH_TOKEN; + if (!PrepareForSignin(signin_type, gaia_id, username, password)) { return; } - // Store our token. + // Store the refresh token. temp_refresh_token_ = refresh_token; - if (!callback.is_null() && !temp_refresh_token_.empty()) { + if (!callback.is_null()) { + // Callback present, let the caller complete the pending sign-in. callback.Run(temp_refresh_token_); } else { - // No oauth token or callback, so just complete our pending signin. + // No callback, so just complete the pending signin. CompletePendingSignin(); } } @@ -350,13 +354,13 @@ void SigninManager::CompletePendingSignin() { DCHECK(!possibly_invalid_account_id_.empty()); OnSignedIn(); - DCHECK(!temp_refresh_token_.empty()); DCHECK(IsAuthenticated()); - std::string account_id = GetAuthenticatedAccountId(); - token_service_->UpdateCredentials(account_id, temp_refresh_token_); - temp_refresh_token_.clear(); - + if (!temp_refresh_token_.empty()) { + std::string account_id = GetAuthenticatedAccountId(); + token_service_->UpdateCredentials(account_id, temp_refresh_token_); + temp_refresh_token_.clear(); + } MergeSigninCredentialIntoCookieJar(); } @@ -385,8 +389,11 @@ void SigninManager::OnSignedIn() { for (auto& observer : observer_list_) { observer.GoogleSigninSucceeded(GetAuthenticatedAccountId(), - GetAuthenticatedAccountInfo().email, - password_); + GetAuthenticatedAccountInfo().email); + + observer.GoogleSigninSucceededWithPassword( + GetAuthenticatedAccountId(), GetAuthenticatedAccountInfo().email, + password_); } client_->OnSignedIn(GetAuthenticatedAccountId(), gaia_id, diff --git a/chromium/components/signin/core/browser/signin_manager.h b/chromium/components/signin/core/browser/signin_manager.h index 92e9ff587ec..bae32cf78e4 100644 --- a/chromium/components/signin/core/browser/signin_manager.h +++ b/chromium/components/signin/core/browser/signin_manager.h @@ -74,8 +74,10 @@ class SigninManager : public SigninManagerBase, const std::string& policy); // Attempt to sign in this user with a refresh token. + // If |refresh_token| is not empty, then SigninManager will add it to the + // |token_service_| when the sign-in flow is completed. // If non-null, the passed |oauth_fetched_callback| callback is invoked once - // signin has been completed. + // sign-in has been completed. // The callback should invoke SignOut() or CompletePendingSignin() to either // continue or cancel the in-process signin. virtual void StartSignInWithRefreshToken( @@ -152,7 +154,11 @@ class SigninManager : public SigninManagerBase, signin_metrics::SignoutDelete signout_delete_metric); private: - enum SigninType { SIGNIN_TYPE_NONE, SIGNIN_TYPE_WITH_REFRESH_TOKEN }; + enum SigninType { + SIGNIN_TYPE_NONE, + SIGNIN_TYPE_WITH_REFRESH_TOKEN, + SIGNIN_TYPE_WITHOUT_REFRESH_TOKEN + }; std::string SigninTypeToString(SigninType type); friend class FakeSigninManager; diff --git a/chromium/components/signin/core/browser/signin_manager_base.cc b/chromium/components/signin/core/browser/signin_manager_base.cc index df125732094..14ad0380e7a 100644 --- a/chromium/components/signin/core/browser/signin_manager_base.cc +++ b/chromium/components/signin/core/browser/signin_manager_base.cc @@ -232,7 +232,9 @@ bool SigninManagerBase::AuthInProgress() const { return false; } -void SigninManagerBase::Shutdown() {} +void SigninManagerBase::Shutdown() { + on_shutdown_callback_list_.Notify(); +} void SigninManagerBase::AddObserver(Observer* observer) { observer_list_.AddObserver(observer); diff --git a/chromium/components/signin/core/browser/signin_manager_base.h b/chromium/components/signin/core/browser/signin_manager_base.h index ddf20d85567..a7c08678e66 100644 --- a/chromium/components/signin/core/browser/signin_manager_base.h +++ b/chromium/components/signin/core/browser/signin_manager_base.h @@ -26,6 +26,7 @@ #include <memory> #include <string> +#include "base/callback_list.h" #include "base/compiler_specific.h" #include "base/logging.h" #include "base/macros.h" @@ -42,6 +43,10 @@ class PrefRegistrySimple; class PrefService; class SigninClient; +namespace password_manager { +class PasswordStoreSigninNotifierImpl; +} + namespace user_prefs { class PrefRegistrySyncable; } @@ -55,8 +60,7 @@ class SigninManagerBase : public KeyedService { // Called when a user signs into Google services such as sync. virtual void GoogleSigninSucceeded(const std::string& account_id, - const std::string& username, - const std::string& password) {} + const std::string& username) {} // Called when the currently signed-in user for a user has been signed out. virtual void GoogleSignedOut(const std::string& account_id, @@ -64,6 +68,30 @@ class SigninManagerBase : public KeyedService { protected: virtual ~Observer() {} + + private: + // Observers that can observer the password of the Google account after a + // successful sign-in. + friend class PasswordStoreSigninNotifierImpl; + + // SigninManagers that fire |GoogleSigninSucceededWithPassword| + // notifications. + friend class SigninManager; + friend class FakeSigninManager; + + // Called when a user signs into Google services such as sync. Also passes + // the password of the Google account that was used to sign in. + // + // Observers should override |GoogleSigninSucceeded| if they are not + // interested in the password thas was used during the sign-in. + // + // Note: The password is always empty on mobile as the user signs in to + // Chrome with accounts that were added to the device, so Chrome does not + // have access to the password. + virtual void GoogleSigninSucceededWithPassword( + const std::string& account_id, + const std::string& username, + const std::string& password) {} }; SigninManagerBase(SigninClient* client, @@ -132,6 +160,15 @@ class SigninManagerBase : public KeyedService { // Gives access to the SigninClient instance associated with this instance. SigninClient* signin_client() const { return client_; } + // Adds a callback that will be called when this instance is shut down.Not + // intended for general usage, but rather for usage only by the Identity + // Service implementation during the time period of conversion of Chrome to + // use the Identity Service. + std::unique_ptr<base::CallbackList<void()>::Subscription> + RegisterOnShutdownCallback(const base::Closure& cb) { + return on_shutdown_callback_list_.Add(cb); + } + protected: AccountTrackerService* account_tracker_service() const { return account_tracker_service_; @@ -169,6 +206,9 @@ class SigninManagerBase : public KeyedService { base::ObserverList<signin_internals_util::SigninDiagnosticsObserver, true> signin_diagnostics_observers_; + // The list of callbacks notified on shutdown. + base::CallbackList<void()> on_shutdown_callback_list_; + base::WeakPtrFactory<SigninManagerBase> weak_pointer_factory_; DISALLOW_COPY_AND_ASSIGN(SigninManagerBase); diff --git a/chromium/components/signin/core/browser/signin_metrics.h b/chromium/components/signin/core/browser/signin_metrics.h index 177ed1fae62..cc6709e2958 100644 --- a/chromium/components/signin/core/browser/signin_metrics.h +++ b/chromium/components/signin/core/browser/signin_metrics.h @@ -143,6 +143,7 @@ enum class AccessPoint : int { ACCESS_POINT_NTP_CONTENT_SUGGESTIONS, ACCESS_POINT_RESIGNIN_INFOBAR, ACCESS_POINT_TAB_SWITCHER, + ACCESS_POINT_FORCE_SIGNIN_WARNING, ACCESS_POINT_MAX, // This must be last. }; diff --git a/chromium/components/signin/core/browser/signin_status_metrics_provider.cc b/chromium/components/signin/core/browser/signin_status_metrics_provider.cc index 699e61d6190..8ead61c4a97 100644 --- a/chromium/components/signin/core/browser/signin_status_metrics_provider.cc +++ b/chromium/components/signin/core/browser/signin_status_metrics_provider.cc @@ -77,8 +77,7 @@ void SigninStatusMetricsProvider::OnSigninManagerShutdown( void SigninStatusMetricsProvider::GoogleSigninSucceeded( const std::string& account_id, - const std::string& username, - const std::string& password) { + const std::string& username) { SigninStatus recorded_signin_status = signin_status(); if (recorded_signin_status == ALL_PROFILES_NOT_SIGNED_IN) { UpdateSigninStatus(MIXED_SIGNIN_STATUS); diff --git a/chromium/components/signin/core/browser/signin_status_metrics_provider.h b/chromium/components/signin/core/browser/signin_status_metrics_provider.h index 9d6e663d126..ee6f0adf6ba 100644 --- a/chromium/components/signin/core/browser/signin_status_metrics_provider.h +++ b/chromium/components/signin/core/browser/signin_status_metrics_provider.h @@ -70,8 +70,7 @@ class SigninStatusMetricsProvider : public SigninStatusMetricsProviderBase, // SigninManagerBase::Observer: void GoogleSigninSucceeded(const std::string& account_id, - const std::string& username, - const std::string& password) override; + const std::string& username) override; void GoogleSignedOut(const std::string& account_id, const std::string& username) override; diff --git a/chromium/components/signin/core/browser/signin_status_metrics_provider_unittest.cc b/chromium/components/signin/core/browser/signin_status_metrics_provider_unittest.cc index 13f54ab77e4..ed1a87129a9 100644 --- a/chromium/components/signin/core/browser/signin_status_metrics_provider_unittest.cc +++ b/chromium/components/signin/core/browser/signin_status_metrics_provider_unittest.cc @@ -27,15 +27,13 @@ TEST(SigninStatusMetricsProviderTest, GoogleSigninSucceeded) { // Initial status is all signed out and then one of the profiles is signed in. metrics_provider.UpdateInitialSigninStatus(2, 0); - metrics_provider.GoogleSigninSucceeded(std::string(), std::string(), - std::string()); + metrics_provider.GoogleSigninSucceeded(std::string(), std::string()); EXPECT_EQ(SigninStatusMetricsProviderBase::MIXED_SIGNIN_STATUS, metrics_provider.GetSigninStatusForTesting()); // Initial status is mixed and then one of the profiles is signed in. metrics_provider.UpdateInitialSigninStatus(2, 1); - metrics_provider.GoogleSigninSucceeded(std::string(), std::string(), - std::string()); + metrics_provider.GoogleSigninSucceeded(std::string(), std::string()); EXPECT_EQ(SigninStatusMetricsProviderBase::MIXED_SIGNIN_STATUS, metrics_provider.GetSigninStatusForTesting()); } diff --git a/chromium/components/signin/core/browser/signin_tracker.cc b/chromium/components/signin/core/browser/signin_tracker.cc index b13365dcab3..24e23983344 100644 --- a/chromium/components/signin/core/browser/signin_tracker.cc +++ b/chromium/components/signin/core/browser/signin_tracker.cc @@ -32,6 +32,12 @@ void SigninTracker::Initialize() { cookie_manager_service_->AddObserver(this); } +void SigninTracker::GoogleSigninSucceeded(const std::string& account_id, + const std::string& username) { + if (token_service_->RefreshTokenIsAvailable(account_id)) + observer_->SigninSuccess(); +} + void SigninTracker::GoogleSigninFailed(const GoogleServiceAuthError& error) { observer_->SigninFailed(error); } diff --git a/chromium/components/signin/core/browser/signin_tracker.h b/chromium/components/signin/core/browser/signin_tracker.h index cabbedf02ca..e433df58722 100644 --- a/chromium/components/signin/core/browser/signin_tracker.h +++ b/chromium/components/signin/core/browser/signin_tracker.h @@ -80,6 +80,8 @@ class SigninTracker : public SigninManagerBase::Observer, ~SigninTracker() override; // SigninManagerBase::Observer implementation. + void GoogleSigninSucceeded(const std::string& account_id, + const std::string& username) override; void GoogleSigninFailed(const GoogleServiceAuthError& error) override; // OAuth2TokenService::Observer implementation. diff --git a/chromium/components/signin/core/common/BUILD.gn b/chromium/components/signin/core/common/BUILD.gn index 670bde9c185..c1a5c09b5e9 100644 --- a/chromium/components/signin/core/common/BUILD.gn +++ b/chromium/components/signin/core/common/BUILD.gn @@ -2,6 +2,17 @@ # Use of this source code is governed by a BSD-style license that can be # found in the LICENSE file. +import("//build/buildflag_header.gni") +import("//components/signin/features.gni") + +buildflag_header("signin_features") { + header = "signin_features.h" + flags = [ + "ENABLE_DICE_SUPPORT=$enable_dice_support", + "ENABLE_MIRROR=$enable_mirror", + ] +} + static_library("common") { sources = [ "profile_management_switches.cc", @@ -15,4 +26,8 @@ static_library("common") { deps = [ "//base", ] + + public_deps = [ + ":signin_features", + ] } diff --git a/chromium/components/signin/core/common/profile_management_switches.cc b/chromium/components/signin/core/common/profile_management_switches.cc index 4b14f6c0331..61dd356e6c0 100644 --- a/chromium/components/signin/core/common/profile_management_switches.cc +++ b/chromium/components/signin/core/common/profile_management_switches.cc @@ -14,14 +14,31 @@ namespace switches { -bool IsEnableAccountConsistency() { -#if defined(OS_ANDROID) || defined(OS_IOS) - // Account consistency is enabled on Android and iOS. - return true; +AccountConsistencyMethod GetAccountConsistencyMethod() { +#if BUILDFLAG(ENABLE_MIRROR) + // Mirror is enabled on Android and iOS. + return AccountConsistencyMethod::kMirror; #else - return base::CommandLine::ForCurrentProcess()->HasSwitch( - switches::kEnableAccountConsistency); -#endif // defined(OS_ANDROID) || defined(OS_IOS) + base::CommandLine* cmd = base::CommandLine::ForCurrentProcess(); + std::string method = cmd->GetSwitchValueASCII(switches::kAccountConsistency); + if (method == switches::kAccountConsistencyMirror) + return AccountConsistencyMethod::kMirror; + +#if BUILDFLAG(ENABLE_DICE_SUPPORT) + if (method == switches::kAccountConsistencyDice) + return AccountConsistencyMethod::kDice; +#endif + + return AccountConsistencyMethod::kDisabled; +#endif // BUILDFLAG(ENABLE_MIRROR) +} + +bool IsAccountConsistencyMirrorEnabled() { + return GetAccountConsistencyMethod() == AccountConsistencyMethod::kMirror; +} + +bool IsAccountConsistencyDiceEnabled() { + return GetAccountConsistencyMethod() == AccountConsistencyMethod::kDice; } bool IsExtensionsMultiAccount() { @@ -33,13 +50,21 @@ bool IsExtensionsMultiAccount() { return base::CommandLine::ForCurrentProcess()->HasSwitch( switches::kExtensionsMultiAccount) || - IsEnableAccountConsistency(); + GetAccountConsistencyMethod() == AccountConsistencyMethod::kMirror; } -void EnableAccountConsistencyForTesting(base::CommandLine* command_line) { -#if !defined(OS_ANDROID) && !defined(OS_IOS) - command_line->AppendSwitch(switches::kEnableAccountConsistency); +void EnableAccountConsistencyMirrorForTesting(base::CommandLine* command_line) { +#if !BUILDFLAG(ENABLE_MIRROR) + command_line->AppendSwitchASCII(switches::kAccountConsistency, + switches::kAccountConsistencyMirror); #endif } +#if BUILDFLAG(ENABLE_DICE_SUPPORT) +void EnableAccountConsistencyDiceForTesting(base::CommandLine* command_line) { + command_line->AppendSwitchASCII(switches::kAccountConsistency, + switches::kAccountConsistencyDice); +} +#endif + } // namespace switches diff --git a/chromium/components/signin/core/common/profile_management_switches.h b/chromium/components/signin/core/common/profile_management_switches.h index b3080e961d0..9642ef5b0ce 100644 --- a/chromium/components/signin/core/common/profile_management_switches.h +++ b/chromium/components/signin/core/common/profile_management_switches.h @@ -9,21 +9,41 @@ #ifndef COMPONENTS_SIGNIN_CORE_COMMON_PROFILE_MANAGEMENT_SWITCHES_H_ #define COMPONENTS_SIGNIN_CORE_COMMON_PROFILE_MANAGEMENT_SWITCHES_H_ +#include "components/signin/core/common/signin_features.h" + namespace base { class CommandLine; } namespace switches { -// Checks whether account consistency is enabled. If enabled, the account +enum class AccountConsistencyMethod { + kDisabled, // No account consistency. + kMirror, // Account management UI in the avatar bubble. + kDice // Account management UI on Gaia webpages. +}; + +// Returns the account consistency method. +AccountConsistencyMethod GetAccountConsistencyMethod(); + +// Checks whether Mirror account consistency is enabled. If enabled, the account // management UI is available in the avatar bubble. -bool IsEnableAccountConsistency(); +bool IsAccountConsistencyMirrorEnabled(); + +// Checks whether Dice account consistency is enabled. If enabled, then account +// management UI is available on the Gaia webpages. +bool IsAccountConsistencyDiceEnabled(); // Whether the chrome.identity API should be multi-account. bool IsExtensionsMultiAccount(); -// Called in tests to force enable account consistency. -void EnableAccountConsistencyForTesting(base::CommandLine* command_line); +// Called in tests to force enable Mirror account consistency. +void EnableAccountConsistencyMirrorForTesting(base::CommandLine* command_line); + +#if BUILDFLAG(ENABLE_DICE_SUPPORT) +// Called in tests to force enable Dice account consistency. +void EnableAccountConsistencyDiceForTesting(base::CommandLine* command_line); +#endif } // namespace switches diff --git a/chromium/components/signin/core/common/signin_switches.cc b/chromium/components/signin/core/common/signin_switches.cc index ef1d865c333..5ef25b778b3 100644 --- a/chromium/components/signin/core/common/signin_switches.cc +++ b/chromium/components/signin/core/common/signin_switches.cc @@ -16,9 +16,17 @@ const char kDisableSigninPromo[] = "disable-signin-promo"; // Disables sending signin scoped device id to LSO with refresh token request. const char kDisableSigninScopedDeviceId[] = "disable-signin-scoped-device-id"; -#if !defined(OS_ANDROID) && !defined(OS_IOS) -// Enables consistent identity features. -const char kEnableAccountConsistency[] = "enable-account-consistency"; +#if !BUILDFLAG(ENABLE_MIRROR) +// Command line flag for enabling account consistency. Default mode is disabled. +// Mirror is a legacy mode in which Google accounts are always addded to Chrome, +// and Chrome then adds them to the Google authentication cookies. +// Dice is a new experiment in which Chrome is aware of the accounts in the +// Google authentication cookies. +const char kAccountConsistency[] = "account-consistency"; + +// Values for the kAccountConsistency flag. +const char kAccountConsistencyMirror[] = "mirror"; +const char kAccountConsistencyDice[] = "dice"; #endif // Enables sending EnableRefreshTokenAnnotationRequest. diff --git a/chromium/components/signin/core/common/signin_switches.h b/chromium/components/signin/core/common/signin_switches.h index 8c0ecc2db9b..5038a1e4fe3 100644 --- a/chromium/components/signin/core/common/signin_switches.h +++ b/chromium/components/signin/core/common/signin_switches.h @@ -5,7 +5,7 @@ #ifndef COMPONENTS_SIGNIN_CORE_COMMON_SIGNIN_SWITCHES_H_ #define COMPONENTS_SIGNIN_CORE_COMMON_SIGNIN_SWITCHES_H_ -#include "base/feature_list.h" +#include "components/signin/core/common/signin_features.h" namespace switches { @@ -22,10 +22,12 @@ extern const char kEnableRefreshTokenAnnotationRequest[]; extern const char kEnableSigninPromo[]; extern const char kExtensionsMultiAccount[]; -#if !defined(OS_ANDROID) && !defined(OS_IOS) -// Note: Account consistency is already enabled on mobile platforms, so this -// switch only exist on desktop platforms. -extern const char kEnableAccountConsistency[]; +#if !BUILDFLAG(ENABLE_MIRROR) +// Note: Account consistency (Mirror) is already enabled on mobile platforms, so +// this switch only exist on desktop platforms. +extern const char kAccountConsistency[]; +extern const char kAccountConsistencyMirror[]; +extern const char kAccountConsistencyDice[]; #endif } // namespace switches diff --git a/chromium/components/signin/features.gni b/chromium/components/signin/features.gni new file mode 100644 index 00000000000..f4636abdb3f --- /dev/null +++ b/chromium/components/signin/features.gni @@ -0,0 +1,9 @@ +# Copyright 2017 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. + +# Dice is supported on the platform (but not necessarily enabled). +enable_dice_support = (is_linux && !is_chromeos) || is_mac || is_win + +# Mirror is enabled and other account consistency mechanisms are not available. +enable_mirror = is_android || is_ios diff --git a/chromium/components/signin/ios/browser/BUILD.gn b/chromium/components/signin/ios/browser/BUILD.gn index b914497f1d0..f34f92eec9a 100644 --- a/chromium/components/signin/ios/browser/BUILD.gn +++ b/chromium/components/signin/ios/browser/BUILD.gn @@ -3,6 +3,7 @@ # found in the LICENSE file. source_set("browser") { + configs += [ "//build/config/compiler:enable_arc" ] sources = [ "account_consistency_service.h", "account_consistency_service.mm", @@ -48,6 +49,7 @@ source_set("test_support") { } source_set("unit_tests") { + configs += [ "//build/config/compiler:enable_arc" ] testonly = true sources = [ "account_consistency_service_unittest.mm", @@ -62,7 +64,8 @@ source_set("unit_tests") { "//components/signin/core/common", "//components/sync_preferences:test_support", "//ios/web", - "//ios/web:test_support", + "//ios/web/public/test", + "//ios/web/public/test/fakes", "//third_party/ocmock", ] } diff --git a/chromium/components/signin/ios/browser/account_consistency_service.h b/chromium/components/signin/ios/browser/account_consistency_service.h index 1f7a1e6eb3f..8df4874f76b 100644 --- a/chromium/components/signin/ios/browser/account_consistency_service.h +++ b/chromium/components/signin/ios/browser/account_consistency_service.h @@ -11,7 +11,6 @@ #include <set> #include <string> -#include "base/mac/scoped_nsobject.h" #include "base/macros.h" #include "base/memory/ref_counted.h" #include "base/time/time.h" @@ -144,8 +143,7 @@ class AccountConsistencyService : public KeyedService, // SigninManagerBase::Observer implementation. void GoogleSigninSucceeded(const std::string& account_id, - const std::string& username, - const std::string& password) override; + const std::string& username) override; void GoogleSignedOut(const std::string& account_id, const std::string& username) override; @@ -178,11 +176,10 @@ class AccountConsistencyService : public KeyedService, std::map<std::string, base::Time> last_cookie_update_map_; // Web view used to apply the CHROME_CONNECTED cookie requests. - base::scoped_nsobject<WKWebView> web_view_; + __strong WKWebView* web_view_; // Navigation delegate of |web_view_| that informs the service when a cookie // request has been applied. - base::scoped_nsobject<AccountConsistencyNavigationDelegate> - navigation_delegate_; + AccountConsistencyNavigationDelegate* navigation_delegate_; // Handlers reacting on GAIA responses with the X-Chrome-Manage-Accounts // header set. diff --git a/chromium/components/signin/ios/browser/account_consistency_service.mm b/chromium/components/signin/ios/browser/account_consistency_service.mm index 5f15df39e15..a56cc1b8626 100644 --- a/chromium/components/signin/ios/browser/account_consistency_service.mm +++ b/chromium/components/signin/ios/browser/account_consistency_service.mm @@ -6,7 +6,6 @@ #import <WebKit/WebKit.h> -#import "base/ios/weak_nsobject.h" #include "base/logging.h" #import "base/mac/foundation_util.h" #include "base/macros.h" @@ -24,6 +23,10 @@ #include "net/base/registry_controlled_domains/registry_controlled_domain.h" #include "url/gurl.h" +#if !defined(__has_feature) || !__has_feature(objc_arc) +#error "This file requires ARC support." +#endif + namespace { // Threshold (in hours) used to control whether the CHROME_CONNECTED cookie @@ -58,7 +61,7 @@ class AccountConsistencyHandler : public web::WebStatePolicyDecider { AccountConsistencyService* account_consistency_service_; // Weak. AccountReconcilor* account_reconcilor_; // Weak. - base::WeakNSProtocol<id<ManageAccountsDelegate>> delegate_; + __weak id<ManageAccountsDelegate> delegate_; }; } @@ -390,14 +393,14 @@ WKWebView* AccountConsistencyService::GetWKWebView() { return nil; } if (!web_view_) { - web_view_.reset([BuildWKWebView() retain]); - navigation_delegate_.reset([[AccountConsistencyNavigationDelegate alloc] + web_view_ = BuildWKWebView(); + navigation_delegate_ = [[AccountConsistencyNavigationDelegate alloc] initWithCallback:base::Bind(&AccountConsistencyService:: FinishedApplyingCookieRequest, - base::Unretained(this), true)]); + base::Unretained(this), true)]; [web_view_ setNavigationDelegate:navigation_delegate_]; } - return web_view_.get(); + return web_view_; } WKWebView* AccountConsistencyService::BuildWKWebView() { @@ -407,8 +410,8 @@ WKWebView* AccountConsistencyService::BuildWKWebView() { void AccountConsistencyService::ResetWKWebView() { [web_view_ setNavigationDelegate:nil]; [web_view_ stopLoading]; - web_view_.reset(); - navigation_delegate_.reset(); + web_view_ = nil; + navigation_delegate_ = nil; applying_cookie_requests_ = false; } @@ -459,8 +462,7 @@ void AccountConsistencyService::OnGaiaAccountsInCookieUpdated( void AccountConsistencyService::GoogleSigninSucceeded( const std::string& account_id, - const std::string& username, - const std::string& password) { + const std::string& username) { AddChromeConnectedCookies(); } diff --git a/chromium/components/signin/ios/browser/account_consistency_service_unittest.mm b/chromium/components/signin/ios/browser/account_consistency_service_unittest.mm index 4dcfccf52ca..f61cebd655c 100644 --- a/chromium/components/signin/ios/browser/account_consistency_service_unittest.mm +++ b/chromium/components/signin/ios/browser/account_consistency_service_unittest.mm @@ -8,7 +8,6 @@ #include <memory> -#import "base/mac/scoped_nsobject.h" #include "components/signin/core/browser/account_reconcilor.h" #include "components/signin/core/browser/account_tracker_service.h" #include "components/signin/core/browser/fake_signin_manager.h" @@ -27,6 +26,10 @@ #include "third_party/ocmock/OCMock/OCMock.h" #include "third_party/ocmock/gtest_support.h" +#if !defined(__has_feature) || !__has_feature(objc_arc) +#error "This file requires ARC support." +#endif + namespace { // URL of the Google domain where the CHROME_CONNECTED cookie is set/removed. NSURL* const kGoogleUrl = [NSURL URLWithString:@"https://google.com/"]; @@ -63,12 +66,11 @@ class FakeAccountConsistencyService : public AccountConsistencyService { private: WKWebView* BuildWKWebView() override { if (!mock_web_view_) { - mock_web_view_.reset( - [[OCMockObject niceMockForClass:[WKWebView class]] retain]); + mock_web_view_ = [OCMockObject niceMockForClass:[WKWebView class]]; } return mock_web_view_; } - base::scoped_nsobject<id> mock_web_view_; + id mock_web_view_; }; // Mock AccountReconcilor to catch call to OnReceivedManageAccountsResponse. @@ -155,7 +157,7 @@ class AccountConsistencyServiceTest : public PlatformTest { void (^continueBlock)(NSInvocation*) = ^(NSInvocation* invocation) { if (!continue_navigation) return; - WKWebView* web_view = nil; + __unsafe_unretained WKWebView* web_view = nil; [invocation getArgument:&web_view atIndex:0]; [GetNavigationDelegate() webView:web_view didFinishNavigation:nil]; }; @@ -236,11 +238,11 @@ TEST_F(AccountConsistencyServiceTest, SignInSignOut) { id delegate = [OCMockObject mockForProtocol:@protocol(ManageAccountsDelegate)]; NSDictionary* headers = [NSDictionary dictionary]; - base::scoped_nsobject<NSHTTPURLResponse> response([[NSHTTPURLResponse alloc] - initWithURL:kCountryGoogleUrl - statusCode:200 - HTTPVersion:@"HTTP/1.1" - headerFields:headers]); + NSHTTPURLResponse* response = + [[NSHTTPURLResponse alloc] initWithURL:kCountryGoogleUrl + statusCode:200 + HTTPVersion:@"HTTP/1.1" + headerFields:headers]; account_consistency_service_->SetWebStateHandler(&web_state_, delegate); EXPECT_TRUE(web_state_.ShouldAllowResponse(response)); web_state_.WebStateDestroyed(); @@ -292,11 +294,11 @@ TEST_F(AccountConsistencyServiceTest, ChromeManageAccountsNotOnGaia) { NSDictionary* headers = [NSDictionary dictionaryWithObject:@"action=DEFAULT" forKey:@"X-Chrome-Manage-Accounts"]; - base::scoped_nsobject<NSHTTPURLResponse> response([[NSHTTPURLResponse alloc] + NSHTTPURLResponse* response = [[NSHTTPURLResponse alloc] initWithURL:[NSURL URLWithString:@"https://google.com"] statusCode:200 HTTPVersion:@"HTTP/1.1" - headerFields:headers]); + headerFields:headers]; account_consistency_service_->SetWebStateHandler(&web_state_, delegate); EXPECT_TRUE(web_state_.ShouldAllowResponse(response)); web_state_.WebStateDestroyed(); @@ -311,11 +313,11 @@ TEST_F(AccountConsistencyServiceTest, ChromeManageAccountsNoHeader) { [OCMockObject mockForProtocol:@protocol(ManageAccountsDelegate)]; NSDictionary* headers = [NSDictionary dictionary]; - base::scoped_nsobject<NSHTTPURLResponse> response([[NSHTTPURLResponse alloc] + NSHTTPURLResponse* response = [[NSHTTPURLResponse alloc] initWithURL:[NSURL URLWithString:@"https://accounts.google.com/"] statusCode:200 HTTPVersion:@"HTTP/1.1" - headerFields:headers]); + headerFields:headers]; account_consistency_service_->SetWebStateHandler(&web_state_, delegate); EXPECT_TRUE(web_state_.ShouldAllowResponse(response)); web_state_.WebStateDestroyed(); @@ -335,11 +337,11 @@ TEST_F(AccountConsistencyServiceTest, ChromeManageAccountsDefault) { NSDictionary* headers = [NSDictionary dictionaryWithObject:@"action=DEFAULT" forKey:@"X-Chrome-Manage-Accounts"]; - base::scoped_nsobject<NSHTTPURLResponse> response([[NSHTTPURLResponse alloc] + NSHTTPURLResponse* response = [[NSHTTPURLResponse alloc] initWithURL:[NSURL URLWithString:@"https://accounts.google.com/"] statusCode:200 HTTPVersion:@"HTTP/1.1" - headerFields:headers]); + headerFields:headers]; account_consistency_service_->SetWebStateHandler(&web_state_, delegate); EXPECT_CALL(account_reconcilor_, OnReceivedManageAccountsResponse( signin::GAIA_SERVICE_TYPE_DEFAULT)) diff --git a/chromium/components/signin/ios/browser/merge_session_observer_bridge.h b/chromium/components/signin/ios/browser/merge_session_observer_bridge.h index 8137dbbf1d0..ec9b10439d1 100644 --- a/chromium/components/signin/ios/browser/merge_session_observer_bridge.h +++ b/chromium/components/signin/ios/browser/merge_session_observer_bridge.h @@ -35,7 +35,7 @@ class MergeSessionObserverBridge : public GaiaCookieManagerService::Observer { const GoogleServiceAuthError& error) override; private: - id<MergeSessionObserverBridgeDelegate> delegate_; + __weak id<MergeSessionObserverBridgeDelegate> delegate_; GaiaCookieManagerService* cookie_manager_service_; DISALLOW_COPY_AND_ASSIGN(MergeSessionObserverBridge); diff --git a/chromium/components/signin/ios/browser/merge_session_observer_bridge.mm b/chromium/components/signin/ios/browser/merge_session_observer_bridge.mm index 0237be1eb61..ee30039d09a 100644 --- a/chromium/components/signin/ios/browser/merge_session_observer_bridge.mm +++ b/chromium/components/signin/ios/browser/merge_session_observer_bridge.mm @@ -7,6 +7,10 @@ #include "base/logging.h" #include "google_apis/gaia/google_service_auth_error.h" +#if !defined(__has_feature) || !__has_feature(objc_arc) +#error "This file requires ARC support." +#endif + MergeSessionObserverBridge::MergeSessionObserverBridge( id<MergeSessionObserverBridgeDelegate> delegate, GaiaCookieManagerService* cookie_manager_service) diff --git a/chromium/components/signin/ios/browser/oauth2_token_service_observer_bridge.h b/chromium/components/signin/ios/browser/oauth2_token_service_observer_bridge.h index 04d38962310..425a9b3e90e 100644 --- a/chromium/components/signin/ios/browser/oauth2_token_service_observer_bridge.h +++ b/chromium/components/signin/ios/browser/oauth2_token_service_observer_bridge.h @@ -7,6 +7,7 @@ #import <Foundation/Foundation.h> +#import "base/ios/weak_nsobject.h" #include "base/macros.h" #include "google_apis/gaia/oauth2_token_service.h" @@ -49,7 +50,7 @@ class OAuth2TokenServiceObserverBridge : public OAuth2TokenService::Observer { private: OAuth2TokenService* token_service_; // weak - id<OAuth2TokenServiceObserverBridgeDelegate> delegate_; + base::WeakNSProtocol<id<OAuth2TokenServiceObserverBridgeDelegate>> delegate_; DISALLOW_COPY_AND_ASSIGN(OAuth2TokenServiceObserverBridge); }; diff --git a/chromium/components/signin/ios/browser/oauth2_token_service_observer_bridge.mm b/chromium/components/signin/ios/browser/oauth2_token_service_observer_bridge.mm index 7d649a939e9..ddaddb068d3 100644 --- a/chromium/components/signin/ios/browser/oauth2_token_service_observer_bridge.mm +++ b/chromium/components/signin/ios/browser/oauth2_token_service_observer_bridge.mm @@ -4,6 +4,10 @@ #include "components/signin/ios/browser/oauth2_token_service_observer_bridge.h" +#if !defined(__has_feature) || !__has_feature(objc_arc) +#error "This file requires ARC support." +#endif + OAuth2TokenServiceObserverBridge::OAuth2TokenServiceObserverBridge( OAuth2TokenService* token_service, id<OAuth2TokenServiceObserverBridgeDelegate> delegate) diff --git a/chromium/components/signin/ios/browser/profile_oauth2_token_service_ios_delegate.mm b/chromium/components/signin/ios/browser/profile_oauth2_token_service_ios_delegate.mm index 49606f24e79..57b10f8d544 100644 --- a/chromium/components/signin/ios/browser/profile_oauth2_token_service_ios_delegate.mm +++ b/chromium/components/signin/ios/browser/profile_oauth2_token_service_ios_delegate.mm @@ -27,6 +27,10 @@ #include "google_apis/gaia/oauth2_access_token_fetcher.h" #include "net/url_request/url_request_status.h" +#if !defined(__has_feature) || !__has_feature(objc_arc) +#error "This file requires ARC support." +#endif + namespace { // Match the way Chromium handles authentication errors in diff --git a/chromium/components/signin/ios/browser/profile_oauth2_token_service_ios_delegate_unittest.mm b/chromium/components/signin/ios/browser/profile_oauth2_token_service_ios_delegate_unittest.mm index a4043b3f022..ecfdd2c1a79 100644 --- a/chromium/components/signin/ios/browser/profile_oauth2_token_service_ios_delegate_unittest.mm +++ b/chromium/components/signin/ios/browser/profile_oauth2_token_service_ios_delegate_unittest.mm @@ -20,6 +20,10 @@ #include "net/url_request/test_url_fetcher_factory.h" #include "testing/gtest/include/gtest/gtest.h" +#if !defined(__has_feature) || !__has_feature(objc_arc) +#error "This file requires ARC support." +#endif + typedef ProfileOAuth2TokenServiceIOSProvider::AccountInfo ProviderAccount; class ProfileOAuth2TokenServiceIOSDelegateTest diff --git a/chromium/components/signin/ios/browser/profile_oauth2_token_service_ios_provider.mm b/chromium/components/signin/ios/browser/profile_oauth2_token_service_ios_provider.mm index 4144c6f2ec7..0ddcca0b5fa 100644 --- a/chromium/components/signin/ios/browser/profile_oauth2_token_service_ios_provider.mm +++ b/chromium/components/signin/ios/browser/profile_oauth2_token_service_ios_provider.mm @@ -4,6 +4,10 @@ #include "components/signin/ios/browser/profile_oauth2_token_service_ios_provider.h" +#if !defined(__has_feature) || !__has_feature(objc_arc) +#error "This file requires ARC support." +#endif + std::vector<ProfileOAuth2TokenServiceIOSProvider::AccountInfo> ProfileOAuth2TokenServiceIOSProvider::GetAllAccounts() const { return std::vector<ProfileOAuth2TokenServiceIOSProvider::AccountInfo>(); |