extension_localization_peer.cc revision 513209b27ff55e2841eac0e4120199c23acce758
1// Copyright (c) 2010 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/common/extensions/extension_localization_peer.h"
6
7#include "base/scoped_ptr.h"
8#include "base/string_util.h"
9#include "chrome/common/extensions/extension_message_bundle.h"
10#include "chrome/common/render_messages.h"
11#include "chrome/common/url_constants.h"
12#include "grit/generated_resources.h"
13#include "grit/renderer_resources.h"
14#include "net/base/net_errors.h"
15#include "net/http/http_response_headers.h"
16#include "webkit/glue/webkit_glue.h"
17
18ExtensionLocalizationPeer::ExtensionLocalizationPeer(
19    webkit_glue::ResourceLoaderBridge::Peer* peer,
20    IPC::Message::Sender* message_sender,
21    const GURL& request_url)
22    : original_peer_(peer),
23      message_sender_(message_sender),
24      request_url_(request_url) {
25}
26
27ExtensionLocalizationPeer::~ExtensionLocalizationPeer() {
28}
29
30// static
31ExtensionLocalizationPeer*
32ExtensionLocalizationPeer::CreateExtensionLocalizationPeer(
33    webkit_glue::ResourceLoaderBridge::Peer* peer,
34    IPC::Message::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(chrome::kExtensionScheme) &&
40          StartsWithASCII(mime_type, "text/css", false)) ?
41      new ExtensionLocalizationPeer(peer, message_sender, request_url) : NULL;
42}
43
44void ExtensionLocalizationPeer::OnUploadProgress(
45    uint64 position, uint64 size) {
46  NOTREACHED();
47}
48
49bool ExtensionLocalizationPeer::OnReceivedRedirect(
50    const GURL& new_url,
51    const webkit_glue::ResourceResponseInfo& info,
52    bool* has_new_first_party_for_cookies,
53    GURL* new_first_party_for_cookies) {
54  NOTREACHED();
55  return false;
56}
57
58void ExtensionLocalizationPeer::OnReceivedResponse(
59    const webkit_glue::ResourceResponseInfo& info,
60    bool content_filtered) {
61  response_info_ = info;
62}
63
64void ExtensionLocalizationPeer::OnReceivedData(const char* data, int len) {
65  data_.append(data, len);
66}
67
68void ExtensionLocalizationPeer::OnCompletedRequest(
69    const URLRequestStatus& status,
70    const std::string& security_info,
71    const base::Time& completion_time) {
72  // Make sure we delete ourselves at the end of this call.
73  scoped_ptr<ExtensionLocalizationPeer> this_deleter(this);
74
75  // Give sub-classes a chance at altering the data.
76  if (status.status() != URLRequestStatus::SUCCESS) {
77    // We failed to load the resource.
78    original_peer_->OnReceivedResponse(response_info_, true);
79    URLRequestStatus status(URLRequestStatus::CANCELED, net::ERR_ABORTED);
80    original_peer_->OnCompletedRequest(status, security_info, completion_time);
81    return;
82  }
83
84  ReplaceMessages();
85
86  original_peer_->OnReceivedResponse(response_info_, true);
87  if (!data_.empty())
88    original_peer_->OnReceivedData(data_.data(),
89                                   static_cast<int>(data_.size()));
90  original_peer_->OnCompletedRequest(status, security_info, completion_time);
91}
92
93void ExtensionLocalizationPeer::ReplaceMessages() {
94  if (!message_sender_ || data_.empty())
95    return;
96
97  if (!request_url_.is_valid())
98    return;
99
100  std::string extension_id = request_url_.host();
101  L10nMessagesMap* l10n_messages = GetL10nMessagesMap(extension_id);
102  if (!l10n_messages) {
103    L10nMessagesMap messages;
104    message_sender_->Send(new ViewHostMsg_GetExtensionMessageBundle(
105        extension_id, &messages));
106
107    // Save messages we got, so we don't have to ask again.
108    // Messages map is never empty, it contains at least @@extension_id value.
109    ExtensionToL10nMessagesMap& l10n_messages_map =
110        *GetExtensionToL10nMessagesMap();
111    l10n_messages_map[extension_id] = messages;
112
113    l10n_messages = GetL10nMessagesMap(extension_id);
114  }
115
116  std::string error;
117  if (ExtensionMessageBundle::ReplaceMessagesWithExternalDictionary(
118          *l10n_messages, &data_, &error)) {
119    data_.resize(data_.size());
120  }
121}
122