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