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 {
38 * Lazy construction pattern.
39 * TODO Make it more general. Use variadic template/tuples/lambdas or sth. Move
42 template <typename T, typename Arg1>
46 explicit Lazy(const Arg1& arg1) :
48 m_object(new std::unique_ptr<T>())
51 Lazy(const Lazy<T, Arg1>& other) :
53 m_object(other.m_object)
57 T& operator*() { return GetObject(); }
58 const T& operator*() const { return GetObject(); }
59 const T* operator->() const { return &GetObject(); }
60 T* operator->() { return &GetObject(); }
62 Lazy<T, Arg1>& operator=(const Lazy<T, Arg1>& other)
64 m_arg1 = other.m_arg1;
65 m_object = other.m_object;
72 (*m_object).reset(new T(m_arg1));
78 // single unique_ptr shared among many Lazy copies
79 mutable std::shared_ptr<std::unique_ptr<T> > m_object;
83 * Struct defining conversion of scheme for given appsvc key for example:
84 * sms:5551212?body=expected%20text => APPSVC_DATA_TEXT + expected%20text
86 struct AppSvcConversion {
87 AppSvcConversion(char const * const keyValue, const std::string& regexStr):
91 char const * const key;
92 Lazy<pcrecpp::RE,std::string> regex;
96 * Struct defining an appsvc operation and a list of scheme conversions used to
97 * fill in additional appsvc data.
99 struct AppSvcOperation {
100 const char* operation;
102 std::list<AppSvcConversion> conversions;
105 typedef std::map<Scheme::Type, AppSvcOperation> AppSvcOperationMap;
107 // Regular expressions used to extract appsvc data from scheme
108 // TODO what about multiple recipients?
109 char const * const REGEX_BODY = ".*[?&]body=([^&]+).*";
110 char const * const REGEX_SMS = "sms:([^&]+).*";
111 char const * const REGEX_MMSTO = "mmsto:([^&]+).*";
112 char const * const REGEX_MAILTO = "mailto:([^&]+).*";
113 char const * const REGEX_TO = ".*[?&]to=([^&]+).*";
114 char const * const REGEX_CC = ".*[?&]cc=([^&]+).*";
115 char const * const REGEX_BCC = ".*[?&]bcc=([^&]+).*";
116 char const * const REGEX_SUBJECT = ".*[?&]subject=([^&]+).*";
117 char const * const REGEX_DATA_CONTEXT = ".*;phone-context=([^:]+).*";
119 AppSvcOperationMap initializeAppSvcOperations()
121 AppSvcOperationMap ret;
123 // FILE, HTTP & HTTPS
124 AppSvcOperation viewOp;
125 viewOp.operation = APPSVC_OPERATION_VIEW;
126 viewOp.needUri = true;
127 // no additional data
128 ret.insert(std::make_pair(Scheme::FILE, viewOp));
129 ret.insert(std::make_pair(Scheme::HTTP, viewOp));
130 ret.insert(std::make_pair(Scheme::HTTPS, viewOp));
133 AppSvcOperation smsOp;
134 smsOp.operation = APPSVC_OPERATION_SEND_TEXT;
135 smsOp.needUri = false;
136 smsOp.conversions.push_back(AppSvcConversion(APPSVC_DATA_TO, REGEX_SMS));
137 smsOp.conversions.push_back(AppSvcConversion(APPSVC_DATA_TEXT, REGEX_BODY));
138 ret.insert(std::make_pair(Scheme::SMS, smsOp));
141 AppSvcOperation sendOp;
142 sendOp.operation = APPSVC_OPERATION_SEND;
143 sendOp.needUri = false;
144 sendOp.conversions.push_back(AppSvcConversion(APPSVC_DATA_TO, REGEX_MMSTO));
145 sendOp.conversions.push_back(AppSvcConversion(APPSVC_DATA_TO, REGEX_MAILTO));
146 sendOp.conversions.push_back(AppSvcConversion(APPSVC_DATA_CC, REGEX_CC));
147 sendOp.conversions.push_back(
148 AppSvcConversion(APPSVC_DATA_BCC, REGEX_BCC));
149 sendOp.conversions.push_back(
150 AppSvcConversion(APPSVC_DATA_SUBJECT, REGEX_SUBJECT));
151 sendOp.conversions.push_back(
152 AppSvcConversion(APPSVC_DATA_TEXT, REGEX_BODY));
153 ret.insert(std::make_pair(Scheme::MMSTO, sendOp));
154 ret.insert(std::make_pair(Scheme::MAILTO, sendOp));
156 // TODO what about DATA?
159 AppSvcOperation telOp;
160 telOp.operation = APPSVC_OPERATION_CALL;
161 telOp.needUri = false;
162 //telOp.conversions.push_back(
163 // AppSvcConversion(APPSVC_DATA_CONTEXT, REGEX_DATA_CONTEXT)); //TODO
164 ret.insert(std::make_pair(Scheme::TEL, telOp));
169 AppSvcOperationMap g_appSvcOperationMap = initializeAppSvcOperations();
174 namespace SchemeActionMap {
176 bool HandleUri(const char* uri,
177 NavigationContext context,
178 WrtDB::AppType appType)
181 LogError("wrong arguments passed");
184 LogDebug("Uri being checked: " << uri);
186 const char *end = strstr(uri, ":");
188 LogError("Lack of scheme - ignoring");
191 std::string name(uri, end);
193 LogDebug("Scheme: " << name);
195 Scheme::Type type = scheme.GetType();
196 if (type < Scheme::FILE || type >= Scheme::COUNT) {
197 LogError("Invalid scheme: " << name);
201 LogDebug("Scheme type: " << type);
202 LogDebug("Navigation context: " << context);
203 LogDebug("Application type: " << appType);
207 case WrtDB::APP_TYPE_WAC20:
208 action = g_wacActionMap[type][context];
210 case WrtDB::APP_TYPE_TIZENWEBAPP:
211 action = g_tizenActionMap[type][context];
214 LogError("Unsupported application type: " << type);
218 LogDebug("Uri action: " << action);
220 // execute action if necessary
222 case URI_ACTION_APPSVC:
224 // find AppSvcOperation for given scheme type
225 auto it = g_appSvcOperationMap.find(type);
226 if (it == g_appSvcOperationMap.end()) {
227 LogError("No entry for scheme: " << name);
231 // prepare appsvc bundle
232 bundle* bundleData = bundle_create();
233 LogDebug("appsvc operation " << it->second.operation);
234 appsvc_set_operation(bundleData, it->second.operation);
235 if (it->second.needUri) {
236 appsvc_set_uri(bundleData, uri);
239 // this is safe as there are no other threads
240 CURL* curl = curl_easy_init();
243 char* unescaped = curl_easy_unescape(curl, uri, 0, &outLength);
244 std::string uUri(unescaped, outLength);
245 curl_free(unescaped);
246 curl_easy_cleanup(curl);
247 LogDebug("unescaped " << uUri);
249 // setup additional appsvc data
250 FOREACH(cit, it->second.conversions) {
251 LogDebug("extracting data for key " << cit->key);
254 pcrecpp::StringPiece input(uUri);
256 // convert scheme text to appsvc format
257 while (cit->regex->Consume(&input, &match)) {
258 LogInfo("Adding apssvc data: " << cit->key << " " << match);
259 appsvc_add_data(bundleData, cit->key, match.c_str());
263 // TODO do we need a callback?
264 CONTROLLER_POST_EVENT(
266 ApplicationLauncherEvents::LaunchApplicationByAppService(
273 case URI_ACTION_VIDEO:
274 CONTROLLER_POST_EVENT(
276 ApplicationLauncherEvents::LaunchApplicationByPkgname(
277 ApplicationLauncherPkgname::PKG_NAME_VIDEO_PLAYER,
285 return (action == URI_ACTION_WRT);
288 } // namespace SchemeActionMap
290 } /* namespace ViewModule */