Home | History | Annotate | Download | only in extensions
      1 // Copyright (c) 2011 The Chromium Authors. All rights reserved.
      2 // Use of this source code is governed by a BSD-style license that can be
      3 // found in the LICENSE file.
      4 
      5 #include "base/message_loop.h"
      6 #include "base/threading/thread.h"
      7 #include "chrome/browser/extensions/extension_service_unittest.h"
      8 #include "chrome/browser/extensions/user_script_listener.h"
      9 #include "chrome/common/chrome_paths.h"
     10 #include "chrome/common/extensions/extension_file_util.h"
     11 #include "content/browser/renderer_host/global_request_id.h"
     12 #include "content/browser/renderer_host/resource_dispatcher_host_request_info.h"
     13 #include "content/browser/renderer_host/resource_handler.h"
     14 #include "content/browser/renderer_host/resource_queue.h"
     15 #include "content/common/notification_service.h"
     16 #include "content/common/notification_type.h"
     17 #include "net/url_request/url_request.h"
     18 #include "net/url_request/url_request_test_job.h"
     19 #include "net/url_request/url_request_test_util.h"
     20 #include "testing/gtest/include/gtest/gtest.h"
     21 
     22 class Profile;
     23 
     24 namespace {
     25 
     26 const char kMatchingUrl[] = "http://google.com/";
     27 const char kNotMatchingUrl[] = "http://example.com/";
     28 const char kTestData[] = "Hello, World!";
     29 
     30 // Dummy ResourceHandler required for ResourceDispatcherHostRequestInfo.
     31 class DummyResourceHandler : public ResourceHandler {
     32  public:
     33   DummyResourceHandler() {
     34   }
     35 
     36   virtual bool OnUploadProgress(int request_id, uint64 position, uint64 size) {
     37     NOTREACHED();
     38     return true;
     39   }
     40 
     41 
     42   virtual bool OnRequestRedirected(int request_id, const GURL& url,
     43                                    ResourceResponse* response,
     44                                    bool* defer) {
     45     NOTREACHED();
     46     return true;
     47   }
     48 
     49   virtual bool OnResponseStarted(int request_id,
     50                                  ResourceResponse* response) {
     51     NOTREACHED();
     52     return true;
     53   }
     54 
     55   virtual bool OnWillStart(int request_id,
     56                            const GURL& url,
     57                            bool* defer) {
     58     NOTREACHED();
     59     return true;
     60   }
     61 
     62   virtual bool OnWillRead(int request_id,
     63                           net::IOBuffer** buf,
     64                           int* buf_size,
     65                           int min_size) {
     66     NOTREACHED();
     67     return true;
     68   }
     69 
     70   virtual bool OnReadCompleted(int request_id, int* bytes_read) {
     71     NOTREACHED();
     72     return true;
     73   }
     74 
     75   virtual bool OnResponseCompleted(int request_id,
     76                                    const net::URLRequestStatus& status,
     77                                    const std::string& security_info) {
     78     NOTREACHED();
     79     return true;
     80   }
     81 
     82   virtual void OnRequestClosed() {
     83   }
     84 
     85  private:
     86   DISALLOW_COPY_AND_ASSIGN(DummyResourceHandler);
     87 };
     88 
     89 ResourceDispatcherHostRequestInfo* CreateRequestInfo(int request_id) {
     90   return new ResourceDispatcherHostRequestInfo(
     91       new DummyResourceHandler(), ChildProcessInfo::RENDER_PROCESS, 0, 0,
     92       request_id, ResourceType::MAIN_FRAME, 0, false, false, false);
     93 }
     94 
     95 // A simple test net::URLRequestJob. We don't care what it does, only that
     96 // whether it starts and finishes.
     97 class SimpleTestJob : public net::URLRequestTestJob {
     98  public:
     99   explicit SimpleTestJob(net::URLRequest* request)
    100     : net::URLRequestTestJob(request, test_headers(), kTestData, true) {}
    101  private:
    102   ~SimpleTestJob() {}
    103 };
    104 
    105 class UserScriptListenerTest
    106     : public ExtensionServiceTestBase,
    107       public net::URLRequest::Interceptor {
    108  public:
    109   UserScriptListenerTest() {
    110     net::URLRequest::RegisterRequestInterceptor(this);
    111   }
    112 
    113   ~UserScriptListenerTest() {
    114     net::URLRequest::UnregisterRequestInterceptor(this);
    115   }
    116 
    117   virtual void SetUp() {
    118     ExtensionServiceTestBase::SetUp();
    119 
    120     InitializeEmptyExtensionService();
    121     service_->Init();
    122     MessageLoop::current()->RunAllPending();
    123 
    124     listener_ = new UserScriptListener();
    125 
    126     ResourceQueue::DelegateSet delegates;
    127     delegates.insert(listener_.get());
    128     resource_queue_.Initialize(delegates);
    129   }
    130 
    131   virtual void TearDown() {
    132     resource_queue_.Shutdown();
    133     listener_ = NULL;
    134     MessageLoop::current()->RunAllPending();
    135   }
    136 
    137   // net::URLRequest::Interceptor
    138   virtual net::URLRequestJob* MaybeIntercept(net::URLRequest* request) {
    139     return new SimpleTestJob(request);
    140   }
    141 
    142  protected:
    143   TestURLRequest* StartTestRequest(net::URLRequest::Delegate* delegate,
    144                                    const std::string& url) {
    145     TestURLRequest* request = new TestURLRequest(GURL(url), delegate);
    146     scoped_ptr<ResourceDispatcherHostRequestInfo> rdh_info(
    147         CreateRequestInfo(0));
    148     resource_queue_.AddRequest(request, *rdh_info.get());
    149     return request;
    150   }
    151 
    152   void LoadTestExtension() {
    153     FilePath test_dir;
    154     ASSERT_TRUE(PathService::Get(chrome::DIR_TEST_DATA, &test_dir));
    155     FilePath extension_path = test_dir
    156         .AppendASCII("extensions")
    157         .AppendASCII("good")
    158         .AppendASCII("Extensions")
    159         .AppendASCII("behllobkkfkfnphdnhnkndlbkcpglgmj")
    160         .AppendASCII("1.0.0.0");
    161     service_->LoadExtension(extension_path);
    162   }
    163 
    164   void UnloadTestExtension() {
    165     ASSERT_FALSE(service_->extensions()->empty());
    166     service_->UnloadExtension(service_->extensions()->at(0)->id(),
    167                               UnloadedExtensionInfo::DISABLE);
    168   }
    169 
    170   scoped_refptr<UserScriptListener> listener_;
    171 
    172  private:
    173   ResourceQueue resource_queue_;
    174 };
    175 
    176 TEST_F(UserScriptListenerTest, DelayAndUpdate) {
    177   LoadTestExtension();
    178   MessageLoop::current()->RunAllPending();
    179 
    180   TestDelegate delegate;
    181   scoped_ptr<TestURLRequest> request(StartTestRequest(&delegate, kMatchingUrl));
    182   ASSERT_FALSE(request->is_pending());
    183 
    184   NotificationService::current()->Notify(
    185       NotificationType::USER_SCRIPTS_UPDATED,
    186       Source<Profile>(profile_.get()),
    187       NotificationService::NoDetails());
    188   MessageLoop::current()->RunAllPending();
    189   EXPECT_EQ(kTestData, delegate.data_received());
    190 }
    191 
    192 TEST_F(UserScriptListenerTest, DelayAndUnload) {
    193   LoadTestExtension();
    194   MessageLoop::current()->RunAllPending();
    195 
    196   TestDelegate delegate;
    197   scoped_ptr<TestURLRequest> request(StartTestRequest(&delegate, kMatchingUrl));
    198   ASSERT_FALSE(request->is_pending());
    199 
    200   UnloadTestExtension();
    201   MessageLoop::current()->RunAllPending();
    202 
    203   // This is still not enough to start delayed requests. We have to notify the
    204   // listener that the user scripts have been updated.
    205   ASSERT_FALSE(request->is_pending());
    206 
    207   NotificationService::current()->Notify(
    208       NotificationType::USER_SCRIPTS_UPDATED,
    209       Source<Profile>(profile_.get()),
    210       NotificationService::NoDetails());
    211   MessageLoop::current()->RunAllPending();
    212   EXPECT_EQ(kTestData, delegate.data_received());
    213 }
    214 
    215 TEST_F(UserScriptListenerTest, NoDelayNoExtension) {
    216   TestDelegate delegate;
    217   scoped_ptr<TestURLRequest> request(StartTestRequest(&delegate, kMatchingUrl));
    218 
    219   // The request should be started immediately.
    220   ASSERT_TRUE(request->is_pending());
    221 
    222   MessageLoop::current()->RunAllPending();
    223   EXPECT_EQ(kTestData, delegate.data_received());
    224 }
    225 
    226 TEST_F(UserScriptListenerTest, NoDelayNotMatching) {
    227   LoadTestExtension();
    228   MessageLoop::current()->RunAllPending();
    229 
    230   TestDelegate delegate;
    231   scoped_ptr<TestURLRequest> request(StartTestRequest(&delegate,
    232                                                       kNotMatchingUrl));
    233 
    234   // The request should be started immediately.
    235   ASSERT_TRUE(request->is_pending());
    236 
    237   MessageLoop::current()->RunAllPending();
    238   EXPECT_EQ(kTestData, delegate.data_received());
    239 }
    240 
    241 }  // namespace
    242