Set mime type for bundle in case of mmsto, sms
[platform/framework/web/wrt.git] / src / view / common / view_logic_uri_support.cpp
1 /*
2  * Copyright (c) 2011 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    view_logic_uri_support.cpp
18  * @author  Pawel Sikorski (p.sikorski@samsung.com)
19  * @brief   Implementation file of UriSupport API used by ViewLogic
20  */
21
22 #include "view_logic_uri_support.h"
23 #include <string>
24 #include <vector>
25 #include <list>
26 #include <dpl/string.h>
27 #include <dpl/log/log.h>
28 #include <dpl/localization/w3c_file_localization.h>
29 #include <widget_model.h>
30 #include <bundle.h>
31 #include <appsvc.h>
32 #include <application_data.h>
33 #include <wrt-commons/custom-handler-dao-ro/CustomHandlerDatabase.h>
34 #include <wrt-commons/custom-handler-dao-ro/custom_handler_dao_read_only.h>
35 #include <stdio.h>
36
37 namespace ViewModule {
38 namespace UriSupport {
39
40 namespace {
41 enum ServiceDataType
42 {
43     SERVICE_DATA_TYPE_OPERATION,
44     SERVICE_DATA_TYPE_URI,
45     SERVICE_DATA_TYPE_MIME,
46     SERVICE_DATA_TYPE_MIME_ELEMENT
47 };
48
49 char const * const SCHEME_TYPE_FILE = "file";
50 char const * const SCHEME_TYPE_WIDGET = "widget";
51 char const * const SERVICE_DATA_WILD_CHAR = "*";
52 char const * const SERVICE_DATA_MIME_TOKEN = "/";
53 const unsigned int SIZE_OF_MIME_ELEMENT = 2;
54
55 std::list<std::string> parsingMimeData(std::string origin, std::string token)
56 {
57     std::list<std::string> parsedData;
58     size_t current = 0;
59     size_t next = 0;
60     do {
61         next = origin.find_first_of(token, current);
62         parsedData.push_back(origin.substr(current, next - current));
63         current = next + 1;
64     } while (next != std::string::npos && current < origin.length());
65     return parsedData;
66 }
67
68 /**
69  * Parses scheme from appsvc. From mailto:test@wacapps.net
70  * it will return list:
71  * 0: mailto
72  * 1: test@wacapps.net
73  */
74 std::vector<std::string> parseScheme(const std::string &scheme)
75 {
76     std::vector<std::string> schemeParts;
77     std::string::size_type pos = scheme.find(":");
78     if (pos != std::string::npos) {
79         schemeParts.push_back(scheme.substr(0, pos));
80         schemeParts.push_back(
81                 scheme.substr(pos + 1, scheme.length() - pos - 1));
82     }
83     return schemeParts;
84 }
85
86 bool compareServiceData(ServiceDataType type,
87                         std::string origin,
88                         std::string other)
89 {
90     if (SERVICE_DATA_TYPE_OPERATION == type) {
91         return origin == other;
92     } else if (SERVICE_DATA_TYPE_URI == type
93                || SERVICE_DATA_TYPE_MIME_ELEMENT == type)
94     {
95         if (SERVICE_DATA_WILD_CHAR == origin) {
96             return true;
97         } else {
98             return origin == other;
99         }
100     } else if (SERVICE_DATA_TYPE_MIME == type) {
101         if (other == "") {
102             return origin == other;
103         }
104
105         std::list<std::string> vectorOrigin =
106             parsingMimeData(origin, SERVICE_DATA_MIME_TOKEN);
107         if (SIZE_OF_MIME_ELEMENT != vectorOrigin.size()) {
108             return false;
109         }
110         std::list<std::string> vectorOther =
111             parsingMimeData(other, SERVICE_DATA_MIME_TOKEN);
112         if (SIZE_OF_MIME_ELEMENT != vectorOther.size()) {
113             return false;
114         }
115
116         FOREACH(it, vectorOrigin) {
117             if (!compareServiceData(SERVICE_DATA_TYPE_MIME_ELEMENT,
118                                     *it,
119                                     vectorOther.front()))
120             {
121                 return false;
122             }
123             vectorOther.pop_front();
124         }
125         return true;
126     } else {
127         LogError("Wrong data type");
128         return false;
129     }
130 }
131 }
132
133 std::string prepareUrl(const std::string &url, const std::string &insert)
134 {
135     std::string urlFixed = url;
136     if (urlFixed.find("file://") == 0) {
137         urlFixed.erase(0, 6);
138     }
139     //replace %s in url with given from appservice
140     int size = snprintf(NULL, 0, urlFixed.c_str(), insert.c_str()) + 1;
141     char buffer[size];
142     snprintf(buffer, size, urlFixed.c_str(), insert.c_str());
143     return std::string(buffer);
144 }
145
146 std::string getCustomHandlerProtocolUri(
147         WidgetModel *widgetModel,
148         const std::string &schemeType,
149         const std::string &schemeValue)
150 {
151     CustomHandlerDB::Interface::attachDatabaseRO();
152     CustomHandlerDB::CustomHandlerDAOReadOnly handlersDao(widgetModel->TizenId);
153     CustomHandlerDB::CustomHandlerPtr handler =
154             handlersDao.getActivProtocolHandler(
155                 DPL::FromASCIIString(schemeType));
156     CustomHandlerDB::Interface::detachDatabase();
157     if (handler) {
158         LogDebug("Found handler, url: " << handler->url);
159         return prepareUrl(DPL::ToUTF8String(handler->base_url) +
160                 DPL::ToUTF8String(handler->url), schemeValue);
161     }
162     return "";
163 }
164
165 std::string getCustomHandlerContentUri(
166         WidgetModel *widgetModel,
167         const std::string &mime,
168         const std::string &mimeValue)
169 {
170     CustomHandlerDB::Interface::attachDatabaseRO();
171     CustomHandlerDB::CustomHandlerDAOReadOnly handlersDao(widgetModel->TizenId);
172     CustomHandlerDB::CustomHandlerPtr handler =
173             handlersDao.getActivContentHandler(
174                 DPL::FromASCIIString(mime));
175     CustomHandlerDB::Interface::detachDatabase();
176     if (handler) {
177         LogDebug("Found handler, url: " << handler->url);
178         return prepareUrl(DPL::ToUTF8String(handler->base_url) +
179                 DPL::ToUTF8String(handler->url), mimeValue);
180     }
181     return "";
182 }
183
184 std::string getAppServiceUri(bundle *bundle, WidgetModel *widgetModel)
185 {
186     if(!bundle)
187     {
188         LogError("Bundle is empty");
189         return std::string("");
190     }
191
192     const char* value = NULL;
193     value = appsvc_get_operation(bundle);
194     std::string operation = value ? value : "";
195     // ignore default operation that is reserved by system
196     if (operation == APPSVC_OPERATION_DEFAULT) {
197         return std::string("");
198     }
199     value = appsvc_get_uri(bundle);
200     std::string scheme = value ? value : "";
201     value = appsvc_get_mime(bundle);
202     std::string mime = value ? value : "";
203
204     LogDebug("operation : " << operation);
205     LogDebug("schemeType : " << scheme);
206     LogDebug("mimetype : " << mime);
207
208     WidgetApplicationServiceList appServiceList =
209         widgetModel->AppServiceList.Get();
210     FOREACH(appServiceIt, appServiceList) {
211         if (compareServiceData(SERVICE_DATA_TYPE_OPERATION,
212                                DPL::ToUTF8String(appServiceIt->operation),
213                                operation) &&
214             compareServiceData(SERVICE_DATA_TYPE_URI,
215                                DPL::ToUTF8String(appServiceIt->scheme),
216                                scheme) &&
217             compareServiceData(SERVICE_DATA_TYPE_MIME,
218                                DPL::ToUTF8String(appServiceIt->mime),
219                                mime))
220         {
221             return DPL::ToUTF8String(appServiceIt->src);
222         }
223     }
224     std::vector<std::string> schemeParts = parseScheme(scheme);
225     if (schemeParts.size() > 1) {
226         LogDebug("Scheme parts: " << schemeParts[0] << ", " << schemeParts[1]);
227         return getCustomHandlerProtocolUri(
228                 widgetModel, schemeParts[0], schemeParts[1]);
229     }
230     if (mime != "") {
231         value = appsvc_get_data(bundle, APPSVC_DATA_SELECTED);
232         if (value != NULL) {
233             LogDebug("Use mime type for: " << value);
234             return getCustomHandlerContentUri(
235                     widgetModel, mime, std::string(value));
236         } else {
237             LogError("Selected file for mime is null, nothind to do");
238         }
239     }
240     LogDebug("no matching result");
241     return std::string("");
242 }
243
244 std::string getUri(WidgetModel *widgetModel, const std::string &defaultUri)
245 {
246     DPL::String uri;
247     std::string startUri;
248     LogDebug("default uri: " << defaultUri);
249     bundle *originBundle = ApplicationDataSingleton::Instance().getBundle();
250     // search application service
251     startUri = getAppServiceUri(originBundle, widgetModel).c_str();
252     LogInfo("application service start uri is " << startUri);
253     if (startUri == "") {
254         LogInfo("application service doesn't have matched data");
255         startUri = defaultUri;
256     } else {
257         // create encoded bundle data only for uri for application service
258         ApplicationDataSingleton::Instance().setEncodedBundle(originBundle);
259     }
260
261     // insert prefix path
262     std::string preFix = DPL::ToUTF8String(widgetModel->PrefixURL.Get());
263
264     if (strstr(startUri.c_str(), "http") == startUri.c_str() ||
265             strstr( startUri.c_str(), preFix.c_str()) == startUri.c_str()) {
266         uri = DPL::FromUTF8String(startUri);
267     } else {
268         uri = widgetModel->PrefixURL.Get() +
269         DPL::FromUTF8String(startUri);
270     }
271     return DPL::ToUTF8String(uri).c_str();
272 }
273
274 DPL::OptionalString localizeURI(const DPL::String& inputURI,
275                                 const WidgetModel* model)
276 {
277     auto uri = DPL::ToUTF8String(inputURI);
278     LogDebug("localizing url: " << uri);
279
280     auto urlcstr = uri.c_str();
281
282     const char *end = strstr(urlcstr, ":");
283     if (!end) {
284         LogDebug("no schema in link, return null");
285         // lack of schema
286         return DPL::Optional<DPL::String>::Null;
287     }
288
289     std::string scheme(urlcstr, end);
290     if (scheme != SCHEME_TYPE_WIDGET && scheme != SCHEME_TYPE_FILE) {
291         LogDebug("scheme doesn't need to localize");
292         return DPL::OptionalString(inputURI);
293     }
294
295     DPL::Optional<DPL::String> found =
296         W3CFileLocalization::getFilePathInWidgetPackageFromUrl(
297             model->TizenId,
298             DPL::FromUTF8String(uri));
299
300     if (found.IsNull()) {
301         // In this case, path doesn't need to localize. return input uri
302         LogDebug("Path not found within current locale in current widget");
303         return DPL::OptionalString(inputURI);
304     } else {
305         DPL::String uri(L"file://" + *found);
306         LogDebug("Will load resource: " << uri);
307         LogDebug("finished");
308         return DPL::OptionalString(uri);
309     }
310 }
311
312 } // namespace UriSupportImplementation
313 } // namespace ViewModule