Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(94)

Unified Diff: chrome/browser/extensions/user_script_listener_unittest.cc

Issue 173482: Re-try r24372 - Delay request loading until all user scripts that request (Closed)
Patch Set: Created 11 years, 4 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « chrome/browser/extensions/user_script_listener.cc ('k') | chrome/browser/extensions/user_script_master.h » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: chrome/browser/extensions/user_script_listener_unittest.cc
diff --git a/chrome/browser/extensions/user_script_listener_unittest.cc b/chrome/browser/extensions/user_script_listener_unittest.cc
new file mode 100644
index 0000000000000000000000000000000000000000..d4fb326a526998ea890dc7bda1b25c76fe18e4ca
--- /dev/null
+++ b/chrome/browser/extensions/user_script_listener_unittest.cc
@@ -0,0 +1,308 @@
+// 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.
+
+#include <algorithm>
+#include <vector>
+
+#include "base/message_loop.h"
+#include "base/thread.h"
+#include "chrome/browser/extensions/extensions_service.h"
+#include "chrome/browser/renderer_host/resource_dispatcher_host.h"
+#include "chrome/common/chrome_paths.h"
+#include "chrome/common/chrome_plugin_lib.h"
+#include "chrome/common/notification_service.h"
+#include "chrome/common/render_messages.h"
+#include "chrome/test/testing_profile.h"
+#include "ipc/ipc_message.h"
+#include "net/url_request/url_request.h"
+#include "net/url_request/url_request_test_job.h"
+#include "testing/gtest/include/gtest/gtest.h"
+#include "webkit/appcache/appcache_interfaces.h"
+
+// A simple test URLRequestJob. We don't care what it does, only that whether it
+// starts and finishes.
+class SimpleTestJob : public URLRequestTestJob {
+ public:
+ explicit SimpleTestJob(URLRequest* request)
+ : URLRequestTestJob(request, test_headers(), test_data_1(), true) {}
+};
+
+class MockUserScriptMaster : public UserScriptMaster {
+public:
+ MockUserScriptMaster(MessageLoop* worker, const FilePath& script_dir) :
+ UserScriptMaster(worker, script_dir) { }
+
+ virtual void StartScan() {
+ // Do nothing. We want to manually control when scans occur.
+ }
+ void TestStartScan() {
+ UserScriptMaster::StartScan();
+ }
+};
+
+class MockIOThread : public base::Thread {
+ public:
+ MockIOThread() : base::Thread("IO") {}
+ virtual ~MockIOThread() { Stop(); }
+
+ private:
+ virtual void Init() {
+ service_.reset(new NotificationService());
+ }
+ virtual void CleanUp() {
+ ChromePluginLib::UnloadAllPlugins();
+ service_.reset();
+ }
+
+ scoped_ptr<NotificationService> service_;
+};
+
+// A class to help with making and handling resource requests.
+class ResourceDispatcherHostTester :
+ public ResourceDispatcherHost::Receiver,
+ public URLRequest::Interceptor,
+ public base::RefCountedThreadSafe<ResourceDispatcherHostTester> {
+ public:
+ ResourceDispatcherHostTester(MessageLoop* io_loop)
+ : Receiver(ChildProcessInfo::RENDER_PROCESS),
+ host_(io_loop),
+ ui_loop_(MessageLoop::current()),
+ io_loop_(io_loop) {
+ URLRequest::RegisterRequestInterceptor(this);
+ }
+ virtual ~ResourceDispatcherHostTester() {
+ URLRequest::UnregisterRequestInterceptor(this);
+ }
+
+ void MakeTestRequest(int request_id, const GURL& url) {
+ io_loop_->PostTask(FROM_HERE, NewRunnableMethod(
+ this, &ResourceDispatcherHostTester::MakeTestRequestOnIOThread,
+ request_id, url));
+ MessageLoop::current()->Run(); // wait for Quit from IO thread
+ }
+
+ void WaitForScan(MockUserScriptMaster* master) {
+ master->TestStartScan();
+ MessageLoop::current()->RunAllPending(); // run the scan
+ io_loop_->PostTask(FROM_HERE, NewRunnableMethod(
+ this, &ResourceDispatcherHostTester::RunPending));
+ MessageLoop::current()->Run(); // wait for Quit from IO thread
+ }
+
+ bool IsRequestStarted(int request_id) {
+ return std::find(started_requests_.begin(), started_requests_.end(),
+ request_id) != started_requests_.end();
+ }
+
+ bool IsRequestComplete(int request_id) {
+ return std::find(completed_requests_.begin(), completed_requests_.end(),
+ request_id) != completed_requests_.end();
+ }
+
+ private:
+ // URLRequest::Interceptor
+ virtual URLRequestJob* MaybeIntercept(URLRequest* request) {
+ return new SimpleTestJob(request);
+ }
+
+ // ResourceDispatcherHost::Receiver implementation
+ virtual bool Send(IPC::Message* msg) {
+ IPC_BEGIN_MESSAGE_MAP(ResourceDispatcherHostTester, *msg)
+ IPC_MESSAGE_HANDLER(ViewMsg_Resource_ReceivedResponse, OnReceivedResponse)
+ IPC_MESSAGE_HANDLER(ViewMsg_Resource_RequestComplete, OnRequestComplete)
+ IPC_END_MESSAGE_MAP()
+ delete msg;
+ return true;
+ }
+
+ URLRequestContext* GetRequestContext(
+ uint32 request_id,
+ const ViewHostMsg_Resource_Request& request_data) {
+ return NULL;
+ }
+
+ // TODO(mpcomplete): Some of this stuff is copied from
+ // resource_dispatcher_host_unittest.cc. Consider sharing.
+ static ViewHostMsg_Resource_Request CreateResourceRequest(const char* method,
+ const GURL& url) {
+ ViewHostMsg_Resource_Request request;
+ request.method = std::string(method);
+ request.url = url;
+ request.first_party_for_cookies = url; // bypass third-party cookie
+ // blocking
+ request.resource_type = ResourceType::MAIN_FRAME;
+ request.load_flags = 0;
+ // init the rest to default values to prevent getting UMR.
+ request.frame_origin = "null";
+ request.main_frame_origin = "null";
+ request.origin_pid = 0;
+ request.request_context = 0;
+ request.appcache_host_id = appcache::kNoHostId;
+ return request;
+ }
+
+ void RunPending() {
+ MessageLoop::current()->SetNestableTasksAllowed(true);
+ MessageLoop::current()->RunAllPending();
+ MessageLoop::current()->SetNestableTasksAllowed(false);
+
+ // return control to UI thread.
+ ui_loop_->PostTask(FROM_HERE, new MessageLoop::QuitTask());
+ }
+
+ void MakeTestRequestOnIOThread(int request_id, const GURL& url) {
+ ViewHostMsg_Resource_Request request = CreateResourceRequest("GET", url);
+ ViewHostMsg_RequestResource msg(0, request_id, request);
+ bool msg_was_ok;
+ host_.OnMessageReceived(msg, this, &msg_was_ok);
+ RunPending();
+ }
+
+ void OnReceivedResponse(int request_id,
+ const ResourceResponseHead& response_head) {
+ started_requests_.push_back(request_id);
+ }
+
+ void OnRequestComplete(int request_id,
+ const URLRequestStatus& status,
+ const std::string& security_info) {
+ completed_requests_.push_back(request_id);
+ }
+
+ ResourceDispatcherHost host_;
+ MessageLoop* ui_loop_;
+ MessageLoop* io_loop_;
+
+ // Note: these variables are accessed on both threads, but since we only
+ // one thread executes at a time, they are safe.
+ std::vector<int> started_requests_;
+ std::vector<int> completed_requests_;
+};
+
+class UserScriptListenerTest : public testing::Test {
+ public:
+ virtual void SetUp() {
+ io_thread_.reset(new MockIOThread());
+ base::Thread::Options options(MessageLoop::TYPE_IO, 0);
+ io_thread_->StartWithOptions(options);
+ DCHECK(io_thread_->message_loop());
+ DCHECK(io_thread_->IsRunning());
+
+ FilePath install_dir = profile_.GetPath()
+ .AppendASCII(ExtensionsService::kInstallDirectoryName);
+
+ resource_tester_ =
+ new ResourceDispatcherHostTester(io_thread_->message_loop());
+
+ master_ = new MockUserScriptMaster(&loop_, install_dir);
+
+ service_ = new ExtensionsService(&profile_,
+ CommandLine::ForCurrentProcess(),
+ profile_.GetPrefs(),
+ install_dir,
+ &loop_,
+ &loop_,
+ false);
+ service_->set_extensions_enabled(true);
+ service_->set_show_extensions_prompts(false);
+ service_->ClearProvidersForTesting();
+ service_->Init();
+ }
+
+ virtual void TearDown() {
+ io_thread_.reset();
+ resource_tester_ = NULL;
+ }
+
+ protected:
+ TestingProfile profile_;
+ MessageLoopForUI loop_;
+ scoped_ptr<MockIOThread> io_thread_;
+ scoped_refptr<ResourceDispatcherHostTester> resource_tester_;
+ scoped_refptr<MockUserScriptMaster> master_;
+ scoped_refptr<ExtensionsService> service_;
+};
+
+// Loads a single extension and ensures that requests to URLs with content
+// scripts are delayed.
+TEST_F(UserScriptListenerTest, SingleExtension) {
+ FilePath extensions_path;
+ ASSERT_TRUE(PathService::Get(chrome::DIR_TEST_DATA, &extensions_path));
+ extensions_path = extensions_path.AppendASCII("extensions");
+ FilePath ext1 = extensions_path
+ .AppendASCII("good")
+ .AppendASCII("Extensions")
+ .AppendASCII("behllobkkfkfnphdnhnkndlbkcpglgmj")
+ .AppendASCII("1.0.0.0");
+ service_->LoadExtension(ext1);
+ loop_.RunAllPending();
+ ASSERT_EQ(1u, service_->extensions()->size());
+
+ // Our extension has a content script on google.com. That request should be
+ // delayed.
+ resource_tester_->MakeTestRequest(0, GURL("http://google.com/"));
+ resource_tester_->MakeTestRequest(1, GURL("http://yahoo.com/"));
+
+ EXPECT_FALSE(resource_tester_->IsRequestStarted(0));
+ EXPECT_TRUE(resource_tester_->IsRequestStarted(1));
+ EXPECT_TRUE(resource_tester_->IsRequestComplete(1));
+
+ // After scanning, the user scripts should be ready and the request can
+ // go through.
+ resource_tester_->WaitForScan(master_.get());
+
+ EXPECT_TRUE(resource_tester_->IsRequestStarted(0));
+ EXPECT_TRUE(resource_tester_->IsRequestComplete(0));
+}
+
+// Loads a single extension and ensures that requests to URLs with content
+// scripts are delayed.
+TEST_F(UserScriptListenerTest, UnloadExtension) {
+ FilePath extensions_path;
+ ASSERT_TRUE(PathService::Get(chrome::DIR_TEST_DATA, &extensions_path));
+ extensions_path = extensions_path.AppendASCII("extensions");
+
+ FilePath ext1 = extensions_path
+ .AppendASCII("good")
+ .AppendASCII("Extensions")
+ .AppendASCII("behllobkkfkfnphdnhnkndlbkcpglgmj")
+ .AppendASCII("1.0.0.0");
+ service_->LoadExtension(ext1);
+ loop_.RunAllPending();
+ ASSERT_EQ(1u, service_->extensions()->size());
+
+ FilePath ext2 = extensions_path
+ .AppendASCII("good")
+ .AppendASCII("Extensions")
+ .AppendASCII("bjafgdebaacbbbecmhlhpofkepfkgcpa")
+ .AppendASCII("1.0");
+ service_->LoadExtension(ext2);
+ loop_.RunAllPending();
+ ASSERT_EQ(2u, service_->extensions()->size());
+
+ // Our extension has a content script on google.com. That request should be
+ // delayed.
+ resource_tester_->MakeTestRequest(0, GURL("http://google.com/"));
+ resource_tester_->MakeTestRequest(1, GURL("http://yahoo.com/"));
+
+ EXPECT_FALSE(resource_tester_->IsRequestStarted(0));
+ EXPECT_TRUE(resource_tester_->IsRequestStarted(1));
+ EXPECT_TRUE(resource_tester_->IsRequestComplete(1));
+
+ // Unload the first extension and run a scan. Request should complete.
+ service_->UnloadExtension("behllobkkfkfnphdnhnkndlbkcpglgmj");
+ resource_tester_->WaitForScan(master_.get());
+
+ EXPECT_TRUE(resource_tester_->IsRequestStarted(0));
+ EXPECT_TRUE(resource_tester_->IsRequestComplete(0));
+
+ // Make the same requests, and they should complete instantly.
+ resource_tester_->MakeTestRequest(2, GURL("http://google.com/"));
+ resource_tester_->MakeTestRequest(3, GURL("http://yahoo.com/"));
+
+ EXPECT_TRUE(resource_tester_->IsRequestStarted(2));
+ EXPECT_TRUE(resource_tester_->IsRequestComplete(2));
+ EXPECT_TRUE(resource_tester_->IsRequestStarted(3));
+ EXPECT_TRUE(resource_tester_->IsRequestComplete(3));
+}
« no previous file with comments | « chrome/browser/extensions/user_script_listener.cc ('k') | chrome/browser/extensions/user_script_master.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698