Upstream version 10.39.225.0
[platform/framework/web/crosswalk.git] / src / chrome / browser / shell_integration_win_unittest.cc
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/shell_integration.h"
6
7 #include <vector>
8
9 #include "base/files/file_path.h"
10 #include "base/files/file_util.h"
11 #include "base/files/scoped_temp_dir.h"
12 #include "base/strings/string16.h"
13 #include "base/strings/string_number_conversions.h"
14 #include "base/strings/utf_string_conversions.h"
15 #include "base/test/test_shortcut_win.h"
16 #include "base/win/scoped_com_initializer.h"
17 #include "base/win/windows_version.h"
18 #include "chrome/browser/web_applications/web_app.h"
19 #include "chrome/common/chrome_constants.h"
20 #include "chrome/common/chrome_paths_internal.h"
21 #include "chrome/installer/util/browser_distribution.h"
22 #include "chrome/installer/util/shell_util.h"
23 #include "chrome/installer/util/util_constants.h"
24 #include "testing/gtest/include/gtest/gtest.h"
25
26 namespace {
27
28 struct ShortcutTestObject {
29   base::FilePath path;
30   base::win::ShortcutProperties properties;
31 };
32
33 class ShellIntegrationWinMigrateShortcutTest : public testing::Test {
34  protected:
35   virtual void SetUp() OVERRIDE {
36     ASSERT_TRUE(temp_dir_.CreateUniqueTempDir());
37
38     // A path to a random target.
39     base::CreateTemporaryFileInDir(temp_dir_.path(), &other_target_);
40
41     // This doesn't need to actually have a base name of "chrome.exe".
42     base::CreateTemporaryFileInDir(temp_dir_.path(), &chrome_exe_);
43
44     chrome_app_id_ =
45         ShellUtil::GetBrowserModelId(BrowserDistribution::GetDistribution(),
46                                      true);
47
48     base::FilePath default_user_data_dir;
49     chrome::GetDefaultUserDataDirectory(&default_user_data_dir);
50     base::FilePath default_profile_path =
51         default_user_data_dir.AppendASCII(chrome::kInitialProfile);
52     app_list_app_id_ =
53         ShellIntegration::GetAppListAppModelIdForProfile(default_profile_path);
54     non_default_user_data_dir_ = base::FilePath(FILE_PATH_LITERAL("root"))
55         .Append(FILE_PATH_LITERAL("Non Default Data Dir"));
56     non_default_profile_ = L"NonDefault";
57     non_default_profile_chrome_app_id_ =
58         ShellIntegration::GetChromiumModelIdForProfile(
59         default_user_data_dir.Append(non_default_profile_));
60     non_default_user_data_dir_chrome_app_id_ =
61         ShellIntegration::GetChromiumModelIdForProfile(
62         non_default_user_data_dir_.AppendASCII(chrome::kInitialProfile));
63     non_default_user_data_dir_and_profile_chrome_app_id_ =
64         ShellIntegration::GetChromiumModelIdForProfile(
65         non_default_user_data_dir_.Append(non_default_profile_));
66
67
68     extension_id_ = L"chromiumexampleappidforunittests";
69     base::string16 app_name =
70         base::UTF8ToUTF16(web_app::GenerateApplicationNameFromExtensionId(
71         base::UTF16ToUTF8(extension_id_)));
72     extension_app_id_ =
73         ShellIntegration::GetAppModelIdForProfile(app_name,
74                                                   default_profile_path);
75     non_default_profile_extension_app_id_ =
76         ShellIntegration::GetAppModelIdForProfile(
77         app_name,
78         default_user_data_dir.Append(non_default_profile_));
79
80     CreateShortcuts();
81   }
82
83   // Creates a test shortcut corresponding to |shortcut_properties| and resets
84   // |shortcut_properties| after copying it to an internal structure for later
85   // verification.
86   void AddTestShortcutAndResetProperties(
87       base::win::ShortcutProperties* shortcut_properties) {
88     ShortcutTestObject shortcut_test_object;
89     base::FilePath shortcut_path =
90         temp_dir_.path().Append(L"Shortcut " +
91                                 base::IntToString16(shortcuts_.size()) +
92                                 installer::kLnkExt);
93     shortcut_test_object.path = shortcut_path;
94     shortcut_test_object.properties = *shortcut_properties;
95     shortcuts_.push_back(shortcut_test_object);
96     ASSERT_TRUE(base::win::CreateOrUpdateShortcutLink(
97         shortcut_path, *shortcut_properties,
98         base::win::SHORTCUT_CREATE_ALWAYS));
99     shortcut_properties->options = 0U;
100   }
101
102   void CreateShortcuts() {
103     // A temporary object to pass properties to
104     // AddTestShortcutAndResetProperties().
105     base::win::ShortcutProperties temp_properties;
106
107     // Shortcut 0 doesn't point to chrome.exe and thus should never be migrated.
108     temp_properties.set_target(other_target_);
109     temp_properties.set_app_id(L"Dumbo");
110     ASSERT_NO_FATAL_FAILURE(
111         AddTestShortcutAndResetProperties(&temp_properties));
112
113     // Shortcut 1 points to chrome.exe and thus should be migrated.
114     temp_properties.set_target(chrome_exe_);
115     temp_properties.set_app_id(L"Dumbo");
116     temp_properties.set_dual_mode(false);
117     ASSERT_NO_FATAL_FAILURE(
118         AddTestShortcutAndResetProperties(&temp_properties));
119
120     // Shortcut 2 points to chrome.exe, but already has the right appid and thus
121     // should only be migrated if dual_mode is desired.
122     temp_properties.set_target(chrome_exe_);
123     temp_properties.set_app_id(chrome_app_id_);
124     ASSERT_NO_FATAL_FAILURE(
125         AddTestShortcutAndResetProperties(&temp_properties));
126
127     // Shortcut 3 is like shortcut 1, but it's appid is a prefix of the expected
128     // appid instead of being totally different.
129     base::string16 chrome_app_id_is_prefix(chrome_app_id_);
130     chrome_app_id_is_prefix.push_back(L'1');
131     temp_properties.set_target(chrome_exe_);
132     temp_properties.set_app_id(chrome_app_id_is_prefix);
133     ASSERT_NO_FATAL_FAILURE(
134         AddTestShortcutAndResetProperties(&temp_properties));
135
136     // Shortcut 4 is like shortcut 1, but it's appid is of the same size as the
137     // expected appid.
138     base::string16 same_size_as_chrome_app_id(L'1', chrome_app_id_.size());
139     temp_properties.set_target(chrome_exe_);
140     temp_properties.set_app_id(same_size_as_chrome_app_id);
141     ASSERT_NO_FATAL_FAILURE(
142         AddTestShortcutAndResetProperties(&temp_properties));
143
144     // Shortcut 5 doesn't have an app_id, nor is dual_mode even set; they should
145     // be set as expected upon migration.
146     temp_properties.set_target(chrome_exe_);
147     ASSERT_NO_FATAL_FAILURE(
148         AddTestShortcutAndResetProperties(&temp_properties));
149
150     // Shortcut 6 has a non-default profile directory and so should get a non-
151     // default app id.
152     temp_properties.set_target(chrome_exe_);
153     temp_properties.set_app_id(L"Dumbo");
154     temp_properties.set_arguments(
155         L"--profile-directory=" + non_default_profile_);
156     ASSERT_NO_FATAL_FAILURE(
157         AddTestShortcutAndResetProperties(&temp_properties));
158
159     // Shortcut 7 has a non-default user data directory and so should get a non-
160     // default app id.
161     temp_properties.set_target(chrome_exe_);
162     temp_properties.set_app_id(L"Dumbo");
163     temp_properties.set_arguments(
164         L"--user-data-dir=\"" + non_default_user_data_dir_.value() + L"\"");
165     ASSERT_NO_FATAL_FAILURE(
166         AddTestShortcutAndResetProperties(&temp_properties));
167
168     // Shortcut 8 has a non-default user data directory as well as a non-default
169     // profile directory and so should get a non-default app id.
170     temp_properties.set_target(chrome_exe_);
171     temp_properties.set_app_id(L"Dumbo");
172     temp_properties.set_arguments(
173         L"--user-data-dir=\"" + non_default_user_data_dir_.value() + L"\" " +
174         L"--profile-directory=" + non_default_profile_);
175     ASSERT_NO_FATAL_FAILURE(
176         AddTestShortcutAndResetProperties(&temp_properties));
177
178     // Shortcut 9 is a shortcut to an app and should get an app id for that app
179     // rather than the chrome app id.
180     temp_properties.set_target(chrome_exe_);
181     temp_properties.set_app_id(L"Dumbo");
182     temp_properties.set_arguments(
183         L"--app-id=" + extension_id_);
184     ASSERT_NO_FATAL_FAILURE(
185         AddTestShortcutAndResetProperties(&temp_properties));
186
187     // Shortcut 10 is a shortcut to an app with a non-default profile and should
188     // get an app id for that app with a non-default app id rather than the
189     // chrome app id.
190     temp_properties.set_target(chrome_exe_);
191     temp_properties.set_app_id(L"Dumbo");
192     temp_properties.set_arguments(
193         L"--app-id=" + extension_id_ +
194         L" --profile-directory=" + non_default_profile_);
195     ASSERT_NO_FATAL_FAILURE(
196         AddTestShortcutAndResetProperties(&temp_properties));
197   }
198
199   base::win::ScopedCOMInitializer com_initializer_;
200
201   base::ScopedTempDir temp_dir_;
202
203   // Test shortcuts.
204   std::vector<ShortcutTestObject> shortcuts_;
205
206   // The path to a fake chrome.exe.
207   base::FilePath chrome_exe_;
208
209   // The path to a random target.
210   base::FilePath other_target_;
211
212   // Chrome's AppUserModelId.
213   base::string16 chrome_app_id_;
214
215   // A profile that isn't the Default profile.
216   base::string16 non_default_profile_;
217
218   // A user data dir that isn't the default.
219   base::FilePath non_default_user_data_dir_;
220
221   // Chrome's AppUserModelId for the non-default profile.
222   base::string16 non_default_profile_chrome_app_id_;
223
224   // Chrome's AppUserModelId for the non-default user data dir.
225   base::string16 non_default_user_data_dir_chrome_app_id_;
226
227   // Chrome's AppUserModelId for the non-default user data dir and non-default
228   // profile.
229   base::string16 non_default_user_data_dir_and_profile_chrome_app_id_;
230
231   // The app launcher's app id.
232   base::string16 app_list_app_id_;
233
234   // An example extension id of an example app.
235   base::string16 extension_id_;
236
237   // The app id of the example app for the default profile and user data dir.
238   base::string16 extension_app_id_;
239
240   // The app id of the example app for the non-default profile.
241   base::string16 non_default_profile_extension_app_id_;
242 };
243
244 }  // namespace
245
246 // Test migration when not checking for dual mode.
247 TEST_F(ShellIntegrationWinMigrateShortcutTest, DontCheckDualMode) {
248   if (base::win::GetVersion() < base::win::VERSION_WIN7)
249     return;
250
251   EXPECT_EQ(9,
252             ShellIntegration::MigrateShortcutsInPathInternal(
253                 chrome_exe_, temp_dir_.path(), false));
254
255   // Only shortcut 1, 3, 4, 5, 6, 7, 8, 9, and 10 should have been migrated.
256   shortcuts_[1].properties.set_app_id(chrome_app_id_);
257   shortcuts_[3].properties.set_app_id(chrome_app_id_);
258   shortcuts_[4].properties.set_app_id(chrome_app_id_);
259   shortcuts_[5].properties.set_app_id(chrome_app_id_);
260   shortcuts_[6].properties.set_app_id(non_default_profile_chrome_app_id_);
261   shortcuts_[7].properties.set_app_id(non_default_user_data_dir_chrome_app_id_);
262   shortcuts_[8].properties.set_app_id(
263       non_default_user_data_dir_and_profile_chrome_app_id_);
264   shortcuts_[9].properties.set_app_id(extension_app_id_);
265   shortcuts_[10].properties.set_app_id(non_default_profile_extension_app_id_);
266
267   for (size_t i = 0; i < shortcuts_.size(); ++i) {
268     // Dual mode should be false for all of these.
269     shortcuts_[i].properties.set_dual_mode(false);
270     base::win::ValidateShortcut(shortcuts_[i].path, shortcuts_[i].properties);
271   }
272
273   // Make sure shortcuts are not re-migrated.
274   EXPECT_EQ(0,
275             ShellIntegration::MigrateShortcutsInPathInternal(
276                 chrome_exe_, temp_dir_.path(), false));
277 }
278
279 // Test migration when also checking for dual mode.
280 TEST_F(ShellIntegrationWinMigrateShortcutTest, CheckDualMode) {
281   if (base::win::GetVersion() < base::win::VERSION_WIN7)
282     return;
283
284   EXPECT_EQ(10,
285             ShellIntegration::MigrateShortcutsInPathInternal(
286                 chrome_exe_, temp_dir_.path(), true));
287
288   // Shortcut 1, 3, 4, 5, 6, 7, 8, 9, and 10 should have had both their app_id
289   // fixed and shortcut 1, 2, 3, 4, and 5 should also have had their dual_mode
290   // property fixed.
291   shortcuts_[1].properties.set_app_id(chrome_app_id_);
292   shortcuts_[3].properties.set_app_id(chrome_app_id_);
293   shortcuts_[4].properties.set_app_id(chrome_app_id_);
294   shortcuts_[5].properties.set_app_id(chrome_app_id_);
295   shortcuts_[6].properties.set_app_id(non_default_profile_chrome_app_id_);
296   shortcuts_[7].properties.set_app_id(non_default_user_data_dir_chrome_app_id_);
297   shortcuts_[8].properties.set_app_id(
298       non_default_user_data_dir_and_profile_chrome_app_id_);
299   shortcuts_[9].properties.set_app_id(extension_app_id_);
300   shortcuts_[10].properties.set_app_id(non_default_profile_extension_app_id_);
301
302   shortcuts_[1].properties.set_dual_mode(true);
303   shortcuts_[2].properties.set_dual_mode(true);
304   shortcuts_[3].properties.set_dual_mode(true);
305   shortcuts_[4].properties.set_dual_mode(true);
306   shortcuts_[5].properties.set_dual_mode(true);
307   shortcuts_[6].properties.set_dual_mode(false);
308   shortcuts_[7].properties.set_dual_mode(false);
309   shortcuts_[8].properties.set_dual_mode(false);
310   shortcuts_[9].properties.set_dual_mode(false);
311   shortcuts_[10].properties.set_dual_mode(false);
312
313   for (size_t i = 0; i < shortcuts_.size(); ++i)
314     base::win::ValidateShortcut(shortcuts_[i].path, shortcuts_[i].properties);
315
316   // Make sure shortcuts are not re-migrated.
317   EXPECT_EQ(0,
318             ShellIntegration::MigrateShortcutsInPathInternal(
319                 chrome_exe_, temp_dir_.path(), false));
320 }
321
322 TEST(ShellIntegrationWinTest, GetAppModelIdForProfileTest) {
323   const base::string16 base_app_id(
324       BrowserDistribution::GetDistribution()->GetBaseAppId());
325
326   // Empty profile path should get chrome::kBrowserAppID
327   base::FilePath empty_path;
328   EXPECT_EQ(base_app_id,
329             ShellIntegration::GetAppModelIdForProfile(base_app_id, empty_path));
330
331   // Default profile path should get chrome::kBrowserAppID
332   base::FilePath default_user_data_dir;
333   chrome::GetDefaultUserDataDirectory(&default_user_data_dir);
334   base::FilePath default_profile_path =
335       default_user_data_dir.AppendASCII(chrome::kInitialProfile);
336   EXPECT_EQ(base_app_id,
337             ShellIntegration::GetAppModelIdForProfile(base_app_id,
338                                                       default_profile_path));
339
340   // Non-default profile path should get chrome::kBrowserAppID joined with
341   // profile info.
342   base::FilePath profile_path(FILE_PATH_LITERAL("root"));
343   profile_path = profile_path.Append(FILE_PATH_LITERAL("udd"));
344   profile_path = profile_path.Append(FILE_PATH_LITERAL("User Data - Test"));
345   EXPECT_EQ(base_app_id + L".udd.UserDataTest",
346             ShellIntegration::GetAppModelIdForProfile(base_app_id,
347                                                       profile_path));
348 }
349
350 TEST(ShellIntegrationWinTest, GetAppListAppModelIdForProfileTest) {
351   base::string16 base_app_id(
352       BrowserDistribution::GetDistribution()->GetBaseAppId());
353   base_app_id.append(L"AppList");
354
355   // Empty profile path should get chrome::kBrowserAppID + AppList
356   base::FilePath empty_path;
357   EXPECT_EQ(base_app_id,
358             ShellIntegration::GetAppListAppModelIdForProfile(empty_path));
359
360   // Default profile path should get chrome::kBrowserAppID + AppList
361   base::FilePath default_user_data_dir;
362   chrome::GetDefaultUserDataDirectory(&default_user_data_dir);
363   base::FilePath default_profile_path =
364       default_user_data_dir.AppendASCII(chrome::kInitialProfile);
365   EXPECT_EQ(base_app_id,
366             ShellIntegration::GetAppListAppModelIdForProfile(
367                 default_profile_path));
368
369   // Non-default profile path should get chrome::kBrowserAppID + AppList joined
370   // with profile info.
371   base::FilePath profile_path(FILE_PATH_LITERAL("root"));
372   profile_path = profile_path.Append(FILE_PATH_LITERAL("udd"));
373   profile_path = profile_path.Append(FILE_PATH_LITERAL("User Data - Test"));
374   EXPECT_EQ(base_app_id + L".udd.UserDataTest",
375             ShellIntegration::GetAppListAppModelIdForProfile(profile_path));
376 }