Revert "Resolving memory leak issue in Reply function of AppControl"
[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_bundle_(nullptr),
112       app_control_(NULL){
113   app_control_clone(&app_control_, app_control);
114   app_control_to_bundle(app_control_, &app_control_bundle_);
115 }
116
117 AppControl:: AppControl()
118     : app_control_bundle_(nullptr),
119       app_control_(NULL){
120   app_control_create(&app_control_);
121   app_control_to_bundle(app_control_, &app_control_bundle_);
122 }
123
124 AppControl::~AppControl() {
125   if (app_control_ != NULL) {
126     app_control_destroy(app_control_);
127   }
128 }
129
130 std::string AppControl::operation() const {
131   const char* operation = appsvc_get_operation(app_control_bundle_);
132
133   if (operation != NULL) {
134     return std::string(operation);
135   } else {
136     return std::string();
137   }
138 }
139
140 void AppControl::set_operation(const std::string& operation) {
141   appsvc_set_operation(app_control_bundle_, operation.c_str());
142 }
143
144 std::string AppControl::mime() const {
145   const char* mime = appsvc_get_mime(app_control_bundle_);
146
147   if (mime != NULL) {
148     return std::string(mime);
149   } else {
150     return std::string();
151   }
152 }
153
154 void AppControl::set_mime(const std::string& mime) {
155   appsvc_set_mime(app_control_bundle_, mime.c_str());
156 }
157
158 std::string AppControl::uri() const {
159   const char* uri = appsvc_get_uri(app_control_bundle_);
160
161   if (uri != NULL) {
162     return std::string(uri);
163   } else {
164     return std::string();
165   }
166 }
167
168 void AppControl::set_uri(const std::string& uri) {
169   appsvc_set_uri(app_control_bundle_, uri.c_str());
170 }
171
172 std::string AppControl::category() const {
173   const char* category = appsvc_get_category(app_control_bundle_);
174
175   if (category != NULL) {
176     return std::string(category);
177   } else {
178     return std::string();
179   }
180 }
181
182 void AppControl::set_category(const std::string& category) {
183   appsvc_set_category(app_control_bundle_, category.c_str());
184 }
185
186 std::string AppControl::data(const std::string& key) const {
187   const char* data = appsvc_get_data(app_control_bundle_, key.c_str());
188
189   if (data != NULL) {
190     return std::string(data);
191   } else {
192     return std::string();
193   }
194 }
195
196 std::vector<std::string> AppControl::data_array(const std::string& key) const {
197   int data_array_len = 0;
198   const char** data_array = appsvc_get_data_array(app_control_bundle_,
199                                                   key.c_str(), &data_array_len);
200   std::vector<std::string> data_vector;
201   if (data_array) {  // checking whether the 'data_array' is valid
202     if (data_array_len > 0) {
203       for (int i = 0; i < data_array_len; i++) {
204         data_vector.push_back(data_array[i]);
205       }
206     }
207   }
208   return data_vector;
209 }
210
211 std::string AppControl::encoded_bundle() {
212   bundle_raw* encoded_data;
213   int len;
214   bundle_encode(app_control_bundle_, &encoded_data, &len);
215   std::unique_ptr<bundle_raw*, decltype(bundle_free_encoded_rawdata)*>
216     ptr { &encoded_data, bundle_free_encoded_rawdata};
217   return std::string(reinterpret_cast<char*>(encoded_data), len);
218 }
219
220 bool AppControl::IsDataArray(const std::string& key) {
221   return appsvc_data_is_array(app_control_bundle_, key.c_str());
222 }
223
224 bool AppControl::AddData(const std::string& key, const std::string& value) {
225   return BundleAddData(app_control_bundle_, key, value);
226 }
227
228
229
230 bool AppControl::AddDataArray(const std::string& key,
231                               const std::vector<std::string>& value_array) {
232   return BundleAddDataArray(app_control_bundle_, key, value_array);
233 }
234
235
236 bool AppControl::Reply(const std::map<std::string,
237                                       std::vector<std::string>>& data) {
238   bundle* result;
239   if (appsvc_create_result_bundle(app_control_bundle_,
240                                   &result) != APPSVC_RET_OK) {
241     LOGGER(ERROR) << "Failed to craete result bundle.";
242     return false;
243   }
244   auto it = data.begin();
245   for ( ; it != data.end(); ++it) {
246     const std::string& key = it->first;
247     if (it->second.size() == 1) {
248       BundleAddData(result, key, it->second[0]);
249     } else {
250       BundleAddDataArray(result, key, it->second);
251     }
252   }
253
254   int ret = appsvc_send_result(result, APPSVC_RES_OK);
255   bundle_free(result);
256
257   return ret == APPSVC_RET_OK ? true : false;
258 }
259
260 bool AppControl::LaunchRequest() {
261   return (app_control_send_launch_request(app_control_, NULL, NULL) ==
262           APP_CONTROL_ERROR_NONE);
263 }
264
265 std::unique_ptr<AppControl> AppControl::MakeAppcontrolFromURL(
266     const std::string& url) {
267   std::string smsto_scheme("smsto");
268
269   std::string request_url(url);
270   std::string scheme = utils::SchemeName(request_url);
271   // smsto: does not supported by platform. change to sms:
272   if (scheme == smsto_scheme) {
273     request_url = "sms" + request_url.substr(smsto_scheme.length());
274     scheme = "sms";
275   }
276
277   std::unique_ptr<AppControl> request(new AppControl());
278   request->set_uri(request_url);
279   request->set_operation(GetOperationFromScheme(scheme));
280   AppendExtraDatafromUrl(request.get(), request_url);
281
282   return std::move(request);
283 }
284
285 }  // namespace common