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 "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