This common module is base of Runtime and Extension component.
Change-Id: If0163dc1671ef81bb353ddc496ec92aaaa705352
Signed-off-by: ss440 <ss440.han@samsung.com>
Signed-off-by: Youngsoo Choi <kenshin.choi@samsung.com>
},
],
}], # OS=="linux"
+ [ 'is_tizen==1', {
+ 'dependencies': [
+ 'tizen/common/common.gyp:*',
+ ],
+ }], # is_tizen==1
],
}, # target <(project_name)
{
%ifarch aarch64
BuildRequires: python-accel-aarch64-cross-aarch64
%endif
+BuildRequires: pkgconfig(appsvc)
+BuildRequires: pkgconfig(aul)
+BuildRequires: pkgconfig(bundle)
+BuildRequires: pkgconfig(capi-appfw-application)
+BuildRequires: pkgconfig(capi-appfw-app-manager)
+BuildRequires: pkgconfig(capi-appfw-package-manager)
+BuildRequires: pkgconfig(capi-system-system-settings)
+BuildRequires: pkgconfig(capi-system-info)
BuildRequires: pkgconfig(chromium-efl)
+BuildRequires: pkgconfig(cynara-client)
BuildRequires: pkgconfig(dbus-glib-1)
+BuildRequires: pkgconfig(dlog)
BuildRequires: pkgconfig(ecore-evas)
BuildRequires: pkgconfig(efl-extension)
BuildRequires: pkgconfig(elementary)
BuildRequires: pkgconfig(evas)
BuildRequires: pkgconfig(expat)
+BuildRequires: pkgconfig(glib-2.0)
BuildRequires: pkgconfig(gmodule-2.0)
BuildRequires: pkgconfig(icu-i18n)
# It's added to use TZ_SYS_RO_PACKAGES.
BuildRequires: pkgconfig(libtzplatform-config)
+BuildRequires: pkgconfig(libwebappenc)
+BuildRequires: pkgconfig(manifest-parser)
BuildRequires: pkgconfig(nss)
+BuildRequires: pkgconfig(pkgmgr-info)
+BuildRequires: pkgconfig(sqlite3)
+BuildRequires: pkgconfig(uuid)
+BuildRequires: pkgconfig(ttrace)
%if "%{?TIZEN_PRODUCT_TV}" == "1"
BuildRequires: pkgconfig(vd-win-util)
%endif
+BuildRequires: pkgconfig(wgt-manifest-handlers)
Requires: /usr/bin/systemctl
--- /dev/null
+{
+ 'variables': {
+ 'build_type%': 'Debug',
+# 'extension_path%': '<(extension_path)',
+# 'injected_bundle_path%': '<(injected_bundle_path)',
+ },
+ 'target_defaults': {
+ 'variables': {
+ 'build_type%': '<(build_type)',
+ },
+ 'conditions': [
+ ['is_tizen==1', {
+ 'cflags': [ '-fPIC' ],
+ 'cflags_cc': [ '-fPIC']
+ }],
+ ['build_type== "Debug"', {
+ 'defines': ['_DEBUG', 'TIZEN_DEBUG_ENABLE', ],
+ 'cflags': [ '-O0', '-g', ],
+ }],
+ ['build_type == "Release"', {
+ 'defines': ['NDEBUG', ],
+ 'cflags': [
+ '-O2',
+ # Don't emit the GCC version ident directives, they just end up
+ # in the .comment section taking up binary size.
+ '-fno-ident',
+ # Put data and code in their own sections, so that unused symbols
+ # can be removed at link time with --gc-sections.
+ '-fdata-sections',
+ '-ffunction-sections',
+ ],
+ }],
+ ],
+ 'includes': [
+ 'cynara-client.gypi',
+ 'pkg-config.gypi',
+# 'xwalk_js2c.gypi',
+ ],
+ 'include_dirs': [
+ '../',
+ '<(SHARED_INTERMEDIATE_DIR)',
+ ],
+# 'defines': [
+# 'EXTENSION_PATH="<(extension_path)"',
+# 'INJECTED_BUNDLE_PATH="<(injected_bundle_path)"',
+# ],
+ 'cflags': [
+ '-std=c++0x',
+ '-fPIC',
+ '-fvisibility=hidden',
+ '-Wall',
+ ],
+ 'libraries' : [
+ '-L./lib',
+ ],
+ },
+}
\ No newline at end of file
--- /dev/null
+{
+ 'variables': {
+ 'pkg-config': 'pkg-config',
+ },
+ 'cflags': [
+ '<!@(<(pkg-config) --cflags cynara-client)'
+ ],
+ 'link_settings': {
+ 'ldflags': [
+ '<!@(<(pkg-config) --libs-only-L --libs-only-other cynara-client)',
+ ],
+ 'libraries': [
+ '<!@(<(pkg-config) --libs-only-l cynara-client)',
+ ],
+ },
+} # cynara-client
--- /dev/null
+{
+ 'variables': {
+ 'packages%': [],
+ },
+
+ 'cflags': [
+ '>!@(if [ -n ">@(packages)" ]; then pkg-config --cflags >@(packages); fi)'
+ ],
+
+ 'link_settings': {
+ 'ldflags': [
+ '>!@(if [ -n ">@(packages)" ]; then pkg-config --libs-only-L --libs-only-other >@(packages); fi)',
+ ],
+ 'libraries': [
+ '>!@(if [ -n ">@(packages)" ]; then pkg-config --libs-only-l >@(packages); fi)',
+ ],
+ },
+}
--- /dev/null
+{
+ 'rules': [
+ {
+ 'rule_name': 'xwalk_js2c',
+ 'extension': 'js',
+ 'inputs': [
+ '../tools/generate_api.py',
+ ],
+ 'outputs': [
+ '<(SHARED_INTERMEDIATE_DIR)/<(RULE_INPUT_ROOT).cc'
+ ],
+ 'process_outputs_as_sources': 1,
+ 'action': [
+ 'python',
+ '<@(_inputs)',
+ '<(RULE_INPUT_PATH)',
+ 'kSource_<(RULE_INPUT_ROOT)',
+ '<@(_outputs)',
+ ],
+ 'message': 'Generating code from <(RULE_INPUT_PATH)',
+ },
+ ],
+}
--- /dev/null
+exclude_files=picojson\.h
\ No newline at end of file
--- /dev/null
+/*
+ * Copyright (c) 2015 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "common/app_control.h"
+
+#include <appsvc.h>
+#include <app_control_internal.h>
+#include <bundle_internal.h>
+
+#include <algorithm>
+#include <memory>
+#include <map>
+#include <regex> // NOLINT
+#include <utility>
+#include <vector>
+
+#include "common/file_utils.h"
+#include "common/logger.h"
+#include "common/string_utils.h"
+
+namespace common {
+
+namespace {
+static bool BundleAddData(bundle* target,
+ const std::string& key,
+ const std::string& value) {
+ int result = appsvc_add_data(target, key.c_str(), value.c_str());
+ if (result < 0) {
+ LOGGER(ERROR) << "Failed to add data to appsvc.";
+ return false;
+ } else {
+ return true;
+ }
+}
+
+static bool BundleAddDataArray(bundle* target,
+ const std::string& key,
+ const std::vector<std::string>& value_array) {
+ int n = value_array.size();
+ std::vector<const char*> v;
+ std::for_each(value_array.begin(), value_array.end(),
+ [&v](const std::string& str) {
+ v.push_back(static_cast<const char*>(str.c_str()));
+ });
+
+ int result = appsvc_add_data_array(target, key.c_str(), v.data(), n);
+ if (result < 0) {
+ LOGGER(ERROR) << "Failed to add an array of data to appsvc.";
+ return false;
+ } else {
+ return true;
+ }
+}
+
+static const std::string GetOperationFromScheme(const std::string& scheme) {
+ static std::map<const std::string, const std::string> table = {
+ {"sms", APP_CONTROL_OPERATION_COMPOSE},
+ {"mmsto", APP_CONTROL_OPERATION_COMPOSE},
+ {"mailto", APP_CONTROL_OPERATION_COMPOSE},
+ {"tel", APP_CONTROL_OPERATION_CALL}};
+ auto found = table.find(scheme);
+ if (found == table.end()) {
+ // default operation
+ return APP_CONTROL_OPERATION_VIEW;
+ }
+ return found->second;
+}
+
+static void AppendExtraDatafromUrl(AppControl* request,
+ const std::string& url) {
+ static std::vector<std::pair<std::string, std::string>> patterns = {
+ {".*[?&]body=([^&]+).*", APP_CONTROL_DATA_TEXT},
+ {".*[?&]cc=([^&]+).*", APP_CONTROL_DATA_CC},
+ {".*[?&]bcc=([^&]+).*", APP_CONTROL_DATA_BCC},
+ {".*[?&]subject=([^&]+).*", APP_CONTROL_DATA_SUBJECT},
+ {".*[?&]to=([^&]+).*", APP_CONTROL_DATA_TO},
+ {"sms:([^?&]+).*", APP_CONTROL_DATA_TO},
+ {"mmsto:([^?&]+).*", APP_CONTROL_DATA_TO},
+ {"mailto:([^?&]+).*", APP_CONTROL_DATA_TO}};
+
+ for (auto& param : patterns) {
+ std::regex pattern(param.first, std::regex_constants::icase);
+ std::smatch result;
+ if (std::regex_match(url, result, pattern) && result.size() >= 2) {
+ std::string extra_data = result[1].str();
+ request->AddData(param.second, utils::UrlDecode(extra_data));
+ }
+ }
+}
+
+} // namespace
+
+AppControl::AppControl(app_control_h app_control) {
+ app_control_clone(&app_control_, app_control);
+ app_control_to_bundle(app_control_, &app_control_bundle_);
+}
+
+AppControl::AppControl() {
+ app_control_create(&app_control_);
+ app_control_to_bundle(app_control_, &app_control_bundle_);
+}
+
+AppControl::~AppControl() {
+ if (app_control_ != NULL) {
+ app_control_destroy(app_control_);
+ }
+}
+
+std::string AppControl::operation() const {
+ const char* operation = appsvc_get_operation(app_control_bundle_);
+
+ if (operation != NULL) {
+ return std::string(operation);
+ } else {
+ return std::string();
+ }
+}
+
+void AppControl::set_operation(const std::string& operation) {
+ appsvc_set_operation(app_control_bundle_, operation.c_str());
+}
+
+std::string AppControl::mime() const {
+ const char* mime = appsvc_get_mime(app_control_bundle_);
+
+ if (mime != NULL) {
+ return std::string(mime);
+ } else {
+ return std::string();
+ }
+}
+
+void AppControl::set_mime(const std::string& mime) {
+ appsvc_set_mime(app_control_bundle_, mime.c_str());
+}
+
+std::string AppControl::uri() const {
+ const char* uri = appsvc_get_uri(app_control_bundle_);
+
+ if (uri != NULL) {
+ return std::string(uri);
+ } else {
+ return std::string();
+ }
+}
+
+void AppControl::set_uri(const std::string& uri) {
+ appsvc_set_uri(app_control_bundle_, uri.c_str());
+}
+
+std::string AppControl::category() const {
+ const char* category = appsvc_get_category(app_control_bundle_);
+
+ if (category != NULL) {
+ return std::string(category);
+ } else {
+ return std::string();
+ }
+}
+
+void AppControl::set_category(const std::string& category) {
+ appsvc_set_category(app_control_bundle_, category.c_str());
+}
+
+std::string AppControl::data(const std::string& key) const {
+ const char* data = appsvc_get_data(app_control_bundle_, key.c_str());
+
+ if (data != NULL) {
+ return std::string(data);
+ } else {
+ return std::string();
+ }
+}
+
+std::vector<std::string> AppControl::data_array(const std::string& key) const {
+ int data_array_len = 0;
+ const char** data_array =
+ appsvc_get_data_array(app_control_bundle_, key.c_str(), &data_array_len);
+ std::vector<std::string> data_vector;
+ if (data_array) { // checking whether the 'data_array' is valid
+ if (data_array_len > 0) {
+ for (int i = 0; i < data_array_len; i++) {
+ data_vector.push_back(data_array[i]);
+ }
+ }
+ }
+ return data_vector;
+}
+
+std::string AppControl::encoded_bundle() {
+ bundle_raw* encoded_data;
+ int len;
+ bundle_encode(app_control_bundle_, &encoded_data, &len);
+ std::unique_ptr<bundle_raw*, decltype(bundle_free_encoded_rawdata)*> ptr{
+ &encoded_data, bundle_free_encoded_rawdata};
+ return std::string(reinterpret_cast<char*>(encoded_data), len);
+}
+
+bool AppControl::IsDataArray(const std::string& key) {
+ return appsvc_data_is_array(app_control_bundle_, key.c_str());
+}
+
+bool AppControl::AddData(const std::string& key, const std::string& value) {
+ return BundleAddData(app_control_bundle_, key, value);
+}
+
+bool AppControl::AddDataArray(const std::string& key,
+ const std::vector<std::string>& value_array) {
+ return BundleAddDataArray(app_control_bundle_, key, value_array);
+}
+
+bool AppControl::Reply(
+ const std::map<std::string, std::vector<std::string>>& data) {
+ bundle* result;
+ if (appsvc_create_result_bundle(app_control_bundle_, &result) !=
+ APPSVC_RET_OK) {
+ LOGGER(ERROR) << "Failed to craete result bundle.";
+ return false;
+ }
+ auto it = data.begin();
+ for (; it != data.end(); ++it) {
+ const std::string& key = it->first;
+ if (it->second.size() == 1) {
+ BundleAddData(result, key, it->second[0]);
+ } else {
+ BundleAddDataArray(result, key, it->second);
+ }
+ }
+
+ int ret = appsvc_send_result(result, APPSVC_RES_OK);
+ bundle_free(result);
+
+ return ret == APPSVC_RET_OK ? true : false;
+}
+
+bool AppControl::LaunchRequest() {
+ return (app_control_send_launch_request(app_control_, NULL, NULL) ==
+ APP_CONTROL_ERROR_NONE);
+}
+
+std::unique_ptr<AppControl> AppControl::MakeAppcontrolFromURL(
+ const std::string& url) {
+ std::string smsto_scheme("smsto");
+
+ std::string request_url(url);
+ std::string scheme = utils::SchemeName(request_url);
+ // smsto: does not supported by platform. change to sms:
+ if (scheme == smsto_scheme) {
+ request_url = "sms" + request_url.substr(smsto_scheme.length());
+ scheme = "sms";
+ }
+
+ std::unique_ptr<AppControl> request(new AppControl());
+ request->set_uri(request_url);
+ request->set_operation(GetOperationFromScheme(scheme));
+ AppendExtraDatafromUrl(request.get(), request_url);
+
+ return std::move(request);
+}
+
+} // namespace common
--- /dev/null
+/*
+ * Copyright (c) 2015 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef XWALK_COMMON_APP_CONTROL_H_
+#define XWALK_COMMON_APP_CONTROL_H_
+
+#include <app_control.h>
+#include <bundle.h>
+#include <map>
+#include <memory>
+#include <string>
+#include <vector>
+
+namespace common {
+
+class AppControl {
+ public:
+ static std::unique_ptr<AppControl> MakeAppcontrolFromURL(
+ const std::string& url);
+ explicit AppControl(app_control_h app_control);
+ AppControl();
+ ~AppControl();
+ // disable copy
+ AppControl(const AppControl& src) = delete;
+ AppControl& operator=(const AppControl&) = delete;
+
+ std::string operation() const;
+ void set_operation(const std::string& operation);
+ std::string mime() const;
+ void set_mime(const std::string& mime);
+ std::string uri() const;
+ void set_uri(const std::string& uri);
+ std::string category() const;
+ void set_category(const std::string& category);
+ std::string data(const std::string& key) const;
+ std::vector<std::string> data_array(const std::string& key) const;
+ std::string encoded_bundle();
+
+ bool IsDataArray(const std::string& key);
+ bool AddData(const std::string& key, const std::string& value);
+ bool AddDataArray(const std::string& key,
+ const std::vector<std::string>& value_array);
+ bool Reply(const std::map<std::string, std::vector<std::string>>& data);
+ bool LaunchRequest();
+
+ private:
+ app_control_h app_control_;
+ bundle* app_control_bundle_;
+};
+
+} // namespace common
+
+#endif // XWALK_COMMON_APP_CONTROL_H_
--- /dev/null
+/*
+ * Copyright (c) 2015 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "common/app_db.h"
+
+#include <app.h>
+#include <sqlite3.h>
+#include <unistd.h>
+#include <fstream>
+#include <memory>
+
+#include "common/logger.h"
+#include "common/string_utils.h"
+#include "common/file_utils.h"
+#include "common/picojson.h"
+#include "common/app_db_sqlite.h"
+
+namespace common {
+
+const char* kCreateDbQuery =
+ "CREATE TABLE IF NOT EXISTS appdb ("
+ "section TEXT, "
+ "key TEXT, "
+ "value TEXT,"
+ "PRIMARY KEY(section, key));";
+
+SqliteDB::SqliteDB(const std::string& app_data_path)
+ : app_data_path_(app_data_path), sqldb_(NULL) {
+ if (app_data_path_.empty()) {
+ std::unique_ptr<char, decltype(std::free)*> path{app_get_data_path(),
+ std::free};
+ if (path.get() != NULL)
+ app_data_path_ = path.get();
+ }
+ Initialize();
+}
+
+SqliteDB::~SqliteDB() {
+ if (sqldb_ != NULL) {
+ sqlite3_close(sqldb_);
+ sqldb_ = NULL;
+ }
+}
+
+void SqliteDB::MigrationAppdb() {
+ // file check
+ std::string migration_path = app_data_path_ + ".runtime.migration";
+ if (!common::utils::Exists(migration_path)) {
+ return;
+ } else {
+ LOGGER(DEBUG) << "Migration file found : " << migration_path;
+ }
+
+ std::ifstream migration_file(migration_path);
+ if (!migration_file.is_open()) {
+ LOGGER(ERROR) << "Fail to open file";
+ return;
+ }
+ picojson::value v;
+ std::string err;
+ err = picojson::parse(v, migration_file);
+ if (!err.empty()) {
+ LOGGER(ERROR) << "Fail to parse file :" << err;
+ return;
+ }
+
+ LOGGER(DEBUG) << "Start to get list data";
+
+ picojson::array data_list;
+
+ if (!v.get("preference").is<picojson::null>()) {
+ picojson::array preference_list =
+ v.get("preference").get<picojson::array>();
+ data_list.insert(data_list.end(), preference_list.begin(),
+ preference_list.end());
+ }
+ if (!v.get("certificate").is<picojson::null>()) {
+ picojson::array certificate_list =
+ v.get("certificate").get<picojson::array>();
+ data_list.insert(data_list.end(), certificate_list.begin(),
+ certificate_list.end());
+ }
+ if (!v.get("security_origin").is<picojson::null>()) {
+ picojson::array security_origin_list =
+ v.get("security_origin").get<picojson::array>();
+ data_list.insert(data_list.end(), security_origin_list.begin(),
+ security_origin_list.end());
+ }
+
+ for (auto it = data_list.begin(); it != data_list.end(); ++it) {
+ if (!it->is<picojson::object>())
+ continue;
+ std::string section = it->get("section").to_str();
+ std::string key = it->get("key").to_str();
+ std::string value = it->get("value").to_str();
+
+ LOGGER(DEBUG) << "INPUT[" << section << "][" << key << "][" << value << "]";
+ Set(section, key, value);
+ }
+
+ LOGGER(DEBUG) << "Migration complete";
+
+ if (0 != remove(migration_path.c_str())) {
+ LOGGER(ERROR) << "Fail to remove migration file";
+ }
+}
+
+void SqliteDB::Initialize() {
+ if (app_data_path_.empty()) {
+ LOGGER(ERROR) << "app data path was empty";
+ return;
+ }
+ std::string db_path = app_data_path_ + "/.appdb.db";
+ int ret = sqlite3_open(db_path.c_str(), &sqldb_);
+ if (ret != SQLITE_OK) {
+ LOGGER(ERROR) << "Fail to open app db :" << sqlite3_errmsg(sqldb_);
+ sqldb_ = NULL;
+ return;
+ }
+ sqlite3_busy_handler(sqldb_,
+ [](void*, int count) {
+ if (count < 5) {
+ LOGGER(ERROR)
+ << "App db was busy, Wait the lock count("
+ << count << ")";
+ usleep(100000 * (count + 1));
+ return 1;
+ } else {
+ LOGGER(ERROR) << "App db was busy, Fail to access";
+ return 0;
+ }
+ },
+ NULL);
+
+ char* errmsg = NULL;
+ ret = sqlite3_exec(sqldb_, kCreateDbQuery, NULL, NULL, &errmsg);
+ if (ret != SQLITE_OK) {
+ LOGGER(ERROR) << "Error to create appdb : " << (errmsg ? errmsg : "");
+ if (errmsg)
+ sqlite3_free(errmsg);
+ }
+ MigrationAppdb();
+}
+
+bool SqliteDB::HasKey(const std::string& section,
+ const std::string& key) const {
+ char* buffer = NULL;
+ sqlite3_stmt* stmt = NULL;
+ bool result = false;
+
+ int ret = 0;
+ buffer = sqlite3_mprintf(
+ "select count(*) from appdb where section = %Q and key = %Q",
+ section.c_str(), key.c_str());
+ if (buffer == NULL) {
+ LOGGER(ERROR) << "error to make query";
+ return false;
+ }
+
+ std::unique_ptr<char, decltype(sqlite3_free)*> scoped_data{buffer,
+ sqlite3_free};
+
+ ret = sqlite3_prepare(sqldb_, buffer, strlen(buffer), &stmt, NULL);
+ if (ret != SQLITE_OK) {
+ LOGGER(ERROR) << "Fail to prepare query : " << sqlite3_errmsg(sqldb_);
+ return false;
+ }
+
+ ret = sqlite3_step(stmt);
+ if (ret == SQLITE_ROW) {
+ int value = sqlite3_column_int(stmt, 0);
+ result = value > 0;
+ }
+
+ sqlite3_finalize(stmt);
+ return result;
+}
+
+std::string SqliteDB::Get(const std::string& section,
+ const std::string& key) const {
+ char* buffer = NULL;
+ sqlite3_stmt* stmt = NULL;
+ std::string result;
+
+ int ret = 0;
+ buffer =
+ sqlite3_mprintf("select value from appdb where section = %Q and key = %Q",
+ section.c_str(), key.c_str());
+ if (buffer == NULL) {
+ LOGGER(ERROR) << "error to make query";
+ return result;
+ }
+
+ std::unique_ptr<char, decltype(sqlite3_free)*> scoped_data{buffer,
+ sqlite3_free};
+
+ ret = sqlite3_prepare(sqldb_, buffer, strlen(buffer), &stmt, NULL);
+ if (ret != SQLITE_OK) {
+ LOGGER(ERROR) << "Fail to prepare query : " << sqlite3_errmsg(sqldb_);
+ return result;
+ }
+
+ ret = sqlite3_step(stmt);
+ if (ret == SQLITE_ROW) {
+ result = std::string(
+ reinterpret_cast<const char*>(sqlite3_column_text(stmt, 0)));
+ }
+
+ sqlite3_finalize(stmt);
+ return result;
+}
+
+void SqliteDB::Set(const std::string& section,
+ const std::string& key,
+ const std::string& value) {
+ char* buffer = NULL;
+ sqlite3_stmt* stmt = NULL;
+
+ int ret = 0;
+ buffer = sqlite3_mprintf(
+ "replace into appdb (section, key, value) values (?, ?, ?);");
+ if (buffer == NULL) {
+ LOGGER(ERROR) << "error to make query";
+ return;
+ }
+
+ std::unique_ptr<char, decltype(sqlite3_free)*> scoped_data{buffer,
+ sqlite3_free};
+
+ ret = sqlite3_prepare(sqldb_, buffer, strlen(buffer), &stmt, NULL);
+ if (ret != SQLITE_OK) {
+ LOGGER(ERROR) << "Fail to prepare query : " << sqlite3_errmsg(sqldb_);
+ return;
+ }
+
+ std::unique_ptr<sqlite3_stmt, decltype(sqlite3_finalize)*> scoped_stmt{
+ stmt, sqlite3_finalize};
+
+ ret = sqlite3_bind_text(stmt, 1, section.c_str(), section.length(),
+ SQLITE_STATIC);
+ if (ret != SQLITE_OK) {
+ LOGGER(ERROR) << "Fail to prepare query bind argument : "
+ << sqlite3_errmsg(sqldb_);
+ return;
+ }
+ ret = sqlite3_bind_text(stmt, 2, key.c_str(), key.length(), SQLITE_STATIC);
+ if (ret != SQLITE_OK) {
+ LOGGER(ERROR) << "Fail to prepare query bind argument : "
+ << sqlite3_errmsg(sqldb_);
+ return;
+ }
+ ret =
+ sqlite3_bind_text(stmt, 3, value.c_str(), value.length(), SQLITE_STATIC);
+ if (ret != SQLITE_OK) {
+ LOGGER(ERROR) << "Fail to prepare query bind argument : "
+ << sqlite3_errmsg(sqldb_);
+ return;
+ }
+ ret = sqlite3_step(stmt);
+ if (ret != SQLITE_DONE) {
+ LOGGER(ERROR) << "Fail to insert data : " << sqlite3_errmsg(sqldb_);
+ }
+}
+
+void SqliteDB::Remove(const std::string& section, const std::string& key) {
+ char* buffer = NULL;
+
+ buffer = sqlite3_mprintf("delete from appdb where section = %Q and key = %Q",
+ section.c_str(), key.c_str());
+
+ if (buffer == NULL) {
+ LOGGER(ERROR) << "error to make query";
+ return;
+ }
+
+ std::unique_ptr<char, decltype(sqlite3_free)*> scoped_data{buffer,
+ sqlite3_free};
+
+ char* errmsg = NULL;
+ int ret = sqlite3_exec(sqldb_, buffer, NULL, NULL, &errmsg);
+ if (ret != SQLITE_OK) {
+ LOGGER(ERROR) << "Error to delete value : " << (errmsg ? errmsg : "");
+ if (errmsg)
+ sqlite3_free(errmsg);
+ }
+}
+
+void SqliteDB::GetKeys(const std::string& section,
+ std::list<std::string>* keys) const {
+ char* buffer = NULL;
+ sqlite3_stmt* stmt = NULL;
+
+ int ret = 0;
+ buffer = sqlite3_mprintf("select key from appdb where section = %Q",
+ section.c_str());
+ if (buffer == NULL) {
+ LOGGER(ERROR) << "error to make query";
+ return;
+ }
+
+ std::unique_ptr<char, decltype(sqlite3_free)*> scoped_data{buffer,
+ sqlite3_free};
+
+ ret = sqlite3_prepare(sqldb_, buffer, strlen(buffer), &stmt, NULL);
+ if (ret != SQLITE_OK) {
+ LOGGER(ERROR) << "Fail to prepare query : " << sqlite3_errmsg(sqldb_);
+ return;
+ }
+
+ ret = sqlite3_step(stmt);
+ while (ret == SQLITE_ROW) {
+ const char* value =
+ reinterpret_cast<const char*>(sqlite3_column_text(stmt, 0));
+ keys->push_back(std::string(value));
+ ret = sqlite3_step(stmt);
+ }
+
+ sqlite3_finalize(stmt);
+ return;
+}
+
+AppDB* AppDB::GetInstance() {
+ static SqliteDB instance;
+ return &instance;
+}
+
+} // namespace common
--- /dev/null
+/*
+ * Copyright (c) 2015 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef XWALK_COMMON_APP_DB_H_
+#define XWALK_COMMON_APP_DB_H_
+
+#include <list>
+#include <string>
+
+namespace common {
+
+class AppDB {
+ public:
+ static AppDB* GetInstance();
+ virtual bool HasKey(const std::string& section,
+ const std::string& key) const = 0;
+ virtual std::string Get(const std::string& section,
+ const std::string& key) const = 0;
+ virtual void Set(const std::string& section,
+ const std::string& key,
+ const std::string& value) = 0;
+ virtual void GetKeys(const std::string& section,
+ std::list<std::string>* keys) const = 0;
+ virtual void Remove(const std::string& section, const std::string& key) = 0;
+};
+} // namespace common
+
+#endif // XWALK_COMMON_APP_DB_H_
--- /dev/null
+/*
+ * Copyright (c) 2015 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef XWALK_COMMON_APP_DB_SQLITE_H_
+#define XWALK_COMMON_APP_DB_SQLITE_H_
+
+#include <list>
+#include <string>
+
+#include "common/app_db.h"
+
+class sqlite3;
+
+namespace common {
+class SqliteDB : public AppDB {
+ public:
+ explicit SqliteDB(const std::string& app_data_path = std::string());
+ ~SqliteDB();
+ virtual bool HasKey(const std::string& section, const std::string& key) const;
+ virtual std::string Get(const std::string& section,
+ const std::string& key) const;
+ virtual void Set(const std::string& section,
+ const std::string& key,
+ const std::string& value);
+ virtual void GetKeys(const std::string& section,
+ std::list<std::string>* keys) const;
+ virtual void Remove(const std::string& section, const std::string& key);
+
+ private:
+ void Initialize();
+ void MigrationAppdb();
+ std::string app_data_path_;
+ sqlite3* sqldb_;
+};
+
+} // namespace common
+
+#endif // XWALK_COMMON_APP_DB_SQLITE_H_
--- /dev/null
+/*
+ * Copyright (c) 2015 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "common/application_data.h"
+
+#include <package_manager.h>
+#include <wgt_manifest_handlers/application_manifest_constants.h>
+#include <wgt_manifest_handlers/widget_config_parser.h>
+#include <app_manager.h>
+#include <app_common.h>
+
+#include <vector>
+
+#include "common/file_utils.h"
+#include "common/logger.h"
+#include "common/profiler.h"
+#include "common/platform_info.h"
+
+namespace common {
+
+namespace {
+
+const char* kPathSeparator = "/";
+const char* kConfigXml = "config.xml";
+const char* kWgtPath = "wgt";
+
+const char* kImeCategory = "http://tizen.org/category/ime";
+const char* kIdleClockCategory = "com.samsung.wmanager.WATCH_CLOCK";
+const char* kWearableClockCategory = "http://tizen.org/category/wearable_clock";
+
+} // namespace
+
+ApplicationData::ApplicationData(const std::string& appid)
+ : app_id_(appid), loaded_(false) {
+ SCOPE_PROFILE();
+ char* res_path = app_get_resource_path();
+ if (res_path != NULL) {
+ application_path_ = std::string(res_path) + kWgtPath + kPathSeparator;
+ free(res_path);
+ }
+}
+
+ApplicationData::~ApplicationData() {}
+
+std::shared_ptr<const wgt::parse::AppControlInfoList>
+ApplicationData::app_control_info_list() const {
+ return app_control_info_list_;
+}
+
+std::shared_ptr<const wgt::parse::CategoryInfoList>
+ApplicationData::category_info_list() const {
+ return category_info_list_;
+}
+
+std::shared_ptr<const wgt::parse::MetaDataInfo>
+ApplicationData::meta_data_info() const {
+ return meta_data_info_;
+}
+
+std::shared_ptr<const wgt::parse::AllowedNavigationInfo>
+ApplicationData::allowed_navigation_info() const {
+ return allowed_navigation_info_;
+}
+
+std::shared_ptr<const wgt::parse::PermissionsInfo>
+ApplicationData::permissions_info() const {
+ return permissions_info_;
+}
+
+std::shared_ptr<const wgt::parse::SettingInfo> ApplicationData::setting_info()
+ const {
+ return setting_info_;
+}
+
+std::shared_ptr<const wgt::parse::LaunchScreenInfo>
+ApplicationData::splash_screen_info() const {
+ return splash_screen_info_;
+}
+
+std::shared_ptr<const wgt::parse::TizenApplicationInfo>
+ApplicationData::tizen_application_info() const {
+ return tizen_application_info_;
+}
+
+std::shared_ptr<const wgt::parse::WidgetInfo> ApplicationData::widget_info()
+ const {
+ return widget_info_;
+}
+
+std::shared_ptr<const wgt::parse::ContentInfo> ApplicationData::content_info()
+ const {
+ return content_info_;
+}
+
+std::shared_ptr<const wgt::parse::WarpInfo> ApplicationData::warp_info() const {
+ return warp_info_;
+}
+
+std::shared_ptr<const wgt::parse::CSPInfo> ApplicationData::csp_info() const {
+ return csp_info_;
+}
+
+std::shared_ptr<const wgt::parse::CSPInfo> ApplicationData::csp_report_info()
+ const {
+ return csp_report_info_;
+}
+
+const std::string ApplicationData::pkg_id() const {
+ if (pkg_id_.empty()) {
+ app_info_h app_info;
+ int ret = app_info_create(app_id_.c_str(), &app_info);
+ if (ret == APP_MANAGER_ERROR_NONE) {
+ char* pkg = NULL;
+ ret = app_info_get_package(app_info, &pkg);
+ if (ret == APP_MANAGER_ERROR_NONE && pkg != NULL) {
+ pkg_id_ = pkg;
+ free(pkg);
+ }
+ app_info_destroy(app_info);
+ }
+ }
+ return pkg_id_;
+}
+
+ApplicationData::AppType ApplicationData::GetAppType() {
+ if (category_info_list_) {
+ auto category_list = category_info_list_->categories;
+ auto it = category_list.begin();
+ auto end = category_list.end();
+ for (; it != end; ++it) {
+ if (TIZEN_FEATURE_web_ime_support && *it == kImeCategory) {
+ return IME;
+ }
+ if (TIZEN_FEATURE_watch_face_support &&
+ (*it == kIdleClockCategory || *it == kWearableClockCategory)) {
+ return WATCH;
+ }
+ }
+ }
+ return UI;
+}
+
+bool ApplicationData::LoadManifestData() {
+ if (loaded_) {
+ return true;
+ }
+
+ SCOPE_PROFILE();
+
+ std::string config_xml_path(application_path_ + kConfigXml);
+ if (!utils::Exists(config_xml_path)) {
+ LOGGER(ERROR) << "Failed to load manifest data : No such file '"
+ << config_xml_path << "'.";
+ return false;
+ }
+
+ std::unique_ptr<wgt::parse::WidgetConfigParser> widget_config_parser;
+ widget_config_parser.reset(new wgt::parse::WidgetConfigParser());
+ if (!widget_config_parser->ParseManifest(config_xml_path)) {
+ LOGGER(ERROR) << "Failed to load widget config parser data: "
+ << widget_config_parser->GetErrorMessage();
+ return false;
+ }
+
+ app_control_info_list_ =
+ std::static_pointer_cast<const wgt::parse::AppControlInfoList>(
+ widget_config_parser->GetManifestData(
+ wgt::parse::AppControlInfo::Key()));
+
+ category_info_list_ =
+ std::static_pointer_cast<const wgt::parse::CategoryInfoList>(
+ widget_config_parser->GetManifestData(
+ wgt::parse::CategoryInfoList::Key()));
+
+ meta_data_info_ = std::static_pointer_cast<const wgt::parse::MetaDataInfo>(
+ widget_config_parser->GetManifestData(wgt::parse::MetaDataInfo::Key()));
+
+ allowed_navigation_info_ =
+ std::static_pointer_cast<const wgt::parse::AllowedNavigationInfo>(
+ widget_config_parser->GetManifestData(
+ wgt::parse::AllowedNavigationInfo::Key()));
+
+ permissions_info_ =
+ std::static_pointer_cast<const wgt::parse::PermissionsInfo>(
+ widget_config_parser->GetManifestData(
+ wgt::parse::PermissionsInfo::Key()));
+
+ setting_info_ = std::static_pointer_cast<const wgt::parse::SettingInfo>(
+ widget_config_parser->GetManifestData(wgt::parse::SettingInfo::Key()));
+
+ splash_screen_info_ =
+ std::static_pointer_cast<const wgt::parse::LaunchScreenInfo>(
+ widget_config_parser->GetManifestData(
+ wgt::parse::LaunchScreenInfo::Key()));
+
+ tizen_application_info_ =
+ std::static_pointer_cast<const wgt::parse::TizenApplicationInfo>(
+ widget_config_parser->GetManifestData(
+ wgt::parse::TizenApplicationInfo::Key()));
+
+ widget_info_ = std::static_pointer_cast<const wgt::parse::WidgetInfo>(
+ widget_config_parser->GetManifestData(wgt::parse::WidgetInfo::Key()));
+
+ content_info_ = std::static_pointer_cast<const wgt::parse::ContentInfo>(
+ widget_config_parser->GetManifestData(wgt::parse::ContentInfo::Key()));
+
+ warp_info_ = std::static_pointer_cast<const wgt::parse::WarpInfo>(
+ widget_config_parser->GetManifestData(wgt::parse::WarpInfo::Key()));
+
+ csp_info_ = std::static_pointer_cast<const wgt::parse::CSPInfo>(
+ widget_config_parser->GetManifestData(wgt::parse::CSPInfo::Key()));
+
+ csp_report_info_ = std::static_pointer_cast<const wgt::parse::CSPInfo>(
+ widget_config_parser->GetManifestData(
+ wgt::parse::CSPInfo::Report_only_key()));
+
+ // Set default empty object
+ if (widget_info_.get() == NULL) {
+ widget_info_.reset(new wgt::parse::WidgetInfo);
+ }
+ if (setting_info_.get() == NULL) {
+ setting_info_.reset(new wgt::parse::SettingInfo);
+ }
+
+ app_type_ = GetAppType();
+ loaded_ = true;
+
+ return true;
+}
+
+// static
+ApplicationDataManager* ApplicationDataManager::GetInstance() {
+ static ApplicationDataManager self;
+ return &self;
+}
+
+ApplicationDataManager::ApplicationDataManager() {}
+
+ApplicationDataManager::~ApplicationDataManager() {}
+
+ApplicationData* ApplicationDataManager::GetApplicationData(
+ const std::string& appid) {
+ auto it = cache_.find(appid);
+ if (it == cache_.end()) {
+ cache_[appid].reset(new ApplicationData(appid));
+ }
+ return cache_[appid].get();
+}
+
+} // namespace common
--- /dev/null
+/*
+ * Copyright (c) 2015 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef XWALK_COMMON_APPLICATION_DATA_H_
+#define XWALK_COMMON_APPLICATION_DATA_H_
+
+#include <wgt_manifest_handlers/application_icons_handler.h>
+#include <wgt_manifest_handlers/appwidget_handler.h>
+#include <wgt_manifest_handlers/app_control_handler.h>
+#include <wgt_manifest_handlers/category_handler.h>
+#include <wgt_manifest_handlers/content_handler.h>
+#include <wgt_manifest_handlers/csp_handler.h>
+#include <wgt_manifest_handlers/ime_handler.h>
+#include <wgt_manifest_handlers/launch_screen_handler.h>
+#include <wgt_manifest_handlers/metadata_handler.h>
+#include <wgt_manifest_handlers/navigation_handler.h>
+#include <wgt_manifest_handlers/permissions_handler.h>
+#include <wgt_manifest_handlers/service_handler.h>
+#include <wgt_manifest_handlers/setting_handler.h>
+#include <wgt_manifest_handlers/tizen_application_handler.h>
+#include <wgt_manifest_handlers/warp_handler.h>
+#include <wgt_manifest_handlers/widget_handler.h>
+
+#include <memory>
+#include <string>
+
+namespace common {
+
+class ApplicationData {
+ public:
+ enum AppType { UI = 0, IME, WATCH };
+
+ explicit ApplicationData(const std::string& appid);
+ ~ApplicationData();
+
+ bool LoadManifestData();
+
+ std::shared_ptr<const wgt::parse::AppControlInfoList> app_control_info_list()
+ const;
+ std::shared_ptr<const wgt::parse::CategoryInfoList> category_info_list()
+ const;
+ std::shared_ptr<const wgt::parse::MetaDataInfo> meta_data_info() const;
+ std::shared_ptr<const wgt::parse::AllowedNavigationInfo>
+ allowed_navigation_info() const;
+ std::shared_ptr<const wgt::parse::PermissionsInfo> permissions_info() const;
+ std::shared_ptr<const wgt::parse::SettingInfo> setting_info() const;
+ std::shared_ptr<const wgt::parse::LaunchScreenInfo> splash_screen_info()
+ const;
+ std::shared_ptr<const wgt::parse::TizenApplicationInfo>
+ tizen_application_info() const;
+ std::shared_ptr<const wgt::parse::WidgetInfo> widget_info() const;
+ std::shared_ptr<const wgt::parse::ContentInfo> content_info() const;
+ std::shared_ptr<const wgt::parse::WarpInfo> warp_info() const;
+ std::shared_ptr<const wgt::parse::CSPInfo> csp_info() const;
+ std::shared_ptr<const wgt::parse::CSPInfo> csp_report_info() const;
+
+ const std::string application_path() const { return application_path_; }
+ const std::string pkg_id() const;
+ const std::string app_id() const { return app_id_; }
+ ApplicationData::AppType app_type() { return app_type_; }
+
+ private:
+ std::shared_ptr<const wgt::parse::AppControlInfoList> app_control_info_list_;
+ std::shared_ptr<const wgt::parse::CategoryInfoList> category_info_list_;
+ std::shared_ptr<const wgt::parse::MetaDataInfo> meta_data_info_;
+ std::shared_ptr<const wgt::parse::AllowedNavigationInfo>
+ allowed_navigation_info_;
+ std::shared_ptr<const wgt::parse::PermissionsInfo> permissions_info_;
+ std::shared_ptr<const wgt::parse::SettingInfo> setting_info_;
+ std::shared_ptr<const wgt::parse::LaunchScreenInfo> splash_screen_info_;
+ std::shared_ptr<const wgt::parse::TizenApplicationInfo>
+ tizen_application_info_;
+ std::shared_ptr<const wgt::parse::WidgetInfo> widget_info_;
+ std::shared_ptr<const wgt::parse::ContentInfo> content_info_;
+ std::shared_ptr<const wgt::parse::WarpInfo> warp_info_;
+ std::shared_ptr<const wgt::parse::CSPInfo> csp_info_;
+ std::shared_ptr<const wgt::parse::CSPInfo> csp_report_info_;
+ ApplicationData::AppType GetAppType();
+
+ std::string application_path_;
+ mutable std::string pkg_id_;
+ std::string app_id_;
+ ApplicationData::AppType app_type_;
+ bool loaded_;
+};
+
+class ApplicationDataManager {
+ public:
+ static ApplicationDataManager* GetInstance();
+
+ ApplicationData* GetApplicationData(const std::string& appid);
+
+ private:
+ ApplicationDataManager();
+ virtual ~ApplicationDataManager();
+
+ std::map<std::string, std::unique_ptr<ApplicationData>> cache_;
+};
+
+} // namespace common
+
+#endif // XWALK_COMMON_APPLICATION_DATA_H_
--- /dev/null
+/*
+ * Copyright (c) 2016 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef XWALK_COMMON_ARRAYSIZE_H_
+#define XWALK_COMMON_ARRAYSIZE_H_
+
+// The ARRAYSIZE(arr) macro returns the # of elements in an array arr.
+// The expression is a compile-time constant, and therefore can be
+// used in defining new arrays, for example. If you use arraysize on
+// a pointer by mistake, you will get a compile-time error.
+//
+// One caveat is that ARRAYSIZE() doesn't accept any array of an
+// anonymous type or a type defined inside a function. In these rare
+// cases, you have to use the unsafe ARRAYSIZE_UNSAFE() macro below. This is
+// due to a limitation in C++'s template system. The limitation might
+// eventually be removed, but it hasn't happened yet.
+
+// This template function declaration is used in defining arraysize.
+// Note that the function doesn't need an implementation, as we only
+// use its type.
+template <typename T, size_t N>
+char (&ArraySizeHelper(T (&array)[N]))[N];
+
+#define ARRAYSIZE(array) (sizeof(ArraySizeHelper(array)))
+
+#endif // XWALK_COMMON_ARRAYSIZE_H_
--- /dev/null
+/*
+ * Copyright (c) 2015 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "common/command_line.h"
+
+#include <cstring>
+
+#include "common/file_utils.h"
+
+namespace common {
+
+namespace {
+
+const char* kOptionPrefix = "--";
+const char* kOptionValueSeparator = "=";
+
+static bool IsValidOptionString(const char* argument) {
+ if (NULL != argument &&
+ strncmp(argument, kOptionPrefix, strlen(kOptionPrefix)) == 0) {
+ return true;
+ } else {
+ return false;
+ }
+}
+
+} // namespace
+
+CommandLine* CommandLine::current_process_commandline_ = NULL;
+
+CommandLine::CommandLine(int argc, char* argv[]) : argc_(argc), argv_(argv) {
+ // Append option or push each arg(not option) into arguments_
+ for (int i = 1; i < argc; ++i) {
+ if (IsValidOptionString(argv[i])) {
+ AppendOption(argv[i]);
+ } else {
+ arguments_.push_back(argv[i]);
+ }
+ }
+
+ // Parse program name and appid from argv_ or arguments_
+ program_ = std::string(argv[0]);
+}
+
+CommandLine::~CommandLine() {}
+
+void CommandLine::AppendOption(const char* value) {
+ std::string option_string(value);
+ std::string option_name;
+ std::string option_value;
+
+ int value_separator_pos =
+ option_string.find(kOptionValueSeparator, strlen(kOptionPrefix));
+ if (value_separator_pos >= 0) {
+ int substr_len = value_separator_pos - strlen(kOptionPrefix);
+ option_name = option_string.substr(strlen(kOptionPrefix), substr_len);
+ option_value = option_string.substr(value_separator_pos + 1);
+ } else {
+ option_name =
+ option_string.substr(strlen(kOptionPrefix), value_separator_pos);
+ }
+
+ options_[option_name] = option_value;
+}
+
+bool CommandLine::HasOptionName(const std::string& option_name) {
+ return (options_.find(option_name) != options_.end());
+}
+
+std::string CommandLine::GetOptionValue(const std::string& option_name) {
+ if (HasOptionName(option_name)) {
+ return options_[option_name];
+ } else {
+ return std::string();
+ }
+}
+
+std::string CommandLine::GetCommandString() {
+ std::string result;
+ result.append(program_);
+ result.append(" ");
+ for (auto& it : options_) {
+ result.append(kOptionPrefix);
+ result.append(it.first);
+ if (!it.second.empty()) {
+ result.append(kOptionValueSeparator);
+ result.append(it.second);
+ }
+ result.append(" ");
+ }
+ for (auto& it : arguments_) {
+ result.append(it);
+ result.append(" ");
+ }
+ return result;
+}
+
+std::string CommandLine::GetAppIdFromCommandLine(const std::string& program) {
+ if (argc_ > 0) {
+ std::string tmp = utils::BaseName(program_);
+ if (tmp == program) {
+ if (arguments_.size() > 0) {
+ // Suppose that appid is at the first of arguments_
+ return arguments_[0];
+ }
+ } else {
+ return tmp;
+ }
+ }
+ return std::string();
+}
+
+// static
+void CommandLine::Reset() {
+ if (!!current_process_commandline_) {
+ delete current_process_commandline_;
+ current_process_commandline_ = NULL;
+ }
+}
+
+// static
+void CommandLine::Init(int argc, char* argv[]) {
+ if (!current_process_commandline_) {
+ current_process_commandline_ = new CommandLine(argc, argv);
+ }
+}
+
+// static
+CommandLine* CommandLine::ForCurrentProcess() {
+ return current_process_commandline_;
+}
+
+} // namespace common
--- /dev/null
+/*
+ * Copyright (c) 2015 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef XWALK_COMMON_COMMAND_LINE_H_
+#define XWALK_COMMON_COMMAND_LINE_H_
+
+#include <map>
+#include <string>
+#include <vector>
+
+namespace common {
+
+class CommandLine {
+ public:
+ // CommandLine only uses long options
+ typedef std::map<std::string, std::string> OptionMap;
+ // Arguments which except for option strings
+ typedef std::vector<std::string> Arguments;
+
+ static void Init(int argc, char* argv[]);
+ static CommandLine* ForCurrentProcess();
+ static void Reset();
+
+ // Test if options_ has 'option_name'
+ bool HasOptionName(const std::string& option_name);
+ // Get the option's value
+ std::string GetOptionValue(const std::string& option_name);
+ // Get command string include options and arguments
+ std::string GetCommandString();
+
+ std::string GetAppIdFromCommandLine(const std::string& program);
+
+ std::string program() const { return program_; }
+ const OptionMap& options() const { return options_; }
+ const Arguments& arguments() const { return arguments_; }
+ char** argv() const { return argv_; }
+ int argc() const { return argc_; }
+
+ private:
+ CommandLine(int argc, char* argv[]);
+ virtual ~CommandLine();
+
+ void AppendOption(const char* value);
+
+ // The singleton CommandLine instance of current process
+ static CommandLine* current_process_commandline_;
+
+ std::string program_;
+ OptionMap options_;
+ Arguments arguments_;
+ int argc_;
+ char** argv_;
+};
+
+} // namespace common
+
+#endif // XWALK_COMMON_COMMAND_LINE_H_
--- /dev/null
+{
+ 'includes':[
+ '../build/common.gypi',
+ ],
+ 'targets': [
+ {
+ 'target_name': 'xwalk_tizen_common',
+ 'type': 'shared_library',
+ 'sources': [
+ 'command_line.h',
+ 'command_line.cc',
+ 'file_utils.h',
+ 'file_utils.cc',
+ 'string_utils.h',
+ 'string_utils.cc',
+ 'logger.h',
+ 'picojson.h',
+ 'profiler.h',
+ 'profiler.cc',
+ 'url.h',
+ 'url.cc',
+ 'app_control.h',
+ 'app_control.cc',
+ 'app_db.h',
+ 'app_db.cc',
+ 'app_db_sqlite.h',
+ 'application_data.h',
+ 'application_data.cc',
+ 'locale_manager.h',
+ 'locale_manager.cc',
+ 'resource_manager.h',
+ 'resource_manager.cc',
+ 'platform_info.h',
+ 'platform_info.cc',
+ ],
+ 'cflags': [
+ '-fvisibility=default',
+ ],
+ 'variables': {
+ 'packages': [
+ 'appsvc',
+ 'aul',
+ 'capi-appfw-application',
+ 'capi-appfw-app-manager',
+ 'capi-appfw-package-manager',
+ 'capi-system-system-settings',
+ 'capi-system-info',
+ 'cynara-client',
+ 'dlog',
+ 'uuid',
+ 'libwebappenc',
+ 'manifest-parser',
+ 'wgt-manifest-handlers',
+ 'pkgmgr-info',
+ 'glib-2.0',
+ 'ttrace',
+ ],
+ },
+# 'conditions': [
+# ['tizen_feature_web_ime_support == 1', {
+# 'defines': ['IME_FEATURE_SUPPORT'],
+# }],
+# ['tizen_feature_watch_face_support == 1', {
+# 'defines': ['WATCH_FACE_FEATURE_SUPPORT'],
+# }],
+# ],
+ 'direct_dependent_settings': {
+# 'libraries': [
+# '-lxwalk_tizen_common',
+# ],
+ 'variables': {
+ 'packages': [
+ 'dlog',
+ ],
+ },
+ },
+ },
+ ],
+}
--- /dev/null
+/*
+ * Copyright (c) 2015 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "common/file_utils.h"
+
+#include <sys/types.h>
+#include <libgen.h>
+#include <unistd.h>
+
+#include <algorithm>
+#include <sstream>
+#include <string>
+
+namespace common {
+namespace utils {
+
+bool Exists(const std::string& path) {
+ return (access(path.c_str(), F_OK) != -1);
+}
+
+std::string BaseName(const std::string& path) {
+ char* p = basename(const_cast<char*>(path.c_str()));
+ return std::string(p);
+}
+
+std::string DirName(const std::string& path) {
+ char* p = dirname(const_cast<char*>(path.c_str()));
+ return std::string(p);
+}
+
+std::string SchemeName(const std::string& uri) {
+ size_t pos = uri.find(":");
+ if (pos != std::string::npos && pos < uri.length()) {
+ return std::string(uri.substr(0, pos));
+ } else {
+ return uri;
+ }
+}
+
+std::string ExtName(const std::string& path) {
+ size_t last_dot = path.find_last_of(".");
+ if (last_dot != 0 && last_dot != std::string::npos) {
+ std::string ext = path.substr(last_dot);
+ size_t end_of_ext = ext.find_first_of("?#");
+ if (end_of_ext != std::string::npos)
+ ext = ext.substr(0, end_of_ext);
+ std::transform(ext.begin(), ext.end(), ext.begin(), ::tolower);
+ return ext;
+ } else {
+ return std::string();
+ }
+}
+
+std::string GetUserRuntimeDir() {
+ uid_t uid = getuid();
+ std::stringstream ss;
+ ss << "/run/user/" << uid;
+ std::string path = ss.str();
+ if (!Exists(path)) {
+ path = "/tmp";
+ }
+ return path;
+}
+
+} // namespace utils
+} // namespace common
--- /dev/null
+/*
+ * Copyright (c) 2015 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef XWALK_COMMON_FILE_UTILS_H_
+#define XWALK_COMMON_FILE_UTILS_H_
+
+#include <string>
+
+namespace common {
+namespace utils {
+
+bool Exists(const std::string& path);
+
+std::string BaseName(const std::string& path);
+
+std::string DirName(const std::string& path);
+
+std::string SchemeName(const std::string& uri);
+
+std::string ExtName(const std::string& path);
+
+std::string GetUserRuntimeDir();
+
+} // namespace utils
+} // namespace common
+
+#endif // XWALK_COMMON_FILE_UTILS_H_
--- /dev/null
+/*
+ * Copyright (c) 2015 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "common/locale_manager.h"
+
+#include <system_settings.h>
+
+#include <algorithm>
+#include <memory>
+
+#include "common/file_utils.h"
+#include "common/logger.h"
+
+namespace common {
+
+namespace {
+
+std::string localeToBCP47LangTag(const std::string locale) {
+ // Cut off codepage information from given string (if any exists)
+ // i.e. change en_US.UTF-8 into en_US */
+ std::string lang = locale.substr(0, locale.find_first_of("."));
+
+ // Replace all '_' with '-'
+ std::replace(lang.begin(), lang.end(), '_', '-');
+ return lang;
+}
+
+} // namespace
+
+LocaleManager::LocaleManager() {
+ UpdateSystemLocale();
+}
+
+LocaleManager::~LocaleManager() {
+ system_settings_unset_changed_cb(SYSTEM_SETTINGS_KEY_LOCALE_LANGUAGE);
+}
+
+void LocaleManager::EnableAutoUpdate(bool enable) {
+ if (enable) {
+ auto callback = [](system_settings_key_e, void* user_data) {
+ LocaleManager* locale = static_cast<LocaleManager*>(user_data);
+ locale->UpdateSystemLocale();
+ };
+ system_settings_set_changed_cb(SYSTEM_SETTINGS_KEY_LOCALE_LANGUAGE,
+ callback, this);
+ } else {
+ system_settings_unset_changed_cb(SYSTEM_SETTINGS_KEY_LOCALE_LANGUAGE);
+ }
+}
+
+void LocaleManager::SetDefaultLocale(const std::string& locale) {
+ if (!default_locale_.empty() && system_locales_.size() > 0 &&
+ system_locales_.back() == default_locale_) {
+ system_locales_.pop_back();
+ }
+ default_locale_ = locale;
+ if (!default_locale_.empty()) {
+ system_locales_.push_back(locale);
+ }
+}
+
+void LocaleManager::UpdateSystemLocale() {
+ char* str = NULL;
+ if (SYSTEM_SETTINGS_ERROR_NONE !=
+ system_settings_get_value_string(SYSTEM_SETTINGS_KEY_LOCALE_LANGUAGE,
+ &str) ||
+ str == NULL) {
+ return;
+ }
+ std::string lang = localeToBCP47LangTag(str);
+ free(str);
+
+ if (lang.length() == 0) {
+ LOGGER(ERROR) << "Language tag was invalid";
+ return;
+ }
+
+ system_locales_.clear();
+ while (true) {
+ LOGGER(DEBUG) << "Processing language description: " << lang;
+ system_locales_.push_back(lang);
+
+ // compatibility with lower language Tag by SDK
+ std::string lower = lang;
+ std::transform(lower.begin(), lower.end(), lower.begin(), ::tolower);
+ if (lower != lang) {
+ system_locales_.push_back(lower);
+ }
+ size_t position = lang.find_last_of("-");
+ if (position == std::string::npos) {
+ break;
+ }
+ lang = lang.substr(0, position);
+ }
+ if (!default_locale_.empty()) {
+ system_locales_.push_back(default_locale_);
+ }
+}
+
+std::string LocaleManager::GetLocalizedString(const StringMap& strmap) {
+ if (strmap.empty()) {
+ return std::string();
+ }
+
+ // find string with system locales
+ for (auto& locale : system_locales_) {
+ auto it = strmap.find(locale);
+ if (it != strmap.end()) {
+ return it->second;
+ }
+ }
+
+ // find string with empty locale
+ auto it = strmap.find("");
+ if (it != strmap.end()) {
+ return it->second;
+ }
+
+ // If localized string is not found, return first string.
+ return strmap.begin()->second;
+}
+
+} // namespace common
--- /dev/null
+/*
+ * Copyright (c) 2015 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef XWALK_COMMON_LOCALE_MANAGER_H_
+#define XWALK_COMMON_LOCALE_MANAGER_H_
+
+#include <list>
+#include <map>
+#include <string>
+
+namespace common {
+
+class LocaleManager {
+ public:
+ typedef std::map<std::string, std::string> StringMap;
+
+ LocaleManager();
+ virtual ~LocaleManager();
+ void SetDefaultLocale(const std::string& locale);
+ void EnableAutoUpdate(bool enable);
+ void UpdateSystemLocale();
+ const std::list<std::string>& system_locales() const {
+ return system_locales_;
+ }
+
+ std::string GetLocalizedString(const StringMap& strmap);
+
+ private:
+ std::string default_locale_;
+ std::list<std::string> system_locales_;
+};
+
+} // namespace common
+
+#endif // XWALK_COMMON_LOCALE_MANAGER_H_
--- /dev/null
+/*
+ * Copyright (c) 2015 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef XWALK_COMMON_LOGGER_H_
+#define XWALK_COMMON_LOGGER_H_
+
+#include <dlog.h>
+#include <sstream>
+
+#undef LOGGER_TAG
+#define LOGGER_TAG "ELECTRON"
+
+#define _LOGGER_LOG(prio, fmt, args...) \
+ LOG_(LOG_ID_MAIN, prio, LOGGER_TAG, fmt, ##args)
+
+#define _LOGGER_SLOG(prio, fmt, args...) \
+ SECURE_LOG_(LOG_ID_MAIN, prio, LOGGER_TAG, fmt, ##args)
+
+#define LoggerD(fmt, args...) _LOGGER_LOG(DLOG_DEBUG, fmt, ##args)
+#define LoggerI(fmt, args...) _LOGGER_LOG(DLOG_INFO, fmt, ##args)
+#define LoggerW(fmt, args...) _LOGGER_LOG(DLOG_WARN, fmt, ##args)
+#define LoggerE(fmt, args...) _LOGGER_LOG(DLOG_ERROR, fmt, ##args)
+
+#define SLoggerD(fmt, args...) _LOGGER_SLOG(DLOG_DEBUG, fmt, ##args)
+#define SLoggerI(fmt, args...) _LOGGER_SLOG(DLOG_INFO, fmt, ##args)
+#define SLoggerW(fmt, args...) _LOGGER_SLOG(DLOG_WARN, fmt, ##args)
+#define SLoggerE(fmt, args...) _LOGGER_SLOG(DLOG_ERROR, fmt, ##args)
+
+namespace common {
+namespace utils {
+
+class LogMessageVodify {
+ public:
+ LogMessageVodify() {}
+ void operator&(const std::ostream&)const {}
+};
+
+class LogMessage {
+ public:
+ LogMessage(int severity,
+ const char* tag,
+ const char* file,
+ const char* func,
+ const int line)
+ : severity_(severity), tag_(tag), file_(file), func_(func), line_(line) {}
+ LogMessage(int severity, const char* tag)
+ : severity_(severity), tag_(tag), file_(NULL), func_(NULL), line_(0) {}
+ ~LogMessage() {
+ if (file_) {
+ __dlog_print(LOG_ID_MAIN, severity_, tag_, "%s: %s(%d) > %s", file_,
+ func_, line_, stream_.str().c_str());
+ } else {
+ __dlog_print(LOG_ID_MAIN, severity_, tag_, "%s", stream_.str().c_str());
+ }
+ }
+ std::ostream& stream() { return stream_; }
+
+ private:
+ const int severity_;
+ const char* tag_;
+ const char* file_;
+ const char* func_;
+ const int line_;
+ std::ostringstream stream_;
+};
+
+} // namespace utils
+} // namespace common
+
+#ifndef __MODULE__
+#define __MODULE__ \
+ (strrchr(__FILE__, '/') ? strrchr(__FILE__, '/') + 1 : __FILE__)
+#endif
+
+#define LOGGER(severity) \
+ common::utils::LogMessageVodify() & \
+ common::utils::LogMessage(DLOG_##severity, LOGGER_TAG, __MODULE__, \
+ __FUNCTION__, __LINE__) \
+ .stream()
+
+#define LOGGER_RAW(level, tag) \
+ common::utils::LogMessageVodify() & \
+ common::utils::LogMessage(level, tag).stream()
+
+#endif // XWALK_COMMON_LOGGER_H_
--- /dev/null
+/*
+ * Copyright 2009-2010 Cybozu Labs, Inc.
+ * Copyright 2011 Kazuho Oku
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY CYBOZU LABS, INC. ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
+ * EVENT SHALL CYBOZU LABS, INC. OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
+ * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * The views and conclusions contained in the software and documentation are
+ * those of the authors and should not be interpreted as representing official
+ * policies, either expressed or implied, of Cybozu Labs, Inc.
+ *
+ */
+#ifndef picojson_h
+#define picojson_h
+
+#include <algorithm>
+#include <cassert>
+#include <cmath>
+#include <cstdio>
+#include <cstdlib>
+#include <cstring>
+#include <iostream>
+#include <iterator>
+#include <map>
+#include <string>
+#include <vector>
+
+#ifdef _MSC_VER
+#define SNPRINTF _snprintf_s
+#pragma warning(push)
+#pragma warning(disable : 4244) // conversion from int to char
+#else
+#define SNPRINTF snprintf
+#endif
+
+namespace picojson {
+
+enum {
+ null_type,
+ boolean_type,
+ number_type,
+ string_type,
+ array_type,
+ object_type
+};
+
+struct null {};
+
+class value {
+ public:
+ typedef std::vector<value> array;
+ typedef std::map<std::string, value> object;
+ union _storage {
+ bool boolean_;
+ double number_;
+ std::string* string_;
+ array* array_;
+ object* object_;
+ };
+
+ protected:
+ int type_;
+ _storage u_;
+
+ public:
+ value();
+ value(int type, bool);
+ explicit value(bool b);
+ explicit value(double n);
+ explicit value(const std::string& s);
+ explicit value(const array& a);
+ explicit value(const object& o);
+ explicit value(const char* s);
+ value(const char* s, size_t len);
+ ~value();
+ value(const value& x);
+ value& operator=(const value& x);
+ void swap(value& x);
+ template <typename T>
+ bool is() const;
+ template <typename T>
+ const T& get() const;
+ template <typename T>
+ T& get();
+ bool evaluate_as_boolean() const;
+ const value& get(size_t idx) const;
+ const value& get(const std::string& key) const;
+ bool contains(size_t idx) const;
+ bool contains(const std::string& key) const;
+ std::string to_str() const;
+ template <typename Iter>
+ void serialize(Iter os) const;
+ std::string serialize() const;
+
+ private:
+ template <typename T>
+ value(const T*); // intentionally defined to block implicit conversion of
+ // pointer to bool
+};
+
+typedef value::array array;
+typedef value::object object;
+
+inline value::value() : type_(null_type) {}
+
+inline value::value(int type, bool) : type_(type) {
+ switch (type) {
+#define INIT(p, v) \
+ case p##type: \
+ u_.p = v; \
+ break
+ INIT(boolean_, false);
+ INIT(number_, 0.0);
+ INIT(string_, new std::string());
+ INIT(array_, new array());
+ INIT(object_, new object());
+#undef INIT
+ default:
+ break;
+ }
+}
+
+inline value::value(bool b) : type_(boolean_type) {
+ u_.boolean_ = b;
+}
+
+inline value::value(double n) : type_(number_type) {
+ u_.number_ = n;
+}
+
+inline value::value(const std::string& s) : type_(string_type) {
+ u_.string_ = new std::string(s);
+}
+
+inline value::value(const array& a) : type_(array_type) {
+ u_.array_ = new array(a);
+}
+
+inline value::value(const object& o) : type_(object_type) {
+ u_.object_ = new object(o);
+}
+
+inline value::value(const char* s) : type_(string_type) {
+ u_.string_ = new std::string(s);
+}
+
+inline value::value(const char* s, size_t len) : type_(string_type) {
+ u_.string_ = new std::string(s, len);
+}
+
+inline value::~value() {
+ switch (type_) {
+#define DEINIT(p) \
+ case p##type: \
+ delete u_.p; \
+ break
+ DEINIT(string_);
+ DEINIT(array_);
+ DEINIT(object_);
+#undef DEINIT
+ default:
+ break;
+ }
+}
+
+inline value::value(const value& x) : type_(x.type_) {
+ switch (type_) {
+#define INIT(p, v) \
+ case p##type: \
+ u_.p = v; \
+ break
+ INIT(string_, new std::string(*x.u_.string_));
+ INIT(array_, new array(*x.u_.array_));
+ INIT(object_, new object(*x.u_.object_));
+#undef INIT
+ default:
+ u_ = x.u_;
+ break;
+ }
+}
+
+inline value& value::operator=(const value& x) {
+ if (this != &x) {
+ this->~value();
+ new (this) value(x);
+ }
+ return *this;
+}
+
+inline void value::swap(value& x) {
+ std::swap(type_, x.type_);
+ std::swap(u_, x.u_);
+}
+
+#define IS(ctype, jtype) \
+ template <> \
+ inline bool value::is<ctype>() const { \
+ return type_ == jtype##_type; \
+ }
+IS(null, null)
+IS(bool, boolean)
+IS(int, number)
+IS(double, number)
+IS(std::string, string)
+IS(array, array)
+IS(object, object)
+#undef IS
+
+#define GET(ctype, var) \
+ template <> \
+ inline const ctype& value::get<ctype>() const { \
+ assert("type mismatch! call vis<type>() before get<type>()" && \
+ is<ctype>()); \
+ return var; \
+ } \
+ template <> \
+ inline ctype& value::get<ctype>() { \
+ assert("type mismatch! call is<type>() before get<type>()" && \
+ is<ctype>()); \
+ return var; \
+ }
+GET(bool, u_.boolean_)
+GET(double, u_.number_)
+GET(std::string, *u_.string_)
+GET(array, *u_.array_)
+GET(object, *u_.object_)
+#undef GET
+
+inline bool value::evaluate_as_boolean() const {
+ switch (type_) {
+ case null_type:
+ return false;
+ case boolean_type:
+ return u_.boolean_;
+ case number_type:
+ return u_.number_ != 0;
+ case string_type:
+ return !u_.string_->empty();
+ default:
+ return true;
+ }
+}
+
+inline const value& value::get(size_t idx) const {
+ static value s_null;
+ assert(is<array>());
+ return idx < u_.array_->size() ? (*u_.array_)[idx] : s_null;
+}
+
+inline const value& value::get(const std::string& key) const {
+ static value s_null;
+ assert(is<object>());
+ object::const_iterator i = u_.object_->find(key);
+ return i != u_.object_->end() ? i->second : s_null;
+}
+
+inline bool value::contains(size_t idx) const {
+ assert(is<array>());
+ return idx < u_.array_->size();
+}
+
+inline bool value::contains(const std::string& key) const {
+ assert(is<object>());
+ object::const_iterator i = u_.object_->find(key);
+ return i != u_.object_->end();
+}
+
+inline std::string value::to_str() const {
+ switch (type_) {
+ case null_type:
+ return "null";
+ case boolean_type:
+ return u_.boolean_ ? "true" : "false";
+ case number_type: {
+ char buf[256];
+ double tmp;
+ SNPRINTF(buf, sizeof(buf),
+ fabs(u_.number_) < (1ULL << 53) && modf(u_.number_, &tmp) == 0
+ ? "%.f"
+ : "%.17g",
+ u_.number_);
+ return buf;
+ }
+ case string_type:
+ return *u_.string_;
+ case array_type:
+ return "array";
+ case object_type:
+ return "object";
+ default:
+ assert(0);
+#ifdef _MSC_VER
+ __assume(0);
+#endif
+ }
+ return std::string();
+}
+
+template <typename Iter>
+void copy(const std::string& s, Iter oi) {
+ std::copy(s.begin(), s.end(), oi);
+}
+
+template <typename Iter>
+void serialize_str(const std::string& s, Iter oi) {
+ *oi++ = '"';
+ for (std::string::const_iterator i = s.begin(); i != s.end(); ++i) {
+ switch (*i) {
+#define MAP(val, sym) \
+ case val: \
+ copy(sym, oi); \
+ break
+ MAP('"', "\\\"");
+ MAP('\\', "\\\\");
+ MAP('/', "\\/");
+ MAP('\b', "\\b");
+ MAP('\f', "\\f");
+ MAP('\n', "\\n");
+ MAP('\r', "\\r");
+ MAP('\t', "\\t");
+#undef MAP
+ default:
+ if ((unsigned char)*i < 0x20 || *i == 0x7f) {
+ char buf[7];
+ SNPRINTF(buf, sizeof(buf), "\\u%04x", *i & 0xff);
+ copy(buf, buf + 6, oi);
+ } else {
+ *oi++ = *i;
+ }
+ break;
+ }
+ }
+ *oi++ = '"';
+}
+
+template <typename Iter>
+void value::serialize(Iter oi) const {
+ switch (type_) {
+ case string_type:
+ serialize_str(*u_.string_, oi);
+ break;
+ case array_type: {
+ *oi++ = '[';
+ for (array::const_iterator i = u_.array_->begin(); i != u_.array_->end();
+ ++i) {
+ if (i != u_.array_->begin()) {
+ *oi++ = ',';
+ }
+ i->serialize(oi);
+ }
+ *oi++ = ']';
+ break;
+ }
+ case object_type: {
+ *oi++ = '{';
+ for (object::const_iterator i = u_.object_->begin();
+ i != u_.object_->end(); ++i) {
+ if (i != u_.object_->begin()) {
+ *oi++ = ',';
+ }
+ serialize_str(i->first, oi);
+ *oi++ = ':';
+ i->second.serialize(oi);
+ }
+ *oi++ = '}';
+ break;
+ }
+ default:
+ copy(to_str(), oi);
+ break;
+ }
+}
+
+inline std::string value::serialize() const {
+ std::string s;
+ serialize(std::back_inserter(s));
+ return s;
+}
+
+template <typename Iter>
+class input {
+ protected:
+ Iter cur_, end_;
+ int last_ch_;
+ bool ungot_;
+ int line_;
+
+ public:
+ input(const Iter& first, const Iter& last)
+ : cur_(first), end_(last), last_ch_(-1), ungot_(false), line_(1) {}
+ int getc() {
+ if (ungot_) {
+ ungot_ = false;
+ return last_ch_;
+ }
+ if (cur_ == end_) {
+ last_ch_ = -1;
+ return -1;
+ }
+ if (last_ch_ == '\n') {
+ line_++;
+ }
+ last_ch_ = *cur_++ & 0xff;
+ return last_ch_;
+ }
+ void ungetc() {
+ if (last_ch_ != -1) {
+ assert(!ungot_);
+ ungot_ = true;
+ }
+ }
+ Iter cur() const { return cur_; }
+ int line() const { return line_; }
+ void skip_ws() {
+ while (1) {
+ int ch = getc();
+ if (!(ch == ' ' || ch == '\t' || ch == '\n' || ch == '\r')) {
+ ungetc();
+ break;
+ }
+ }
+ }
+ bool expect(int expect) {
+ skip_ws();
+ if (getc() != expect) {
+ ungetc();
+ return false;
+ }
+ return true;
+ }
+ bool match(const std::string& pattern) {
+ for (std::string::const_iterator pi(pattern.begin()); pi != pattern.end();
+ ++pi) {
+ if (getc() != *pi) {
+ ungetc();
+ return false;
+ }
+ }
+ return true;
+ }
+};
+
+template <typename Iter>
+inline int _parse_quadhex(input<Iter>& in) {
+ int uni_ch = 0, hex;
+ for (int i = 0; i < 4; i++) {
+ if ((hex = in.getc()) == -1) {
+ return -1;
+ }
+ if ('0' <= hex && hex <= '9') {
+ hex -= '0';
+ } else if ('A' <= hex && hex <= 'F') {
+ hex -= 'A' - 0xa;
+ } else if ('a' <= hex && hex <= 'f') {
+ hex -= 'a' - 0xa;
+ } else {
+ in.ungetc();
+ return -1;
+ }
+ uni_ch = uni_ch * 16 + hex;
+ }
+ return uni_ch;
+}
+
+template <typename String, typename Iter>
+inline bool _parse_codepoint(String& out, input<Iter>& in) {
+ int uni_ch;
+ if ((uni_ch = _parse_quadhex(in)) == -1) {
+ return false;
+ }
+ if (0xd800 <= uni_ch && uni_ch <= 0xdfff) {
+ if (0xdc00 <= uni_ch) {
+ // a second 16-bit of a surrogate pair appeared
+ return false;
+ }
+ // first 16-bit of surrogate pair, get the next one
+ if (in.getc() != '\\' || in.getc() != 'u') {
+ in.ungetc();
+ return false;
+ }
+ int second = _parse_quadhex(in);
+ if (!(0xdc00 <= second && second <= 0xdfff)) {
+ return false;
+ }
+ uni_ch = ((uni_ch - 0xd800) << 10) | ((second - 0xdc00) & 0x3ff);
+ uni_ch += 0x10000;
+ }
+ if (uni_ch < 0x80) {
+ out.push_back(uni_ch);
+ } else {
+ if (uni_ch < 0x800) {
+ out.push_back(0xc0 | (uni_ch >> 6));
+ } else {
+ if (uni_ch < 0x10000) {
+ out.push_back(0xe0 | (uni_ch >> 12));
+ } else {
+ out.push_back(0xf0 | (uni_ch >> 18));
+ out.push_back(0x80 | ((uni_ch >> 12) & 0x3f));
+ }
+ out.push_back(0x80 | ((uni_ch >> 6) & 0x3f));
+ }
+ out.push_back(0x80 | (uni_ch & 0x3f));
+ }
+ return true;
+}
+
+template <typename String, typename Iter>
+inline bool _parse_string(String& out, input<Iter>& in) {
+ while (1) {
+ int ch = in.getc();
+ if (ch < ' ') {
+ in.ungetc();
+ return false;
+ } else if (ch == '"') {
+ return true;
+ } else if (ch == '\\') {
+ if ((ch = in.getc()) == -1) {
+ return false;
+ }
+ switch (ch) {
+#define MAP(sym, val) \
+ case sym: \
+ out.push_back(val); \
+ break
+ MAP('"', '\"');
+ MAP('\\', '\\');
+ MAP('/', '/');
+ MAP('b', '\b');
+ MAP('f', '\f');
+ MAP('n', '\n');
+ MAP('r', '\r');
+ MAP('t', '\t');
+#undef MAP
+ case 'u':
+ if (!_parse_codepoint(out, in)) {
+ return false;
+ }
+ break;
+ default:
+ return false;
+ }
+ } else {
+ out.push_back(ch);
+ }
+ }
+ return false;
+}
+
+template <typename Context, typename Iter>
+inline bool _parse_array(Context& ctx, input<Iter>& in) {
+ if (!ctx.parse_array_start()) {
+ return false;
+ }
+ if (in.expect(']')) {
+ return true;
+ }
+ size_t idx = 0;
+ do {
+ if (!ctx.parse_array_item(in, idx)) {
+ return false;
+ }
+ idx++;
+ } while (in.expect(','));
+ return in.expect(']');
+}
+
+template <typename Context, typename Iter>
+inline bool _parse_object(Context& ctx, input<Iter>& in) {
+ if (!ctx.parse_object_start()) {
+ return false;
+ }
+ if (in.expect('}')) {
+ return true;
+ }
+ do {
+ std::string key;
+ if (!in.expect('"') || !_parse_string(key, in) || !in.expect(':')) {
+ return false;
+ }
+ if (!ctx.parse_object_item(in, key)) {
+ return false;
+ }
+ } while (in.expect(','));
+ return in.expect('}');
+}
+
+template <typename Iter>
+inline bool _parse_number(double& out, input<Iter>& in) {
+ std::string num_str;
+ while (1) {
+ int ch = in.getc();
+ if (('0' <= ch && ch <= '9') || ch == '+' || ch == '-' || ch == '.' ||
+ ch == 'e' || ch == 'E') {
+ num_str.push_back(ch);
+ } else {
+ in.ungetc();
+ break;
+ }
+ }
+ char* endp;
+ out = strtod(num_str.c_str(), &endp);
+ return endp == num_str.c_str() + num_str.size();
+}
+
+template <typename Context, typename Iter>
+inline bool _parse(Context& ctx, input<Iter>& in) {
+ in.skip_ws();
+ int ch = in.getc();
+ switch (ch) {
+#define IS(ch, text, op) \
+ case ch: \
+ if (in.match(text) && op) { \
+ return true; \
+ } else { \
+ return false; \
+ }
+ IS('n', "ull", ctx.set_null());
+ IS('f', "alse", ctx.set_bool(false));
+ IS('t', "rue", ctx.set_bool(true));
+#undef IS
+ case '"':
+ return ctx.parse_string(in);
+ case '[':
+ return _parse_array(ctx, in);
+ case '{':
+ return _parse_object(ctx, in);
+ default:
+ if (('0' <= ch && ch <= '9') || ch == '-') {
+ in.ungetc();
+ double f;
+ if (_parse_number(f, in)) {
+ ctx.set_number(f);
+ return true;
+ } else {
+ return false;
+ }
+ }
+ break;
+ }
+ in.ungetc();
+ return false;
+}
+
+class deny_parse_context {
+ public:
+ bool set_null() { return false; }
+ bool set_bool(bool) { return false; }
+ bool set_number(double) { return false; }
+ template <typename Iter>
+ bool parse_string(input<Iter>&) {
+ return false;
+ }
+ bool parse_array_start() { return false; }
+ template <typename Iter>
+ bool parse_array_item(input<Iter>&, size_t) {
+ return false;
+ }
+ bool parse_object_start() { return false; }
+ template <typename Iter>
+ bool parse_object_item(input<Iter>&, const std::string&) {
+ return false;
+ }
+};
+
+class default_parse_context {
+ protected:
+ value* out_;
+
+ public:
+ default_parse_context(value* out) : out_(out) {}
+ bool set_null() {
+ *out_ = value();
+ return true;
+ }
+ bool set_bool(bool b) {
+ *out_ = value(b);
+ return true;
+ }
+ bool set_number(double f) {
+ *out_ = value(f);
+ return true;
+ }
+ template <typename Iter>
+ bool parse_string(input<Iter>& in) {
+ *out_ = value(string_type, false);
+ return _parse_string(out_->get<std::string>(), in);
+ }
+ bool parse_array_start() {
+ *out_ = value(array_type, false);
+ return true;
+ }
+ template <typename Iter>
+ bool parse_array_item(input<Iter>& in, size_t) {
+ array& a = out_->get<array>();
+ a.push_back(value());
+ default_parse_context ctx(&a.back());
+ return _parse(ctx, in);
+ }
+ bool parse_object_start() {
+ *out_ = value(object_type, false);
+ return true;
+ }
+ template <typename Iter>
+ bool parse_object_item(input<Iter>& in, const std::string& key) {
+ object& o = out_->get<object>();
+ default_parse_context ctx(&o[key]);
+ return _parse(ctx, in);
+ }
+
+ private:
+ default_parse_context(const default_parse_context&);
+ default_parse_context& operator=(const default_parse_context&);
+};
+
+class null_parse_context {
+ public:
+ struct dummy_str {
+ void push_back(int) {}
+ };
+
+ public:
+ null_parse_context() {}
+ bool set_null() { return true; }
+ bool set_bool(bool) { return true; }
+ bool set_number(double) { return true; }
+ template <typename Iter>
+ bool parse_string(input<Iter>& in) {
+ dummy_str s;
+ return _parse_string(s, in);
+ }
+ bool parse_array_start() { return true; }
+ template <typename Iter>
+ bool parse_array_item(input<Iter>& in, size_t) {
+ return _parse(*this, in);
+ }
+ bool parse_object_start() { return true; }
+ template <typename Iter>
+ bool parse_object_item(input<Iter>& in, const std::string&) {
+ return _parse(*this, in);
+ }
+
+ private:
+ null_parse_context(const null_parse_context&);
+ null_parse_context& operator=(const null_parse_context&);
+};
+
+// obsolete, use the version below
+template <typename Iter>
+inline std::string parse(value& out, Iter& pos, const Iter& last) {
+ std::string err;
+ pos = parse(out, pos, last, &err);
+ return err;
+}
+
+template <typename Context, typename Iter>
+inline Iter _parse(Context& ctx,
+ const Iter& first,
+ const Iter& last,
+ std::string* err) {
+ input<Iter> in(first, last);
+ if (!_parse(ctx, in) && err != NULL) {
+ char buf[64];
+ SNPRINTF(buf, sizeof(buf), "syntax error at line %d near: ", in.line());
+ *err = buf;
+ while (1) {
+ int ch = in.getc();
+ if (ch == -1 || ch == '\n') {
+ break;
+ } else if (ch >= ' ') {
+ err->push_back(ch);
+ }
+ }
+ }
+ return in.cur();
+}
+
+template <typename Iter>
+inline Iter parse(value& out,
+ const Iter& first,
+ const Iter& last,
+ std::string* err) {
+ default_parse_context ctx(&out);
+ return _parse(ctx, first, last, err);
+}
+
+inline std::string parse(value& out, std::istream& is) {
+ std::string err;
+ parse(out, std::istreambuf_iterator<char>(is.rdbuf()),
+ std::istreambuf_iterator<char>(), &err);
+ return err;
+}
+
+template <typename T>
+struct last_error_t {
+ static std::string s;
+};
+template <typename T>
+std::string last_error_t<T>::s;
+
+inline void set_last_error(const std::string& s) {
+ last_error_t<bool>::s = s;
+}
+
+inline const std::string& get_last_error() {
+ return last_error_t<bool>::s;
+}
+
+inline bool operator==(const value& x, const value& y) {
+ if (x.is<null>())
+ return y.is<null>();
+#define PICOJSON_CMP(type) \
+ if (x.is<type>()) \
+ return y.is<type>() && x.get<type>() == y.get<type>()
+ PICOJSON_CMP(bool);
+ PICOJSON_CMP(double);
+ PICOJSON_CMP(std::string);
+ PICOJSON_CMP(array);
+ PICOJSON_CMP(object);
+#undef PICOJSON_CMP
+ assert(0);
+#ifdef _MSC_VER
+ __assume(0);
+#endif
+ return false;
+}
+
+inline bool operator!=(const value& x, const value& y) {
+ return !(x == y);
+}
+}
+
+namespace std {
+template <>
+inline void swap(picojson::value& x, picojson::value& y) {
+ x.swap(y);
+}
+}
+
+inline std::istream& operator>>(std::istream& is, picojson::value& x) {
+ picojson::set_last_error(std::string());
+ std::string err = picojson::parse(x, is);
+ if (!err.empty()) {
+ picojson::set_last_error(err);
+ is.setstate(std::ios::failbit);
+ }
+ return is;
+}
+
+inline std::ostream& operator<<(std::ostream& os, const picojson::value& x) {
+ x.serialize(std::ostream_iterator<char>(os));
+ return os;
+}
+#ifdef _MSC_VER
+#pragma warning(pop)
+#endif
+
+#endif
+#ifdef TEST_PICOJSON
+#ifdef _MSC_VER
+#pragma warning(disable : 4127) // conditional expression is constant
+#endif
+
+using namespace std;
+
+static void plan(int num) {
+ printf("1..%d\n", num);
+}
+
+static bool success = true;
+
+static void ok(bool b, const char* name = "") {
+ static int n = 1;
+ if (!b)
+ success = false;
+ printf("%s %d - %s\n", b ? "ok" : "ng", n++, name);
+}
+
+template <typename T>
+void is(const T& x, const T& y, const char* name = "") {
+ if (x == y) {
+ ok(true, name);
+ } else {
+ ok(false, name);
+ }
+}
+
+#include <algorithm>
+#include <sstream>
+#include <float.h>
+#include <limits.h>
+
+int main(void) {
+ plan(85);
+
+// constructors
+#define TEST(expr, expected) \
+ is(picojson::value expr.serialize(), string(expected), \
+ "picojson::value" #expr)
+
+ TEST((true), "true");
+ TEST((false), "false");
+ TEST((42.0), "42");
+ TEST((string("hello")), "\"hello\"");
+ TEST(("hello"), "\"hello\"");
+ TEST(("hello", 4), "\"hell\"");
+
+ {
+ double a = 1;
+ for (int i = 0; i < 1024; i++) {
+ picojson::value vi(a);
+ std::stringstream ss;
+ ss << vi;
+ picojson::value vo;
+ ss >> vo;
+ double b = vo.get<double>();
+ if ((i < 53 && a != b) || fabs(a - b) / b > 1e-8) {
+ printf("ng i=%d a=%.18e b=%.18e\n", i, a, b);
+ }
+ a *= 2;
+ }
+ }
+
+#undef TEST
+
+#define TEST(in, type, cmp, serialize_test) \
+ { \
+ picojson::value v; \
+ const char* s = in; \
+ string err = picojson::parse(v, s, s + strlen(s)); \
+ ok(err.empty(), in " no error"); \
+ ok(v.is<type>(), in " check type"); \
+ is<type>(v.get<type>(), cmp, in " correct output"); \
+ is(*s, '\0', in " read to eof"); \
+ if (serialize_test) { \
+ is(v.serialize(), string(in), in " serialize"); \
+ } \
+ }
+ TEST("false", bool, false, true);
+ TEST("true", bool, true, true);
+ TEST("90.5", double, 90.5, false);
+ TEST("1.7976931348623157e+308", double, DBL_MAX, false);
+ TEST("\"hello\"", string, string("hello"), true);
+ TEST("\"\\\"\\\\\\/\\b\\f\\n\\r\\t\"", string, string("\"\\/\b\f\n\r\t"),
+ true);
+ TEST("\"\\u0061\\u30af\\u30ea\\u30b9\"", string,
+ string("a\xe3\x82\xaf\xe3\x83\xaa\xe3\x82\xb9"), false);
+ TEST("\"\\ud840\\udc0b\"", string, string("\xf0\xa0\x80\x8b"), false);
+#undef TEST
+
+#define TEST(type, expr) \
+ { \
+ picojson::value v; \
+ const char* s = expr; \
+ string err = picojson::parse(v, s, s + strlen(s)); \
+ ok(err.empty(), "empty " #type " no error"); \
+ ok(v.is<picojson::type>(), "empty " #type " check type"); \
+ ok(v.get<picojson::type>().empty(), "check " #type " array size"); \
+ }
+ TEST(array, "[]");
+ TEST(object, "{}");
+#undef TEST
+
+ {
+ picojson::value v;
+ const char* s = "[1,true,\"hello\"]";
+ string err = picojson::parse(v, s, s + strlen(s));
+ ok(err.empty(), "array no error");
+ ok(v.is<picojson::array>(), "array check type");
+ is(v.get<picojson::array>().size(), size_t(3), "check array size");
+ ok(v.contains(0), "check contains array[0]");
+ ok(v.get(0).is<double>(), "check array[0] type");
+ is(v.get(0).get<double>(), 1.0, "check array[0] value");
+ ok(v.contains(1), "check contains array[1]");
+ ok(v.get(1).is<bool>(), "check array[1] type");
+ ok(v.get(1).get<bool>(), "check array[1] value");
+ ok(v.contains(2), "check contains array[2]");
+ ok(v.get(2).is<string>(), "check array[2] type");
+ is(v.get(2).get<string>(), string("hello"), "check array[2] value");
+ ok(!v.contains(3), "check not contains array[3]");
+ }
+
+ {
+ picojson::value v;
+ const char* s = "{ \"a\": true }";
+ string err = picojson::parse(v, s, s + strlen(s));
+ ok(err.empty(), "object no error");
+ ok(v.is<picojson::object>(), "object check type");
+ is(v.get<picojson::object>().size(), size_t(1), "check object size");
+ ok(v.contains("a"), "check contains property");
+ ok(v.get("a").is<bool>(), "check bool property exists");
+ is(v.get("a").get<bool>(), true, "check bool property value");
+ is(v.serialize(), string("{\"a\":true}"), "serialize object");
+ ok(!v.contains("z"), "check not contains property");
+ }
+
+#define TEST(json, msg) \
+ do { \
+ picojson::value v; \
+ const char* s = json; \
+ string err = picojson::parse(v, s, s + strlen(s)); \
+ is(err, string("syntax error at line " msg), msg); \
+ } while (0)
+ TEST("falsoa", "1 near: oa");
+ TEST("{]", "1 near: ]");
+ TEST("\n\bbell", "2 near: bell");
+ TEST("\"abc\nd\"", "1 near: ");
+#undef TEST
+
+ {
+ picojson::value v1, v2;
+ const char* s;
+ string err;
+ s = "{ \"b\": true, \"a\": [1,2,\"three\"], \"d\": 2 }";
+ err = picojson::parse(v1, s, s + strlen(s));
+ s = "{ \"d\": 2.0, \"b\": true, \"a\": [1,2,\"three\"] }";
+ err = picojson::parse(v2, s, s + strlen(s));
+ ok((v1 == v2), "check == operator in deep comparison");
+ }
+
+ {
+ picojson::value v1, v2;
+ const char* s;
+ string err;
+ s = "{ \"b\": true, \"a\": [1,2,\"three\"], \"d\": 2 }";
+ err = picojson::parse(v1, s, s + strlen(s));
+ s = "{ \"d\": 2.0, \"a\": [1,\"three\"], \"b\": true }";
+ err = picojson::parse(v2, s, s + strlen(s));
+ ok((v1 != v2), "check != operator for array in deep comparison");
+ }
+
+ {
+ picojson::value v1, v2;
+ const char* s;
+ string err;
+ s = "{ \"b\": true, \"a\": [1,2,\"three\"], \"d\": 2 }";
+ err = picojson::parse(v1, s, s + strlen(s));
+ s = "{ \"d\": 2.0, \"a\": [1,2,\"three\"], \"b\": false }";
+ err = picojson::parse(v2, s, s + strlen(s));
+ ok((v1 != v2), "check != operator for object in deep comparison");
+ }
+
+ {
+ picojson::value v1, v2;
+ const char* s;
+ string err;
+ s = "{ \"b\": true, \"a\": [1,2,\"three\"], \"d\": 2 }";
+ err = picojson::parse(v1, s, s + strlen(s));
+ picojson::object& o = v1.get<picojson::object>();
+ o.erase("b");
+ picojson::array& a = o["a"].get<picojson::array>();
+ picojson::array::iterator i;
+ i = std::remove(a.begin(), a.end(), picojson::value(std::string("three")));
+ a.erase(i, a.end());
+ s = "{ \"a\": [1,2], \"d\": 2 }";
+ err = picojson::parse(v2, s, s + strlen(s));
+ ok((v1 == v2), "check erase()");
+ }
+
+ ok(picojson::value(3.0).serialize() == "3",
+ "integral number should be serialized as a integer");
+
+ {
+ const char* s = "{ \"a\": [1,2], \"d\": 2 }";
+ picojson::null_parse_context ctx;
+ string err;
+ picojson::_parse(ctx, s, s + strlen(s), &err);
+ ok(err.empty(), "null_parse_context");
+ }
+
+ {
+ picojson::value v1, v2;
+ v1 = picojson::value(true);
+ swap(v1, v2);
+ ok(v1.is<picojson::null>(), "swap (null)");
+ ok(v2.get<bool>() == true, "swap (bool)");
+
+ v1 = picojson::value("a");
+ v2 = picojson::value(1.0);
+ swap(v1, v2);
+ ok(v1.get<double>() == 1.0, "swap (dobule)");
+ ok(v2.get<string>() == "a", "swap (string)");
+
+ v1 = picojson::value(picojson::object());
+ v2 = picojson::value(picojson::array());
+ swap(v1, v2);
+ ok(v1.is<picojson::array>(), "swap (array)");
+ ok(v2.is<picojson::object>(), "swap (object)");
+ }
+
+ return success ? 0 : 1;
+}
+
+#endif
--- /dev/null
+/*
+ * Copyright (c) 2016 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <cstdlib>
+#include <system_info.h>
+#include "common/platform_info.h"
+
+namespace common {
+
+enum _profile getProfile(void) {
+ static enum _profile profile = kPROFILE_UNKNOWN;
+
+ // This is false only for the first execution. Let's optimize it.
+ if (__builtin_expect(profile != kPROFILE_UNKNOWN, 1))
+ return profile;
+
+ char* profileName;
+ system_info_get_platform_string("http://tizen.org/feature/profile",
+ &profileName);
+ switch (*profileName) {
+ case 'm':
+ case 'M':
+ profile = kPROFILE_MOBILE;
+ break;
+ case 'w':
+ case 'W':
+ profile = kPROFILE_WEARABLE;
+ break;
+ case 't':
+ case 'T':
+ profile = kPROFILE_TV;
+ break;
+ case 'i':
+ case 'I':
+ profile = kPROFILE_IVI;
+ break;
+ default: // common or unknown ==> ALL ARE COMMON.
+ profile = kPROFILE_COMMON;
+ }
+ free(profileName);
+
+ return profile;
+}
+
+} // namespace common
--- /dev/null
+/*
+ * Copyright (c) 2016 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef XWALK_COMMON_PLATFORM_INFO_H_
+#define XWALK_COMMON_PLATFORM_INFO_H_
+
+namespace common {
+
+enum _profile {
+ kPROFILE_UNKNOWN = 0,
+ kPROFILE_MOBILE = 0x1,
+ kPROFILE_WEARABLE = 0x2,
+ kPROFILE_TV = 0x4,
+ kPROFILE_IVI = 0x8,
+ kPROFILE_COMMON = 0x10,
+};
+
+// To optimize for GBMs, you may define the following values based on profile
+// (e.g., #define TIZEN_FEATURE_blahblah (1))
+
+#define TIZEN_FEATURE_web_ime_support \
+ (common::getProfile() & ((common::kPROFILE_WEARABLE) | (common::kPROFILE_TV)))
+#define TIZEN_FEATURE_manual_rotate_support \
+ (common::getProfile() & ((common::kPROFILE_MOBILE)))
+#define TIZEN_FEATURE_watch_face_support \
+ (common::getProfile() & ((common::kPROFILE_WEARABLE)))
+#define TIZEN_FEATURE_rotary_event_support \
+ (common::getProfile() & ((common::kPROFILE_WEARABLE)))
+
+extern enum _profile getProfile(void);
+
+} // namespace common
+#endif // XWALK_COMMON_PLATFORM_INFO_H_
--- /dev/null
+/*
+ * Copyright (c) 2015 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "common/profiler.h"
+
+#include <math.h>
+#include <ttrace.h>
+
+#include "common/logger.h"
+#include "common/string_utils.h"
+
+namespace common {
+
+namespace {
+
+void PrintProfileTime(const char* step, const struct timespec& start) {
+ struct timespec end;
+ clock_gettime(CLOCK_REALTIME, &end);
+ int64_t diff_in_milli = (end.tv_sec - start.tv_sec) * 1000 +
+ round((end.tv_nsec - start.tv_nsec) * 0.000001);
+ std::ostringstream ss;
+ ss << "END (" << diff_in_milli << "ms)";
+ PrintProfileLog(step, ss.str().c_str());
+}
+
+} // namespace
+
+void PrintProfileLog(const char* func, const char* tag) {
+ LOGGER_RAW(DLOG_DEBUG, LOGGER_TAG)
+ << "[PROF] [" << utils::GetCurrentMilliSeconds() << "] " << func << ":"
+ << tag;
+}
+
+ScopeProfile::ScopeProfile(const char* step, const bool isStep)
+ : step_(step), expired_(false), isStep_(isStep) {
+ clock_gettime(CLOCK_REALTIME, &start_);
+
+ if (!isStep) {
+ // Remove return type and parameter info from __PRETTY_FUNCTION__
+ int se = step_.find_first_of('(');
+ int ss = step_.find_last_of(' ', se) + 1;
+ if (ss < se) {
+ step_ = step_.substr(ss, se - ss);
+ }
+ }
+
+ PrintProfileLog(step_.c_str(), "START");
+
+ if (isStep_)
+ traceAsyncBegin(TTRACE_TAG_WEB, 0, "%s%s", "XWALK:", step_.c_str());
+ else
+ traceBegin(TTRACE_TAG_WEB, "%s%s", "XWALK:", step_.c_str());
+}
+
+ScopeProfile::~ScopeProfile() {
+ if (!expired_) {
+ PrintProfileTime(step_.c_str(), start_);
+
+ if (isStep_)
+ traceAsyncEnd(TTRACE_TAG_WEB, 0, "%s%s", "XWALK:", step_.c_str());
+ else
+ traceEnd(TTRACE_TAG_WEB);
+ }
+}
+
+void ScopeProfile::Reset() {
+ clock_gettime(CLOCK_REALTIME, &start_);
+ PrintProfileLog(step_.c_str(), "START-updated");
+
+ if (isStep_)
+ traceAsyncEnd(TTRACE_TAG_WEB, 0, "%s%s", "XWALK:", step_.c_str());
+ else
+ traceEnd(TTRACE_TAG_WEB);
+}
+
+void ScopeProfile::End() {
+ expired_ = true;
+ PrintProfileTime(step_.c_str(), start_);
+}
+
+StepProfile* StepProfile::GetInstance() {
+ static StepProfile instance;
+ return &instance;
+}
+
+StepProfile::StepProfile() {}
+
+StepProfile::~StepProfile() {}
+
+void StepProfile::Start(const char* step) {
+ map_[step].reset(new ScopeProfile(step, true));
+}
+
+void StepProfile::End(const char* step) {
+ map_[step].reset();
+}
+
+} // namespace common
--- /dev/null
+/*
+ * Copyright (c) 2015 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef XWALK_COMMON_PROFILER_H_
+#define XWALK_COMMON_PROFILER_H_
+
+#include <time.h>
+
+#include <map>
+#include <memory>
+#include <string>
+
+namespace common {
+
+#define PROFILE_START() PrintProfileLog(__FUNCTION__, "START");
+#define PROFILE_END() PrintProfileLog(__FUNCTION__, "END");
+#define PROFILE(x) PrintProfileLog(__FUNCTION__, x);
+
+void PrintProfileLog(const char* func, const char* tag);
+
+class ScopeProfile {
+ public:
+ explicit ScopeProfile(const char* step, const bool isStep);
+ ~ScopeProfile();
+ void Reset();
+ void End();
+
+ private:
+ std::string step_;
+ struct timespec start_;
+ bool expired_;
+ bool isStep_;
+};
+
+class StepProfile {
+ public:
+ static StepProfile* GetInstance();
+ void Start(const char* step);
+ void End(const char* step);
+
+ private:
+ StepProfile();
+ ~StepProfile();
+ typedef std::map<const std::string, std::unique_ptr<ScopeProfile> >
+ ProfileMapT;
+ ProfileMapT map_;
+};
+
+} // namespace common
+
+#define SCOPE_PROFILE() \
+ common::ScopeProfile __profile(__PRETTY_FUNCTION__, false);
+
+#define STEP_PROFILE_START(x) common::StepProfile::GetInstance()->Start(x)
+
+#define STEP_PROFILE_END(x) common::StepProfile::GetInstance()->End(x)
+
+#endif // XWALK_COMMON_PROFILER_H_
--- /dev/null
+/*
+ * Copyright (c) 2015 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "common/resource_manager.h"
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <aul.h>
+#include <pkgmgr-info.h>
+#include <stdio.h>
+#include <unistd.h>
+#include <web_app_enc.h>
+
+#include <algorithm>
+#include <functional>
+#include <memory>
+#include <set>
+#include <sstream>
+#include <vector>
+
+#include "common/application_data.h"
+#include "common/app_control.h"
+#include "common/file_utils.h"
+#include "common/locale_manager.h"
+#include "common/logger.h"
+#include "common/string_utils.h"
+#include "common/url.h"
+
+using wgt::parse::AppControlInfo;
+
+namespace common {
+
+namespace {
+
+typedef std::vector<AppControlInfo> AppControlList;
+
+// Scheme type
+const char* kSchemeTypeApp = "app://";
+const char* kSchemeTypeFile = "file://";
+const char* kSchemeTypeHttp = "http://";
+const char* kSchemeTypeHttps = "https://";
+// lendth of scheme identifier ://
+const int kSchemeIdLen = 3;
+// TODO(wy80.choi): comment out below unused const variables if needed.
+// const char* kSchemeTypeWidget = "widget://";
+
+// Default Start Files
+const char* kDefaultStartFiles[] = {"index.htm", "index.html", "index.svg",
+ "index.xhtml", "index.xht"};
+
+// Default Encoding
+const char* kDefaultEncoding = "UTF-8";
+
+// EncryptedFileExtensions
+const std::set<std::string> kEncryptedFileExtensions{".html", ".htm", ".css",
+ ".js"};
+
+static std::string GetMimeFromUri(const std::string& uri) {
+ // checking passed uri is local file
+ std::string file_uri_case(kSchemeTypeFile);
+ int ret = AUL_R_EINVAL;
+ char mimetype[128] = {
+ 0,
+ };
+ size_t pos = std::string::npos;
+ if (utils::StartsWith(uri, file_uri_case)) {
+ // case 1. uri = file:///xxxx
+ ret =
+ aul_get_mime_from_file(uri.substr(pos + file_uri_case.length()).c_str(),
+ mimetype, sizeof(mimetype));
+ } else if (utils::StartsWith(uri, "/")) {
+ // case 2. uri = /xxxx
+ ret = aul_get_mime_from_file(uri.c_str(), mimetype, sizeof(mimetype));
+ }
+
+ if (ret == AUL_R_OK) {
+ return std::string(mimetype);
+ } else {
+ return std::string();
+ }
+}
+
+static bool CompareMime(const std::string& info_mime,
+ const std::string& request_mime) {
+ // suppose that these mimetypes are valid expressions ('type'/'sub-type')
+ if (info_mime == "*" || info_mime == "*/*")
+ return true;
+
+ if (request_mime.empty())
+ return info_mime.empty();
+
+ std::string info_type;
+ std::string info_sub;
+ std::string request_type;
+ std::string request_sub;
+ if (!(utils::SplitString(info_mime, &info_type, &info_sub, '/') &&
+ utils::SplitString(request_mime, &request_type, &request_sub, '/')))
+ return false;
+
+ return info_type == request_type && (info_sub == "*")
+ ? true
+ : (info_sub == request_sub);
+}
+
+static bool CompareUri(const std::string& info_uri,
+ const std::string& request_uri) {
+ if (info_uri == "*")
+ return true;
+
+ if (request_uri.empty())
+ return info_uri.empty();
+
+ std::string info_scheme = utils::SchemeName(info_uri);
+
+ // if has only scheme or scheme+star. ex) http, http://, http://*
+ if (!info_scheme.empty() &&
+ (info_uri == info_scheme || utils::EndsWith(info_uri, "://") ||
+ utils::EndsWith(info_uri, "://*"))) {
+ return utils::SchemeName(request_uri) == info_scheme;
+ }
+
+ if (utils::EndsWith(info_uri, "*")) {
+ return utils::StartsWith(request_uri,
+ info_uri.substr(0, info_uri.length() - 1));
+ } else {
+ return request_uri == info_uri;
+ }
+}
+
+static std::string InsertPrefixPath(const std::string& start_uri) {
+ if (start_uri.find("://") != std::string::npos)
+ return start_uri;
+ else
+ return std::string(kSchemeTypeFile) + "/" + start_uri;
+}
+
+} // namespace
+
+ResourceManager::Resource::Resource(const std::string& uri)
+ : uri_(uri), should_reset_(true), encoding_(kDefaultEncoding) {}
+
+ResourceManager::Resource::Resource(const std::string& uri, bool should_reset)
+ : uri_(uri), should_reset_(should_reset), encoding_(kDefaultEncoding) {}
+
+ResourceManager::Resource::Resource(const std::string& uri,
+ const std::string& mime,
+ const std::string& encoding)
+ : uri_(uri), mime_(mime), should_reset_(true), encoding_(encoding) {}
+
+ResourceManager::Resource::Resource(const ResourceManager::Resource& res) {
+ *this = res;
+}
+
+ResourceManager::Resource& ResourceManager::Resource::operator=(
+ const ResourceManager::Resource& res) {
+ this->uri_ = res.uri();
+ this->mime_ = res.mime();
+ this->should_reset_ = res.should_reset();
+ this->encoding_ = res.encoding();
+ return *this;
+}
+
+bool ResourceManager::Resource::operator==(const Resource& res) {
+ if (this->uri_ == res.uri() && this->mime_ == res.mime() &&
+ this->should_reset_ == res.should_reset() &&
+ this->encoding_ == res.encoding()) {
+ return true;
+ } else {
+ return false;
+ }
+}
+
+ResourceManager::ResourceManager(ApplicationData* application_data,
+ LocaleManager* locale_manager)
+ : application_data_(application_data),
+ locale_manager_(locale_manager),
+ security_model_version_(0) {
+ if (application_data != NULL) {
+ appid_ = application_data->tizen_application_info()->id();
+ if (application_data->csp_info() != NULL ||
+ application_data->csp_report_info() != NULL ||
+ application_data->allowed_navigation_info() != NULL) {
+ security_model_version_ = 2;
+ } else {
+ security_model_version_ = 1;
+ }
+ }
+}
+
+std::unique_ptr<ResourceManager::Resource>
+ResourceManager::GetDefaultResource() {
+ std::string src;
+ std::string type;
+ std::string encoding = kDefaultEncoding;
+
+ std::shared_ptr<const wgt::parse::ContentInfo> content_info;
+ if (application_data_) {
+ content_info = application_data_->content_info();
+ if (content_info) {
+ src = content_info->src();
+ type = content_info->type();
+ encoding = content_info->encoding();
+ LOGGER(DEBUG) << "src: " << src;
+ LOGGER(DEBUG) << "type: " << type;
+ LOGGER(DEBUG) << "encoding: " << encoding;
+ } else {
+ LOGGER(DEBUG) << "content_info is null";
+ }
+ }
+
+ // Check that tizen:content src is external page
+ if (utils::StartsWith(src, kSchemeTypeHttp) ||
+ utils::StartsWith(src, kSchemeTypeHttps)) {
+ LOGGER(DEBUG) << "tizen content_info's src is an external page";
+ return std::unique_ptr<Resource>(new Resource(src, type, encoding));
+ }
+
+ // Find based on default start files list, if src is empty or invald
+ if (!content_info || !utils::Exists(resource_base_path_ + src)) {
+ for (auto& start_file : kDefaultStartFiles) {
+ if (utils::Exists(resource_base_path_ + start_file)) {
+ src = InsertPrefixPath(start_file);
+ LOGGER(DEBUG) << "start file: " << src;
+ return std::unique_ptr<Resource>(new Resource(src, type, encoding));
+ }
+ }
+ // shouldn't be entered here
+ LOGGER(ERROR) << "it can't enter here. can't find any default start file";
+ return std::unique_ptr<Resource>(new Resource(src, type, encoding));
+ }
+
+ return std::unique_ptr<Resource>(
+ new Resource(InsertPrefixPath(src), type, encoding));
+}
+
+std::unique_ptr<ResourceManager::Resource> ResourceManager::GetMatchedResource(
+ const AppControlInfo& app_control_info) {
+ if (!app_control_info.src().empty()) {
+ return std::unique_ptr<Resource>(
+ new Resource(InsertPrefixPath(app_control_info.src()),
+ app_control_info.reload() == "disable" ? false : true));
+ }
+ return GetDefaultResource();
+}
+
+std::unique_ptr<ResourceManager::Resource> ResourceManager::GetStartResource(
+ const AppControl* app_control) {
+ std::string operation = app_control->operation();
+ if (operation.empty()) {
+ LOGGER(ERROR) << "operation(mandatory) is NULL";
+ return GetDefaultResource();
+ }
+
+ std::string mime = app_control->mime();
+ std::string uri = app_control->uri();
+ if (mime.empty() && !uri.empty()) {
+ mime = GetMimeFromUri(uri);
+ }
+
+ LOGGER(DEBUG) << "Passed AppControl data";
+ LOGGER(DEBUG) << " - operation : " << operation;
+ LOGGER(DEBUG) << " - mimetype : " << mime;
+ LOGGER(DEBUG) << " - uri : " << uri;
+
+ if (application_data_ == NULL ||
+ application_data_->app_control_info_list() == NULL) {
+ return GetDefaultResource();
+ }
+
+ auto app_control_list = application_data_->app_control_info_list()->controls;
+
+ AppControlList::const_iterator iter = std::find_if(
+ app_control_list.begin(), app_control_list.end(),
+ [&operation, &uri, &mime](AppControlInfo& info) -> bool {
+ return (info.operation() == operation) &&
+ CompareMime(info.mime(), mime) && CompareUri(info.uri(), uri);
+ });
+
+ if (iter != app_control_list.end()) {
+ return GetMatchedResource(*iter);
+ } else {
+ return GetDefaultResource();
+ }
+}
+
+std::string ResourceManager::GetLocalizedPath(const std::string& origin) {
+ std::string file_scheme = std::string() + kSchemeTypeFile + "/";
+ std::string app_scheme = std::string() + kSchemeTypeApp;
+ std::string locale_path = "locales/";
+ auto find = locale_cache_.find(origin);
+ if (find != locale_cache_.end()) {
+ return find->second;
+ }
+ std::string& result = locale_cache_[origin];
+ result = origin;
+ std::string url = origin;
+
+ std::string suffix;
+ size_t pos = url.find_first_of("#?");
+ if (pos != std::string::npos) {
+ suffix = url.substr(pos);
+ url.resize(pos);
+ }
+
+ if (utils::StartsWith(url, app_scheme)) {
+ // remove "app://"
+ url.erase(0, app_scheme.length());
+
+ // remove app id + /
+ std::string check = appid_ + "/";
+ if (utils::StartsWith(url, check)) {
+ url.erase(0, check.length());
+ } else {
+ LOGGER(ERROR) << "Invalid uri: {scheme:app} uri=" << origin;
+ return result;
+ }
+ } else if (utils::StartsWith(url, file_scheme)) {
+ // remove "file:///"
+ url.erase(0, file_scheme.length());
+ }
+
+ if (!url.empty() && url[url.length() - 1] == '/') {
+ url.erase(url.length() - 1, 1);
+ }
+
+ if (url.empty()) {
+ LOGGER(ERROR) << "Invalid uri: uri=" << origin;
+ return result;
+ }
+
+ std::string file_path = utils::UrlDecode(RemoveLocalePath(url));
+ for (auto& locales : locale_manager_->system_locales()) {
+ // check ../locales/
+ std::string app_locale_path = resource_base_path_ + locale_path;
+ if (!Exists(app_locale_path)) {
+ break;
+ }
+
+ // check locale path ../locales/en_us/
+ std::string app_localized_path = app_locale_path + locales + "/";
+ if (!Exists(app_localized_path)) {
+ continue;
+ }
+ std::string resource_path = app_localized_path + file_path;
+ if (Exists(resource_path)) {
+ result = "file://" + resource_path + suffix;
+ return result;
+ }
+ }
+
+ std::string default_locale = resource_base_path_ + file_path;
+ if (Exists(default_locale)) {
+ result = "file://" + default_locale + suffix;
+ return result;
+ }
+
+ LOGGER(ERROR) << "Invalid uri: uri=" << origin << ", decoded=" << file_path;
+ return result;
+}
+
+std::string ResourceManager::RemoveLocalePath(const std::string& path) {
+ std::string locale_path = "locales/";
+ std::string result_path = path.at(0) == '/' ? path : "/" + path;
+ if (!utils::StartsWith(result_path, resource_base_path_)) {
+ return path;
+ }
+
+ result_path = result_path.substr(resource_base_path_.length());
+ if (!utils::StartsWith(result_path, locale_path)) {
+ return result_path;
+ }
+
+ size_t found = result_path.find_first_of('/', locale_path.length());
+ if (found != std::string::npos) {
+ result_path = result_path.substr(found + 1);
+ }
+ return result_path;
+}
+
+void ResourceManager::set_base_resource_path(const std::string& path) {
+ if (path.empty()) {
+ return;
+ }
+
+ resource_base_path_ = path;
+ if (resource_base_path_[resource_base_path_.length() - 1] != '/') {
+ resource_base_path_ += "/";
+ }
+}
+
+bool ResourceManager::Exists(const std::string& path) {
+ auto find = file_existed_cache_.find(path);
+ if (find != file_existed_cache_.end()) {
+ return find->second;
+ }
+ bool ret = file_existed_cache_[path] = utils::Exists(path);
+ return ret;
+}
+
+bool ResourceManager::AllowNavigation(const std::string& url) {
+ if (security_model_version_ == 2)
+ return CheckAllowNavigation(url);
+ return CheckWARP(url);
+}
+
+bool ResourceManager::AllowedResource(const std::string& url) {
+ if (security_model_version_ == 2)
+ return true;
+ return CheckWARP(url);
+}
+
+bool ResourceManager::CheckWARP(const std::string& url) {
+ // allow non-external resource
+ if (!utils::StartsWith(url, kSchemeTypeHttp) &&
+ !utils::StartsWith(url, kSchemeTypeHttps)) {
+ return true;
+ }
+
+ auto warp = application_data_->warp_info();
+ if (warp.get() == NULL)
+ return false;
+
+ auto find = warp_cache_.find(url);
+ if (find != warp_cache_.end()) {
+ return find->second;
+ }
+
+ bool& result = warp_cache_[url];
+ result = true;
+
+ URL url_info(url);
+
+ // if didn't have a scheme, it means local resource
+ if (url_info.scheme().empty()) {
+ return true;
+ }
+
+ for (auto& allow : warp->access_map()) {
+ if (allow.first == "*") {
+ return true;
+ } else if (allow.first.empty()) {
+ continue;
+ }
+
+ URL allow_url(allow.first);
+
+ // should be match the scheme and port
+ if (allow_url.scheme() != url_info.scheme() ||
+ allow_url.port() != url_info.port()) {
+ continue;
+ }
+
+ // if domain alos was matched, allow resource
+ if (allow_url.domain() == url_info.domain()) {
+ return true;
+ } else if (allow.second) {
+ // if does not match domain, should be check sub domain
+
+ // filter : test.com , subdomain=true
+ // url : aaa.test.com
+ // check url was ends with ".test.com"
+ if (utils::EndsWith(url_info.domain(), "." + allow_url.domain())) {
+ return true;
+ }
+ }
+ }
+
+ return result = false;
+}
+
+bool ResourceManager::CheckAllowNavigation(const std::string& url) {
+ // allow non-external resource
+ if (!utils::StartsWith(url, kSchemeTypeHttp) &&
+ !utils::StartsWith(url, kSchemeTypeHttps)) {
+ return true;
+ }
+
+ auto allow = application_data_->allowed_navigation_info();
+ if (allow.get() == NULL)
+ return false;
+
+ auto find = warp_cache_.find(url);
+ if (find != warp_cache_.end()) {
+ return find->second;
+ }
+
+ bool& result = warp_cache_[url];
+ result = true;
+
+ URL url_info(url);
+
+ // if didn't have a scheme, it means local resource
+ if (url_info.scheme().empty()) {
+ return true;
+ }
+
+ for (auto& allow_domain : allow->GetAllowedDomains()) {
+ URL a_domain_info(allow_domain);
+
+ // check wildcard *
+ if (a_domain_info.domain() == "*") {
+ return true;
+ }
+
+ bool prefix_wild = false;
+ bool suffix_wild = false;
+ std::string a_domain = a_domain_info.domain();
+ if (utils::StartsWith(a_domain, "*")) {
+ prefix_wild = true;
+ // *.domain.com -> .domain.com
+ a_domain = a_domain.substr(1);
+ }
+ if (utils::EndsWith(a_domain, "*")) {
+ suffix_wild = true;
+ // domain.* -> domain.
+ a_domain = a_domain.substr(0, a_domain.length() - 1);
+ }
+
+ if (!prefix_wild && !suffix_wild) {
+ // if no wildcard, should be exactly matched
+ if (url_info.domain() == a_domain) {
+ return true;
+ }
+ } else if (prefix_wild && !suffix_wild) {
+ // *.domain.com : it shoud be "domain.com" or end with ".domain.com"
+ if (url_info.domain() == a_domain.substr(1) ||
+ utils::EndsWith(url_info.domain(), a_domain)) {
+ return true;
+ }
+ } else if (!prefix_wild && suffix_wild) {
+ // www.sample.* : it should be starts with "www.sample."
+ if (utils::StartsWith(url_info.domain(), a_domain)) {
+ return true;
+ }
+ } else if (prefix_wild && suffix_wild) {
+ // *.sample.* : it should be starts with sample. or can find ".sample."
+ // in url
+ if (utils::StartsWith(url_info.domain(), a_domain.substr(1)) ||
+ std::string::npos != url_info.domain().find(a_domain)) {
+ return true;
+ }
+ }
+ }
+
+ return result = false;
+}
+
+bool ResourceManager::IsEncrypted(const std::string& path) {
+ auto setting = application_data_->setting_info();
+ if (setting.get() == NULL)
+ return false;
+
+ if (setting->encryption_enabled()) {
+ std::string ext = utils::ExtName(path);
+ if (kEncryptedFileExtensions.count(ext) > 0) {
+ return true;
+ }
+ }
+ return false;
+}
+
+std::string ResourceManager::DecryptResource(const std::string& path) {
+ // read file and make a buffer
+ std::string src_path(path);
+ if (utils::StartsWith(src_path, kSchemeTypeFile)) {
+ src_path.erase(0, strlen(kSchemeTypeFile));
+ }
+
+ // Remove the parameters at the end of an href attribute
+ size_t end_of_path = src_path.find_first_of("?#");
+ if (end_of_path != std::string::npos)
+ src_path = src_path.substr(0, end_of_path);
+
+ // checking web app type
+ static bool inited = false;
+ static bool is_global = false;
+ static bool is_preload = false;
+
+ std::string pkg_id = application_data_->pkg_id();
+ if (!inited) {
+ inited = true;
+ pkgmgrinfo_pkginfo_h handle;
+ int ret =
+ pkgmgrinfo_pkginfo_get_usr_pkginfo(pkg_id.c_str(), getuid(), &handle);
+ if (ret != PMINFO_R_OK) {
+ LOGGER(ERROR) << "Could not get handle for pkginfo : pkg_id = " << pkg_id;
+ return path;
+ } else {
+ ret = pkgmgrinfo_pkginfo_is_global(handle, &is_global);
+ if (ret != PMINFO_R_OK) {
+ LOGGER(ERROR) << "Could not check is_global : pkg_id = " << pkg_id;
+ pkgmgrinfo_pkginfo_destroy_pkginfo(handle);
+ return path;
+ }
+ ret = pkgmgrinfo_pkginfo_is_preload(handle, &is_preload);
+ if (ret != PMINFO_R_OK) {
+ LOGGER(ERROR) << "Could not check is_preload : pkg_id = " << pkg_id;
+ pkgmgrinfo_pkginfo_destroy_pkginfo(handle);
+ return path;
+ }
+ pkgmgrinfo_pkginfo_destroy_pkginfo(handle);
+ }
+ }
+
+ struct stat buf;
+ memset(&buf, 0, sizeof(buf));
+ if (stat(src_path.c_str(), &buf) == 0) {
+ const std::size_t file_size = buf.st_size;
+ std::unique_ptr<unsigned char[]> in_chunk;
+
+ if (0 == file_size) {
+ LOGGER(ERROR) << src_path.c_str()
+ << " size is 0, so decryption is skiped";
+ return path;
+ }
+
+ FILE* src = fopen(src_path.c_str(), "rb");
+ if (src == NULL) {
+ LOGGER(ERROR) << "Cannot open file for decryption: " << path;
+ return path;
+ }
+
+ // Read buffer from the source file
+ std::unique_ptr<unsigned char[]> decrypted_str(
+ new unsigned char[file_size]);
+ int decrypted_size = 0;
+
+ do {
+ unsigned char get_dec_size[5];
+ memset(get_dec_size, 0x00, sizeof(get_dec_size));
+
+ size_t read_size = fread(get_dec_size, 1, 4, src);
+ if (0 != read_size) {
+ unsigned int read_buf_size = 0;
+ std::istringstream(std::string((char*)get_dec_size)) >> read_buf_size;
+ if (read_buf_size == 0) {
+ LOGGER(ERROR) << "Failed to read resource";
+ fclose(src);
+ return path;
+ }
+ in_chunk.reset(new unsigned char[read_buf_size]);
+
+ size_t dec_read_size = fread(in_chunk.get(), 1, read_buf_size, src);
+ if (0 != dec_read_size) {
+ unsigned char* decrypted_data = nullptr;
+ size_t decrypted_len = 0;
+ int ret;
+ if (is_global) {
+ ret = wae_decrypt_global_web_application(
+ pkg_id.c_str(), is_preload, in_chunk.get(), (int)dec_read_size,
+ &decrypted_data, &decrypted_len);
+ } else {
+ ret = wae_decrypt_web_application(
+ getuid(), pkg_id.c_str(), in_chunk.get(), (int)dec_read_size,
+ &decrypted_data, &decrypted_len);
+ }
+
+ if (WAE_ERROR_NONE != ret) {
+ LOGGER(ERROR) << "Error during decryption: ";
+ switch (ret) {
+ case WAE_ERROR_INVALID_PARAMETER:
+ LOGGER(ERROR) << "WAE_ERROR_INVALID_PARAMETER";
+ break;
+ case WAE_ERROR_PERMISSION_DENIED:
+ LOGGER(ERROR) << "WAE_ERROR_PERMISSION_DENIED";
+ break;
+ case WAE_ERROR_NO_KEY:
+ LOGGER(ERROR) << "WAE_ERROR_NO_KEY";
+ break;
+ case WAE_ERROR_KEY_MANAGER:
+ LOGGER(ERROR) << "WAE_ERROR_KEY_MANAGER";
+ break;
+ case WAE_ERROR_CRYPTO:
+ LOGGER(ERROR) << "WAE_ERROR_CRYPTO";
+ break;
+ case WAE_ERROR_UNKNOWN:
+ LOGGER(ERROR) << "WAE_ERROR_UNKNOWN";
+ break;
+ default:
+ LOGGER(ERROR) << "UNKNOWN";
+ break;
+ }
+ fclose(src);
+ return path;
+ }
+
+ memcpy(decrypted_str.get() + decrypted_size, decrypted_data,
+ decrypted_len);
+ decrypted_size += decrypted_len;
+ std::free(decrypted_data);
+ }
+ }
+ } while (0 == std::feof(src));
+ fclose(src);
+ memset(decrypted_str.get() + decrypted_size, '\n',
+ file_size - decrypted_size);
+
+ // change to data schem
+ std::stringstream dst_str;
+ std::string content_type = GetMimeFromUri(path);
+ std::string encoded =
+ utils::Base64Encode(decrypted_str.get(), decrypted_size);
+ dst_str << "data:" << content_type << ";base64," << encoded;
+
+ decrypted_str.reset(new unsigned char[file_size]);
+
+ return dst_str.str();
+ }
+ return path;
+}
+
+} // namespace common
--- /dev/null
+/*
+ * Copyright (c) 2015 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef XWALK_COMMON_RESOURCE_MANAGER_H_
+#define XWALK_COMMON_RESOURCE_MANAGER_H_
+
+#include <map>
+#include <memory>
+#include <string>
+
+namespace wgt {
+namespace parse {
+class AppControlInfo;
+} // namespace parse
+} // namespace wgt
+
+namespace common {
+
+class ApplicationData;
+class LocaleManager;
+class AppControl;
+
+class ResourceManager {
+ public:
+ class Resource {
+ public:
+ explicit Resource(const std::string& uri);
+ Resource(const std::string& uri, bool should_reset);
+ Resource(const std::string& uri,
+ const std::string& mime,
+ const std::string& encoding);
+ Resource(const Resource& res);
+ ~Resource() {}
+
+ Resource& operator=(const Resource& res);
+ bool operator==(const Resource& res);
+
+ void set_uri(const std::string& uri) { uri_ = uri; }
+ void set_mime(const std::string& mime) { mime_ = mime; }
+ void set_should_reset(bool should_reset) { should_reset_ = should_reset; }
+ void set_encoding(const std::string& encoding) { encoding_ = encoding; }
+
+ std::string uri() const { return uri_; }
+ std::string mime() const { return mime_; }
+ bool should_reset() const { return should_reset_; }
+ std::string encoding() const { return encoding_; }
+
+ private:
+ std::string uri_;
+ std::string mime_;
+ bool should_reset_;
+ std::string encoding_;
+ };
+
+ ResourceManager(ApplicationData* application_data,
+ LocaleManager* locale_manager);
+ ~ResourceManager() {}
+
+ // input : file:///..... , app://[appid]/....
+ // output : /[system path]/.../locales/.../
+ std::string GetLocalizedPath(const std::string& origin);
+ std::unique_ptr<Resource> GetStartResource(const AppControl* app_control);
+ bool AllowNavigation(const std::string& url);
+ bool AllowedResource(const std::string& url);
+
+ bool IsEncrypted(const std::string& url);
+ std::string DecryptResource(const std::string& path);
+
+ void set_base_resource_path(const std::string& base_path);
+
+ private:
+ std::unique_ptr<Resource> GetMatchedResource(
+ const wgt::parse::AppControlInfo&);
+ std::unique_ptr<Resource> GetDefaultResource();
+
+ // for localization
+ bool Exists(const std::string& path);
+ bool CheckWARP(const std::string& url);
+ bool CheckAllowNavigation(const std::string& url);
+ std::string RemoveLocalePath(const std::string& path);
+
+ std::string resource_base_path_;
+ std::string appid_;
+ std::map<const std::string, bool> file_existed_cache_;
+ std::map<const std::string, std::string> locale_cache_;
+ std::map<const std::string, bool> warp_cache_;
+
+ ApplicationData* application_data_;
+ LocaleManager* locale_manager_;
+ int security_model_version_;
+};
+
+} // namespace common
+
+#endif // XWALK_COMMON_RESOURCE_MANAGER_H_
--- /dev/null
+/*
+ * Copyright (c) 2015 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "common/string_utils.h"
+
+#include <uuid/uuid.h>
+#include <glib.h>
+#include <math.h>
+#include <time.h>
+
+#include <algorithm>
+#include <iomanip>
+#include <memory>
+#include <sstream>
+#include <string>
+#include <vector>
+
+namespace common {
+namespace utils {
+
+std::string GenerateUUID() {
+ char tmp[37];
+ uuid_t uuid;
+ uuid_generate(uuid);
+ uuid_unparse(uuid, tmp);
+ return std::string(tmp);
+}
+
+bool StartsWith(const std::string& str, const std::string& sub) {
+ if (sub.size() > str.size())
+ return false;
+ return std::equal(sub.begin(), sub.end(), str.begin());
+}
+
+bool EndsWith(const std::string& str, const std::string& sub) {
+ if (sub.size() > str.size())
+ return false;
+ return std::equal(sub.rbegin(), sub.rend(), str.rbegin());
+}
+
+std::string ReplaceAll(const std::string& replace,
+ const std::string& from,
+ const std::string& to) {
+ std::string str = replace;
+ size_t pos = str.find(from);
+ while (pos != std::string::npos) {
+ str.replace(pos, from.length(), to);
+ pos = str.find(from, pos + to.length());
+ }
+ return str;
+}
+
+std::string GetCurrentMilliSeconds() {
+ std::ostringstream ss;
+ struct timespec spec;
+ clock_gettime(CLOCK_REALTIME, &spec);
+ ss << (spec.tv_sec % 10000) << "." << std::setw(3) << std::setfill('0')
+ << (round(spec.tv_nsec / 1.0e6));
+ return ss.str();
+}
+
+bool SplitString(const std::string& str,
+ std::string* part_1,
+ std::string* part_2,
+ const char delim) {
+ if (part_1 == nullptr || part_2 == nullptr)
+ return false;
+
+ size_t pos = str.find(delim);
+ if (pos == std::string::npos)
+ return false;
+
+ *part_1 = str.substr(0, pos);
+ *part_2 = str.substr(pos + 1);
+ return true;
+}
+
+std::string UrlDecode(const std::string& url) {
+ std::unique_ptr<char, decltype(std::free)*> decoded_str{
+ g_uri_unescape_string(url.c_str(), NULL), std::free};
+ return decoded_str.get() != nullptr ? std::string(decoded_str.get()) : url;
+}
+
+std::string UrlEncode(const std::string& url) {
+ std::unique_ptr<char, decltype(std::free)*> encoded_str{
+ g_uri_escape_string(url.c_str(), NULL, TRUE), std::free};
+ return encoded_str.get() != nullptr ? std::string(encoded_str.get()) : url;
+}
+
+std::string Base64Encode(const unsigned char* data, size_t len) {
+ gchar* encoded = g_base64_encode(data, len);
+ std::unique_ptr<gchar, decltype(g_free)*> encoded_ptr{encoded, g_free};
+ return std::string(encoded);
+}
+
+} // namespace utils
+} // namespace common
--- /dev/null
+/*
+ * Copyright (c) 2015 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef XWALK_COMMON_STRING_UTILS_H_
+#define XWALK_COMMON_STRING_UTILS_H_
+
+#include <string>
+#include <vector>
+
+namespace common {
+namespace utils {
+
+std::string GenerateUUID();
+bool StartsWith(const std::string& str, const std::string& sub);
+bool EndsWith(const std::string& str, const std::string& sub);
+std::string ReplaceAll(const std::string& replace,
+ const std::string& from,
+ const std::string& to);
+std::string GetCurrentMilliSeconds();
+bool SplitString(const std::string& str,
+ std::string* part_1,
+ std::string* part_2,
+ const char delim);
+std::string UrlEncode(const std::string& url);
+std::string UrlDecode(const std::string& url);
+std::string Base64Encode(const unsigned char* data, size_t len);
+
+} // namespace utils
+} // namespace common
+
+#endif // XWALK_COMMON_STRING_UTILS_H_
--- /dev/null
+/*
+ * Copyright (c) 2015 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "common/url.h"
+
+#include <algorithm>
+#include <stdexcept>
+
+#include "common/logger.h"
+#include "common/string_utils.h"
+
+namespace common {
+
+namespace {
+
+const char* kSchemeTypeFile = "file";
+const char* kSchemeTypeHttp = "http";
+const char* kSchemeTypeHttps = "https";
+const char* kSchemeTypeSsh = "ssh";
+const char* kSchemeTypeFtp = "ftp";
+
+// length of scheme identifier ://
+const int kSchemeIdLen = 3;
+int kPortHttp = 80;
+int kPortHttps = 443;
+int kPortSsh = 22;
+int kPortFtp = 21;
+int kPortDefault = 0;
+
+int GetDefaultPort(const std::string& scheme) {
+ if (scheme == kSchemeTypeHttp)
+ return kPortHttp;
+ else if (scheme == kSchemeTypeHttps)
+ return kPortHttps;
+ else if (scheme == kSchemeTypeSsh)
+ return kPortSsh;
+ else if (scheme == kSchemeTypeFtp)
+ return kPortFtp;
+ else
+ return kPortDefault;
+}
+
+} // namespace
+
+class URLImpl {
+ public:
+ explicit URLImpl(const std::string& url);
+ URLImpl() {}
+
+ std::string url() const { return url_; }
+ std::string scheme() const { return scheme_; }
+ std::string domain() const { return domain_; }
+ int port() const { return port_; }
+ std::string path() const { return path_; }
+
+ private:
+ std::string url_;
+ std::string scheme_;
+ std::string domain_;
+ int port_;
+ std::string path_;
+
+ bool ExtractScheme();
+ void ExtractDomain();
+ void ExtractDomainPort();
+ void ExtractPath();
+};
+
+URLImpl::URLImpl(const std::string& url) : port_(0) {
+ if (url.empty())
+ return;
+
+ url_ = url;
+ if (!ExtractScheme()) {
+ ExtractDomain();
+ ExtractPath();
+ return;
+ }
+
+ if (scheme_ != kSchemeTypeFile)
+ ExtractDomainPort();
+
+ ExtractPath();
+}
+
+bool URLImpl::ExtractScheme() {
+ size_t end_of_scheme = 0;
+ if (url_.find("://") != std::string::npos) {
+ end_of_scheme = url_.find("://");
+ std::string scheme = url_.substr(0, end_of_scheme);
+ std::transform(scheme.begin(), scheme.end(), scheme.begin(), ::tolower);
+ scheme_ = scheme;
+ return true;
+ } else {
+ return false;
+ }
+}
+
+void URLImpl::ExtractDomain() {
+ size_t start_of_domain =
+ scheme_.empty() ? 0 : scheme_.length() + kSchemeIdLen;
+ size_t end_of_domain = url_.find_first_of('/', start_of_domain);
+ size_t at = url_.find_first_of('@', start_of_domain);
+ if (at < end_of_domain) {
+ start_of_domain = at + 1;
+ }
+ domain_ = url_.substr(start_of_domain, end_of_domain == std::string::npos
+ ? std::string::npos
+ : end_of_domain - start_of_domain);
+ LOGGER(INFO) << "Extract Domain is " << domain_;
+}
+
+void URLImpl::ExtractDomainPort() {
+ ExtractDomain();
+ std::string domain = domain_;
+
+ // Decide start position to find port considering IPv6 case
+ size_t start_pos = domain.find('@');
+ start_pos = (start_pos != std::string::npos) ? start_pos + 1 : 0;
+ if (domain[start_pos] == '[')
+ start_pos = domain.find(']', start_pos + 1);
+
+ size_t port_separator =
+ domain.find_first_of(':', start_pos != std::string::npos ? start_pos : 0);
+ if (port_separator != std::string::npos) {
+ domain_ = domain.substr(0, port_separator);
+ std::string port = domain.substr(port_separator + 1);
+ if (port.empty()) {
+ port_ = GetDefaultPort(scheme_);
+ } else {
+ try {
+ port_ = std::stoi(port);
+ } catch (...) {
+ port_ = GetDefaultPort(scheme_);
+ }
+ }
+ } else {
+ domain_ = domain;
+ port_ = GetDefaultPort(scheme_);
+ }
+}
+
+void URLImpl::ExtractPath() {
+ std::string sub_url =
+ url_.substr(scheme_.empty() ? 0 : scheme_.length() + kSchemeIdLen);
+ if (domain_.empty()) {
+ path_ = sub_url;
+ } else {
+ size_t start_of_path = sub_url.find_first_of('/');
+ if (start_of_path != std::string::npos)
+ path_ = sub_url.substr(start_of_path);
+ }
+}
+
+URL::URL(const std::string& url) {
+ impl_ = new URLImpl(url);
+}
+
+std::string URL::url() const {
+ return impl_->url();
+}
+std::string URL::scheme() const {
+ return impl_->scheme();
+}
+std::string URL::domain() const {
+ return impl_->domain();
+}
+int URL::port() const {
+ return impl_->port();
+}
+std::string URL::path() const {
+ return impl_->path();
+}
+
+URL::~URL() {
+ delete impl_;
+}
+
+} // namespace common
--- /dev/null
+/*
+ * Copyright (c) 2015 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef XWALK_COMMON_URL_H_
+#define XWALK_COMMON_URL_H_
+
+#include <string>
+
+namespace common {
+
+class URLImpl;
+
+/*
+ * This class parses a given url based on its scheme type.
+ * The parsed data is stored in different variables depending on the scheme
+ * type.
+ * The following shows the variables which are used for each scheme type:
+ * http:// https:// ssh:// ftp://
+ * => url_, scheme_, domain_, port_, path_
+ * app://
+ * => url_, scheme_, domain_, path_
+ * file://
+ * => url_, scheme_, path_
+ * No Scheme Type
+ * => domain_, path_
+ *
+ * If the url does not have specific data, an empty string will be stored
+ * in the corresponding variables.(RFC 1738)
+ *
+ * ex) http://user:password@www.tizen.org:8080/market/Item?12345
+ * url_ = http://user:password@www.tizen.org:8080/market/Item?12345
+ * scheme_ = http
+ * user_ = user
+ * password_ = password
+ * domain_ = www.tizen.org
+ * port_ = 8080
+ * path_ = /market/Item?12345
+*/
+class URL {
+ public:
+ explicit URL(const std::string& url);
+ ~URL();
+
+ std::string url() const;
+ std::string scheme() const;
+ std::string domain() const;
+ int port() const;
+ std::string path() const;
+
+ private:
+ URLImpl* impl_;
+};
+
+} // namespace common
+
+#endif // XWALK_COMMON_URL_H_