• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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:
ExtensionIconManagerTest()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 
~ExtensionIconManagerTest()28   virtual ~ExtensionIconManagerTest() {}
29 
ImageLoadObserved()30   void ImageLoadObserved() {
31     unwaited_image_loads_++;
32     if (waiting_) {
33       MessageLoop::current()->Quit();
34     }
35   }
36 
WaitForImageLoad()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:
SetUp()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:
TestIconManager(ExtensionIconManagerTest * test)71   explicit TestIconManager(ExtensionIconManagerTest* test) : test_(test) {}
~TestIconManager()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.
OnImageLoaded(SkBitmap * image,const ExtensionResource & resource,int index)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.
GetDefaultIcon()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.
TEST_F(ExtensionIconManagerTest,LoadRemoveLoad)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