diff options
15 files changed, 260 insertions, 155 deletions
diff --git a/chrome/browser/extensions/extension_startup_unittest.cc b/chrome/browser/extensions/extension_startup_unittest.cc new file mode 100644 index 0000000..ce9b885 --- /dev/null +++ b/chrome/browser/extensions/extension_startup_unittest.cc @@ -0,0 +1,204 @@ +#include <vector> + +#include "base/command_line.h" +#include "base/file_path.h" +#include "base/file_util.h" +#include "base/path_service.h" +#include "chrome/browser/browser.h" +#include "chrome/browser/extensions/extensions_service.h" +#include "chrome/browser/profile.h" +#include "chrome/common/chrome_paths.h" +#include "chrome/common/chrome_switches.h" +#include "chrome/common/notification_details.h" +#include "chrome/common/notification_observer.h" +#include "chrome/common/notification_registrar.h" +#include "chrome/common/notification_service.h" +#include "chrome/common/notification_type.h" +#include "chrome/test/in_process_browser_test.h" +#include "chrome/test/ui_test_utils.h" +#include "net/base/net_util.h" + +// This file contains high-level regression tests for the extensions system. The +// goal here is not to test everything in depth, but to run the system as close +// as possible end-to-end to find any gaps in test coverage in the lower-level +// unit tests. + +class ExtensionStartupTestBase + : public InProcessBrowserTest, public NotificationObserver { + public: + ExtensionStartupTestBase() + : enable_extensions_(false), enable_user_scripts_(false) { + EnableDOMAutomation(); + } + + protected: + // InProcessBrowserTest + virtual void SetUpCommandLine(CommandLine* command_line) { + FilePath profile_dir; + PathService::Get(chrome::DIR_USER_DATA, &profile_dir); + profile_dir = profile_dir.AppendASCII("Default"); + file_util::CreateDirectory(profile_dir); + + preferences_file_ = profile_dir.AppendASCII("Preferences"); + user_scripts_dir_ = profile_dir.AppendASCII("User Scripts"); + extensions_dir_ = profile_dir.AppendASCII("Extensions"); + + if (enable_extensions_) { + command_line->AppendSwitch(switches::kEnableExtensions); + + FilePath src_dir; + PathService::Get(chrome::DIR_TEST_DATA, &src_dir); + src_dir = src_dir.AppendASCII("extensions").AppendASCII("good"); + + file_util::CopyFile(src_dir.AppendASCII("Preferences"), + preferences_file_); + file_util::CopyDirectory(src_dir.AppendASCII("Extensions"), + profile_dir, true); // recursive + } + + if (enable_user_scripts_) { + command_line->AppendSwitch(switches::kEnableUserScripts); + + FilePath src_dir; + PathService::Get(chrome::DIR_TEST_DATA, &src_dir); + src_dir = src_dir.AppendASCII("extensions").AppendASCII("good") + .AppendASCII("Extensions") + .AppendASCII("behllobkkfkfnphdnhnkndlbkcpglgmj") + .AppendASCII("1.0.0.0"); + + file_util::CreateDirectory(user_scripts_dir_); + file_util::CopyFile(src_dir.AppendASCII("script2.js"), + user_scripts_dir_.AppendASCII("script2.user.js")); + } + } + + // NotificationObserver + virtual void Observe(NotificationType type, + const NotificationSource& source, + const NotificationDetails& details) { + switch (type.value) { + case NotificationType::EXTENSIONS_READY: + case NotificationType::USER_SCRIPTS_UPDATED: + MessageLoopForUI::current()->Quit(); + break; + } + } + + virtual void TearDown() { + file_util::Delete(preferences_file_, false); + file_util::Delete(user_scripts_dir_, true); + file_util::Delete(extensions_dir_, true); + } + + FilePath preferences_file_; + FilePath extensions_dir_; + FilePath user_scripts_dir_; + bool enable_extensions_; + bool enable_user_scripts_; + NotificationRegistrar registrar_; +}; + + +// ExtensionsStartupTest +// Ensures that we can startup the browser with --enable-extensions and some +// extensions installed and see them run and do basic things. + +class ExtensionsStartupTest : public ExtensionStartupTestBase { + public: + ExtensionsStartupTest() { + enable_extensions_ = true; + } +}; + +IN_PROC_BROWSER_TEST_F(ExtensionsStartupTest, Test) { + ExtensionsService* service = browser()->profile()->GetExtensionsService(); + if (!service->is_ready()) { + registrar_.Add(this, NotificationType::EXTENSIONS_READY, + NotificationService::AllSources()); + ui_test_utils::RunMessageLoop(); + registrar_.Remove(this, NotificationType::EXTENSIONS_READY, + NotificationService::AllSources()); + } + ASSERT_EQ(3u, service->extensions()->size()); + ASSERT_TRUE(service->extensions_enabled()); + + UserScriptMaster* master = browser()->profile()->GetUserScriptMaster(); + if (!master->ScriptsReady()) { + // Wait for UserScriptMaster to finish its scan. + registrar_.Add(this, NotificationType::USER_SCRIPTS_UPDATED, + NotificationService::AllSources()); + ui_test_utils::RunMessageLoop(); + registrar_.Remove(this, NotificationType::USER_SCRIPTS_UPDATED, + NotificationService::AllSources()); + } + ASSERT_TRUE(master->ScriptsReady()); + + FilePath test_file; + PathService::Get(chrome::DIR_TEST_DATA, &test_file); + test_file = test_file.AppendASCII("extensions") + .AppendASCII("test_file.html"); + + // Now we should be able to load a page affected by the content script and see + // the effect. + ui_test_utils::NavigateToURL(browser(), net::FilePathToFileURL(test_file)); + + // Test that the content script ran. + bool result = false; + ui_test_utils::ExecuteJavaScriptAndExtractBool( + browser()->GetSelectedTabContents(), L"", + L"window.domAutomationController.send(" + L"document.defaultView.getComputedStyle(document.body, null)." + L"getPropertyValue('background-color') == 'rgb(245, 245, 220)')", + &result); + EXPECT_TRUE(result); + + ui_test_utils::ExecuteJavaScriptAndExtractBool( + browser()->GetSelectedTabContents(), L"", + L"window.domAutomationController.send(document.title == 'Modified')", + &result); + EXPECT_TRUE(result); + + // TODO(aa): Move the stuff in ExtensionBrowserTest here? +} + + +// ExtensionsStartupUserScriptTest +// Tests that we can startup with --enable-user-scripts and run user sripts and +// see them do basic things. + +class ExtensionsStartupUserScriptTest : public ExtensionStartupTestBase { + public: + ExtensionsStartupUserScriptTest() { + enable_user_scripts_ = true; + } +}; + +IN_PROC_BROWSER_TEST_F(ExtensionsStartupUserScriptTest, Test) { + UserScriptMaster* master = browser()->profile()->GetUserScriptMaster(); + if (!master->ScriptsReady()) { + // Wait for UserScriptMaster to finish its scan. + registrar_.Add(this, NotificationType::USER_SCRIPTS_UPDATED, + NotificationService::AllSources()); + ui_test_utils::RunMessageLoop(); + registrar_.Remove(this, NotificationType::USER_SCRIPTS_UPDATED, + NotificationService::AllSources()); + } + ASSERT_TRUE(master->ScriptsReady()); + + FilePath test_file; + PathService::Get(chrome::DIR_TEST_DATA, &test_file); + test_file = test_file.AppendASCII("extensions") + .AppendASCII("test_file.html"); + + // Now we should be able to load a page affected by the content script and see + // the effect. + ui_test_utils::NavigateToURL(browser(), net::FilePathToFileURL(test_file)); + + // Test that the user script ran. + bool result = false; + ui_test_utils::ExecuteJavaScriptAndExtractBool( + browser()->GetSelectedTabContents(), L"", + L"window.domAutomationController.send(document.title == 'Modified')", + &result); + EXPECT_TRUE(result); +} diff --git a/chrome/browser/extensions/extensions_service_unittest.cc b/chrome/browser/extensions/extensions_service_unittest.cc index 8de8b61..92cd377 100644 --- a/chrome/browser/extensions/extensions_service_unittest.cc +++ b/chrome/browser/extensions/extensions_service_unittest.cc @@ -521,11 +521,13 @@ TEST_F(ExtensionsServiceTest, LoadAllExtensionsFromDirectorySuccess) { const UserScriptList& scripts = extension->content_scripts(); const std::vector<std::string>& toolstrips = extension->toolstrips(); ASSERT_EQ(2u, scripts.size()); - EXPECT_EQ(2u, scripts[0].url_patterns().size()); - EXPECT_EQ("http://*.google.com/*", + EXPECT_EQ(3u, scripts[0].url_patterns().size()); + EXPECT_EQ("file://*", scripts[0].url_patterns()[0].GetAsString()); - EXPECT_EQ("https://*.google.com/*", + EXPECT_EQ("http://*.google.com/*", scripts[0].url_patterns()[1].GetAsString()); + EXPECT_EQ("https://*.google.com/*", + scripts[0].url_patterns()[2].GetAsString()); EXPECT_EQ(2u, scripts[0].js_scripts().size()); EXPECT_EQ( NormalizeSeperators(extension->path().AppendASCII("script1.js").value()), @@ -1389,10 +1391,41 @@ TEST_F(ExtensionsServiceTest, ExternalPrefProvider) { EXPECT_EQ(1, visitor.Visit(json_data, ignore_list)); } +class ExtensionsReadyRecorder : public NotificationObserver { + public: + ExtensionsReadyRecorder() : ready_(false) { + registrar_.Add(this, NotificationType::EXTENSIONS_READY, + NotificationService::AllSources()); + } + + void set_ready(bool value) { ready_ = value; } + bool ready() { return ready_; } + + private: + virtual void Observe(NotificationType type, + const NotificationSource& source, + const NotificationDetails& details) { + switch (type.value) { + case NotificationType::EXTENSIONS_READY: + ready_ = true; + break; + default: + NOTREACHED(); + } + } + + NotificationRegistrar registrar_; + bool ready_; +}; + // Test that we get enabled/disabled correctly for all the pref/command-line // combinations. We don't want to derive from the ExtensionsServiceTest class // for this test, so we use ExtensionsServiceTestSimple. +// +// Also tests that we always fire EXTENSIONS_READY, no matter whether we are +// enabled or not. TEST(ExtensionsServiceTestSimple, Enabledness) { + ExtensionsReadyRecorder recorder; TestingProfile profile; MessageLoop loop; scoped_ptr<CommandLine> command_line; @@ -1405,20 +1438,35 @@ TEST(ExtensionsServiceTestSimple, Enabledness) { service = new ExtensionsService(&profile, command_line.get(), profile.GetPrefs(), install_dir, &loop, &loop); EXPECT_FALSE(service->extensions_enabled()); + service->Init(); + loop.RunAllPending(); + EXPECT_TRUE(recorder.ready()); // If either the command line or pref is set, we are enabled. + recorder.set_ready(false); command_line->AppendSwitch(switches::kEnableExtensions); service = new ExtensionsService(&profile, command_line.get(), profile.GetPrefs(), install_dir, &loop, &loop); EXPECT_TRUE(service->extensions_enabled()); + service->Init(); + loop.RunAllPending(); + EXPECT_TRUE(recorder.ready()); + recorder.set_ready(false); profile.GetPrefs()->SetBoolean(prefs::kEnableExtensions, true); service = new ExtensionsService(&profile, command_line.get(), profile.GetPrefs(), install_dir, &loop, &loop); EXPECT_TRUE(service->extensions_enabled()); + service->Init(); + loop.RunAllPending(); + EXPECT_TRUE(recorder.ready()); + recorder.set_ready(false); command_line.reset(new CommandLine(L"")); service = new ExtensionsService(&profile, command_line.get(), profile.GetPrefs(), install_dir, &loop, &loop); EXPECT_TRUE(service->extensions_enabled()); + service->Init(); + loop.RunAllPending(); + EXPECT_TRUE(recorder.ready()); } diff --git a/chrome/chrome.gyp b/chrome/chrome.gyp index 26ebb7f..d47a5c0 100644 --- a/chrome/chrome.gyp +++ b/chrome/chrome.gyp @@ -24,6 +24,7 @@ ], 'browser_tests_sources_win_specific': [ 'browser/extensions/extension_shelf_model_unittest.cc', + 'browser/extensions/extension_startup_unittest.cc', 'browser/extensions/extension_browsertest.cc', 'browser/extensions/test_extension_loader.cc', 'browser/extensions/test_extension_loader.h', diff --git a/chrome/test/data/extensions/content_script_inject/js_test.js b/chrome/test/data/extensions/content_script_inject/js_test.js deleted file mode 100644 index 87a0930..0000000 --- a/chrome/test/data/extensions/content_script_inject/js_test.js +++ /dev/null @@ -1,33 +0,0 @@ -// Copyright (c) 2009 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -// A quick and dirty JavaScript test runner.
-
-function assert(truth) {
- if (!truth) {
- throw new Error('Assertion failed');
- }
-}
-
-function runAllTests() {
- // If there was already an error, do nothing. We don't want to muddy
- // up the results.
- if (document.title.indexOf("Error: ") == 0) {
- return;
- }
-
- for (var propName in window) {
- if (typeof window[propName] == "function" &&
- propName.indexOf("test") == 0) {
- try {
- window[propName]();
- document.title += propName + ",";
- } catch (e) {
- // We use document.title to communicate results back to the browser.
- document.title = "Error: " + propName + ': ' + e.message;
- return;
- }
- }
- }
-}
diff --git a/chrome/test/data/extensions/content_script_inject/manifest.json b/chrome/test/data/extensions/content_script_inject/manifest.json deleted file mode 100644 index 48e4496..0000000 --- a/chrome/test/data/extensions/content_script_inject/manifest.json +++ /dev/null @@ -1,20 +0,0 @@ -{ - "version": "1.0.0.0", - "name": "User script inject", - "content_scripts": [ - { - "matches": ["file://*/content_script_inject_page.html"], - "css": ["script1.css"], - "js": ["js_test.js", "script1a.js", "script1b.js"] - }, - { - "matches": ["file://*/content_script_inject_page.html"], - "js": ["js_test.js", "script2.js"] - }, - { - "matches": ["file://*/content_script_inject_page.html"], - "js": ["js_test.js", "script3.js"], - "run_at": "document_start" - } - ] -} diff --git a/chrome/test/data/extensions/content_script_inject/script1.css b/chrome/test/data/extensions/content_script_inject/script1.css deleted file mode 100644 index 521b501b..0000000 --- a/chrome/test/data/extensions/content_script_inject/script1.css +++ /dev/null @@ -1,10 +0,0 @@ -/* -Copyright (c) 2006-2009 The Chromium Authors. All rights reserved. -Use of this source code is governed by a BSD-style license that can be -found in the LICENSE file. -*/ - -/* script1b.js tests that this rule was applied. */ -body { - background:red; -} diff --git a/chrome/test/data/extensions/content_script_inject/script1a.js b/chrome/test/data/extensions/content_script_inject/script1a.js deleted file mode 100644 index 87f4f55..0000000 --- a/chrome/test/data/extensions/content_script_inject/script1a.js +++ /dev/null @@ -1,7 +0,0 @@ -// Copyright (c) 2009 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -// create a global variable. script1b.js tests to make sure it is visible and -// script2.js tests to make sure it is not. -var script1_var = 1; diff --git a/chrome/test/data/extensions/content_script_inject/script1b.js b/chrome/test/data/extensions/content_script_inject/script1b.js deleted file mode 100644 index 8e7e102..0000000 --- a/chrome/test/data/extensions/content_script_inject/script1b.js +++ /dev/null @@ -1,27 +0,0 @@ -// Copyright (c) 2009 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -// This tests that we are running in the same global context as script1a.js. -function testScriptFilesRunInSameContext() { - assert(script1_var === 1); -} - -// This tests that our relationship to content is working correctly. -// a) We should not see content globals in our global scope. -// b) We should have a contentWindow object that looks like a DOM Window. -// c) We should be able to access content globals via contentWindow. -function testContentInteraction() { - assert(typeof content_var == "undefined"); - assert(typeof contentWindow != "undefined"); - assert(contentWindow.location.href.match(/content_script_inject_page.html$/)); - assert(contentWindow.content_var == "hello"); -} - -// Test that our css in script1.css was injected successfully. -function testCSSWasInjected() { - assert(document.defaultView.getComputedStyle( - document.body, null)["background-color"] == "rgb(255, 0, 0)"); -} - -runAllTests(); diff --git a/chrome/test/data/extensions/content_script_inject/script2.js b/chrome/test/data/extensions/content_script_inject/script2.js deleted file mode 100644 index 9133afa2..0000000 --- a/chrome/test/data/extensions/content_script_inject/script2.js +++ /dev/null @@ -1,12 +0,0 @@ -// Copyright (c) 2009 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -// Tests that we cannot see global variables defined in other content scripts. -// This var was defined in script1a.js. We run each content script in a separate -// context, so we shouldn't see globals across them. -function testCannotSeeOtherContentScriptGlobals() {
- assert(typeof script1_var == "undefined");
-}
-
-runAllTests();
diff --git a/chrome/test/data/extensions/content_script_inject/script3.js b/chrome/test/data/extensions/content_script_inject/script3.js deleted file mode 100644 index 15bc225..0000000 --- a/chrome/test/data/extensions/content_script_inject/script3.js +++ /dev/null @@ -1,31 +0,0 @@ -// Copyright (c) 2009 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -var gotDOMContentLoadedEvent = false; - -// Test that at parse time, we have the document element. -// This basically tests that we don't get injected too early (before there is -// a document element). -var hasDocumentElement = (document.documentElement.tagName == "HTML"); - -// TODO(aa): We would like to add more tests here verifying that we aren't -// injected too late. For example, we could test that there are zero child -// nodes to the documentElement, but unfortunately run_at:document_start is -// currently buggy and doesn't guarantee that. - -window.addEventListener("DOMContentLoaded", function() { - gotDOMContentLoadedEvent = true; -}, false); - -// Don't run tests until onload so that we can test that DOMContentLoaded and -// onload happen after this script runs. -window.addEventListener("load", runAllTests, false); - -function testRunAtDocumentStart() { - assert(hasDocumentElement); -} - -function testGotLoadEvents() { - assert(gotDOMContentLoadedEvent); -} diff --git a/chrome/test/data/extensions/content_script_inject_page.html b/chrome/test/data/extensions/content_script_inject_page.html deleted file mode 100644 index 4412e19..0000000 --- a/chrome/test/data/extensions/content_script_inject_page.html +++ /dev/null @@ -1,10 +0,0 @@ -<html> -<head> -<title></title> -<script> -var content_var = "hello"; -</script> -</head> -<body> -</body> -</html> diff --git a/chrome/test/data/extensions/good/Extensions/behllobkkfkfnphdnhnkndlbkcpglgmj/1.0.0.0/manifest.json b/chrome/test/data/extensions/good/Extensions/behllobkkfkfnphdnhnkndlbkcpglgmj/1.0.0.0/manifest.json index 544b6b6..c2255cc 100644 --- a/chrome/test/data/extensions/good/Extensions/behllobkkfkfnphdnhnkndlbkcpglgmj/1.0.0.0/manifest.json +++ b/chrome/test/data/extensions/good/Extensions/behllobkkfkfnphdnhnkndlbkcpglgmj/1.0.0.0/manifest.json @@ -10,7 +10,7 @@ "permissions": ["http://*.google.com/*", "https://*.google.com/*"], "content_scripts": [ { - "matches": ["http://*.google.com/*", "https://*.google.com/*"], + "matches": ["file://*", "http://*.google.com/*", "https://*.google.com/*"], "js": ["script1.js", "script2.js"], "css": ["style1.css", "style2.css", "style2.css"] }, diff --git a/chrome/test/data/extensions/good/Extensions/behllobkkfkfnphdnhnkndlbkcpglgmj/1.0.0.0/script2.js b/chrome/test/data/extensions/good/Extensions/behllobkkfkfnphdnhnkndlbkcpglgmj/1.0.0.0/script2.js index 4ffd7b9..b6dc38e 100644 --- a/chrome/test/data/extensions/good/Extensions/behllobkkfkfnphdnhnkndlbkcpglgmj/1.0.0.0/script2.js +++ b/chrome/test/data/extensions/good/Extensions/behllobkkfkfnphdnhnkndlbkcpglgmj/1.0.0.0/script2.js @@ -1 +1,2 @@ // script2 +document.title = "Modified"; diff --git a/chrome/test/data/extensions/test_file.html b/chrome/test/data/extensions/test_file.html new file mode 100755 index 0000000..9718b43 --- /dev/null +++ b/chrome/test/data/extensions/test_file.html @@ -0,0 +1 @@ +<title>Unmodified</title>
diff --git a/chrome/test/data/extensions/ui/create_extension_detail_value_expected_output/good-extension1.json b/chrome/test/data/extensions/ui/create_extension_detail_value_expected_output/good-extension1.json index 0f0e048..6c50242 100644 --- a/chrome/test/data/extensions/ui/create_extension_detail_value_expected_output/good-extension1.json +++ b/chrome/test/data/extensions/ui/create_extension_detail_value_expected_output/good-extension1.json @@ -6,7 +6,7 @@ "permissions": ["http://*.google.com/*", "https://*.google.com/*"], "content_scripts": [ { - "matches": ["http://*.google.com/*", "https://*.google.com/*"], + "matches": ["file://*", "http://*.google.com/*", "https://*.google.com/*"], "js": ["script1.js", "script2.js"], "css": ["style1.css", "style2.css", "style2.css"] }, |