From c407dc5cd9bdc5668497f21b26b09d988ab439de Mon Sep 17 00:00:00 2001 From: Ben Murdoch Date: Thu, 29 Jul 2010 17:14:53 +0100 Subject: Merge Chromium src@r53293 Change-Id: Ia79acf8670f385cee48c45b0a75371d8e950af34 --- .../extensions/user_script_master_unittest.cc | 264 +++++++++++++++++++++ 1 file changed, 264 insertions(+) create mode 100644 chrome/browser/extensions/user_script_master_unittest.cc (limited to 'chrome/browser/extensions/user_script_master_unittest.cc') diff --git a/chrome/browser/extensions/user_script_master_unittest.cc b/chrome/browser/extensions/user_script_master_unittest.cc new file mode 100644 index 0000000..3760941 --- /dev/null +++ b/chrome/browser/extensions/user_script_master_unittest.cc @@ -0,0 +1,264 @@ +// Copyright (c) 2008 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. + +#include "chrome/browser/extensions/user_script_master.h" + +#include + +#include "base/file_path.h" +#include "base/file_util.h" +#include "base/message_loop.h" +#include "base/path_service.h" +#include "base/string_util.h" +#include "chrome/browser/chrome_thread.h" +#include "chrome/common/notification_registrar.h" +#include "chrome/common/notification_service.h" +#include "chrome/test/testing_profile.h" +#include "testing/gtest/include/gtest/gtest.h" + +// Test bringing up a master on a specific directory, putting a script +// in there, etc. + +class UserScriptMasterTest : public testing::Test, + public NotificationObserver { + public: + UserScriptMasterTest() + : message_loop_(MessageLoop::TYPE_UI), + shared_memory_(NULL) { + } + + virtual void SetUp() { + // Name a subdirectory of the temp directory. + FilePath tmp_dir; + ASSERT_TRUE(PathService::Get(base::DIR_TEMP, &tmp_dir)); + script_dir_ = tmp_dir.AppendASCII("UserScriptTest"); + + // Create a fresh, empty copy of this directory. + file_util::Delete(script_dir_, true); + file_util::CreateDirectory(script_dir_); + + // Register for all user script notifications. + registrar_.Add(this, NotificationType::USER_SCRIPTS_UPDATED, + NotificationService::AllSources()); + + // UserScriptMaster posts tasks to the file thread so make the current + // thread look like one. + file_thread_.reset(new ChromeThread( + ChromeThread::FILE, MessageLoop::current())); + } + + virtual void TearDown() { + // Clean up test directory. + ASSERT_TRUE(file_util::Delete(script_dir_, true)); + ASSERT_FALSE(file_util::PathExists(script_dir_)); + file_thread_.reset(); + } + + virtual void Observe(NotificationType type, + const NotificationSource& source, + const NotificationDetails& details) { + DCHECK(type == NotificationType::USER_SCRIPTS_UPDATED); + + shared_memory_ = Details(details).ptr(); + if (MessageLoop::current() == &message_loop_) + MessageLoop::current()->Quit(); + } + + NotificationRegistrar registrar_; + + // MessageLoop used in tests. + MessageLoop message_loop_; + + scoped_ptr file_thread_; + + // Directory containing user scripts. + FilePath script_dir_; + + // Updated to the script shared memory when we get notified. + base::SharedMemory* shared_memory_; +}; + +// Test that we get notified even when there are no scripts. +TEST_F(UserScriptMasterTest, NoScripts) { + TestingProfile profile; + scoped_refptr master(new UserScriptMaster(script_dir_, + &profile)); + master->StartScan(); + message_loop_.PostTask(FROM_HERE, new MessageLoop::QuitTask); + message_loop_.Run(); + + ASSERT_TRUE(shared_memory_ != NULL); +} + +// Test that we get notified about scripts if they're already in the test dir. +TEST_F(UserScriptMasterTest, ExistingScripts) { + TestingProfile profile; + FilePath path = script_dir_.AppendASCII("script.user.js"); + + const char content[] = "some content"; + size_t written = file_util::WriteFile(path, content, sizeof(content)); + ASSERT_EQ(written, sizeof(content)); + + scoped_refptr master(new UserScriptMaster(script_dir_, + &profile)); + master->StartScan(); + + message_loop_.PostTask(FROM_HERE, new MessageLoop::QuitTask); + message_loop_.Run(); + + ASSERT_TRUE(shared_memory_ != NULL); +} + +TEST_F(UserScriptMasterTest, Parse1) { + const std::string text( + "// This is my awesome script\n" + "// It does stuff.\n" + "// ==UserScript== trailing garbage\n" + "// @name foobar script\n" + "// @namespace http://www.google.com/\n" + "// @include *mail.google.com*\n" + "// \n" + "// @othergarbage\n" + "// @include *mail.yahoo.com*\r\n" + "// @include \t *mail.msn.com*\n" // extra spaces after "@include" OK + "//@include not-recognized\n" // must have one space after "//" + "// ==/UserScript== trailing garbage\n" + "\n" + "\n" + "alert('hoo!');\n"); + + UserScript script; + EXPECT_TRUE(UserScriptMaster::ScriptReloader::ParseMetadataHeader( + text, &script)); + ASSERT_EQ(3U, script.globs().size()); + EXPECT_EQ("*mail.google.com*", script.globs()[0]); + EXPECT_EQ("*mail.yahoo.com*", script.globs()[1]); + EXPECT_EQ("*mail.msn.com*", script.globs()[2]); +} + +TEST_F(UserScriptMasterTest, Parse2) { + const std::string text("default to @include *"); + + UserScript script; + EXPECT_TRUE(UserScriptMaster::ScriptReloader::ParseMetadataHeader( + text, &script)); + ASSERT_EQ(1U, script.globs().size()); + EXPECT_EQ("*", script.globs()[0]); +} + +TEST_F(UserScriptMasterTest, Parse3) { + const std::string text( + "// ==UserScript==\n" + "// @include *foo*\n" + "// ==/UserScript=="); // no trailing newline + + UserScript script; + UserScriptMaster::ScriptReloader::ParseMetadataHeader(text, &script); + ASSERT_EQ(1U, script.globs().size()); + EXPECT_EQ("*foo*", script.globs()[0]); +} + +TEST_F(UserScriptMasterTest, Parse4) { + const std::string text( + "// ==UserScript==\n" + "// @match http://*.mail.google.com/*\n" + "// @match \t http://mail.yahoo.com/*\n" + "// ==/UserScript==\n"); + + UserScript script; + EXPECT_TRUE(UserScriptMaster::ScriptReloader::ParseMetadataHeader( + text, &script)); + EXPECT_EQ(0U, script.globs().size()); + ASSERT_EQ(2U, script.url_patterns().size()); + EXPECT_EQ("http://*.mail.google.com/*", + script.url_patterns()[0].GetAsString()); + EXPECT_EQ("http://mail.yahoo.com/*", + script.url_patterns()[1].GetAsString()); +} + +TEST_F(UserScriptMasterTest, Parse5) { + const std::string text( + "// ==UserScript==\n" + "// @match http://*mail.google.com/*\n" + "// ==/UserScript==\n"); + + // Invalid @match value. + UserScript script; + EXPECT_FALSE(UserScriptMaster::ScriptReloader::ParseMetadataHeader( + text, &script)); +} + +TEST_F(UserScriptMasterTest, Parse6) { + const std::string text( + "// ==UserScript==\n" + "// @include http://*.mail.google.com/*\n" + "// @match \t http://mail.yahoo.com/*\n" + "// ==/UserScript==\n"); + + // Allowed to match @include and @match. + UserScript script; + EXPECT_TRUE(UserScriptMaster::ScriptReloader::ParseMetadataHeader( + text, &script)); +} + +TEST_F(UserScriptMasterTest, Parse7) { + // Greasemonkey allows there to be any leading text before the comment marker. + const std::string text( + "// ==UserScript==\n" + "adsasdfasf// @name hello\n" + " // @description\twiggity woo\n" + "\t// @match \t http://mail.yahoo.com/*\n" + "// ==/UserScript==\n"); + + UserScript script; + EXPECT_TRUE(UserScriptMaster::ScriptReloader::ParseMetadataHeader( + text, &script)); + ASSERT_EQ("hello", script.name()); + ASSERT_EQ("wiggity woo", script.description()); + ASSERT_EQ(1U, script.url_patterns().size()); + EXPECT_EQ("http://mail.yahoo.com/*", + script.url_patterns()[0].GetAsString()); +} + +TEST_F(UserScriptMasterTest, SkipBOMAtTheBeginning) { + FilePath path = script_dir_.AppendASCII("script.user.js"); + + const std::string content( + "\xEF\xBB\xBF// ==UserScript==\n" + "// @match http://*.mail.google.com/*\n" + "// ==/UserScript==\n"); + size_t written = file_util::WriteFile(path, content.c_str(), content.size()); + ASSERT_EQ(written, content.size()); + + UserScriptList script_list; + UserScriptMaster::ScriptReloader::LoadScriptsFromDirectory( + script_dir_, &script_list); + ASSERT_EQ(1U, script_list.size()); + + EXPECT_EQ(content.substr(3), + script_list[0].js_scripts()[0].GetContent().as_string()); + EXPECT_EQ("http://*.mail.google.com/*", + script_list[0].url_patterns()[0].GetAsString()); +} + +TEST_F(UserScriptMasterTest, LeaveBOMNotAtTheBeginning) { + FilePath path = script_dir_.AppendASCII("script.user.js"); + + const std::string content( + "// ==UserScript==\n" + "// @match http://*.mail.google.com/*\n" + "// ==/UserScript==\n" + "// @bom \xEF\xBB\xBF"); + size_t written = file_util::WriteFile(path, content.c_str(), content.size()); + ASSERT_EQ(written, content.size()); + + UserScriptList script_list; + UserScriptMaster::ScriptReloader::LoadScriptsFromDirectory( + script_dir_, &script_list); + ASSERT_EQ(1U, script_list.size()); + + EXPECT_EQ(content, script_list[0].js_scripts()[0].GetContent().as_string()); + EXPECT_EQ("http://*.mail.google.com/*", + script_list[0].url_patterns()[0].GetAsString()); +} -- cgit v1.1