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