12a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// Copyright (c) 2012 The Chromium Authors. All rights reserved.
22a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be
32a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// found in the LICENSE file.
42a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
52a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "chrome/browser/extensions/app_icon_loader_impl.h"
62a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
72a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "base/stl_util.h"
82a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "chrome/browser/extensions/extension_service.h"
9f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)#include "chrome/browser/extensions/extension_util.h"
102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "chrome/browser/profiles/profile.h"
112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "chrome/common/extensions/extension_constants.h"
125d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "extensions/browser/extension_system.h"
13f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)#include "extensions/common/extension.h"
14c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch#include "extensions/common/manifest_handlers/icons_handler.h"
152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "ui/gfx/color_utils.h"
162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "ui/gfx/image/image_skia_operations.h"
172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)namespace {
192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)const extensions::Extension* GetExtensionByID(Profile* profile,
212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                              const std::string& id) {
222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  ExtensionService* service =
232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      extensions::ExtensionSystem::Get(profile)->extension_service();
242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (!service)
252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return NULL;
262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return service->GetInstalledExtension(id);
272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}  // namespace
302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)namespace extensions {
322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)AppIconLoaderImpl::AppIconLoaderImpl(
342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    Profile* profile,
352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    int icon_size,
362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    AppIconLoader::Delegate* delegate)
372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    : profile_(profile),
382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      delegate_(delegate),
392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      icon_size_(icon_size) {
402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)AppIconLoaderImpl::~AppIconLoaderImpl() {
442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  STLDeleteContainerPairFirstPointers(map_.begin(), map_.end());
452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void AppIconLoaderImpl::FetchImage(const std::string& id) {
482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  for (ImageToExtensionIDMap::const_iterator i = map_.begin();
492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)       i != map_.end(); ++i) {
502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    if (i->second == id)
512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      return;  // Already loading the image.
522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  const extensions::Extension* extension = GetExtensionByID(profile_, id);
552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (!extension)
562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return;
572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  extensions::IconImage* image = new extensions::IconImage(
592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      profile_,
602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      extension,
612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      extensions::IconsInfo::GetIcons(extension),
622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      icon_size_,
635c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu      extensions::util::GetDefaultAppIcon(),
642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      this);
652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // |map_| takes ownership of |image|.
662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  map_[image] = id;
672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Triggers image loading now instead of depending on paint message. This
692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // makes the temp blank image be shown for shorter time and improves user
702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // experience. See http://crbug.com/146114.
7168043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  image->image_skia().EnsureRepsForSupportedScales();
722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void AppIconLoaderImpl::ClearImage(const std::string& id) {
752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  for (ImageToExtensionIDMap::iterator i = map_.begin();
762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)       i != map_.end(); ++i) {
772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    if (i->second == id) {
782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      delete i->first;
792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      map_.erase(i);
802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      break;
812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    }
822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void AppIconLoaderImpl::UpdateImage(const std::string& id) {
862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  for (ImageToExtensionIDMap::iterator i = map_.begin();
872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)       i != map_.end(); ++i) {
882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    if (i->second == id) {
892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      BuildImage(i->second, i->first->image_skia());
902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      break;
912a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    }
922a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
932a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
942a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
952a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void AppIconLoaderImpl::OnExtensionIconImageChanged(
962a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    extensions::IconImage* image) {
972a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  ImageToExtensionIDMap::iterator i = map_.find(image);
982a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (i == map_.end())
992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return;  // The image has been removed, do nothing.
1002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  BuildImage(i->second, i->first->image_skia());
1022a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
1032a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void AppIconLoaderImpl::BuildImage(const std::string& id,
1052a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                   const gfx::ImageSkia& icon) {
1062a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  gfx::ImageSkia image = icon;
1072a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1085d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  if (!util::IsAppLaunchable(id, profile_)) {
1092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    const color_utils::HSL shift = {-1, 0, 0.6};
1102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    image = gfx::ImageSkiaOperations::CreateHSLShiftedImage(image, shift);
1112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
1122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  delegate_->SetAppImage(id, image);
1142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
1152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}  // namespace extensions
117