Initialize Tizen 2.3
[framework/web/wrt-installer.git] / src_wearable / configuration_parser / widget_parser.cpp
1 /*
2  * Copyright (c) 2011 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  * This file  have been implemented in compliance with  W3C WARP SPEC.
18  * but there are some patent issue between  W3C WARP SPEC and APPLE.
19  * so if you want to use this file, refer to the README file in root directory
20  */
21 /**
22  * @file        widget_parser.cpp
23  * @author      Lukasz Wrzosek (l.wrzosek@samsung.com)
24  * @version     0.1
25  * @brief
26  */
27
28 #include <widget_parser.h>
29 #include "ignoring_parser.h"
30 #include "deny_all_parser.h"
31 #include <dpl/wrt-dao-ro/config_parser_data.h>
32 #include "libiriwrapper.h"
33 #include "wrt-commons/i18n-dao-ro/i18n_dao_read_only.h"
34 #include <dpl/utils/warp_iri.h>
35 #include <dpl/utils/mime_type_utils.h>
36 #include <language_subtag_rst_tree.h>
37 #include <algorithm>
38 #include <cerrno>
39 #include <climits>
40 #include <cmath>
41 #include <cstdlib>
42 #include <cstdio>
43 #include <functional>
44 #include <locale>
45 #include <memory>
46 #include <string>
47 #include <boost/optional.hpp>
48
49 #include <dpl/foreach.h>
50 #include <dpl/platform.h>
51 #include <dpl/utils/warp_iri.h>
52 #include <dpl/utils/mime_type_utils.h>
53 #include <dpl/wrt-dao-ro/config_parser_data.h>
54 #include <iri.h>
55 #include <pcrecpp.h>
56
57 #include <deny_all_parser.h>
58 #include <ignoring_parser.h>
59 #include <installer_log.h>
60 #include <language_subtag_rst_tree.h>
61 #include <libiriwrapper.h>
62
63 using namespace WrtDB;
64
65 namespace Unicode {
66 static const DPL::String UTF_LRE = L"\x0202a";
67 static const DPL::String UTF_LRO = L"\x0202d";
68 static const DPL::String UTF_RLE = L"\x0202b";
69 static const DPL::String UTF_RLO = L"\x0202e";
70 static const DPL::String UTF_PDF = L"\x0202c";
71
72 Direction ParseDirAttribute(const XmlAttribute& attribute)
73 {
74     Assert(L"dir" == attribute.name);
75     if (L"ltr" == attribute.value) {
76         return LRE;
77     } else if (L"rtl" == attribute.value) {
78         return RLE;
79     } else if (L"lro" == attribute.value) {
80         return LRO;
81     } else if (L"rlo" == attribute.value) {
82         return RLO;
83     } else {
84         _W("dir attribute has wrong value: %ls ", attribute.value.c_str());
85         return EMPTY;
86     }
87 }
88
89 void UpdateTextWithDirectionMark(Direction direction,
90                                  DPL::String* text)
91 {
92     Assert(text);
93     switch (direction) {
94     case RLO:
95         *text = UTF_RLO + *text + UTF_PDF;
96         break;
97     case RLE:
98         *text = UTF_RLE + *text + UTF_PDF;
99         break;
100     case LRE:
101         *text = UTF_LRE + *text + UTF_PDF;
102         break;
103     case LRO:
104         *text = UTF_LRO + *text + UTF_PDF;
105         break;
106     case EMPTY:
107         break;
108     default:
109         Assert(false);
110         break;
111     }
112 }
113 } // namespace Unicode
114
115 class InnerElementsParser : public ElementParser
116 {
117   public:
118     virtual ActionFunc GetElementParser(const DPL::String& /*ns*/,
119                                         const DPL::String& /*name*/)
120     {
121         return std::bind(&InnerElementsParser::Other, this);
122     }
123
124     virtual void Accept(const Element& /*element*/)
125     {}
126
127     virtual void Accept(const Text& text)
128     {
129         if (!m_text) {
130             m_text = text;
131         } else {
132             m_text->value += text.value;
133         }
134     }
135
136     virtual void Accept(const XmlAttribute& attribute)
137     {
138         if (attribute.name == L"dir") {
139             m_textDirection = Unicode::ParseDirAttribute(attribute);
140         }
141     }
142
143     virtual void Verify()
144     {
145         if (!!m_text) {
146             Unicode::UpdateTextWithDirectionMark(m_textDirection,
147                                                  &m_text->value);
148             m_parentParser->Accept(*m_text);
149         }
150     }
151
152     InnerElementsParser(ElementParserPtr parent) :
153         m_parentParser(parent),
154         m_textDirection(Unicode::EMPTY)
155     {}
156
157     ElementParserPtr Other()
158     {
159         return ElementParserPtr(new InnerElementsParser(
160                                     std::static_pointer_cast<ElementParser>(
161                                         shared_from_this())));
162     }
163
164   private:
165     boost::optional<Text> m_text;
166     ElementParserPtr m_parentParser;
167     Unicode::Direction m_textDirection;
168 };
169
170 class NameParser : public ElementParser
171 {
172   public:
173     virtual ActionFunc GetElementParser(const DPL::String& /*ns*/,
174                                         const DPL::String& /*name*/)
175     {
176         return std::bind(&NameParser::Other, this);
177     }
178
179     virtual void Accept(const Element& element)
180     {
181         m_lang = element.lang;
182         m_name = L"";
183     }
184
185     virtual void Accept(const Text& text)
186     {
187         if (!m_name) {
188             m_name = text.value;
189         } else {
190             *m_name += text.value;
191         }
192     }
193
194     virtual void Accept(const XmlAttribute& attribute)
195     {
196         if (attribute.name == L"short") {
197             if (!m_shortName) {
198                 m_shortName = attribute.value;
199             }
200         } else if (attribute.name == L"dir") {
201             m_textDirection = Unicode::ParseDirAttribute(attribute);
202         }
203     }
204
205     virtual void Verify()
206     {
207         ConfigParserData::LocalizedData& data = m_data.localizedDataSet[m_lang];
208         if (!data.name) {
209             NormalizeString(m_name);
210             NormalizeString(m_shortName);
211             if (!!m_name) {
212                 Unicode::UpdateTextWithDirectionMark(m_textDirection, &*m_name);
213             }
214             data.name = m_name;
215             if (!!m_shortName) {
216                 Unicode::UpdateTextWithDirectionMark(m_textDirection,
217                                                      &*m_shortName);
218             }
219             data.shortName = m_shortName;
220         }
221     }
222
223     NameParser(Unicode::Direction direction,
224                ConfigParserData& data) :
225         m_data(data),
226         m_textDirection(direction)
227     {}
228
229     ElementParserPtr Other()
230     {
231         return ElementParserPtr(new InnerElementsParser(
232                                     std::static_pointer_cast<ElementParser>(
233                                         shared_from_this())));
234     }
235
236   private:
237     ConfigParserData& m_data;
238     DPL::OptionalString m_name;
239     DPL::OptionalString m_shortName;
240     DPL::OptionalString m_dir;
241     DPL::String m_lang;
242     Unicode::Direction m_textDirection;
243 };
244
245 class AccessParser : public ElementParser
246 {
247   public:
248     enum StandardType
249     {
250         STANDARD_TYPE_NONE,
251         STANDARD_TYPE_WARP
252     };
253
254     virtual ActionFunc GetElementParser(const DPL::String& /*ns*/,
255                                         const DPL::String& /*name*/)
256     {
257         return std::bind(&AccessParser::Other, this);
258     }
259
260     virtual void Accept(const Element& element)
261     {
262         // for tizen web apps WARP should be used
263         if (element.ns == ConfigurationNamespace::W3CWidgetNamespaceName ||
264             element.ns == ConfigurationNamespace::TizenWebAppNamespaceName)
265         {
266             m_standardType = STANDARD_TYPE_WARP;
267         }
268     }
269
270     virtual void Accept(const Text& /*text*/)
271     {}
272
273     void AcceptWac(const XmlAttribute& attribute)
274     {
275         if (attribute.name == L"origin") {
276             m_strIRIOrigin = attribute.value;
277             NormalizeString(m_strIRIOrigin);
278         } else if (attribute.name == L"subdomains") {
279             DPL::String normalizedValue = attribute.value;
280             NormalizeString(normalizedValue);
281
282             if (normalizedValue == L"true") {
283                 m_bSubDomainAccess = true;
284             } else if (normalizedValue == L"false") {
285                 m_bSubDomainAccess = false;
286             }
287         }
288     }
289
290     virtual void Accept(const XmlAttribute& attribute)
291     {
292         switch (m_standardType) {
293         case STANDARD_TYPE_WARP:
294             AcceptWac(attribute);
295             break;
296         default:
297             _E("Error in Access tag - unknown standard.");
298             break;
299         }
300     }
301
302     void VerifyWac()
303     {
304         WarpIRI iri;
305         iri.set(m_strIRIOrigin, false);
306
307         if (!iri.isAccessDefinition()) {
308             _W("Access list element: %ls is not acceptable by WARP standard and will be ignored!",
309                 m_strIRIOrigin.c_str());
310             return;
311         }
312
313         if(m_strIRIOrigin == L"*") //wildcard match means yes for subdomains
314         {
315             m_bSubDomainAccess = true;
316         }
317
318         ConfigParserData::AccessInfo accessInfo(m_strIRIOrigin,
319                                                 m_bSubDomainAccess);
320         //std::pair <ConfigParserData::AccessInfoSet::iterator, bool> ret =
321         m_data.accessInfoSet.insert(accessInfo);
322     }
323
324     virtual void Verify()
325     {
326         switch (m_standardType) {
327         case STANDARD_TYPE_WARP:
328             VerifyWac();
329             break;
330         default:
331             _E("Error in Access tag - unknown standard.");
332             break;
333         }
334     }
335
336     AccessParser(ConfigParserData& data) :
337         ElementParser(),
338         m_bSubDomainAccess(false),
339         m_standardType(STANDARD_TYPE_NONE),
340         m_network(false),
341         m_data(data)
342     {}
343
344     ElementParserPtr Other()
345     {
346         return ElementParserPtr(new InnerElementsParser(
347                                     ElementParserPtr(shared_from_this())));
348     }
349
350   private:
351     DPL::String m_strIRIOrigin;
352     bool m_bSubDomainAccess;
353     StandardType m_standardType;
354     bool m_network;
355     ConfigParserData& m_data;
356 };
357
358 class DescriptionParser : public ElementParser
359 {
360   public:
361     virtual ActionFunc GetElementParser(const DPL::String& /*ns*/,
362                                         const DPL::String& /*name*/)
363     {
364         return std::bind(&DescriptionParser::Other, this);
365     }
366
367     virtual void Accept(const Element& element)
368     {
369         m_lang = element.lang;
370         m_description = L"";
371     }
372
373     ElementParserPtr Other()
374     {
375         return ElementParserPtr(new InnerElementsParser(
376                                     std::static_pointer_cast<ElementParser>(
377                                         shared_from_this())));
378     }
379
380     virtual void Accept(const Text& text)
381     {
382         if (!m_description) {
383             m_description = text.value;
384         } else {
385             *m_description += text.value;
386         }
387     }
388
389     virtual void Accept(const XmlAttribute& attribute)
390     {
391         if (attribute.name == L"dir") {
392             m_textDirection = Unicode::ParseDirAttribute(attribute);
393         }
394     }
395
396     virtual void Verify()
397     {
398         ConfigParserData::LocalizedData& data = m_data.localizedDataSet[m_lang];
399         if (!data.description) {
400             if (!!m_description) {
401                 Unicode::UpdateTextWithDirectionMark(m_textDirection,
402                                                      &*m_description);
403             }
404             data.description = m_description;
405         }
406     }
407
408     DescriptionParser(Unicode::Direction direction,
409                       ConfigParserData& data) :
410         m_data(data),
411         m_lang(),
412         m_description(),
413         m_textDirection(direction)
414     {}
415
416   private:
417     ConfigParserData& m_data;
418     DPL::String m_lang;
419     DPL::OptionalString m_description;
420     Unicode::Direction m_textDirection;
421 };
422
423 class AuthorParser : public ElementParser
424 {
425   public:
426     virtual ActionFunc GetElementParser(const DPL::String& /*ns*/,
427                                         const DPL::String& /*name*/)
428     {
429         return std::bind(&AuthorParser::Other, this);
430     }
431
432     AuthorParser(Unicode::Direction direction,
433                  ConfigParserData& data) :
434         m_data(data),
435         m_textDirection(direction)
436     {}
437
438     virtual void Accept(const Element& /*element*/)
439     {
440         m_authorName = L"";
441     }
442
443     virtual void Accept(const Text& text)
444     {
445         *(m_authorName) += text.value;
446     }
447
448     virtual void Accept(const XmlAttribute& attribute)
449     {
450         if (attribute.name == L"href") {
451             //Validate href IRI and ignore it if invalid
452             //See also test: ta-argMozRiC-an
453             LibIri::Wrapper iri(DPL::ToUTF8String(attribute.value).c_str());
454             if (iri.Validate()) {
455                 m_authorHref = attribute.value;
456             }
457         } else if (attribute.name == L"email") {
458             m_authorEmail = attribute.value;
459         } else if (attribute.name == L"dir") {
460             m_textDirection = Unicode::ParseDirAttribute(attribute);
461         }
462     }
463
464     virtual void Verify()
465     {
466         if (!m_data.authorName && !m_data.authorHref && !m_data.authorEmail) {
467             NormalizeString(m_authorName);
468             NormalizeString(m_authorHref);
469             NormalizeString(m_authorEmail);
470             if (!!m_authorName) {
471                 Unicode::UpdateTextWithDirectionMark(m_textDirection,
472                                                      &*m_authorName);
473                 m_data.authorName = m_authorName;
474             }
475             if (!!m_authorHref) {
476                 m_data.authorHref = m_authorHref;
477             }
478             if (!!m_authorEmail) {
479                 m_data.authorEmail = m_authorEmail;
480             }
481         }
482     }
483
484     ElementParserPtr Other()
485     {
486         return ElementParserPtr(new InnerElementsParser(
487                                     std::static_pointer_cast<ElementParser>(
488                                         shared_from_this())));
489     }
490
491   private:
492     ConfigParserData& m_data;
493     DPL::OptionalString m_authorEmail;
494     DPL::OptionalString m_authorHref;
495     DPL::OptionalString m_authorName;
496     Unicode::Direction m_textDirection;
497 };
498
499 class LicenseParser : public ElementParser
500 {
501   public:
502     virtual ActionFunc GetElementParser(const DPL::String& /*ns*/,
503                                         const DPL::String& /*name*/)
504     {
505         return std::bind(&LicenseParser::Other, this);
506     }
507
508     LicenseParser(Unicode::Direction direction,
509                   ConfigParserData& data) :
510         m_data(data),
511         m_ignore(true),
512         m_textDirection(direction)
513     {}
514
515     virtual void Accept(const Element& element)
516     {
517         if (!m_license) {
518             m_lang = element.lang;
519             m_license = L"";
520             m_ignore = false;
521         }
522     }
523
524     virtual void Accept(const Text& text)
525     {
526         if (!m_ignore) {
527             *m_license += text.value;
528         }
529     }
530
531     virtual void Accept(const XmlAttribute& attribute)
532     {
533         if (!m_ignore) {
534             if (attribute.name == L"href" && !m_licenseHref) {
535                 m_licenseHref = attribute.value;
536             } else if (attribute.name == L"file" && !m_licenseFile) {
537                 m_licenseFile = attribute.value;
538             } else if (attribute.name == L"dir") {
539                 m_textDirection = Unicode::ParseDirAttribute(attribute);
540             }
541         }
542     }
543
544     virtual void Verify()
545     {
546         ConfigParserData::LocalizedData& data = m_data.localizedDataSet[m_lang];
547         if (!data.license) {
548             if (!!m_license) {
549                 Unicode::UpdateTextWithDirectionMark(m_textDirection,
550                                                      &*m_license);
551             }
552             data.license = m_license;
553             data.licenseHref = m_licenseHref;
554             data.licenseFile = m_licenseFile;
555         }
556     }
557
558     ElementParserPtr Other()
559     {
560         return ElementParserPtr(new InnerElementsParser(
561                                     ElementParserPtr(shared_from_this())));
562     }
563
564   private:
565     ConfigParserData& m_data;
566     DPL::String m_lang;
567     bool m_ignore;
568
569     DPL::OptionalString m_license;
570     DPL::OptionalString m_licenseFile;
571     DPL::OptionalString m_licenseHref;
572     Unicode::Direction m_textDirection;
573 };
574
575 class IconParser : public ElementParser
576 {
577     DECLARE_EXCEPTION_TYPE(ElementParser::Exception::ParseError, BadSrcError)
578
579   public:
580     virtual ActionFunc GetElementParser(const DPL::String& /*ns*/,
581                                         const DPL::String& /*name*/)
582     {
583         return &IgnoringParser::Create; //ignore unknown according to w3c
584     }
585
586     IconParser(ConfigParserData& data) : ElementParser(),
587         m_data(data), m_isSmall(false)
588     {}
589
590     IconParser(ConfigParserData& data, bool isSmall) : ElementParser(),
591         m_data(data), m_isSmall(isSmall)
592     {}
593
594     virtual void Accept(const Element& /*element*/) { }
595
596     virtual void Accept(const XmlAttribute& attribute)
597     {
598         if (attribute.name == L"src") {
599             if (attribute.value.size() > 0) {
600                 m_src = attribute.value;
601             }
602         } else if (attribute.name == L"width") {
603             m_width = ParseSizeAttributeValue(attribute.value);
604         } else if (attribute.name == L"height") {
605             m_height = ParseSizeAttributeValue(attribute.value);
606         }
607     }
608
609     virtual void Accept(const Text& /*text*/)
610     {
611         ThrowMsg(Exception::ParseError, "Icon element must be empty");
612     }
613
614     virtual void Verify()
615     {
616         if (!m_src) {
617             _W("src attribute of icon element is mandatory - ignoring");
618             return;
619         }
620
621         Try
622         {
623             ConfigParserData::Icon icon(delocalizeSrcPath(*m_src));
624             icon.width = m_width;
625             icon.height = m_height;
626             icon.isSmall = m_isSmall;
627
628             ConfigParserData::IconsList::iterator it = std::find(
629                     m_data.iconsList.begin(), m_data.iconsList.end(), icon);
630             if (it == m_data.iconsList.end()) {
631                 m_data.iconsList.push_front(icon);
632             }
633         }
634         Catch(BadSrcError)
635         {
636             _W("src attribute is invalid: %ls", (*m_src).c_str());
637         }
638     }
639
640   private:
641     ConfigParserData& m_data;
642     DPL::OptionalString m_src;
643     DPL::OptionalInt m_width;
644     DPL::OptionalInt m_height;
645     bool m_isSmall;
646
647     static DPL::OptionalInt ParseSizeAttributeValue(const DPL::String& value)
648     {
649         DPL::OptionalString normalizedValue = value;
650         NormalizeString(normalizedValue);
651         if (!(*normalizedValue).empty()) {
652             char* reterr = NULL;
653             errno = 0;
654             long int valueInt =
655                 strtol(DPL::ToUTF8String(value).c_str(), &reterr, 10);
656             if (errno != 0 ||
657                 std::string(reterr) == DPL::ToUTF8String(value) ||
658                 valueInt <= 0)
659             {
660                 return DPL::OptionalInt();
661             } else {
662                 return valueInt;
663             }
664         }
665         return DPL::OptionalInt();
666     }
667
668     /**
669      * @brief delocalizePath removes locales folder from relative path if
670      * neccessary
671      * @param source source string
672      *
673      * @throw BadSrcError if string is bad value of src attribute
674      *
675      * @return corrected string
676      */
677     static DPL::String delocalizeSrcPath(const DPL::String & source)
678     {
679         static const DPL::String localeFolder(L"locales/");
680         static const int index = localeFolder.size();
681
682         DPL::String result = source;
683
684         if (source.substr(0, index) == localeFolder) {
685             size_t pos = result.find_first_of('/', index);
686             if (pos != std::string::npos && pos + 1 < source.size()) {
687                 result = result.substr(pos + 1, source.size());
688             } else {
689                 Throw(BadSrcError);
690             }
691         }
692         return result;
693     }
694 };
695
696 class ContentParser : public ElementParser
697 {
698   public:
699     virtual ActionFunc GetElementParser(const DPL::String& /*ns*/,
700                                         const DPL::String& /*name*/)
701     {
702         return &IgnoringParser::Create; //ignore unknown according to w3c
703     }
704
705     ContentParser(ConfigParserData& data) :
706         ElementParser(),
707         m_data(data)
708     {}
709
710     virtual void Accept(const Element& element)
711     {
712         m_namespace = element.ns;
713     }
714
715     virtual void Accept(const Text& /*text*/)
716     {}
717
718     virtual void Accept(const XmlAttribute& attribute)
719     {
720         DPL::String value = attribute.value;
721         NormalizeString(value);
722
723         if (attribute.name == L"src") {
724             m_src = value;
725         } else if (attribute.name == L"type") {
726             m_type = value;
727             MimeTypeUtils::MimeAttributes mimeAttributes =
728                 MimeTypeUtils::getMimeAttributes(value);
729             if ((mimeAttributes.count(L"charset") > 0) && !m_encoding)
730             {
731                 m_encoding = mimeAttributes[L"charset"];
732             }
733         } else if (attribute.name == L"encoding") {
734             if (!value.empty()) {
735                 m_encoding = value;
736             }
737         }
738     }
739
740     virtual void Verify()
741     {
742         if(!!m_data.startFileEncountered)
743         {
744             if(m_data.startFileNamespace == m_namespace
745                 || m_namespace != ConfigurationNamespace::TizenWebAppNamespaceName)
746             {
747                 return;
748             }
749             //else continue -> if previous item was not in tizen namespace
750         }
751
752         m_data.startFileEncountered = true;
753         m_data.startFileNamespace = m_namespace;
754
755         if (m_namespace == ConfigurationNamespace::TizenWebAppNamespaceName &&
756                 (!m_src || m_src->empty())) {
757             ThrowMsg(Exception::ParseError, "content element must have correct src element");
758         }
759
760         if (!!m_src) {
761             m_data.startFile = m_src;
762             m_data.startFileContentType = m_type;
763             if (!!m_encoding) {
764                 m_data.startFileEncoding = m_encoding;
765             } else {
766                 m_data.startFileEncoding = L"UTF-8";
767             }
768         }
769     }
770
771   private:
772     DPL::OptionalString m_src;
773     DPL::OptionalString m_type;
774     DPL::OptionalString m_encoding;
775     ConfigParserData& m_data;
776     DPL::String m_namespace;
777 };
778
779 class PreferenceParser : public ElementParser
780 {
781   public:
782     virtual ActionFunc GetElementParser(const DPL::String& /*ns*/,
783                                         const DPL::String& /*name*/)
784     {
785         return &IgnoringParser::Create; //ignore unknown according to w3c
786     }
787
788     virtual void Accept(const XmlAttribute& attribute)
789     {
790         if (attribute.name == L"name") {
791             m_name = attribute.value;
792         } else if (attribute.name == L"value") {
793             m_value = attribute.value;
794         } else if (attribute.name == L"readonly") {
795             if (attribute.value == L"true") {
796                 m_required = true;
797             } else {
798                 m_required = false;
799             }
800         }
801     }
802
803     virtual void Accept(const Element& /*element*/)
804     {}
805
806     virtual void Accept(const Text& /*text*/)
807     {
808         ThrowMsg(Exception::ParseError, "param element must be empty");
809     }
810
811     virtual void Verify()
812     {
813         if (!m_name) {
814             _W("preference element must have name attribute");
815             return;
816         }
817         NormalizeString(m_name);
818         NormalizeString(m_value);
819         ConfigParserData::Preference preference(*m_name, m_required);
820         preference.value = m_value;
821         if (m_data.preferencesList.find(preference) ==
822             m_data.preferencesList.end())
823         {
824             m_data.preferencesList.insert(preference);
825         }
826     }
827
828     PreferenceParser(ConfigParserData& data) :
829         ElementParser(),
830         m_required(false),
831         m_data(data)
832     {}
833
834   private:
835     DPL::OptionalString m_name;
836     DPL::OptionalString m_value;
837     bool m_required;
838     ConfigParserData& m_data;
839 };
840
841 class SettingParser : public ElementParser
842 {
843   public:
844     virtual ActionFunc GetElementParser(const DPL::String& /*ns*/,
845                                         const DPL::String& /*name*/)
846     {
847         return &IgnoringParser::Create; //ignore unknown according to w3c
848     }
849
850     virtual void Accept(const Text& /*text*/)
851     {}
852
853     virtual void Accept(const Element& /*element*/)
854     {}
855
856     virtual void Accept(const XmlAttribute& attribute)
857     {
858         m_setting.m_name = attribute.name;
859         m_setting.m_value = attribute.value;
860         m_data.settingsList.insert(m_setting);
861     }
862
863     virtual void Verify()
864     {}
865
866     SettingParser(ConfigParserData& data) :
867         ElementParser(),
868         m_data(data),
869         m_setting(L"", L"")
870     {}
871
872   private:
873     ConfigParserData& m_data;
874     ConfigParserData::Setting m_setting;
875 };
876
877 class AppControlParser : public ElementParser
878 {
879   public:
880     struct SourceParser : public ElementParser
881     {
882       public:
883         virtual ActionFunc GetElementParser(const DPL::String& /*ns*/,
884                                             const DPL::String& /*name*/)
885         {
886             return &IgnoringParser::Create; //ignore unknown according to w3c
887         }
888
889         virtual void Accept(const Text& /*text*/)
890         {}
891
892         virtual void Accept(const Element& /*element*/)
893         {}
894
895         virtual void Accept(const XmlAttribute& attribute)
896         {
897             if (attribute.name == L"name") {
898                 if (attribute.value.size() > 0) {
899                     m_value = attribute.value;
900                     NormalizeString(m_value);
901                 }
902             }
903         }
904
905         virtual void Verify()
906         {
907             if (!m_value || *m_value == L"") {
908                 return;
909             }
910
911             m_data.m_src = *m_value;
912         }
913
914         SourceParser(ConfigParserData::AppControlInfo& data) :
915             ElementParser(),
916             m_properNamespace(false),
917             m_data(data)
918         {}
919
920       private:
921         bool m_properNamespace;
922         DPL::OptionalString m_value;
923         ConfigParserData::AppControlInfo& m_data;
924     };
925
926     struct OperationParser : public ElementParser
927     {
928       public:
929         virtual ActionFunc GetElementParser(const DPL::String& /*ns*/,
930                                             const DPL::String& /*name*/)
931         {
932             return &IgnoringParser::Create; //ignore unknown according to w3c
933         }
934
935         virtual void Accept(const Text& /*text*/)
936         {}
937
938         virtual void Accept(const Element& /*element*/)
939         {}
940
941         virtual void Accept(const XmlAttribute& attribute)
942         {
943             if (attribute.name == L"name") {
944                 if (attribute.value.size() > 0) {
945                     m_value = attribute.value;
946                     NormalizeString(m_value);
947                 }
948             }
949         }
950
951         virtual void Verify()
952         {
953             if (!m_value || *m_value == L"") {
954                 return;
955             }
956
957             m_data.m_operation = *m_value;
958         }
959
960         OperationParser(ConfigParserData::AppControlInfo& data) :
961             ElementParser(),
962             m_properNamespace(false),
963             m_data(data)
964         {}
965
966       private:
967         bool m_properNamespace;
968         DPL::OptionalString m_value;
969         ConfigParserData::AppControlInfo& m_data;
970     };
971
972     struct UriParser : public ElementParser
973     {
974       public:
975         virtual ActionFunc GetElementParser(const DPL::String& /*ns*/,
976                                             const DPL::String& /*name*/)
977         {
978             return &IgnoringParser::Create; //ignore unknown according to w3c
979         }
980
981         virtual void Accept(const Text& /*text*/)
982         {}
983
984         virtual void Accept(const Element& /*element*/)
985         {}
986
987         virtual void Accept(const XmlAttribute& attribute)
988         {
989             if (attribute.name == L"name") {
990                 if (attribute.value.size() > 0) {
991                     m_value = attribute.value;
992                     NormalizeString(m_value);
993                 }
994             }
995         }
996
997         virtual void Verify()
998         {
999             // exception
1000             DPL::String ignoreUri(L"file");
1001
1002             if (!!m_value && *m_value == ignoreUri)
1003             {
1004                 _D("exception : '%ls' scheme will be ignored.", (*m_value).c_str());
1005                 m_value = DPL::OptionalString();
1006             }
1007
1008             if (!m_value || *m_value == L"") {
1009                 return;
1010             }
1011
1012             DPL::String wildString(L"*/*");
1013             if ((m_data.m_uriList.find(wildString) == m_data.m_uriList.end())
1014                 && (m_data.m_uriList.find(*m_value) == m_data.m_uriList.end()))
1015             {
1016                 m_data.m_uriList.insert(*m_value);
1017             } else {
1018                 _D("Ignoring uri with name %ls", (*m_value).c_str());
1019             }
1020         }
1021
1022         UriParser(ConfigParserData::AppControlInfo& data) :
1023             ElementParser(),
1024             m_properNamespace(false),
1025             m_data(data)
1026         {}
1027
1028       private:
1029         bool m_properNamespace;
1030         DPL::OptionalString m_value;
1031         ConfigParserData::AppControlInfo& m_data;
1032     };
1033
1034     struct MimeParser : public ElementParser
1035     {
1036       public:
1037         virtual ActionFunc GetElementParser(const DPL::String& /*ns*/,
1038                                             const DPL::String& /*name*/)
1039         {
1040             return &IgnoringParser::Create; //ignore unknown according to w3c
1041         }
1042
1043         virtual void Accept(const Text& /*text*/)
1044         {}
1045
1046         virtual void Accept(const Element& /*element*/)
1047         {}
1048
1049         virtual void Accept(const XmlAttribute& attribute)
1050         {
1051             if (attribute.name == L"name") {
1052                 if (attribute.value.size() > 0) {
1053                     m_value = attribute.value;
1054                     NormalizeString(m_value);
1055                 }
1056             }
1057         }
1058
1059         virtual void Verify()
1060         {
1061             if (!m_value || *m_value == L"") {
1062                 return;
1063             }
1064
1065             DPL::String wildString(L"*/*");
1066             if ((m_data.m_mimeList.find(wildString) ==
1067                  m_data.m_mimeList.end())
1068                 && (m_data.m_mimeList.find(*m_value) ==
1069                     m_data.m_mimeList.end()))
1070             {
1071                 m_data.m_mimeList.insert(*m_value);
1072             } else {
1073                 _D("Ignoring mime with name %ls", (*m_value).c_str());
1074             }
1075         }
1076
1077         MimeParser(ConfigParserData::AppControlInfo& data) :
1078             ElementParser(),
1079             m_properNamespace(false),
1080             m_data(data)
1081         {}
1082
1083       private:
1084         bool m_properNamespace;
1085         DPL::OptionalString m_value;
1086         ConfigParserData::AppControlInfo& m_data;
1087     };
1088
1089     struct DispositionParser : public ElementParser
1090     {
1091       public:
1092         virtual ActionFunc GetElementParser(const DPL::String& /*ns*/,
1093                                             const DPL::String& /*name*/)
1094         {
1095             return &IgnoringParser::Create;
1096         }
1097
1098         virtual void Accept(const Text& /*text*/)
1099         {}
1100
1101         virtual void Accept(const Element& /*element*/)
1102         {}
1103
1104         virtual void Accept(const XmlAttribute& attribute)
1105         {
1106             if (attribute.name == L"name") {
1107                 if (attribute.value.size() > 0) {
1108                     m_value = attribute.value;
1109                     NormalizeString(m_value);
1110                 }
1111             }
1112         }
1113
1114         virtual void Verify()
1115         {
1116             if (!m_value || *m_value == L"") {
1117                 return;
1118             }
1119
1120             DPL::String windowString(L"window");
1121             DPL::String inlineString(L"inline");
1122
1123             if (*m_value == L"window") {
1124                 m_data.m_disposition =
1125                     ConfigParserData::AppControlInfo::Disposition::WINDOW;
1126             } else if (*m_value == L"inline") {
1127                 m_data.m_disposition =
1128                     ConfigParserData::AppControlInfo::Disposition::INLINE;
1129             } else {
1130                 _D("Ignoring dispostion value %ls", (*m_value).c_str());
1131             }
1132         }
1133
1134         DispositionParser(ConfigParserData::AppControlInfo& data) :
1135             ElementParser(),
1136             m_properNamespace(false),
1137             m_data(data)
1138         {}
1139
1140       private:
1141         bool m_properNamespace;
1142         DPL::OptionalString m_value;
1143         ConfigParserData::AppControlInfo& m_data;
1144     };
1145
1146     virtual ActionFunc GetElementParser(const DPL::String& /*ns*/,
1147                                         const DPL::String& name)
1148     {
1149         if (name == L"src") {
1150             return std::bind(&AppControlParser::OnSourceElement, this);
1151         } else if (name == L"operation") {
1152             return std::bind(&AppControlParser::OnOperationElement, this);
1153         } else if (name == L"uri") {
1154             return std::bind(&AppControlParser::OnUriElement, this);
1155         } else if (name == L"mime") {
1156             return std::bind(&AppControlParser::OnMimeElement, this);
1157         } else if (name == L"disposition") {
1158             return std::bind(&AppControlParser::OnDispositionElement, this);
1159         } else {
1160             return &IgnoringParser::Create; //ignore unknown according to w3c
1161         }
1162     }
1163
1164     virtual void Accept(const XmlAttribute& /*attribute*/)
1165     {}
1166
1167     virtual void Accept(const Element& element)
1168     {
1169         _W("namespace for app service = %ls", element.ns.c_str());
1170         if (element.ns == ConfigurationNamespace::W3CWidgetNamespaceName) {
1171             ThrowMsg(Exception::ParseError,
1172                      "Wrong xml namespace for widget element");
1173         }
1174     }
1175
1176     virtual void Accept(const Text& /*text*/)
1177     {
1178         ThrowMsg(Exception::ParseError, "param element must be empty");
1179     }
1180
1181     virtual void Verify()
1182     {
1183         if (m_appControl.m_src == L"") {
1184             ThrowMsg(Exception::ParseError, "service element must have src element");
1185         }
1186
1187         if (m_appControl.m_operation == L"") {
1188             ThrowMsg(Exception::ParseError, "service element must have operation element");
1189         }
1190
1191         auto res = std::find(m_data.appControlList.begin(), m_data.appControlList.end(), m_appControl);
1192         if(res != m_data.appControlList.end()) {
1193             ThrowMsg(Exception::ParseError, "service element must be unique");
1194         }
1195
1196 #ifdef NFC_EXCEPTION_HANDLING_FOR_TIZEN_2_2_ONLY
1197         // XXX This feature should be retained to Tizen 2.2 only.
1198         // NFC exception handling which was requested from Tizen Device API team.
1199
1200         const DPL::String exceptionNfcOperation =
1201                        L"http://tizen.org/appcontrol/operation/nfc/transaction";
1202         const DPL::String exceptionNfcUri  = L"nfc://secure/aid/";
1203         const DPL::String divertingNfcUri1 = L"nfc://secure/SIM1/aid/";
1204         const DPL::String divertingNfcUri2 = L"nfc://secure/eSE/aid/";
1205
1206         if (m_appControl.m_operation == exceptionNfcOperation
1207             && m_appControl.m_mimeList.empty()
1208             && m_appControl.m_uriList.size() == 1
1209             && (m_appControl.m_uriList.begin())->compare(0, exceptionNfcUri.length(), exceptionNfcUri) == 0)
1210         {
1211             DPL::String originalUri = *m_appControl.m_uriList.begin();
1212             DPL::String newUri = originalUri;
1213
1214             newUri.replace(0, exceptionNfcUri.length(), divertingNfcUri1);
1215             m_appControl.m_uriList.erase(m_appControl.m_uriList.begin());
1216             m_appControl.m_uriList.insert(newUri);
1217             m_data.appControlList.push_back(m_appControl);
1218             _D("NFC exception : %ls -> %ls", originalUri.c_str(), newUri.c_str());
1219
1220             newUri = originalUri;
1221             newUri.replace(0, exceptionNfcUri.length(), divertingNfcUri2);
1222             m_appControl.m_uriList.erase(m_appControl.m_uriList.begin());
1223             m_appControl.m_uriList.insert(newUri);
1224             m_data.appControlList.push_back(m_appControl);
1225             _D("NFC exception : %ls -> %ls", originalUri.c_str(), newUri.c_str());
1226
1227             return;
1228         }
1229 #endif // NFC_EXCEPTION_HANDLING_FOR_TIZEN_2_2_ONLY
1230
1231         m_data.appControlList.push_back(m_appControl);
1232     }
1233
1234     ElementParserPtr OnSourceElement()
1235     {
1236         return ElementParserPtr(new SourceParser(m_appControl));
1237     }
1238
1239     ElementParserPtr OnOperationElement()
1240     {
1241         return ElementParserPtr(new OperationParser(m_appControl));
1242     }
1243
1244     ElementParserPtr OnUriElement()
1245     {
1246         return ElementParserPtr(new UriParser(m_appControl));
1247     }
1248
1249     ElementParserPtr OnMimeElement()
1250     {
1251         return ElementParserPtr(new MimeParser(m_appControl));
1252     }
1253
1254     ElementParserPtr OnDispositionElement()
1255     {
1256         return ElementParserPtr(new DispositionParser(m_appControl));
1257     }
1258
1259     AppControlParser(ConfigParserData& data) :
1260         ElementParser(),
1261         m_data(data),
1262         m_appControl(L"")
1263     {}
1264
1265   private:
1266     ConfigParserData& m_data;
1267     ConfigParserData::AppControlInfo m_appControl;
1268 };
1269
1270 class ApplicationParser : public ElementParser
1271 {
1272   public:
1273     virtual ActionFunc GetElementParser(const DPL::String& /*ns*/,
1274                                         const DPL::String& /*name*/)
1275     {
1276         return &IgnoringParser::Create; //ignore unknown according to w3c
1277     }
1278
1279     virtual void Accept(const Text& /*text*/)
1280     {
1281         if (m_properNamespace) {
1282             ThrowMsg(Exception::ParseError, "application element must be empty");
1283         }
1284     }
1285
1286     virtual void Accept(const Element& element)
1287     {
1288         if (element.ns ==
1289             ConfigurationNamespace::TizenWebAppNamespaceName)
1290         {
1291             m_properNamespace = true;
1292         }
1293     }
1294
1295     virtual void Accept(const XmlAttribute& attribute)
1296     {
1297         if (m_properNamespace) {
1298             if (attribute.name == L"id") {
1299                 m_id = attribute.value;
1300                 NormalizeAndTrimSpaceString(m_id);
1301             } else if (attribute.name == L"package") {
1302                 m_package = attribute.value;
1303             } else if (attribute.name == L"required_version") {
1304                 m_version = attribute.value;
1305                 NormalizeString(m_version);
1306             } else {
1307                 ThrowMsg(Exception::ParseError,
1308                          "unknown attribute '" +
1309                          DPL::ToUTF8String(attribute.name) +
1310                          "' in application element");
1311             }
1312         }
1313     }
1314
1315     virtual void Verify()
1316     {
1317         if(m_data.didFoundTizenApplicationElement)
1318         {
1319             ThrowMsg(Exception::ParseError, "tizen:application element must occur only once");
1320         }
1321         m_data.didFoundTizenApplicationElement = true;
1322
1323         VerifyIdAndPackage();
1324         VerifyVersion();
1325     }
1326
1327     ApplicationParser(ConfigParserData& data) :
1328         ElementParser(),
1329         m_data(data),
1330         m_id(DPL::OptionalString()),
1331         m_version(DPL::OptionalString()),
1332         m_properNamespace(false)
1333     {}
1334
1335     static const char* const REGEXP_ID;
1336
1337   private:
1338     void VerifyIdAndPackage()
1339     {
1340         if (!m_package)
1341         {
1342             ThrowMsg(Exception::ParseError,
1343                      "application element must have package attribute");
1344         }
1345         else
1346         {
1347             pcrecpp::RE re(REGEXP_PACKAGE);
1348             if (!re.FullMatch(DPL::ToUTF8String(*m_package)))
1349             {
1350                 ThrowMsg(Exception::ParseError,
1351                          "invalid format of package attribute");
1352             }
1353         }
1354
1355         if (!m_id) {
1356             ThrowMsg(Exception::ParseError,
1357                      "application element must have id attribute");
1358         }
1359         else
1360         {
1361             std::string package;
1362             pcrecpp::RE re(REGEXP_ID);
1363             if (!re.FullMatch(DPL::ToUTF8String(*m_id), &package))
1364             {
1365                 ThrowMsg(Exception::ParseError,
1366                          "invalid format of id attribute");
1367             }
1368             if (package != DPL::ToUTF8String(*m_package))
1369             {
1370                 ThrowMsg(Exception::ParseError,
1371                          "invalid package prefix in id attribute");
1372             }
1373         }
1374
1375         m_data.tizenAppId = m_id;
1376         m_data.tizenPkgId = m_package;
1377     }
1378
1379     void VerifyVersion()
1380     {
1381         if (!m_version)
1382         {
1383             ThrowMsg(Exception::ParseError,
1384                      "application element must have required_version attribute");
1385         }
1386         else
1387         {
1388             pcrecpp::RE re(REGEXP_VERSION);
1389             if (!re.FullMatch(DPL::ToUTF8String(*m_version)))
1390             {
1391                 ThrowMsg(Exception::ParseError,
1392                          "invalid format of version attribute");
1393             }
1394         }
1395
1396         m_data.tizenMinVersionRequired = m_version;
1397     }
1398
1399     static const char* const REGEXP_PACKAGE;
1400     static const char* const REGEXP_VERSION;
1401
1402     ConfigParserData& m_data;
1403     DPL::OptionalString m_id;
1404     DPL::OptionalString m_package;
1405     DPL::OptionalString m_version;
1406     bool m_properNamespace;
1407 };
1408
1409 const char* const ApplicationParser::REGEXP_PACKAGE = "[0-9A-Za-z]{10}";
1410 const char* const ApplicationParser::REGEXP_ID = "([0-9A-Za-z]{10})\\.[0-9A-Za-z]{1,52}";
1411 const char* const ApplicationParser::REGEXP_VERSION = "\\d+\\.\\d+(\\.\\d+)*";
1412
1413 class SplashParser : public ElementParser
1414 {
1415   public:
1416     virtual ActionFunc GetElementParser(const DPL::String& /*ns*/,
1417                                         const DPL::String& /*name*/)
1418     {
1419         return &IgnoringParser::Create; //ignore unknown according to w3c
1420     }
1421
1422     virtual void Accept(const XmlAttribute& attribute)
1423     {
1424         if (m_properNamespace)
1425         {
1426             if (attribute.name == L"src") {
1427                 if (attribute.value.size() > 0) {
1428                     m_src = attribute.value;
1429                 }
1430             }
1431         }
1432     }
1433
1434     virtual void Accept(const Element& element)
1435     {
1436         if (element.ns ==
1437             ConfigurationNamespace::TizenWebAppNamespaceName)
1438         {
1439             m_properNamespace = true;
1440         }
1441     }
1442
1443     virtual void Accept(const Text& /*text*/)
1444     {}
1445
1446     virtual void Verify()
1447     {
1448         if (!m_src)
1449         {
1450             _W("src attribute of splash element is mandatory - ignoring");
1451             return;
1452         }
1453
1454         m_data.splashImgSrc = m_src;
1455     }
1456
1457     SplashParser(ConfigParserData& data) :
1458         ElementParser(),
1459         m_data(data),
1460         m_properNamespace(false)
1461     {}
1462
1463   private:
1464     DPL::OptionalString m_src;
1465     ConfigParserData& m_data;
1466     bool m_properNamespace;
1467 };
1468
1469 class BackgroundParser : public ElementParser
1470 {
1471   public:
1472     virtual ActionFunc GetElementParser(const DPL::String& /*ns*/,
1473                                         const DPL::String& /*name*/)
1474     {
1475         return &IgnoringParser::Create; //ignore unknown according to w3c
1476     }
1477
1478     virtual void Accept(const XmlAttribute& attribute)
1479     {
1480         if (attribute.name == L"src") {
1481             if (attribute.value.size() > 0) {
1482                 m_src = attribute.value;
1483             }
1484         }
1485     }
1486
1487     virtual void Accept(const Element& /*element*/)
1488     {}
1489
1490     virtual void Accept(const Text& /*text*/)
1491     {}
1492
1493     virtual void Verify()
1494     {
1495         if (!m_src) {
1496             _W("src attribute of background element is mandatory - ignoring");
1497             return;
1498         }
1499
1500         m_data.backgroundPage = m_src;
1501     }
1502
1503     explicit BackgroundParser(ConfigParserData& data) :
1504         m_data(data)
1505     {}
1506
1507   private:
1508     DPL::OptionalString m_src;
1509     ConfigParserData& m_data;
1510 };
1511
1512 class PrivilegeParser : public ElementParser
1513 {
1514   public:
1515     virtual ActionFunc GetElementParser(const DPL::String& /*ns*/,
1516                                         const DPL::String& /*name*/)
1517     {
1518         return &IgnoringParser::Create; //ignore unknown according to w3c
1519     }
1520
1521     virtual void Accept(const Text& /*text*/)
1522     {}
1523
1524     virtual void Accept(const Element& element)
1525     {
1526         if (element.ns ==
1527             ConfigurationNamespace::TizenWebAppNamespaceName)
1528         {
1529             m_properNamespace = true;
1530         }
1531         _D("element");
1532     }
1533
1534     virtual void Accept(const XmlAttribute& attribute)
1535     {
1536         if (m_properNamespace) {
1537             if (attribute.name == L"name") {
1538                 m_feature.name = attribute.value;
1539                 m_privilege.name = attribute.value;
1540             }
1541         }
1542     }
1543
1544     virtual void Verify()
1545     {
1546         LibIri::Wrapper iri(DPL::ToUTF8String(m_feature.name).c_str());
1547
1548         if (m_feature.name != L"") {
1549             if (iri.Validate()) {
1550                 if (m_data.featuresList.find(m_feature) ==
1551                     m_data.featuresList.end())
1552                 {
1553                     m_data.featuresList.insert(m_feature);
1554                 } else {
1555                     _D("Ignoring feature with name %ls", m_feature.name.c_str());
1556                 }
1557             }
1558         }
1559
1560         LibIri::Wrapper iriPrivilege(
1561             DPL::ToUTF8String(m_privilege.name).c_str());
1562
1563         if (m_privilege.name != L"") {
1564             if (iriPrivilege.Validate()) {
1565                 if (m_data.privilegeList.find(m_privilege) ==
1566                     m_data.privilegeList.end())
1567                 {
1568                     m_data.privilegeList.insert(m_privilege);
1569                 } else {
1570                     _D("Ignoring privilege with name %ls", m_privilege.name.c_str());
1571                 }
1572             }
1573         }
1574     }
1575
1576     PrivilegeParser(ConfigParserData& data) :
1577         ElementParser(),
1578         m_data(data),
1579         m_feature(L""),
1580         m_privilege(L""),
1581         m_properNamespace(false)
1582     {}
1583
1584   private:
1585     ConfigParserData& m_data;
1586     ConfigParserData::Feature m_feature;
1587     ConfigParserData::Privilege m_privilege;
1588     bool m_properNamespace;
1589 };
1590
1591 class CategoryParser : public ElementParser
1592 {
1593   public:
1594     virtual ActionFunc GetElementParser(const DPL::String& /*ns*/,
1595                                         const DPL::String& /*name*/)
1596     {
1597         return &IgnoringParser::Create; //ignore unknown according to w3c
1598     }
1599
1600     virtual void Accept(const Element& element)
1601     {
1602         if (element.ns ==
1603             ConfigurationNamespace::TizenWebAppNamespaceName)
1604         {
1605             m_properNamespace = true;
1606         }
1607         LogDebug("element");
1608     }
1609
1610     virtual void Accept(const XmlAttribute& attribute)
1611     {
1612         if (m_properNamespace) {
1613             if (attribute.name == L"name") {
1614                 if (attribute.value.size() > 0) {
1615                     m_name = attribute.value;
1616                 }
1617             }
1618         }
1619     }
1620
1621     virtual void Accept(const Text& /*text*/)
1622     {}
1623
1624     virtual void Verify()
1625     {
1626         if (!m_name) {
1627             _W("name attribute of category element is mandatory - ignoring");
1628             return;
1629         }
1630
1631         if (m_data.categoryList.find(*m_name) ==
1632             m_data.categoryList.end())
1633         {
1634             m_data.categoryList.insert(*m_name);
1635         }
1636
1637     }
1638
1639     explicit CategoryParser(ConfigParserData& data) :
1640         m_data(data),
1641         m_properNamespace(false)
1642     {}
1643
1644   private:
1645     DPL::OptionalString m_name;
1646     ConfigParserData& m_data;
1647     bool m_properNamespace;
1648 };
1649
1650 #ifdef DBOX_ENABLED
1651 class AppWidgetParser : public ElementParser
1652 {
1653   public:
1654
1655     struct BoxLabelParser : public ElementParser
1656     {
1657         virtual ActionFunc GetElementParser(const DPL::String& /*ns*/,
1658                                             const DPL::String& /*name*/)
1659         {
1660             return &IgnoringParser::Create; //ignore unknown according to w3c
1661         }
1662
1663         virtual void Accept(const XmlAttribute& attribute)
1664         {
1665             if (m_properNamespace) {
1666                  m_lang = attribute.lang;
1667             }
1668         }
1669         virtual void Accept(const Element& element)
1670         {
1671             if (element.ns ==
1672                 ConfigurationNamespace::TizenWebAppNamespaceName)
1673             {
1674                 m_properNamespace = true;
1675             }
1676         }
1677
1678         virtual void Accept(const Text& text)
1679         {
1680             if (m_properNamespace) {
1681                 m_label = text.value;
1682             }
1683         }
1684
1685         virtual void Verify()
1686         {
1687             std::pair<DPL::String, DPL::String> boxLabel;
1688             if (m_label.empty()) {
1689                 _W("box-label element is empty");
1690                 boxLabel.first = DPL::FromUTF8String("");
1691                 boxLabel.second = DPL::FromUTF8String("");
1692                 m_data.m_label.push_back(boxLabel);
1693             }
1694             else {
1695                 boxLabel.first = m_lang;
1696                 boxLabel.second = m_label;
1697                 m_data.m_label.push_back(boxLabel);
1698             }
1699         }
1700
1701         BoxLabelParser(ConfigParserData::LiveboxInfo& data) :
1702             ElementParser(),
1703             m_properNamespace(false),
1704             m_data(data)
1705         {}
1706
1707       private:
1708         DPL::String m_lang;
1709         DPL::String m_label;
1710         bool m_properNamespace;
1711         ConfigParserData::LiveboxInfo& m_data;
1712     };
1713
1714     struct BoxIconParser : public ElementParser
1715     {
1716         virtual ActionFunc GetElementParser(const DPL::String& /*ns*/,
1717                                             const DPL::String& /*name*/)
1718         {
1719             return &IgnoringParser::Create; //ignore unknown according to w3c
1720         }
1721
1722         virtual void Accept(const XmlAttribute& attribute)
1723         {
1724             if (m_properNamespace) {
1725                 if (attribute.name == L"src") {
1726                     m_icon = attribute.value;
1727                 }
1728             }
1729         }
1730
1731         virtual void Accept(const Element& element)
1732         {
1733             if (element.ns ==
1734                 ConfigurationNamespace::TizenWebAppNamespaceName)
1735             {
1736                 m_properNamespace = true;
1737             }
1738         }
1739
1740         virtual void Accept(const Text& /*text*/)
1741         {}
1742
1743         virtual void Verify()
1744         {
1745             if (m_icon.empty()) {
1746                 ThrowMsg(Exception::ParseError,
1747                     "src attribute of box-icon element is mandatory - ignoring");
1748             }
1749             if (!m_data.m_icon.empty()) {
1750                 ThrowMsg(Exception::ParseError,
1751                     "<tizen:box-icon /> element should occur as 0 or 1 time");
1752             }
1753             m_data.m_icon = m_icon;
1754         }
1755
1756         explicit BoxIconParser(ConfigParserData::LiveboxInfo& data) :
1757             ElementParser(),
1758             m_properNamespace(false),
1759             m_data(data)
1760         {}
1761
1762       private:
1763         DPL::String m_icon;
1764         bool m_properNamespace;
1765         ConfigParserData::LiveboxInfo& m_data;
1766     };
1767
1768     struct BoxContentParser : public ElementParser
1769     {
1770         struct BoxSizeParser : public ElementParser
1771         {
1772             virtual ActionFunc GetElementParser(const DPL::String& /*ns*/,
1773                                                 const DPL::String& /*name*/)
1774             {
1775                 return &IgnoringParser::Create; //ignore unknown according to w3c
1776             }
1777
1778             virtual void Accept(const XmlAttribute& attribute)
1779             {
1780                 if (m_properNamespace) {
1781                     if (attribute.name == L"preview") {
1782                         m_preview = attribute.value;
1783                     }
1784                     if (attribute.name == L"use-decoration") {
1785                         m_useDecoration = attribute.value;
1786                     }
1787                 }
1788             }
1789
1790             virtual void Accept(const Element& element)
1791             {
1792                 if (element.ns ==
1793                     ConfigurationNamespace::TizenWebAppNamespaceName)
1794                 {
1795                     m_properNamespace = true;
1796                 }
1797             }
1798
1799             virtual void Accept(const Text& text)
1800             {
1801                 if (m_properNamespace) {
1802                     m_size = text.value;
1803                 }
1804             }
1805
1806             virtual void Verify()
1807             {
1808                 if(m_size.empty()) {
1809                     ThrowMsg(Exception::ParseError,
1810                         "size is mandatory - ignoring");
1811                 }
1812
1813                 if (m_useDecoration.empty() || CheckIfNotTrueNorFalse(m_useDecoration)) {
1814                     m_useDecoration = L"true"; // default value
1815                 }
1816
1817                 ConfigParserData::LiveboxInfo::BoxSizeInfo boxSizeInfo;
1818                 boxSizeInfo.m_size = m_size;
1819                 boxSizeInfo.m_preview = m_preview;
1820                 boxSizeInfo.m_useDecoration = m_useDecoration;
1821                 m_data.m_boxSize.push_back(boxSizeInfo);
1822             }
1823
1824             explicit BoxSizeParser(
1825                 ConfigParserData::LiveboxInfo::BoxContentInfo& data) :
1826                 ElementParser(),
1827                 m_properNamespace(false),
1828                 m_data(data)
1829             {}
1830
1831           private:
1832             DPL::String m_size;
1833             DPL::String m_preview;
1834             DPL::String m_useDecoration;
1835             bool m_properNamespace;
1836             ConfigParserData::LiveboxInfo::BoxContentInfo& m_data;
1837         };
1838
1839         struct PdParser : public ElementParser
1840         {
1841             virtual ActionFunc GetElementParser(const DPL::String& /*ns*/,
1842                                                 const DPL::String& /*name*/)
1843             {
1844                 return &IgnoringParser::Create; //ignore unknown according to w3c
1845             }
1846
1847             virtual void Accept(const XmlAttribute& attribute)
1848             {
1849                 if (m_properNamespace) {
1850                     if (attribute.name == L"src") {
1851                         m_src = attribute.value;
1852                     } else if (attribute.name == L"width") {
1853                         m_width = attribute.value;
1854                     } else if (attribute.name == L"height") {
1855                         m_height = attribute.value;
1856                     } else if (attribute.name == L"fast-open") {
1857                         m_fastOpen= attribute.value;
1858                     }
1859                 }
1860             }
1861
1862             virtual void Accept(const Element& element)
1863             {
1864                 if (element.ns ==
1865                     ConfigurationNamespace::TizenWebAppNamespaceName)
1866                 {
1867                     m_properNamespace = true;
1868                 }
1869             }
1870
1871             virtual void Accept(const Text& /*text*/)
1872             {}
1873
1874             virtual void Verify()
1875             {
1876                 if (m_src.empty()) {
1877                     ThrowMsg(Exception::ParseError,
1878                         "src attribute of pd element is mandatory - ignoring");
1879                 }
1880
1881                 if (m_width.empty()) {
1882                     ThrowMsg(Exception::ParseError,
1883                         "width attribute of pd element is mandatory - ignoring");
1884                 }
1885
1886                 if (m_height.empty()) {
1887                     ThrowMsg(Exception::ParseError,
1888                         "height attribute of pd element is mandatory - ignoring");
1889                 }
1890
1891                 if (!ConvertToInt(m_width)) {
1892                     ThrowMsg(Exception::ParseError,
1893                         "width attribute of pd element cannot be converted to int - ignoring. value: " << m_width);
1894                 }
1895
1896
1897                 DPL::OptionalInt height = ConvertToInt(m_height);
1898
1899                 if (!height) {
1900                     ThrowMsg(Exception::ParseError,
1901                         "height attribute of pd element cannot be converted to int - ignoring. value: " << m_height);
1902                 }
1903
1904                 if (*height < 1) {
1905                     m_height = L"1";
1906                     _D("height attribute of pd element shouldn't be less than 1. Changed to 1 from %d", *height);
1907                 } else if (*height > 380){
1908                     m_height = L"380";
1909                     _D("height attribute of pd element shouldn't be greater than 380. Changed to 380 from %d", *height);
1910                 }
1911
1912                 if (!m_data.m_pdSrc.empty()) {
1913                     ThrowMsg(Exception::ParseError, "<tizen:pd> element should occur as 0 or 1 time");
1914                 }
1915
1916                 m_data.m_pdSrc = m_src;
1917                 m_data.m_pdWidth = m_width;
1918                 m_data.m_pdHeight = m_height;
1919                 m_data.m_pdFastOpen = m_fastOpen;
1920             }
1921
1922             explicit PdParser(
1923                 ConfigParserData::LiveboxInfo::BoxContentInfo& data) :
1924                 ElementParser(),
1925                 m_properNamespace(false),
1926                 m_data(data)
1927             {}
1928
1929           private:
1930             DPL::OptionalInt ConvertToInt(const DPL::String& intAsString)
1931             {
1932                 char * endptr;
1933                 std::string tempStr = DPL::ToUTF8String(intAsString);
1934                 const char * intAsString_c = tempStr.c_str();
1935                 errno = 0;
1936                 long int intAsString_i = strtol(intAsString_c, &endptr, 10);
1937
1938                 if ((errno == ERANGE && (intAsString_i == LONG_MAX || intAsString_i == LONG_MIN))
1939                         || intAsString_i > INT_MAX || intAsString_i < INT_MIN
1940                         || *endptr != '\0') {
1941                     return DPL::OptionalInt();
1942                 }
1943
1944                 return static_cast<int>(intAsString_i);
1945             }
1946
1947             DPL::String m_src;
1948             DPL::String m_width;
1949             DPL::String m_height;
1950             DPL::String m_fastOpen;
1951
1952             bool m_properNamespace;
1953             ConfigParserData::LiveboxInfo::BoxContentInfo& m_data;
1954         };
1955
1956         virtual ActionFunc GetElementParser(const DPL::String& /*ns*/,
1957                                             const DPL::String& name)
1958         {
1959             if (name == L"box-size") {
1960                 return std::bind(&AppWidgetParser::BoxContentParser::OnBoxSizeElement, this);
1961             } else if (name == L"pd") {
1962                 return std::bind(&AppWidgetParser::BoxContentParser::OnPdElement, this);
1963             } else {
1964                 ThrowMsg(Exception::ParseError,
1965                          "No element parser for name: " << name);
1966             }
1967         }
1968
1969         virtual void Accept(const XmlAttribute& attribute)
1970         {
1971             if (m_properNamespace) {
1972                 if (attribute.name == L"src") {
1973                     m_box.m_boxSrc = attribute.value;
1974                 }
1975                 if (attribute.name == L"mouse-event") {
1976                     m_box.m_boxMouseEvent = attribute.value;
1977                 }
1978                 if (attribute.name == L"touch-effect") {
1979                     m_box.m_boxTouchEffect = attribute.value;
1980                 }
1981             }
1982         }
1983
1984         virtual void Accept(const Element& element)
1985         {
1986             if (element.ns ==
1987                 ConfigurationNamespace::TizenWebAppNamespaceName)
1988             {
1989                 m_properNamespace = true;
1990             }
1991         }
1992
1993         virtual void Accept(const Text& /*text*/)
1994         {}
1995
1996         virtual void Verify()
1997         {
1998             if (m_box.m_boxSrc.empty()) {
1999                 ThrowMsg(Exception::ParseError,
2000                     "src attribute of box-content element is mandatory - ignoring");
2001             }
2002
2003             if (m_box.m_boxMouseEvent.empty() || CheckIfNotTrueNorFalse(m_box.m_boxMouseEvent)) {
2004                 m_box.m_boxMouseEvent = L"false"; // default value
2005             }
2006
2007             if (m_box.m_boxTouchEffect.empty() || CheckIfNotTrueNorFalse(m_box.m_boxTouchEffect)) {
2008                 m_box.m_boxTouchEffect = L"true"; // default value
2009             }
2010
2011             if (m_box.m_boxSize.empty()) {
2012                 ThrowMsg(Exception::ParseError,
2013                     "box-size element of box-content element not found - ignoring");
2014             }
2015
2016             if (!m_data.m_boxInfo.m_boxSrc.empty()) {
2017                 ThrowMsg(Exception::ParseError, "<tizen:box-content> element must occur exactly 1 time");
2018             }
2019
2020             m_data.m_boxInfo = m_box;
2021         }
2022
2023         explicit BoxContentParser(ConfigParserData::LiveboxInfo& data) :
2024             ElementParser(),
2025             m_properNamespace(false),
2026             m_data(data)
2027         {}
2028
2029         ElementParserPtr OnBoxSizeElement()
2030         {
2031             return ElementParserPtr(new BoxSizeParser(m_box));
2032         }
2033
2034         ElementParserPtr OnPdElement()
2035         {
2036             return ElementParserPtr(new PdParser(m_box));
2037         }
2038
2039       private:
2040         bool m_properNamespace;
2041         ConfigParserData::LiveboxInfo& m_data;
2042         ConfigParserData::LiveboxInfo::BoxContentInfo m_box;
2043     };
2044
2045     virtual ActionFunc GetElementParser(const DPL::String& /*ns*/,
2046                                         const DPL::String& name)
2047     {
2048         if (name == L"box-label") {
2049             return std::bind(&AppWidgetParser::OnBoxLabelElement, this);
2050         } else if (name == L"box-icon") {
2051             return std::bind(&AppWidgetParser::OnBoxIconElement, this);
2052         } else if (name == L"box-content") {
2053             return std::bind(&AppWidgetParser::OnBoxContentElement, this);
2054         } else {
2055             return &IgnoringParser::Create; //ignore unknown according to w3c
2056         }
2057     }
2058
2059     virtual void Accept(const XmlAttribute& attribute)
2060     {
2061         if (m_properNamespace) {
2062             if (attribute.name == L"id") {
2063                 m_liveboxId = attribute.value;
2064             } else if (attribute.name == L"primary") {
2065                 m_primary = attribute.value;
2066             } else if (attribute.name == L"auto-launch") {
2067                 m_autoLaunch = attribute.value;
2068             } else if (attribute.name == L"update-period") {
2069                 m_updatePeriod = attribute.value;
2070             } else if (attribute.name == L"type") {
2071                 m_type = attribute.value;
2072             }
2073         }
2074     }
2075
2076     virtual void Accept(const Element& element)
2077     {
2078         if (element.ns ==
2079             ConfigurationNamespace::TizenWebAppNamespaceName)
2080         {
2081             m_properNamespace = true;
2082         }
2083     }
2084
2085     virtual void Accept(const Text& /*text*/)
2086     {}
2087
2088     virtual void Verify()
2089     {
2090         if (m_liveboxId.empty()) {
2091             ThrowMsg(Exception::ParseError,
2092                  "app-widget element must have id attribute");
2093         }
2094         else
2095         {
2096             pcrecpp::RE re(REGEXP_ID_STRING.c_str());
2097             if (!re.FullMatch(DPL::ToUTF8String(m_liveboxId)))
2098             {
2099                 ThrowMsg(Exception::ParseError,
2100                      "invalid format of app-widget id attribute");
2101             }
2102         }
2103
2104         if (m_primary.empty() || CheckIfNotTrueNorFalse(m_primary))
2105         {
2106             m_primary = L"true";        //default value
2107         }
2108
2109         if (!m_updatePeriod.empty())
2110         {
2111             char * endptr;
2112             errno = 0;
2113             std::string tempStr = DPL::ToUTF8String(m_updatePeriod);
2114
2115             //set standard locale to fix decimal point mark - '.'
2116             std::string currentLocale = setlocale(LC_NUMERIC, NULL);
2117             if (NULL == setlocale(LC_NUMERIC, "C"))
2118                 _W("Failed to change locale to \"C\"");
2119             double updatePeriod = strtod(tempStr.c_str(), &endptr);
2120
2121             //go back to previous locale
2122             if (NULL == setlocale(LC_NUMERIC, currentLocale.c_str()))
2123                 _W("Failed to set previous locale");
2124
2125             if ((errno == ERANGE && (updatePeriod == -HUGE_VAL || updatePeriod == HUGE_VAL))
2126                     || *endptr != '\0') {
2127                 ThrowMsg(Exception::ParseError,
2128                     "update-period attribute of app-widget element should be a number - ignoring. current value: " << m_updatePeriod);
2129             } else if (updatePeriod < 1800.0) {
2130                 _D("update-period attribute of app-widget element shouldn't be less than 1800.0 - changed to 1800 from value: %ls", m_updatePeriod.c_str());
2131                 m_updatePeriod = L"1800.0";
2132             }
2133         }
2134
2135         if (m_autoLaunch.empty() || CheckIfNotTrueNorFalse(m_autoLaunch))
2136         {
2137             m_autoLaunch = L"false"; // default value
2138         }
2139
2140         if(m_livebox.m_label.empty()) {
2141             ThrowMsg(Exception::ParseError,
2142                 "box-label element of app-widget element not found - ignoring");
2143         }
2144
2145         if(!m_boxContentFound) {
2146             ThrowMsg(Exception::ParseError,
2147                 "box-content element of app-widget element not found - ignoring");
2148         }
2149
2150         m_livebox.m_liveboxId = m_liveboxId;
2151         m_livebox.m_primary = m_primary;
2152         m_livebox.m_autoLaunch = m_autoLaunch;
2153         m_livebox.m_updatePeriod = m_updatePeriod;
2154         m_livebox.m_type = m_type;
2155
2156         m_data.m_livebox.push_back(m_livebox);
2157     }
2158
2159     explicit AppWidgetParser(ConfigParserData& data) :
2160         ElementParser(),
2161         m_data(data),
2162         m_properNamespace(false),
2163         m_boxContentFound(false)
2164     {
2165         m_livebox = ConfigParserData::LiveboxInfo();
2166     }
2167
2168     ElementParserPtr OnBoxLabelElement()
2169     {
2170
2171         return ElementParserPtr(new BoxLabelParser(m_livebox));
2172     }
2173
2174     ElementParserPtr OnBoxIconElement()
2175     {
2176         return ElementParserPtr(new BoxIconParser(m_livebox));
2177     }
2178
2179     ElementParserPtr OnBoxContentElement()
2180     {
2181         m_boxContentFound = true;
2182         return ElementParserPtr(new BoxContentParser(m_livebox));
2183     }
2184
2185   private:
2186     static std::string REGEXP_ID_STRING;
2187     ConfigParserData& m_data;
2188     ConfigParserData::LiveboxInfo m_livebox;
2189     DPL::String m_liveboxId;
2190     DPL::String m_primary;
2191     DPL::String m_autoLaunch;
2192     DPL::String m_updatePeriod;
2193     DPL::String m_type;
2194     bool m_properNamespace;
2195     bool m_boxContentFound;
2196
2197     static bool CheckIfNotTrueNorFalse(const DPL::String &stringToCheck)
2198     {
2199         return stringToCheck.compare(L"true") != 0 && stringToCheck.compare(L"false") != 0;
2200     }
2201 };
2202
2203 std::string AppWidgetParser::REGEXP_ID_STRING = std::string(ApplicationParser::REGEXP_ID) + "\\.[0-9A-Za-z]+";
2204 #endif
2205
2206 class AllowNavigationParser : public ElementParser
2207 {
2208   public:
2209     AllowNavigationParser(ConfigParserData& data) :
2210       ElementParser(),
2211       m_data(data),
2212       m_properNamespace(false)
2213     {}
2214
2215     virtual ActionFunc GetElementParser(const DPL::String& /*ns*/,
2216                                         const DPL::String& /*name*/)
2217     {
2218         return &IgnoringParser::Create; //ignore unknown according to w3c
2219     }
2220
2221     virtual void Accept(const Element& element)
2222     {
2223         if (element.ns == ConfigurationNamespace::TizenWebAppNamespaceName) {
2224             m_properNamespace = true;
2225         }
2226     }
2227
2228     virtual void Accept(const Text& text)
2229     {
2230         if (m_properNamespace)
2231         {
2232             m_origin = text.value;
2233         }
2234     }
2235
2236     virtual void Accept(const XmlAttribute& /*attribute*/)
2237     {
2238     }
2239
2240     virtual void Verify()
2241     {
2242         if (m_data.allowNavigationEncountered || !m_properNamespace)
2243         {
2244             return;
2245         }
2246         m_data.allowNavigationEncountered = true;
2247
2248         if (!m_origin) {
2249             _W("data is empty");
2250             return;
2251         }
2252
2253         char* data = strdup(DPL::ToUTF8String(*m_origin).c_str());
2254         char* ptr = strtok(data," \n\r\t");
2255         while (ptr != NULL) {
2256             std::string origin = ptr;
2257             ptr = strtok(NULL," \n\r\t");
2258             if(origin == "*") {
2259                 ConfigParserData::AllowNavigationInfo info(L"*", L"*");
2260                 m_data.allowNavigationInfoList.push_back(info);
2261                 continue;
2262             }
2263
2264             std::unique_ptr<iri_t, decltype(&iri_destroy)> iri(iri_parse(origin.c_str()), iri_destroy);
2265             if (!iri->host || strlen(iri->host) == 0) {
2266                 // input origin should has schem and host
2267                 // in case of file scheme path is filled
2268                 // "http://"
2269                 _W("input origin isn't verified");
2270                 continue;
2271             }
2272             DPL::String scheme = L"*";
2273             if (iri->scheme && strlen(iri->scheme) != 0) {
2274                 scheme = DPL::FromUTF8String(iri->scheme);
2275             }
2276             ConfigParserData::AllowNavigationInfo info(
2277                 scheme,
2278                 DPL::FromUTF8String(iri->host));
2279             m_data.allowNavigationInfoList.push_back(info);
2280         }
2281         free(data);
2282     }
2283
2284   private:
2285     DPL::OptionalString m_origin;
2286     ConfigParserData& m_data;
2287     bool m_properNamespace;
2288 };
2289
2290 class CspParser : public ElementParser
2291 {
2292   public:
2293     virtual ActionFunc GetElementParser(const DPL::String& /*ns*/,
2294                                         const DPL::String& /*name*/)
2295     {
2296         return &IgnoringParser::Create; //ignore unknown according to w3c
2297     }
2298
2299     CspParser(ConfigParserData& data) :
2300         ElementParser(),
2301         m_data(data),
2302         m_properNamespace(false)
2303     {}
2304
2305     virtual void Accept(const Element& element)
2306     {
2307         if (element.ns == ConfigurationNamespace::TizenWebAppNamespaceName) {
2308             m_properNamespace = true;
2309         }
2310     }
2311
2312     virtual void Accept(const XmlAttribute& /*attribute*/)
2313     {}
2314
2315     virtual void Accept(const Text& text)
2316     {
2317         if (m_properNamespace) {
2318             m_policy = text.value;
2319         }
2320     }
2321
2322     virtual void Verify()
2323     {
2324         if (m_data.cspPolicyEncountered) {
2325             return;
2326         }
2327         m_data.cspPolicyEncountered = true;
2328
2329         if (!!m_policy) {
2330             m_data.cspPolicy = *m_policy;
2331         }
2332     }
2333
2334   private:
2335     ConfigParserData& m_data;
2336     bool m_properNamespace;
2337     DPL::OptionalString m_policy;
2338 };
2339
2340 class CspReportOnlyParser : public ElementParser
2341 {
2342   public:
2343     virtual ActionFunc GetElementParser(const DPL::String& /*ns*/,
2344                                         const DPL::String& /*name*/)
2345     {
2346         return &IgnoringParser::Create; //ignore unknown according to w3c
2347     }
2348
2349     CspReportOnlyParser(ConfigParserData& data) :
2350         ElementParser(),
2351         m_data(data),
2352         m_properNamespace(false)
2353     {}
2354
2355     virtual void Accept(const Element& element)
2356     {
2357         if (element.ns == ConfigurationNamespace::TizenWebAppNamespaceName) {
2358             m_properNamespace = true;
2359         }
2360     }
2361
2362     virtual void Accept(const XmlAttribute& /*attribute*/)
2363     {}
2364
2365     virtual void Accept(const Text& text)
2366     {
2367         if (m_properNamespace) {
2368             m_policy = text.value;
2369         }
2370     }
2371
2372     virtual void Verify()
2373     {
2374         if (m_data.cspPolicyReportOnlyEncountered) {
2375             return;
2376         }
2377         m_data.cspPolicyReportOnlyEncountered = true;
2378
2379         if (!!m_policy) {
2380             m_data.cspPolicyReportOnly = *m_policy;
2381         }
2382     }
2383
2384   private:
2385     ConfigParserData& m_data;
2386     bool m_properNamespace;
2387     DPL::OptionalString m_policy;
2388 };
2389
2390 class AccountParser : public ElementParser
2391 {
2392   public:
2393       struct IconParser : public ElementParser
2394     {
2395         public:
2396             virtual ActionFunc GetElementParser(const DPL::String& /*ns*/,
2397                     const DPL::String& /*name*/)
2398             {
2399                 return &IgnoringParser::Create; //ignore unknown according to w3c
2400             }
2401
2402             virtual void Accept(const Text& text)
2403             {
2404                 if (text.value == L"") {
2405                     return;
2406                 }
2407                 m_value = text.value;
2408             }
2409
2410             virtual void Accept(const Element& /*element*/)
2411             {}
2412
2413             virtual void Accept(const XmlAttribute& attribute)
2414             {
2415                 if (attribute.name == L"section") {
2416                     if (attribute.value == L"Account") {
2417                         m_type = ConfigParserData::IconSectionType::DefaultIcon;
2418                     } else if (attribute.value == L"AccountSmall") {
2419                         m_type = ConfigParserData::IconSectionType::SmallIcon;
2420                     }
2421                 }
2422             }
2423
2424             virtual void Verify()
2425             {
2426                 if (!m_value || *m_value == L"") {
2427                     return;
2428                 }
2429
2430                 std::pair<ConfigParserData::IconSectionType, DPL::String> icon;
2431                 icon.first = m_type;
2432                 icon.second = *m_value;
2433
2434                 m_data.m_iconSet.insert(icon);
2435             }
2436
2437             IconParser(ConfigParserData::AccountProvider& data) :
2438                 ElementParser(),
2439                 m_properNamespace(false),
2440                 m_type(ConfigParserData::DefaultIcon),
2441                 m_data(data)
2442         {}
2443
2444         private:
2445             bool m_properNamespace;
2446             ConfigParserData::IconSectionType m_type;
2447             ConfigParserData::AccountProvider& m_data;
2448             DPL::OptionalString m_value;
2449     };
2450
2451       struct DisplayNameParser : public ElementParser
2452     {
2453         public:
2454             virtual ActionFunc GetElementParser(const DPL::String& /*ns*/,
2455                     const DPL::String& /*name*/)
2456             {
2457                 return &IgnoringParser::Create; //ignore unknown according to w3c
2458             }
2459
2460             virtual void Accept(const Text& text)
2461             {
2462                 if (text.value == L"") {
2463                     return;
2464                 }
2465                 m_value = text.value;
2466             }
2467
2468             virtual void Accept(const Element& element)
2469             {
2470                 m_lang = element.lang;
2471                 m_value= L"";
2472             }
2473
2474             virtual void Accept(const XmlAttribute& /*attribute*/)
2475             {}
2476
2477             virtual void Verify()
2478             {
2479                 if (!m_value || *m_value == L"") {
2480                     return;
2481                 }
2482
2483                 std::pair<DPL::String, DPL::String> name;
2484                 name.first = *m_lang;
2485                 name.second = *m_value;
2486
2487                 m_data.m_displayNameSet.insert(name);
2488             }
2489
2490             DisplayNameParser(ConfigParserData::AccountProvider& data) :
2491                 ElementParser(),
2492                 m_properNamespace(false),
2493                 m_data(data)
2494         {}
2495
2496         private:
2497             bool m_properNamespace;
2498             DPL::OptionalString m_lang;
2499             DPL::OptionalString m_value;
2500             ConfigParserData::AccountProvider& m_data;
2501     };
2502
2503       struct CapabilityParser : public ElementParser
2504     {
2505         public:
2506             virtual ActionFunc GetElementParser(const DPL::String& /*ns*/,
2507                     const DPL::String& /*name*/)
2508             {
2509                 return &IgnoringParser::Create; //ignore unknown according to w3c
2510             }
2511
2512             virtual void Accept(const Text& text)
2513             {
2514                 if (text.value == L"") {
2515                     return;
2516                 }
2517                 m_value = text.value;
2518             }
2519
2520             virtual void Accept(const Element& /*element*/)
2521             {}
2522
2523             virtual void Accept(const XmlAttribute& /*attribute*/)
2524             {}
2525
2526             virtual void Verify()
2527             {
2528                 if (!m_value || *m_value == L"") {
2529                     return;
2530                 }
2531                 m_data.m_capabilityList.push_back(*m_value);
2532             }
2533
2534             CapabilityParser(ConfigParserData::AccountProvider& data) :
2535                 ElementParser(),
2536                 m_properNamespace(false),
2537                 m_data(data)
2538         {}
2539
2540         private:
2541             bool m_properNamespace;
2542             DPL::OptionalString m_value;
2543             ConfigParserData::AccountProvider& m_data;
2544     };
2545       virtual ActionFunc GetElementParser(const DPL::String& /*ns*/,
2546               const DPL::String& name)
2547       {
2548           if (name == L"icon") {
2549               return std::bind(&AccountParser::OnIconElement, this);
2550           } else if (name == L"display-name") {
2551               return std::bind(&AccountParser::OnDisplayNameElement, this);
2552           } else if (name == L"capability") {
2553               return std::bind(&AccountParser::OnCapabilityElement, this);
2554           } else {
2555               return &IgnoringParser::Create; //ignore unknown according to w3c
2556           }
2557       }
2558
2559       virtual void Accept(const Text& /*text*/)
2560       {}
2561
2562       virtual void Accept(const Element& /*element*/)
2563       {}
2564
2565       virtual void Accept(const XmlAttribute& attribute)
2566       {
2567           if (attribute.name == L"multiple-account-support") {
2568               if (attribute.value == L"true") {
2569                   m_account.m_multiAccountSupport = true;
2570               }
2571           }
2572       }
2573
2574       virtual void Verify()
2575       {
2576       }
2577
2578       ElementParserPtr OnIconElement()
2579       {
2580           return ElementParserPtr(new IconParser(m_account));
2581       }
2582
2583       ElementParserPtr OnDisplayNameElement()
2584       {
2585           return ElementParserPtr(new DisplayNameParser(m_account));
2586       }
2587
2588       ElementParserPtr OnCapabilityElement()
2589       {
2590           return ElementParserPtr(new CapabilityParser(m_account));
2591       }
2592
2593       AccountParser(ConfigParserData& data) :
2594           ElementParser(),
2595           m_properNamespace(false),
2596           m_multiSupport(false),
2597           m_data(data),
2598           m_account(data.accountProvider)
2599     {
2600     }
2601
2602   private:
2603       bool m_properNamespace;
2604       bool m_multiSupport;
2605       ConfigParserData& m_data;
2606       ConfigParserData::AccountProvider& m_account;
2607 };
2608
2609 class MetadataParser : public ElementParser
2610 {
2611   public:
2612     virtual ActionFunc GetElementParser(const DPL::String& /*ns*/,
2613                                         const DPL::String& /*name*/)
2614     {
2615         return &IgnoringParser::Create; //ignore unknown according to w3c
2616     }
2617
2618     virtual void Accept(const XmlAttribute& attribute)
2619     {
2620         if (m_properNamespace) {
2621             if (attribute.name == L"key") {
2622                 m_key = attribute.value;
2623             } else if (attribute.name == L"value") {
2624                 m_value = attribute.value;
2625             }
2626         }
2627     }
2628
2629     virtual void Accept(const Element& element)
2630     {
2631         if (element.ns == ConfigurationNamespace::TizenWebAppNamespaceName) {
2632             m_properNamespace = true;
2633         }
2634     }
2635
2636     virtual void Accept(const Text& /*text*/)
2637     {
2638         ThrowMsg(Exception::ParseError, "param element must be empty");
2639     }
2640
2641     virtual void Verify()
2642     {
2643         if (!m_key) {
2644             _W("metadata element must have key attribute");
2645             return;
2646         }
2647         NormalizeString(m_key);
2648         NormalizeString(m_value);
2649         ConfigParserData::Metadata metaData(m_key, m_value);
2650         FOREACH(it, m_data.metadataList) {
2651             if (!DPL::StringCompare(*it->key, *m_key)) {
2652                 _E("Key isn't unique");
2653                 return;
2654             }
2655         }
2656         m_data.metadataList.push_back(metaData);
2657     }
2658
2659     MetadataParser(ConfigParserData& data) :
2660         ElementParser(),
2661         m_data(data),
2662         m_properNamespace(false)
2663     {}
2664
2665   private:
2666     DPL::OptionalString m_key;
2667     DPL::OptionalString m_value;
2668     ConfigParserData& m_data;
2669     bool m_properNamespace;
2670 };
2671
2672 #ifdef IME_ENABLED
2673 class ImeParser : public ElementParser
2674 {
2675   public:
2676     struct UuidParser : public ElementParser
2677     {
2678       public:
2679         virtual ActionFunc GetElementParser(const DPL::String& /*ns*/,
2680                                             const DPL::String& /*name*/)
2681         {
2682             return &IgnoringParser::Create;
2683         }
2684
2685         virtual void Accept(const XmlAttribute& attribute)
2686         {}
2687
2688         virtual void Accept(const Element& element)
2689         {}
2690
2691         virtual void Accept(const Text& text)
2692         {
2693             if (m_uuid.empty()) {
2694                 m_uuid = text.value;
2695             } else {
2696                 m_uuid += text.value;
2697             }
2698         }
2699
2700         virtual void Verify()
2701         {
2702             if (m_uuid.empty()) {
2703                 ThrowMsg(Exception::ParseError, "uuid text is empty");
2704             }
2705             m_imeAppInfo.uuid = m_uuid;
2706         }
2707
2708         UuidParser(ConfigParserData::ImeAppInfo& data) :
2709             ElementParser(),
2710             m_imeAppInfo(data)
2711         {}
2712
2713       private:
2714           ConfigParserData::ImeAppInfo& m_imeAppInfo;
2715           DPL::String m_uuid;
2716     };
2717
2718     struct LanguagesParser : public ElementParser
2719     {
2720       public:
2721         virtual ActionFunc GetElementParser(const DPL::String& /*ns*/,
2722                                             const DPL::String& name)
2723         {
2724             if (name == L"language") {
2725                 return std::bind(&LanguagesParser::OnLanguageElement, this);
2726             } else {
2727                 return &IgnoringParser::Create;
2728             }
2729         }
2730
2731         virtual void Accept(const XmlAttribute& attribute)
2732         {}
2733
2734         virtual void Accept(const Element& element)
2735         {}
2736
2737         virtual void Accept(const Text& text)
2738         {
2739             ThrowMsg(Exception::ParseError, "param element must be empty");
2740         }
2741
2742         virtual void Verify()
2743         {}
2744
2745         LanguagesParser(ConfigParserData::ImeAppInfo& data) :
2746             ElementParser(),
2747             m_imeAppInfo(data)
2748         {}
2749
2750         ElementParserPtr OnLanguageElement()
2751         {
2752             return ElementParserPtr(new LanguageParser(m_imeAppInfo));
2753         }
2754
2755       private:
2756           ConfigParserData::ImeAppInfo& m_imeAppInfo;
2757     };
2758
2759     struct LanguageParser : public ElementParser
2760     {
2761       public:
2762         virtual ActionFunc GetElementParser(const DPL::String& /*ns*/,
2763                                                     const DPL::String& name)
2764         {
2765             return &IgnoringParser::Create;
2766         }
2767
2768         virtual void Accept(const XmlAttribute& attribute)
2769         {}
2770
2771         virtual void Accept(const Element& element)
2772         {}
2773
2774         virtual void Accept(const Text& text)
2775         {
2776             if (m_language.empty()) {
2777                 m_language = text.value;
2778             } else {
2779                 m_language += text.value;
2780             }
2781         }
2782
2783         virtual void Verify()
2784         {
2785             if (m_language.empty()) {
2786                 ThrowMsg(Exception::ParseError, "language text is empty");
2787             }
2788             m_imeAppInfo.languageList.insert(m_language);
2789         }
2790
2791         LanguageParser(ConfigParserData::ImeAppInfo& data) :
2792             ElementParser(),
2793             m_imeAppInfo(data)
2794         {}
2795
2796       private:
2797           ConfigParserData::ImeAppInfo& m_imeAppInfo;
2798           DPL::String m_language;
2799     };
2800
2801     virtual ActionFunc GetElementParser(const DPL::String& /*ns*/,
2802                                         const DPL::String& name)
2803     {
2804         if (name == L"uuid") {
2805             return std::bind(&ImeParser::OnUuidElement, this);
2806         } else if (name == L"languages") {
2807             return std::bind(&ImeParser::OnLanguagesElement, this);
2808         } else {
2809             return &IgnoringParser::Create;
2810         }
2811     }
2812
2813     virtual void Accept(const Text& /*text*/)
2814     {
2815         ThrowMsg(Exception::ParseError, "param element must be empty");
2816     }
2817
2818     virtual void Accept(const Element& element)
2819     {}
2820
2821     virtual void Accept(const XmlAttribute& attribute)
2822     {}
2823
2824     virtual void Verify()
2825     {
2826         if (m_imeAppInfo.uuid.empty()) {
2827             ThrowMsg(Exception::ParseError, "ime element must have uuid element");
2828             return;
2829         }
2830
2831         if (m_imeAppInfo.languageList.empty()) {
2832             ThrowMsg(Exception::ParseError, "ime element must have language element");
2833             return;
2834         }
2835         m_data.imeAppInfoList.push_back(m_imeAppInfo);
2836     }
2837
2838     ImeParser(ConfigParserData& data) :
2839         ElementParser(),
2840         m_data(data),
2841         m_imeAppInfo()
2842     {}
2843
2844     ElementParserPtr OnLanguagesElement()
2845     {
2846         return ElementParserPtr(new LanguagesParser(m_imeAppInfo));
2847     }
2848
2849     ElementParserPtr OnUuidElement()
2850     {
2851         return ElementParserPtr(new UuidParser(m_imeAppInfo));
2852     }
2853
2854   private:
2855     ConfigParserData& m_data;
2856     ConfigParserData::ImeAppInfo m_imeAppInfo;
2857 };
2858 #endif
2859
2860 #ifdef SERVICE_ENABLED
2861 class ServiceAppParser : public ElementParser
2862 {
2863   public:
2864     struct ServiceContentParser : public ElementParser
2865     {
2866         virtual ActionFunc GetElementParser(const DPL::String& /*ns*/,
2867                                             const DPL::String& /*name*/)
2868         {
2869             return &IgnoringParser::Create; //ignore unknown according to w3c
2870         }
2871
2872         virtual void Accept(const XmlAttribute& attribute)
2873         {
2874            if (attribute.name == L"src") {
2875                m_src = attribute.value;
2876            }
2877         }
2878
2879         virtual void Accept(const Element& element)
2880         {}
2881
2882         virtual void Accept(const Text& /*text*/)
2883         {
2884             ThrowMsg(Exception::ParseError, "param element must be empty");
2885         }
2886
2887         virtual void Verify()
2888         {
2889             if (m_src.empty()) {
2890                 ThrowMsg(Exception::ParseError, "src attribute of service-content element is mandatory");
2891             }
2892
2893             if (!m_serviceAppInfo.serviceContent.empty()) {
2894                 ThrowMsg(Exception::ParseError, "service-content element occurs more than 1 time");
2895             }
2896             m_serviceAppInfo.serviceContent = m_src;
2897         }
2898
2899         explicit ServiceContentParser(ConfigParserData::ServiceAppInfo& data) :
2900             ElementParser(),
2901             m_serviceAppInfo(data)
2902         {}
2903
2904       private:
2905         DPL::String m_src;
2906         ConfigParserData::ServiceAppInfo& m_serviceAppInfo;;
2907     };
2908
2909     struct ServiceNameParser : public ElementParser
2910     {
2911         virtual ActionFunc GetElementParser(const DPL::String& /*ns*/,
2912                                             const DPL::String& /*name*/)
2913         {
2914             return &IgnoringParser::Create;
2915         }
2916
2917         virtual void Accept(const XmlAttribute& attribute)
2918         {
2919             m_lang = attribute.lang;
2920         }
2921
2922         virtual void Accept(const Element& element)
2923         {}
2924
2925         virtual void Accept(const Text& text)
2926         {
2927             m_name = text.value;
2928         }
2929
2930         virtual void Verify()
2931         {
2932             ConfigParserData::LocalizedData& data = m_serviceAppInfo.m_localizedDataSet[m_lang];
2933             if (data.name.IsNull()) {
2934                 NormalizeString(m_name);
2935                 data.name = m_name;
2936             }
2937         }
2938
2939         ServiceNameParser(ConfigParserData::ServiceAppInfo& data) :
2940             ElementParser(),
2941             m_serviceAppInfo(data)
2942         {}
2943
2944       private:
2945         DPL::String m_lang;
2946         DPL::String m_name;
2947         ConfigParserData::ServiceAppInfo& m_serviceAppInfo;
2948     };
2949
2950     struct ServiceIconParser : public ElementParser
2951     {
2952         virtual ActionFunc GetElementParser(const DPL::String& /*ns*/,
2953                                             const DPL::String& /*name*/)
2954         {
2955             return &IgnoringParser::Create;
2956         }
2957
2958         virtual void Accept(const XmlAttribute& attribute)
2959         {
2960             if (attribute.name == L"src") {
2961                 m_icon.src = attribute.value;
2962             }
2963             else if (attribute.name == L"width") {
2964                 m_icon.width = ConvertToInt(attribute.value);
2965             }
2966             else if (attribute.name == L"height") {
2967                 m_icon.height = ConvertToInt(attribute.value);
2968             }
2969         }
2970
2971         virtual void Accept(const Element& element)
2972         {}
2973
2974         virtual void Accept(const Text& /*text*/)
2975         {
2976             ThrowMsg(Exception::ParseError, "param element must be empty");
2977         }
2978
2979         virtual void Verify()
2980         {
2981             if (m_icon.src.empty()) {
2982                 ThrowMsg(Exception::ParseError,
2983                     "src attribute of service-icon element is mandatory - ignoring");
2984             }
2985              m_serviceAppInfo.m_iconsList.push_back(m_icon);
2986         }
2987
2988         explicit ServiceIconParser(ConfigParserData::ServiceAppInfo& data) :
2989             ElementParser(),
2990             m_icon(L""),
2991             m_serviceAppInfo(data)
2992         {}
2993
2994     private:
2995         DPL::OptionalInt ConvertToInt(const DPL::String& intAsString)
2996         {
2997             char * endptr;
2998             std::string tempStr = DPL::ToUTF8String(intAsString);
2999             const char * intAsString_c = tempStr.c_str();
3000             errno = 0;
3001             long int intAsString_i = strtol(intAsString_c, &endptr, 10);
3002
3003             if ((errno == ERANGE && (intAsString_i == LONG_MAX || intAsString_i == LONG_MIN))
3004                     || intAsString_i > INT_MAX || intAsString_i < INT_MIN
3005                     || *endptr != '\0') {
3006                 return DPL::OptionalInt();
3007             }
3008
3009             return static_cast<int>(intAsString_i);
3010         }
3011
3012       private:
3013         ConfigParserData::Icon m_icon;
3014         ConfigParserData::ServiceAppInfo& m_serviceAppInfo;
3015     };
3016
3017     struct ServiceDescriptionParser : public ElementParser
3018     {
3019         virtual ActionFunc GetElementParser(const DPL::String& /*ns*/, const DPL::String& /*name*/)
3020         {
3021             return &IgnoringParser::Create; //ignore unknown according to w3c
3022         }
3023
3024         virtual void Accept(const XmlAttribute& attribute)
3025         {
3026             m_lang = attribute.lang;
3027         }
3028         virtual void Accept(const Element& element)
3029         {}
3030
3031         virtual void Accept(const Text& text)
3032         {
3033             m_description = text.value;
3034         }
3035
3036         virtual void Verify()
3037         {
3038             ConfigParserData::LocalizedData& data = m_serviceAppInfo.m_localizedDataSet[m_lang];
3039             if (data.description.IsNull()) {
3040                 NormalizeString(m_description);
3041                 data.description = m_description;
3042             }
3043         }
3044
3045         ServiceDescriptionParser(ConfigParserData::ServiceAppInfo& data) :
3046             ElementParser(),
3047             m_serviceAppInfo(data)
3048         {}
3049
3050     private:
3051         DPL::String m_lang;
3052         DPL::String m_description;
3053         ConfigParserData::ServiceAppInfo& m_serviceAppInfo;
3054     };
3055
3056     virtual ActionFunc GetElementParser(const DPL::String& /*ns*/,
3057                                         const DPL::String& name)
3058     {
3059         if (name == L"service-content") {
3060             return std::bind(&ServiceAppParser::OnServiceContentElement, this);
3061         } else if (name == L"service-name") {
3062             return std::bind(&ServiceAppParser::OnServiceNameElement, this);
3063         } else if (name == L"service-icon") {
3064             return std::bind(&ServiceAppParser::OnServiceIconElement, this);
3065         } else if (name == L"service-description") {
3066             return std::bind(&ServiceAppParser::OnServiceDescriptionElement, this);
3067         } else {
3068             return &IgnoringParser::Create;
3069         }
3070     }
3071
3072     virtual void Accept(const Element& element)
3073     {}
3074
3075     virtual void Accept(const XmlAttribute& attribute)
3076     {
3077         if (attribute.name == L"id") {
3078             if (attribute.value.size() > 0) {
3079                 m_serviceId = attribute.value;
3080             }
3081         } else if (attribute.name == L"auto_restart") {
3082             if (attribute.value == L"true") {
3083                 m_autoRestart = true;
3084             } else if (attribute.value == L"false") {
3085                 m_autoRestart = false;
3086             } else {
3087                 ThrowMsg(Exception::ParseError, "Wrong boolean value");
3088             }
3089         } else if (attribute.name == L"on_boot") {
3090             if (attribute.value == L"true") {
3091                 m_onBoot = true;
3092             } else if (attribute.value == L"false") {
3093                 m_onBoot = false;
3094             } else {
3095                 ThrowMsg(Exception::ParseError, "Wrong boolean value");
3096             }
3097         }
3098     }
3099
3100     virtual void Accept(const Text& /*text*/)
3101     {
3102         ThrowMsg(Exception::ParseError, "param element must be empty");
3103     }
3104
3105     virtual void Verify()
3106     {
3107         if (m_serviceAppInfo.serviceContent.empty()) {
3108             ThrowMsg(Exception::ParseError, "service element must have service-content element");
3109             return;
3110         }
3111
3112         if (m_serviceId.empty()) {
3113             ThrowMsg(Exception::ParseError, "service attribute must have id attribute");
3114             return;
3115         }
3116         m_serviceAppInfo.serviceId = m_serviceId;
3117
3118         m_serviceAppInfo.autoRestart = m_autoRestart;
3119
3120         m_serviceAppInfo.onBoot = m_onBoot;
3121
3122         m_data.serviceAppInfoList.push_back(m_serviceAppInfo);
3123     }
3124
3125     ServiceAppParser(ConfigParserData& data) :
3126         ElementParser(),
3127         m_data(data),
3128         m_serviceAppInfo(),
3129         m_onBoot(false),
3130         m_autoRestart(false)
3131     {}
3132
3133     ElementParserPtr OnServiceContentElement()
3134     {
3135         return ElementParserPtr(new ServiceContentParser(m_serviceAppInfo));
3136     }
3137
3138     ElementParserPtr OnServiceNameElement()
3139     {
3140         return ElementParserPtr(new ServiceNameParser(m_serviceAppInfo));
3141     }
3142
3143     ElementParserPtr OnServiceIconElement()
3144     {
3145         return ElementParserPtr(new ServiceIconParser(m_serviceAppInfo));
3146     }
3147
3148     ElementParserPtr OnServiceDescriptionElement()
3149     {
3150         return ElementParserPtr(new ServiceDescriptionParser(m_serviceAppInfo));
3151     }
3152
3153   private:
3154     DPL::String m_serviceId;
3155     ConfigParserData& m_data;
3156     ConfigParserData::ServiceAppInfo m_serviceAppInfo;
3157     bool m_autoRestart;
3158     bool m_onBoot;
3159 };
3160 #endif
3161
3162 ElementParser::ActionFunc WidgetParser::GetElementParser(
3163     const DPL::String& /*ns*/,
3164     const DPL::String& name)
3165 {
3166     FuncMap::const_iterator it = m_map.find(name);
3167     if (it != m_map.end()) {
3168         return it->second;
3169     } else {
3170         return &IgnoringParser::Create; //ignore unknown according to w3c
3171     }
3172 }
3173
3174 WidgetParser::WidgetParser(ConfigParserData& data) :
3175     m_data(data),
3176     m_textDirection(Unicode::EMPTY)
3177 {
3178     m_map[L"name"] = std::bind(&WidgetParser::OnNameElement, this);
3179     m_map[L"access"] = std::bind(&WidgetParser::OnAccessElement, this);
3180     m_map[L"description"] = std::bind(&WidgetParser::OnDescriptionElement, this);
3181     m_map[L"author"] = std::bind(&WidgetParser::OnAuthorElement, this);
3182     m_map[L"license"] = std::bind(&WidgetParser::OnLicenseElement, this);
3183     m_map[L"icon"] = std::bind(&WidgetParser::OnIconElement, this);
3184     m_map[L"small-icon"] = std::bind(&WidgetParser::OnSmallIconElement, this);
3185     m_map[L"content"] = std::bind(&WidgetParser::OnContentElement, this);
3186     m_map[L"preference"] = std::bind(&WidgetParser::OnPreferenceElement, this);
3187     m_map[L"setting"] = std::bind(&WidgetParser::OnSettingElement, this);
3188     m_map[L"application"] = std::bind(&WidgetParser::OnApplicationElement, this);
3189 #ifdef IME_ENABLED
3190     m_map[L"ime"] = std::bind(&WidgetParser::OnImeElement, this);
3191 #endif
3192 #ifdef SERVICE_ENABLED
3193     m_map[L"service"] = std::bind(&WidgetParser::OnServiceAppElement, this);
3194 #endif
3195     m_map[L"splash"] = std::bind(&WidgetParser::OnSplashElement, this);
3196     m_map[L"background"] = std::bind(&WidgetParser::OnBackgroundElement, this);
3197     m_map[L"privilege"] = std::bind(&WidgetParser::OnPrivilegeElement, this);
3198     m_map[L"app-control"] = std::bind(&WidgetParser::OnAppControlElement, this);
3199     m_map[L"category"] = std::bind(&WidgetParser::OnCategoryElement, this);
3200 #ifdef DBOX_ENABLED
3201     m_map[L"app-widget"] = std::bind(&WidgetParser::OnAppWidgetElement, this);
3202 #endif
3203 #if ENABLE(CONTENT_SECURITY_POLICY)
3204     m_map[L"content-security-policy"] = std::bind(&WidgetParser::OnCspElement, this);
3205     m_map[L"content-security-policy-report-only"] = std::bind(&WidgetParser::OnCspReportOnlyElement, this);
3206 #endif
3207 #if ENABLE(ALLOW_NAVIGATION)
3208     m_map[L"allow-navigation"] = std::bind(&WidgetParser::OnAllowNavigationElement, this);
3209 #endif
3210     m_map[L"account"] = std::bind(&WidgetParser::OnAccountElement, this);
3211     m_map[L"metadata"] = std::bind(&WidgetParser::OnMetadataElement, this);
3212 }
3213
3214 ElementParserPtr WidgetParser::OnNameElement()
3215 {
3216     return ElementParserPtr(new NameParser(m_textDirection, m_data));
3217 }
3218
3219 ElementParserPtr WidgetParser::OnAccessElement()
3220 {
3221     return ElementParserPtr(new AccessParser(m_data));
3222 }
3223
3224 ElementParserPtr WidgetParser::OnDescriptionElement()
3225 {
3226     return ElementParserPtr(new DescriptionParser(m_textDirection, m_data));
3227 }
3228
3229 ElementParserPtr WidgetParser::OnAuthorElement()
3230 {
3231     return ElementParserPtr(new AuthorParser(m_textDirection, m_data));
3232 }
3233
3234 ElementParserPtr WidgetParser::OnLicenseElement()
3235 {
3236     return ElementParserPtr(new LicenseParser(m_textDirection, m_data));
3237 }
3238
3239 ElementParserPtr WidgetParser::OnIconElement()
3240 {
3241     return ElementParserPtr(new IconParser(m_data));
3242 }
3243
3244 ElementParserPtr WidgetParser::OnSmallIconElement()
3245 {
3246     return ElementParserPtr(new IconParser(m_data, true));
3247 }
3248
3249 ElementParserPtr WidgetParser::OnContentElement()
3250 {
3251     return ElementParserPtr(new ContentParser(m_data));
3252 }
3253
3254 ElementParserPtr WidgetParser::OnPreferenceElement()
3255 {
3256     return ElementParserPtr(new PreferenceParser(m_data));
3257 }
3258
3259 ElementParserPtr WidgetParser::OnSettingElement()
3260 {
3261     return ElementParserPtr(new SettingParser(m_data));
3262 }
3263
3264 ElementParserPtr WidgetParser::OnApplicationElement()
3265 {
3266     return ElementParserPtr(new ApplicationParser(m_data));
3267 }
3268
3269 ElementParserPtr WidgetParser::OnSplashElement()
3270 {
3271     return ElementParserPtr(new SplashParser(m_data));
3272 }
3273
3274 ElementParserPtr WidgetParser::OnBackgroundElement()
3275 {
3276     return ElementParserPtr(new BackgroundParser(m_data));
3277 }
3278
3279 ElementParserPtr WidgetParser::OnPrivilegeElement()
3280 {
3281     return ElementParserPtr(new PrivilegeParser(m_data));
3282 }
3283
3284 ElementParserPtr WidgetParser::OnAppControlElement()
3285 {
3286     return ElementParserPtr(new AppControlParser(m_data));
3287 }
3288
3289 ElementParserPtr WidgetParser::OnCategoryElement()
3290 {
3291     return ElementParserPtr(new CategoryParser(m_data));
3292 }
3293
3294 #ifdef DBOX_ENABLED
3295 ElementParserPtr WidgetParser::OnAppWidgetElement()
3296 {
3297     return ElementParserPtr(new AppWidgetParser(m_data));
3298 }
3299 #endif
3300
3301 ElementParserPtr WidgetParser::OnCspElement()
3302 {
3303     return ElementParserPtr(new CspParser(m_data));
3304 }
3305
3306 ElementParserPtr WidgetParser::OnCspReportOnlyElement()
3307 {
3308     return ElementParserPtr(new CspReportOnlyParser(m_data));
3309 }
3310
3311 ElementParserPtr WidgetParser::OnAllowNavigationElement()
3312 {
3313     return ElementParserPtr(new AllowNavigationParser(m_data));
3314 }
3315
3316 ElementParserPtr WidgetParser::OnAccountElement()
3317 {
3318     return ElementParserPtr(new AccountParser(m_data));
3319 }
3320
3321 ElementParserPtr WidgetParser::OnMetadataElement()
3322 {
3323     return ElementParserPtr(new MetadataParser(m_data));
3324 }
3325
3326 #ifdef IME_ENABLED
3327 ElementParserPtr WidgetParser::OnImeElement()
3328 {
3329     return ElementParserPtr(new ImeParser(m_data));
3330 }
3331 #endif
3332
3333 #ifdef SERVICE_ENABLED
3334 ElementParserPtr WidgetParser::OnServiceAppElement()
3335 {
3336     return ElementParserPtr(new ServiceAppParser(m_data));
3337 }
3338 #endif
3339
3340 void WidgetParser::Accept(const Element& element)
3341 {
3342     if (element.ns != ConfigurationNamespace::W3CWidgetNamespaceName &&
3343         element.ns != ConfigurationNamespace::TizenWebAppNamespaceName)
3344     {
3345         ThrowMsg(Exception::ParseError,
3346                  "Wrong xml namespace for widget element");
3347     }
3348 }
3349
3350 void WidgetParser::Accept(const Text& /*text*/)
3351 {
3352     ThrowMsg(Exception::ParseError, "widged element must be empty");
3353 }
3354
3355 void WidgetParser::Accept(const XmlAttribute& attribute)
3356 {
3357     if (attribute.name == L"id") {
3358         LibIri::Wrapper iri(DPL::ToUTF8String(attribute.value).c_str());
3359         //If may important tests starts to fail this test we will have
3360         //to consider commenting this test out again.
3361         if (iri.Validate()) {
3362             m_data.widget_id = attribute.value;
3363             NormalizeString(m_data.widget_id);
3364         } else {
3365             _W("Widget id validation failed: %ls", attribute.value.c_str());
3366         }
3367     } else if (attribute.name == L"version") {
3368         m_version = attribute.value;
3369         NormalizeString(m_version);
3370     } else if (attribute.name == L"min-version") {
3371         _D("min-version attribute was found. Value: %ls", attribute.value.c_str());
3372         m_minVersion = attribute.value;
3373         NormalizeString(m_minVersion);
3374         m_data.minVersionRequired = m_minVersion;
3375     } else if (attribute.name == L"height") {
3376         DPL::OptionalString value = attribute.value;
3377         NormalizeString(value);
3378         std::string v = DPL::ToUTF8String(*value);
3379
3380         if (!v.empty()) {
3381             unsigned char c = v.c_str()[0];
3382             if (isdigit(c)) {
3383                 int val = 0;
3384                 for (size_t i = 0; i < v.size(); ++i) {
3385                     c = v.c_str()[i];
3386                     if (isdigit(c)) {
3387                         val *= 10;
3388                         val += (c - '0');
3389                     } else {
3390                         break;
3391                     }
3392                 }
3393                 m_data.height = val;
3394             }
3395         }
3396     } else if (attribute.name == L"width") {
3397         DPL::OptionalString value = attribute.value;
3398         NormalizeString(value);
3399         std::string v = DPL::ToUTF8String(*value);
3400
3401         if (!v.empty()) {
3402             unsigned char c = v.c_str()[0];
3403             if (c >= '0' && c <= '9') {
3404                 int val = 0;
3405                 for (size_t i = 0; i < v.size(); ++i) {
3406                     c = v.c_str()[i];
3407                     if (c >= '0' && c <= '9') {
3408                         val *= 10;
3409                         val += (c - '0');
3410                     } else {
3411                         break;
3412                     }
3413                 }
3414                 m_data.width = val;
3415             }
3416         }
3417     } else if (attribute.name == L"viewmodes") {
3418         DPL::Tokenize(attribute.value,
3419                       L" ",
3420                       std::inserter(m_windowModes,
3421                                     m_windowModes.end()),
3422                       true);
3423     } else if (attribute.name == L"dir") {
3424         m_textDirection = Unicode::ParseDirAttribute(attribute);
3425     } else if (L"defaultlocale" == attribute.name) {
3426         if (!m_defaultlocale) {
3427             m_defaultlocale = attribute.value;
3428             NormalizeString(m_defaultlocale);
3429             std::string dl = DPL::ToUTF8String(*m_defaultlocale);
3430
3431             if (!LanguageSubtagRstTreeSingleton::Instance().
3432                     ValidateLanguageTag(dl)) {
3433                 _W("Language tag: %s is not valid", dl.c_str());
3434                 m_defaultlocale = DPL::OptionalString();
3435             } else {
3436                 _D("Default locale found %s", dl.c_str());
3437             }
3438         } else {
3439             _W("Ignoring subsequent default locale");
3440         }
3441         //Any other value consider as a namespace definition
3442     } else if (attribute.name == L"xmlns" || attribute.prefix == L"xmlns") {
3443         _D("Namespace domain: %ls", attribute.name.c_str());
3444         _D("Namespace value: %ls", attribute.value.c_str());
3445         m_nameSpaces[attribute.name] = attribute.value;
3446     }
3447     else {
3448         _E("Unknown attirbute: namespace=%ls, name=%ls, value=%ls",
3449             attribute.ns.c_str(), attribute.name.c_str(), attribute.value.c_str());
3450     }
3451 }
3452
3453 void WidgetParser::Verify()
3454 {
3455     FOREACH(mode, m_windowModes) {
3456         if (L"windowed" == *mode || L"floating" == *mode ||
3457             L"fullscreen" == *mode || L"maximized" == *mode ||
3458             L"minimized" == *mode)
3459         {
3460             m_data.windowModes.insert(*mode);
3461         }
3462     }
3463     if (!!m_version) {
3464         Unicode::UpdateTextWithDirectionMark(m_textDirection, &*m_version);
3465         m_data.version = m_version;
3466     }
3467     m_data.defaultlocale = m_defaultlocale;
3468     FOREACH(ns, m_nameSpaces) {
3469         m_data.nameSpaces.insert(ns->second);
3470     }
3471 }