ce625e902e46e26873ab4cd898a864eb64fb9303
[platform/framework/web/crosswalk-tizen.git] / common / app_control.cc
1 /*
2  * Copyright (c) 2015 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 #include "common/app_control.h"
18
19 #include <appsvc.h>
20 #include <app_control_internal.h>
21 #include <bundle_internal.h>
22
23 #include <algorithm>
24 #include <memory>
25 #include <map>
26 #include <regex> // NOLINT
27 #include <utility>
28 #include <vector>
29
30 #include "common/file_utils.h"
31 #include "common/logger.h"
32 #include "common/string_utils.h"
33
34 namespace common {
35
36 namespace {
37 static bool BundleAddData(bundle* target, const std::string& key,
38                           const std::string& value) {
39   int result = appsvc_add_data(target, key.c_str(), value.c_str());
40   if (result < 0) {
41     LOGGER(ERROR) << "Failed to add data to appsvc.";
42     return false;
43   } else {
44     return true;
45   }
46 }
47
48 static bool BundleAddDataArray(bundle* target, const std::string& key,
49                                const std::vector<std::string>& value_array) {
50   int n = value_array.size();
51   std::vector<const char*> v;
52   std::for_each(value_array.begin(), value_array.end(),
53                 [&v] (const std::string& str) {
54                   v.push_back(static_cast<const char*>(str.c_str()));
55                 });
56
57   int result = appsvc_add_data_array(target, key.c_str(),
58                                      v.data(), n);
59   if (result < 0) {
60     LOGGER(ERROR) << "Failed to add an array of data to appsvc.";
61     return false;
62   } else {
63     return true;
64   }
65 }
66
67 static const std::string GetOperationFromScheme(const std::string& scheme) {
68   static std::map<const std::string, const std::string> table = {
69     {"sms", APP_CONTROL_OPERATION_COMPOSE},
70     {"mmsto", APP_CONTROL_OPERATION_COMPOSE},
71     {"mailto", APP_CONTROL_OPERATION_COMPOSE},
72     {"tel", APP_CONTROL_OPERATION_CALL}
73   };
74   auto found = table.find(scheme);
75   if (found == table.end()) {
76     // default operation
77     return APP_CONTROL_OPERATION_VIEW;
78   }
79   return found->second;
80 }
81
82 static void AppendExtraDatafromUrl(AppControl* request,
83                                    const std::string& url) {
84   static std::vector<std::pair<std::string, std::string> > patterns = {
85     {".*[?&]body=([^&]+).*", APP_CONTROL_DATA_TEXT},
86     {".*[?&]cc=([^&]+).*", APP_CONTROL_DATA_CC},
87     {".*[?&]bcc=([^&]+).*", APP_CONTROL_DATA_BCC},
88     {".*[?&]subject=([^&]+).*", APP_CONTROL_DATA_SUBJECT},
89     {".*[?&]to=([^&]+).*", APP_CONTROL_DATA_TO},
90     {"sms:([^?&]+).*", APP_CONTROL_DATA_TO},
91     {"mmsto:([^?&]+).*", APP_CONTROL_DATA_TO},
92     {"mailto:([^?&]+).*", APP_CONTROL_DATA_TO}
93   };
94
95   for (auto& param : patterns) {
96     std::regex pattern(param.first, std::regex_constants::icase);
97     std::smatch result;
98     if (std::regex_match(url, result, pattern) && result.size() >= 2) {
99       std::string extra_data = result[1].str();
100       request->AddData(
101         param.second,
102         utils::UrlDecode(extra_data));
103     }
104   }
105 }
106
107
108 }  // namespace
109
110 AppControl::AppControl(app_control_h app_control) {
111   app_control_clone(&app_control_, app_control);
112   app_control_to_bundle(app_control_, &app_control_bundle_);
113 }
114
115 AppControl:: AppControl() {
116   app_control_create(&app_control_);
117   app_control_to_bundle(app_control_, &app_control_bundle_);
118 }
119
120 AppControl::~AppControl() {
121   if (app_control_ != NULL) {
122     app_control_destroy(app_control_);
123   }
124 }
125
126 std::string AppControl::operation() const {
127   const char* operation = appsvc_get_operation(app_control_bundle_);
128
129   if (operation != NULL) {
130     return std::string(operation);
131   } else {
132     return std::string();
133   }
134 }
135
136 void AppControl::set_operation(const std::string& operation) {
137   appsvc_set_operation(app_control_bundle_, operation.c_str());
138 }
139
140 std::string AppControl::mime() const {
141   const char* mime = appsvc_get_mime(app_control_bundle_);
142
143   if (mime != NULL) {
144     return std::string(mime);
145   } else {
146     return std::string();
147   }
148 }
149
150 void AppControl::set_mime(const std::string& mime) {
151   appsvc_set_mime(app_control_bundle_, mime.c_str());
152 }
153
154 std::string AppControl::uri() const {
155   const char* uri = appsvc_get_uri(app_control_bundle_);
156
157   if (uri != NULL) {
158     return std::string(uri);
159   } else {
160     return std::string();
161   }
162 }
163
164 void AppControl::set_uri(const std::string& uri) {
165   appsvc_set_uri(app_control_bundle_, uri.c_str());
166 }
167
168 std::string AppControl::category() const {
169   const char* category = appsvc_get_category(app_control_bundle_);
170
171   if (category != NULL) {
172     return std::string(category);
173   } else {
174     return std::string();
175   }
176 }
177
178 void AppControl::set_category(const std::string& category) {
179   appsvc_set_category(app_control_bundle_, category.c_str());
180 }
181
182 std::string AppControl::data(const std::string& key) const {
183   const char* data = appsvc_get_data(app_control_bundle_, key.c_str());
184
185   if (data != NULL) {
186     return std::string(data);
187   } else {
188     return std::string();
189   }
190 }
191
192 std::vector<std::string> AppControl::data_array(const std::string& key) const {
193   int data_array_len = 0;
194   const char** data_array = appsvc_get_data_array(app_control_bundle_,
195                                                   key.c_str(), &data_array_len);
196   std::vector<std::string> data_vector;
197   if (data_array) {  // checking whether the 'data_array' is valid
198     if (data_array_len > 0) {
199       for (int i = 0; i < data_array_len; i++) {
200         data_vector.push_back(data_array[i]);
201       }
202     }
203   }
204   return data_vector;
205 }
206
207 std::string AppControl::encoded_bundle() {
208   bundle_raw* encoded_data;
209   int len;
210   bundle_encode(app_control_bundle_, &encoded_data, &len);
211   std::unique_ptr<bundle_raw*, decltype(bundle_free_encoded_rawdata)*>
212     ptr { &encoded_data, bundle_free_encoded_rawdata};
213   return std::string(reinterpret_cast<char*>(encoded_data), len);
214 }
215
216 bool AppControl::IsDataArray(const std::string& key) {
217   return appsvc_data_is_array(app_control_bundle_, key.c_str());
218 }
219
220 bool AppControl::AddData(const std::string& key, const std::string& value) {
221   return BundleAddData(app_control_bundle_, key, value);
222 }
223
224
225
226 bool AppControl::AddDataArray(const std::string& key,
227                               const std::vector<std::string>& value_array) {
228   return BundleAddDataArray(app_control_bundle_, key, value_array);
229 }
230
231
232 bool AppControl::Reply(const std::map<std::string,
233                                       std::vector<std::string>>& data) {
234   bundle* result;
235   if (appsvc_create_result_bundle(app_control_bundle_,
236                                   &result) != APPSVC_RET_OK) {
237     LOGGER(ERROR) << "Failed to craete result bundle.";
238     return false;
239   }
240   auto it = data.begin();
241   for ( ; it != data.end(); ++it) {
242     const std::string& key = it->first;
243     if (it->second.size() == 1) {
244       BundleAddData(result, key, it->second[0]);
245     } else {
246       BundleAddDataArray(result, key, it->second);
247     }
248   }
249
250   int ret = appsvc_send_result(result, APPSVC_RES_OK);
251   bundle_free(result);
252
253   return ret == APPSVC_RET_OK ? true : false;
254 }
255
256 bool AppControl::LaunchRequest() {
257   return (app_control_send_launch_request(app_control_, NULL, NULL) ==
258           APP_CONTROL_ERROR_NONE);
259 }
260
261 std::unique_ptr<AppControl> AppControl::MakeAppcontrolFromURL(
262     const std::string& url) {
263   std::string smsto_scheme("smsto");
264
265   std::string request_url(url);
266   std::string scheme = utils::SchemeName(request_url);
267   // smsto: does not supported by platform. change to sms:
268   if (scheme == smsto_scheme) {
269     request_url = "sms" + request_url.substr(smsto_scheme.length());
270     scheme = "sms";
271   }
272
273   std::unique_ptr<AppControl> request(new AppControl());
274   request->set_uri(request_url);
275   request->set_operation(GetOperationFromScheme(scheme));
276   AppendExtraDatafromUrl(request.get(), request_url);
277
278   return std::move(request);
279 }
280
281 }  // namespace common