Home | History | Annotate | Download | only in chromeos
      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