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 3 // found in the LICENSE file. 4 5 #include "chrome/browser/ui/webui/options/chromeos/user_image_source.h" 6 7 #include "base/memory/ref_counted_memory.h" 8 #include "base/message_loop/message_loop.h" 9 #include "base/strings/string_split.h" 10 #include "chrome/browser/chromeos/login/default_user_images.h" 11 #include "chrome/browser/chromeos/login/user_manager.h" 12 #include "chrome/common/url_constants.h" 13 #include "grit/theme_resources.h" 14 #include "net/base/escape.h" 15 #include "ui/base/resource/resource_bundle.h" 16 #include "ui/gfx/codec/png_codec.h" 17 #include "url/url_parse.h" 18 19 namespace { 20 21 // Animated key is used in user image URL requests to specify that 22 // animated version of user image is required. Without that key 23 // non-animated version of user image should be returned. 24 const char kKeyAnimated[] = "animated"; 25 26 // Parses the user image URL, which looks like 27 // "chrome://userimage/user@host?key1=value1&...&key_n=value_n", 28 // to user email and optional parameters. 29 void ParseRequest(const GURL& url, 30 std::string* email, 31 bool* is_image_animated) { 32 DCHECK(url.is_valid()); 33 *email = net::UnescapeURLComponent(url.path().substr(1), 34 (net::UnescapeRule::URL_SPECIAL_CHARS | 35 net::UnescapeRule::SPACES)); 36 std::string url_spec = url.possibly_invalid_spec(); 37 url_parse::Component query = url.parsed_for_possibly_invalid_spec().query; 38 url_parse::Component key, value; 39 *is_image_animated = false; 40 while (ExtractQueryKeyValue(url_spec.c_str(), &query, &key, &value)) { 41 if (url_spec.substr(key.begin, key.len) == kKeyAnimated) { 42 *is_image_animated = true; 43 break; 44 } 45 } 46 } 47 48 } // namespace 49 50 namespace chromeos { 51 namespace options { 52 53 base::RefCountedMemory* UserImageSource::GetUserImage( 54 const std::string& email, 55 bool is_image_animated, 56 ui::ScaleFactor scale_factor) const { 57 const chromeos::User* user = chromeos::UserManager::Get()->FindUser(email); 58 if (user) { 59 if (user->has_animated_image() && is_image_animated) { 60 return new base::RefCountedBytes(user->animated_image()); 61 } else if (user->has_raw_image()) { 62 return new base::RefCountedBytes(user->raw_image()); 63 } else if (user->image_is_stub()) { 64 return ResourceBundle::GetSharedInstance(). 65 LoadDataResourceBytesForScale(IDR_PROFILE_PICTURE_LOADING, 66 scale_factor); 67 } else if (user->HasDefaultImage()) { 68 return ResourceBundle::GetSharedInstance(). 69 LoadDataResourceBytesForScale( 70 kDefaultImageResourceIDs[user->image_index()], 71 scale_factor); 72 } else { 73 NOTREACHED() << "User with custom image missing raw data"; 74 } 75 } 76 return ResourceBundle::GetSharedInstance(). 77 LoadDataResourceBytesForScale(IDR_LOGIN_DEFAULT_USER, scale_factor); 78 } 79 80 UserImageSource::UserImageSource() { 81 } 82 83 UserImageSource::~UserImageSource() {} 84 85 std::string UserImageSource::GetSource() const { 86 return chrome::kChromeUIUserImageHost; 87 } 88 89 void UserImageSource::StartDataRequest( 90 const std::string& path, 91 int render_process_id, 92 int render_view_id, 93 const content::URLDataSource::GotDataCallback& callback) { 94 std::string email; 95 bool is_image_animated = false; 96 GURL url(chrome::kChromeUIUserImageURL + path); 97 ParseRequest(url, &email, &is_image_animated); 98 callback.Run(GetUserImage(email, is_image_animated, ui::SCALE_FACTOR_100P)); 99 } 100 101 std::string UserImageSource::GetMimeType(const std::string& path) const { 102 // We need to explicitly return a mime type, otherwise if the user tries to 103 // drag the image they get no extension. 104 std::string email; 105 bool is_image_animated = false; 106 107 GURL url(chrome::kChromeUIUserImageURL + path); 108 ParseRequest(url, &email, &is_image_animated); 109 110 if (is_image_animated) { 111 const chromeos::User* user = chromeos::UserManager::Get()->FindUser(email); 112 if (user && user->has_animated_image()) 113 return "image/gif"; 114 } 115 return "image/png"; 116 } 117 118 } // namespace options 119 } // namespace chromeos 120