2 * Copyright (c) 2011 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 scheme_action_map.cpp
18 * @author Krzysztof Jackiewicz (k.jackiewicz@samsung.com)
22 #include "scheme_action_map.h"
24 #include <dpl/log/log.h>
25 #include <dpl/event/controller.h>
26 #include <application_launcher.h>
30 #include <curl/curl.h>
31 #include "scheme_action_map_data.h"
33 namespace ViewModule {
36 * Lazy construction pattern.
37 * TODO Make it more general. Use variadic template/tuples/lambdas or sth. Move
40 template <typename T, typename Arg1>
44 explicit Lazy(const Arg1& arg1) :
46 m_object(new std::unique_ptr<T>())
48 Lazy(const Lazy<T, Arg1>& other) :
50 m_object(other.m_object)
57 const T& operator*() const
61 const T* operator->() const
70 Lazy<T, Arg1>& operator=(const Lazy<T, Arg1>& other)
72 m_arg1 = other.m_arg1;
73 m_object = other.m_object;
81 (*m_object).reset(new T(m_arg1));
87 // single unique_ptr shared among many Lazy copies
88 mutable std::shared_ptr<std::unique_ptr<T> > m_object;
92 * Struct defining conversion of scheme for given appsvc key for example:
93 * sms:5551212?body=expected%20text => APPSVC_DATA_TEXT + expected%20text
95 struct AppSvcConversion {
96 AppSvcConversion(char const * const keyValue,
97 const std::string& regexStr) :
100 char const * const key;
101 Lazy<pcrecpp::RE, std::string> regex;
105 * Struct defining an appsvc operation and a list of scheme conversions used to
106 * fill in additional appsvc data.
108 struct AppSvcOperation {
109 const char* operation;
111 std::list<AppSvcConversion> conversions;
114 typedef std::map<Scheme::Type, AppSvcOperation> AppSvcOperationMap;
116 // Regular expressions used to extract appsvc data from scheme
117 // TODO what about multiple recipients?
118 char const * const REGEX_BODY = ".*[?&]body=([^&]+).*";
119 char const * const REGEX_SMS = "sms:([^&]+).*";
120 char const * const REGEX_MMSTO = "mmsto:([^&]+).*";
121 char const * const REGEX_MAILTO = "mailto:([^&]+).*";
122 char const * const REGEX_TO = ".*[?&]to=([^&]+).*";
123 char const * const REGEX_CC = ".*[?&]cc=([^&]+).*";
124 char const * const REGEX_BCC = ".*[?&]bcc=([^&]+).*";
125 char const * const REGEX_SUBJECT = ".*[?&]subject=([^&]+).*";
126 char const * const REGEX_DATA_CONTEXT = ".*;phone-context=([^:]+).*";
128 AppSvcOperationMap initializeAppSvcOperations()
130 AppSvcOperationMap ret;
132 // FILE, HTTP & HTTPS
133 AppSvcOperation viewOp;
134 viewOp.operation = APPSVC_OPERATION_VIEW;
135 viewOp.needUri = true;
136 // no additional data
137 ret.insert(std::make_pair(Scheme::FILE, viewOp));
138 ret.insert(std::make_pair(Scheme::HTTP, viewOp));
139 ret.insert(std::make_pair(Scheme::HTTPS, viewOp));
142 AppSvcOperation smsOp;
143 smsOp.operation = APPSVC_OPERATION_SEND_TEXT;
144 smsOp.needUri = false;
145 smsOp.conversions.push_back(AppSvcConversion(APPSVC_DATA_TO, REGEX_SMS));
146 smsOp.conversions.push_back(AppSvcConversion(APPSVC_DATA_TEXT, REGEX_BODY));
147 ret.insert(std::make_pair(Scheme::SMS, smsOp));
150 AppSvcOperation sendOp;
151 sendOp.operation = APPSVC_OPERATION_SEND;
152 sendOp.needUri = true;
153 sendOp.conversions.push_back(AppSvcConversion(APPSVC_DATA_TO, REGEX_MMSTO));
154 sendOp.conversions.push_back(AppSvcConversion(APPSVC_DATA_TO, REGEX_MAILTO));
155 sendOp.conversions.push_back(AppSvcConversion(APPSVC_DATA_CC, REGEX_CC));
156 sendOp.conversions.push_back(
157 AppSvcConversion(APPSVC_DATA_BCC, REGEX_BCC));
158 sendOp.conversions.push_back(
159 AppSvcConversion(APPSVC_DATA_SUBJECT, REGEX_SUBJECT));
160 sendOp.conversions.push_back(
161 AppSvcConversion(APPSVC_DATA_TEXT, REGEX_BODY));
162 ret.insert(std::make_pair(Scheme::MMSTO, sendOp));
163 ret.insert(std::make_pair(Scheme::MAILTO, sendOp));
165 // TODO what about DATA?
168 AppSvcOperation telOp;
169 telOp.operation = APPSVC_OPERATION_CALL;
170 telOp.needUri = true;
171 ret.insert(std::make_pair(Scheme::TEL, telOp));
176 AppSvcOperationMap g_appSvcOperationMap = initializeAppSvcOperations();
179 namespace SchemeActionMap {
180 bool HandleUri(const char* uri,
181 NavigationContext context,
182 WrtDB::AppType appType)
185 LogError("wrong arguments passed");
188 LogDebug("Uri being checked: " << uri);
190 const char *end = strstr(uri, ":");
192 LogError("Lack of scheme - ignoring");
195 std::string name(uri, end);
197 LogDebug("Scheme: " << name);
199 Scheme::Type type = scheme.GetType();
200 if (type < Scheme::FILE || type >= Scheme::COUNT) {
201 LogError("Invalid scheme: " << name);
202 // case of unknown scheme, send to app-control
203 // This is temporary soultion. "invalid" scheme should be handled by
205 bundle* bundleData = bundle_create();
206 appsvc_set_operation(bundleData, APPSVC_OPERATION_VIEW);
207 appsvc_set_uri(bundleData, uri);
208 CONTROLLER_POST_EVENT(
210 ApplicationLauncherEvents::LaunchApplicationByAppService(
217 LogDebug("Scheme type: " << type);
218 LogDebug("Navigation context: " << context);
219 LogDebug("Application type: " << appType);
223 case WrtDB::APP_TYPE_WAC20:
224 action = g_wacActionMap[type][context];
226 case WrtDB::APP_TYPE_TIZENWEBAPP:
227 action = g_tizenActionMap[type][context];
230 LogError("Unsupported application type: " << type);
234 LogDebug("Uri action: " << action);
236 // execute action if necessary
238 case URI_ACTION_APPSVC:
240 // find AppSvcOperation for given scheme type
241 auto it = g_appSvcOperationMap.find(type);
242 if (it == g_appSvcOperationMap.end()) {
243 LogError("No entry for scheme: " << name);
247 // prepare appsvc bundle
248 bundle* bundleData = bundle_create();
249 LogDebug("appsvc operation " << it->second.operation);
250 appsvc_set_operation(bundleData, it->second.operation);
251 if (it->second.needUri) {
252 appsvc_set_uri(bundleData, uri);
255 // this is safe as there are no other threads
256 CURL* curl = curl_easy_init();
259 char* unescaped = curl_easy_unescape(curl, uri, 0, &outLength);
260 std::string uUri(unescaped, outLength);
261 curl_free(unescaped);
262 curl_easy_cleanup(curl);
263 LogDebug("unescaped " << uUri);
265 // setup additional appsvc data
266 FOREACH(cit, it->second.conversions) {
267 LogDebug("extracting data for key " << cit->key);
270 pcrecpp::StringPiece input(uUri);
272 // convert scheme text to appsvc format
273 while (cit->regex->Consume(&input, &match)) {
274 LogInfo("Adding apssvc data: " << cit->key << " " << match);
275 appsvc_add_data(bundleData, cit->key, match.c_str());
279 // TODO do we need a callback?
280 CONTROLLER_POST_EVENT(
282 ApplicationLauncherEvents::LaunchApplicationByAppService(
289 case URI_ACTION_VIDEO:
290 CONTROLLER_POST_EVENT(
292 ApplicationLauncherEvents::LaunchApplicationByPkgname(
293 ApplicationLauncherPkgname::PKG_NAME_VIDEO_PLAYER,
301 return (action == URI_ACTION_WRT);
303 } // namespace SchemeActionMap
304 } /* namespace ViewModule */