Upstream version 5.34.104.0
[platform/framework/web/crosswalk.git] / src / chrome / renderer / security_filter_peer.cc
1 // Copyright (c) 2012 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/security_filter_peer.h"
6
7 #include "base/memory/scoped_ptr.h"
8 #include "base/strings/stringprintf.h"
9 #include "grit/generated_resources.h"
10 #include "net/base/net_errors.h"
11 #include "net/http/http_response_headers.h"
12 #include "ui/base/l10n/l10n_util.h"
13
14 SecurityFilterPeer::SecurityFilterPeer(
15     webkit_glue::ResourceLoaderBridge* resource_loader_bridge,
16     webkit_glue::ResourceLoaderBridge::Peer* peer)
17     : original_peer_(peer),
18       resource_loader_bridge_(resource_loader_bridge) {
19 }
20
21 SecurityFilterPeer::~SecurityFilterPeer() {
22 }
23
24 // static
25 SecurityFilterPeer*
26     SecurityFilterPeer::CreateSecurityFilterPeerForDeniedRequest(
27     ResourceType::Type resource_type,
28     webkit_glue::ResourceLoaderBridge::Peer* peer,
29     int os_error) {
30   // Create a filter for SSL and CERT errors.
31   switch (os_error) {
32     case net::ERR_SSL_PROTOCOL_ERROR:
33     case net::ERR_CERT_COMMON_NAME_INVALID:
34     case net::ERR_CERT_DATE_INVALID:
35     case net::ERR_CERT_AUTHORITY_INVALID:
36     case net::ERR_CERT_CONTAINS_ERRORS:
37     case net::ERR_CERT_NO_REVOCATION_MECHANISM:
38     case net::ERR_CERT_UNABLE_TO_CHECK_REVOCATION:
39     case net::ERR_CERT_REVOKED:
40     case net::ERR_CERT_INVALID:
41     case net::ERR_CERT_WEAK_SIGNATURE_ALGORITHM:
42     case net::ERR_CERT_WEAK_KEY:
43     case net::ERR_CERT_NAME_CONSTRAINT_VIOLATION:
44     case net::ERR_INSECURE_RESPONSE:
45     case net::ERR_SSL_PINNED_KEY_NOT_IN_CERT_CHAIN:
46       if (ResourceType::IsFrame(resource_type))
47         return CreateSecurityFilterPeerForFrame(peer, os_error);
48       // Any other content is entirely filtered-out.
49       return new ReplaceContentPeer(NULL, peer, std::string(), std::string());
50     default:
51       // For other errors, we use our normal error handling.
52       return NULL;
53   }
54 }
55
56 // static
57 SecurityFilterPeer* SecurityFilterPeer::CreateSecurityFilterPeerForFrame(
58     webkit_glue::ResourceLoaderBridge::Peer* peer, int os_error) {
59   // TODO(jcampan): use a different message when getting a phishing/malware
60   // error.
61   std::string html = base::StringPrintf(
62       "<html><meta charset='UTF-8'>"
63       "<body style='background-color:#990000;color:white;'>"
64       "%s</body></html>",
65       l10n_util::GetStringUTF8(IDS_UNSAFE_FRAME_MESSAGE).c_str());
66   return new ReplaceContentPeer(NULL, peer, "text/html", html);
67 }
68
69 void SecurityFilterPeer::OnUploadProgress(uint64 position, uint64 size) {
70   original_peer_->OnUploadProgress(position, size);
71 }
72
73 bool SecurityFilterPeer::OnReceivedRedirect(
74     const GURL& new_url,
75     const webkit_glue::ResourceResponseInfo& info,
76     bool* has_new_first_party_for_cookies,
77     GURL* new_first_party_for_cookies) {
78   NOTREACHED();
79   return false;
80 }
81
82 void SecurityFilterPeer::OnReceivedResponse(
83     const webkit_glue::ResourceResponseInfo& info) {
84   NOTREACHED();
85 }
86
87 void SecurityFilterPeer::OnReceivedData(const char* data,
88                                         int data_length,
89                                         int encoded_data_length) {
90   NOTREACHED();
91 }
92
93 void SecurityFilterPeer::OnCompletedRequest(
94     int error_code,
95     bool was_ignored_by_handler,
96     bool stale_copy_in_cache,
97     const std::string& security_info,
98     const base::TimeTicks& completion_time,
99     int64 total_transfer_size) {
100   NOTREACHED();
101 }
102
103 // static
104 void ProcessResponseInfo(
105     const webkit_glue::ResourceResponseInfo& info_in,
106     webkit_glue::ResourceResponseInfo* info_out,
107     const std::string& mime_type) {
108   DCHECK(info_out);
109   *info_out = info_in;
110   info_out->mime_type = mime_type;
111   // Let's create our own HTTP headers.
112   std::string raw_headers;
113   raw_headers.append("HTTP/1.1 200 OK");
114   raw_headers.push_back('\0');
115   // Don't cache the data we are serving, it is not the real data for that URL
116   // (if the filtered resource were to make it into the WebCore cache, then the
117   // same URL loaded in a safe scenario would still return the filtered
118   // resource).
119   raw_headers.append("cache-control: no-cache");
120   raw_headers.push_back('\0');
121   if (!mime_type.empty()) {
122     raw_headers.append("content-type: ");
123     raw_headers.append(mime_type);
124     raw_headers.push_back('\0');
125   }
126   raw_headers.push_back('\0');
127   net::HttpResponseHeaders* new_headers =
128       new net::HttpResponseHeaders(raw_headers);
129   info_out->headers = new_headers;
130 }
131
132 ////////////////////////////////////////////////////////////////////////////////
133 // BufferedPeer
134
135 BufferedPeer::BufferedPeer(
136     webkit_glue::ResourceLoaderBridge* resource_loader_bridge,
137     webkit_glue::ResourceLoaderBridge::Peer* peer,
138     const std::string& mime_type)
139     : SecurityFilterPeer(resource_loader_bridge, peer),
140       mime_type_(mime_type) {
141 }
142
143 BufferedPeer::~BufferedPeer() {
144 }
145
146 void BufferedPeer::OnReceivedResponse(
147     const webkit_glue::ResourceResponseInfo& info) {
148   ProcessResponseInfo(info, &response_info_, mime_type_);
149 }
150
151 void BufferedPeer::OnReceivedData(const char* data,
152                                   int data_length,
153                                   int encoded_data_length) {
154   data_.append(data, data_length);
155 }
156
157 void BufferedPeer::OnCompletedRequest(int error_code,
158                                       bool was_ignored_by_handler,
159                                       bool stale_copy_in_cache,
160                                       const std::string& security_info,
161                                       const base::TimeTicks& completion_time,
162                                       int64 total_transfer_size) {
163   // Make sure we delete ourselves at the end of this call.
164   scoped_ptr<BufferedPeer> this_deleter(this);
165
166   // Give sub-classes a chance at altering the data.
167   if (error_code != net::OK || !DataReady()) {
168     // Pretend we failed to load the resource.
169     original_peer_->OnReceivedResponse(response_info_);
170     original_peer_->OnCompletedRequest(net::ERR_ABORTED, false,
171                                        stale_copy_in_cache,
172                                        security_info, completion_time,
173                                        total_transfer_size);
174     return;
175   }
176
177   original_peer_->OnReceivedResponse(response_info_);
178   if (!data_.empty())
179     original_peer_->OnReceivedData(data_.data(),
180                                    static_cast<int>(data_.size()),
181                                    -1);
182   original_peer_->OnCompletedRequest(error_code, was_ignored_by_handler,
183                                      stale_copy_in_cache, security_info,
184                                      completion_time, total_transfer_size);
185 }
186
187 ////////////////////////////////////////////////////////////////////////////////
188 // ReplaceContentPeer
189
190 ReplaceContentPeer::ReplaceContentPeer(
191     webkit_glue::ResourceLoaderBridge* resource_loader_bridge,
192     webkit_glue::ResourceLoaderBridge::Peer* peer,
193     const std::string& mime_type,
194     const std::string& data)
195     : SecurityFilterPeer(resource_loader_bridge, peer),
196       mime_type_(mime_type),
197       data_(data) {
198 }
199
200 ReplaceContentPeer::~ReplaceContentPeer() {
201 }
202
203 void ReplaceContentPeer::OnReceivedResponse(
204     const webkit_glue::ResourceResponseInfo& info) {
205   // Ignore this, we'll serve some alternate content in OnCompletedRequest.
206 }
207
208 void ReplaceContentPeer::OnReceivedData(const char* data,
209                                         int data_length,
210                                         int encoded_data_length) {
211   // Ignore this, we'll serve some alternate content in OnCompletedRequest.
212 }
213
214 void ReplaceContentPeer::OnCompletedRequest(
215     int error_code,
216     bool was_ignored_by_handler,
217     bool stale_copy_in_cache,
218     const std::string& security_info,
219     const base::TimeTicks& completion_time,
220     int64 total_transfer_size) {
221   webkit_glue::ResourceResponseInfo info;
222   ProcessResponseInfo(info, &info, mime_type_);
223   info.security_info = security_info;
224   info.content_length = static_cast<int>(data_.size());
225   original_peer_->OnReceivedResponse(info);
226   if (!data_.empty())
227     original_peer_->OnReceivedData(data_.data(),
228                                    static_cast<int>(data_.size()),
229                                    -1);
230   original_peer_->OnCompletedRequest(net::OK,
231                                      false,
232                                      stale_copy_in_cache,
233                                      security_info,
234                                      completion_time,
235                                      total_transfer_size);
236
237   // The request processing is complete, we must delete ourselves.
238   delete this;
239 }