1// Copyright 2014 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 "cc/resources/ui_resource_bitmap.h"
6#include "content/browser/android/system_ui_resource_manager_impl.h"
7#include "content/public/browser/android/ui_resource_client_android.h"
8#include "content/public/browser/android/ui_resource_provider.h"
9#include "testing/gtest/include/gtest/gtest.h"
10#include "third_party/skia/include/core/SkBitmap.h"
11#include "third_party/skia/include/core/SkCanvas.h"
12
13namespace content {
14
15class TestSystemUIResourceManagerImpl
16    : public content::SystemUIResourceManagerImpl {
17 public:
18  TestSystemUIResourceManagerImpl(content::UIResourceProvider* provider)
19      : SystemUIResourceManagerImpl(provider) {}
20
21  virtual ~TestSystemUIResourceManagerImpl() {}
22
23  virtual void BuildResource(
24      ui::SystemUIResourceManager::ResourceType type) OVERRIDE {}
25
26  void SetResourceAsLoaded(ui::SystemUIResourceManager::ResourceType type) {
27    SkBitmap small_bitmap;
28    SkCanvas canvas(small_bitmap);
29    small_bitmap.allocPixels(
30        SkImageInfo::Make(1, 1, kRGBA_8888_SkColorType, kOpaque_SkAlphaType));
31    canvas.drawColor(SK_ColorWHITE);
32    small_bitmap.setImmutable();
33    OnFinishedLoadBitmap(type, &small_bitmap);
34  }
35};
36
37namespace {
38
39const ui::SystemUIResourceManager::ResourceType TEST_RESOURCE_TYPE =
40    ui::SystemUIResourceManager::OVERSCROLL_GLOW;
41
42class MockUIResourceProvider : public content::UIResourceProvider {
43 public:
44  MockUIResourceProvider()
45      : next_ui_resource_id_(1),
46        has_layer_tree_host_(true),
47        system_ui_resource_manager_(this) {}
48
49  virtual ~MockUIResourceProvider() {}
50
51  virtual cc::UIResourceId CreateUIResource(
52      content::UIResourceClientAndroid* client) OVERRIDE {
53    if (!has_layer_tree_host_)
54      return 0;
55    cc::UIResourceId id = next_ui_resource_id_++;
56    client->GetBitmap(id, false);
57    ui_resource_client_map_[id] = client;
58    return id;
59  }
60
61  virtual void DeleteUIResource(cc::UIResourceId id) OVERRIDE {
62    CHECK(has_layer_tree_host_);
63    ui_resource_client_map_.erase(id);
64  }
65
66  virtual bool SupportsETC1NonPowerOfTwo() const OVERRIDE { return true; }
67
68  void LayerTreeHostCleared() {
69    has_layer_tree_host_ = false;
70    UIResourceClientMap client_map = ui_resource_client_map_;
71    ui_resource_client_map_.clear();
72    for (UIResourceClientMap::iterator iter = client_map.begin();
73         iter != client_map.end();
74         iter++) {
75      iter->second->UIResourceIsInvalid();
76    }
77  }
78
79  void LayerTreeHostReturned() { has_layer_tree_host_ = true; }
80
81  TestSystemUIResourceManagerImpl& GetSystemUIResourceManager() {
82    return system_ui_resource_manager_;
83  }
84
85  cc::UIResourceId next_ui_resource_id() const { return next_ui_resource_id_; }
86
87 private:
88  typedef base::hash_map<cc::UIResourceId, content::UIResourceClientAndroid*>
89      UIResourceClientMap;
90
91  cc::UIResourceId next_ui_resource_id_;
92  UIResourceClientMap ui_resource_client_map_;
93  bool has_layer_tree_host_;
94
95  // The UIResourceProvider owns the SystemUIResourceManager.
96  TestSystemUIResourceManagerImpl system_ui_resource_manager_;
97};
98
99}  // namespace
100
101class SystemUIResourceManagerImplTest : public testing::Test {
102 public:
103  void PreloadResource(ui::SystemUIResourceManager::ResourceType type) {
104    ui_resource_provider_.GetSystemUIResourceManager().PreloadResource(type);
105  }
106
107  cc::UIResourceId GetUIResourceId(
108      ui::SystemUIResourceManager::ResourceType type) {
109    return ui_resource_provider_.GetSystemUIResourceManager().GetUIResourceId(
110        type);
111  }
112
113  void LayerTreeHostCleared() { ui_resource_provider_.LayerTreeHostCleared(); }
114
115  void LayerTreeHostReturned() {
116    ui_resource_provider_.LayerTreeHostReturned();
117  }
118
119  void SetResourceAsLoaded(ui::SystemUIResourceManager::ResourceType type) {
120    ui_resource_provider_.GetSystemUIResourceManager().SetResourceAsLoaded(
121        type);
122  }
123
124  cc::UIResourceId GetNextUIResourceId() const {
125    return ui_resource_provider_.next_ui_resource_id();
126  }
127
128 private:
129  MockUIResourceProvider ui_resource_provider_;
130};
131
132TEST_F(SystemUIResourceManagerImplTest, GetResourceAfterBitmapLoaded) {
133  SetResourceAsLoaded(TEST_RESOURCE_TYPE);
134  EXPECT_NE(0, GetUIResourceId(TEST_RESOURCE_TYPE));
135}
136
137TEST_F(SystemUIResourceManagerImplTest, GetResourceBeforeLoadBitmap) {
138  EXPECT_EQ(0, GetUIResourceId(TEST_RESOURCE_TYPE));
139  SetResourceAsLoaded(TEST_RESOURCE_TYPE);
140  EXPECT_NE(0, GetUIResourceId(TEST_RESOURCE_TYPE));
141}
142
143TEST_F(SystemUIResourceManagerImplTest, PreloadEnsureResource) {
144  // Preloading the resource should trigger bitmap loading, but the actual
145  // resource id will not be generated until it is explicitly requested.
146  cc::UIResourceId first_resource_id = GetNextUIResourceId();
147  PreloadResource(TEST_RESOURCE_TYPE);
148  SetResourceAsLoaded(TEST_RESOURCE_TYPE);
149  EXPECT_EQ(first_resource_id, GetNextUIResourceId());
150  EXPECT_NE(0, GetUIResourceId(TEST_RESOURCE_TYPE));
151  EXPECT_NE(first_resource_id, GetNextUIResourceId());
152}
153
154TEST_F(SystemUIResourceManagerImplTest, ResetLayerTreeHost) {
155  EXPECT_EQ(0, GetUIResourceId(TEST_RESOURCE_TYPE));
156  LayerTreeHostCleared();
157  EXPECT_EQ(0, GetUIResourceId(TEST_RESOURCE_TYPE));
158  LayerTreeHostReturned();
159  EXPECT_EQ(0, GetUIResourceId(TEST_RESOURCE_TYPE));
160
161  SetResourceAsLoaded(TEST_RESOURCE_TYPE);
162  EXPECT_NE(0, GetUIResourceId(TEST_RESOURCE_TYPE));
163  LayerTreeHostCleared();
164  EXPECT_EQ(0, GetUIResourceId(TEST_RESOURCE_TYPE));
165  LayerTreeHostReturned();
166  EXPECT_NE(0, GetUIResourceId(TEST_RESOURCE_TYPE));
167}
168
169}  // namespace content
170