6a6b6c4412d0095d946e85fac549c4ab196ee899
[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         m_data.appControlList.push_back(m_appControl);
1177     }
1178
1179     ElementParserPtr OnSourceElement()
1180     {
1181         return ElementParserPtr(new SourceParser(m_appControl));
1182     }
1183
1184     ElementParserPtr OnOperationElement()
1185     {
1186         return ElementParserPtr(new OperationParser(m_appControl));
1187     }
1188
1189     ElementParserPtr OnUriElement()
1190     {
1191         return ElementParserPtr(new UriParser(m_appControl));
1192     }
1193
1194     ElementParserPtr OnMimeElement()
1195     {
1196         return ElementParserPtr(new MimeParser(m_appControl));
1197     }
1198
1199     ElementParserPtr OnDispositionElement()
1200     {
1201         return ElementParserPtr(new DispositionParser(m_appControl));
1202     }
1203
1204     AppControlParser(ConfigParserData& data) :
1205         ElementParser(),
1206         m_data(data),
1207         m_appControl(L"")
1208     {}
1209
1210   private:
1211     ConfigParserData& m_data;
1212     ConfigParserData::AppControlInfo m_appControl;
1213 };
1214
1215 class ApplicationParser : public ElementParser
1216 {
1217   public:
1218     virtual ActionFunc GetElementParser(const DPL::String& /*ns*/,
1219                                         const DPL::String& /*name*/)
1220     {
1221         return &IgnoringParser::Create; //ignore unknown according to w3c
1222     }
1223
1224     virtual void Accept(const Text& /*text*/)
1225     {
1226         if (m_properNamespace) {
1227             ThrowMsg(Exception::ParseError, "application element must be empty");
1228         }
1229     }
1230
1231     virtual void Accept(const Element& element)
1232     {
1233         if (element.ns ==
1234             ConfigurationNamespace::TizenWebAppNamespaceName)
1235         {
1236             m_properNamespace = true;
1237         }
1238     }
1239
1240     virtual void Accept(const XmlAttribute& attribute)
1241     {
1242         if (m_properNamespace) {
1243             if (attribute.name == L"id") {
1244                 m_id = attribute.value;
1245                 NormalizeAndTrimSpaceString(m_id);
1246             } else if (attribute.name == L"package") {
1247                 m_package = attribute.value;
1248             } else if (attribute.name == L"required_version") {
1249                 m_version = attribute.value;
1250                 NormalizeString(m_version);
1251             } else {
1252                 ThrowMsg(Exception::ParseError,
1253                          "unknown attribute '" +
1254                          DPL::ToUTF8String(attribute.name) +
1255                          "' in application element");
1256             }
1257         }
1258     }
1259
1260     virtual void Verify()
1261     {
1262         VerifyIdAndPackage();
1263         VerifyVersion();
1264     }
1265
1266     ApplicationParser(ConfigParserData& data) :
1267         ElementParser(),
1268         m_data(data),
1269         m_id(DPL::OptionalString::Null),
1270         m_version(DPL::OptionalString::Null),
1271         m_properNamespace(false)
1272     {}
1273
1274     static const char* const REGEXP_ID;
1275
1276   private:
1277     void VerifyIdAndPackage()
1278     {
1279         if (!m_package)
1280         {
1281             ThrowMsg(Exception::ParseError,
1282                      "application element must have package attribute");
1283         }
1284         else
1285         {
1286             pcrecpp::RE re(REGEXP_PACKAGE);
1287             if (!re.FullMatch(DPL::ToUTF8String(*m_package)))
1288             {
1289                 ThrowMsg(Exception::ParseError,
1290                          "invalid format of package attribute");
1291             }
1292         }
1293
1294         if (!m_id) {
1295             ThrowMsg(Exception::ParseError,
1296                      "application element must have id attribute");
1297         }
1298         else
1299         {
1300             std::string package;
1301             pcrecpp::RE re(REGEXP_ID);
1302             if (!re.FullMatch(DPL::ToUTF8String(*m_id), &package))
1303             {
1304                 ThrowMsg(Exception::ParseError,
1305                          "invalid format of id attribute");
1306             }
1307             if (package != DPL::ToUTF8String(*m_package))
1308             {
1309                 ThrowMsg(Exception::ParseError,
1310                          "invalid package prefix in id attribute");
1311             }
1312         }
1313
1314         m_data.tizenAppId = m_id;
1315         m_data.tizenPkgId = m_package;
1316     }
1317
1318     void VerifyVersion()
1319     {
1320         if (!m_version)
1321         {
1322             ThrowMsg(Exception::ParseError,
1323                      "application element must have required_version attribute");
1324         }
1325         else
1326         {
1327             pcrecpp::RE re(REGEXP_VERSION);
1328             if (!re.FullMatch(DPL::ToUTF8String(*m_version)))
1329             {
1330                 ThrowMsg(Exception::ParseError,
1331                          "invalid format of version attribute");
1332             }
1333         }
1334
1335         m_data.tizenMinVersionRequired = m_version;
1336     }
1337
1338     static const char* const REGEXP_PACKAGE;
1339     static const char* const REGEXP_VERSION;
1340
1341     ConfigParserData& m_data;
1342     DPL::OptionalString m_id;
1343     DPL::OptionalString m_package;
1344     DPL::OptionalString m_version;
1345     bool m_properNamespace;
1346 };
1347
1348 const char* const ApplicationParser::REGEXP_PACKAGE = "[0-9A-Za-z]{10}";
1349 const char* const ApplicationParser::REGEXP_ID = "([0-9A-Za-z]{10})\\.[0-9A-Za-z]{1,52}";
1350 const char* const ApplicationParser::REGEXP_VERSION = "\\d+\\.\\d+(\\.\\d+)?";
1351
1352 class SplashParser : public ElementParser
1353 {
1354   public:
1355     virtual ActionFunc GetElementParser(const DPL::String& /*ns*/,
1356                                         const DPL::String& /*name*/)
1357     {
1358         return &IgnoringParser::Create; //ignore unknown according to w3c
1359     }
1360
1361     virtual void Accept(const XmlAttribute& attribute)
1362     {
1363         if (m_properNamespace)
1364         {
1365             if (attribute.name == L"src") {
1366                 if (attribute.value.size() > 0) {
1367                     m_src = attribute.value;
1368                 }
1369             }
1370         }
1371     }
1372
1373     virtual void Accept(const Element& element)
1374     {
1375         if (element.ns ==
1376             ConfigurationNamespace::TizenWebAppNamespaceName)
1377         {
1378             m_properNamespace = true;
1379         }
1380     }
1381
1382     virtual void Accept(const Text& /*text*/)
1383     {}
1384
1385     virtual void Verify()
1386     {
1387         if (m_src.IsNull())
1388         {
1389             _W("src attribute of splash element is mandatory - ignoring");
1390             return;
1391         }
1392
1393         m_data.splashImgSrc = m_src;
1394     }
1395
1396     SplashParser(ConfigParserData& data) :
1397         ElementParser(),
1398         m_data(data),
1399         m_properNamespace(false)
1400     {}
1401
1402   private:
1403     DPL::OptionalString m_src;
1404     ConfigParserData& m_data;
1405     bool m_properNamespace;
1406 };
1407
1408 class BackgroundParser : public ElementParser
1409 {
1410   public:
1411     virtual ActionFunc GetElementParser(const DPL::String& /*ns*/,
1412                                         const DPL::String& /*name*/)
1413     {
1414         return &IgnoringParser::Create; //ignore unknown according to w3c
1415     }
1416
1417     virtual void Accept(const XmlAttribute& attribute)
1418     {
1419         if (attribute.name == L"src") {
1420             if (attribute.value.size() > 0) {
1421                 m_src = attribute.value;
1422             }
1423         }
1424     }
1425
1426     virtual void Accept(const Element& /*element*/)
1427     {}
1428
1429     virtual void Accept(const Text& /*text*/)
1430     {}
1431
1432     virtual void Verify()
1433     {
1434         if (m_src.IsNull()) {
1435             _W("src attribute of background element is mandatory - ignoring");
1436             return;
1437         }
1438
1439         m_data.backgroundPage = m_src;
1440     }
1441
1442     explicit BackgroundParser(ConfigParserData& data) :
1443         m_data(data)
1444     {}
1445
1446   private:
1447     DPL::OptionalString m_src;
1448     ConfigParserData& m_data;
1449 };
1450
1451 class PrivilegeParser : public ElementParser
1452 {
1453   public:
1454     virtual ActionFunc GetElementParser(const DPL::String& /*ns*/,
1455                                         const DPL::String& /*name*/)
1456     {
1457         return &IgnoringParser::Create; //ignore unknown according to w3c
1458     }
1459
1460     virtual void Accept(const Text& /*text*/)
1461     {}
1462
1463     virtual void Accept(const Element& element)
1464     {
1465         if (element.ns ==
1466             ConfigurationNamespace::TizenWebAppNamespaceName)
1467         {
1468             m_properNamespace = true;
1469         }
1470         _D("element");
1471     }
1472
1473     virtual void Accept(const XmlAttribute& attribute)
1474     {
1475         if (m_properNamespace) {
1476             if (attribute.name == L"name") {
1477                 m_feature.name = attribute.value;
1478                 m_privilege.name = attribute.value;
1479             }
1480         }
1481     }
1482
1483     virtual void Verify()
1484     {
1485         LibIri::Wrapper iri(DPL::ToUTF8String(m_feature.name).c_str());
1486
1487         if (m_feature.name != L"") {
1488             if (iri.Validate()) {
1489                 if (m_data.featuresList.find(m_feature) ==
1490                     m_data.featuresList.end())
1491                 {
1492                     m_data.featuresList.insert(m_feature);
1493                 } else {
1494                     _D("Ignoring feature with name %ls", m_feature.name.c_str());
1495                 }
1496             }
1497         }
1498
1499         LibIri::Wrapper iriPrivilege(
1500             DPL::ToUTF8String(m_privilege.name).c_str());
1501
1502         if (m_privilege.name != L"") {
1503             if (iriPrivilege.Validate()) {
1504                 if (m_data.privilegeList.find(m_privilege) ==
1505                     m_data.privilegeList.end())
1506                 {
1507                     m_data.privilegeList.insert(m_privilege);
1508                 } else {
1509                     _D("Ignoring privilege with name %ls", m_privilege.name.c_str());
1510                 }
1511             }
1512         }
1513     }
1514
1515     PrivilegeParser(ConfigParserData& data) :
1516         ElementParser(),
1517         m_data(data),
1518         m_feature(L""),
1519         m_privilege(L""),
1520         m_properNamespace(false)
1521     {}
1522
1523   private:
1524     ConfigParserData& m_data;
1525     ConfigParserData::Feature m_feature;
1526     ConfigParserData::Privilege m_privilege;
1527     bool m_properNamespace;
1528 };
1529
1530 class CategoryParser : public ElementParser
1531 {
1532   public:
1533     virtual ActionFunc GetElementParser(const DPL::String& /*ns*/,
1534                                         const DPL::String& /*name*/)
1535     {
1536         return &IgnoringParser::Create; //ignore unknown according to w3c
1537     }
1538
1539     virtual void Accept(const XmlAttribute& attribute)
1540     {
1541         if (attribute.name == L"name") {
1542             if (attribute.value.size() > 0) {
1543                 m_name = attribute.value;
1544             }
1545         }
1546     }
1547
1548     virtual void Accept(const Element& /*element*/)
1549     {}
1550
1551     virtual void Accept(const Text& /*text*/)
1552     {}
1553
1554     virtual void Verify()
1555     {
1556         if (m_name.IsNull()) {
1557             _W("name attribute of category element is mandatory - ignoring");
1558             return;
1559         }
1560
1561         if (m_data.categoryList.find(*m_name) ==
1562             m_data.categoryList.end())
1563         {
1564             m_data.categoryList.insert(*m_name);
1565         }
1566     }
1567
1568     explicit CategoryParser(ConfigParserData& data) :
1569         m_data(data)
1570     {}
1571
1572   private:
1573     DPL::OptionalString m_name;
1574     ConfigParserData& m_data;
1575 };
1576
1577 class AppWidgetParser : public ElementParser
1578 {
1579   public:
1580
1581     struct BoxLabelParser : public ElementParser
1582     {
1583         virtual ActionFunc GetElementParser(const DPL::String& /*ns*/,
1584                                             const DPL::String& /*name*/)
1585         {
1586             return &IgnoringParser::Create; //ignore unknown according to w3c
1587         }
1588
1589         virtual void Accept(const XmlAttribute& attribute)
1590         {
1591             if (m_properNamespace) {
1592                  m_lang = attribute.lang;
1593             }
1594         }
1595         virtual void Accept(const Element& element)
1596         {
1597             if (element.ns ==
1598                 ConfigurationNamespace::TizenWebAppNamespaceName)
1599             {
1600                 m_properNamespace = true;
1601             }
1602         }
1603
1604         virtual void Accept(const Text& text)
1605         {
1606             if (m_properNamespace) {
1607                 m_label = text.value;
1608             }
1609         }
1610
1611         virtual void Verify()
1612         {
1613             std::pair<DPL::String, DPL::String> boxLabel;
1614             if (m_label.empty()) {
1615                 _W("box-label element is empty");
1616                 boxLabel.first = DPL::FromUTF8String("");
1617                 boxLabel.second = DPL::FromUTF8String("");
1618                 m_data.m_label.push_back(boxLabel);
1619             }
1620             else {
1621                 boxLabel.first = m_lang;
1622                 boxLabel.second = m_label;
1623                 m_data.m_label.push_back(boxLabel);
1624             }
1625         }
1626
1627         BoxLabelParser(ConfigParserData::LiveboxInfo& data) :
1628             ElementParser(),
1629             m_properNamespace(false),
1630             m_data(data)
1631         {}
1632
1633       private:
1634         DPL::String m_lang;
1635         DPL::String m_label;
1636         bool m_properNamespace;
1637         ConfigParserData::LiveboxInfo& m_data;
1638     };
1639
1640     struct BoxIconParser : public ElementParser
1641     {
1642         virtual ActionFunc GetElementParser(const DPL::String& /*ns*/,
1643                                             const DPL::String& /*name*/)
1644         {
1645             return &IgnoringParser::Create; //ignore unknown according to w3c
1646         }
1647
1648         virtual void Accept(const XmlAttribute& attribute)
1649         {
1650             if (m_properNamespace) {
1651                 if (attribute.name == L"src") {
1652                     m_icon = attribute.value;
1653                 }
1654             }
1655         }
1656
1657         virtual void Accept(const Element& element)
1658         {
1659             if (element.ns ==
1660                 ConfigurationNamespace::TizenWebAppNamespaceName)
1661             {
1662                 m_properNamespace = true;
1663             }
1664         }
1665
1666         virtual void Accept(const Text& /*text*/)
1667         {}
1668
1669         virtual void Verify()
1670         {
1671             if (m_icon.empty()) {
1672                 ThrowMsg(Exception::ParseError,
1673                     "src attribute of box-icon element is mandatory - ignoring");
1674             }
1675             m_data.m_icon = m_icon;
1676         }
1677
1678         explicit BoxIconParser(ConfigParserData::LiveboxInfo& data) :
1679             ElementParser(),
1680             m_properNamespace(false),
1681             m_data(data)
1682         {}
1683
1684       private:
1685         DPL::String m_icon;
1686         bool m_properNamespace;
1687         ConfigParserData::LiveboxInfo& m_data;
1688     };
1689
1690     struct BoxContentParser : public ElementParser
1691     {
1692         struct BoxSizeParser : public ElementParser
1693         {
1694             virtual ActionFunc GetElementParser(const DPL::String& /*ns*/,
1695                                                 const DPL::String& /*name*/)
1696             {
1697                 return &IgnoringParser::Create; //ignore unknown according to w3c
1698             }
1699
1700             virtual void Accept(const XmlAttribute& attribute)
1701             {
1702                 if (m_properNamespace) {
1703                     if (attribute.name == L"preview") {
1704                         m_preview = attribute.value;
1705                     }
1706                     if (attribute.name == L"use-decoration") {
1707                         m_useDecoration = attribute.value;
1708                     }
1709                 }
1710             }
1711
1712             virtual void Accept(const Element& element)
1713             {
1714                 if (element.ns ==
1715                     ConfigurationNamespace::TizenWebAppNamespaceName)
1716                 {
1717                     m_properNamespace = true;
1718                 }
1719             }
1720
1721             virtual void Accept(const Text& text)
1722             {
1723                 if (m_properNamespace) {
1724                     m_size = text.value;
1725                 }
1726             }
1727
1728             virtual void Verify()
1729             {
1730                 if(m_size.empty()) {
1731                     ThrowMsg(Exception::ParseError,
1732                         "size is mandatory - ignoring");
1733                 }
1734
1735                 ConfigParserData::LiveboxInfo::BoxSizeInfo boxSizeInfo;
1736                 boxSizeInfo.m_size = m_size;
1737                 boxSizeInfo.m_preview = m_preview;
1738                 boxSizeInfo.m_useDecoration = m_useDecoration;
1739                 m_data.m_boxSize.push_back(boxSizeInfo);
1740             }
1741
1742             explicit BoxSizeParser(
1743                 ConfigParserData::LiveboxInfo::BoxContentInfo& data) :
1744                 ElementParser(),
1745                 m_properNamespace(false),
1746                 m_data(data)
1747             {}
1748
1749           private:
1750             DPL::String m_size;
1751             DPL::String m_preview;
1752             DPL::String m_useDecoration;
1753             bool m_properNamespace;
1754             ConfigParserData::LiveboxInfo::BoxContentInfo& m_data;
1755         };
1756
1757         struct PdParser : public ElementParser
1758         {
1759             virtual ActionFunc GetElementParser(const DPL::String& /*ns*/,
1760                                                 const DPL::String& /*name*/)
1761             {
1762                 return &IgnoringParser::Create; //ignore unknown according to w3c
1763             }
1764
1765             virtual void Accept(const XmlAttribute& attribute)
1766             {
1767                 if (m_properNamespace) {
1768                     if (attribute.name == L"src") {
1769                         m_src = attribute.value;
1770                     } else if (attribute.name == L"width") {
1771                         m_width = attribute.value;
1772                     } else if (attribute.name == L"height") {
1773                         m_height = attribute.value;
1774                     } else if (attribute.name == L"fast-open") {
1775                         m_fastOpen= attribute.value;
1776                     }
1777                 }
1778             }
1779
1780             virtual void Accept(const Element& element)
1781             {
1782                 if (element.ns ==
1783                     ConfigurationNamespace::TizenWebAppNamespaceName)
1784                 {
1785                     m_properNamespace = true;
1786                 }
1787             }
1788
1789             virtual void Accept(const Text& /*text*/)
1790             {}
1791
1792             virtual void Verify()
1793             {
1794                 if (m_src.empty()) {
1795                     ThrowMsg(Exception::ParseError,
1796                         "src attribute of pd element is mandatory - ignoring");
1797                 }
1798
1799                 if (m_width.empty()) {
1800                     ThrowMsg(Exception::ParseError,
1801                         "width attribute of pd element is mandatory - ignoring");
1802                 }
1803
1804                 if (m_height.empty()) {
1805                     ThrowMsg(Exception::ParseError,
1806                         "height attribute of pd element is mandatory - ignoring");
1807                 }
1808
1809                 if (ConvertToInt(m_width).IsNull()) {
1810                     ThrowMsg(Exception::ParseError,
1811                         "width attribute of pd element cannot be converted to int - ignoring. value: " << m_width);
1812                 }
1813
1814
1815                 DPL::OptionalInt height = ConvertToInt(m_height);
1816
1817                 if (height.IsNull()) {
1818                     ThrowMsg(Exception::ParseError,
1819                         "height attribute of pd element cannot be converted to int - ignoring. value: " << m_height);
1820                 }
1821
1822                 if (*height < 1) {
1823                     m_height = L"1";
1824                     _D("height attribute of pd element shouldn't be less than 1. Changed to 1 from %d", *height);
1825                 } else if (*height > 380){
1826                     m_height = L"380";
1827                     _D("height attribute of pd element shouldn't be greater than 380. Changed to 380 from %d", *height);
1828                 }
1829
1830                 m_data.m_pdSrc = m_src;
1831                 m_data.m_pdWidth = m_width;
1832                 m_data.m_pdHeight = m_height;
1833                 m_data.m_pdFastOpen = m_fastOpen;
1834             }
1835
1836             explicit PdParser(
1837                 ConfigParserData::LiveboxInfo::BoxContentInfo& data) :
1838                 ElementParser(),
1839                 m_properNamespace(false),
1840                 m_data(data)
1841             {}
1842
1843           private:
1844             DPL::OptionalInt ConvertToInt(const DPL::String& intAsString)
1845             {
1846                 char * endptr;
1847                 std::string tempStr = DPL::ToUTF8String(intAsString);
1848                 const char * intAsString_c = tempStr.c_str();
1849                 errno = 0;
1850                 long int intAsString_i = strtol(intAsString_c, &endptr, 10);
1851
1852                 if ((errno == ERANGE && (intAsString_i == LONG_MAX || intAsString_i == LONG_MIN))
1853                         || intAsString_i > INT_MAX || intAsString_i < INT_MIN
1854                         || *endptr != '\0') {
1855                     return DPL::OptionalInt::Null;
1856                 }
1857
1858                 return static_cast<int>(intAsString_i);
1859             }
1860
1861             DPL::String m_src;
1862             DPL::String m_width;
1863             DPL::String m_height;
1864             DPL::String m_fastOpen;
1865
1866             bool m_properNamespace;
1867             ConfigParserData::LiveboxInfo::BoxContentInfo& m_data;
1868         };
1869
1870         virtual ActionFunc GetElementParser(const DPL::String& /*ns*/,
1871                                             const DPL::String& name)
1872         {
1873             if (name == L"box-size") {
1874                 return DPL::MakeDelegate(
1875                            this,
1876                            &AppWidgetParser::BoxContentParser::
1877                                OnBoxSizeElement);
1878             } else if (name == L"pd") {
1879                 return DPL::MakeDelegate(
1880                            this,
1881                            &AppWidgetParser::BoxContentParser::
1882                                OnPdElement);
1883             } else {
1884                 ThrowMsg(Exception::ParseError,
1885                          "No element parser for name: " << name);
1886             }
1887         }
1888
1889         virtual void Accept(const XmlAttribute& attribute)
1890         {
1891             if (m_properNamespace) {
1892                 if (attribute.name == L"src") {
1893                     m_box.m_boxSrc = attribute.value;
1894                 }
1895                 if (attribute.name == L"mouse-event") {
1896                     m_box.m_boxMouseEvent = attribute.value;
1897                 }
1898                 if (attribute.name == L"touch-effect") {
1899                     m_box.m_boxTouchEffect = attribute.value;
1900                 }
1901             }
1902         }
1903
1904         virtual void Accept(const Element& element)
1905         {
1906             if (element.ns ==
1907                 ConfigurationNamespace::TizenWebAppNamespaceName)
1908             {
1909                 m_properNamespace = true;
1910             }
1911         }
1912
1913         virtual void Accept(const Text& /*text*/)
1914         {}
1915
1916         virtual void Verify()
1917         {
1918             if (m_box.m_boxSrc.empty()) {
1919                 ThrowMsg(Exception::ParseError,
1920                     "src attribute of box-content element is mandatory - ignoring");
1921             }
1922
1923             if (!m_box.m_boxMouseEvent.empty() &&
1924                     CheckIfNotTrueNorFalse(m_box.m_boxMouseEvent))
1925             {
1926                 ThrowMsg(Exception::ParseError,
1927                     "mouse-event attribute of box-content element should be true or false - ignoring");
1928             }
1929
1930             if (!m_box.m_boxTouchEffect.empty() &&
1931                     CheckIfNotTrueNorFalse(m_box.m_boxTouchEffect))
1932             {
1933                 ThrowMsg(Exception::ParseError,
1934                     "touch-effect attribute of box-content element should be true or false - ignoring");
1935             }
1936
1937             if (m_box.m_boxMouseEvent.empty()) {
1938                 m_box.m_boxMouseEvent = L"false";
1939             }
1940
1941             if (m_box.m_boxTouchEffect.empty()) {
1942                 m_box.m_boxTouchEffect = L"true";
1943             }
1944
1945             if (m_box.m_boxSize.empty()) {
1946                 ThrowMsg(Exception::ParseError,
1947                     "box-size element of box-content element not found - ignoring");
1948             }
1949
1950             m_data.m_boxInfo = m_box;
1951         }
1952
1953         explicit BoxContentParser(ConfigParserData::LiveboxInfo& data) :
1954             ElementParser(),
1955             m_properNamespace(false),
1956             m_data(data)
1957         {}
1958
1959         ElementParserPtr OnBoxSizeElement()
1960         {
1961             return ElementParserPtr(new BoxSizeParser(m_box));
1962         }
1963
1964         ElementParserPtr OnPdElement()
1965         {
1966             return ElementParserPtr(new PdParser(m_box));
1967         }
1968
1969       private:
1970         bool m_properNamespace;
1971         ConfigParserData::LiveboxInfo& m_data;
1972         ConfigParserData::LiveboxInfo::BoxContentInfo m_box;
1973     };
1974
1975     virtual ActionFunc GetElementParser(const DPL::String& /*ns*/,
1976                                         const DPL::String& name)
1977     {
1978         if (name == L"box-label") {
1979             return DPL::MakeDelegate(this, &AppWidgetParser::OnBoxLabelElement);
1980         } else if (name == L"box-icon") {
1981             return DPL::MakeDelegate(this, &AppWidgetParser::OnBoxIconElement);
1982         } else if (name == L"box-content") {
1983             return DPL::MakeDelegate(this, &AppWidgetParser::OnBoxContentElement);
1984         } else {
1985             return &IgnoringParser::Create; //ignore unknown according to w3c
1986         }
1987     }
1988
1989     virtual void Accept(const XmlAttribute& attribute)
1990     {
1991         if (m_properNamespace) {
1992             if (attribute.name == L"id") {
1993                 m_liveboxId = attribute.value;
1994             } else if (attribute.name == L"primary") {
1995                 m_primary = attribute.value;
1996             } else if (attribute.name == L"auto-launch") {
1997                 m_autoLaunch = attribute.value;
1998             } else if (attribute.name == L"update-period") {
1999                 m_updatePeriod = attribute.value;
2000             } else if (attribute.name == L"type") {
2001                 m_type = attribute.value;
2002             }
2003         }
2004     }
2005
2006     virtual void Accept(const Element& element)
2007     {
2008         if (element.ns ==
2009             ConfigurationNamespace::TizenWebAppNamespaceName)
2010         {
2011             m_properNamespace = true;
2012         }
2013     }
2014
2015     virtual void Accept(const Text& /*text*/)
2016     {}
2017
2018     virtual void Verify()
2019     {
2020         if (m_liveboxId.empty()) {
2021             ThrowMsg(Exception::ParseError,
2022                  "app-widget element must have id attribute");
2023         }
2024         else
2025         {
2026             pcrecpp::RE re(REGEXP_ID_STRING.c_str());
2027             if (!re.FullMatch(DPL::ToUTF8String(m_liveboxId)))
2028             {
2029                 ThrowMsg(Exception::ParseError,
2030                      "invalid format of app-widget id attribute");
2031             }
2032         }
2033
2034         if (m_primary.empty())
2035         {
2036             ThrowMsg(Exception::ParseError,
2037                  "app-widget element must have primary attribute");
2038         } else if (CheckIfNotTrueNorFalse(m_primary))
2039         {
2040             ThrowMsg(Exception::ParseError,
2041                 "auto-launch attribute of app-widget element should be true or false - ignoring");
2042         }
2043
2044         if (!m_autoLaunch.empty() &&
2045                 CheckIfNotTrueNorFalse(m_autoLaunch))
2046         {
2047             ThrowMsg(Exception::ParseError,
2048                 "auto-launch attribute of app-widget element should be true or false - ignoring");
2049         }
2050
2051         if (!m_updatePeriod.empty())
2052         {
2053             char * endptr;
2054             errno = 0;
2055             std::string tempStr = DPL::ToUTF8String(m_updatePeriod);
2056
2057             //set standard locale to fix decimal point mark - '.'
2058             std::string currentLocale = setlocale(LC_NUMERIC, NULL);
2059             if (NULL == setlocale(LC_NUMERIC, "C"))
2060                 _W("Failed to change locale to \"C\"");
2061             double updatePeriod = strtod(tempStr.c_str(), &endptr);
2062
2063             //go back to previous locale
2064             if (NULL == setlocale(LC_NUMERIC, currentLocale.c_str()))
2065                 _W("Failed to set previous locale");
2066
2067             if ((errno == ERANGE && (updatePeriod == -HUGE_VAL || updatePeriod == HUGE_VAL))
2068                     || *endptr != '\0') {
2069                 ThrowMsg(Exception::ParseError,
2070                     "update-period attribute of app-widget element should be a number - ignoring. current value: " << m_updatePeriod);
2071             } else if (updatePeriod < 1800.0) {
2072                 _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());
2073                 m_updatePeriod = L"1800.0";
2074             }
2075         }
2076
2077         if (m_autoLaunch.empty()) {
2078             m_autoLaunch = L"false";
2079         }
2080
2081         if(m_livebox.m_label.empty()) {
2082             ThrowMsg(Exception::ParseError,
2083                 "box-label element of app-widget element not found - ignoring");
2084         }
2085
2086         if(!m_boxContentFound) {
2087             ThrowMsg(Exception::ParseError,
2088                 "box-content element of app-widget element not found - ignoring");
2089         }
2090
2091         m_livebox.m_liveboxId = m_liveboxId;
2092         m_livebox.m_primary = m_primary;
2093         m_livebox.m_autoLaunch = m_autoLaunch;
2094         m_livebox.m_updatePeriod = m_updatePeriod;
2095         m_livebox.m_type = m_type;
2096
2097         m_data.m_livebox.push_back(m_livebox);
2098     }
2099
2100     explicit AppWidgetParser(ConfigParserData& data) :
2101         ElementParser(),
2102         m_data(data),
2103         m_properNamespace(false),
2104         m_boxContentFound(false)
2105     {
2106         m_livebox = ConfigParserData::LiveboxInfo();
2107     }
2108
2109     ElementParserPtr OnBoxLabelElement()
2110     {
2111
2112         return ElementParserPtr(new BoxLabelParser(m_livebox));
2113     }
2114
2115     ElementParserPtr OnBoxIconElement()
2116     {
2117         return ElementParserPtr(new BoxIconParser(m_livebox));
2118     }
2119
2120     ElementParserPtr OnBoxContentElement()
2121     {
2122         m_boxContentFound = true;
2123         return ElementParserPtr(new BoxContentParser(m_livebox));
2124     }
2125
2126   private:
2127     static std::string REGEXP_ID_STRING;
2128     ConfigParserData& m_data;
2129     ConfigParserData::LiveboxInfo m_livebox;
2130     DPL::String m_liveboxId;
2131     DPL::String m_primary;
2132     DPL::String m_autoLaunch;
2133     DPL::String m_updatePeriod;
2134     DPL::String m_type;
2135     bool m_properNamespace;
2136     bool m_boxContentFound;
2137
2138     static bool CheckIfNotTrueNorFalse(const DPL::String &stringToCheck)
2139     {
2140         return stringToCheck.compare(L"true") != 0 && stringToCheck.compare(L"false") != 0;
2141     }
2142 };
2143
2144 std::string AppWidgetParser::REGEXP_ID_STRING = std::string(ApplicationParser::REGEXP_ID) + "\\.[0-9A-Za-z]+";
2145
2146 class AllowNavigationParser : public ElementParser
2147 {
2148   public:
2149     AllowNavigationParser(ConfigParserData& data) :
2150       ElementParser(),
2151       m_data(data),
2152       m_properNamespace(false)
2153     {}
2154
2155     virtual ActionFunc GetElementParser(const DPL::String& /*ns*/,
2156                                         const DPL::String& /*name*/)
2157     {
2158         return &IgnoringParser::Create; //ignore unknown according to w3c
2159     }
2160
2161     virtual void Accept(const Element& element)
2162     {
2163         if (element.ns == ConfigurationNamespace::TizenWebAppNamespaceName) {
2164             m_properNamespace = true;
2165         }
2166     }
2167
2168     virtual void Accept(const Text& text)
2169     {
2170         if (m_properNamespace)
2171         {
2172             m_origin = text.value;
2173         }
2174     }
2175
2176     virtual void Accept(const XmlAttribute& /*attribute*/)
2177     {
2178     }
2179
2180     virtual void Verify()
2181     {
2182         if (m_data.allowNavigationEncountered || !m_properNamespace)
2183         {
2184             return;
2185         }
2186         m_data.allowNavigationEncountered = true;
2187
2188         if (m_origin.IsNull()) {
2189             _W("data is empty");
2190             return;
2191         }
2192
2193         char* data = strdup(DPL::ToUTF8String(*m_origin).c_str());
2194         char* ptr = strtok(data," ");
2195         while (ptr != NULL) {
2196             std::string origin = ptr;
2197             ptr = strtok(NULL," ");
2198             if(origin == "*") {
2199                 ConfigParserData::AllowNavigationInfo info(L"*", L"*");
2200                 m_data.allowNavigationInfoList.push_back(info);
2201                 continue;
2202             }
2203
2204             DPL::ScopedPtr<iri_t> iri(iri_parse(origin.c_str()));
2205             if (!iri->host || strlen(iri->host) == 0) {
2206                 // input origin should has schem and host
2207                 // in case of file scheme path is filled
2208                 // "http://"
2209                 _W("input origin isn't verified");
2210                 continue;
2211             }
2212             DPL::String scheme = L"*";
2213             if (iri->scheme && strlen(iri->scheme) != 0) {
2214                 scheme = DPL::FromUTF8String(iri->scheme);
2215             }
2216             ConfigParserData::AllowNavigationInfo info(
2217                 scheme,
2218                 DPL::FromUTF8String(iri->host));
2219             m_data.allowNavigationInfoList.push_back(info);
2220         }
2221         free(data);
2222     }
2223
2224   private:
2225     DPL::OptionalString m_origin;
2226     ConfigParserData& m_data;
2227     bool m_properNamespace;
2228 };
2229
2230 class CspParser : public ElementParser
2231 {
2232   public:
2233     virtual ActionFunc GetElementParser(const DPL::String& /*ns*/,
2234                                         const DPL::String& /*name*/)
2235     {
2236         return &IgnoringParser::Create; //ignore unknown according to w3c
2237     }
2238
2239     CspParser(ConfigParserData& data) :
2240         ElementParser(),
2241         m_data(data),
2242         m_properNamespace(false)
2243     {}
2244
2245     virtual void Accept(const Element& element)
2246     {
2247         if (element.ns == ConfigurationNamespace::TizenWebAppNamespaceName) {
2248             m_properNamespace = true;
2249         }
2250     }
2251
2252     virtual void Accept(const XmlAttribute& /*attribute*/)
2253     {}
2254
2255     virtual void Accept(const Text& text)
2256     {
2257         if (m_properNamespace) {
2258             m_policy = text.value;
2259         }
2260     }
2261
2262     virtual void Verify()
2263     {
2264         if (!m_policy.IsNull()) {
2265             m_data.cspPolicy = *m_policy;
2266         }
2267     }
2268
2269   private:
2270     ConfigParserData& m_data;
2271     bool m_properNamespace;
2272     DPL::OptionalString m_policy;
2273 };
2274
2275 class CspReportOnlyParser : public ElementParser
2276 {
2277   public:
2278     virtual ActionFunc GetElementParser(const DPL::String& /*ns*/,
2279                                         const DPL::String& /*name*/)
2280     {
2281         return &IgnoringParser::Create; //ignore unknown according to w3c
2282     }
2283
2284     CspReportOnlyParser(ConfigParserData& data) :
2285         ElementParser(),
2286         m_data(data),
2287         m_properNamespace(false)
2288     {}
2289
2290     virtual void Accept(const Element& element)
2291     {
2292         if (element.ns == ConfigurationNamespace::TizenWebAppNamespaceName) {
2293             m_properNamespace = true;
2294         }
2295     }
2296
2297     virtual void Accept(const XmlAttribute& /*attribute*/)
2298     {}
2299
2300     virtual void Accept(const Text& text)
2301     {
2302         if (m_properNamespace) {
2303             m_policy = text.value;
2304         }
2305     }
2306
2307     virtual void Verify()
2308     {
2309         if (!m_policy.IsNull()) {
2310             m_data.cspPolicyReportOnly = *m_policy;
2311         }
2312     }
2313
2314   private:
2315     ConfigParserData& m_data;
2316     bool m_properNamespace;
2317     DPL::OptionalString m_policy;
2318 };
2319
2320 class AccountParser : public ElementParser
2321 {
2322   public:
2323     struct AccountProviderParser : public ElementParser
2324     {
2325       public:
2326
2327           struct IconParser : public ElementParser
2328         {
2329             public:
2330                 virtual ActionFunc GetElementParser(const DPL::String& /*ns*/,
2331                         const DPL::String& /*name*/)
2332                 {
2333                     return &IgnoringParser::Create; //ignore unknown according to w3c
2334                 }
2335
2336                 virtual void Accept(const Text& text)
2337                 {
2338                     if (text.value == L"") {
2339                         return;
2340                     }
2341                     m_value = text.value;
2342                 }
2343
2344                 virtual void Accept(const Element& /*element*/)
2345                 {}
2346
2347                 virtual void Accept(const XmlAttribute& attribute)
2348                 {
2349                     if (attribute.name == L"section") {
2350                         if (attribute.value == L"account") {
2351                             m_type = ConfigParserData::IconSectionType::DefaultIcon;
2352                         } else if (attribute.value == L"account-small") {
2353                             m_type = ConfigParserData::IconSectionType::SmallIcon;
2354                         }
2355                     }
2356                 }
2357
2358                 virtual void Verify()
2359                 {
2360                     if (m_value.IsNull() || *m_value == L"") {
2361                         return;
2362                     }
2363
2364                     std::pair<ConfigParserData::IconSectionType, DPL::String> icon;
2365                     icon.first = m_type;
2366                     icon.second = *m_value;
2367
2368                     m_data.m_iconSet.insert(icon);
2369                 }
2370
2371                 IconParser(ConfigParserData::AccountProvider& data) :
2372                     ElementParser(),
2373                     m_properNamespace(false),
2374                     m_type(ConfigParserData::DefaultIcon),
2375                     m_data(data)
2376             {}
2377
2378             private:
2379                 bool m_properNamespace;
2380                 ConfigParserData::IconSectionType m_type;
2381                 ConfigParserData::AccountProvider& m_data;
2382                 DPL::OptionalString m_value;
2383         };
2384
2385           struct DisplayNameParser : public ElementParser
2386         {
2387             public:
2388                 virtual ActionFunc GetElementParser(const DPL::String& /*ns*/,
2389                         const DPL::String& /*name*/)
2390                 {
2391                     return &IgnoringParser::Create; //ignore unknown according to w3c
2392                 }
2393
2394                 virtual void Accept(const Text& text)
2395                 {
2396                     if (text.value == L"") {
2397                         return;
2398                     }
2399                     m_value = text.value;
2400                 }
2401
2402                 virtual void Accept(const Element& element)
2403                 {
2404                     m_lang = element.lang;
2405                     m_value= L"";
2406                 }
2407
2408                 virtual void Accept(const XmlAttribute& /*attribute*/)
2409                 {}
2410
2411                 virtual void Verify()
2412                 {
2413                     if (m_value.IsNull() || *m_value == L"") {
2414                         return;
2415                     }
2416
2417                     std::pair<DPL::String, DPL::String> name;
2418                     name.first = *m_lang;
2419                     name.second = *m_value;
2420
2421                     m_data.m_displayNameSet.insert(name);
2422                 }
2423
2424                 DisplayNameParser(ConfigParserData::AccountProvider& data) :
2425                     ElementParser(),
2426                     m_properNamespace(false),
2427                     m_data(data)
2428             {}
2429
2430             private:
2431                 bool m_properNamespace;
2432                 DPL::OptionalString m_lang;
2433                 DPL::OptionalString m_value;
2434                 ConfigParserData::AccountProvider& m_data;
2435         };
2436
2437           struct CapabilityParser : public ElementParser
2438         {
2439             public:
2440                 virtual ActionFunc GetElementParser(const DPL::String& /*ns*/,
2441                         const DPL::String& /*name*/)
2442                 {
2443                     return &IgnoringParser::Create; //ignore unknown according to w3c
2444                 }
2445
2446                 virtual void Accept(const Text& text)
2447                 {
2448                     if (text.value == L"") {
2449                         return;
2450                     }
2451                     m_value = text.value;
2452                 }
2453
2454                 virtual void Accept(const Element& /*element*/)
2455                 {}
2456
2457                 virtual void Accept(const XmlAttribute& /*attribute*/)
2458                 {}
2459
2460                 virtual void Verify()
2461                 {
2462                     if (m_value.IsNull() || *m_value == L"") {
2463                         return;
2464                     }
2465                     m_data.m_capabilityList.push_back(*m_value);
2466                 }
2467
2468                 CapabilityParser(ConfigParserData::AccountProvider& data) :
2469                     ElementParser(),
2470                     m_properNamespace(false),
2471                     m_data(data)
2472             {}
2473
2474             private:
2475                 bool m_properNamespace;
2476                 DPL::OptionalString m_value;
2477                 ConfigParserData::AccountProvider& m_data;
2478         };
2479           virtual ActionFunc GetElementParser(const DPL::String& /*ns*/,
2480                   const DPL::String& name)
2481           {
2482               if (name == L"icon") {
2483                   return DPL::MakeDelegate(this, &AccountProviderParser::OnIconElement);
2484               } else if (name == L"display-name") {
2485                   return DPL::MakeDelegate(this,
2486                           &AccountProviderParser::OnDisplayNameElement);
2487               } else if (name == L"capability") {
2488                   return DPL::MakeDelegate(this, &AccountProviderParser::OnCapabilityElement);
2489               } else {
2490                   return &IgnoringParser::Create; //ignore unknown according to w3c
2491               }
2492           }
2493
2494           virtual void Accept(const Text& /*text*/)
2495           {}
2496
2497           virtual void Accept(const Element& /*element*/)
2498           {}
2499
2500           virtual void Accept(const XmlAttribute& attribute)
2501           {
2502               if (attribute.name == L"multiple-accounts-support") {
2503                   if (attribute.value == L"true") {
2504                       m_multiSupport = true;
2505                   }
2506               }
2507           }
2508
2509           virtual void Verify()
2510           {
2511               m_data.m_multiAccountSupport = m_multiSupport;
2512           }
2513
2514           ElementParserPtr OnIconElement()
2515           {
2516               return ElementParserPtr(new IconParser(m_data));
2517           }
2518
2519           ElementParserPtr OnDisplayNameElement()
2520           {
2521               return ElementParserPtr(new DisplayNameParser(m_data));
2522           }
2523
2524           ElementParserPtr OnCapabilityElement()
2525           {
2526               return ElementParserPtr(new CapabilityParser(m_data));
2527           }
2528
2529           AccountProviderParser(ConfigParserData::AccountProvider& data) :
2530               ElementParser(),
2531               m_properNamespace(false),
2532               m_multiSupport(false),
2533               m_data(data)
2534         {}
2535
2536       private:
2537           bool m_properNamespace;
2538           bool m_multiSupport;
2539           ConfigParserData::AccountProvider& m_data;
2540     };
2541
2542     virtual ActionFunc GetElementParser(const DPL::String& /*ns*/,
2543             const DPL::String& name)
2544     {
2545         if (name == L"account-provider") {
2546             return DPL::MakeDelegate(this, &AccountParser::OnProviderElement);
2547         } else {
2548             return &IgnoringParser::Create; //ignore unknown according to w3c
2549         }
2550     }
2551
2552     virtual void Accept(const Element& element)
2553     {
2554         if (element.ns == ConfigurationNamespace::TizenWebAppNamespaceName) {
2555             m_properNamespace = true;
2556         }
2557     }
2558
2559     virtual void Accept(const XmlAttribute& /*attribute*/)
2560     {}
2561
2562     virtual void Accept(const Text& /*text*/)
2563     {}
2564
2565     virtual void Verify()
2566     {}
2567
2568     ElementParserPtr OnProviderElement()
2569     {
2570         return ElementParserPtr(new AccountProviderParser(m_account));
2571     }
2572
2573     AccountParser(ConfigParserData& data) :
2574         ElementParser(),
2575         m_data(data),
2576         m_account(data.accountProvider),
2577         m_properNamespace(false),
2578         m_multiSupport(false)
2579     {}
2580
2581   private:
2582     ConfigParserData& m_data;
2583     ConfigParserData::AccountProvider& m_account;
2584     bool m_properNamespace;
2585     bool m_multiSupport;
2586 };
2587
2588 class MetadataParser : public ElementParser
2589 {
2590   public:
2591     virtual ActionFunc GetElementParser(const DPL::String& /*ns*/,
2592                                         const DPL::String& /*name*/)
2593     {
2594         return &IgnoringParser::Create; //ignore unknown according to w3c
2595     }
2596
2597     virtual void Accept(const XmlAttribute& attribute)
2598     {
2599         if (m_properNamespace) {
2600             if (attribute.name == L"key") {
2601                 m_key = attribute.value;
2602             } else if (attribute.name == L"value") {
2603                 m_value = attribute.value;
2604             }
2605         }
2606     }
2607
2608     virtual void Accept(const Element& element)
2609     {
2610         if (element.ns == ConfigurationNamespace::TizenWebAppNamespaceName) {
2611             m_properNamespace = true;
2612         }
2613     }
2614
2615     virtual void Accept(const Text& /*text*/)
2616     {
2617         ThrowMsg(Exception::ParseError, "param element must be empty");
2618     }
2619
2620     virtual void Verify()
2621     {
2622         if (m_key.IsNull()) {
2623             _W("metadata element must have key attribute");
2624             return;
2625         }
2626         NormalizeString(m_key);
2627         NormalizeString(m_value);
2628         ConfigParserData::Metadata metaData(m_key, m_value);
2629         FOREACH(it, m_data.metadataList) {
2630             if (!DPL::StringCompare(*it->key, *m_key)) {
2631                 _E("Key isn't unique");
2632                 return;
2633             }
2634         }
2635         m_data.metadataList.push_back(metaData);
2636     }
2637
2638     MetadataParser(ConfigParserData& data) :
2639         ElementParser(),
2640         m_data(data),
2641         m_properNamespace(false)
2642     {}
2643
2644   private:
2645     DPL::OptionalString m_key;
2646     DPL::OptionalString m_value;
2647     ConfigParserData& m_data;
2648     bool m_properNamespace;
2649 };
2650
2651 ElementParser::ActionFunc WidgetParser::GetElementParser(
2652     const DPL::String& /*ns*/,
2653     const DPL::String& name)
2654 {
2655     FuncMap::const_iterator it = m_map.find(name);
2656     if (it != m_map.end()) {
2657         return it->second;
2658     } else {
2659         return &IgnoringParser::Create; //ignore unknown according to w3c
2660     }
2661 }
2662
2663 WidgetParser::WidgetParser(ConfigParserData& data) :
2664     m_data(data),
2665     m_textDirection(Unicode::EMPTY)
2666 {
2667     m_map[L"name"] = DPL::MakeDelegate(this, &WidgetParser::OnNameElement);
2668     m_map[L"access"] = DPL::MakeDelegate(this, &WidgetParser::OnAccessElement);
2669     m_map[L"description"] =
2670         DPL::MakeDelegate(this, &WidgetParser::OnDescriptionElement);
2671     m_map[L"author"] = DPL::MakeDelegate(this, &WidgetParser::OnAuthorElement);
2672     m_map[L"license"] =
2673         DPL::MakeDelegate(this, &WidgetParser::OnLicenseElement);
2674     m_map[L"icon"] = DPL::MakeDelegate(this, &WidgetParser::OnIconElement);
2675     m_map[L"content"] =
2676         DPL::MakeDelegate(this, &WidgetParser::OnContentElement);
2677     m_map[L"preference"] =
2678         DPL::MakeDelegate(this, &WidgetParser::OnPreferenceElement);
2679     m_map[L"setting"] =
2680         DPL::MakeDelegate(this, &WidgetParser::OnSettingElement);
2681     m_map[L"application"] = DPL::MakeDelegate(
2682             this,
2683             &WidgetParser::
2684                 OnApplicationElement);
2685     m_map[L"splash"] = DPL::MakeDelegate(this, &WidgetParser::OnSplashElement);
2686     m_map[L"background"] = DPL::MakeDelegate(this,
2687                                              &WidgetParser::OnBackgroundElement);
2688     m_map[L"privilege"] = DPL::MakeDelegate(this,
2689                                             &WidgetParser::OnPrivilegeElement);
2690     m_map[L"app-control"] = DPL::MakeDelegate(
2691             this,
2692             &WidgetParser::
2693                 OnAppControlElement);
2694     m_map[L"category"] = DPL::MakeDelegate(this,
2695                                            &WidgetParser::OnCategoryElement);
2696     m_map[L"app-widget"] = DPL::MakeDelegate(this, &WidgetParser::OnAppWidgetElement);
2697 #ifdef CSP_ENABLED
2698     m_map[L"content-security-policy"] = DPL::MakeDelegate(
2699             this,
2700             &WidgetParser::
2701                 OnCspElement);
2702     m_map[L"content-security-policy-report-only"] = DPL::MakeDelegate(
2703             this,
2704             &WidgetParser::
2705                 OnCspReportOnlyElement);
2706 #endif
2707 #ifdef ALLOW_NAVIGATION_ENABLED
2708     m_map[L"allow-navigation"] =
2709         DPL::MakeDelegate(this, &WidgetParser::OnAllowNavigationElement);
2710 #endif
2711     m_map[L"account"] = DPL::MakeDelegate(this, &WidgetParser::OnAccountElement);
2712     m_map[L"metadata"] = DPL::MakeDelegate(this, &WidgetParser::OnMetadataElement);
2713 }
2714
2715 ElementParserPtr WidgetParser::OnNameElement()
2716 {
2717     return ElementParserPtr(new NameParser(m_textDirection, m_data));
2718 }
2719
2720 ElementParserPtr WidgetParser::OnAccessElement()
2721 {
2722     return ElementParserPtr(new AccessParser(m_data));
2723 }
2724
2725 ElementParserPtr WidgetParser::OnDescriptionElement()
2726 {
2727     return ElementParserPtr(new DescriptionParser(m_textDirection, m_data));
2728 }
2729
2730 ElementParserPtr WidgetParser::OnAuthorElement()
2731 {
2732     return ElementParserPtr(new AuthorParser(m_textDirection, m_data));
2733 }
2734
2735 ElementParserPtr WidgetParser::OnLicenseElement()
2736 {
2737     return ElementParserPtr(new LicenseParser(m_textDirection, m_data));
2738 }
2739
2740 ElementParserPtr WidgetParser::OnIconElement()
2741 {
2742     return ElementParserPtr(new IconParser(m_data));
2743 }
2744
2745 ElementParserPtr WidgetParser::OnContentElement()
2746 {
2747     return ElementParserPtr(new ContentParser(m_data));
2748 }
2749
2750 ElementParserPtr WidgetParser::OnPreferenceElement()
2751 {
2752     return ElementParserPtr(new PreferenceParser(m_data));
2753 }
2754
2755 ElementParserPtr WidgetParser::OnSettingElement()
2756 {
2757     return ElementParserPtr(new SettingParser(m_data));
2758 }
2759
2760 ElementParserPtr WidgetParser::OnApplicationElement()
2761 {
2762     return ElementParserPtr(new ApplicationParser(m_data));
2763 }
2764
2765 ElementParserPtr WidgetParser::OnSplashElement()
2766 {
2767     return ElementParserPtr(new SplashParser(m_data));
2768 }
2769
2770 ElementParserPtr WidgetParser::OnBackgroundElement()
2771 {
2772     return ElementParserPtr(new BackgroundParser(m_data));
2773 }
2774
2775 ElementParserPtr WidgetParser::OnPrivilegeElement()
2776 {
2777     return ElementParserPtr(new PrivilegeParser(m_data));
2778 }
2779
2780 ElementParserPtr WidgetParser::OnAppControlElement()
2781 {
2782     return ElementParserPtr(new AppControlParser(m_data));
2783 }
2784
2785 ElementParserPtr WidgetParser::OnCategoryElement()
2786 {
2787     return ElementParserPtr(new CategoryParser(m_data));
2788 }
2789
2790 ElementParserPtr WidgetParser::OnAppWidgetElement()
2791 {
2792     return ElementParserPtr(new AppWidgetParser(m_data));
2793 }
2794
2795 ElementParserPtr WidgetParser::OnCspElement()
2796 {
2797     return ElementParserPtr(new CspParser(m_data));
2798 }
2799
2800 ElementParserPtr WidgetParser::OnCspReportOnlyElement()
2801 {
2802     return ElementParserPtr(new CspReportOnlyParser(m_data));
2803 }
2804
2805 ElementParserPtr WidgetParser::OnAllowNavigationElement()
2806 {
2807     return ElementParserPtr(new AllowNavigationParser(m_data));
2808 }
2809
2810 ElementParserPtr WidgetParser::OnAccountElement()
2811 {
2812     return ElementParserPtr(new AccountParser(m_data));
2813 }
2814
2815 ElementParserPtr WidgetParser::OnMetadataElement()
2816 {
2817     return ElementParserPtr(new MetadataParser(m_data));
2818 }
2819
2820 void WidgetParser::Accept(const Element& element)
2821 {
2822     if (element.ns != ConfigurationNamespace::W3CWidgetNamespaceName &&
2823         element.ns != ConfigurationNamespace::TizenWebAppNamespaceName)
2824     {
2825         ThrowMsg(Exception::ParseError,
2826                  "Wrong xml namespace for widget element");
2827     }
2828 }
2829
2830 void WidgetParser::Accept(const Text& /*text*/)
2831 {
2832     ThrowMsg(Exception::ParseError, "widged element must be empty");
2833 }
2834
2835 void WidgetParser::Accept(const XmlAttribute& attribute)
2836 {
2837     if (attribute.name == L"id") {
2838         LibIri::Wrapper iri(DPL::ToUTF8String(attribute.value).c_str());
2839         //If may important tests starts to fail this test we will have
2840         //to consider commenting this test out again.
2841         if (iri.Validate()) {
2842             m_data.widget_id = attribute.value;
2843             NormalizeString(m_data.widget_id);
2844         } else {
2845             _W("Widget id validation failed: %ls", attribute.value.c_str());
2846         }
2847     } else if (attribute.name == L"version") {
2848         m_version = attribute.value;
2849         NormalizeString(m_version);
2850     } else if (attribute.name == L"min-version") {
2851         _D("min-version attribute was found. Value: %ls", attribute.value.c_str());
2852         m_minVersion = attribute.value;
2853         NormalizeString(m_minVersion);
2854         m_data.minVersionRequired = m_minVersion;
2855     } else if (attribute.name == L"height") {
2856         DPL::OptionalString value = attribute.value;
2857         NormalizeString(value);
2858         std::string v = DPL::ToUTF8String(*value);
2859
2860         if (!v.empty()) {
2861             unsigned char c = v.c_str()[0];
2862             if (isdigit(c)) {
2863                 int val = 0;
2864                 for (size_t i = 0; i < v.size(); ++i) {
2865                     c = v.c_str()[i];
2866                     if (isdigit(c)) {
2867                         val *= 10;
2868                         val += (c - '0');
2869                     } else {
2870                         break;
2871                     }
2872                 }
2873                 m_data.height = val;
2874             }
2875         }
2876     } else if (attribute.name == L"width") {
2877         DPL::OptionalString value = attribute.value;
2878         NormalizeString(value);
2879         std::string v = DPL::ToUTF8String(*value);
2880
2881         if (!v.empty()) {
2882             unsigned char c = v.c_str()[0];
2883             if (c >= '0' && c <= '9') {
2884                 int val = 0;
2885                 for (size_t i = 0; i < v.size(); ++i) {
2886                     c = v.c_str()[i];
2887                     if (c >= '0' && c <= '9') {
2888                         val *= 10;
2889                         val += (c - '0');
2890                     } else {
2891                         break;
2892                     }
2893                 }
2894                 m_data.width = val;
2895             }
2896         }
2897     } else if (attribute.name == L"viewmodes") {
2898         DPL::Tokenize(attribute.value,
2899                       L" ",
2900                       std::inserter(m_windowModes,
2901                                     m_windowModes.end()),
2902                       true);
2903     } else if (attribute.name == L"dir") {
2904         m_textDirection = Unicode::ParseDirAttribute(attribute);
2905     } else if (L"defaultlocale" == attribute.name) {
2906         if (!m_defaultlocale) {
2907             m_defaultlocale = attribute.value;
2908             NormalizeString(m_defaultlocale);
2909             if( I18n::DB::I18nDAOReadOnly::IsValidSubTag
2910                     (attribute.value, RECORD_TYPE_LANGUAGE)) {
2911                 _D("Default Locale Found %ls", (*m_defaultlocale).c_str());
2912             } else {
2913                 _W("Default Locate Is Invalid");
2914             }
2915         } else {
2916             _W("Ignoring subsequent default locale");
2917         }
2918
2919         //Any other value consider as a namespace definition
2920     } else if (attribute.name == L"xmlns" || attribute.prefix == L"xmlns") {
2921         _D("Namespace domain: %ls", attribute.name.c_str());
2922         _D("Namespace value: %ls", attribute.value.c_str());
2923         m_nameSpaces[attribute.name] = attribute.value;
2924     } else {
2925         _E("Unknown attirbute: namespace=%ls, name=%ls, value=%ls",
2926             attribute.ns.c_str(), attribute.name.c_str(), attribute.value.c_str());
2927     }
2928 }
2929
2930 void WidgetParser::Verify()
2931 {
2932     FOREACH(mode, m_windowModes) {
2933         if (L"windowed" == *mode || L"floating" == *mode ||
2934             L"fullscreen" == *mode || L"maximized" == *mode ||
2935             L"minimized" == *mode)
2936         {
2937             m_data.windowModes.insert(*mode);
2938         }
2939     }
2940     if (!m_version.IsNull()) {
2941         Unicode::UpdateTextWithDirectionMark(m_textDirection, &*m_version);
2942         m_data.version = m_version;
2943     }
2944     m_data.defaultlocale = m_defaultlocale;
2945     FOREACH(ns, m_nameSpaces) {
2946         m_data.nameSpaces.insert(ns->second);
2947     }
2948 }
2949