2 * Copyright (c) 2015 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 #include "wrt/src/browser/native_app_control.h"
20 #include <app_control_internal.h>
21 #include <bundle_internal.h>
26 #include <regex> // NOLINT
30 #include "base/logging.h"
31 #include "wrt/src/base/file_utils.h"
32 #include "wrt/src/base/string_utils.h"
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());
43 LOG(ERROR) << "Failed to add data to appsvc.";
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()));
60 int result = appsvc_add_data_array(target, key.c_str(), v.data(), n);
62 LOG(ERROR) << "Failed to add an array of data to appsvc.";
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}
76 auto found = table.find(scheme);
77 if (found == table.end()) {
79 return APP_CONTROL_OPERATION_VIEW;
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}
97 for (auto& param : patterns) {
98 std::regex pattern(param.first, std::regex_constants::icase);
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));
110 std::unique_ptr<NativeAppControl> NativeAppControl::MakeAppcontrolFromURL(
111 const std::string& url) {
112 std::string smsto_scheme("smsto");
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());
122 std::unique_ptr<NativeAppControl> request(new NativeAppControl());
123 request->SetUri(request_url);
124 request->SetOperation(GetOperationFromScheme(scheme));
125 AppendExtraDatafromUrl(request.get(), request_url);
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_);
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;
141 app_control_to_bundle(app_control_, &app_control_bundle_);
144 NativeAppControl::~NativeAppControl() {
146 app_control_destroy(app_control_);
149 std::string NativeAppControl::GetOperation() const {
150 const char* operation = appsvc_get_operation(app_control_bundle_);
151 return operation ? std::string(operation) : std::string();
154 void NativeAppControl::SetOperation(const std::string& operation) {
155 appsvc_set_operation(app_control_bundle_, operation.c_str());
158 std::string NativeAppControl::GetMime() const {
159 const char* mime = appsvc_get_mime(app_control_bundle_);
160 return mime ? std::string(mime) : std::string();
163 void NativeAppControl::SetMime(const std::string& mime) {
164 appsvc_set_mime(app_control_bundle_, mime.c_str());
167 std::string NativeAppControl::GetUri() const {
168 const char* uri = appsvc_get_uri(app_control_bundle_);
169 return uri ? std::string(uri) : std::string();
172 void NativeAppControl::SetUri(const std::string& uri) {
173 appsvc_set_uri(app_control_bundle_, uri.c_str());
176 std::string NativeAppControl::GetCategory() const {
177 const char* category = appsvc_get_category(app_control_bundle_);
178 return category ? std::string(category) : std::string();
181 void NativeAppControl::SetCategory(const std::string& category) {
182 appsvc_set_category(app_control_bundle_, category.c_str());
185 bool NativeAppControl::IsDataArray(const std::string& key) {
186 return appsvc_data_is_array(app_control_bundle_, key.c_str());
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();
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]);
210 bool NativeAppControl::AddData(
211 const std::string& key, const std::string& value) {
212 return BundleAddData(app_control_bundle_, key, value);
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);
220 bool NativeAppControl::SendLaunchRequest() {
221 return (app_control_send_launch_request(app_control_, nullptr, nullptr) ==
222 APP_CONTROL_ERROR_NONE);
225 bool NativeAppControl::Reply(
226 const std::map<std::string, std::vector<std::string>>& data) {
228 if (appsvc_create_result_bundle(app_control_bundle_, &result) !=
230 LOG(ERROR) << "Failed to craete result bundle.";
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]);
239 BundleAddDataArray(result, key, it->second);
243 int ret = appsvc_send_result(result, APPSVC_RES_OK);
246 return ret == APPSVC_RET_OK;
249 std::string NativeAppControl::GetEncodedBundle() {
250 bundle_raw* encoded_data;
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);