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