2 * Copyright (c) 2012 Samsung Electronics Co., Ltd All Rights Reserved
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
8 * http://www.apache.org/licenses/LICENSE-2.0
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.
17 * @file bundle_uri_handling.cpp
18 * @author Marcin Kaminski (marcin.ka@samsung.com)
22 #include "bundle_uri_handling.h"
23 #include <dpl/log/log.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>
33 #include <dpl/localization/w3c_file_localization.h>
35 #include <widget_data_types.h>
36 #include <dpl/wrt-dao-ro/common_dao_types.h>
37 // WKBundle API (i.e. message sending)
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:",
52 WKStringRef block_message = WKStringCreateWithUTF8CString("uri_block_msg");
54 bool checkWARP(const char *url, const DPL::String& tizenId)
56 // ignore WARP in test mode
57 if (GlobalSettings::WarpTestModeEnabled()) {
61 if (WarpIRI::isIRISchemaIgnored(url)) {
62 // scheme is not supported by WARP
66 WrtDB::WidgetDAOReadOnly dao = WrtDB::WidgetDAOReadOnly(tizenId);
67 WrtDB::WidgetAccessInfoList widgetAccessInfoList;
68 dao.getWidgetAccessInfo(widgetAccessInfoList);
70 return (static_cast<WidgetAccessList>(widgetAccessInfoList)).isRequiredIRI(
71 DPL::FromUTF8String(std::string(url)));
74 bool checkACE(const char* url, bool xhr, const DPL::String& tizenId)
77 for (size_t i = 0; ACE_IGNORED_SCHEMA[i]; ++i) {
79 ACE_IGNORED_SCHEMA[i],
80 strlen(ACE_IGNORED_SCHEMA[i])))
87 const char *devCapNamesMarkup = "externalNetworkAccess";
88 const char *devCapNamesXHR = "XMLHttpRequest";
90 ace_request_t aceRequest;
92 aceRequest.widget_handle = WrtDB::WidgetDAOReadOnly::getHandle(tizenId);
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];
102 aceRequest.dev_cap_list.items[0].name =
103 const_cast<ace_string_t>(devCapNamesXHR);
105 aceRequest.dev_cap_list.items[0].name =
106 const_cast<ace_string_t>(devCapNamesMarkup);
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);
116 ace_bool_t result = ACE_FALSE;
118 LogDebug("Making ace check with new C-API");
120 ace_return_t ret = ace_check_access(&aceRequest, &result);
122 LogDebug("Result is: " << static_cast<int>(result));
124 delete[] aceRequest.dev_cap_list.items[0].param_list.items;
125 delete[] aceRequest.dev_cap_list.items;
127 return ACE_OK == ret && ACE_TRUE == result;
130 bool filterURIBySecurity(DPL::OptionalString &op_uri,
132 const DPL::String& tizenId)
135 return true; //accept empty uri
138 auto uri = DPL::ToUTF8String(*op_uri);
139 if (!checkWARP(uri.c_str(), tizenId)) {
140 LogDebug("Request was blocked by WARP: " << uri);
144 if (!checkACE(uri.c_str(), is_xhr, tizenId)) {
145 LogDebug("Request was blocked by ACE: " << uri);
151 } // namespace (anonymous)
153 namespace BundleURIHandling {
154 DPL::Optional<DPL::String> processURI(const DPL::String& inputURI,
156 const DPL::String& tizenId,
159 DPL::Optional<DPL::String> uri = localizeURI(inputURI, tizenId);
162 LogDebug("uri is empty");
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,
177 return DPL::Optional<DPL::String>::Null;
183 DPL::OptionalString localizeURI(const DPL::String& inputURI,
184 const DPL::String& tizenId)
186 auto uri = DPL::ToUTF8String(inputURI);
187 LogDebug("localizing url: " << uri);
189 auto urlcstr = uri.c_str();
191 const char *end = strstr(urlcstr, ":");
193 LogDebug("no schema in link, return null");
195 return DPL::Optional<DPL::String>::Null;
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);
204 DPL::Optional<DPL::String> found =
205 W3CFileLocalization::getFilePathInWidgetPackageFromUrl(
207 DPL::FromUTF8String(uri));
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);
214 DPL::String uri(L"file://" + *found);
215 LogDebug("Will load resource: " << uri);
216 LogDebug("finished");
217 return DPL::OptionalString(uri);
220 } // namespace BundleURIHandling