summaryrefslogtreecommitdiffstats
path: root/chrome/browser/extensions/extension_icon_manager_unittest.cc
blob: 51c76eaa073687f02bc3cf35fb0f7442d8459867 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
// Copyright (c) 2010 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.

#include "base/message_loop.h"
#include "base/path_service.h"
#include "base/values.h"
#include "chrome/browser/browser_thread.h"
#include "chrome/browser/extensions/extension_icon_manager.h"
#include "chrome/common/chrome_paths.h"
#include "chrome/common/extensions/extension.h"
#include "chrome/common/extensions/extension_resource.h"
#include "chrome/common/json_value_serializer.h"
#include "gfx/skia_util.h"
#include "testing/gtest/include/gtest/gtest.h"

// Our test class that takes care of managing the necessary threads for loading
// extension icons, and waiting for those loads to happen.
class ExtensionIconManagerTest : public testing::Test {
 public:
  ExtensionIconManagerTest() :
      unwaited_image_loads_(0),
      waiting_(false),
      ui_thread_(BrowserThread::UI, &ui_loop_),
      file_thread_(BrowserThread::FILE),
      io_thread_(BrowserThread::IO) {}

  virtual ~ExtensionIconManagerTest() {}

  void ImageLoadObserved() {
    unwaited_image_loads_++;
    if (waiting_) {
      MessageLoop::current()->Quit();
    }
  }

  void WaitForImageLoad() {
    if (unwaited_image_loads_ == 0) {
      waiting_ = true;
      MessageLoop::current()->Run();
      waiting_ = false;
    }
    ASSERT_GT(unwaited_image_loads_, 0);
    unwaited_image_loads_--;
  }

 private:
  virtual void SetUp() {
    file_thread_.Start();
    io_thread_.Start();
  }

  // The number of observed image loads that have not been waited for.
  int unwaited_image_loads_;

  // Whether we are currently waiting for an image load.
  bool waiting_;

  MessageLoop ui_loop_;
  BrowserThread ui_thread_;
  BrowserThread file_thread_;
  BrowserThread io_thread_;

  DISALLOW_COPY_AND_ASSIGN(ExtensionIconManagerTest);
};

// This is a specialization of ExtensionIconManager, with a special override to
// call back to the test when an icon has completed loading.
class TestIconManager : public ExtensionIconManager {
 public:
  explicit TestIconManager(ExtensionIconManagerTest* test) : test_(test) {}
  virtual ~TestIconManager() {}

  // Implements the ImageLoadingTracker::Observer interface, and calls through
  // to the base class' implementation. Then it lets the test know that an
  // image load was observed.
  virtual void OnImageLoaded(SkBitmap* image, ExtensionResource resource,
                             int index) {
    ExtensionIconManager::OnImageLoaded(image, resource, index);
    test_->ImageLoadObserved();
  }

 private:
  ExtensionIconManagerTest* test_;

  DISALLOW_COPY_AND_ASSIGN(TestIconManager);
};

// Returns the default icon that ExtensionIconManager gives when an extension
// doesn't have an icon.
SkBitmap GetDefaultIcon() {
  std::string dummy_id;
  EXPECT_TRUE(Extension::GenerateId(std::string("whatever"), &dummy_id));
  ExtensionIconManager manager;
  return manager.GetIcon(dummy_id);
}

// Tests loading an icon for an extension, removing it, then re-loading it.
TEST_F(ExtensionIconManagerTest, LoadRemoveLoad) {
  SkBitmap default_icon = GetDefaultIcon();

  FilePath test_dir;
  ASSERT_TRUE(PathService::Get(chrome::DIR_TEST_DATA, &test_dir));
  FilePath manifest_path = test_dir.AppendASCII(
      "extensions/image_loading_tracker/app.json");

  JSONFileValueSerializer serializer(manifest_path);
  scoped_ptr<DictionaryValue> manifest(
      static_cast<DictionaryValue*>(serializer.Deserialize(NULL, NULL)));
  ASSERT_TRUE(manifest.get() != NULL);

  Extension extension(manifest_path.DirName());
  ASSERT_TRUE(extension.InitFromValue(*manifest.get(),
                                      false /* require_key */,
                                      NULL /* errors */));
  TestIconManager icon_manager(this);

  // Load the icon and grab the bitmap.
  icon_manager.LoadIcon(&extension);
  WaitForImageLoad();
  SkBitmap first_icon = icon_manager.GetIcon(extension.id());
  EXPECT_FALSE(gfx::BitmapsAreEqual(first_icon, default_icon));

  // Remove the icon from the manager.
  icon_manager.RemoveIcon(extension.id());

  // Now re-load the icon - we should get the same result bitmap (and not the
  // default icon).
  icon_manager.LoadIcon(&extension);
  WaitForImageLoad();
  SkBitmap second_icon = icon_manager.GetIcon(extension.id());
  EXPECT_FALSE(gfx::BitmapsAreEqual(second_icon, default_icon));

  EXPECT_TRUE(gfx::BitmapsAreEqual(first_icon, second_icon));
}