C++程序  |  113行  |  4.31 KB

// Copyright (c) 2011 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#ifndef CHROME_BROWSER_EXTENSIONS_IMAGE_LOADING_TRACKER_H_
#define CHROME_BROWSER_EXTENSIONS_IMAGE_LOADING_TRACKER_H_
#pragma once

#include <map>

#include "base/memory/ref_counted.h"
#include "content/common/notification_observer.h"
#include "content/common/notification_registrar.h"

class Extension;
class ExtensionResource;
class SkBitmap;

namespace gfx {
  class Size;
}

// The views need to load their icons asynchronously but might be deleted before
// the images have loaded. This class encapsulates a loader class that stays
// alive while the request is in progress (manages its own lifetime) and keeps
// track of whether the view still cares about the icon loading.
//
// To use this class, have your class derive from ImageLoadingTracker::Observer,
// and add a member variable ImageLoadingTracker tracker_. Then override
// Observer::OnImageLoaded and call:
//   tracker_.LoadImage(extension, resource, max_size, false);
// ... and wait for OnImageLoaded to be called back on you with a pointer to the
// SkBitmap loaded.
// NOTE: if the image is available already (or the resource is not valid), the
// Observer is notified immediately from the call to LoadImage. In other words,
// by the time LoadImage returns the observer has been notified.
//
class ImageLoadingTracker : public NotificationObserver {
 public:
  enum CacheParam {
    CACHE,
    DONT_CACHE
  };

  class Observer {
   public:
    virtual ~Observer();

    // Will be called when the image with the given index has loaded.
    // The |image| is owned by the tracker, so the observer should make a copy
    // if they need to access it after this call. |image| can be null if valid
    // image was not found or it failed to decode. |resource| is the
    // ExtensionResource where the |image| came from and the |index| represents
    // the index of the image just loaded (starts at 0 and increments every
    // time LoadImage is called).
    virtual void OnImageLoaded(SkBitmap* image,
                               const ExtensionResource& resource,
                               int index) = 0;
  };

  explicit ImageLoadingTracker(Observer* observer);
  ~ImageLoadingTracker();

  // Specify image resource to load. If the loaded image is larger than
  // |max_size| it will be resized to those dimensions. IMPORTANT NOTE: this
  // function may call back your observer synchronously (ie before it returns)
  // if the image was found in the cache.
  void LoadImage(const Extension* extension,
                 const ExtensionResource& resource,
                 const gfx::Size& max_size,
                 CacheParam cache);

 private:
  typedef std::map<int, const Extension*> LoadMap;

  class ImageLoader;

  // When an image has finished loaded and been resized on the file thread, it
  // is posted back to this method on the original thread.  This method then
  // calls the observer's OnImageLoaded and deletes the ImageLoadingTracker if
  // it was the last image in the list. The |original_size| should be the size
  // of the image before any resizing was done.
  // |image| may be null if the file failed to decode.
  void OnImageLoaded(SkBitmap* image, const ExtensionResource& resource,
                     const gfx::Size& original_size, int id);

  // NotificationObserver method. If an extension is uninstalled while we're
  // waiting for the image we remove the entry from load_map_.
  virtual void Observe(NotificationType type,
                       const NotificationSource& source,
                       const NotificationDetails& details);

  // The view that is waiting for the image to load.
  Observer* observer_;

  // ID to use for next image requested. This is an ever increasing integer.
  int next_id_;

  // The object responsible for loading the image on the File thread.
  scoped_refptr<ImageLoader> loader_;

  // If LoadImage is told to cache the result an entry is added here. The
  // integer identifies the id assigned to the request. If the extension is
  // deleted while fetching the image the entry is removed from the map.
  LoadMap load_map_;

  NotificationRegistrar registrar_;

  DISALLOW_COPY_AND_ASSIGN(ImageLoadingTracker);
};

#endif  // CHROME_BROWSER_EXTENSIONS_IMAGE_LOADING_TRACKER_H_