Home | History | Annotate | Download | only in extensions
      1 // Copyright (c) 2011 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 "base/message_loop.h"
      6 #include "base/path_service.h"
      7 #include "base/values.h"
      8 #include "chrome/browser/extensions/extension_icon_manager.h"
      9 #include "chrome/common/chrome_paths.h"
     10 #include "chrome/common/extensions/extension.h"
     11 #include "chrome/common/extensions/extension_resource.h"
     12 #include "content/browser/browser_thread.h"
     13 #include "content/common/json_value_serializer.h"
     14 #include "testing/gtest/include/gtest/gtest.h"
     15 #include "ui/gfx/skia_util.h"
     16 
     17 // Our test class that takes care of managing the necessary threads for loading
     18 // extension icons, and waiting for those loads to happen.
     19 class ExtensionIconManagerTest : public testing::Test {
     20  public:
     21   ExtensionIconManagerTest() :
     22       unwaited_image_loads_(0),
     23       waiting_(false),
     24       ui_thread_(BrowserThread::UI, &ui_loop_),
     25       file_thread_(BrowserThread::FILE),
     26       io_thread_(BrowserThread::IO) {}
     27 
     28   virtual ~ExtensionIconManagerTest() {}
     29 
     30   void ImageLoadObserved() {
     31     unwaited_image_loads_++;
     32     if (waiting_) {
     33       MessageLoop::current()->Quit();
     34     }
     35   }
     36 
     37   void WaitForImageLoad() {
     38     if (unwaited_image_loads_ == 0) {
     39       waiting_ = true;
     40       MessageLoop::current()->Run();
     41       waiting_ = false;
     42     }
     43     ASSERT_GT(unwaited_image_loads_, 0);
     44     unwaited_image_loads_--;
     45   }
     46 
     47  private:
     48   virtual void SetUp() {
     49     file_thread_.Start();
     50     io_thread_.Start();
     51   }
     52 
     53   // The number of observed image loads that have not been waited for.
     54   int unwaited_image_loads_;
     55 
     56   // Whether we are currently waiting for an image load.
     57   bool waiting_;
     58 
     59   MessageLoop ui_loop_;
     60   BrowserThread ui_thread_;
     61   BrowserThread file_thread_;
     62   BrowserThread io_thread_;
     63 
     64   DISALLOW_COPY_AND_ASSIGN(ExtensionIconManagerTest);
     65 };
     66 
     67 // This is a specialization of ExtensionIconManager, with a special override to
     68 // call back to the test when an icon has completed loading.
     69 class TestIconManager : public ExtensionIconManager {
     70  public:
     71   explicit TestIconManager(ExtensionIconManagerTest* test) : test_(test) {}
     72   virtual ~TestIconManager() {}
     73 
     74   // Implements the ImageLoadingTracker::Observer interface, and calls through
     75   // to the base class' implementation. Then it lets the test know that an
     76   // image load was observed.
     77   virtual void OnImageLoaded(SkBitmap* image, const ExtensionResource& resource,
     78                              int index) {
     79     ExtensionIconManager::OnImageLoaded(image, resource, index);
     80     test_->ImageLoadObserved();
     81   }
     82 
     83  private:
     84   ExtensionIconManagerTest* test_;
     85 
     86   DISALLOW_COPY_AND_ASSIGN(TestIconManager);
     87 };
     88 
     89 // Returns the default icon that ExtensionIconManager gives when an extension
     90 // doesn't have an icon.
     91 SkBitmap GetDefaultIcon() {
     92   std::string dummy_id;
     93   EXPECT_TRUE(Extension::GenerateId(std::string("whatever"), &dummy_id));
     94   ExtensionIconManager manager;
     95   return manager.GetIcon(dummy_id);
     96 }
     97 
     98 // Tests loading an icon for an extension, removing it, then re-loading it.
     99 TEST_F(ExtensionIconManagerTest, LoadRemoveLoad) {
    100   SkBitmap default_icon = GetDefaultIcon();
    101 
    102   FilePath test_dir;
    103   ASSERT_TRUE(PathService::Get(chrome::DIR_TEST_DATA, &test_dir));
    104   FilePath manifest_path = test_dir.AppendASCII(
    105       "extensions/image_loading_tracker/app.json");
    106 
    107   JSONFileValueSerializer serializer(manifest_path);
    108   scoped_ptr<DictionaryValue> manifest(
    109       static_cast<DictionaryValue*>(serializer.Deserialize(NULL, NULL)));
    110   ASSERT_TRUE(manifest.get() != NULL);
    111 
    112   scoped_refptr<Extension> extension(Extension::Create(
    113       manifest_path.DirName(), Extension::INVALID, *manifest.get(),
    114       Extension::STRICT_ERROR_CHECKS, NULL));
    115   ASSERT_TRUE(extension.get());
    116   TestIconManager icon_manager(this);
    117 
    118   // Load the icon and grab the bitmap.
    119   icon_manager.LoadIcon(extension.get());
    120   WaitForImageLoad();
    121   SkBitmap first_icon = icon_manager.GetIcon(extension->id());
    122   EXPECT_FALSE(gfx::BitmapsAreEqual(first_icon, default_icon));
    123 
    124   // Remove the icon from the manager.
    125   icon_manager.RemoveIcon(extension->id());
    126 
    127   // Now re-load the icon - we should get the same result bitmap (and not the
    128   // default icon).
    129   icon_manager.LoadIcon(extension.get());
    130   WaitForImageLoad();
    131   SkBitmap second_icon = icon_manager.GetIcon(extension->id());
    132   EXPECT_FALSE(gfx::BitmapsAreEqual(second_icon, default_icon));
    133 
    134   EXPECT_TRUE(gfx::BitmapsAreEqual(first_icon, second_icon));
    135 }
    136