Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(15)

Side by Side Diff: chrome/browser/signin/signin_header_helper.cc

Issue 315773002: Parse the mirror response header. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Compile Created 6 years, 6 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « chrome/browser/signin/signin_header_helper.h ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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 "chrome/browser/signin/signin_header_helper.h" 5 #include "chrome/browser/signin/signin_header_helper.h"
6 6
7 #include "base/strings/string_number_conversions.h" 7 #include "base/strings/string_number_conversions.h"
8 #include "base/strings/string_util.h"
8 #include "base/strings/stringprintf.h" 9 #include "base/strings/stringprintf.h"
9 #include "chrome/browser/google/google_util.h" 10 #include "chrome/browser/google/google_util.h"
10 #include "chrome/browser/prefs/incognito_mode_prefs.h" 11 #include "chrome/browser/prefs/incognito_mode_prefs.h"
11 #include "chrome/browser/profiles/profile_io_data.h" 12 #include "chrome/browser/profiles/profile_io_data.h"
12 #include "chrome/browser/tab_contents/tab_util.h" 13 #include "chrome/browser/tab_contents/tab_util.h"
13 #include "chrome/browser/ui/browser_window.h" 14 #include "chrome/browser/ui/browser_window.h"
14 #include "chrome/common/url_constants.h" 15 #include "chrome/common/url_constants.h"
15 #include "components/signin/core/common/profile_management_switches.h" 16 #include "components/signin/core/common/profile_management_switches.h"
16 #include "content/public/browser/browser_thread.h" 17 #include "content/public/browser/browser_thread.h"
17 #include "content/public/browser/web_contents.h" 18 #include "content/public/browser/web_contents.h"
18 #include "google_apis/gaia/gaia_auth_util.h" 19 #include "google_apis/gaia/gaia_auth_util.h"
19 #include "net/http/http_response_headers.h" 20 #include "net/http/http_response_headers.h"
20 #include "net/url_request/url_request.h" 21 #include "net/url_request/url_request.h"
21 22
22 #if defined(OS_ANDROID) 23 #if defined(OS_ANDROID)
23 #include "chrome/browser/android/signin/account_management_screen_helper.h" 24 #include "chrome/browser/android/signin/account_management_screen_helper.h"
24 #else 25 #else
25 #include "chrome/browser/ui/browser_commands.h" 26 #include "chrome/browser/ui/browser_commands.h"
26 #include "chrome/browser/ui/browser_finder.h" 27 #include "chrome/browser/ui/browser_finder.h"
27 #endif // defined(OS_ANDROID) 28 #endif // defined(OS_ANDROID)
28 29
29 namespace { 30 namespace {
30 31
32 // Dictionary of fields in a mirror response header.
33 typedef std::map<std::string, std::string> MirrorResponseHeaderDictionary;
34
31 const char kChromeConnectedHeader[] = "X-Chrome-Connected"; 35 const char kChromeConnectedHeader[] = "X-Chrome-Connected";
32 const char kChromeManageAccountsHeader[] = "X-Chrome-Manage-Accounts"; 36 const char kChromeManageAccountsHeader[] = "X-Chrome-Manage-Accounts";
33 const char kGaiaIdAttrName[] = "id"; 37 const char kGaiaIdAttrName[] = "id";
34 const char kProfileModeAttrName[] = "mode"; 38 const char kProfileModeAttrName[] = "mode";
35 const char kEnableAccountConsistencyAttrName[] = "enable_account_consistency"; 39 const char kEnableAccountConsistencyAttrName[] = "enable_account_consistency";
36 40
37 // Determine the service type that has been passed from GAIA in the header. 41 // Determines the service type that has been passed from GAIA in the header.
38 signin::GAIAServiceType GetGAIAServiceTypeFromHeader( 42 signin::GAIAServiceType GetGAIAServiceTypeFromHeader(
39 const std::string& header_value) { 43 const std::string& header_value) {
40 if (header_value == "SIGNOUT") 44 if (header_value == "SIGNOUT")
41 return signin::GAIA_SERVICE_TYPE_SIGNOUT; 45 return signin::GAIA_SERVICE_TYPE_SIGNOUT;
42 else if (header_value == "INCOGNITO") 46 else if (header_value == "INCOGNITO")
43 return signin::GAIA_SERVICE_TYPE_INCOGNITO; 47 return signin::GAIA_SERVICE_TYPE_INCOGNITO;
44 else if (header_value == "ADDSESSION") 48 else if (header_value == "ADDSESSION")
45 return signin::GAIA_SERVICE_TYPE_ADDSESSION; 49 return signin::GAIA_SERVICE_TYPE_ADDSESSION;
46 else if (header_value == "REAUTH") 50 else if (header_value == "REAUTH")
47 return signin::GAIA_SERVICE_TYPE_REAUTH; 51 return signin::GAIA_SERVICE_TYPE_REAUTH;
48 else if (header_value == "DEFAULT") 52 else if (header_value == "DEFAULT")
49 return signin::GAIA_SERVICE_TYPE_DEFAULT; 53 return signin::GAIA_SERVICE_TYPE_DEFAULT;
50 else 54 else
51 return signin::GAIA_SERVICE_TYPE_NONE; 55 return signin::GAIA_SERVICE_TYPE_NONE;
52 } 56 }
53 57
58 // Parses the mirror response header. Its expected format is
59 // "key1=value1,key2=value2,...".
60 MirrorResponseHeaderDictionary ParseMirrorResponseHeader(
61 const std::string& header_value) {
62 std::vector<std::string> fields;
63 if (!Tokenize(header_value, std::string(","), &fields))
64 return MirrorResponseHeaderDictionary();
65
66 MirrorResponseHeaderDictionary dictionary;
67 for (std::vector<std::string>::iterator i = fields.begin();
68 i != fields.end(); ++i) {
69 std::string field(*i);
70 std::vector<std::string> tokens;
71 if (Tokenize(field, "=", &tokens) != 2) {
72 DLOG(WARNING) << "Unexpected GAIA header filed '" << field << "'.";
73 continue;
74 }
75 dictionary[tokens[0]] = tokens[1];
76 }
77 return dictionary;
78 }
79
80 #if !defined(OS_IOS)
54 // Processes the mirror response header on the UI thread. Currently depending 81 // Processes the mirror response header on the UI thread. Currently depending
55 // on the value of |header_value|, it either shows the profile avatar menu, or 82 // on the value of |header_value|, it either shows the profile avatar menu, or
56 // opens an incognito window/tab. 83 // opens an incognito window/tab.
57 void ProcessMirrorHeaderUIThread( 84 void ProcessMirrorHeaderUIThread(
58 int child_id, int route_id, const std::string& header_value) { 85 int child_id, int route_id,
86 signin::ManageAccountsParams manage_accounts_params) {
59 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)); 87 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
60 88
89 signin::GAIAServiceType service_type = manage_accounts_params.service_type;
90 DCHECK_NE(signin::GAIA_SERVICE_TYPE_NONE, service_type);
91
61 content::WebContents* web_contents = 92 content::WebContents* web_contents =
62 tab_util::GetWebContentsByID(child_id, route_id); 93 tab_util::GetWebContentsByID(child_id, route_id);
63 if (!web_contents) 94 if (!web_contents)
64 return; 95 return;
65 96
66 signin::GAIAServiceType service_type =
67 GetGAIAServiceTypeFromHeader(header_value);
68
69 #if !defined(OS_ANDROID) 97 #if !defined(OS_ANDROID)
70 Browser* browser = chrome::FindBrowserWithWebContents(web_contents); 98 Browser* browser = chrome::FindBrowserWithWebContents(web_contents);
71 if (browser) { 99 if (browser) {
72 if (service_type == signin::GAIA_SERVICE_TYPE_INCOGNITO) { 100 if (service_type == signin::GAIA_SERVICE_TYPE_INCOGNITO) {
73 chrome::NewIncognitoWindow(browser); 101 chrome::NewIncognitoWindow(browser);
74 } else { 102 } else {
75 browser->window()->ShowAvatarBubbleFromAvatarButton( 103 browser->window()->ShowAvatarBubbleFromAvatarButton(
76 BrowserWindow::AVATAR_BUBBLE_MODE_ACCOUNT_MANAGEMENT, 104 BrowserWindow::AVATAR_BUBBLE_MODE_ACCOUNT_MANAGEMENT,
77 service_type); 105 service_type);
78 } 106 }
79 } 107 }
80 #else // defined(OS_ANDROID) 108 #else // defined(OS_ANDROID)
81 if (service_type == signin::GAIA_SERVICE_TYPE_INCOGNITO) { 109 if (service_type == signin::GAIA_SERVICE_TYPE_INCOGNITO) {
82 web_contents->OpenURL(content::OpenURLParams( 110 web_contents->OpenURL(content::OpenURLParams(
83 GURL(chrome::kChromeUINativeNewTabURL), content::Referrer(), 111 GURL(chrome::kChromeUINativeNewTabURL), content::Referrer(),
84 OFF_THE_RECORD, content::PAGE_TRANSITION_AUTO_TOPLEVEL, false)); 112 OFF_THE_RECORD, content::PAGE_TRANSITION_AUTO_TOPLEVEL, false));
85 } else { 113 } else {
86 AccountManagementScreenHelper::OpenAccountManagementScreen( 114 AccountManagementScreenHelper::OpenAccountManagementScreen(
87 Profile::FromBrowserContext(web_contents->GetBrowserContext()), 115 Profile::FromBrowserContext(web_contents->GetBrowserContext()),
88 service_type); 116 service_type);
89 } 117 }
90 #endif // OS_ANDROID 118 #endif // OS_ANDROID
91 } 119 }
120 #endif // !defined(OS_IOS)
92 121
93 bool IsDriveOrigin(const GURL& url) { 122 bool IsDriveOrigin(const GURL& url) {
94 if (!url.SchemeIsSecure()) 123 if (!url.SchemeIsSecure())
95 return false; 124 return false;
96 125
97 const GURL kGoogleDriveURL("https://drive.google.com"); 126 const GURL kGoogleDriveURL("https://drive.google.com");
98 const GURL kGoogleDocsURL("https://docs.google.com"); 127 const GURL kGoogleDocsURL("https://docs.google.com");
99 return url == kGoogleDriveURL || url == kGoogleDocsURL; 128 return url == kGoogleDriveURL || url == kGoogleDocsURL;
100 } 129 }
101 130
102 } // empty namespace 131 } // empty namespace
103 132
104 namespace signin { 133 namespace signin {
105 134
106 void AppendMirrorRequestHeaderIfPossible( 135 bool AppendMirrorRequestHeaderIfPossible(
107 net::URLRequest* request, 136 net::URLRequest* request,
108 const GURL& redirect_url, 137 const GURL& redirect_url,
109 ProfileIOData* io_data, 138 ProfileIOData* io_data,
110 int child_id, 139 int child_id,
111 int route_id) { 140 int route_id) {
112 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::IO)); 141 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::IO));
113 142
114 if (io_data->IsOffTheRecord() || 143 if (io_data->IsOffTheRecord() ||
115 io_data->google_services_username()->GetValue().empty()) { 144 io_data->google_services_username()->GetValue().empty()) {
116 return; 145 return false;
117 } 146 }
118 147
119 // Only set the header for Drive always, and other Google properties if 148 // Only set the header for Drive always, and other Google properties if
120 // new-profile-management is enabled. 149 // new-profile-management is enabled.
121 // Vasquette, which is integrated with most Google properties, needs the 150 // Vasquette, which is integrated with most Google properties, needs the
122 // header to redirect certain user actions to Chrome native UI. Drive needs 151 // header to redirect certain user actions to Chrome native UI. Drive needs
123 // the header to tell if the current user is connected. The drive path is a 152 // the header to tell if the current user is connected. The drive path is a
124 // temporary workaround until the more generic chrome.principals API is 153 // temporary workaround until the more generic chrome.principals API is
125 // available. 154 // available.
126 const GURL& url = redirect_url.is_empty() ? request->url() : redirect_url; 155 const GURL& url = redirect_url.is_empty() ? request->url() : redirect_url;
127 GURL origin(url.GetOrigin()); 156 GURL origin(url.GetOrigin());
128 bool is_new_profile_management = switches::IsNewProfileManagement(); 157 bool is_new_profile_management = switches::IsNewProfileManagement();
129 bool is_google_url = 158 bool is_google_url =
130 !switches::IsEnableWebBasedSignin() && 159 !switches::IsEnableWebBasedSignin() &&
131 is_new_profile_management && 160 is_new_profile_management &&
132 google_util::IsGoogleDomainUrl( 161 google_util::IsGoogleDomainUrl(
133 url, 162 url,
134 google_util::ALLOW_SUBDOMAIN, 163 google_util::ALLOW_SUBDOMAIN,
135 google_util::DISALLOW_NON_STANDARD_PORTS); 164 google_util::DISALLOW_NON_STANDARD_PORTS);
136 if (!is_google_url && !IsDriveOrigin(origin)) 165 if (!is_google_url && !IsDriveOrigin(origin))
137 return; 166 return false;
138 167
139 std::string account_id(io_data->google_services_account_id()->GetValue()); 168 std::string account_id(io_data->google_services_account_id()->GetValue());
140 169
141 int profile_mode_mask = PROFILE_MODE_DEFAULT; 170 int profile_mode_mask = PROFILE_MODE_DEFAULT;
142 // TODO(guohui): Needs to check for parent control as well. 171 // TODO(guohui): Needs to check for parent control as well.
143 if (io_data->incognito_availibility()->GetValue() == 172 if (io_data->incognito_availibility()->GetValue() ==
144 IncognitoModePrefs::DISABLED) { 173 IncognitoModePrefs::DISABLED) {
145 profile_mode_mask |= PROFILE_MODE_INCOGNITO_DISABLED; 174 profile_mode_mask |= PROFILE_MODE_INCOGNITO_DISABLED;
146 } 175 }
147 176
148 // TODO(guohui): needs to make a new flag for enabling account consistency. 177 // TODO(guohui): needs to make a new flag for enabling account consistency.
149 std::string header_value(base::StringPrintf("%s=%s,%s=%s,%s=%s", 178 std::string header_value(base::StringPrintf("%s=%s,%s=%s,%s=%s",
150 kGaiaIdAttrName, account_id.c_str(), 179 kGaiaIdAttrName, account_id.c_str(),
151 kProfileModeAttrName, base::IntToString(profile_mode_mask).c_str(), 180 kProfileModeAttrName, base::IntToString(profile_mode_mask).c_str(),
152 kEnableAccountConsistencyAttrName, 181 kEnableAccountConsistencyAttrName,
153 is_new_profile_management ? "true" : "false")); 182 is_new_profile_management ? "true" : "false"));
154 request->SetExtraRequestHeaderByName( 183 request->SetExtraRequestHeaderByName(
155 kChromeConnectedHeader, header_value, false); 184 kChromeConnectedHeader, header_value, false);
185 return true;
186 }
187
188 ManageAccountsParams GetManageAccountsParams(net::URLRequest* request,
189 ProfileIOData* io_data) {
190 ManageAccountsParams params;
191 params.service_type = GAIA_SERVICE_TYPE_NONE;
192 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::IO));
193 if (!gaia::IsGaiaSignonRealm(request->url().GetOrigin()))
194 return params;
195
196 std::string header_value;
197 if (!request->response_headers()->GetNormalizedHeader(
198 kChromeManageAccountsHeader, &header_value)) {
199 return params;
200 }
201
202 DCHECK(switches::IsNewProfileManagement() && !io_data->IsOffTheRecord());
203
204 MirrorResponseHeaderDictionary header_dictionary =
205 ParseMirrorResponseHeader(header_value);
206 if (header_dictionary.count("action")) {
207 params.service_type =
208 GetGAIAServiceTypeFromHeader(header_dictionary["action"]);
209 }
210 return params;
156 } 211 }
157 212
158 void ProcessMirrorResponseHeaderIfExists( 213 void ProcessMirrorResponseHeaderIfExists(
159 net::URLRequest* request, 214 net::URLRequest* request,
160 ProfileIOData* io_data, 215 ProfileIOData* io_data,
161 int child_id, 216 int child_id,
162 int route_id) { 217 int route_id) {
218 #if defined(OS_IOS)
219 NOTREACHED();
220 #else
163 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::IO)); 221 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::IO));
222 ManageAccountsParams params = GetManageAccountsParams(request, io_data);
223 if (params.service_type == GAIA_SERVICE_TYPE_NONE)
224 return;
164 225
165 std::string header_value; 226 content::BrowserThread::PostTask(
166 if (gaia::IsGaiaSignonRealm(request->url().GetOrigin()) && 227 content::BrowserThread::UI, FROM_HERE,
167 request->response_headers()->GetNormalizedHeader( 228 base::Bind(ProcessMirrorHeaderUIThread, child_id, route_id, params));
168 kChromeManageAccountsHeader, &header_value)) { 229 #endif // defined(OS_IOS)
169 DCHECK(switches::IsNewProfileManagement() &&
170 !io_data->IsOffTheRecord());
171 content::BrowserThread::PostTask(
172 content::BrowserThread::UI, FROM_HERE,
173 base::Bind(ProcessMirrorHeaderUIThread, child_id, route_id,
174 header_value));
175 }
176 } 230 }
177 231
178 } // namespace signin 232 } // namespace signin
OLDNEW
« no previous file with comments | « chrome/browser/signin/signin_header_helper.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698