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

Side by Side Diff: chrome/browser/profiles/profile_downloader.cc

Issue 8772055: Use Google Plus API to get profile information (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: log Created 9 years 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
« no previous file with comments | « no previous file | 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 (c) 2011 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2011 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/profiles/profile_downloader.h" 5 #include "chrome/browser/profiles/profile_downloader.h"
6 6
7 #include <string> 7 #include <string>
8 #include <vector> 8 #include <vector>
9 9
10 #include "base/json/json_reader.h" 10 #include "base/json/json_reader.h"
(...skipping 20 matching lines...) Expand all
31 #include "skia/ext/image_operations.h" 31 #include "skia/ext/image_operations.h"
32 32
33 using content::BrowserThread; 33 using content::BrowserThread;
34 34
35 namespace { 35 namespace {
36 36
37 // Template for optional authorization header when using an OAuth access token. 37 // Template for optional authorization header when using an OAuth access token.
38 const char kAuthorizationHeader[] = 38 const char kAuthorizationHeader[] =
39 "Authorization: Bearer %s"; 39 "Authorization: Bearer %s";
40 40
41 // URL requesting Picasa API for user info. 41 // URL requesting user info.
42 const char kUserEntryURL[] = 42 const char kUserEntryURL[] =
43 "http://picasaweb.google.com/data/entry/api/user/default?alt=json"; 43 "https://www.googleapis.com/oauth2/v1/userinfo?alt=json";
44 44
45 // OAuth scope for the Picasa API. 45 // OAuth scope for the user info API.
46 const char kPicasaScope[] = "http://picasaweb.google.com/data/"; 46 const char kAPIScope[] = "https://www.googleapis.com/auth/userinfo.profile";
47 47
48 // Path in JSON dictionary to user's photo thumbnail URL. 48 // Path in JSON dictionary to user's photo thumbnail URL.
49 const char kPhotoThumbnailURLPath[] = "entry.gphoto$thumbnail.$t"; 49 const char kPhotoThumbnailURLPath[] = "picture";
50 50
51 const char kNickNamePath[] = "entry.gphoto$nickname.$t"; 51 const char kNickNamePath[] = "name";
52 52
53 // Path format for specifying thumbnail's size. 53 // Path format for specifying thumbnail's size.
54 const char kThumbnailSizeFormat[] = "s%d-c"; 54 const char kThumbnailSizeFormat[] = "s%d-c";
55 // Default Picasa thumbnail size. 55 // Default thumbnail size.
56 const int kDefaultThumbnailSize = 64; 56 const int kDefaultThumbnailSize = 64;
57 57
58 // Separator of URL path components. 58 // Separator of URL path components.
59 const char kURLPathSeparator = '/'; 59 const char kURLPathSeparator = '/';
60 60
61 // Photo ID of the Picasa Web Albums profile picture (base64 of 0). 61 // Photo ID of the Picasa Web Albums profile picture (base64 of 0).
62 const char kPicasaPhotoId[] = "AAAAAAAAAAA"; 62 const char kPicasaPhotoId[] = "AAAAAAAAAAA";
63 63
64 // Photo version of the default PWA profile picture (base64 of 1). 64 // Photo version of the default PWA profile picture (base64 of 1).
65 const char kDefaultPicasaPhotoVersion[] = "AAAAAAAAAAE"; 65 const char kDefaultPicasaPhotoVersion[] = "AAAAAAAAAAE";
66 66
67 // Photo ID of the Google+ profile picture (base64 of 2). 67 // Photo ID of the Google+ profile picture (base64 of 2).
68 const char kGooglePlusPhotoId[] = "AAAAAAAAAAI"; 68 const char kGooglePlusPhotoId[] = "AAAAAAAAAAI";
69 69
70 // Photo version of the default Google+ profile picture (base64 of 0). 70 // Photo version of the default Google+ profile picture (base64 of 0).
71 const char kDefaultGooglePlusPhotoVersion[] = "AAAAAAAAAAA"; 71 const char kDefaultGooglePlusPhotoVersion[] = "AAAAAAAAAAA";
72 72
73 // Number of path components in profile picture URL. 73 // The minimum number of path components in profile picture URL.
74 const size_t kProfileImageURLPathComponentsCount = 7; 74 const size_t kProfileImageURLPathComponentsCount = 6;
75 75
76 // Index of path component with photo ID. 76 // Index of path component with photo ID.
77 const int kPhotoIdPathComponentIndex = 2; 77 const int kPhotoIdPathComponentIndex = 2;
78 78
79 // Index of path component with photo version. 79 // Index of path component with photo version.
80 const int kPhotoVersionPathComponentIndex = 3; 80 const int kPhotoVersionPathComponentIndex = 3;
81 81
82 bool GetImageURLWithSize(const GURL& old_url, int size, GURL* new_url) {
Munjal (Google) 2011/12/03 06:02:33 Would be nice to add a comment about what this fun
sail 2011/12/04 01:48:53 Done.
83 DCHECK(new_url);
84 std::vector<std::string> components;
85 base::SplitString(old_url.path(), kURLPathSeparator, &components);
86 if (components.size() == 0)
87 return false;
88
89 std::string old_spec = old_url.spec();
Munjal (Google) 2011/12/03 06:02:33 Nit: const std::string& old_spec
sail 2011/12/04 01:48:53 Done.
90 std::string default_size_component(
91 base::StringPrintf(kThumbnailSizeFormat, kDefaultThumbnailSize));
92 std::string new_size_component(
93 base::StringPrintf(kThumbnailSizeFormat, size));
94
95 // Check if a thumbnail size is already specified in the URL, e.g.,
96 // http://lh0.ggpht.com/-abcd1aBCDEf/AAAA/AAA_A/abc12/s64-c/1234567890.jpg
97 size_t pos = old_spec.find(default_size_component);
98 if (pos != std::string::npos) {
99 size_t end = pos + default_size_component.size();
100 std::string new_spec = old_spec.substr(0, pos) + new_size_component +
101 old_spec.substr(end, old_spec.size() - end);
Munjal (Google) 2011/12/03 06:02:33 Nit: You can skip the second parameter to substr s
sail 2011/12/04 01:48:53 Done.
102 *new_url = GURL(new_spec);
103 return new_url->is_valid();
104 }
105
106 // A thubmnail size is not already embedded in the URL so insert it before
107 // the last component.
108 std::string file_name = old_url.ExtractFileName();
Munjal (Google) 2011/12/03 06:02:33 Nit: const std::string& file_name
sail 2011/12/04 01:48:53 Done.
109 pos = old_spec.find(file_name);
110 if (pos != std::string::npos) {
Munjal (Google) 2011/12/03 06:02:33 Would it ever happen that pos is npos given that f
sail 2011/12/04 01:48:53 Good point. The file name can be empty so I replac
111 std::string new_spec = old_spec.substr(0, pos) + new_size_component +
112 old_spec.substr(pos - 1, old_spec.size() - pos + 1);
Munjal (Google) 2011/12/03 06:02:33 Nit: Same comment about skipping second arg to sub
sail 2011/12/04 01:48:53 Done.
113 *new_url = GURL(new_spec);
114 return new_url->is_valid();
115 }
Munjal (Google) 2011/12/03 06:02:33 Looking at the two code paths here, it seems like
sail 2011/12/04 01:48:53 Done.
116
117 // We can't set the image size, just use the default size.
118 *new_url = old_url;
119 return true;
120 }
Munjal (Google) 2011/12/03 06:02:33 It will be nice to add some unit tests for this me
sail 2011/12/04 01:48:53 Done.
121
82 } // namespace 122 } // namespace
83 123
84 bool ProfileDownloader::GetProfileNickNameAndImageURL(const std::string& data, 124 bool ProfileDownloader::GetProfileNickNameAndImageURL(const std::string& data,
85 string16* nick_name, 125 string16* nick_name,
86 std::string* url) const { 126 std::string* url) const {
87 DCHECK(nick_name); 127 DCHECK(nick_name);
88 DCHECK(url); 128 DCHECK(url);
89 *nick_name = string16(); 129 *nick_name = string16();
90 *url = std::string(); 130 *url = std::string();
91 131
(...skipping 13 matching lines...) Expand all
105 } 145 }
106 base::DictionaryValue* root_dictionary = 146 base::DictionaryValue* root_dictionary =
107 static_cast<base::DictionaryValue*>(root_value.get()); 147 static_cast<base::DictionaryValue*>(root_value.get());
108 148
109 if (!root_dictionary->GetString(kNickNamePath, nick_name)) { 149 if (!root_dictionary->GetString(kNickNamePath, nick_name)) {
110 LOG(ERROR) << "Can't find nick name path in JSON data: " 150 LOG(ERROR) << "Can't find nick name path in JSON data: "
111 << data; 151 << data;
112 return false; 152 return false;
113 } 153 }
114 154
115 std::string thumbnail_url_string; 155 std::string url_string;
116 if (!root_dictionary->GetString( 156 if (!root_dictionary->GetString(kPhotoThumbnailURLPath, &url_string)) {
117 kPhotoThumbnailURLPath, &thumbnail_url_string)) {
118 LOG(ERROR) << "Can't find thumbnail path in JSON data: " 157 LOG(ERROR) << "Can't find thumbnail path in JSON data: "
119 << data; 158 << data;
120 return false; 159 return false;
121 } 160 }
122 161
123 // Try to change the size of thumbnail we are going to get. 162 GURL new_url;
124 // Typical URL looks like this:
125 // http://lh0.ggpht.com/-abcd1aBCDEf/AAAA/AAA_A/abc12/s64-c/1234567890.jpg
126 std::string default_thumbnail_size_path_component(
127 base::StringPrintf(kThumbnailSizeFormat, kDefaultThumbnailSize));
128 int image_size = delegate_->GetDesiredImageSideLength(); 163 int image_size = delegate_->GetDesiredImageSideLength();
129 std::string new_thumbnail_size_path_component( 164 if (!GetImageURLWithSize(GURL(url_string), image_size, &new_url)) {
130 base::StringPrintf(kThumbnailSizeFormat, image_size)); 165 LOG(ERROR) << "GetImageURLWithSize failed for url: " << url_string;
131 size_t thumbnail_size_pos = 166 return false;
132 thumbnail_url_string.find(default_thumbnail_size_path_component);
133 if (thumbnail_size_pos != std::string::npos) {
134 size_t thumbnail_size_end =
135 thumbnail_size_pos + default_thumbnail_size_path_component.size();
136 thumbnail_url_string =
137 thumbnail_url_string.substr(0, thumbnail_size_pos) +
138 new_thumbnail_size_path_component +
139 thumbnail_url_string.substr(
140 thumbnail_size_end,
141 thumbnail_url_string.size() - thumbnail_size_end);
142 } else {
143 LOG(WARNING) << "Hasn't found thumbnail size part in image URL: "
144 << thumbnail_url_string;
145 // Use the thumbnail URL we have.
146 } 167 }
147 168
148 GURL thumbnail_url(thumbnail_url_string); 169 *url = new_url.spec();
149 if (!thumbnail_url.is_valid()) {
150 LOG(ERROR) << "Thumbnail URL is not valid: " << thumbnail_url_string;
151 return false;
152 }
153 *url = thumbnail_url.spec();
154 return true; 170 return true;
155 } 171 }
156 172
157 bool ProfileDownloader::IsDefaultProfileImageURL(const std::string& url) const { 173 bool ProfileDownloader::IsDefaultProfileImageURL(const std::string& url) const {
158 GURL image_url_object(url); 174 GURL image_url_object(url);
159 DCHECK(image_url_object.is_valid()); 175 DCHECK(image_url_object.is_valid());
160 VLOG(1) << "URL to check for default image: " << image_url_object.spec(); 176 VLOG(1) << "URL to check for default image: " << image_url_object.spec();
161 std::vector<std::string> path_components; 177 std::vector<std::string> path_components;
162 base::SplitString(image_url_object.path(), 178 base::SplitString(image_url_object.path(),
163 kURLPathSeparator, 179 kURLPathSeparator,
164 &path_components); 180 &path_components);
165 181
166 if (path_components.size() != kProfileImageURLPathComponentsCount) 182 if (path_components.size() < kProfileImageURLPathComponentsCount)
167 return false; 183 return false;
168 184
169 const std::string& photo_id = path_components[kPhotoIdPathComponentIndex]; 185 const std::string& photo_id = path_components[kPhotoIdPathComponentIndex];
170 const std::string& photo_version = 186 const std::string& photo_version =
171 path_components[kPhotoVersionPathComponentIndex]; 187 path_components[kPhotoVersionPathComponentIndex];
172 188
173 // There are at least two pairs of (ID, version) for the default photo: 189 // There are at least two pairs of (ID, version) for the default photo:
174 // the default Google+ profile photo and the default Picasa profile photo. 190 // the default Google+ profile photo and the default Picasa profile photo.
175 return ((photo_id == kPicasaPhotoId && 191 return ((photo_id == kPicasaPhotoId &&
176 photo_version == kDefaultPicasaPhotoVersion) || 192 photo_version == kDefaultPicasaPhotoVersion) ||
(...skipping 59 matching lines...) Expand 10 before | Expand all | Expand 10 after
236 base::StringPrintf(kAuthorizationHeader, auth_token_.c_str())); 252 base::StringPrintf(kAuthorizationHeader, auth_token_.c_str()));
237 } 253 }
238 user_entry_fetcher_->Start(); 254 user_entry_fetcher_->Start();
239 } 255 }
240 256
241 void ProfileDownloader::StartFetchingOAuth2AccessToken() { 257 void ProfileDownloader::StartFetchingOAuth2AccessToken() {
242 TokenService* service = delegate_->GetBrowserProfile()->GetTokenService(); 258 TokenService* service = delegate_->GetBrowserProfile()->GetTokenService();
243 DCHECK(!service->GetOAuth2LoginRefreshToken().empty()); 259 DCHECK(!service->GetOAuth2LoginRefreshToken().empty());
244 260
245 std::vector<std::string> scopes; 261 std::vector<std::string> scopes;
246 scopes.push_back(kPicasaScope); 262 scopes.push_back(kAPIScope);
247 oauth2_access_token_fetcher_.reset(new OAuth2AccessTokenFetcher( 263 oauth2_access_token_fetcher_.reset(new OAuth2AccessTokenFetcher(
248 this, delegate_->GetBrowserProfile()->GetRequestContext())); 264 this, delegate_->GetBrowserProfile()->GetRequestContext()));
249 oauth2_access_token_fetcher_->Start( 265 oauth2_access_token_fetcher_->Start(
250 GaiaUrls::GetInstance()->oauth2_chrome_client_id(), 266 GaiaUrls::GetInstance()->oauth2_chrome_client_id(),
251 GaiaUrls::GetInstance()->oauth2_chrome_client_secret(), 267 GaiaUrls::GetInstance()->oauth2_chrome_client_secret(),
252 service->GetOAuth2LoginRefreshToken(), 268 service->GetOAuth2LoginRefreshToken(),
253 scopes); 269 scopes);
254 } 270 }
255 271
256 ProfileDownloader::~ProfileDownloader() {} 272 ProfileDownloader::~ProfileDownloader() {}
(...skipping 95 matching lines...) Expand 10 before | Expand all | Expand 10 after
352 void ProfileDownloader::OnGetTokenSuccess(const std::string& access_token) { 368 void ProfileDownloader::OnGetTokenSuccess(const std::string& access_token) {
353 auth_token_ = access_token; 369 auth_token_ = access_token;
354 StartFetchingImage(); 370 StartFetchingImage();
355 } 371 }
356 372
357 // Callback for OAuth2AccessTokenFetcher on failure. 373 // Callback for OAuth2AccessTokenFetcher on failure.
358 void ProfileDownloader::OnGetTokenFailure(const GoogleServiceAuthError& error) { 374 void ProfileDownloader::OnGetTokenFailure(const GoogleServiceAuthError& error) {
359 LOG(WARNING) << "ProfileDownloader: token request using refresh token failed"; 375 LOG(WARNING) << "ProfileDownloader: token request using refresh token failed";
360 delegate_->OnDownloadComplete(this, false); 376 delegate_->OnDownloadComplete(this, false);
361 } 377 }
OLDNEW
« no previous file with comments | « no previous file | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698