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