| 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" |  | 
|   14 #include "components/content_settings/core/browser/cookie_settings.h" |   12 #include "components/content_settings/core/browser/cookie_settings.h" | 
|   15 #include "components/google/core/browser/google_util.h" |   13 #include "components/google/core/browser/google_util.h" | 
|   16 #include "components/signin/core/browser/chrome_connected_header_helper.h" |   14 #include "components/signin/core/browser/chrome_connected_header_helper.h" | 
|   17 #include "components/signin/core/common/profile_management_switches.h" |   15 #include "components/signin/core/common/profile_management_switches.h" | 
|   18 #include "google_apis/gaia/gaia_auth_util.h" |   16 #include "google_apis/gaia/gaia_auth_util.h" | 
|   19 #include "google_apis/gaia/gaia_urls.h" |   17 #include "google_apis/gaia/gaia_urls.h" | 
|   20 #include "net/base/escape.h" |   18 #include "net/base/escape.h" | 
|   21 #include "net/http/http_response_headers.h" |  | 
|   22 #include "net/url_request/url_request.h" |   19 #include "net/url_request/url_request.h" | 
|   23 #include "url/gurl.h" |   20 #include "url/gurl.h" | 
|   24  |   21  | 
|   25 #if !defined(OS_IOS) && !defined(OS_ANDROID) |   22 #if !defined(OS_IOS) && !defined(OS_ANDROID) | 
|   26 #include "components/signin/core/browser/dice_header_helper.h" |   23 #include "components/signin/core/browser/dice_header_helper.h" | 
|   27 #endif |   24 #endif | 
|   28  |   25  | 
|   29 namespace signin { |   26 namespace signin { | 
|   30  |   27  | 
|   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"; |   28 extern const char kChromeConnectedHeader[] = "X-Chrome-Connected"; | 
|   85 extern const char kDiceRequestHeader[] = "X-Chrome-ID-Consistency-Request"; |   29 extern const char kDiceRequestHeader[] = "X-Chrome-ID-Consistency-Request"; | 
|   86  |   30  | 
|   87 ManageAccountsParams::ManageAccountsParams() |   31 ManageAccountsParams::ManageAccountsParams() | 
|   88     : service_type(GAIA_SERVICE_TYPE_NONE), |   32     : service_type(GAIA_SERVICE_TYPE_NONE), | 
|   89       email(""), |   33       email(""), | 
|   90       is_saml(false), |   34       is_saml(false), | 
|   91       continue_url(""), |   35       continue_url(""), | 
|   92       is_same_tab(false) { |   36       is_same_tab(false) { | 
|   93 #if !defined(OS_IOS) |   37 #if !defined(OS_IOS) | 
| (...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
|  138         IsUrlEligibleForRequestHeader(request->url()) && |   82         IsUrlEligibleForRequestHeader(request->url()) && | 
|  139         !IsUrlEligibleForRequestHeader(redirect_url)) { |   83         !IsUrlEligibleForRequestHeader(redirect_url)) { | 
|  140       request->RemoveRequestHeaderByName(header_name); |   84       request->RemoveRequestHeaderByName(header_name); | 
|  141     } |   85     } | 
|  142     return false; |   86     return false; | 
|  143   } |   87   } | 
|  144   request->SetExtraRequestHeaderByName(header_name, header_value, false); |   88   request->SetExtraRequestHeaderByName(header_name, header_value, false); | 
|  145   return true; |   89   return true; | 
|  146 } |   90 } | 
|  147  |   91  | 
 |   92 // static | 
 |   93 SigninHeaderHelper::ResponseHeaderDictionary | 
 |   94 SigninHeaderHelper::ParseAccountConsistencyResponseHeader( | 
 |   95     const std::string& header_value) { | 
 |   96   ResponseHeaderDictionary dictionary; | 
 |   97   for (const base::StringPiece& field : | 
 |   98        base::SplitStringPiece(header_value, ",", base::KEEP_WHITESPACE, | 
 |   99                               base::SPLIT_WANT_NONEMPTY)) { | 
 |  100     size_t delim = field.find_first_of('='); | 
 |  101     if (delim == std::string::npos) { | 
 |  102       DLOG(WARNING) << "Unexpected Gaia header field '" << field << "'."; | 
 |  103       continue; | 
 |  104     } | 
 |  105     dictionary[field.substr(0, delim).as_string()] = net::UnescapeURLComponent( | 
 |  106         field.substr(delim + 1).as_string(), | 
 |  107         net::UnescapeRule::PATH_SEPARATORS | | 
 |  108             net::UnescapeRule::URL_SPECIAL_CHARS_EXCEPT_PATH_SEPARATORS); | 
 |  109   } | 
 |  110   return dictionary; | 
 |  111 } | 
 |  112  | 
|  148 std::string SigninHeaderHelper::BuildRequestHeaderIfPossible( |  113 std::string SigninHeaderHelper::BuildRequestHeaderIfPossible( | 
|  149     bool is_header_request, |  114     bool is_header_request, | 
|  150     const GURL& url, |  115     const GURL& url, | 
|  151     const std::string& account_id, |  116     const std::string& account_id, | 
|  152     const content_settings::CookieSettings* cookie_settings, |  117     const content_settings::CookieSettings* cookie_settings, | 
|  153     int profile_mode_mask) { |  118     int profile_mode_mask) { | 
|  154   // If signin cookies are not allowed, don't add the header. |  119   // If signin cookies are not allowed, don't add the header. | 
|  155   if (!SettingsAllowSigninCookies(cookie_settings)) |  120   if (!SettingsAllowSigninCookies(cookie_settings)) | 
|  156     return std::string(); |  121     return std::string(); | 
|  157  |  122  | 
| (...skipping 20 matching lines...) Expand all  Loading... | 
|  178 #endif |  143 #endif | 
|  179  |  144  | 
|  180   ChromeConnectedHeaderHelper chrome_connected_helper; |  145   ChromeConnectedHeaderHelper chrome_connected_helper; | 
|  181   chrome_connected_helper.AppendOrRemoveRequestHeader( |  146   chrome_connected_helper.AppendOrRemoveRequestHeader( | 
|  182       request, kChromeConnectedHeader, redirect_url, account_id, |  147       request, kChromeConnectedHeader, redirect_url, account_id, | 
|  183       cookie_settings, profile_mode_mask); |  148       cookie_settings, profile_mode_mask); | 
|  184 } |  149 } | 
|  185  |  150  | 
|  186 ManageAccountsParams BuildManageAccountsParams( |  151 ManageAccountsParams BuildManageAccountsParams( | 
|  187     const std::string& header_value) { |  152     const std::string& header_value) { | 
|  188   ManageAccountsParams params; |  153   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); |  | 
|  228   return BuildManageAccountsParams(header_value); |  | 
|  229 } |  154 } | 
|  230  |  155  | 
|  231 }  // namespace signin |  156 }  // namespace signin | 
| OLD | NEW |