OLD | NEW |
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/webui/options2/chromeos/user_image_source.h" | 5 #include "chrome/browser/ui/webui/options2/chromeos/user_image_source.h" |
6 | 6 |
7 #include "base/memory/ref_counted_memory.h" | 7 #include "base/memory/ref_counted_memory.h" |
8 #include "base/message_loop.h" | 8 #include "base/message_loop.h" |
9 #include "base/string_split.h" | 9 #include "base/string_split.h" |
| 10 #include "chrome/browser/chromeos/login/default_user_images.h" |
10 #include "chrome/browser/chromeos/login/user_manager.h" | 11 #include "chrome/browser/chromeos/login/user_manager.h" |
| 12 #include "chrome/browser/ui/webui/web_ui_util.cc" |
11 #include "chrome/common/url_constants.h" | 13 #include "chrome/common/url_constants.h" |
12 #include "googleurl/src/url_parse.h" | 14 #include "googleurl/src/url_parse.h" |
13 #include "grit/theme_resources.h" | 15 #include "grit/theme_resources.h" |
14 #include "ui/base/resource/resource_bundle.h" | 16 #include "ui/base/resource/resource_bundle.h" |
15 #include "ui/gfx/codec/png_codec.h" | 17 #include "ui/gfx/codec/png_codec.h" |
16 | 18 |
17 namespace { | 19 namespace { |
18 | 20 |
19 // Animated key is used in user image URL requests to specify that | 21 // Animated key is used in user image URL requests to specify that |
20 // animated version of user image is required. Without that key | 22 // animated version of user image is required. Without that key |
21 // non-animated version of user image should be returned. | 23 // non-animated version of user image should be returned. |
22 const char kKeyAnimated[] = "animated"; | 24 const char kKeyAnimated[] = "animated"; |
23 | 25 |
24 // Extracts from user image request user email and type of requested | 26 // Parses the user image URL, which looks like |
25 // image (animated or non-animated). |path| is an user image request | 27 // "chrome://userimage/user@host?key1=value1&...&key_n=value_n@<scale>x", |
26 // and should look like "username@host?key1=value1&...&key_n=value_n". | 28 // to user email, optional parameters and scale factor. |
27 // So, "username@host" is stored into |email|. If a query part of | 29 void ParseRequest(const GURL& url, |
28 // |path| contains "animated" key, |is_image_animated| is set to true, | |
29 // otherwise |is_image_animated| is set to false. Doesn't change | |
30 // arguments if email can't be parsed (for instance, in guest mode). | |
31 void ParseRequest(const std::string& path, | |
32 std::string* email, | 30 std::string* email, |
33 bool* is_image_animated) { | 31 bool* is_image_animated, |
34 url_parse::Parsed parsed; | 32 ui::ScaleFactor* scale_factor) { |
35 url_parse::ParseStandardURL(path.c_str(), path.size(), &parsed); | 33 DCHECK(url.is_valid()); |
36 if (!parsed.username.is_valid() || !parsed.host.is_valid()) | |
37 return; | |
38 | 34 |
39 DCHECK(email != NULL); | 35 *email = url.path(); |
40 *email = path.substr(parsed.username.begin, parsed.username.len); | 36 email->erase(0, 1); // Strip initial slash. |
41 email->append("@"); | |
42 email->append(path.substr(parsed.host.begin, parsed.host.len)); | |
43 | 37 |
44 if (!parsed.query.is_valid()) | 38 // TODO(ivankr): when all chrome://userimage URLs have a valid @<scale>x, |
45 return; | 39 // remove this and pass |email| instead of |&path| to ParsePathAndScale. |
| 40 size_t pos = email->find('@'); |
| 41 if (pos != std::string::npos) { |
| 42 pos = email->find('@', pos + 1); |
| 43 if (pos != std::string::npos) |
| 44 email->erase(pos); |
| 45 } |
| 46 std::string path; |
| 47 web_ui_util::ParsePathAndScale(url, &path, scale_factor); |
46 | 48 |
47 url_parse::Component query = parsed.query; | 49 std::string url_spec = url.possibly_invalid_spec(); |
| 50 url_parse::Component query = url.parsed_for_possibly_invalid_spec().query; |
48 url_parse::Component key, value; | 51 url_parse::Component key, value; |
49 DCHECK(is_image_animated != NULL); | |
50 *is_image_animated = false; | 52 *is_image_animated = false; |
51 while (ExtractQueryKeyValue(path.c_str(), &query, &key, &value)) { | 53 while (ExtractQueryKeyValue(url_spec.c_str(), &query, &key, &value)) { |
52 if (path.substr(key.begin, key.len) == kKeyAnimated) { | 54 if (url_spec.substr(key.begin, key.len) == kKeyAnimated) { |
53 *is_image_animated = true; | 55 *is_image_animated = true; |
54 break; | 56 break; |
55 } | 57 } |
56 } | 58 } |
57 } | 59 } |
58 | 60 |
59 } // namespace | 61 } // namespace |
60 | 62 |
61 namespace chromeos { | 63 namespace chromeos { |
62 namespace options2 { | 64 namespace options2 { |
63 | 65 |
64 std::vector<unsigned char> UserImageSource::GetUserImage( | 66 base::RefCountedMemory* UserImageSource::GetUserImage( |
65 const std::string& email, bool is_image_animated) const { | 67 const std::string& email, |
| 68 bool is_image_animated, |
| 69 ui::ScaleFactor scale_factor) const { |
66 const chromeos::User* user = chromeos::UserManager::Get()->FindUser(email); | 70 const chromeos::User* user = chromeos::UserManager::Get()->FindUser(email); |
67 if (user) { | 71 if (user) { |
68 if (user->has_animated_image() && is_image_animated) | 72 if (user->has_animated_image() && is_image_animated) { |
69 return user->animated_image(); | 73 return new base::RefCountedBytes(user->animated_image()); |
70 else if (user->has_raw_image()) | 74 } else if (user->has_raw_image()) { |
71 return user->raw_image(); | 75 return new base::RefCountedBytes(user->raw_image()); |
| 76 } else if (user->has_default_image()) { |
| 77 return ResourceBundle::GetSharedInstance(). |
| 78 LoadDataResourceBytes(kDefaultImageResources[user->image_index()], |
| 79 scale_factor); |
| 80 } else { |
| 81 NOTREACHED() << "User with custom image missing raw data"; |
| 82 } |
72 } | 83 } |
73 std::vector<unsigned char> user_image; | 84 return ResourceBundle::GetSharedInstance(). |
74 gfx::PNGCodec::EncodeBGRASkBitmap( | 85 LoadDataResourceBytes(IDR_LOGIN_DEFAULT_USER, scale_factor); |
75 *ResourceBundle::GetSharedInstance().GetImageSkiaNamed( | |
76 IDR_LOGIN_DEFAULT_USER), | |
77 false, | |
78 &user_image); | |
79 return user_image; | |
80 } | 86 } |
81 | 87 |
82 UserImageSource::UserImageSource() | 88 UserImageSource::UserImageSource() |
83 : DataSource(chrome::kChromeUIUserImageHost, MessageLoop::current()) { | 89 : DataSource(chrome::kChromeUIUserImageHost, MessageLoop::current()) { |
84 } | 90 } |
85 | 91 |
86 UserImageSource::~UserImageSource() {} | 92 UserImageSource::~UserImageSource() {} |
87 | 93 |
88 void UserImageSource::StartDataRequest(const std::string& path, | 94 void UserImageSource::StartDataRequest(const std::string& path, |
89 bool is_incognito, | 95 bool is_incognito, |
90 int request_id) { | 96 int request_id) { |
91 std::string email; | 97 std::string email; |
92 bool is_image_animated = false; | 98 bool is_image_animated = false; |
93 ParseRequest(path, &email, &is_image_animated); | 99 ui::ScaleFactor scale_factor; |
94 | 100 GURL url(chrome::kChromeUIUserImageURL + path); |
95 std::vector<unsigned char> image = GetUserImage(email, is_image_animated); | 101 ParseRequest(url, &email, &is_image_animated, &scale_factor); |
96 SendResponse(request_id, new base::RefCountedBytes(image)); | 102 SendResponse(request_id, |
| 103 GetUserImage(email, is_image_animated, scale_factor)); |
97 } | 104 } |
98 | 105 |
99 std::string UserImageSource::GetMimeType(const std::string& path) const { | 106 std::string UserImageSource::GetMimeType(const std::string& path) const { |
100 // We need to explicitly return a mime type, otherwise if the user tries to | 107 // We need to explicitly return a mime type, otherwise if the user tries to |
101 // drag the image they get no extension. | 108 // drag the image they get no extension. |
102 std::string email; | 109 std::string email; |
103 bool is_image_animated = false; | 110 bool is_image_animated = false; |
104 ParseRequest(path, &email, &is_image_animated); | 111 ui::ScaleFactor scale_factor; |
| 112 |
| 113 GURL url(chrome::kChromeUIUserImageURL + path); |
| 114 ParseRequest(url, &email, &is_image_animated, &scale_factor); |
105 | 115 |
106 if (is_image_animated) { | 116 if (is_image_animated) { |
107 const chromeos::User* user = chromeos::UserManager::Get()->FindUser(email); | 117 const chromeos::User* user = chromeos::UserManager::Get()->FindUser(email); |
108 if (user && user->has_animated_image()) | 118 if (user && user->has_animated_image()) |
109 return "image/gif"; | 119 return "image/gif"; |
110 } | 120 } |
111 return "image/png"; | 121 return "image/png"; |
112 } | 122 } |
113 | 123 |
114 } // namespace options2 | 124 } // namespace options2 |
115 } // namespace chromeos | 125 } // namespace chromeos |
OLD | NEW |