| OLD | NEW |
| 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 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 | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "chrome/browser/shell_integration.h" | 5 #include "chrome/browser/shell_integration.h" |
| 6 | 6 |
| 7 #include <cstdlib> | 7 #include <cstdlib> |
| 8 #include <map> | 8 #include <map> |
| 9 | 9 |
| 10 #include "base/file_util.h" | 10 #include "base/file_util.h" |
| (...skipping 88 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 99 private: | 99 private: |
| 100 // Map from name to original value, or the empty string if there was no | 100 // Map from name to original value, or the empty string if there was no |
| 101 // previous value. | 101 // previous value. |
| 102 std::map<std::string, std::string> old_variables_; | 102 std::map<std::string, std::string> old_variables_; |
| 103 | 103 |
| 104 DISALLOW_COPY_AND_ASSIGN(ScopedEnvironment); | 104 DISALLOW_COPY_AND_ASSIGN(ScopedEnvironment); |
| 105 }; | 105 }; |
| 106 | 106 |
| 107 } // namespace | 107 } // namespace |
| 108 | 108 |
| 109 TEST(ShellIntegrationTest, GetDesktopShortcutTemplate) { | 109 TEST(ShellIntegrationTest, GetExistingDesktopShortcutContents) { |
| 110 #if defined(GOOGLE_CHROME_BUILD) | 110 const char kTemplateFilename[] = "shortcut-test.desktop"; |
| 111 const char kTemplateFilename[] = "google-chrome.desktop"; | 111 base::FilePath kTemplateFilepath(kTemplateFilename); |
| 112 #else // CHROMIUM_BUILD | |
| 113 const char kTemplateFilename[] = "chromium-browser.desktop"; | |
| 114 #endif | |
| 115 | |
| 116 const char kTestData1[] = "a magical testing string"; | 112 const char kTestData1[] = "a magical testing string"; |
| 117 const char kTestData2[] = "a different testing string"; | 113 const char kTestData2[] = "a different testing string"; |
| 118 | 114 |
| 119 MessageLoop message_loop; | 115 MessageLoop message_loop; |
| 120 content::TestBrowserThread file_thread(BrowserThread::FILE, &message_loop); | 116 content::TestBrowserThread file_thread(BrowserThread::FILE, &message_loop); |
| 121 | 117 |
| 122 // Test that it searches $XDG_DATA_HOME/applications. | 118 // Test that it searches $XDG_DATA_HOME/applications. |
| 123 { | 119 { |
| 124 base::ScopedTempDir temp_dir; | 120 base::ScopedTempDir temp_dir; |
| 125 ASSERT_TRUE(temp_dir.CreateUniqueTempDir()); | 121 ASSERT_TRUE(temp_dir.CreateUniqueTempDir()); |
| 126 | 122 |
| 127 MockEnvironment env; | 123 MockEnvironment env; |
| 128 env.Set("XDG_DATA_HOME", temp_dir.path().value()); | 124 env.Set("XDG_DATA_HOME", temp_dir.path().value()); |
| 129 // Create a file in a non-applications directory. This should be ignored. | 125 // Create a file in a non-applications directory. This should be ignored. |
| 130 ASSERT_TRUE(file_util::WriteFile( | 126 ASSERT_TRUE(file_util::WriteFile( |
| 131 temp_dir.path().AppendASCII(kTemplateFilename), | 127 temp_dir.path().AppendASCII(kTemplateFilename), |
| 132 kTestData2, strlen(kTestData2))); | 128 kTestData2, strlen(kTestData2))); |
| 133 ASSERT_TRUE(file_util::CreateDirectory( | 129 ASSERT_TRUE(file_util::CreateDirectory( |
| 134 temp_dir.path().AppendASCII("applications"))); | 130 temp_dir.path().AppendASCII("applications"))); |
| 135 ASSERT_TRUE(file_util::WriteFile( | 131 ASSERT_TRUE(file_util::WriteFile( |
| 136 temp_dir.path().AppendASCII("applications") | 132 temp_dir.path().AppendASCII("applications") |
| 137 .AppendASCII(kTemplateFilename), | 133 .AppendASCII(kTemplateFilename), |
| 138 kTestData1, strlen(kTestData1))); | 134 kTestData1, strlen(kTestData1))); |
| 139 std::string contents; | 135 std::string contents; |
| 140 ASSERT_TRUE(ShellIntegrationLinux::GetDesktopShortcutTemplate(&env, | 136 ASSERT_TRUE( |
| 141 &contents)); | 137 ShellIntegrationLinux::GetExistingDesktopShortcutContents( |
| 138 &env, kTemplateFilepath, &contents)); |
| 142 EXPECT_EQ(kTestData1, contents); | 139 EXPECT_EQ(kTestData1, contents); |
| 143 } | 140 } |
| 144 | 141 |
| 145 // Test that it falls back to $HOME/.local/share/applications. | 142 // Test that it falls back to $HOME/.local/share/applications. |
| 146 { | 143 { |
| 147 base::ScopedTempDir temp_dir; | 144 base::ScopedTempDir temp_dir; |
| 148 ASSERT_TRUE(temp_dir.CreateUniqueTempDir()); | 145 ASSERT_TRUE(temp_dir.CreateUniqueTempDir()); |
| 149 | 146 |
| 150 MockEnvironment env; | 147 MockEnvironment env; |
| 151 env.Set("HOME", temp_dir.path().value()); | 148 env.Set("HOME", temp_dir.path().value()); |
| 152 ASSERT_TRUE(file_util::CreateDirectory( | 149 ASSERT_TRUE(file_util::CreateDirectory( |
| 153 temp_dir.path().AppendASCII(".local/share/applications"))); | 150 temp_dir.path().AppendASCII(".local/share/applications"))); |
| 154 ASSERT_TRUE(file_util::WriteFile( | 151 ASSERT_TRUE(file_util::WriteFile( |
| 155 temp_dir.path().AppendASCII(".local/share/applications") | 152 temp_dir.path().AppendASCII(".local/share/applications") |
| 156 .AppendASCII(kTemplateFilename), | 153 .AppendASCII(kTemplateFilename), |
| 157 kTestData1, strlen(kTestData1))); | 154 kTestData1, strlen(kTestData1))); |
| 158 std::string contents; | 155 std::string contents; |
| 159 ASSERT_TRUE(ShellIntegrationLinux::GetDesktopShortcutTemplate(&env, | 156 ASSERT_TRUE( |
| 160 &contents)); | 157 ShellIntegrationLinux::GetExistingDesktopShortcutContents( |
| 158 &env, kTemplateFilepath, &contents)); |
| 161 EXPECT_EQ(kTestData1, contents); | 159 EXPECT_EQ(kTestData1, contents); |
| 162 } | 160 } |
| 163 | 161 |
| 164 // Test that it searches $XDG_DATA_DIRS/applications. | 162 // Test that it searches $XDG_DATA_DIRS/applications. |
| 165 { | 163 { |
| 166 base::ScopedTempDir temp_dir; | 164 base::ScopedTempDir temp_dir; |
| 167 ASSERT_TRUE(temp_dir.CreateUniqueTempDir()); | 165 ASSERT_TRUE(temp_dir.CreateUniqueTempDir()); |
| 168 | 166 |
| 169 MockEnvironment env; | 167 MockEnvironment env; |
| 170 env.Set("XDG_DATA_DIRS", temp_dir.path().value()); | 168 env.Set("XDG_DATA_DIRS", temp_dir.path().value()); |
| 171 ASSERT_TRUE(file_util::CreateDirectory( | 169 ASSERT_TRUE(file_util::CreateDirectory( |
| 172 temp_dir.path().AppendASCII("applications"))); | 170 temp_dir.path().AppendASCII("applications"))); |
| 173 ASSERT_TRUE(file_util::WriteFile( | 171 ASSERT_TRUE(file_util::WriteFile( |
| 174 temp_dir.path().AppendASCII("applications") | 172 temp_dir.path().AppendASCII("applications") |
| 175 .AppendASCII(kTemplateFilename), | 173 .AppendASCII(kTemplateFilename), |
| 176 kTestData2, strlen(kTestData2))); | 174 kTestData2, strlen(kTestData2))); |
| 177 std::string contents; | 175 std::string contents; |
| 178 ASSERT_TRUE(ShellIntegrationLinux::GetDesktopShortcutTemplate(&env, | 176 ASSERT_TRUE( |
| 179 &contents)); | 177 ShellIntegrationLinux::GetExistingDesktopShortcutContents( |
| 178 &env, kTemplateFilepath, &contents)); |
| 180 EXPECT_EQ(kTestData2, contents); | 179 EXPECT_EQ(kTestData2, contents); |
| 181 } | 180 } |
| 182 | 181 |
| 183 // Test that it searches $X/applications for each X in $XDG_DATA_DIRS. | 182 // Test that it searches $X/applications for each X in $XDG_DATA_DIRS. |
| 184 { | 183 { |
| 185 base::ScopedTempDir temp_dir1; | 184 base::ScopedTempDir temp_dir1; |
| 186 ASSERT_TRUE(temp_dir1.CreateUniqueTempDir()); | 185 ASSERT_TRUE(temp_dir1.CreateUniqueTempDir()); |
| 187 base::ScopedTempDir temp_dir2; | 186 base::ScopedTempDir temp_dir2; |
| 188 ASSERT_TRUE(temp_dir2.CreateUniqueTempDir()); | 187 ASSERT_TRUE(temp_dir2.CreateUniqueTempDir()); |
| 189 | 188 |
| 190 MockEnvironment env; | 189 MockEnvironment env; |
| 191 env.Set("XDG_DATA_DIRS", temp_dir1.path().value() + ":" + | 190 env.Set("XDG_DATA_DIRS", temp_dir1.path().value() + ":" + |
| 192 temp_dir2.path().value()); | 191 temp_dir2.path().value()); |
| 193 // Create a file in a non-applications directory. This should be ignored. | 192 // Create a file in a non-applications directory. This should be ignored. |
| 194 ASSERT_TRUE(file_util::WriteFile( | 193 ASSERT_TRUE(file_util::WriteFile( |
| 195 temp_dir1.path().AppendASCII(kTemplateFilename), | 194 temp_dir1.path().AppendASCII(kTemplateFilename), |
| 196 kTestData1, strlen(kTestData1))); | 195 kTestData1, strlen(kTestData1))); |
| 197 // Only create a findable desktop file in the second path. | 196 // Only create a findable desktop file in the second path. |
| 198 ASSERT_TRUE(file_util::CreateDirectory( | 197 ASSERT_TRUE(file_util::CreateDirectory( |
| 199 temp_dir2.path().AppendASCII("applications"))); | 198 temp_dir2.path().AppendASCII("applications"))); |
| 200 ASSERT_TRUE(file_util::WriteFile( | 199 ASSERT_TRUE(file_util::WriteFile( |
| 201 temp_dir2.path().AppendASCII("applications") | 200 temp_dir2.path().AppendASCII("applications") |
| 202 .AppendASCII(kTemplateFilename), | 201 .AppendASCII(kTemplateFilename), |
| 203 kTestData2, strlen(kTestData2))); | 202 kTestData2, strlen(kTestData2))); |
| 204 std::string contents; | 203 std::string contents; |
| 205 ASSERT_TRUE(ShellIntegrationLinux::GetDesktopShortcutTemplate(&env, | 204 ASSERT_TRUE( |
| 206 &contents)); | 205 ShellIntegrationLinux::GetExistingDesktopShortcutContents( |
| 206 &env, kTemplateFilepath, &contents)); |
| 207 EXPECT_EQ(kTestData2, contents); | 207 EXPECT_EQ(kTestData2, contents); |
| 208 } | 208 } |
| 209 } | 209 } |
| 210 | 210 |
| 211 TEST(ShellIntegrationTest, GetDesktopShortcutTemplate) { |
| 212 #if defined(GOOGLE_CHROME_BUILD) |
| 213 const char kTemplateFilename[] = "google-chrome.desktop"; |
| 214 #else // CHROMIUM_BUILD |
| 215 const char kTemplateFilename[] = "chromium-browser.desktop"; |
| 216 #endif |
| 217 |
| 218 const char kTestData[] = "a magical testing string"; |
| 219 |
| 220 MessageLoop message_loop; |
| 221 content::TestBrowserThread file_thread(BrowserThread::FILE, &message_loop); |
| 222 |
| 223 // Just do a simple test. The details are covered by |
| 224 // GetExistingDesktopShortcutContents test. |
| 225 { |
| 226 base::ScopedTempDir temp_dir; |
| 227 ASSERT_TRUE(temp_dir.CreateUniqueTempDir()); |
| 228 |
| 229 MockEnvironment env; |
| 230 env.Set("XDG_DATA_HOME", temp_dir.path().value()); |
| 231 ASSERT_TRUE(file_util::CreateDirectory( |
| 232 temp_dir.path().AppendASCII("applications"))); |
| 233 ASSERT_TRUE(file_util::WriteFile( |
| 234 temp_dir.path().AppendASCII("applications") |
| 235 .AppendASCII(kTemplateFilename), |
| 236 kTestData, strlen(kTestData))); |
| 237 std::string contents; |
| 238 ASSERT_TRUE(ShellIntegrationLinux::GetDesktopShortcutTemplate(&env, |
| 239 &contents)); |
| 240 EXPECT_EQ(kTestData, contents); |
| 241 } |
| 242 } |
| 243 |
| 211 TEST(ShellIntegrationTest, GetWebShortcutFilename) { | 244 TEST(ShellIntegrationTest, GetWebShortcutFilename) { |
| 212 const struct { | 245 const struct { |
| 213 const base::FilePath::CharType* path; | 246 const base::FilePath::CharType* path; |
| 214 const char* url; | 247 const char* url; |
| 215 } test_cases[] = { | 248 } test_cases[] = { |
| 216 { FPL("http___foo_.desktop"), "http://foo" }, | 249 { FPL("http___foo_.desktop"), "http://foo" }, |
| 217 { FPL("http___foo_bar_.desktop"), "http://foo/bar/" }, | 250 { FPL("http___foo_bar_.desktop"), "http://foo/bar/" }, |
| 218 { FPL("http___foo_bar_a=b&c=d.desktop"), "http://foo/bar?a=b&c=d" }, | 251 { FPL("http___foo_bar_a=b&c=d.desktop"), "http://foo/bar?a=b&c=d" }, |
| 219 | 252 |
| 220 // Now we're starting to be more evil... | 253 // Now we're starting to be more evil... |
| 221 { FPL("http___foo_.desktop"), "http://foo/bar/baz/../../../../../" }, | 254 { FPL("http___foo_.desktop"), "http://foo/bar/baz/../../../../../" }, |
| 222 { FPL("http___foo_.desktop"), "http://foo/bar/././../baz/././../" }, | 255 { FPL("http___foo_.desktop"), "http://foo/bar/././../baz/././../" }, |
| 223 { FPL("http___.._.desktop"), "http://../../../../" }, | 256 { FPL("http___.._.desktop"), "http://../../../../" }, |
| 224 }; | 257 }; |
| 225 for (size_t i = 0; i < ARRAYSIZE_UNSAFE(test_cases); i++) { | 258 for (size_t i = 0; i < ARRAYSIZE_UNSAFE(test_cases); i++) { |
| 226 EXPECT_EQ(std::string(chrome::kBrowserProcessExecutableName) + "-" + | 259 EXPECT_EQ(std::string(chrome::kBrowserProcessExecutableName) + "-" + |
| 227 test_cases[i].path, | 260 test_cases[i].path, |
| 228 ShellIntegrationLinux::GetWebShortcutFilename( | 261 ShellIntegrationLinux::GetWebShortcutFilename( |
| 229 GURL(test_cases[i].url)).value()) << | 262 GURL(test_cases[i].url)).value()) << |
| 230 " while testing " << test_cases[i].url; | 263 " while testing " << test_cases[i].url; |
| 231 } | 264 } |
| 232 } | 265 } |
| 233 | 266 |
| 234 TEST(ShellIntegrationTest, GetDesktopFileContents) { | 267 TEST(ShellIntegrationTest, GetDesktopFileContents) { |
| 235 const struct { | 268 const struct { |
| 236 const char* url; | 269 const char* url; |
| 237 const char* title; | 270 const char* title; |
| 238 const char* icon_name; | 271 const char* icon_name; |
| 272 bool nodisplay; |
| 239 const char* template_contents; | 273 const char* template_contents; |
| 240 const char* expected_output; | 274 const char* expected_output; |
| 241 } test_cases[] = { | 275 } test_cases[] = { |
| 242 // Dumb case. | 276 // Dumb case. |
| 243 { "ignored", "ignored", "ignored", "", "#!/usr/bin/env xdg-open\n" }, | 277 { "ignored", "ignored", "ignored", false, "", "#!/usr/bin/env xdg-open\n" }, |
| 244 | 278 |
| 245 // Real-world case. | 279 // Real-world case. |
| 246 { "http://gmail.com", | 280 { "http://gmail.com", |
| 247 "GMail", | 281 "GMail", |
| 248 "chrome-http__gmail.com", | 282 "chrome-http__gmail.com", |
| 283 false, |
| 249 | 284 |
| 250 "[Desktop Entry]\n" | 285 "[Desktop Entry]\n" |
| 251 "Version=1.0\n" | 286 "Version=1.0\n" |
| 252 "Encoding=UTF-8\n" | 287 "Encoding=UTF-8\n" |
| 253 "Name=Google Chrome\n" | 288 "Name=Google Chrome\n" |
| 254 "GenericName=Web Browser\n" | 289 "GenericName=Web Browser\n" |
| 255 "Comment=The web browser from Google\n" | 290 "Comment=The web browser from Google\n" |
| 256 "Exec=/opt/google/chrome/google-chrome %U\n" | 291 "Exec=/opt/google/chrome/google-chrome %U\n" |
| 257 "Terminal=false\n" | 292 "Terminal=false\n" |
| 258 "Icon=/opt/google/chrome/product_logo_48.png\n" | 293 "Icon=/opt/google/chrome/product_logo_48.png\n" |
| (...skipping 21 matching lines...) Expand all Loading... |
| 280 // Aura Chrome does not (yet) set WMClass, so we only expect | 315 // Aura Chrome does not (yet) set WMClass, so we only expect |
| 281 // StartupWMClass on non-Aura builds. | 316 // StartupWMClass on non-Aura builds. |
| 282 "StartupWMClass=gmail.com\n" | 317 "StartupWMClass=gmail.com\n" |
| 283 #endif | 318 #endif |
| 284 }, | 319 }, |
| 285 | 320 |
| 286 // Make sure we don't insert duplicate shebangs. | 321 // Make sure we don't insert duplicate shebangs. |
| 287 { "http://gmail.com", | 322 { "http://gmail.com", |
| 288 "GMail", | 323 "GMail", |
| 289 "chrome-http__gmail.com", | 324 "chrome-http__gmail.com", |
| 325 false, |
| 290 | 326 |
| 291 "#!/some/shebang\n" | 327 "#!/some/shebang\n" |
| 292 "[Desktop Entry]\n" | 328 "[Desktop Entry]\n" |
| 293 "Name=Google Chrome\n" | 329 "Name=Google Chrome\n" |
| 294 "Exec=/opt/google/chrome/google-chrome %U\n", | 330 "Exec=/opt/google/chrome/google-chrome %U\n", |
| 295 | 331 |
| 296 "#!/usr/bin/env xdg-open\n" | 332 "#!/usr/bin/env xdg-open\n" |
| 297 "[Desktop Entry]\n" | 333 "[Desktop Entry]\n" |
| 298 "Name=GMail\n" | 334 "Name=GMail\n" |
| 299 "Exec=/opt/google/chrome/google-chrome --app=http://gmail.com/\n" | 335 "Exec=/opt/google/chrome/google-chrome --app=http://gmail.com/\n" |
| 300 "Icon=chrome-http__gmail.com\n" | 336 "Icon=chrome-http__gmail.com\n" |
| 301 #if !defined(USE_AURA) | 337 #if !defined(USE_AURA) |
| 302 // Aura Chrome does not (yet) set WMClass, so we only expect | 338 // Aura Chrome does not (yet) set WMClass, so we only expect |
| 303 // StartupWMClass on non-Aura builds. | 339 // StartupWMClass on non-Aura builds. |
| 304 "StartupWMClass=gmail.com\n" | 340 "StartupWMClass=gmail.com\n" |
| 305 #endif | 341 #endif |
| 306 }, | 342 }, |
| 307 | 343 |
| 308 // Make sure i18n-ed names and other fields are removed. | 344 // Make sure i18n-ed names and other fields are removed. |
| 309 { "http://gmail.com", | 345 { "http://gmail.com", |
| 310 "GMail", | 346 "GMail", |
| 311 "chrome-http__gmail.com", | 347 "chrome-http__gmail.com", |
| 348 false, |
| 312 | 349 |
| 313 "[Desktop Entry]\n" | 350 "[Desktop Entry]\n" |
| 314 "Name=Google Chrome\n" | 351 "Name=Google Chrome\n" |
| 315 "Name[en_AU]=Google Chrome\n" | 352 "Name[en_AU]=Google Chrome\n" |
| 316 "Name[pl]=Google Chrome\n" | 353 "Name[pl]=Google Chrome\n" |
| 317 "GenericName=Web Browser\n" | 354 "GenericName=Web Browser\n" |
| 318 "GenericName[en_AU]=Web Browser\n" | 355 "GenericName[en_AU]=Web Browser\n" |
| 319 "GenericName[pl]=Navegador Web\n" | 356 "GenericName[pl]=Navegador Web\n" |
| 320 "Exec=/opt/google/chrome/google-chrome %U\n" | 357 "Exec=/opt/google/chrome/google-chrome %U\n" |
| 321 "Comment[en_AU]=Some comment.\n" | 358 "Comment[en_AU]=Some comment.\n" |
| 322 "Comment[pl]=Jakis komentarz.\n", | 359 "Comment[pl]=Jakis komentarz.\n", |
| 323 | 360 |
| 324 "#!/usr/bin/env xdg-open\n" | 361 "#!/usr/bin/env xdg-open\n" |
| 325 "[Desktop Entry]\n" | 362 "[Desktop Entry]\n" |
| 326 "Name=GMail\n" | 363 "Name=GMail\n" |
| 327 "Exec=/opt/google/chrome/google-chrome --app=http://gmail.com/\n" | 364 "Exec=/opt/google/chrome/google-chrome --app=http://gmail.com/\n" |
| 328 "Icon=chrome-http__gmail.com\n" | 365 "Icon=chrome-http__gmail.com\n" |
| 329 #if !defined(USE_AURA) | 366 #if !defined(USE_AURA) |
| 330 // Aura Chrome does not (yet) set WMClass, so we only expect | 367 // Aura Chrome does not (yet) set WMClass, so we only expect |
| 331 // StartupWMClass on non-Aura builds. | 368 // StartupWMClass on non-Aura builds. |
| 332 "StartupWMClass=gmail.com\n" | 369 "StartupWMClass=gmail.com\n" |
| 333 #endif | 370 #endif |
| 334 }, | 371 }, |
| 335 | 372 |
| 336 // Make sure that empty icons are replaced by the chrome icon. | 373 // Make sure that empty icons are replaced by the chrome icon. |
| 337 { "http://gmail.com", | 374 { "http://gmail.com", |
| 338 "GMail", | 375 "GMail", |
| 339 "", | 376 "", |
| 377 false, |
| 340 | 378 |
| 341 "[Desktop Entry]\n" | 379 "[Desktop Entry]\n" |
| 342 "Name=Google Chrome\n" | 380 "Name=Google Chrome\n" |
| 343 "Exec=/opt/google/chrome/google-chrome %U\n" | 381 "Exec=/opt/google/chrome/google-chrome %U\n" |
| 344 "Comment[pl]=Jakis komentarz.\n" | 382 "Comment[pl]=Jakis komentarz.\n" |
| 345 "Icon=/opt/google/chrome/product_logo_48.png\n", | 383 "Icon=/opt/google/chrome/product_logo_48.png\n", |
| 346 | 384 |
| 347 "#!/usr/bin/env xdg-open\n" | 385 "#!/usr/bin/env xdg-open\n" |
| 348 "[Desktop Entry]\n" | 386 "[Desktop Entry]\n" |
| 349 "Name=GMail\n" | 387 "Name=GMail\n" |
| 350 "Exec=/opt/google/chrome/google-chrome --app=http://gmail.com/\n" | 388 "Exec=/opt/google/chrome/google-chrome --app=http://gmail.com/\n" |
| 351 "Icon=/opt/google/chrome/product_logo_48.png\n" | 389 "Icon=/opt/google/chrome/product_logo_48.png\n" |
| 352 #if !defined(USE_AURA) | 390 #if !defined(USE_AURA) |
| 353 // Aura Chrome does not (yet) set WMClass, so we only expect | 391 // Aura Chrome does not (yet) set WMClass, so we only expect |
| 354 // StartupWMClass on non-Aura builds. | 392 // StartupWMClass on non-Aura builds. |
| 355 "StartupWMClass=gmail.com\n" | 393 "StartupWMClass=gmail.com\n" |
| 356 #endif | 394 #endif |
| 357 }, | 395 }, |
| 358 | 396 |
| 397 // Test adding NoDisplay=true. |
| 398 { "http://gmail.com", |
| 399 "GMail", |
| 400 "chrome-http__gmail.com", |
| 401 true, |
| 402 |
| 403 "[Desktop Entry]\n" |
| 404 "Name=Google Chrome\n" |
| 405 "Exec=/opt/google/chrome/google-chrome %U\n", |
| 406 |
| 407 "#!/usr/bin/env xdg-open\n" |
| 408 "[Desktop Entry]\n" |
| 409 "Name=GMail\n" |
| 410 "Exec=/opt/google/chrome/google-chrome --app=http://gmail.com/\n" |
| 411 "Icon=chrome-http__gmail.com\n" |
| 412 "NoDisplay=true\n" |
| 413 #if !defined(USE_AURA) |
| 414 // Aura Chrome does not (yet) set WMClass, so we only expect |
| 415 // StartupWMClass on non-Aura builds. |
| 416 "StartupWMClass=gmail.com\n" |
| 417 #endif |
| 418 }, |
| 419 |
| 359 // Now we're starting to be more evil... | 420 // Now we're starting to be more evil... |
| 360 { "http://evil.com/evil --join-the-b0tnet", | 421 { "http://evil.com/evil --join-the-b0tnet", |
| 361 "Ownz0red\nExec=rm -rf /", | 422 "Ownz0red\nExec=rm -rf /", |
| 362 "chrome-http__evil.com_evil", | 423 "chrome-http__evil.com_evil", |
| 424 false, |
| 363 | 425 |
| 364 "[Desktop Entry]\n" | 426 "[Desktop Entry]\n" |
| 365 "Name=Google Chrome\n" | 427 "Name=Google Chrome\n" |
| 366 "Exec=/opt/google/chrome/google-chrome %U\n", | 428 "Exec=/opt/google/chrome/google-chrome %U\n", |
| 367 | 429 |
| 368 "#!/usr/bin/env xdg-open\n" | 430 "#!/usr/bin/env xdg-open\n" |
| 369 "[Desktop Entry]\n" | 431 "[Desktop Entry]\n" |
| 370 "Name=http://evil.com/evil%20--join-the-b0tnet\n" | 432 "Name=http://evil.com/evil%20--join-the-b0tnet\n" |
| 371 "Exec=/opt/google/chrome/google-chrome " | 433 "Exec=/opt/google/chrome/google-chrome " |
| 372 "--app=http://evil.com/evil%20--join-the-b0tnet\n" | 434 "--app=http://evil.com/evil%20--join-the-b0tnet\n" |
| 373 "Icon=chrome-http__evil.com_evil\n" | 435 "Icon=chrome-http__evil.com_evil\n" |
| 374 #if !defined(USE_AURA) | 436 #if !defined(USE_AURA) |
| 375 // Aura Chrome does not (yet) set WMClass, so we only expect | 437 // Aura Chrome does not (yet) set WMClass, so we only expect |
| 376 // StartupWMClass on non-Aura builds. | 438 // StartupWMClass on non-Aura builds. |
| 377 "StartupWMClass=evil.com__evil%20--join-the-b0tnet\n" | 439 "StartupWMClass=evil.com__evil%20--join-the-b0tnet\n" |
| 378 #endif | 440 #endif |
| 379 }, | 441 }, |
| 380 { "http://evil.com/evil; rm -rf /; \"; rm -rf $HOME >ownz0red", | 442 { "http://evil.com/evil; rm -rf /; \"; rm -rf $HOME >ownz0red", |
| 381 "Innocent Title", | 443 "Innocent Title", |
| 382 "chrome-http__evil.com_evil", | 444 "chrome-http__evil.com_evil", |
| 445 false, |
| 383 | 446 |
| 384 "[Desktop Entry]\n" | 447 "[Desktop Entry]\n" |
| 385 "Name=Google Chrome\n" | 448 "Name=Google Chrome\n" |
| 386 "Exec=/opt/google/chrome/google-chrome %U\n", | 449 "Exec=/opt/google/chrome/google-chrome %U\n", |
| 387 | 450 |
| 388 "#!/usr/bin/env xdg-open\n" | 451 "#!/usr/bin/env xdg-open\n" |
| 389 "[Desktop Entry]\n" | 452 "[Desktop Entry]\n" |
| 390 "Name=Innocent Title\n" | 453 "Name=Innocent Title\n" |
| 391 "Exec=/opt/google/chrome/google-chrome " | 454 "Exec=/opt/google/chrome/google-chrome " |
| 392 "\"--app=http://evil.com/evil;%20rm%20-rf%20/;%20%22;%20rm%20" | 455 "\"--app=http://evil.com/evil;%20rm%20-rf%20/;%20%22;%20rm%20" |
| 393 // Note: $ is escaped as \$ within an arg to Exec, and then | 456 // Note: $ is escaped as \$ within an arg to Exec, and then |
| 394 // the \ is escaped as \\ as all strings in a Desktop file should | 457 // the \ is escaped as \\ as all strings in a Desktop file should |
| 395 // be; finally, \\ becomes \\\\ when represented in a C++ string! | 458 // be; finally, \\ becomes \\\\ when represented in a C++ string! |
| 396 "-rf%20\\\\$HOME%20%3Eownz0red\"\n" | 459 "-rf%20\\\\$HOME%20%3Eownz0red\"\n" |
| 397 "Icon=chrome-http__evil.com_evil\n" | 460 "Icon=chrome-http__evil.com_evil\n" |
| 398 #if !defined(USE_AURA) | 461 #if !defined(USE_AURA) |
| 399 // Aura Chrome does not (yet) set WMClass, so we only expect | 462 // Aura Chrome does not (yet) set WMClass, so we only expect |
| 400 // StartupWMClass on non-Aura builds. | 463 // StartupWMClass on non-Aura builds. |
| 401 "StartupWMClass=evil.com__evil;%20rm%20-rf%20_;%20%22;%20" | 464 "StartupWMClass=evil.com__evil;%20rm%20-rf%20_;%20%22;%20" |
| 402 "rm%20-rf%20$HOME%20%3Eownz0red\n" | 465 "rm%20-rf%20$HOME%20%3Eownz0red\n" |
| 403 #endif | 466 #endif |
| 404 }, | 467 }, |
| 405 { "http://evil.com/evil | cat `echo ownz0red` >/dev/null", | 468 { "http://evil.com/evil | cat `echo ownz0red` >/dev/null", |
| 406 "Innocent Title", | 469 "Innocent Title", |
| 407 "chrome-http__evil.com_evil", | 470 "chrome-http__evil.com_evil", |
| 471 false, |
| 408 | 472 |
| 409 "[Desktop Entry]\n" | 473 "[Desktop Entry]\n" |
| 410 "Name=Google Chrome\n" | 474 "Name=Google Chrome\n" |
| 411 "Exec=/opt/google/chrome/google-chrome %U\n", | 475 "Exec=/opt/google/chrome/google-chrome %U\n", |
| 412 | 476 |
| 413 "#!/usr/bin/env xdg-open\n" | 477 "#!/usr/bin/env xdg-open\n" |
| 414 "[Desktop Entry]\n" | 478 "[Desktop Entry]\n" |
| 415 "Name=Innocent Title\n" | 479 "Name=Innocent Title\n" |
| 416 "Exec=/opt/google/chrome/google-chrome " | 480 "Exec=/opt/google/chrome/google-chrome " |
| 417 "--app=http://evil.com/evil%20%7C%20cat%20%60echo%20ownz0red" | 481 "--app=http://evil.com/evil%20%7C%20cat%20%60echo%20ownz0red" |
| (...skipping 19 matching lines...) Expand all Loading... |
| 437 EXPECT_EQ( | 501 EXPECT_EQ( |
| 438 test_cases[i].expected_output, | 502 test_cases[i].expected_output, |
| 439 ShellIntegrationLinux::GetDesktopFileContents( | 503 ShellIntegrationLinux::GetDesktopFileContents( |
| 440 test_cases[i].template_contents, | 504 test_cases[i].template_contents, |
| 441 web_app::GenerateApplicationNameFromURL(GURL(test_cases[i].url)), | 505 web_app::GenerateApplicationNameFromURL(GURL(test_cases[i].url)), |
| 442 GURL(test_cases[i].url), | 506 GURL(test_cases[i].url), |
| 443 "", | 507 "", |
| 444 base::FilePath(), | 508 base::FilePath(), |
| 445 ASCIIToUTF16(test_cases[i].title), | 509 ASCIIToUTF16(test_cases[i].title), |
| 446 test_cases[i].icon_name, | 510 test_cases[i].icon_name, |
| 447 base::FilePath())); | 511 base::FilePath(), |
| 512 test_cases[i].nodisplay)); |
| 448 } | 513 } |
| 449 } | 514 } |
| 515 |
| 516 TEST(ShellIntegrationTest, DesktopShortcutLocations) { |
| 517 base::FilePath kProfilePath("Default"); |
| 518 const char kExtensionId[] = "test_extension"; |
| 519 const char kTemplateFilename[] = "chrome-test_extension-Default.desktop"; |
| 520 base::FilePath kTemplateFilepath(kTemplateFilename); |
| 521 const char kNoDisplayDesktopFile[] = "[Desktop Entry]\nNoDisplay=true"; |
| 522 |
| 523 MessageLoop message_loop; |
| 524 content::TestBrowserThread file_thread(BrowserThread::FILE, &message_loop); |
| 525 |
| 526 // No existing shortcuts. |
| 527 { |
| 528 MockEnvironment env; |
| 529 ShellIntegration::ShortcutLocations result = |
| 530 ShellIntegrationLinux::DesktopShortcutLocations( |
| 531 &env, kProfilePath, kExtensionId); |
| 532 EXPECT_FALSE(result.on_desktop); |
| 533 EXPECT_FALSE(result.in_applications_menu); |
| 534 EXPECT_FALSE(result.in_quick_launch_bar); |
| 535 } |
| 536 |
| 537 // Shortcut on desktop. |
| 538 { |
| 539 base::ScopedTempDir temp_dir; |
| 540 ASSERT_TRUE(temp_dir.CreateUniqueTempDir()); |
| 541 base::FilePath desktop_path = temp_dir.path(); |
| 542 |
| 543 MockEnvironment env; |
| 544 ASSERT_TRUE(file_util::CreateDirectory(desktop_path)); |
| 545 ASSERT_FALSE(file_util::WriteFile( |
| 546 desktop_path.AppendASCII(kTemplateFilename), |
| 547 "", 0)); |
| 548 ShellIntegration::ShortcutLocations result = |
| 549 ShellIntegrationLinux::DesktopShortcutLocations( |
| 550 &env, kProfilePath, kExtensionId, desktop_path); |
| 551 EXPECT_TRUE(result.on_desktop); |
| 552 EXPECT_FALSE(result.in_applications_menu); |
| 553 EXPECT_FALSE(result.in_quick_launch_bar); |
| 554 } |
| 555 |
| 556 // Shortcut in applications directory. |
| 557 { |
| 558 base::ScopedTempDir temp_dir; |
| 559 ASSERT_TRUE(temp_dir.CreateUniqueTempDir()); |
| 560 base::FilePath apps_path = temp_dir.path().AppendASCII("applications"); |
| 561 |
| 562 MockEnvironment env; |
| 563 env.Set("XDG_DATA_HOME", temp_dir.path().value()); |
| 564 ASSERT_TRUE(file_util::CreateDirectory(apps_path)); |
| 565 ASSERT_FALSE(file_util::WriteFile( |
| 566 apps_path.AppendASCII(kTemplateFilename), |
| 567 "", 0)); |
| 568 ShellIntegration::ShortcutLocations result = |
| 569 ShellIntegrationLinux::DesktopShortcutLocations( |
| 570 &env, kProfilePath, kExtensionId); |
| 571 EXPECT_FALSE(result.on_desktop); |
| 572 EXPECT_TRUE(result.in_applications_menu); |
| 573 EXPECT_FALSE(result.in_quick_launch_bar); |
| 574 } |
| 575 |
| 576 // Shortcut in applications directory with NoDisplay=true. |
| 577 { |
| 578 base::ScopedTempDir temp_dir; |
| 579 ASSERT_TRUE(temp_dir.CreateUniqueTempDir()); |
| 580 base::FilePath apps_path = temp_dir.path().AppendASCII("applications"); |
| 581 |
| 582 MockEnvironment env; |
| 583 env.Set("XDG_DATA_HOME", temp_dir.path().value()); |
| 584 ASSERT_TRUE(file_util::CreateDirectory(apps_path)); |
| 585 ASSERT_TRUE(file_util::WriteFile( |
| 586 apps_path.AppendASCII(kTemplateFilename), |
| 587 kNoDisplayDesktopFile, strlen(kNoDisplayDesktopFile))); |
| 588 ShellIntegration::ShortcutLocations result = |
| 589 ShellIntegrationLinux::DesktopShortcutLocations( |
| 590 &env, kProfilePath, kExtensionId); |
| 591 // Doesn't count as being in applications menu. |
| 592 EXPECT_FALSE(result.on_desktop); |
| 593 EXPECT_FALSE(result.in_applications_menu); |
| 594 EXPECT_FALSE(result.in_quick_launch_bar); |
| 595 } |
| 596 |
| 597 // Shortcut on desktop and in applications directory. |
| 598 { |
| 599 base::ScopedTempDir temp_dir1; |
| 600 ASSERT_TRUE(temp_dir1.CreateUniqueTempDir()); |
| 601 base::FilePath desktop_path = temp_dir1.path(); |
| 602 |
| 603 base::ScopedTempDir temp_dir2; |
| 604 ASSERT_TRUE(temp_dir2.CreateUniqueTempDir()); |
| 605 base::FilePath apps_path = temp_dir2.path().AppendASCII("applications"); |
| 606 |
| 607 MockEnvironment env; |
| 608 ASSERT_TRUE(file_util::CreateDirectory(desktop_path)); |
| 609 ASSERT_FALSE(file_util::WriteFile( |
| 610 desktop_path.AppendASCII(kTemplateFilename), |
| 611 "", 0)); |
| 612 env.Set("XDG_DATA_HOME", temp_dir2.path().value()); |
| 613 ASSERT_TRUE(file_util::CreateDirectory(apps_path)); |
| 614 ASSERT_FALSE(file_util::WriteFile( |
| 615 apps_path.AppendASCII(kTemplateFilename), |
| 616 "", 0)); |
| 617 ShellIntegration::ShortcutLocations result = |
| 618 ShellIntegrationLinux::DesktopShortcutLocations( |
| 619 &env, kProfilePath, kExtensionId, desktop_path); |
| 620 EXPECT_TRUE(result.on_desktop); |
| 621 EXPECT_TRUE(result.in_applications_menu); |
| 622 EXPECT_FALSE(result.in_quick_launch_bar); |
| 623 } |
| 624 } |
| 625 |
| 450 #endif | 626 #endif |
| OLD | NEW |