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 <map>
      6 #include <string>
      7 
      8 #include "base/memory/scoped_ptr.h"
      9 #include "chrome/common/extensions/extension_message_bundle.h"
     10 #include "chrome/common/extensions/extension_localization_peer.h"
     11 #include "ipc/ipc_message.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/glue/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 static_cast<IPC::SyncMessage*>(message)->GetReplyDeserializer();
     36   delete message;
     37 }
     38 
     39 class MockIpcMessageSender : public IPC::Message::Sender {
     40  public:
     41   MockIpcMessageSender() {
     42     ON_CALL(*this, Send(_))
     43         .WillByDefault(DoAll(Invoke(MessageDeleter), Return(true)));
     44   }
     45 
     46   virtual ~MockIpcMessageSender() {}
     47 
     48   MOCK_METHOD1(Send, bool(IPC::Message* message));
     49 
     50  private:
     51   DISALLOW_COPY_AND_ASSIGN(MockIpcMessageSender);
     52 };
     53 
     54 class MockResourceLoaderBridgePeer
     55     : public webkit_glue::ResourceLoaderBridge::Peer {
     56  public:
     57   MockResourceLoaderBridgePeer() {}
     58   virtual ~MockResourceLoaderBridgePeer() {}
     59 
     60   MOCK_METHOD2(OnUploadProgress, void(uint64 position, uint64 size));
     61   MOCK_METHOD4(OnReceivedRedirect, bool(
     62       const GURL& new_url,
     63       const webkit_glue::ResourceResponseInfo& info,
     64       bool* has_new_first_party_for_cookies,
     65       GURL* new_first_party_for_cookies));
     66   MOCK_METHOD1(OnReceivedResponse, void(
     67       const webkit_glue::ResourceResponseInfo& info));
     68   MOCK_METHOD1(OnDownloadedData, void(int len));
     69   MOCK_METHOD3(OnReceivedData, void(const char* data,
     70                                     int data_length,
     71                                     int encoded_data_length));
     72   MOCK_METHOD3(OnCompletedRequest, void(
     73       const net::URLRequestStatus& status,
     74       const std::string& security_info,
     75       const base::Time& 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     IsURLRequestEqual(net::URLRequestStatus::CANCELED), "", base::Time()));
    146 
    147   net::URLRequestStatus status;
    148   status.set_status(net::URLRequestStatus::FAILED);
    149   filter_peer->OnCompletedRequest(status, "", base::Time());
    150 }
    151 
    152 TEST_F(ExtensionLocalizationPeerTest, OnCompletedRequestEmptyData) {
    153   // It will self-delete once it exits OnCompletedRequest.
    154   ExtensionLocalizationPeer* filter_peer = filter_peer_.release();
    155 
    156   EXPECT_CALL(*original_peer_, OnReceivedData(_, _, _)).Times(0);
    157   EXPECT_CALL(*sender_, Send(_)).Times(0);
    158 
    159   EXPECT_CALL(*original_peer_, OnReceivedResponse(_));
    160   EXPECT_CALL(*original_peer_, OnCompletedRequest(
    161       IsURLRequestEqual(net::URLRequestStatus::SUCCESS), "", base::Time()));
    162 
    163   net::URLRequestStatus status;
    164   status.set_status(net::URLRequestStatus::SUCCESS);
    165   filter_peer->OnCompletedRequest(status, "", base::Time());
    166 }
    167 
    168 TEST_F(ExtensionLocalizationPeerTest, OnCompletedRequestNoCatalogs) {
    169   // It will self-delete once it exits OnCompletedRequest.
    170   ExtensionLocalizationPeer* filter_peer = filter_peer_.release();
    171 
    172   SetData(filter_peer, "some text");
    173 
    174   EXPECT_CALL(*sender_, Send(_));
    175 
    176   std::string data = GetData(filter_peer);
    177   EXPECT_CALL(*original_peer_,
    178               OnReceivedData(StrEq(data.data()), data.length(), -1)).Times(2);
    179 
    180   EXPECT_CALL(*original_peer_, OnReceivedResponse(_)).Times(2);
    181   EXPECT_CALL(*original_peer_, OnCompletedRequest(
    182       IsURLRequestEqual(
    183           net::URLRequestStatus::SUCCESS), "", base::Time())).Times(2);
    184 
    185   net::URLRequestStatus status;
    186   status.set_status(net::URLRequestStatus::SUCCESS);
    187   filter_peer->OnCompletedRequest(status, "", base::Time());
    188 
    189   // Test if Send gets called again (it shouldn't be) when first call returned
    190   // an empty dictionary.
    191   filter_peer =
    192       CreateExtensionLocalizationPeer("text/css", GURL(kExtensionUrl_1));
    193   SetData(filter_peer, "some text");
    194   filter_peer->OnCompletedRequest(status, "", base::Time());
    195 }
    196 
    197 TEST_F(ExtensionLocalizationPeerTest, OnCompletedRequestWithCatalogs) {
    198   // It will self-delete once it exits OnCompletedRequest.
    199   ExtensionLocalizationPeer* filter_peer =
    200       CreateExtensionLocalizationPeer("text/css", GURL(kExtensionUrl_2));
    201 
    202   L10nMessagesMap messages;
    203   messages.insert(std::make_pair("text", "new text"));
    204   ExtensionToL10nMessagesMap& l10n_messages_map =
    205       *GetExtensionToL10nMessagesMap();
    206   l10n_messages_map["some_id2"] = messages;
    207 
    208   SetData(filter_peer, "some __MSG_text__");
    209 
    210   // We already have messages in memory, Send will be skipped.
    211   EXPECT_CALL(*sender_, Send(_)).Times(0);
    212 
    213   // __MSG_text__ gets replaced with "new text".
    214   std::string data("some new text");
    215   EXPECT_CALL(*original_peer_,
    216               OnReceivedData(StrEq(data.data()), data.length(), -1));
    217 
    218   EXPECT_CALL(*original_peer_, OnReceivedResponse(_));
    219   EXPECT_CALL(*original_peer_, OnCompletedRequest(
    220       IsURLRequestEqual(net::URLRequestStatus::SUCCESS), "", base::Time()));
    221 
    222   net::URLRequestStatus status;
    223   status.set_status(net::URLRequestStatus::SUCCESS);
    224   filter_peer->OnCompletedRequest(status, "", base::Time());
    225 }
    226 
    227 TEST_F(ExtensionLocalizationPeerTest, OnCompletedRequestReplaceMessagesFails) {
    228   // It will self-delete once it exits OnCompletedRequest.
    229   ExtensionLocalizationPeer* filter_peer =
    230       CreateExtensionLocalizationPeer("text/css", GURL(kExtensionUrl_3));
    231 
    232   L10nMessagesMap messages;
    233   messages.insert(std::make_pair("text", "new text"));
    234   ExtensionToL10nMessagesMap& l10n_messages_map =
    235       *GetExtensionToL10nMessagesMap();
    236   l10n_messages_map["some_id3"] = messages;
    237 
    238   std::string message("some __MSG_missing_message__");
    239   SetData(filter_peer, message);
    240 
    241   // We already have messages in memory, Send will be skipped.
    242   EXPECT_CALL(*sender_, Send(_)).Times(0);
    243 
    244   // __MSG_missing_message__ is missing, so message stays the same.
    245   EXPECT_CALL(*original_peer_,
    246               OnReceivedData(StrEq(message.data()), message.length(), -1));
    247 
    248   EXPECT_CALL(*original_peer_, OnReceivedResponse(_));
    249   EXPECT_CALL(*original_peer_, OnCompletedRequest(
    250       IsURLRequestEqual(net::URLRequestStatus::SUCCESS), "", base::Time()));
    251 
    252   net::URLRequestStatus status;
    253   status.set_status(net::URLRequestStatus::SUCCESS);
    254   filter_peer->OnCompletedRequest(status, "", base::Time());
    255 }
    256