Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright 2013 The Chromium Authors. All rights reserved. | 1 // Copyright 2013 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "components/signin/core/browser/signin_header_helper.h" | 5 #include "components/signin/core/browser/signin_header_helper.h" |
| 6 | 6 |
| 7 #include <stddef.h> | 7 #include <stddef.h> |
| 8 #include <map> | |
| 9 | 8 |
| 10 #include "base/logging.h" | 9 #include "base/logging.h" |
| 11 #include "base/macros.h" | 10 #include "base/macros.h" |
| 12 #include "base/strings/string_split.h" | 11 #include "base/strings/string_split.h" |
| 13 #include "build/build_config.h" | 12 #include "build/build_config.h" |
| 14 #include "components/content_settings/core/browser/cookie_settings.h" | 13 #include "components/content_settings/core/browser/cookie_settings.h" |
| 15 #include "components/google/core/browser/google_util.h" | 14 #include "components/google/core/browser/google_util.h" |
| 16 #include "components/signin/core/browser/chrome_connected_header_helper.h" | 15 #include "components/signin/core/browser/chrome_connected_header_helper.h" |
| 17 #include "components/signin/core/common/profile_management_switches.h" | 16 #include "components/signin/core/common/profile_management_switches.h" |
| 18 #include "google_apis/gaia/gaia_auth_util.h" | 17 #include "google_apis/gaia/gaia_auth_util.h" |
| 19 #include "google_apis/gaia/gaia_urls.h" | 18 #include "google_apis/gaia/gaia_urls.h" |
| 20 #include "net/base/escape.h" | 19 #include "net/base/escape.h" |
| 21 #include "net/http/http_response_headers.h" | |
| 22 #include "net/url_request/url_request.h" | 20 #include "net/url_request/url_request.h" |
| 23 #include "url/gurl.h" | 21 #include "url/gurl.h" |
| 24 | 22 |
| 25 #if !defined(OS_IOS) && !defined(OS_ANDROID) | 23 #if !defined(OS_IOS) && !defined(OS_ANDROID) |
| 26 #include "components/signin/core/browser/dice_header_helper.h" | 24 #include "components/signin/core/browser/dice_header_helper.h" |
| 27 #endif | 25 #endif |
| 28 | 26 |
| 29 namespace signin { | 27 namespace signin { |
| 30 | 28 |
| 31 namespace { | |
| 32 | |
| 33 // Dictionary of fields in a mirror response header. | |
| 34 typedef std::map<std::string, std::string> MirrorResponseHeaderDictionary; | |
| 35 | |
| 36 const char kChromeManageAccountsHeader[] = "X-Chrome-Manage-Accounts"; | |
| 37 const char kContinueUrlAttrName[] = "continue_url"; | |
| 38 const char kEmailAttrName[] = "email"; | |
| 39 const char kIsSameTabAttrName[] = "is_same_tab"; | |
| 40 const char kIsSamlAttrName[] = "is_saml"; | |
| 41 const char kServiceTypeAttrName[] = "action"; | |
| 42 | |
| 43 // Determines the service type that has been passed from Gaia in the header. | |
| 44 GAIAServiceType GetGAIAServiceTypeFromHeader(const std::string& header_value) { | |
| 45 if (header_value == "SIGNOUT") | |
| 46 return GAIA_SERVICE_TYPE_SIGNOUT; | |
| 47 else if (header_value == "INCOGNITO") | |
| 48 return GAIA_SERVICE_TYPE_INCOGNITO; | |
| 49 else if (header_value == "ADDSESSION") | |
| 50 return GAIA_SERVICE_TYPE_ADDSESSION; | |
| 51 else if (header_value == "REAUTH") | |
| 52 return GAIA_SERVICE_TYPE_REAUTH; | |
| 53 else if (header_value == "SIGNUP") | |
| 54 return GAIA_SERVICE_TYPE_SIGNUP; | |
| 55 else if (header_value == "DEFAULT") | |
| 56 return GAIA_SERVICE_TYPE_DEFAULT; | |
| 57 else | |
| 58 return GAIA_SERVICE_TYPE_NONE; | |
| 59 } | |
| 60 | |
| 61 // Parses the mirror response header. Its expected format is | |
| 62 // "key1=value1,key2=value2,...". | |
| 63 MirrorResponseHeaderDictionary ParseMirrorResponseHeader( | |
| 64 const std::string& header_value) { | |
| 65 MirrorResponseHeaderDictionary dictionary; | |
| 66 for (const base::StringPiece& field : | |
| 67 base::SplitStringPiece(header_value, ",", base::KEEP_WHITESPACE, | |
| 68 base::SPLIT_WANT_NONEMPTY)) { | |
| 69 size_t delim = field.find_first_of('='); | |
| 70 if (delim == std::string::npos) { | |
| 71 DLOG(WARNING) << "Unexpected Gaia header field '" << field << "'."; | |
| 72 continue; | |
| 73 } | |
| 74 dictionary[field.substr(0, delim).as_string()] = net::UnescapeURLComponent( | |
| 75 field.substr(delim + 1).as_string(), | |
| 76 net::UnescapeRule::PATH_SEPARATORS | | |
| 77 net::UnescapeRule::URL_SPECIAL_CHARS_EXCEPT_PATH_SEPARATORS); | |
| 78 } | |
| 79 return dictionary; | |
| 80 } | |
| 81 | |
| 82 } // namespace | |
| 83 | |
| 84 extern const char kChromeConnectedHeader[] = "X-Chrome-Connected"; | 29 extern const char kChromeConnectedHeader[] = "X-Chrome-Connected"; |
| 85 extern const char kDiceRequestHeader[] = "X-Chrome-ID-Consistency-Request"; | 30 extern const char kDiceRequestHeader[] = "X-Chrome-ID-Consistency-Request"; |
| 86 | 31 |
| 87 ManageAccountsParams::ManageAccountsParams() | 32 ManageAccountsParams::ManageAccountsParams() |
| 88 : service_type(GAIA_SERVICE_TYPE_NONE), | 33 : service_type(GAIA_SERVICE_TYPE_NONE), |
| 89 email(""), | 34 email(""), |
| 90 is_saml(false), | 35 is_saml(false), |
| 91 continue_url(""), | 36 continue_url(""), |
| 92 is_same_tab(false) { | 37 is_same_tab(false) { |
| 93 #if !defined(OS_IOS) | 38 #if !defined(OS_IOS) |
| (...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 138 IsUrlEligibleForRequestHeader(request->url()) && | 83 IsUrlEligibleForRequestHeader(request->url()) && |
| 139 !IsUrlEligibleForRequestHeader(redirect_url)) { | 84 !IsUrlEligibleForRequestHeader(redirect_url)) { |
| 140 request->RemoveRequestHeaderByName(header_name); | 85 request->RemoveRequestHeaderByName(header_name); |
| 141 } | 86 } |
| 142 return false; | 87 return false; |
| 143 } | 88 } |
| 144 request->SetExtraRequestHeaderByName(header_name, header_value, false); | 89 request->SetExtraRequestHeaderByName(header_name, header_value, false); |
| 145 return true; | 90 return true; |
| 146 } | 91 } |
| 147 | 92 |
| 93 // static | |
| 94 SigninHeaderHelper::ResponseHeaderDictionary | |
| 95 SigninHeaderHelper::ParseAccountConsistencyResponseHeader( | |
| 96 const std::string& header_value) { | |
| 97 ResponseHeaderDictionary dictionary; | |
| 98 for (const base::StringPiece& field : | |
| 99 base::SplitStringPiece(header_value, ",", base::KEEP_WHITESPACE, | |
| 100 base::SPLIT_WANT_NONEMPTY)) { | |
| 101 size_t delim = field.find_first_of('='); | |
| 102 if (delim == std::string::npos) { | |
| 103 DLOG(WARNING) << "Unexpected Gaia header field '" << field << "'."; | |
| 104 continue; | |
| 105 } | |
| 106 dictionary[field.substr(0, delim).as_string()] = net::UnescapeURLComponent( | |
| 107 field.substr(delim + 1).as_string(), | |
| 108 net::UnescapeRule::PATH_SEPARATORS | | |
| 109 net::UnescapeRule::URL_SPECIAL_CHARS_EXCEPT_PATH_SEPARATORS); | |
| 110 } | |
| 111 return dictionary; | |
| 112 } | |
| 113 | |
| 148 std::string SigninHeaderHelper::BuildRequestHeaderIfPossible( | 114 std::string SigninHeaderHelper::BuildRequestHeaderIfPossible( |
| 149 bool is_header_request, | 115 bool is_header_request, |
| 150 const GURL& url, | 116 const GURL& url, |
| 151 const std::string& account_id, | 117 const std::string& account_id, |
| 152 const content_settings::CookieSettings* cookie_settings, | 118 const content_settings::CookieSettings* cookie_settings, |
| 153 int profile_mode_mask) { | 119 int profile_mode_mask) { |
| 154 // If signin cookies are not allowed, don't add the header. | 120 // If signin cookies are not allowed, don't add the header. |
| 155 if (!SettingsAllowSigninCookies(cookie_settings)) | 121 if (!SettingsAllowSigninCookies(cookie_settings)) |
| 156 return std::string(); | 122 return std::string(); |
| 157 | 123 |
| (...skipping 20 matching lines...) Expand all Loading... | |
| 178 #endif | 144 #endif |
| 179 | 145 |
| 180 ChromeConnectedHeaderHelper chrome_connected_helper; | 146 ChromeConnectedHeaderHelper chrome_connected_helper; |
| 181 chrome_connected_helper.AppendOrRemoveRequestHeader( | 147 chrome_connected_helper.AppendOrRemoveRequestHeader( |
| 182 request, kChromeConnectedHeader, redirect_url, account_id, | 148 request, kChromeConnectedHeader, redirect_url, account_id, |
| 183 cookie_settings, profile_mode_mask); | 149 cookie_settings, profile_mode_mask); |
| 184 } | 150 } |
| 185 | 151 |
| 186 ManageAccountsParams BuildManageAccountsParams( | 152 ManageAccountsParams BuildManageAccountsParams( |
| 187 const std::string& header_value) { | 153 const std::string& header_value) { |
| 188 ManageAccountsParams params; | 154 return ChromeConnectedHeaderHelper::BuildManageAccountsParams(header_value); |
| 189 MirrorResponseHeaderDictionary header_dictionary = | |
| 190 ParseMirrorResponseHeader(header_value); | |
| 191 MirrorResponseHeaderDictionary::const_iterator it = header_dictionary.begin(); | |
| 192 for (; it != header_dictionary.end(); ++it) { | |
| 193 const std::string key_name(it->first); | |
| 194 if (key_name == kServiceTypeAttrName) { | |
| 195 params.service_type = | |
| 196 GetGAIAServiceTypeFromHeader(header_dictionary[kServiceTypeAttrName]); | |
| 197 } else if (key_name == kEmailAttrName) { | |
| 198 params.email = header_dictionary[kEmailAttrName]; | |
| 199 } else if (key_name == kIsSamlAttrName) { | |
| 200 params.is_saml = header_dictionary[kIsSamlAttrName] == "true"; | |
| 201 } else if (key_name == kContinueUrlAttrName) { | |
| 202 params.continue_url = header_dictionary[kContinueUrlAttrName]; | |
| 203 } else if (key_name == kIsSameTabAttrName) { | |
| 204 params.is_same_tab = header_dictionary[kIsSameTabAttrName] == "true"; | |
| 205 } else { | |
| 206 DLOG(WARNING) << "Unexpected Gaia header attribute '" << key_name << "'."; | |
| 207 } | |
| 208 } | |
| 209 return params; | |
| 210 } | |
| 211 | |
| 212 ManageAccountsParams BuildManageAccountsParamsIfExists(net::URLRequest* request, | |
| 213 bool is_off_the_record) { | |
| 214 ManageAccountsParams empty_params; | |
| 215 empty_params.service_type = GAIA_SERVICE_TYPE_NONE; | |
| 216 if (!gaia::IsGaiaSignonRealm(request->url().GetOrigin())) | |
| 217 return empty_params; | |
| 218 | |
| 219 std::string header_value; | |
| 220 net::HttpResponseHeaders* response_headers = request->response_headers(); | |
| 221 if (!response_headers || | |
| 222 !response_headers->GetNormalizedHeader( | |
| 223 kChromeManageAccountsHeader, &header_value)) { | |
| 224 return empty_params; | |
| 225 } | |
| 226 | |
| 227 DCHECK(switches::IsAccountConsistencyMirrorEnabled() && !is_off_the_record); | |
|
droger
2017/06/12 12:46:38
This is the DCHECK I am mentioning in the other co
| |
| 228 return BuildManageAccountsParams(header_value); | |
| 229 } | 155 } |
| 230 | 156 |
| 231 } // namespace signin | 157 } // namespace signin |
| OLD | NEW |