Home | History | Annotate | Download | only in search
      1 // Copyright 2013 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 "chrome/browser/search/iframe_source.h"
      6 
      7 #include "base/bind.h"
      8 #include "base/memory/ref_counted_memory.h"
      9 #include "base/memory/scoped_ptr.h"
     10 #include "base/message_loop/message_loop.h"
     11 #include "chrome/browser/search/instant_io_context.h"
     12 #include "content/public/browser/browser_thread.h"
     13 #include "content/public/browser/resource_request_info.h"
     14 #include "content/public/test/mock_resource_context.h"
     15 #include "content/public/test/test_browser_thread_bundle.h"
     16 #include "grit/browser_resources.h"
     17 #include "net/base/request_priority.h"
     18 #include "net/url_request/url_request.h"
     19 #include "net/url_request/url_request_context.h"
     20 #include "net/url_request/url_request_test_util.h"
     21 #include "testing/gtest/include/gtest/gtest.h"
     22 #include "url/gurl.h"
     23 
     24 const int kNonInstantRendererPID = 0;
     25 const char kNonInstantOrigin[] = "http://evil";
     26 const int kInstantRendererPID = 1;
     27 const char kInstantOrigin[] = "chrome-search://instant";
     28 const int kInvalidRendererPID = 42;
     29 
     30 class TestIframeSource : public IframeSource {
     31  public:
     32   using IframeSource::GetMimeType;
     33   using IframeSource::ShouldServiceRequest;
     34   using IframeSource::SendResource;
     35   using IframeSource::SendJSWithOrigin;
     36 
     37  protected:
     38   virtual std::string GetSource() const OVERRIDE {
     39     return "test";
     40   }
     41 
     42   virtual bool ServesPath(const std::string& path) const OVERRIDE {
     43     return path == "/valid.html" || path == "/valid.js";
     44   }
     45 
     46   virtual void StartDataRequest(
     47       const std::string& path,
     48       int render_process_id,
     49       int render_view_id,
     50       const content::URLDataSource::GotDataCallback& callback) OVERRIDE {
     51   }
     52 
     53   // RenderViewHost is hard to mock in concert with everything else, so stub
     54   // this method out for testing.
     55   virtual bool GetOrigin(
     56       int process_id,
     57       int render_view_id,
     58       std::string* origin) const OVERRIDE {
     59     if (process_id == kInstantRendererPID) {
     60       *origin = kInstantOrigin;
     61       return true;
     62     }
     63     if (process_id == kNonInstantRendererPID) {
     64       *origin = kNonInstantOrigin;
     65       return true;
     66     }
     67     return false;
     68   }
     69 };
     70 
     71 class IframeSourceTest : public testing::Test {
     72  public:
     73   // net::URLRequest wants to be executed with a message loop that has TYPE_IO.
     74   // InstantIOContext needs to be created on the UI thread and have everything
     75   // else happen on the IO thread. This setup is a hacky way to satisfy all
     76   // those constraints.
     77   IframeSourceTest()
     78       : thread_bundle_(content::TestBrowserThreadBundle::IO_MAINLOOP),
     79         resource_context_(&test_url_request_context_),
     80         instant_io_context_(NULL),
     81         response_(NULL) {
     82   }
     83 
     84   TestIframeSource* source() { return source_.get(); }
     85 
     86   std::string response_string() {
     87     if (response_.get()) {
     88       return std::string(reinterpret_cast<const char*>(response_->front()),
     89                          response_->size());
     90     }
     91     return "";
     92   }
     93 
     94   net::URLRequest* MockRequest(
     95       const std::string& url,
     96       bool allocate_info,
     97       int render_process_id,
     98       int render_view_id) {
     99     net::URLRequest* request =
    100         new net::URLRequest(GURL(url),
    101                             net::DEFAULT_PRIORITY,
    102                             NULL,
    103                             resource_context_.GetRequestContext());
    104     if (allocate_info) {
    105       content::ResourceRequestInfo::AllocateForTesting(request,
    106                                                        ResourceType::SUB_FRAME,
    107                                                        &resource_context_,
    108                                                        render_process_id,
    109                                                        render_view_id,
    110                                                        false);
    111     }
    112     return request;
    113   }
    114 
    115   void SendResource(int resource_id) {
    116     source()->SendResource(resource_id, callback_);
    117   }
    118 
    119   void SendJSWithOrigin(
    120       int resource_id,
    121       int render_process_id,
    122       int render_view_id) {
    123     source()->SendJSWithOrigin(resource_id, render_process_id, render_view_id,
    124                                callback_);
    125   }
    126 
    127  private:
    128   virtual void SetUp() OVERRIDE {
    129     source_.reset(new TestIframeSource());
    130     callback_ = base::Bind(&IframeSourceTest::SaveResponse,
    131                            base::Unretained(this));
    132     instant_io_context_ = new InstantIOContext;
    133     InstantIOContext::SetUserDataOnIO(&resource_context_, instant_io_context_);
    134     InstantIOContext::AddInstantProcessOnIO(instant_io_context_,
    135                                             kInstantRendererPID);
    136     response_ = NULL;
    137   }
    138 
    139   virtual void TearDown() {
    140     source_.reset();
    141   }
    142 
    143   void SaveResponse(base::RefCountedMemory* data) {
    144     response_ = data;
    145   }
    146 
    147   content::TestBrowserThreadBundle thread_bundle_;
    148 
    149   net::TestURLRequestContext test_url_request_context_;
    150   content::MockResourceContext resource_context_;
    151   scoped_ptr<TestIframeSource> source_;
    152   content::URLDataSource::GotDataCallback callback_;
    153   scoped_refptr<InstantIOContext> instant_io_context_;
    154   scoped_refptr<base::RefCountedMemory> response_;
    155 };
    156 
    157 TEST_F(IframeSourceTest, ShouldServiceRequest) {
    158   scoped_ptr<net::URLRequest> request;
    159   request.reset(MockRequest("http://test/loader.js", true,
    160                             kNonInstantRendererPID, 0));
    161   EXPECT_FALSE(source()->ShouldServiceRequest(request.get()));
    162   request.reset(MockRequest("chrome-search://bogus/valid.js", true,
    163                             kInstantRendererPID, 0));
    164   EXPECT_FALSE(source()->ShouldServiceRequest(request.get()));
    165   request.reset(MockRequest("chrome-search://test/bogus.js", true,
    166                             kInstantRendererPID, 0));
    167   EXPECT_FALSE(source()->ShouldServiceRequest(request.get()));
    168   request.reset(MockRequest("chrome-search://test/valid.js", true,
    169                             kInstantRendererPID, 0));
    170   EXPECT_TRUE(source()->ShouldServiceRequest(request.get()));
    171   request.reset(MockRequest("chrome-search://test/valid.js", true,
    172                             kNonInstantRendererPID, 0));
    173   EXPECT_FALSE(source()->ShouldServiceRequest(request.get()));
    174   request.reset(MockRequest("chrome-search://test/valid.js", true,
    175                             kInvalidRendererPID, 0));
    176   EXPECT_FALSE(source()->ShouldServiceRequest(request.get()));
    177 }
    178 
    179 TEST_F(IframeSourceTest, GetMimeType) {
    180   // URLDataManagerBackend does not include / in path_and_query.
    181   EXPECT_EQ("text/html", source()->GetMimeType("foo.html"));
    182   EXPECT_EQ("application/javascript", source()->GetMimeType("foo.js"));
    183   EXPECT_EQ("text/css", source()->GetMimeType("foo.css"));
    184   EXPECT_EQ("image/png", source()->GetMimeType("foo.png"));
    185   EXPECT_EQ("", source()->GetMimeType("bogus"));
    186 }
    187 
    188 TEST_F(IframeSourceTest, SendResource) {
    189   SendResource(IDR_MOST_VISITED_TITLE_HTML);
    190   EXPECT_FALSE(response_string().empty());
    191 }
    192 
    193 TEST_F(IframeSourceTest, SendJSWithOrigin) {
    194   SendJSWithOrigin(IDR_MOST_VISITED_TITLE_JS, kInstantRendererPID, 0);
    195   EXPECT_FALSE(response_string().empty());
    196   SendJSWithOrigin(IDR_MOST_VISITED_TITLE_JS, kNonInstantRendererPID, 0);
    197   EXPECT_FALSE(response_string().empty());
    198   SendJSWithOrigin(IDR_MOST_VISITED_TITLE_JS, kInvalidRendererPID, 0);
    199   EXPECT_TRUE(response_string().empty());
    200 }
    201