Chromium Code Reviews| Index: chrome/browser/extensions/network_delay_listener_unittest.cc |
| =================================================================== |
| --- chrome/browser/extensions/network_delay_listener_unittest.cc (revision 0) |
| +++ chrome/browser/extensions/network_delay_listener_unittest.cc (revision 0) |
| @@ -0,0 +1,284 @@ |
| +// Copyright (c) 2011 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 "base/message_loop.h" |
| +#include "chrome/browser/extensions/extension_host.h" |
| +#include "chrome/browser/extensions/extension_service_unittest.h" |
| +#include "chrome/browser/extensions/network_delay_listener.h" |
| +#include "chrome/common/chrome_notification_types.h" |
| +#include "chrome/common/chrome_paths.h" |
| +#include "chrome/common/chrome_view_types.h" |
| +#include "chrome/common/extensions/extension_file_util.h" |
| +#include "content/browser/mock_resource_context.h" |
| +#include "content/browser/renderer_host/dummy_resource_handler.h" |
| +#include "content/browser/renderer_host/resource_dispatcher_host_request_info.h" |
| +#include "content/browser/renderer_host/resource_queue.h" |
| +#include "content/browser/site_instance.h" |
| +#include "content/common/notification_service.h" |
| +#include "net/url_request/url_request.h" |
| +#include "net/url_request/url_request_test_job.h" |
| +#include "net/url_request/url_request_test_util.h" |
| + |
| +#include "testing/gtest/include/gtest/gtest.h" |
| + |
| +class Profile; |
| + |
| +using content::DummyResourceHandler; |
| + |
| +namespace { |
| + |
| +const char kTestUrl[] = "http://www.google.com/"; |
| +const char kTestData[] = "Hello, World!"; |
| +const char kTestExtensionId1[] = "jfjjgilipffmpphcikcmjdaoomecgelc"; |
| +const char kTestExtensionId2[] = "pjohnlkdpdolplmenneanegndccmdlpc"; |
| +const char kTestExtensionNoNetworkDelay[] = "aocebcndggcnnmflapdklcmnfojmkmie"; |
| + |
| +ResourceDispatcherHostRequestInfo* CreateRequestInfo(int request_id) { |
| + return new ResourceDispatcherHostRequestInfo( |
| + new DummyResourceHandler(), ChildProcessInfo::RENDER_PROCESS, 0, 0, 0, |
| + request_id, false, -1, ResourceType::MAIN_FRAME, PageTransition::LINK, 0, |
| + false, false, false, content::MockResourceContext::GetInstance()); |
| +} |
| + |
| +// A simple test net::URLRequestJob. We don't care what it does, only whether |
| +// it starts and finishes. |
| +class SimpleTestJob : public net::URLRequestTestJob { |
| + public: |
| + explicit SimpleTestJob(net::URLRequest* request) |
| + : net::URLRequestTestJob(request, test_headers(), kTestData, true) {} |
| + private: |
| + ~SimpleTestJob() {} |
| +}; |
| + |
| +// An ExtensionHost that doesn't require a Profile or TabContents, to use |
| +// in notifications to the NetworkDelayListener. |
| +class TestExtensionHost : public ExtensionHost { |
| + public: |
| + explicit TestExtensionHost(const Extension* extension, |
|
Pam (message me for reviews)
2011/10/12 14:35:03
Oops, I'll remove "explicit".
|
| + content::ViewType::Type host_type) |
| + : ExtensionHost(extension, host_type) { |
| + } |
| +}; |
| + |
| +} // namespace |
| + |
| +class NetworkDelayListenerTest |
| + : public ExtensionServiceTestBase, |
| + public net::URLRequest::Interceptor { |
| + public: |
| + NetworkDelayListenerTest() { |
| + net::URLRequest::Deprecated::RegisterRequestInterceptor(this); |
| + } |
| + |
| + ~NetworkDelayListenerTest() { |
| + net::URLRequest::Deprecated::UnregisterRequestInterceptor(this); |
| + } |
| + |
| + virtual void SetUp() { |
| + ExtensionServiceTestBase::SetUp(); |
| + |
| + InitializeEmptyExtensionService(); |
| + service_->Init(); |
| + MessageLoop::current()->RunAllPending(); |
| + |
| + listener_ = new NetworkDelayListener(); |
| + |
| + ResourceQueue::DelegateSet delegates; |
| + delegates.insert(listener_.get()); |
| + resource_queue_.Initialize(delegates); |
| + } |
| + |
| + virtual void TearDown() { |
| + resource_queue_.Shutdown(); |
| + listener_ = NULL; |
| + MessageLoop::current()->RunAllPending(); |
| + } |
| + |
| + // net::URLRequest::Interceptor |
| + virtual net::URLRequestJob* MaybeIntercept(net::URLRequest* request) { |
| + return new SimpleTestJob(request); |
| + } |
| + |
| + protected: |
| + TestURLRequest* StartTestRequest(net::URLRequest::Delegate* delegate, |
| + const std::string& url) { |
| + TestURLRequest* request = new TestURLRequest(GURL(url), delegate); |
| + scoped_ptr<ResourceDispatcherHostRequestInfo> rdh_info( |
| + CreateRequestInfo(0)); |
| + resource_queue_.AddRequest(request, *rdh_info.get()); |
| + return request; |
| + } |
| + |
| + void LoadTestExtension(const char* id) { |
| + FilePath test_dir; |
| + ASSERT_TRUE(PathService::Get(chrome::DIR_TEST_DATA, &test_dir)); |
| + FilePath extension_path = test_dir |
| + .AppendASCII("extensions") |
| + .AppendASCII("network_delay") |
| + .AppendASCII(id) |
| + .AppendASCII("1.0"); |
| + |
| + service_->LoadExtension(extension_path); |
| + MessageLoop::current()->RunAllPending(); |
| + } |
| + |
| + void LoadTestExtension1() { |
| + LoadTestExtension(kTestExtensionId1); |
| + ASSERT_FALSE(service_->extensions()->empty()); |
| + extension1_ = service_->extensions()->at(0).get(); |
| + ASSERT_FALSE(extension1_ == NULL); |
| + } |
| + |
| + void SendExtensionLoadedNotification(const Extension* extension) { |
| + scoped_ptr<TestExtensionHost> background_host( |
| + new TestExtensionHost(extension, |
| + chrome::ViewType::EXTENSION_BACKGROUND_PAGE)); |
| + NotificationService::current()->Notify( |
| + chrome::NOTIFICATION_EXTENSION_HOST_DID_STOP_LOADING, |
| + Source<Profile>(profile_.get()), |
| + Details<ExtensionHost>(background_host.get())); |
| + MessageLoop::current()->RunAllPending(); |
| + } |
| + |
| + void SendExtensionsReadyNotification() { |
| + NotificationService::current()->Notify( |
| + chrome::NOTIFICATION_EXTENSIONS_READY, |
| + Source<Profile>(profile_.get()), |
| + NotificationService::NoDetails()); |
| + MessageLoop::current()->RunAllPending(); |
| + } |
| + |
| + scoped_refptr<NetworkDelayListener> listener_; |
| + |
| + // Weak reference. |
| + const Extension* extension1_; |
| + |
| + private: |
| + ResourceQueue resource_queue_; |
| +}; |
| + |
| +namespace { |
| + |
| +// Tests that an extension delays network requests, and that loading its |
| +// background page releases the block. |
| +TEST_F(NetworkDelayListenerTest, DelayAndLoad) { |
| + LoadTestExtension1(); |
| + |
| + TestDelegate delegate; |
| + scoped_ptr<TestURLRequest> request(StartTestRequest(&delegate, kTestUrl)); |
| + ASSERT_FALSE(request->is_pending()); |
| + |
| + // We don't care about a loaded extension dialog. |
| + scoped_ptr<TestExtensionHost> dialog_host( |
| + new TestExtensionHost(extension1_, chrome::ViewType::EXTENSION_DIALOG)); |
| + NotificationService::current()->Notify( |
| + chrome::NOTIFICATION_EXTENSION_HOST_DID_STOP_LOADING, |
| + Source<Profile>(profile_.get()), |
| + Details<ExtensionHost>(dialog_host.get())); |
| + MessageLoop::current()->RunAllPending(); |
| + |
| + SendExtensionLoadedNotification(extension1_); |
| + EXPECT_EQ(kTestData, delegate.data_received()); |
| +} |
| + |
| +// Tests that an extension delays network requests, and that unloading it |
| +// releases the block. |
| +TEST_F(NetworkDelayListenerTest, DelayAndUnload) { |
| + LoadTestExtension1(); |
| + |
| + TestDelegate delegate; |
| + scoped_ptr<TestURLRequest> request(StartTestRequest(&delegate, kTestUrl)); |
| + ASSERT_FALSE(request->is_pending()); |
| + |
| + service_->UnloadExtension(extension1_->id(), |
| + extension_misc::UNLOAD_REASON_DISABLE); |
| + MessageLoop::current()->RunAllPending(); |
| + EXPECT_EQ(kTestData, delegate.data_received()); |
| +} |
| + |
| +// Tests that two blocking extensions must both load for the block to be |
| +// released. |
| +TEST_F(NetworkDelayListenerTest, TwoBlockingExtensions) { |
| + LoadTestExtension1(); |
| + LoadTestExtension(kTestExtensionId2); |
| + ASSERT_EQ(2, service_->extensions()->size()); |
| + const Extension* extension2 = service_->extensions()->at(1).get(); |
| + ASSERT_FALSE(extension2 == NULL); |
| + |
| + TestDelegate delegate; |
| + scoped_ptr<TestURLRequest> request(StartTestRequest(&delegate, kTestUrl)); |
| + ASSERT_FALSE(request->is_pending()); |
| + |
| + SendExtensionLoadedNotification(extension1_); |
| + ASSERT_FALSE(request->is_pending()); |
| + |
| + SendExtensionLoadedNotification(extension2); |
| + EXPECT_EQ(kTestData, delegate.data_received()); |
| +} |
| + |
| +// Tests that unloading a fully loaded extension (i.e., saying it's "ready" |
| +// twice) doesn't crash. |
| +TEST_F(NetworkDelayListenerTest, ExtensionReadyTwice) { |
| + LoadTestExtension1(); |
| + |
| + TestDelegate delegate; |
| + scoped_ptr<TestURLRequest> request(StartTestRequest(&delegate, kTestUrl)); |
| + ASSERT_FALSE(request->is_pending()); |
| + |
| + SendExtensionLoadedNotification(extension1_); |
| + EXPECT_EQ(kTestData, delegate.data_received()); |
| + |
| + service_->UnloadExtension(extension1_->id(), |
| + extension_misc::UNLOAD_REASON_DISABLE); |
| + MessageLoop::current()->RunAllPending(); |
| +} |
| + |
| +// Tests that the misleadingly named NOTIFICATION_EXTENSIONS_READY doesn't |
| +// release network requests. |
| +TEST_F(NetworkDelayListenerTest, ExtensionsReadyNotReady) { |
| + LoadTestExtension1(); |
| + |
| + TestDelegate delegate; |
| + scoped_ptr<TestURLRequest> request(StartTestRequest(&delegate, kTestUrl)); |
| + ASSERT_FALSE(request->is_pending()); |
| + |
| + SendExtensionsReadyNotification(); |
| + ASSERT_FALSE(request->is_pending()); |
| + |
| + SendExtensionLoadedNotification(extension1_); |
| + EXPECT_EQ(kTestData, delegate.data_received()); |
| +} |
| + |
| +// Tests that there's no delay if no loaded extension needs one. |
| +TEST_F(NetworkDelayListenerTest, NoDelayNoWebRequest) { |
| + LoadTestExtension(kTestExtensionNoNetworkDelay); |
| + ASSERT_FALSE(service_->extensions()->empty()); |
| + |
| + SendExtensionsReadyNotification(); |
| + |
| + TestDelegate delegate; |
| + scoped_ptr<TestURLRequest> request(StartTestRequest(&delegate, kTestUrl)); |
| + |
| + // The request should be started immediately. |
| + ASSERT_TRUE(request->is_pending()); |
| + |
| + MessageLoop::current()->RunAllPending(); |
| + EXPECT_EQ(kTestData, delegate.data_received()); |
| +} |
| + |
| +// Tests that there's no delay if no extensions are loaded. |
| +TEST_F(NetworkDelayListenerTest, NoDelayNoExtensions) { |
| + SendExtensionsReadyNotification(); |
| + |
| + TestDelegate delegate; |
| + scoped_ptr<TestURLRequest> request(StartTestRequest(&delegate, kTestUrl)); |
| + |
| + // The request should be started immediately. |
| + ASSERT_TRUE(request->is_pending()); |
| + |
| + MessageLoop::current()->RunAllPending(); |
| + EXPECT_EQ(kTestData, delegate.data_received()); |
| +} |
| + |
| +} // namespace |
| Property changes on: chrome\browser\extensions\network_delay_listener_unittest.cc |
| ___________________________________________________________________ |
| Added: svn:executable |
| + * |
| Added: svn:eol-style |
| + LF |