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)
44 char const * const SCHEME_TYPE_FILE = "file";
45 char const * const SCHEME_TYPE_WIDGET = "widget";
46 char const * const WARP_ERROR_MSG =
47 "file:///usr/etc/wrt/warp_security_error.msg";
48 char const * const PARAM_URL = "param:url";
49 char const * const ACE_IGNORED_SCHEMA[] = { "file://", "widget://", "data:",
50 "tel:", "sms:", "mmsto:", "mailto:", 0 };
52 WKStringRef block_message = WKStringCreateWithUTF8CString("uri_block_msg");
55 bool checkWARP(const char *url, const DPL::String& tizenId)
57 // ignore WARP in test mode
58 if (GlobalSettings::WarpTestModeEnabled()) {
62 if (WarpIRI::isIRISchemaIgnored(url)) {
63 // scheme is not supported by WARP
67 WrtDB::WidgetDAOReadOnly dao = WrtDB::WidgetDAOReadOnly(tizenId);
68 WrtDB::WidgetAccessInfoList widgetAccessInfoList;
69 dao.getWidgetAccessInfo(widgetAccessInfoList);
71 return (static_cast<WidgetAccessList>(widgetAccessInfoList)).isRequiredIRI(
72 DPL::FromUTF8String(std::string(url)));
75 bool checkACE(const char* url, bool xhr, const DPL::String& tizenId)
78 for (size_t i = 0; ACE_IGNORED_SCHEMA[i]; ++i) {
80 ACE_IGNORED_SCHEMA[i],
81 strlen(ACE_IGNORED_SCHEMA[i])))
88 const char *devCapNamesMarkup = "externalNetworkAccess";
89 const char *devCapNamesXHR = "XMLHttpRequest";
91 ace_request_t aceRequest;
93 aceRequest.widget_handle = WrtDB::WidgetDAOReadOnly::getHandle(tizenId);
95 // TODO! We should get session id from somewhere (outside Widget Process)
96 const std::string session = "";
97 aceRequest.session_id = const_cast<ace_session_id_t>(session.c_str());
98 aceRequest.feature_list.count = 0;
99 aceRequest.dev_cap_list.count = 1;
100 aceRequest.dev_cap_list.items = new ace_dev_cap_t[1];
103 aceRequest.dev_cap_list.items[0].name =
104 const_cast<ace_string_t>(devCapNamesXHR);
106 aceRequest.dev_cap_list.items[0].name =
107 const_cast<ace_string_t>(devCapNamesMarkup);
110 aceRequest.dev_cap_list.items[0].param_list.count = 1;
111 aceRequest.dev_cap_list.items[0].param_list.items = new ace_param_t[1];
112 aceRequest.dev_cap_list.items[0].param_list.items[0].name =
113 const_cast<ace_string_t>(PARAM_URL);
114 aceRequest.dev_cap_list.items[0].param_list.items[0].value =
115 const_cast<ace_string_t>(url);
118 ace_bool_t result = ACE_FALSE;
120 LogDebug("Making ace check with new C-API");
122 ace_return_t ret = ace_check_access(&aceRequest, &result);
124 LogDebug("Result is: " << static_cast<int>(result));
126 delete [] aceRequest.dev_cap_list.items[0].param_list.items;
127 delete [] aceRequest.dev_cap_list.items;
129 return ACE_OK == ret && ACE_TRUE == result;
133 bool filterURIBySecurity(DPL::OptionalString &op_uri,
135 const DPL::String& tizenId)
139 return true; //accept empty uri
142 auto uri = DPL::ToUTF8String(*op_uri);
143 if (!checkWARP(uri.c_str(), tizenId))
145 LogDebug("Request was blocked by WARP: " << uri);
149 if (!checkACE(uri.c_str(), is_xhr, tizenId))
151 LogDebug("Request was blocked by ACE: " << uri);
157 } // namespace (anonymous)
159 namespace BundleURIHandling {
161 DPL::Optional<DPL::String> processURI(const DPL::String& inputURI,
162 bool is_xhr, const DPL::String& tizenId, WKBundleRef bundle)
164 DPL::Optional<DPL::String> uri = localizeURI(inputURI, tizenId);
168 LogDebug("uri is empty");
173 if (!filterURIBySecurity(uri, is_xhr, tizenId))
175 WKStringRef urlStr = WKStringCreateWithUTF8CString(
176 DPL::ToUTF8String(*uri).c_str());
177 WKTypeRef retVal = NULL;
178 // Send information about blocked URI to view_logic
179 LogInfo("Sent blocked uri to open browser later : " << uri);
180 WKBundlePostSynchronousMessage(bundle, block_message,
184 return DPL::Optional<DPL::String>::Null;
190 DPL::OptionalString localizeURI(const DPL::String& inputURI,
191 const DPL::String& tizenId)
193 auto uri = DPL::ToUTF8String(inputURI);
194 LogDebug("localizing url: " << uri);
196 auto urlcstr = uri.c_str();
198 const char *end = strstr(urlcstr, ":");
200 LogDebug("no schema in link, return null");
202 return DPL::Optional<DPL::String>::Null;
205 std::string scheme(urlcstr, end);
206 if (scheme != SCHEME_TYPE_WIDGET && scheme != SCHEME_TYPE_FILE) {
207 LogDebug("scheme doesn't need to localize");
208 return DPL::OptionalString(inputURI);
211 DPL::Optional<DPL::String> found =
212 W3CFileLocalization::getFilePathInWidgetPackageFromUrl(
214 DPL::FromUTF8String(uri));
216 if (found.IsNull()) {
217 // In this case, path doesn't need to localize. return input uri
218 LogDebug("Path not found within current locale in current widget");
219 return DPL::OptionalString(inputURI);
221 DPL::String uri(L"file://" + *found);
222 LogDebug("Will load resource: " << uri);
223 LogDebug("finished");
224 return DPL::OptionalString(uri);
228 } // namespace BundleURIHandling