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