OLD | NEW |
| (Empty) |
1 // Copyright (c) 2012 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 "chrome/browser/ui/views/ash/launcher/chrome_launcher_controller.h" | |
6 | |
7 #include <algorithm> | |
8 #include <string> | |
9 #include <vector> | |
10 | |
11 #include "ash/launcher/launcher_model.h" | |
12 #include "base/compiler_specific.h" | |
13 #include "base/file_path.h" | |
14 #include "base/memory/scoped_ptr.h" | |
15 #include "base/message_loop.h" | |
16 #include "base/values.h" | |
17 #include "chrome/browser/extensions/extension_service.h" | |
18 #include "chrome/browser/extensions/test_extension_system.h" | |
19 #include "chrome/browser/ui/ash/chrome_launcher_prefs.h" | |
20 #include "chrome/common/extensions/extension.h" | |
21 #include "chrome/common/pref_names.h" | |
22 #include "chrome/test/base/testing_pref_service.h" | |
23 #include "chrome/test/base/testing_profile.h" | |
24 #include "content/public/test/test_browser_thread.h" | |
25 #include "testing/gtest/include/gtest/gtest.h" | |
26 | |
27 using extensions::Extension; | |
28 | |
29 class ChromeLauncherControllerTest : public testing::Test { | |
30 protected: | |
31 ChromeLauncherControllerTest() | |
32 : ui_thread_(content::BrowserThread::UI, &loop_), | |
33 file_thread_(content::BrowserThread::FILE, &loop_), | |
34 profile_(new TestingProfile()), | |
35 extension_service_(NULL) { | |
36 DictionaryValue manifest; | |
37 manifest.SetString("name", "launcher controller test extension"); | |
38 manifest.SetString("version", "1"); | |
39 manifest.SetString("description", "for testing pinned apps"); | |
40 | |
41 extensions::TestExtensionSystem* extension_system( | |
42 static_cast<extensions::TestExtensionSystem*>( | |
43 extensions::ExtensionSystem::Get(profile_.get()))); | |
44 extension_service_ = extension_system->CreateExtensionService( | |
45 CommandLine::ForCurrentProcess(), FilePath(), false); | |
46 | |
47 std::string error; | |
48 extension1_ = Extension::Create(FilePath(), Extension::LOAD, manifest, | |
49 Extension::NO_FLAGS, | |
50 "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", | |
51 &error); | |
52 extension2_ = Extension::Create(FilePath(), Extension::LOAD, manifest, | |
53 Extension::NO_FLAGS, | |
54 "bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb", | |
55 &error); | |
56 // Fake gmail extension. | |
57 extension3_ = Extension::Create(FilePath(), Extension::LOAD, manifest, | |
58 Extension::NO_FLAGS, | |
59 "pjkljhegncpnkpknbcohdijeoejaedia", | |
60 &error); | |
61 // Fake search extension. | |
62 extension4_ = Extension::Create(FilePath(), Extension::LOAD, manifest, | |
63 Extension::NO_FLAGS, | |
64 "coobgpohoikkiipiblmjeljniedjpjpf", | |
65 &error); | |
66 } | |
67 | |
68 virtual void TearDown() OVERRIDE { | |
69 profile_.reset(); | |
70 // Execute any pending deletion tasks. | |
71 loop_.RunAllPending(); | |
72 } | |
73 | |
74 void InsertPrefValue(base::ListValue* pref_value, | |
75 int index, | |
76 const std::string& extension_id) { | |
77 base::DictionaryValue* entry = new DictionaryValue(); | |
78 entry->SetString(ash::kPinnedAppsPrefAppIDPath, extension_id); | |
79 pref_value->Insert(index, entry); | |
80 } | |
81 | |
82 // Gets the currently configured app launchers from the controller. | |
83 void GetAppLaunchers(ChromeLauncherController* controller, | |
84 std::vector<std::string>* launchers) { | |
85 launchers->clear(); | |
86 for (ash::LauncherItems::const_iterator iter(model_.items().begin()); | |
87 iter != model_.items().end(); ++iter) { | |
88 ChromeLauncherController::IDToItemMap::const_iterator entry( | |
89 controller->id_to_item_map_.find(iter->id)); | |
90 if (iter->type == ash::TYPE_APP_SHORTCUT && | |
91 entry != controller->id_to_item_map_.end()) { | |
92 launchers->push_back(entry->second.app_id); | |
93 } | |
94 } | |
95 } | |
96 | |
97 // Needed for extension service & friends to work. | |
98 MessageLoop loop_; | |
99 content::TestBrowserThread ui_thread_; | |
100 content::TestBrowserThread file_thread_; | |
101 | |
102 scoped_refptr<Extension> extension1_; | |
103 scoped_refptr<Extension> extension2_; | |
104 scoped_refptr<Extension> extension3_; | |
105 scoped_refptr<Extension> extension4_; | |
106 scoped_ptr<TestingProfile> profile_; | |
107 ash::LauncherModel model_; | |
108 | |
109 ExtensionService* extension_service_; | |
110 | |
111 DISALLOW_COPY_AND_ASSIGN(ChromeLauncherControllerTest); | |
112 }; | |
113 | |
114 TEST_F(ChromeLauncherControllerTest, DefaultApps) { | |
115 ChromeLauncherController launcher_controller(profile_.get(), &model_); | |
116 launcher_controller.Init(); | |
117 | |
118 // Model should only contain the browser shortcut and app list items. | |
119 EXPECT_EQ(2, model_.item_count()); | |
120 EXPECT_FALSE(launcher_controller.IsAppPinned(extension1_->id())); | |
121 EXPECT_FALSE(launcher_controller.IsAppPinned(extension2_->id())); | |
122 EXPECT_FALSE(launcher_controller.IsAppPinned(extension3_->id())); | |
123 | |
124 // Installing |extension3_| should add it to the launcher. | |
125 extension_service_->AddExtension(extension3_.get()); | |
126 EXPECT_EQ(3, model_.item_count()); | |
127 EXPECT_EQ(ash::TYPE_APP_SHORTCUT, model_.items()[1].type); | |
128 EXPECT_FALSE(launcher_controller.IsAppPinned(extension1_->id())); | |
129 EXPECT_FALSE(launcher_controller.IsAppPinned(extension2_->id())); | |
130 EXPECT_TRUE(launcher_controller.IsAppPinned(extension3_->id())); | |
131 } | |
132 | |
133 TEST_F(ChromeLauncherControllerTest, Policy) { | |
134 extension_service_->AddExtension(extension1_.get()); | |
135 extension_service_->AddExtension(extension3_.get()); | |
136 | |
137 base::ListValue policy_value; | |
138 InsertPrefValue(&policy_value, 0, extension1_->id()); | |
139 InsertPrefValue(&policy_value, 1, extension2_->id()); | |
140 profile_->GetTestingPrefService()->SetManagedPref(prefs::kPinnedLauncherApps, | |
141 policy_value.DeepCopy()); | |
142 | |
143 // Only |extension1_| should get pinned. |extension2_| is specified but not | |
144 // installed, and |extension3_| is part of the default set, but that shouldn't | |
145 // take effect when the policy override is in place. | |
146 ChromeLauncherController launcher_controller(profile_.get(), &model_); | |
147 launcher_controller.Init(); | |
148 EXPECT_EQ(3, model_.item_count()); | |
149 EXPECT_EQ(ash::TYPE_APP_SHORTCUT, model_.items()[1].type); | |
150 EXPECT_TRUE(launcher_controller.IsAppPinned(extension1_->id())); | |
151 EXPECT_FALSE(launcher_controller.IsAppPinned(extension2_->id())); | |
152 EXPECT_FALSE(launcher_controller.IsAppPinned(extension3_->id())); | |
153 | |
154 // Installing |extension2_| should add it to the launcher. | |
155 extension_service_->AddExtension(extension2_.get()); | |
156 EXPECT_EQ(4, model_.item_count()); | |
157 EXPECT_EQ(ash::TYPE_APP_SHORTCUT, model_.items()[1].type); | |
158 EXPECT_EQ(ash::TYPE_APP_SHORTCUT, model_.items()[2].type); | |
159 EXPECT_TRUE(launcher_controller.IsAppPinned(extension1_->id())); | |
160 EXPECT_TRUE(launcher_controller.IsAppPinned(extension2_->id())); | |
161 EXPECT_FALSE(launcher_controller.IsAppPinned(extension3_->id())); | |
162 | |
163 // Removing |extension1_| from the policy should be reflected in the launcher. | |
164 policy_value.Remove(0, NULL); | |
165 profile_->GetTestingPrefService()->SetManagedPref(prefs::kPinnedLauncherApps, | |
166 policy_value.DeepCopy()); | |
167 EXPECT_EQ(3, model_.item_count()); | |
168 EXPECT_EQ(ash::TYPE_APP_SHORTCUT, model_.items()[1].type); | |
169 EXPECT_FALSE(launcher_controller.IsAppPinned(extension1_->id())); | |
170 EXPECT_TRUE(launcher_controller.IsAppPinned(extension2_->id())); | |
171 EXPECT_FALSE(launcher_controller.IsAppPinned(extension3_->id())); | |
172 } | |
173 | |
174 TEST_F(ChromeLauncherControllerTest, UnloadAndLoad) { | |
175 extension_service_->AddExtension(extension3_.get()); | |
176 extension_service_->AddExtension(extension4_.get()); | |
177 | |
178 ChromeLauncherController launcher_controller(profile_.get(), &model_); | |
179 launcher_controller.Init(); | |
180 | |
181 EXPECT_TRUE(launcher_controller.IsAppPinned(extension3_->id())); | |
182 EXPECT_TRUE(launcher_controller.IsAppPinned(extension4_->id())); | |
183 | |
184 extension_service_->UnloadExtension(extension3_->id(), | |
185 extension_misc::UNLOAD_REASON_UPDATE); | |
186 EXPECT_TRUE(launcher_controller.IsAppPinned(extension3_->id())); | |
187 EXPECT_EQ(ash::STATUS_IS_PENDING, model_.items()[1].status); | |
188 | |
189 extension_service_->AddExtension(extension3_.get()); | |
190 EXPECT_TRUE(launcher_controller.IsAppPinned(extension3_->id())); | |
191 EXPECT_EQ(ash::STATUS_CLOSED, model_.items()[1].status); | |
192 | |
193 EXPECT_TRUE(launcher_controller.IsAppPinned(extension4_->id())); | |
194 } | |
195 | |
196 TEST_F(ChromeLauncherControllerTest, UnpinWithUninstall) { | |
197 extension_service_->AddExtension(extension3_.get()); | |
198 extension_service_->AddExtension(extension4_.get()); | |
199 | |
200 ChromeLauncherController launcher_controller(profile_.get(), &model_); | |
201 launcher_controller.Init(); | |
202 | |
203 EXPECT_TRUE(launcher_controller.IsAppPinned(extension3_->id())); | |
204 EXPECT_TRUE(launcher_controller.IsAppPinned(extension4_->id())); | |
205 | |
206 extension_service_->UnloadExtension(extension3_->id(), | |
207 extension_misc::UNLOAD_REASON_UNINSTALL); | |
208 | |
209 EXPECT_FALSE(launcher_controller.IsAppPinned(extension3_->id())); | |
210 EXPECT_TRUE(launcher_controller.IsAppPinned(extension4_->id())); | |
211 } | |
212 | |
213 TEST_F(ChromeLauncherControllerTest, PrefUpdates) { | |
214 extension_service_->AddExtension(extension2_.get()); | |
215 extension_service_->AddExtension(extension3_.get()); | |
216 extension_service_->AddExtension(extension4_.get()); | |
217 ChromeLauncherController controller(profile_.get(), &model_); | |
218 | |
219 std::vector<std::string> expected_launchers; | |
220 std::vector<std::string> actual_launchers; | |
221 base::ListValue pref_value; | |
222 profile_->GetTestingPrefService()->SetUserPref(prefs::kPinnedLauncherApps, | |
223 pref_value.DeepCopy()); | |
224 GetAppLaunchers(&controller, &actual_launchers); | |
225 EXPECT_EQ(expected_launchers, actual_launchers); | |
226 | |
227 // Unavailable extensions don't create launcher items. | |
228 InsertPrefValue(&pref_value, 0, extension1_->id()); | |
229 InsertPrefValue(&pref_value, 1, extension2_->id()); | |
230 InsertPrefValue(&pref_value, 2, extension4_->id()); | |
231 profile_->GetTestingPrefService()->SetUserPref(prefs::kPinnedLauncherApps, | |
232 pref_value.DeepCopy()); | |
233 expected_launchers.push_back(extension2_->id()); | |
234 expected_launchers.push_back(extension4_->id()); | |
235 GetAppLaunchers(&controller, &actual_launchers); | |
236 EXPECT_EQ(expected_launchers, actual_launchers); | |
237 | |
238 // Redundant pref entries show up only once. | |
239 InsertPrefValue(&pref_value, 2, extension3_->id()); | |
240 InsertPrefValue(&pref_value, 2, extension3_->id()); | |
241 InsertPrefValue(&pref_value, 5, extension3_->id()); | |
242 profile_->GetTestingPrefService()->SetUserPref(prefs::kPinnedLauncherApps, | |
243 pref_value.DeepCopy()); | |
244 expected_launchers.insert(expected_launchers.begin() + 1, extension3_->id()); | |
245 GetAppLaunchers(&controller, &actual_launchers); | |
246 EXPECT_EQ(expected_launchers, actual_launchers); | |
247 | |
248 // Order changes are reflected correctly. | |
249 pref_value.Clear(); | |
250 InsertPrefValue(&pref_value, 0, extension4_->id()); | |
251 InsertPrefValue(&pref_value, 1, extension3_->id()); | |
252 InsertPrefValue(&pref_value, 2, extension2_->id()); | |
253 profile_->GetTestingPrefService()->SetUserPref(prefs::kPinnedLauncherApps, | |
254 pref_value.DeepCopy()); | |
255 std::reverse(expected_launchers.begin(), expected_launchers.end()); | |
256 GetAppLaunchers(&controller, &actual_launchers); | |
257 EXPECT_EQ(expected_launchers, actual_launchers); | |
258 | |
259 // Clearing works. | |
260 pref_value.Clear(); | |
261 profile_->GetTestingPrefService()->SetUserPref(prefs::kPinnedLauncherApps, | |
262 pref_value.DeepCopy()); | |
263 expected_launchers.clear(); | |
264 GetAppLaunchers(&controller, &actual_launchers); | |
265 EXPECT_EQ(expected_launchers, actual_launchers); | |
266 } | |
267 | |
268 TEST_F(ChromeLauncherControllerTest, PendingInsertionOrder) { | |
269 extension_service_->AddExtension(extension1_.get()); | |
270 extension_service_->AddExtension(extension3_.get()); | |
271 ChromeLauncherController controller(profile_.get(), &model_); | |
272 | |
273 base::ListValue pref_value; | |
274 InsertPrefValue(&pref_value, 0, extension1_->id()); | |
275 InsertPrefValue(&pref_value, 1, extension2_->id()); | |
276 InsertPrefValue(&pref_value, 2, extension3_->id()); | |
277 profile_->GetTestingPrefService()->SetUserPref(prefs::kPinnedLauncherApps, | |
278 pref_value.DeepCopy()); | |
279 | |
280 std::vector<std::string> expected_launchers; | |
281 expected_launchers.push_back(extension1_->id()); | |
282 expected_launchers.push_back(extension3_->id()); | |
283 std::vector<std::string> actual_launchers; | |
284 | |
285 GetAppLaunchers(&controller, &actual_launchers); | |
286 EXPECT_EQ(expected_launchers, actual_launchers); | |
287 | |
288 // Install |extension2| and verify it shows up between the other two. | |
289 extension_service_->AddExtension(extension2_.get()); | |
290 expected_launchers.insert(expected_launchers.begin() + 1, extension2_->id()); | |
291 GetAppLaunchers(&controller, &actual_launchers); | |
292 EXPECT_EQ(expected_launchers, actual_launchers); | |
293 } | |
OLD | NEW |