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

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: Move Params structure to auto_login_info_bar_delegate.h. 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 FetchUsernameThroughSigninManager(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
42 AutoLoginPrompter::AutoLoginPrompter( 66 AutoLoginPrompter::AutoLoginPrompter(
43 WebContents* web_contents, 67 WebContents* web_contents,
44 const std::string& username, 68 const Params& params)
45 const std::string& args)
46 : web_contents_(web_contents), 69 : web_contents_(web_contents),
47 username_(username), 70 params_(params) {
48 args_(args) {
49 registrar_.Add(this, content::NOTIFICATION_LOAD_STOP, 71 registrar_.Add(this, content::NOTIFICATION_LOAD_STOP,
50 content::Source<NavigationController>( 72 content::Source<NavigationController>(
51 &web_contents_->GetController())); 73 &web_contents_->GetController()));
52 registrar_.Add(this, content::NOTIFICATION_WEB_CONTENTS_DESTROYED, 74 registrar_.Add(this, content::NOTIFICATION_WEB_CONTENTS_DESTROYED,
53 content::Source<WebContents>(web_contents_)); 75 content::Source<WebContents>(web_contents_));
54 } 76 }
55 77
56 AutoLoginPrompter::~AutoLoginPrompter() { 78 AutoLoginPrompter::~AutoLoginPrompter() {
57 } 79 }
58 80
59 // static 81 // static
60 void AutoLoginPrompter::ShowInfoBarIfPossible(net::URLRequest* request, 82 void AutoLoginPrompter::ShowInfoBarIfPossible(net::URLRequest* request,
61 int child_id, 83 int child_id,
62 int route_id) { 84 int route_id) {
63 if (!CommandLine::ForCurrentProcess()->HasSwitch(switches::kEnableAutologin)) 85 if (!CommandLine::ForCurrentProcess()->HasSwitch(switches::kEnableAutologin))
64 return; 86 return;
65 87
66 // See if the response contains the X-Auto-Login header. If so, this was 88 // 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 89 // a request for a login page, and the server is allowing the browser to
68 // suggest auto-login, if available. 90 // suggest auto-login, if available.
69 std::string value; 91 std::string value;
70 request->GetResponseHeaderByName("X-Auto-Login", &value); 92 request->GetResponseHeaderByName("X-Auto-Login", &value);
71 if (value.empty()) 93 Params params;
72 return; 94 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; 95 return;
98 96
99 BrowserThread::PostTask( 97 BrowserThread::PostTask(
100 BrowserThread::UI, FROM_HERE, 98 BrowserThread::UI, FROM_HERE,
101 base::Bind(&AutoLoginPrompter::ShowInfoBarUIThread, account, args, 99 base::Bind(&ShowInfoBarUIThread,
102 request->url(), child_id, route_id)); 100 params, request->url(), child_id, route_id));
103 } 101 }
104 102
105 // static 103 // static
106 void AutoLoginPrompter::ShowInfoBarUIThread(const std::string& account, 104 void AutoLoginPrompter::ShowInfoBarUIThread(Params params,
107 const std::string& args,
108 const GURL& url, 105 const GURL& url,
109 int child_id, 106 int child_id,
110 int route_id) { 107 int route_id) {
111 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 108 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
112
113 WebContents* web_contents = tab_util::GetWebContentsByID(child_id, route_id); 109 WebContents* web_contents = tab_util::GetWebContentsByID(child_id, route_id);
114 if (!web_contents) 110 if (!web_contents)
115 return; 111 return;
116 112
117 Profile* profile = 113 Profile* profile =
118 Profile::FromBrowserContext(web_contents->GetBrowserContext()); 114 Profile::FromBrowserContext(web_contents->GetBrowserContext());
119 115
120 if (!profile->GetPrefs()->GetBoolean(prefs::kAutologinEnabled)) 116 if (!profile->GetPrefs()->GetBoolean(prefs::kAutologinEnabled))
121 return; 117 return;
122 118
123 // In an incognito window, there may not be a profile sync service and/or 119 #if !defined(OS_ANDROID)
124 // signin manager. 120 // On Android, the username is fetched on the Java side from the
125 if (!ProfileSyncServiceFactory::GetInstance()->HasProfileSyncService( 121 // AccountManager provided by the platform.
126 profile)) { 122 if (!FetchUsernameThroughSigninManager(profile, &params.username))
127 return; 123 return;
128 } 124 #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 125
140 // Make sure that |account|, if specified, matches the logged in user. 126 // Make sure that |account|, if specified, matches the logged in user.
141 // However, |account| is usually empty. 127 // However, |account| is usually empty.
142 if (!account.empty() && (username != account)) 128 if (!params.username.empty() && !params.account.empty() &&
129 params.username != params.account)
143 return; 130 return;
144
145 // We can't add the infobar just yet, since we need to wait for the tab to 131 // 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 132 // finish loading. If we don't, the info bar appears and then disappears
147 // immediately. Create an AutoLoginPrompter instance to listen for the 133 // immediately. Create an AutoLoginPrompter instance to listen for the
148 // relevant notifications; it will delete itself. 134 // relevant notifications; it will delete itself.
149 new AutoLoginPrompter(web_contents, username, args); 135 new AutoLoginPrompter(web_contents, params);
150 } 136 }
151 137
152 void AutoLoginPrompter::Observe(int type, 138 void AutoLoginPrompter::Observe(int type,
153 const content::NotificationSource& source, 139 const content::NotificationSource& source,
154 const content::NotificationDetails& details) { 140 const content::NotificationDetails& details) {
155 if (type == content::NOTIFICATION_LOAD_STOP) { 141 if (type == content::NOTIFICATION_LOAD_STOP) {
156 TabContents* tab_contents = TabContents::FromWebContents(web_contents_); 142 TabContents* tab_contents = TabContents::FromWebContents(web_contents_);
157 // |tab_contents| is NULL for WebContents hosted in WebDialog. 143 // |tab_contents| is NULL for WebContents hosted in WebDialog.
158 if (tab_contents) { 144 if (tab_contents) {
159 InfoBarTabHelper* infobar_helper = tab_contents->infobar_tab_helper(); 145 InfoBarTabHelper* infobar_helper = tab_contents->infobar_tab_helper();
160 infobar_helper->AddInfoBar(new AutoLoginInfoBarDelegate(infobar_helper, 146 infobar_helper->AddInfoBar(
161 username_, 147 new AutoLoginInfoBarDelegate(infobar_helper, params_));
162 args_));
163 } 148 }
164 } 149 }
165 // Either we couldn't add the infobar, we added the infobar, or the tab 150 // 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 151 // contents was destroyed before the navigation completed. In any case
167 // there's no reason to live further. 152 // there's no reason to live further.
168 delete this; 153 delete this;
169 } 154 }
155
156 // static
157 bool AutoLoginPrompter::ParseAutoLoginHeader(const std::string& input,
158 Params* output) {
159 // TODO(pliard): Investigate/fix potential internationalization issue. It
160 // seems that "account" from the x-auto-login header might contain non-ASCII
161 // characters.
162 if (input.empty())
163 return false;
164
165 std::vector<std::pair<std::string, std::string> > pairs;
166 if (!base::SplitStringIntoKeyValuePairs(input, '=', '&', &pairs))
167 return false;
168
169 // Parse the information from the |input| string.
170 Params params;
171 for (size_t i = 0; i < pairs.size(); ++i) {
172 const std::pair<std::string, std::string>& pair = pairs[i];
173 if (pair.first == "realm") {
174 params.realm = net::UnescapeURLComponent(
Peter Kasting 2012/06/28 19:13:45 Nit: You could factor out: std::string unesca
Philippe 2012/06/29 08:48:10 Done.
175 pair.second, net::UnescapeRule::URL_SPECIAL_CHARS);
176 // Currently we only accept GAIA credentials.
177 if (params.realm != "com.google")
178 return false;
179 } else if (pair.first == "account") {
180 params.account = net::UnescapeURLComponent(
181 pair.second, net::UnescapeRule::URL_SPECIAL_CHARS);
182 } else if (pair.first == "args") {
183 params.args = net::UnescapeURLComponent(
184 pair.second, net::UnescapeRule::URL_SPECIAL_CHARS);
185 }
186 }
187 if (params.realm.empty() || params.args.empty())
188 return false;
189
190 *output = params;
191 return true;
192 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698