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 19using testing::_; 20using testing::DoAll; 21using testing::Invoke; 22using testing::StrEq; 23using testing::Return; 24 25static const char* const kExtensionUrl_1 = 26 "chrome-extension://some_id/popup.css"; 27 28static const char* const kExtensionUrl_2 = 29 "chrome-extension://some_id2/popup.css"; 30 31static const char* const kExtensionUrl_3 = 32 "chrome-extension://some_id3/popup.css"; 33 34void MessageDeleter(IPC::Message* message) { 35 delete static_cast<IPC::SyncMessage*>(message)->GetReplyDeserializer(); 36 delete message; 37} 38 39class 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 54class 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 81class 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 115TEST_F(ExtensionLocalizationPeerTest, CreateWithWrongMimeType) { 116 filter_peer_.reset( 117 CreateExtensionLocalizationPeer("text/html", GURL(kExtensionUrl_1))); 118 EXPECT_TRUE(NULL == filter_peer_.get()); 119} 120 121TEST_F(ExtensionLocalizationPeerTest, CreateWithValidInput) { 122 EXPECT_TRUE(NULL != filter_peer_.get()); 123} 124 125TEST_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 137MATCHER_P(IsURLRequestEqual, status, "") { return arg.status() == status; } 138 139TEST_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 152TEST_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 168TEST_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 197TEST_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 227TEST_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