user_image_source.cc revision 5d1f7b1de12d16ceb2c938c56701a3e8bfa558f7
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
19namespace {
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.
24const 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.
29void 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
50namespace chromeos {
51namespace options {
52
53base::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
80UserImageSource::UserImageSource() {
81}
82
83UserImageSource::~UserImageSource() {}
84
85std::string UserImageSource::GetSource() const {
86  return chrome::kChromeUIUserImageHost;
87}
88
89void UserImageSource::StartDataRequest(
90    const std::string& path,
91    int render_process_id,
92    int render_frame_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
101std::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