Fix invalid licenses
[platform/framework/web/crosswalk-tizen.git] / src / common / resource_manager.cc
1 /*
2  * Copyright (c) 2015 Samsung Electronics Co., Ltd All Rights Reserved
3  *
4  *    Licensed under the Apache License, Version 2.0 (the "License");
5  *    you may not use this file except in compliance with the License.
6  *    You may obtain a copy of the License at
7  *
8  *        http://www.apache.org/licenses/LICENSE-2.0
9  *
10  *    Unless required by applicable law or agreed to in writing, software
11  *    distributed under the License is distributed on an "AS IS" BASIS,
12  *    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  *    See the License for the specific language governing permissions and
14  *    limitations under the License.
15  */
16
17 #include "common/resource_manager.h"
18
19 #include <stdio.h>
20 #include <aul.h>
21
22 #include <memory>
23 #include <regex>
24 #include <vector>
25
26 #include "common/logger.h"
27 #include "common/file_utils.h"
28 #include "common/string_utils.h"
29 #include "common/app_control.h"
30 #include "common/application_data.h"
31 #include "common/locale_manager.h"
32
33 using wgt::parse::AppControlInfo;
34
35 namespace wrt {
36
37 namespace {
38
39 typedef std::vector<AppControlInfo> AppControlList;
40
41 // Scheme type
42 const char* kSchemeTypeApp = "app://";
43 const char* kSchemeTypeFile = "file://";
44 // TODO(wy80.choi): comment out below unused const variables if needed.
45 // const char* kSchemeTypeHttp = "http://";
46 // const char* kSchemeTypeHttps = "https://";
47 // const char* kSchemeTypeWidget = "widget://";
48
49 // Default Start Files
50 const char* kDefaultStartFiles[] = {
51   "index.htm",
52   "index.html",
53   "index.svg",
54   "index.xhtml",
55   "index.xht"
56 };
57
58 static std::string GetMimeFromUri(const std::string& uri) {
59   // checking passed uri is local file
60   std::string file_uri_case(kSchemeTypeFile);
61   int ret = AUL_R_EINVAL;
62   char mimetype[128] = {0, };
63   size_t pos = std::string::npos;
64   if (utils::StartsWith(uri, file_uri_case)) {
65     // case 1. uri = file:///xxxx
66     ret = aul_get_mime_from_file(uri.substr(pos+file_uri_case.length()).c_str(),
67                                  mimetype, sizeof(mimetype));
68   } else if (utils::StartsWith(uri, "/")) {
69     // case 2. uri = /xxxx
70     ret = aul_get_mime_from_file(uri.c_str(),
71                                  mimetype, sizeof(mimetype));
72   }
73
74   if (ret == AUL_R_OK) {
75     return std::string(mimetype);
76   } else {
77     return std::string();
78   }
79 }
80
81 static bool CompareStringWithWildcard(const std::string& origin,
82                                       const std::string& target) {
83   std::string wildcard_str = utils::ReplaceAll(origin, "*", ".*");
84   try {
85     std::regex re(wildcard_str, std::regex_constants::icase);
86     return std::regex_match(target.begin(), target.end(), re);
87   } catch (std::regex_error& e) {
88     LOGGER(ERROR) << "regex_error caught: " << e.what();
89     return false;
90   }
91 }
92
93 static bool CompareMime(const std::string& origin, const std::string& target) {
94   return CompareStringWithWildcard(origin, target);
95 }
96
97 static bool CompareUri(const std::string& origin_uri,
98                        const std::string& target_uri) {
99   std::string origin_scheme = utils::SchemeName(origin_uri);
100   std::string target_scheme = utils::SchemeName(target_uri);
101
102   if (!origin_scheme.empty() && !target_scheme.empty()) {
103     return (origin_scheme == target_scheme);
104   } else {
105     return CompareStringWithWildcard(origin_uri, target_uri);
106   }
107 }
108
109 static AppControlList::const_iterator CompareMimeAndUri(
110     const AppControlList& operation_list,
111     const std::string& mime, const std::string& uri) {
112   if (mime.empty() && uri.empty()) {
113     // 1. request_mime = "", request_uri = ""
114     for (auto iter = operation_list.begin();
115          iter != operation_list.end(); ++iter) {
116       if (iter->mime().empty() && iter->uri().empty()) {
117         return iter;
118       }
119     }
120   } else if (mime.empty() && !uri.empty()) {
121     // 2.. request_mime = "", request_uri = "blahblah"
122     for (auto iter = operation_list.begin();
123          iter != operation_list.end(); ++iter) {
124       if (iter->mime().empty() && CompareUri(iter->uri(), uri)) {
125         return iter;
126       }
127     }
128   } else if (!mime.empty() && uri.empty()) {
129     // 3... request_mime = "blahblah", request_uri = ""
130     for (auto iter = operation_list.begin();
131          iter != operation_list.end(); ++iter) {
132       if (iter->uri().empty() && CompareMime(iter->mime(), mime)) {
133         return iter;
134       }
135     }
136   } else {
137     // 4... request_mime = "blahblah", request_uri = "blahblah"
138     for (auto iter = operation_list.begin();
139          iter != operation_list.end(); ++iter) {
140       if (CompareMime(iter->mime(), mime) &&
141           CompareUri(iter->uri(), uri)) {
142         return iter;
143       }
144     }
145   }
146   return operation_list.end();
147 }
148
149 static void FindOperations(AppControlList* app_control_list,
150                            const std::string& operation) {
151   auto iter = app_control_list->begin();
152   while (iter != app_control_list->end()) {
153     if (iter->operation() != operation) {
154       app_control_list->erase(iter++);
155     } else {
156       ++iter;
157     }
158   }
159 }
160
161 static std::string InsertPrefixPath(const std::string& start_uri) {
162   if (start_uri.find("://") != std::string::npos) {
163     return start_uri;
164   } else {
165     return std::string() + kSchemeTypeFile + "/" + start_uri;
166   }
167 }
168
169 }  // namespace
170
171 ResourceManager::Resource::Resource(const std::string& uri)
172   : uri_(uri), should_reset_(true) {}
173
174 ResourceManager::Resource::Resource(const std::string& uri,
175                                     const std::string& mime)
176   : uri_(uri), mime_(mime), should_reset_(true) {}
177
178 ResourceManager::Resource::Resource(const std::string& uri,
179                                     const std::string& mime, bool should_reset)
180   : uri_(uri), mime_(mime), should_reset_(should_reset) {}
181
182 ResourceManager::Resource::Resource(const ResourceManager::Resource& res) {
183   *this = res;
184 }
185
186 ResourceManager::Resource& ResourceManager::Resource::operator=(
187     const ResourceManager::Resource& res) {
188   this->uri_ = res.uri();
189   this->mime_ = res.mime();
190   this->should_reset_ = res.should_reset();
191   return *this;
192 }
193
194 bool ResourceManager::Resource::operator==(const Resource& res) {
195   if (this->uri_ == res.uri() && this->mime_ == res.mime()
196      && this->should_reset_ == res.should_reset()) {
197     return true;
198   } else {
199     return false;
200   }
201 }
202
203 ResourceManager::ResourceManager(ApplicationData* application_data,
204                                  LocaleManager* locale_manager)
205     : application_data_(application_data), locale_manager_(locale_manager) {
206   if (application_data != NULL) {
207     appid_ = application_data->tizen_application_info()->id();
208   }
209 }
210
211 std::string ResourceManager::GetDefaultOrEmpty() {
212   std::string default_src;
213
214   // content src
215   auto content_info = application_data_->content_info();
216   if (content_info) {
217     default_src = content_info->src();
218   } else {
219     LOGGER(WARN) << "ContentInfo is NULL.";
220   }
221
222   if (!default_src.empty()) {
223     return InsertPrefixPath(default_src);
224   }
225
226   // if there is no content src, find reserved index files
227   for (auto& start_file : kDefaultStartFiles) {
228     if (utils::Exists(resource_base_path_ + start_file)) {
229       default_src = start_file;
230     }
231   }
232
233   return InsertPrefixPath(default_src);
234 }
235
236 std::string ResourceManager::GetMatchedSrcOrUri(
237     const AppControlInfo& app_control_info) {
238   if (!app_control_info.src().empty()) {
239     return InsertPrefixPath(app_control_info.src());
240   }
241
242   if (!app_control_info.uri().empty()) {
243     return InsertPrefixPath(app_control_info.uri());
244   }
245
246   return GetDefaultOrEmpty();
247 }
248
249 std::unique_ptr<ResourceManager::Resource> ResourceManager::GetStartResource(
250     const AppControl* app_control) {
251   std::string operation = app_control->operation();
252   if (operation.empty()) {
253     LOGGER(ERROR) << "operation(mandatory) is NULL";
254     return std::unique_ptr<Resource>(new Resource(GetDefaultOrEmpty()));
255   }
256
257   std::string mime = app_control->mime();
258   std::string uri = app_control->uri();
259   if (mime.empty() && !uri.empty()) {
260     mime = GetMimeFromUri(uri);
261   }
262
263   LOGGER(DEBUG) << "Passed AppControl data";
264   LOGGER(DEBUG) << " - operation : " << operation;
265   LOGGER(DEBUG) << " - mimetype  : " << mime;
266   LOGGER(DEBUG) << " - uri       : " << uri;
267
268   if (application_data_ == NULL ||
269       application_data_->app_control_info_list() == NULL) {
270     return std::unique_ptr<Resource>(new Resource(GetDefaultOrEmpty()));
271   }
272
273   AppControlList app_control_list =
274     application_data_->app_control_info_list()->controls;
275   FindOperations(&app_control_list, operation);
276
277   if (!app_control_list.empty()) {
278     AppControlList::const_iterator iter =
279       CompareMimeAndUri(app_control_list, mime, uri);
280     if (iter != app_control_list.end()) {
281       // TODO(jh5.cho) : following comment will be added after SRPOL implement
282       return std::unique_ptr<Resource>(
283         new Resource(GetMatchedSrcOrUri(*iter), iter->mime()
284                    /*, iter->should_reset()*/));
285     } else {
286     return std::unique_ptr<Resource>(new Resource(GetDefaultOrEmpty()));
287     }
288   } else {
289     return std::unique_ptr<Resource>(new Resource(GetDefaultOrEmpty()));
290   }
291 }
292
293 std::string ResourceManager::GetLocalizedPath(const std::string& origin) {
294   std::string file_scheme = std::string() + kSchemeTypeFile + "/";
295   std::string app_scheme = std::string() + kSchemeTypeApp;
296   std::string locale_path = "locales/";
297   auto find = locale_cache_.find(origin);
298   if (find != locale_cache_.end()) {
299     return find->second;
300   }
301   std::string& result = locale_cache_[origin];
302   std::string url = origin;
303
304   std::string suffix;
305   size_t pos = url.find_first_of("#?");
306   if (pos != std::string::npos) {
307     suffix = url.substr(pos);
308     url.resize(pos);
309   }
310
311   if (utils::StartsWith(url, app_scheme)) {
312     // remove "app://"
313     url.erase(0, app_scheme.length());
314
315     // remove app id + /
316     std::string check = appid_ + "/";
317     if (utils::StartsWith(url, check)) {
318       url.erase(0, check.length());
319     } else {
320       LOGGER(ERROR) << "Invalid appid";
321       return result;
322     }
323   } else if (utils::StartsWith(url, file_scheme)) {
324     // remove "file:///"
325     url.erase(0, file_scheme.length());
326   }
327
328   if (!url.empty() && url[url.length()-1] == '/') {
329       url.erase(url.length()-1, 1);
330   }
331
332   if (url.empty()) {
333     LOGGER(ERROR) << "URL Localization error";
334     return result;
335   }
336
337   for (auto& locales : locale_manager_->system_locales()) {
338     // check ../locales/
339     std::string app_locale_path = resource_base_path_ + locale_path;
340     if (!Exists(app_locale_path)) {
341       break;
342     }
343     std::string resource_path = app_locale_path + locales + "/" + url;
344     if (Exists(resource_path)) {
345       result = "file://" + resource_path + suffix;
346       return result;
347     }
348   }
349
350   std::string default_locale = resource_base_path_ + url;
351   if (Exists(default_locale)) {
352     result = "file://" + default_locale + suffix;
353     return result;
354   }
355   result = url + suffix;
356   return result;
357 }
358
359 void ResourceManager::set_base_resource_path(const std::string& path) {
360   if (path.empty()) {
361     return;
362   }
363
364   resource_base_path_ = path;
365   if (resource_base_path_[resource_base_path_.length()-1] != '/') {
366     resource_base_path_ += "/";
367   }
368 }
369
370 bool ResourceManager::Exists(const std::string& path) {
371   auto find = file_existed_cache_.find(path);
372   if (find != file_existed_cache_.end()) {
373     return find->second;
374   }
375   bool ret = file_existed_cache_[path] = utils::Exists(path);
376   return ret;
377 }
378
379 }  // namespace wrt