Home | History | Annotate | Download | only in extensions
      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 <map>
      6 #include <string>
      7 
      8 #include "base/memory/scoped_ptr.h"
      9 #include "chrome/common/extensions/message_bundle.h"
     10 #include "chrome/renderer/extensions/extension_localization_peer.h"
     11 #include "ipc/ipc_sender.h"
     12 #include "ipc/ipc_sync_message.h"
     13 #include "net/base/net_errors.h"
     14 #include "net/url_request/url_request_status.h"
     15 #include "testing/gmock/include/gmock/gmock.h"
     16 #include "testing/gtest/include/gtest/gtest.h"
     17 #include "webkit/child/resource_loader_bridge.h"
     18 
     19 using testing::_;
     20 using testing::DoAll;
     21 using testing::Invoke;
     22 using testing::StrEq;
     23 using testing::Return;
     24 
     25 static const char* const kExtensionUrl_1 =
     26     "chrome-extension://some_id/popup.css";
     27 
     28 static const char* const kExtensionUrl_2 =
     29     "chrome-extension://some_id2/popup.css";
     30 
     31 static const char* const kExtensionUrl_3 =
     32     "chrome-extension://some_id3/popup.css";
     33 
     34 void MessageDeleter(IPC::Message* message) {
     35   delete message;
     36 }
     37 
     38 class MockIpcMessageSender : public IPC::Sender {
     39  public:
     40   MockIpcMessageSender() {
     41     ON_CALL(*this, Send(_))
     42         .WillByDefault(DoAll(Invoke(MessageDeleter), Return(true)));
     43   }
     44 
     45   virtual ~MockIpcMessageSender() {}
     46 
     47   MOCK_METHOD1(Send, bool(IPC::Message* message));
     48 
     49  private:
     50   DISALLOW_COPY_AND_ASSIGN(MockIpcMessageSender);
     51 };
     52 
     53 class MockResourceLoaderBridgePeer
     54     : public webkit_glue::ResourceLoaderBridge::Peer {
     55  public:
     56   MockResourceLoaderBridgePeer() {}
     57   virtual ~MockResourceLoaderBridgePeer() {}
     58 
     59   MOCK_METHOD2(OnUploadProgress, void(uint64 position, uint64 size));
     60   MOCK_METHOD4(OnReceivedRedirect, bool(
     61       const GURL& new_url,
     62       const webkit_glue::ResourceResponseInfo& info,
     63       bool* has_new_first_party_for_cookies,
     64       GURL* new_first_party_for_cookies));
     65   MOCK_METHOD1(OnReceivedResponse, void(
     66       const webkit_glue::ResourceResponseInfo& info));
     67   MOCK_METHOD1(OnDownloadedData, void(int len));
     68   MOCK_METHOD3(OnReceivedData, void(const char* data,
     69                                     int data_length,
     70                                     int encoded_data_length));
     71   MOCK_METHOD4(OnCompletedRequest, void(
     72       int error_code,
     73       bool was_ignored_by_handler,
     74       const std::string& security_info,
     75       const base::TimeTicks& completion_time));
     76 
     77  private:
     78   DISALLOW_COPY_AND_ASSIGN(MockResourceLoaderBridgePeer);
     79 };
     80 
     81 class ExtensionLocalizationPeerTest : public testing::Test {
     82  protected:
     83   virtual void SetUp() {
     84     sender_.reset(new MockIpcMessageSender());
     85     original_peer_.reset(new MockResourceLoaderBridgePeer());
     86     filter_peer_.reset(
     87         ExtensionLocalizationPeer::CreateExtensionLocalizationPeer(
     88             original_peer_.get(), sender_.get(), "text/css",
     89             GURL(kExtensionUrl_1)));
     90   }
     91 
     92   ExtensionLocalizationPeer* CreateExtensionLocalizationPeer(
     93       const std::string& mime_type,
     94       const GURL& request_url) {
     95     return ExtensionLocalizationPeer::CreateExtensionLocalizationPeer(
     96         original_peer_.get(), sender_.get(), mime_type, request_url);
     97   }
     98 
     99   std::string GetData(ExtensionLocalizationPeer* filter_peer) {
    100     EXPECT_TRUE(NULL != filter_peer);
    101     return filter_peer->data_;
    102   }
    103 
    104   void SetData(ExtensionLocalizationPeer* filter_peer,
    105                const std::string& data) {
    106     EXPECT_TRUE(NULL != filter_peer);
    107     filter_peer->data_ = data;
    108   }
    109 
    110   scoped_ptr<MockIpcMessageSender> sender_;
    111   scoped_ptr<MockResourceLoaderBridgePeer> original_peer_;
    112   scoped_ptr<ExtensionLocalizationPeer> filter_peer_;
    113 };
    114 
    115 TEST_F(ExtensionLocalizationPeerTest, CreateWithWrongMimeType) {
    116   filter_peer_.reset(
    117       CreateExtensionLocalizationPeer("text/html", GURL(kExtensionUrl_1)));
    118   EXPECT_TRUE(NULL == filter_peer_.get());
    119 }
    120 
    121 TEST_F(ExtensionLocalizationPeerTest, CreateWithValidInput) {
    122   EXPECT_TRUE(NULL != filter_peer_.get());
    123 }
    124 
    125 TEST_F(ExtensionLocalizationPeerTest, OnReceivedData) {
    126   EXPECT_TRUE(GetData(filter_peer_.get()).empty());
    127 
    128   const std::string data_chunk("12345");
    129   filter_peer_->OnReceivedData(data_chunk.c_str(), data_chunk.length(), -1);
    130 
    131   EXPECT_EQ(data_chunk, GetData(filter_peer_.get()));
    132 
    133   filter_peer_->OnReceivedData(data_chunk.c_str(), data_chunk.length(), -1);
    134   EXPECT_EQ(data_chunk + data_chunk, GetData(filter_peer_.get()));
    135 }
    136 
    137 MATCHER_P(IsURLRequestEqual, status, "") { return arg.status() == status; }
    138 
    139 TEST_F(ExtensionLocalizationPeerTest, OnCompletedRequestBadURLRequestStatus) {
    140   // It will self-delete once it exits OnCompletedRequest.
    141   ExtensionLocalizationPeer* filter_peer = filter_peer_.release();
    142 
    143   EXPECT_CALL(*original_peer_, OnReceivedResponse(_));
    144   EXPECT_CALL(*original_peer_, OnCompletedRequest(
    145     net::ERR_ABORTED, false, "", base::TimeTicks()));
    146 
    147   filter_peer->OnCompletedRequest(
    148       net::ERR_FAILED, false, std::string(), base::TimeTicks());
    149 }
    150 
    151 TEST_F(ExtensionLocalizationPeerTest, OnCompletedRequestEmptyData) {
    152   // It will self-delete once it exits OnCompletedRequest.
    153   ExtensionLocalizationPeer* filter_peer = filter_peer_.release();
    154 
    155   EXPECT_CALL(*original_peer_, OnReceivedData(_, _, _)).Times(0);
    156   EXPECT_CALL(*sender_, Send(_)).Times(0);
    157 
    158   EXPECT_CALL(*original_peer_, OnReceivedResponse(_));
    159   EXPECT_CALL(*original_peer_, OnCompletedRequest(
    160       net::OK, false, "", base::TimeTicks()));
    161 
    162   filter_peer->OnCompletedRequest(
    163       net::OK, false, std::string(), base::TimeTicks());
    164 }
    165 
    166 TEST_F(ExtensionLocalizationPeerTest, OnCompletedRequestNoCatalogs) {
    167   // It will self-delete once it exits OnCompletedRequest.
    168   ExtensionLocalizationPeer* filter_peer = filter_peer_.release();
    169 
    170   SetData(filter_peer, "some text");
    171 
    172   EXPECT_CALL(*sender_, Send(_));
    173 
    174   std::string data = GetData(filter_peer);
    175   EXPECT_CALL(*original_peer_,
    176               OnReceivedData(StrEq(data.data()), data.length(), -1)).Times(2);
    177 
    178   EXPECT_CALL(*original_peer_, OnReceivedResponse(_)).Times(2);
    179   EXPECT_CALL(*original_peer_, OnCompletedRequest(
    180           net::OK, false, "", base::TimeTicks())).Times(2);
    181 
    182   filter_peer->OnCompletedRequest(
    183       net::OK, false, std::string(), base::TimeTicks());
    184 
    185   // Test if Send gets called again (it shouldn't be) when first call returned
    186   // an empty dictionary.
    187   filter_peer =
    188       CreateExtensionLocalizationPeer("text/css", GURL(kExtensionUrl_1));
    189   SetData(filter_peer, "some text");
    190   filter_peer->OnCompletedRequest(
    191       net::OK, false, std::string(), base::TimeTicks());
    192 }
    193 
    194 TEST_F(ExtensionLocalizationPeerTest, OnCompletedRequestWithCatalogs) {
    195   // It will self-delete once it exits OnCompletedRequest.
    196   ExtensionLocalizationPeer* filter_peer =
    197       CreateExtensionLocalizationPeer("text/css", GURL(kExtensionUrl_2));
    198 
    199   extensions::L10nMessagesMap messages;
    200   messages.insert(std::make_pair("text", "new text"));
    201   extensions::ExtensionToL10nMessagesMap& l10n_messages_map =
    202       *extensions::GetExtensionToL10nMessagesMap();
    203   l10n_messages_map["some_id2"] = messages;
    204 
    205   SetData(filter_peer, "some __MSG_text__");
    206 
    207   // We already have messages in memory, Send will be skipped.
    208   EXPECT_CALL(*sender_, Send(_)).Times(0);
    209 
    210   // __MSG_text__ gets replaced with "new text".
    211   std::string data("some new text");
    212   EXPECT_CALL(*original_peer_,
    213               OnReceivedData(StrEq(data.data()), data.length(), -1));
    214 
    215   EXPECT_CALL(*original_peer_, OnReceivedResponse(_));
    216   EXPECT_CALL(*original_peer_, OnCompletedRequest(
    217       net::OK, false, "", base::TimeTicks()));
    218 
    219   filter_peer->OnCompletedRequest(
    220       net::OK, false, std::string(), base::TimeTicks());
    221 }
    222 
    223 TEST_F(ExtensionLocalizationPeerTest, OnCompletedRequestReplaceMessagesFails) {
    224   // It will self-delete once it exits OnCompletedRequest.
    225   ExtensionLocalizationPeer* filter_peer =
    226       CreateExtensionLocalizationPeer("text/css", GURL(kExtensionUrl_3));
    227 
    228   extensions::L10nMessagesMap messages;
    229   messages.insert(std::make_pair("text", "new text"));
    230   extensions::ExtensionToL10nMessagesMap& l10n_messages_map =
    231       *extensions::GetExtensionToL10nMessagesMap();
    232   l10n_messages_map["some_id3"] = messages;
    233 
    234   std::string message("some __MSG_missing_message__");
    235   SetData(filter_peer, message);
    236 
    237   // We already have messages in memory, Send will be skipped.
    238   EXPECT_CALL(*sender_, Send(_)).Times(0);
    239 
    240   // __MSG_missing_message__ is missing, so message stays the same.
    241   EXPECT_CALL(*original_peer_,
    242               OnReceivedData(StrEq(message.data()), message.length(), -1));
    243 
    244   EXPECT_CALL(*original_peer_, OnReceivedResponse(_));
    245   EXPECT_CALL(*original_peer_, OnCompletedRequest(
    246       net::OK, false, "", base::TimeTicks()));
    247 
    248   filter_peer->OnCompletedRequest(
    249       net::OK, false, std::string(), base::TimeTicks());
    250 }
    251