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

Side by Side Diff: chrome/browser/ui/auto_login_prompter.cc

Issue 10690006: Upstream changes needed by Android auto-login. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Address Nico's comments Created 8 years, 5 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 | Annotate | Revision Log
OLDNEW
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2012 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/ui/auto_login_prompter.h" 5 #include "chrome/browser/ui/auto_login_prompter.h"
6 6
7 #include "base/bind.h" 7 #include "base/bind.h"
8 #include "base/command_line.h" 8 #include "base/command_line.h"
9 #include "base/logging.h" 9 #include "base/logging.h"
10 #include "base/string_split.h" 10 #include "base/string_split.h"
(...skipping 21 matching lines...) Expand all
32 #include "content/public/browser/notification_types.h" 32 #include "content/public/browser/notification_types.h"
33 #include "content/public/browser/web_contents.h" 33 #include "content/public/browser/web_contents.h"
34 #include "googleurl/src/gurl.h" 34 #include "googleurl/src/gurl.h"
35 #include "net/base/escape.h" 35 #include "net/base/escape.h"
36 #include "net/url_request/url_request.h" 36 #include "net/url_request/url_request.h"
37 37
38 using content::BrowserThread; 38 using content::BrowserThread;
39 using content::NavigationController; 39 using content::NavigationController;
40 using content::WebContents; 40 using content::WebContents;
41 41
42 namespace {
43
44 bool FetchUsername(Profile* profile, std::string* output) {
45 // In an incognito window, there may not be a profile sync service and/or
46 // signin manager.
47 if (!ProfileSyncServiceFactory::GetInstance()->HasProfileSyncService(
48 profile)) {
49 return false;
50 }
51
52 if (!TokenServiceFactory::GetForProfile(profile)->AreCredentialsValid())
53 return false;
54
55 SigninManager* signin_manager =
56 SigninManagerFactory::GetInstance()->GetForProfile(profile);
57 if (!signin_manager)
58 return false;
59
60 *output = signin_manager->GetAuthenticatedUsername();
61 return true;
62 }
63
64 } // namespace
65
66 AutoLoginPrompter::Params::Params() {}
67 AutoLoginPrompter::Params::~Params() {}
68
42 AutoLoginPrompter::AutoLoginPrompter( 69 AutoLoginPrompter::AutoLoginPrompter(
43 WebContents* web_contents, 70 WebContents* web_contents,
44 const std::string& username, 71 const Params& params)
45 const std::string& args)
46 : web_contents_(web_contents), 72 : web_contents_(web_contents),
47 username_(username), 73 params_(params) {
48 args_(args) {
49 registrar_.Add(this, content::NOTIFICATION_LOAD_STOP, 74 registrar_.Add(this, content::NOTIFICATION_LOAD_STOP,
50 content::Source<NavigationController>( 75 content::Source<NavigationController>(
51 &web_contents_->GetController())); 76 &web_contents_->GetController()));
52 registrar_.Add(this, content::NOTIFICATION_WEB_CONTENTS_DESTROYED, 77 registrar_.Add(this, content::NOTIFICATION_WEB_CONTENTS_DESTROYED,
53 content::Source<WebContents>(web_contents_)); 78 content::Source<WebContents>(web_contents_));
54 } 79 }
55 80
56 AutoLoginPrompter::~AutoLoginPrompter() { 81 AutoLoginPrompter::~AutoLoginPrompter() {
57 } 82 }
58 83
59 // static 84 // static
60 void AutoLoginPrompter::ShowInfoBarIfPossible(net::URLRequest* request, 85 void AutoLoginPrompter::ShowInfoBarIfPossible(net::URLRequest* request,
61 int child_id, 86 int child_id,
62 int route_id) { 87 int route_id) {
63 if (!CommandLine::ForCurrentProcess()->HasSwitch(switches::kEnableAutologin)) 88 if (!CommandLine::ForCurrentProcess()->HasSwitch(switches::kEnableAutologin))
64 return; 89 return;
65 90
66 // See if the response contains the X-Auto-Login header. If so, this was 91 // See if the response contains the X-Auto-Login header. If so, this was
67 // a request for a login page, and the server is allowing the browser to 92 // a request for a login page, and the server is allowing the browser to
68 // suggest auto-login, if available. 93 // suggest auto-login, if available.
69 std::string value; 94 std::string value;
70 request->GetResponseHeaderByName("X-Auto-Login", &value); 95 request->GetResponseHeaderByName("X-Auto-Login", &value);
71 if (value.empty()) 96 Params params;
72 return; 97 if (!ParseAutoLoginHeader(value, &params))
73
74 std::vector<std::pair<std::string, std::string> > pairs;
75 if (!base::SplitStringIntoKeyValuePairs(value, '=', '&', &pairs))
76 return;
77
78 // Parse the information from the value string.
79 std::string realm;
80 std::string account;
81 std::string args;
82 for (size_t i = 0; i < pairs.size(); ++i) {
83 const std::pair<std::string, std::string>& pair = pairs[i];
84 if (pair.first == "realm") {
85 realm = net::UnescapeURLComponent(pair.second,
86 net::UnescapeRule::URL_SPECIAL_CHARS);
87 } else if (pair.first == "account") {
88 account = net::UnescapeURLComponent(pair.second,
89 net::UnescapeRule::URL_SPECIAL_CHARS);
90 } else if (pair.first == "args") {
91 args = pair.second;
92 }
93 }
94
95 // Currently we only accept GAIA credentials.
96 if (realm != "com.google")
97 return; 98 return;
98 99
99 BrowserThread::PostTask( 100 BrowserThread::PostTask(
100 BrowserThread::UI, FROM_HERE, 101 BrowserThread::UI, FROM_HERE,
101 base::Bind(&AutoLoginPrompter::ShowInfoBarUIThread, account, args, 102 base::Bind(&ShowInfoBarUIThread,
102 request->url(), child_id, route_id)); 103 params, request->url(), child_id, route_id));
103 } 104 }
104 105
105 // static 106 // static
106 void AutoLoginPrompter::ShowInfoBarUIThread(const std::string& account, 107 void AutoLoginPrompter::ShowInfoBarUIThread(const Params& params,
107 const std::string& args,
108 const GURL& url, 108 const GURL& url,
109 int child_id, 109 int child_id,
110 int route_id) { 110 int route_id) {
111 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 111 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
112
113 WebContents* web_contents = tab_util::GetWebContentsByID(child_id, route_id); 112 WebContents* web_contents = tab_util::GetWebContentsByID(child_id, route_id);
114 if (!web_contents) 113 if (!web_contents)
115 return; 114 return;
116 115
117 Profile* profile = 116 Profile* profile =
118 Profile::FromBrowserContext(web_contents->GetBrowserContext()); 117 Profile::FromBrowserContext(web_contents->GetBrowserContext());
119 118
120 if (!profile->GetPrefs()->GetBoolean(prefs::kAutologinEnabled)) 119 if (!profile->GetPrefs()->GetBoolean(prefs::kAutologinEnabled))
121 return; 120 return;
122 121
123 // In an incognito window, there may not be a profile sync service and/or 122 Params params_copy(params);
Peter Kasting 2012/06/27 17:39:05 Nit: Why not pass this in by value?
Philippe 2012/06/28 09:24:00 Done.
124 // signin manager. 123 #if !defined(OS_ANDROID)
125 if (!ProfileSyncServiceFactory::GetInstance()->HasProfileSyncService( 124 // On Android, the username is fetched later from the AccountManager on the
Peter Kasting 2012/06/27 17:39:05 Nit: What does "later" mean? This function must b
Philippe 2012/06/28 09:24:00 I removed 'later' and made the comment clearer (I
126 profile)) { 125 // Java side.
126 if (!FetchUsername(profile, &params_copy.username))
127 return; 127 return;
128 } 128 #endif
129
130 if (!TokenServiceFactory::GetForProfile(profile)->AreCredentialsValid())
131 return;
132
133 SigninManager* signin_manager =
134 SigninManagerFactory::GetInstance()->GetForProfile(profile);
135 if (!signin_manager)
136 return;
137
138 const std::string& username = signin_manager->GetAuthenticatedUsername();
139 129
140 // Make sure that |account|, if specified, matches the logged in user. 130 // Make sure that |account|, if specified, matches the logged in user.
141 // However, |account| is usually empty. 131 // However, |account| is usually empty.
142 if (!account.empty() && (username != account)) 132 if (!params.username.empty() && !params.account.empty() &&
133 params_copy.username != params.account) {
Peter Kasting 2012/06/27 17:39:05 Nit: {} not needed
Philippe 2012/06/28 09:24:00 Done.
143 return; 134 return;
144 135 }
145 // We can't add the infobar just yet, since we need to wait for the tab to 136 // We can't add the infobar just yet, since we need to wait for the tab to
146 // finish loading. If we don't, the info bar appears and then disappears 137 // finish loading. If we don't, the info bar appears and then disappears
147 // immediately. Create an AutoLoginPrompter instance to listen for the 138 // immediately. Create an AutoLoginPrompter instance to listen for the
148 // relevant notifications; it will delete itself. 139 // relevant notifications; it will delete itself.
149 new AutoLoginPrompter(web_contents, username, args); 140 new AutoLoginPrompter(web_contents, params_copy);
150 } 141 }
151 142
152 void AutoLoginPrompter::Observe(int type, 143 void AutoLoginPrompter::Observe(int type,
153 const content::NotificationSource& source, 144 const content::NotificationSource& source,
154 const content::NotificationDetails& details) { 145 const content::NotificationDetails& details) {
155 if (type == content::NOTIFICATION_LOAD_STOP) { 146 if (type == content::NOTIFICATION_LOAD_STOP) {
156 TabContents* tab_contents = TabContents::FromWebContents(web_contents_); 147 TabContents* tab_contents = TabContents::FromWebContents(web_contents_);
157 // |tab_contents| is NULL for WebContents hosted in WebDialog. 148 // |tab_contents| is NULL for WebContents hosted in WebDialog.
158 if (tab_contents) { 149 if (tab_contents) {
159 InfoBarTabHelper* infobar_helper = tab_contents->infobar_tab_helper(); 150 InfoBarTabHelper* infobar_helper = tab_contents->infobar_tab_helper();
160 infobar_helper->AddInfoBar(new AutoLoginInfoBarDelegate(infobar_helper, 151 infobar_helper->AddInfoBar(new AutoLoginInfoBarDelegate(
161 username_, 152 infobar_helper,
Peter Kasting 2012/06/27 17:39:05 Nit: Strange wrapping. Put more args on this line
Philippe 2012/06/28 09:24:00 Done.
162 args_)); 153 params_.realm, params_.account, params_.args, params_.username));
163 } 154 }
164 } 155 }
165 // Either we couldn't add the infobar, we added the infobar, or the tab 156 // Either we couldn't add the infobar, we added the infobar, or the tab
166 // contents was destroyed before the navigation completed. In any case 157 // contents was destroyed before the navigation completed. In any case
167 // there's no reason to live further. 158 // there's no reason to live further.
168 delete this; 159 delete this;
169 } 160 }
161
162 // static
163 bool AutoLoginPrompter::ParseAutoLoginHeader(const std::string& input,
164 Params* output) {
165 // TODO(pliard): Investigate/fix potential internationalization issue. It
166 // seems that "account" from the x-auto-login header might contain non-ASCII
167 // characters.
168 if (input.empty())
169 return false;
170
171 std::vector<std::pair<std::string, std::string> > pairs;
172 if (!base::SplitStringIntoKeyValuePairs(input, '=', '&', &pairs))
173 return false;
174
175 // Parse the information from the |input| string.
176 Params params;
177 for (size_t i = 0; i < pairs.size(); ++i) {
178 const std::pair<std::string, std::string>& pair = pairs[i];
179 if (pair.first == "realm") {
180 params.realm = net::UnescapeURLComponent(
181 pair.second, net::UnescapeRule::URL_SPECIAL_CHARS);
182 // Currently we only accept GAIA credentials.
183 if (params.realm != "com.google")
184 return false;
185 } else if (pair.first == "account") {
186 params.account = net::UnescapeURLComponent(
187 pair.second, net::UnescapeRule::URL_SPECIAL_CHARS);
188 } else if (pair.first == "args") {
189 params.args = net::UnescapeURLComponent(
190 pair.second, net::UnescapeRule::URL_SPECIAL_CHARS);
191 }
192 }
193 if (params.realm.empty() || params.args.empty())
194 return false;
195
196 *output = params;
197 return true;
198 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698