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/renderer/extensions/extension_localization_peer.h" 6 7 #include "base/memory/scoped_ptr.h" 8 #include "base/strings/string_util.h" 9 #include "chrome/common/url_constants.h" 10 #include "extensions/common/constants.h" 11 #include "extensions/common/extension_messages.h" 12 #include "extensions/common/message_bundle.h" 13 #include "grit/generated_resources.h" 14 #include "ipc/ipc_sender.h" 15 #include "net/base/net_errors.h" 16 #include "net/http/http_response_headers.h" 17 18 ExtensionLocalizationPeer::ExtensionLocalizationPeer( 19 content::RequestPeer* peer, 20 IPC::Sender* message_sender, 21 const GURL& request_url) 22 : original_peer_(peer), 23 message_sender_(message_sender), 24 request_url_(request_url) { 25 } 26 27 ExtensionLocalizationPeer::~ExtensionLocalizationPeer() { 28 } 29 30 // static 31 ExtensionLocalizationPeer* 32 ExtensionLocalizationPeer::CreateExtensionLocalizationPeer( 33 content::RequestPeer* peer, 34 IPC::Sender* message_sender, 35 const std::string& mime_type, 36 const GURL& request_url) { 37 // Return NULL if content is not text/css or it doesn't belong to extension 38 // scheme. 39 return (request_url.SchemeIs(extensions::kExtensionScheme) && 40 StartsWithASCII(mime_type, "text/css", false)) ? 41 new ExtensionLocalizationPeer(peer, message_sender, request_url) : NULL; 42 } 43 44 void ExtensionLocalizationPeer::OnUploadProgress( 45 uint64 position, uint64 size) { 46 NOTREACHED(); 47 } 48 49 bool ExtensionLocalizationPeer::OnReceivedRedirect( 50 const GURL& new_url, 51 const GURL& new_first_party_for_cookies, 52 const content::ResourceResponseInfo& info) { 53 NOTREACHED(); 54 return false; 55 } 56 57 void ExtensionLocalizationPeer::OnReceivedResponse( 58 const content::ResourceResponseInfo& info) { 59 response_info_ = info; 60 } 61 62 void ExtensionLocalizationPeer::OnReceivedData(const char* data, 63 int data_length, 64 int encoded_data_length) { 65 data_.append(data, data_length); 66 } 67 68 void ExtensionLocalizationPeer::OnCompletedRequest( 69 int error_code, 70 bool was_ignored_by_handler, 71 bool stale_copy_in_cache, 72 const std::string& security_info, 73 const base::TimeTicks& completion_time, 74 int64 total_transfer_size) { 75 // Make sure we delete ourselves at the end of this call. 76 scoped_ptr<ExtensionLocalizationPeer> this_deleter(this); 77 78 // Give sub-classes a chance at altering the data. 79 if (error_code != net::OK) { 80 // We failed to load the resource. 81 original_peer_->OnReceivedResponse(response_info_); 82 original_peer_->OnCompletedRequest(net::ERR_ABORTED, false, 83 stale_copy_in_cache, security_info, 84 completion_time, 85 total_transfer_size); 86 return; 87 } 88 89 ReplaceMessages(); 90 91 original_peer_->OnReceivedResponse(response_info_); 92 if (!data_.empty()) 93 original_peer_->OnReceivedData(data_.data(), 94 static_cast<int>(data_.size()), 95 -1); 96 original_peer_->OnCompletedRequest(error_code, was_ignored_by_handler, 97 stale_copy_in_cache, 98 security_info, completion_time, 99 total_transfer_size); 100 } 101 102 void ExtensionLocalizationPeer::ReplaceMessages() { 103 if (!message_sender_ || data_.empty()) 104 return; 105 106 if (!request_url_.is_valid()) 107 return; 108 109 std::string extension_id = request_url_.host(); 110 extensions::L10nMessagesMap* l10n_messages = 111 extensions::GetL10nMessagesMap(extension_id); 112 if (!l10n_messages) { 113 extensions::L10nMessagesMap messages; 114 message_sender_->Send(new ExtensionHostMsg_GetMessageBundle( 115 extension_id, &messages)); 116 117 // Save messages we got, so we don't have to ask again. 118 // Messages map is never empty, it contains at least @@extension_id value. 119 extensions::ExtensionToL10nMessagesMap& l10n_messages_map = 120 *extensions::GetExtensionToL10nMessagesMap(); 121 l10n_messages_map[extension_id] = messages; 122 123 l10n_messages = extensions::GetL10nMessagesMap(extension_id); 124 } 125 126 std::string error; 127 if (extensions::MessageBundle::ReplaceMessagesWithExternalDictionary( 128 *l10n_messages, &data_, &error)) { 129 data_.resize(data_.size()); 130 } 131 } 132