Source code formating unification
[platform/framework/web/wrt.git] / src / view / webkit / bundles / bundle_uri_handling.cpp
1 /*
2  * Copyright (c) 2012 Samsung Electronics Co., Ltd All Rights Reserved
3  *
4  *    Licensed under the Apache License, Version 2.0 (the "License");
5  *    you may not use this file except in compliance with the License.
6  *    You may obtain a copy of the License at
7  *
8  *        http://www.apache.org/licenses/LICENSE-2.0
9  *
10  *    Unless required by applicable law or agreed to in writing, software
11  *    distributed under the License is distributed on an "AS IS" BASIS,
12  *    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  *    See the License for the specific language governing permissions and
14  *    limitations under the License.
15  */
16 /*
17  * @file    bundle_uri_handling.cpp
18  * @author  Marcin Kaminski (marcin.ka@samsung.com)
19  * @version 1.0
20  */
21
22 #include "bundle_uri_handling.h"
23 #include <dpl/log/log.h>
24 #include <string.h>
25 #include <dpl/utils/wrt_global_settings.h>
26 // For dao creation (widget info fetching)
27 #include <dpl/wrt-dao-ro/widget_dao_read_only.h>
28 // security checks for URI
29 #include <ace-common/ace_api_common.h>
30 #include <ace-client/ace_api_client.h>
31 #include <dpl/utils/warp_iri.h>
32 // URI localization
33 #include <dpl/localization/w3c_file_localization.h>
34 // WARP check
35 #include <widget_data_types.h>
36 #include <dpl/wrt-dao-ro/common_dao_types.h>
37 // WKBundle API (i.e. message sending)
38 #include <WKBundle.h>
39 #include <WKString.h>
40 #include <WKType.h>
41
42 namespace {
43 char const * const SCHEME_TYPE_FILE = "file";
44 char const * const SCHEME_TYPE_WIDGET = "widget";
45 char const * const WARP_ERROR_MSG =
46     "file:///usr/etc/wrt/warp_security_error.msg";
47 char const * const PARAM_URL = "param:url";
48 char const * const ACE_IGNORED_SCHEMA[] = { "file://", "widget://", "data:",
49                                             "tel:", "sms:", "mmsto:", "mailto:",
50                                             0 };
51
52 WKStringRef block_message = WKStringCreateWithUTF8CString("uri_block_msg");
53
54 bool checkWARP(const char *url, const DPL::String& tizenId)
55 {
56     // ignore WARP in test mode
57     if (GlobalSettings::WarpTestModeEnabled()) {
58         return true;
59     }
60
61     if (WarpIRI::isIRISchemaIgnored(url)) {
62         // scheme is not supported by WARP
63         return true;
64     }
65
66     WrtDB::WidgetDAOReadOnly dao = WrtDB::WidgetDAOReadOnly(tizenId);
67     WrtDB::WidgetAccessInfoList widgetAccessInfoList;
68     dao.getWidgetAccessInfo(widgetAccessInfoList);
69
70     return (static_cast<WidgetAccessList>(widgetAccessInfoList)).isRequiredIRI(
71                DPL::FromUTF8String(std::string(url)));
72 }
73
74 bool checkACE(const char* url, bool xhr, const DPL::String& tizenId)
75 {
76     if (url) {
77         for (size_t i = 0; ACE_IGNORED_SCHEMA[i]; ++i) {
78             if (0 == strncmp(url,
79                              ACE_IGNORED_SCHEMA[i],
80                              strlen(ACE_IGNORED_SCHEMA[i])))
81             {
82                 return true;
83             }
84         }
85     }
86
87     const char *devCapNamesMarkup = "externalNetworkAccess";
88     const char *devCapNamesXHR = "XMLHttpRequest";
89
90     ace_request_t aceRequest;
91
92     aceRequest.widget_handle = WrtDB::WidgetDAOReadOnly::getHandle(tizenId);
93
94     // TODO! We should get session id from somewhere (outside Widget Process)
95     const std::string session = "";
96     aceRequest.session_id = const_cast<ace_session_id_t>(session.c_str());
97     aceRequest.feature_list.count = 0;
98     aceRequest.dev_cap_list.count = 1;
99     aceRequest.dev_cap_list.items = new ace_dev_cap_t[1];
100
101     if (xhr) {
102         aceRequest.dev_cap_list.items[0].name =
103             const_cast<ace_string_t>(devCapNamesXHR);
104     } else {
105         aceRequest.dev_cap_list.items[0].name =
106             const_cast<ace_string_t>(devCapNamesMarkup);
107     }
108
109     aceRequest.dev_cap_list.items[0].param_list.count = 1;
110     aceRequest.dev_cap_list.items[0].param_list.items = new ace_param_t[1];
111     aceRequest.dev_cap_list.items[0].param_list.items[0].name =
112         const_cast<ace_string_t>(PARAM_URL);
113     aceRequest.dev_cap_list.items[0].param_list.items[0].value =
114         const_cast<ace_string_t>(url);
115
116     ace_bool_t result = ACE_FALSE;
117
118     LogDebug("Making ace check with new C-API");
119
120     ace_return_t ret = ace_check_access(&aceRequest, &result);
121
122     LogDebug("Result is: " << static_cast<int>(result));
123
124     delete[] aceRequest.dev_cap_list.items[0].param_list.items;
125     delete[] aceRequest.dev_cap_list.items;
126
127     return ACE_OK == ret && ACE_TRUE == result;
128 }
129
130 bool filterURIBySecurity(DPL::OptionalString &op_uri,
131                          bool is_xhr,
132                          const DPL::String& tizenId)
133 {
134     if (!op_uri) {
135         return true; //accept empty uri
136     }
137
138     auto uri = DPL::ToUTF8String(*op_uri);
139     if (!checkWARP(uri.c_str(), tizenId)) {
140         LogDebug("Request was blocked by WARP: " << uri);
141         return false;
142     }
143
144     if (!checkACE(uri.c_str(), is_xhr, tizenId)) {
145         LogDebug("Request was blocked by ACE: " << uri);
146         return false;
147     }
148
149     return true;
150 }
151 } // namespace (anonymous)
152
153 namespace BundleURIHandling {
154 DPL::Optional<DPL::String> processURI(const DPL::String& inputURI,
155                                       bool is_xhr,
156                                       const DPL::String& tizenId,
157                                       WKBundleRef bundle)
158 {
159     DPL::Optional<DPL::String> uri = localizeURI(inputURI, tizenId);
160
161     if (uri.IsNull()) {
162         LogDebug("uri is empty");
163         return uri;
164     }
165
166     // check ACE, WARP
167     if (!filterURIBySecurity(uri, is_xhr, tizenId)) {
168         WKStringRef urlStr = WKStringCreateWithUTF8CString(
169                 DPL::ToUTF8String(*uri).c_str());
170         WKTypeRef retVal = NULL;
171         // Send information about blocked URI to view_logic
172         LogInfo("Sent blocked uri to open browser later : " << uri);
173         WKBundlePostSynchronousMessage(bundle, block_message,
174                                        urlStr, &retVal);
175         WKRelease(urlStr);
176         WKRelease(retVal);
177         return DPL::Optional<DPL::String>::Null;
178     }
179
180     return uri;
181 }
182
183 DPL::OptionalString localizeURI(const DPL::String& inputURI,
184                                 const DPL::String& tizenId)
185 {
186     auto uri = DPL::ToUTF8String(inputURI);
187     LogDebug("localizing url: " << uri);
188
189     auto urlcstr = uri.c_str();
190
191     const char *end = strstr(urlcstr, ":");
192     if (!end) {
193         LogDebug("no schema in link, return null");
194         // lack of schema
195         return DPL::Optional<DPL::String>::Null;
196     }
197
198     std::string scheme(urlcstr, end);
199     if (scheme != SCHEME_TYPE_WIDGET && scheme != SCHEME_TYPE_FILE) {
200         LogDebug("scheme doesn't need to localize");
201         return DPL::OptionalString(inputURI);
202     }
203
204     DPL::Optional<DPL::String> found =
205         W3CFileLocalization::getFilePathInWidgetPackageFromUrl(
206             tizenId,
207             DPL::FromUTF8String(uri));
208
209     if (found.IsNull()) {
210         // In this case, path doesn't need to localize. return input uri
211         LogDebug("Path not found within current locale in current widget");
212         return DPL::OptionalString(inputURI);
213     } else {
214         DPL::String uri(L"file://" + *found);
215         LogDebug("Will load resource: " << uri);
216         LogDebug("finished");
217         return DPL::OptionalString(uri);
218     }
219 }
220 } // namespace BundleURIHandling