[Release] wrt-installer_0.1.85
[platform/framework/web/wrt-installer.git] / src / configuration_parser / widget_parser.cpp
1 /*
2  * Copyright (c) 2011 Samsung Electronics Co., Ltd All Rights Reserved
3  *
4  *    Licensed under the Apache License, Version 2.0 (the "License");
5  *    you may not use this file except in compliance with the License.
6  *    You may obtain a copy of the License at
7  *
8  *        http://www.apache.org/licenses/LICENSE-2.0
9  *
10  *    Unless required by applicable law or agreed to in writing, software
11  *    distributed under the License is distributed on an "AS IS" BASIS,
12  *    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  *    See the License for the specific language governing permissions and
14  *    limitations under the License.
15  */
16 /**
17  * This file  have been implemented in compliance with  W3C WARP SPEC.
18  * but there are some patent issue between  W3C WARP SPEC and APPLE.
19  * so if you want to use this file, refer to the README file in root directory
20  */
21 /**
22  * @file        widget_parser.cpp
23  * @author      Lukasz Wrzosek (l.wrzosek@samsung.com)
24  * @version     0.1
25  * @brief
26  */
27 #include "widget_parser.h"
28 #include "ignoring_parser.h"
29 #include "deny_all_parser.h"
30 #include <dpl/wrt-dao-ro/config_parser_data.h>
31 #include "libiriwrapper.h"
32 #include <dpl/utils/warp_iri.h>
33 #include <dpl/utils/mime_type_utils.h>
34 #include <language_subtag_rst_tree.h>
35
36 #include <iri.h>
37 #include <dpl/log/log.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 using namespace WrtDB;
52
53 namespace Unicode {
54 static const DPL::String UTF_LRE = L"\x0202a";
55 static const DPL::String UTF_LRO = L"\x0202d";
56 static const DPL::String UTF_RLE = L"\x0202b";
57 static const DPL::String UTF_RLO = L"\x0202e";
58 static const DPL::String UTF_PDF = L"\x0202c";
59
60 Direction ParseDirAttribute(const XmlAttribute& attribute)
61 {
62     Assert(L"dir" == attribute.name);
63     if (L"ltr" == attribute.value) {
64         return LRE;
65     } else if (L"rtl" == attribute.value) {
66         return RLE;
67     } else if (L"lro" == attribute.value) {
68         return LRO;
69     } else if (L"rlo" == attribute.value) {
70         return RLO;
71     } else {
72         LogWarning("dir attribute has wrong value:" << attribute.value);
73         return EMPTY;
74     }
75 }
76
77 void UpdateTextWithDirectionMark(Direction direction,
78                                  DPL::String* text)
79 {
80     Assert(text);
81     switch (direction) {
82     case RLO:
83         *text = UTF_RLO + *text + UTF_PDF;
84         break;
85     case RLE:
86         *text = UTF_RLE + *text + UTF_PDF;
87         break;
88     case LRE:
89         *text = UTF_LRE + *text + UTF_PDF;
90         break;
91     case LRO:
92         *text = UTF_LRO + *text + UTF_PDF;
93         break;
94     case EMPTY:
95         break;
96     default:
97         Assert(false);
98         break;
99     }
100 }
101 } // namespace Unicode
102
103 class InnerElementsParser : public ElementParser
104 {
105   public:
106     virtual ActionFunc GetElementParser(const DPL::String& /*ns*/,
107                                         const DPL::String& /*name*/)
108     {
109         return DPL::MakeDelegate(this, &InnerElementsParser::Other);
110     }
111
112     virtual void Accept(const Element& /*element*/)
113     {}
114
115     virtual void Accept(const Text& text)
116     {
117         if (m_text.IsNull()) {
118             m_text = text;
119         } else {
120             m_text->value += text.value;
121         }
122     }
123
124     virtual void Accept(const XmlAttribute& attribute)
125     {
126         if (attribute.name == L"dir") {
127             m_textDirection = Unicode::ParseDirAttribute(attribute);
128         }
129     }
130
131     virtual void Verify()
132     {
133         if (!m_text.IsNull()) {
134             Unicode::UpdateTextWithDirectionMark(m_textDirection,
135                                                  &m_text->value);
136             m_parentParser->Accept(*m_text);
137         }
138     }
139
140     InnerElementsParser(ElementParserPtr parent) :
141         m_parentParser(parent),
142         m_textDirection(Unicode::EMPTY)
143     {}
144
145     ElementParserPtr Other()
146     {
147         return ElementParserPtr(new InnerElementsParser(
148                                     std::static_pointer_cast<ElementParser>(
149                                         shared_from_this())));
150     }
151
152   private:
153     DPL::Optional<Text> m_text;
154     ElementParserPtr m_parentParser;
155     Unicode::Direction m_textDirection;
156 };
157
158 class NameParser : public ElementParser
159 {
160   public:
161     virtual ActionFunc GetElementParser(const DPL::String& /*ns*/,
162                                         const DPL::String& /*name*/)
163     {
164         return DPL::MakeDelegate(this, &NameParser::Other);
165     }
166
167     virtual void Accept(const Element& element)
168     {
169         m_lang = element.lang;
170         m_name = L"";
171     }
172
173     virtual void Accept(const Text& text)
174     {
175         if (m_name.IsNull()) {
176             m_name = text.value;
177         } else {
178             *m_name += text.value;
179         }
180     }
181
182     virtual void Accept(const XmlAttribute& attribute)
183     {
184         if (attribute.name == L"short") {
185             if (m_shortName.IsNull()) {
186                 m_shortName = attribute.value;
187             }
188         } else if (attribute.name == L"dir") {
189             m_textDirection = Unicode::ParseDirAttribute(attribute);
190         }
191     }
192
193     virtual void Verify()
194     {
195         ConfigParserData::LocalizedData& data = m_data.localizedDataSet[m_lang];
196         if (data.name.IsNull()) {
197             NormalizeString(m_name);
198             NormalizeString(m_shortName);
199             if (!m_name.IsNull()) {
200                 Unicode::UpdateTextWithDirectionMark(m_textDirection, &*m_name);
201             }
202             data.name = m_name;
203             if (!m_shortName.IsNull()) {
204                 Unicode::UpdateTextWithDirectionMark(m_textDirection,
205                                                      &*m_shortName);
206             }
207             data.shortName = m_shortName;
208         }
209     }
210
211     NameParser(Unicode::Direction direction,
212                ConfigParserData& data) :
213         m_data(data),
214         m_textDirection(direction)
215     {}
216
217     ElementParserPtr Other()
218     {
219         return ElementParserPtr(new InnerElementsParser(
220                                     std::static_pointer_cast<ElementParser>(
221                                         shared_from_this())));
222     }
223
224   private:
225     ConfigParserData& m_data;
226     DPL::OptionalString m_name;
227     DPL::OptionalString m_shortName;
228     DPL::OptionalString m_dir;
229     DPL::String m_lang;
230     Unicode::Direction m_textDirection;
231 };
232
233 class AccessParser : public ElementParser
234 {
235   public:
236     enum StandardType
237     {
238         STANDARD_TYPE_NONE,
239         STANDARD_TYPE_WARP
240     };
241
242     virtual ActionFunc GetElementParser(const DPL::String& /*ns*/,
243                                         const DPL::String& /*name*/)
244     {
245         return DPL::MakeDelegate(this, &AccessParser::Other);
246     }
247
248     virtual void Accept(const Element& element)
249     {
250         // for tizen web apps WARP should be used
251         if (element.ns == ConfigurationNamespace::W3CWidgetNamespaceName ||
252             element.ns == ConfigurationNamespace::TizenWebAppNamespaceName)
253         {
254             m_standardType = STANDARD_TYPE_WARP;
255         }
256     }
257
258     virtual void Accept(const Text& /*text*/)
259     {}
260
261     void AcceptWac(const XmlAttribute& attribute)
262     {
263         if (attribute.name == L"origin") {
264             m_strIRIOrigin = attribute.value;
265             NormalizeString(m_strIRIOrigin);
266         } else if (attribute.name == L"subdomains") {
267             DPL::String normalizedValue = attribute.value;
268             NormalizeString(normalizedValue);
269
270             if (normalizedValue == L"true") {
271                 m_bSubDomainAccess = true;
272             } else if (normalizedValue == L"false") {
273                 m_bSubDomainAccess = false;
274             }
275         }
276     }
277
278     virtual void Accept(const XmlAttribute& attribute)
279     {
280         switch (m_standardType) {
281         case STANDARD_TYPE_WARP:
282             AcceptWac(attribute);
283             break;
284         default:
285             LogError("Error in Access tag - unknown standard.");
286             break;
287         }
288     }
289
290     void VerifyWac()
291     {
292         WarpIRI iri;
293         iri.set(m_strIRIOrigin, false);
294
295         if (!iri.isAccessDefinition()) {
296             LogWarning("Access list element: " <<
297                        m_strIRIOrigin <<
298                        " is not acceptable by WARP" <<
299                        "standard and will be ignored!");
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             LogError("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             LogWarning("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             LogWarning("src attribute is invalid: " << m_src);
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             LogWarning("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 LinkParser : public ElementParser
825 {
826   public:
827     virtual ActionFunc GetElementParser(const DPL::String& /*ns*/,
828                                         const DPL::String& /*name*/)
829     {
830         return &DenyAllParser::Create;
831     }
832
833     virtual void Accept(const XmlAttribute& attribute)
834     {
835         if (m_properNamespace) {
836             LogDebug("attribute");
837             if (attribute.name == L"rel") {
838                 if (attribute.value != L"describedby") {
839                     ThrowMsg(Exception::ParseError,
840                              "rel attribute must have describedby value");
841                 }
842             } else if (attribute.name == L"type") {} else if (attribute.name ==
843                                                               L"href")
844             {
845                 LogDebug("here is href");
846                 m_href = attribute.value;
847             } else {
848                 ThrowMsg(Exception::ParseError,
849                          "unknown attribute '" +
850                          DPL::ToUTF8String(attribute.name) +
851                          "' in link element");
852             }
853         }
854     }
855
856     virtual void Accept(const Element& element)
857     {
858         if (element.ns ==
859             ConfigurationNamespace::WacWidgetNamespaceNameForLinkElement)
860         {
861             m_properNamespace = true;
862         }
863         LogDebug("element");
864     }
865
866     virtual void Accept(const Text&)
867     {
868         if (m_properNamespace) {
869             LogDebug("text");
870             ThrowMsg(Exception::ParseError, "link element must be empty");
871         }
872     }
873
874     virtual void Verify()
875     {
876         if (!m_href) {
877             ThrowMsg(Exception::ParseError,
878                      "link element must have href attribute");
879         }
880
881         LibIri::Wrapper iri(DPL::ToUTF8String(*m_href).c_str());
882         if (!iri.Validate()) { // TODO: Better uri validator ?
883             ThrowMsg(Exception::ParseError,
884                      "href attribute must be a valid iri/uri/url");
885         }
886     }
887
888     LinkParser(ConfigParserData& data) :
889         ElementParser(),
890         m_properNamespace(false),
891         m_data(data),
892         m_href(DPL::OptionalString::Null)
893     {}
894
895   private:
896     bool m_properNamespace;
897     ConfigParserData& m_data;
898     DPL::OptionalString m_href;
899 };
900
901 class SettingParser : public ElementParser
902 {
903   public:
904     virtual ActionFunc GetElementParser(const DPL::String& /*ns*/,
905                                         const DPL::String& /*name*/)
906     {
907         return &IgnoringParser::Create; //ignore unknown according to w3c
908     }
909
910     virtual void Accept(const Text& /*text*/)
911     {}
912
913     virtual void Accept(const Element& /*element*/)
914     {}
915
916     virtual void Accept(const XmlAttribute& attribute)
917     {
918         m_setting.m_name = attribute.name;
919         m_setting.m_value = attribute.value;
920         m_data.settingsList.insert(m_setting);
921     }
922
923     virtual void Verify()
924     {}
925
926     SettingParser(ConfigParserData& data) :
927         ElementParser(),
928         m_data(data),
929         m_setting(L"", L"")
930     {}
931
932   private:
933     ConfigParserData& m_data;
934     ConfigParserData::Setting m_setting;
935 };
936
937 class AppControlParser : public ElementParser
938 {
939   public:
940     struct SourceParser : public ElementParser
941     {
942       public:
943         virtual ActionFunc GetElementParser(const DPL::String& /*ns*/,
944                                             const DPL::String& /*name*/)
945         {
946             return &IgnoringParser::Create; //ignore unknown according to w3c
947         }
948
949         virtual void Accept(const Text& /*text*/)
950         {}
951
952         virtual void Accept(const Element& /*element*/)
953         {}
954
955         virtual void Accept(const XmlAttribute& attribute)
956         {
957             if (attribute.name == L"name") {
958                 if (attribute.value.size() > 0) {
959                     m_value = attribute.value;
960                     NormalizeString(m_value);
961                 }
962             }
963         }
964
965         virtual void Verify()
966         {
967             if (m_value.IsNull() || *m_value == L"") {
968                 return;
969             }
970
971             m_data.m_src = *m_value;
972         }
973
974         SourceParser(ConfigParserData::AppControlInfo& data) :
975             ElementParser(),
976             m_properNamespace(false),
977             m_data(data)
978         {}
979
980       private:
981         bool m_properNamespace;
982         DPL::OptionalString m_value;
983         ConfigParserData::AppControlInfo& m_data;
984     };
985
986     struct OperationParser : public ElementParser
987     {
988       public:
989         virtual ActionFunc GetElementParser(const DPL::String& /*ns*/,
990                                             const DPL::String& /*name*/)
991         {
992             return &IgnoringParser::Create; //ignore unknown according to w3c
993         }
994
995         virtual void Accept(const Text& /*text*/)
996         {}
997
998         virtual void Accept(const Element& /*element*/)
999         {}
1000
1001         virtual void Accept(const XmlAttribute& attribute)
1002         {
1003             if (attribute.name == L"name") {
1004                 if (attribute.value.size() > 0) {
1005                     m_value = attribute.value;
1006                     NormalizeString(m_value);
1007                 }
1008             }
1009         }
1010
1011         virtual void Verify()
1012         {
1013             if (m_value.IsNull() || *m_value == L"") {
1014                 return;
1015             }
1016
1017             m_data.m_operation = *m_value;
1018         }
1019
1020         OperationParser(ConfigParserData::AppControlInfo& data) :
1021             ElementParser(),
1022             m_properNamespace(false),
1023             m_data(data)
1024         {}
1025
1026       private:
1027         bool m_properNamespace;
1028         DPL::OptionalString m_value;
1029         ConfigParserData::AppControlInfo& m_data;
1030     };
1031
1032     struct UriParser : public ElementParser
1033     {
1034       public:
1035         virtual ActionFunc GetElementParser(const DPL::String& /*ns*/,
1036                                             const DPL::String& /*name*/)
1037         {
1038             return &IgnoringParser::Create; //ignore unknown according to w3c
1039         }
1040
1041         virtual void Accept(const Text& /*text*/)
1042         {}
1043
1044         virtual void Accept(const Element& /*element*/)
1045         {}
1046
1047         virtual void Accept(const XmlAttribute& attribute)
1048         {
1049             if (attribute.name == L"name") {
1050                 if (attribute.value.size() > 0) {
1051                     m_value = attribute.value;
1052                     NormalizeString(m_value);
1053                 }
1054             }
1055         }
1056
1057         virtual void Verify()
1058         {
1059             // exception
1060             DPL::String ignoreUri(L"file");
1061
1062             if (!m_value.IsNull() && *m_value == ignoreUri)
1063             {
1064                 LogInfo("exception : '" << *m_value << "' scheme will be ignored.");
1065                 m_value = DPL::OptionalString::Null;
1066             }
1067
1068             if (m_value.IsNull() || *m_value == L"") {
1069                 return;
1070             }
1071
1072             DPL::String wildString(L"*/*");
1073             if ((m_data.m_uriList.find(wildString) == m_data.m_uriList.end())
1074                 && (m_data.m_uriList.find(*m_value) == m_data.m_uriList.end()))
1075             {
1076                 m_data.m_uriList.insert(*m_value);
1077             } else {
1078                 LogDebug("Ignoring uri with name" <<
1079                          DPL::ToUTF8String(*m_value));
1080             }
1081         }
1082
1083         UriParser(ConfigParserData::AppControlInfo& data) :
1084             ElementParser(),
1085             m_properNamespace(false),
1086             m_data(data)
1087         {}
1088
1089       private:
1090         bool m_properNamespace;
1091         DPL::OptionalString m_value;
1092         ConfigParserData::AppControlInfo& m_data;
1093     };
1094
1095     struct MimeParser : public ElementParser
1096     {
1097       public:
1098         virtual ActionFunc GetElementParser(const DPL::String& /*ns*/,
1099                                             const DPL::String& /*name*/)
1100         {
1101             return &IgnoringParser::Create; //ignore unknown according to w3c
1102         }
1103
1104         virtual void Accept(const Text& /*text*/)
1105         {}
1106
1107         virtual void Accept(const Element& /*element*/)
1108         {}
1109
1110         virtual void Accept(const XmlAttribute& attribute)
1111         {
1112             if (attribute.name == L"name") {
1113                 if (attribute.value.size() > 0) {
1114                     m_value = attribute.value;
1115                     NormalizeString(m_value);
1116                 }
1117             }
1118         }
1119
1120         virtual void Verify()
1121         {
1122             if (m_value.IsNull() || *m_value == L"") {
1123                 return;
1124             }
1125
1126             DPL::String wildString(L"*/*");
1127             if ((m_data.m_mimeList.find(wildString) ==
1128                  m_data.m_mimeList.end())
1129                 && (m_data.m_mimeList.find(*m_value) ==
1130                     m_data.m_mimeList.end()))
1131             {
1132                 m_data.m_mimeList.insert(*m_value);
1133             } else {
1134                 LogDebug("Ignoring mime with name" <<
1135                          DPL::ToUTF8String(*m_value));
1136             }
1137         }
1138
1139         MimeParser(ConfigParserData::AppControlInfo& data) :
1140             ElementParser(),
1141             m_properNamespace(false),
1142             m_data(data)
1143         {}
1144
1145       private:
1146         bool m_properNamespace;
1147         DPL::OptionalString m_value;
1148         ConfigParserData::AppControlInfo& m_data;
1149     };
1150
1151     virtual ActionFunc GetElementParser(const DPL::String& /*ns*/,
1152                                         const DPL::String& name)
1153     {
1154         if (name == L"src") {
1155             return DPL::MakeDelegate(this, &AppControlParser::OnSourceElement);
1156         } else if (name == L"operation") {
1157             return DPL::MakeDelegate(this,
1158                                      &AppControlParser::OnOperationElement);
1159         } else if (name == L"uri") {
1160             return DPL::MakeDelegate(this, &AppControlParser::OnUriElement);
1161         } else if (name == L"mime") {
1162             return DPL::MakeDelegate(this, &AppControlParser::OnMimeElement);
1163         } else {
1164             return &IgnoringParser::Create; //ignore unknown according to w3c
1165         }
1166     }
1167
1168     virtual void Accept(const XmlAttribute& /*attribute*/)
1169     {}
1170
1171     virtual void Accept(const Element& element)
1172     {
1173         LogWarning("namespace for app service = " << element.ns);
1174         if (element.ns == ConfigurationNamespace::W3CWidgetNamespaceName) {
1175             ThrowMsg(Exception::ParseError,
1176                      "Wrong xml namespace for widget element");
1177         }
1178     }
1179
1180     virtual void Accept(const Text& /*text*/)
1181     {
1182         ThrowMsg(Exception::ParseError, "param element must be empty");
1183     }
1184
1185     virtual void Verify()
1186     {
1187         if (m_appControl.m_src == L"") {
1188             ThrowMsg(Exception::ParseError, "service element must have src element");
1189         }
1190
1191         if (m_appControl.m_operation == L"") {
1192             ThrowMsg(Exception::ParseError, "service element must have operation element");
1193         }
1194
1195         m_data.appControlList.push_back(m_appControl);
1196     }
1197
1198     ElementParserPtr OnSourceElement()
1199     {
1200         return ElementParserPtr(new SourceParser(m_appControl));
1201     }
1202
1203     ElementParserPtr OnOperationElement()
1204     {
1205         return ElementParserPtr(new OperationParser(m_appControl));
1206     }
1207
1208     ElementParserPtr OnUriElement()
1209     {
1210         return ElementParserPtr(new UriParser(m_appControl));
1211     }
1212
1213     ElementParserPtr OnMimeElement()
1214     {
1215         return ElementParserPtr(new MimeParser(m_appControl));
1216     }
1217
1218     AppControlParser(ConfigParserData& data) :
1219         ElementParser(),
1220         m_data(data),
1221         m_appControl(L"")
1222     {}
1223
1224   private:
1225     ConfigParserData& m_data;
1226     ConfigParserData::AppControlInfo m_appControl;
1227 };
1228
1229 class ApplicationParser : public ElementParser
1230 {
1231   public:
1232     virtual ActionFunc GetElementParser(const DPL::String& /*ns*/,
1233                                         const DPL::String& /*name*/)
1234     {
1235         return &IgnoringParser::Create; //ignore unknown according to w3c
1236     }
1237
1238     virtual void Accept(const Text& /*text*/)
1239     {
1240         if (m_properNamespace) {
1241             ThrowMsg(Exception::ParseError, "application element must be empty");
1242         }
1243     }
1244
1245     virtual void Accept(const Element& element)
1246     {
1247         if (element.ns ==
1248             ConfigurationNamespace::TizenWebAppNamespaceName)
1249         {
1250             m_properNamespace = true;
1251         }
1252     }
1253
1254     virtual void Accept(const XmlAttribute& attribute)
1255     {
1256         if (m_properNamespace) {
1257             if (attribute.name == L"id") {
1258                 m_id = attribute.value;
1259                 NormalizeAndTrimSpaceString(m_id);
1260             } else if (attribute.name == L"package") {
1261                 m_package = attribute.value;
1262             } else if (attribute.name == L"required_version") {
1263                 m_version = attribute.value;
1264                 NormalizeString(m_version);
1265             } else {
1266                 ThrowMsg(Exception::ParseError,
1267                          "unknown attribute '" +
1268                          DPL::ToUTF8String(attribute.name) +
1269                          "' in application element");
1270             }
1271         }
1272     }
1273
1274     virtual void Verify()
1275     {
1276         VerifyIdAndPackage();
1277         VerifyVersion();
1278     }
1279
1280     ApplicationParser(ConfigParserData& data) :
1281         ElementParser(),
1282         m_data(data),
1283         m_id(DPL::OptionalString::Null),
1284         m_version(DPL::OptionalString::Null),
1285         m_properNamespace(false)
1286     {}
1287
1288     static const char* const REGEXP_ID;
1289
1290   private:
1291     void VerifyIdAndPackage()
1292     {
1293         if (!m_package)
1294         {
1295             ThrowMsg(Exception::ParseError,
1296                      "application element must have package attribute");
1297         }
1298         else
1299         {
1300             pcrecpp::RE re(REGEXP_PACKAGE);
1301             if (!re.FullMatch(DPL::ToUTF8String(*m_package)))
1302             {
1303                 ThrowMsg(Exception::ParseError,
1304                          "invalid format of package attribute");
1305             }
1306         }
1307
1308         if (!m_id) {
1309             ThrowMsg(Exception::ParseError,
1310                      "application element must have id attribute");
1311         }
1312         else
1313         {
1314             std::string package;
1315             pcrecpp::RE re(REGEXP_ID);
1316             if (!re.FullMatch(DPL::ToUTF8String(*m_id), &package))
1317             {
1318                 ThrowMsg(Exception::ParseError,
1319                          "invalid format of id attribute");
1320             }
1321             if (package != DPL::ToUTF8String(*m_package))
1322             {
1323                 ThrowMsg(Exception::ParseError,
1324                          "invalid package prefix in id attribute");
1325             }
1326         }
1327
1328         m_data.tizenAppId = m_id;
1329         m_data.tizenPkgId = m_package;
1330     }
1331
1332     void VerifyVersion()
1333     {
1334         if (!m_version)
1335         {
1336             ThrowMsg(Exception::ParseError,
1337                      "application element must have required_version attribute");
1338         }
1339         else
1340         {
1341             pcrecpp::RE re(REGEXP_VERSION);
1342             if (!re.FullMatch(DPL::ToUTF8String(*m_version)))
1343             {
1344                 ThrowMsg(Exception::ParseError,
1345                          "invalid format of version attribute");
1346             }
1347         }
1348
1349         m_data.tizenMinVersionRequired = m_version;
1350     }
1351
1352     static const char* const REGEXP_PACKAGE;
1353     static const char* const REGEXP_VERSION;
1354
1355     ConfigParserData& m_data;
1356     DPL::OptionalString m_id;
1357     DPL::OptionalString m_package;
1358     DPL::OptionalString m_version;
1359     bool m_properNamespace;
1360 };
1361
1362 const char* const ApplicationParser::REGEXP_PACKAGE = "[0-9A-Za-z]{10}";
1363 const char* const ApplicationParser::REGEXP_ID = "([0-9A-Za-z]{10})\\.[0-9A-Za-z]{1,52}";
1364 const char* const ApplicationParser::REGEXP_VERSION = "\\d+\\.\\d+(\\.\\d+)?";
1365
1366 class SplashParser : public ElementParser
1367 {
1368   public:
1369     virtual ActionFunc GetElementParser(const DPL::String& /*ns*/,
1370                                         const DPL::String& /*name*/)
1371     {
1372         return &IgnoringParser::Create; //ignore unknown according to w3c
1373     }
1374
1375     virtual void Accept(const XmlAttribute& attribute)
1376     {
1377         if (m_properNamespace)
1378         {
1379             if (attribute.name == L"src") {
1380                 if (attribute.value.size() > 0) {
1381                     m_src = attribute.value;
1382                 }
1383             }
1384         }
1385     }
1386
1387     virtual void Accept(const Element& element)
1388     {
1389         if (element.ns ==
1390             ConfigurationNamespace::TizenWebAppNamespaceName)
1391         {
1392             m_properNamespace = true;
1393         }
1394     }
1395
1396     virtual void Accept(const Text& /*text*/)
1397     {}
1398
1399     virtual void Verify()
1400     {
1401         if (m_src.IsNull())
1402         {
1403             LogWarning("src attribute of splash element is mandatory - ignoring");
1404             return;
1405         }
1406
1407         m_data.splashImgSrc = m_src;
1408     }
1409
1410     SplashParser(ConfigParserData& data) :
1411         ElementParser(),
1412         m_data(data),
1413         m_properNamespace(false)
1414     {}
1415
1416   private:
1417     DPL::OptionalString m_src;
1418     ConfigParserData& m_data;
1419     bool m_properNamespace;
1420 };
1421
1422 class BackgroundParser : public ElementParser
1423 {
1424   public:
1425     virtual ActionFunc GetElementParser(const DPL::String& /*ns*/,
1426                                         const DPL::String& /*name*/)
1427     {
1428         return &IgnoringParser::Create; //ignore unknown according to w3c
1429     }
1430
1431     virtual void Accept(const XmlAttribute& attribute)
1432     {
1433         if (attribute.name == L"src") {
1434             if (attribute.value.size() > 0) {
1435                 m_src = attribute.value;
1436             }
1437         }
1438     }
1439
1440     virtual void Accept(const Element& /*element*/)
1441     {}
1442
1443     virtual void Accept(const Text& /*text*/)
1444     {}
1445
1446     virtual void Verify()
1447     {
1448         if (m_src.IsNull()) {
1449             LogWarning(
1450                 "src attribute of background element is mandatory - ignoring");
1451             return;
1452         }
1453
1454         m_data.backgroundPage = m_src;
1455     }
1456
1457     explicit BackgroundParser(ConfigParserData& data) :
1458         m_data(data)
1459     {}
1460
1461   private:
1462     DPL::OptionalString m_src;
1463     ConfigParserData& m_data;
1464 };
1465
1466 class PrivilegeParser : public ElementParser
1467 {
1468   public:
1469     virtual ActionFunc GetElementParser(const DPL::String& /*ns*/,
1470                                         const DPL::String& /*name*/)
1471     {
1472         return &IgnoringParser::Create; //ignore unknown according to w3c
1473     }
1474
1475     virtual void Accept(const Text& /*text*/)
1476     {}
1477
1478     virtual void Accept(const Element& element)
1479     {
1480         if (element.ns ==
1481             ConfigurationNamespace::TizenWebAppNamespaceName)
1482         {
1483             m_properNamespace = true;
1484         }
1485         LogDebug("element");
1486     }
1487
1488     virtual void Accept(const XmlAttribute& attribute)
1489     {
1490         if (m_properNamespace) {
1491             if (attribute.name == L"name") {
1492                 m_feature.name = attribute.value;
1493                 m_privilege.name = attribute.value;
1494             }
1495         }
1496     }
1497
1498     virtual void Verify()
1499     {
1500         LibIri::Wrapper iri(DPL::ToUTF8String(m_feature.name).c_str());
1501
1502         if (m_feature.name != L"") {
1503             if (iri.Validate()) {
1504                 if (m_data.featuresList.find(m_feature) ==
1505                     m_data.featuresList.end())
1506                 {
1507                     m_data.featuresList.insert(m_feature);
1508                 } else {
1509                     LogDebug("Ignoring feature with name" <<
1510                         DPL::ToUTF8String(m_feature.name));
1511                 }
1512             }
1513         }
1514
1515         LibIri::Wrapper iriPrivilege(
1516             DPL::ToUTF8String(m_privilege.name).c_str());
1517
1518         if (m_privilege.name != L"") {
1519             if (iriPrivilege.Validate()) {
1520                 if (m_data.privilegeList.find(m_privilege) ==
1521                     m_data.privilegeList.end())
1522                 {
1523                     m_data.privilegeList.insert(m_privilege);
1524                 } else {
1525                     LogDebug("Ignoring privilege with name" <<
1526                              DPL::ToUTF8String(m_privilege.name));
1527                 }
1528             }
1529         }
1530     }
1531
1532     PrivilegeParser(ConfigParserData& data) :
1533         ElementParser(),
1534         m_data(data),
1535         m_feature(L""),
1536         m_privilege(L""),
1537         m_properNamespace(false)
1538     {}
1539
1540   private:
1541     ConfigParserData& m_data;
1542     ConfigParserData::Feature m_feature;
1543     ConfigParserData::Privilege m_privilege;
1544     bool m_properNamespace;
1545 };
1546
1547 class CategoryParser : public ElementParser
1548 {
1549   public:
1550     virtual ActionFunc GetElementParser(const DPL::String& /*ns*/,
1551                                         const DPL::String& /*name*/)
1552     {
1553         return &IgnoringParser::Create; //ignore unknown according to w3c
1554     }
1555
1556     virtual void Accept(const XmlAttribute& attribute)
1557     {
1558         if (attribute.name == L"name") {
1559             if (attribute.value.size() > 0) {
1560                 m_name = attribute.value;
1561             }
1562         }
1563     }
1564
1565     virtual void Accept(const Element& /*element*/)
1566     {}
1567
1568     virtual void Accept(const Text& /*text*/)
1569     {}
1570
1571     virtual void Verify()
1572     {
1573         if (m_name.IsNull()) {
1574             LogWarning(
1575                 "name attribute of category element is mandatory - ignoring");
1576             return;
1577         }
1578
1579         if (m_data.categoryList.find(*m_name) ==
1580             m_data.categoryList.end())
1581         {
1582             m_data.categoryList.insert(*m_name);
1583         }
1584     }
1585
1586     explicit CategoryParser(ConfigParserData& data) :
1587         m_data(data)
1588     {}
1589
1590   private:
1591     DPL::OptionalString m_name;
1592     ConfigParserData& m_data;
1593 };
1594
1595 class AppWidgetParser : public ElementParser
1596 {
1597   public:
1598
1599     struct BoxLabelParser : public ElementParser
1600     {
1601         virtual ActionFunc GetElementParser(const DPL::String& /*ns*/,
1602                                             const DPL::String& /*name*/)
1603         {
1604             return &IgnoringParser::Create; //ignore unknown according to w3c
1605         }
1606
1607         virtual void Accept(const XmlAttribute& attribute)
1608         {
1609             if (m_properNamespace) {
1610                  m_lang = attribute.lang;
1611             }
1612         }
1613         virtual void Accept(const Element& element)
1614         {
1615             if (element.ns ==
1616                 ConfigurationNamespace::TizenWebAppNamespaceName)
1617             {
1618                 m_properNamespace = true;
1619             }
1620         }
1621
1622         virtual void Accept(const Text& text)
1623         {
1624             if (m_properNamespace) {
1625                 m_label = text.value;
1626             }
1627         }
1628
1629         virtual void Verify()
1630         {
1631             std::pair<DPL::String, DPL::String> boxLabel;
1632             if (m_label.empty()) {
1633                 LogWarning("box-label element is empty");
1634                 boxLabel.first = DPL::FromUTF8String("");
1635                 boxLabel.second = DPL::FromUTF8String("");
1636                 m_data.m_label.push_back(boxLabel);
1637             }
1638             else {
1639                 boxLabel.first = m_lang;
1640                 boxLabel.second = m_label;
1641                 m_data.m_label.push_back(boxLabel);
1642             }
1643         }
1644
1645         BoxLabelParser(ConfigParserData::LiveboxInfo& data) :
1646             ElementParser(),
1647             m_properNamespace(false),
1648             m_data(data)
1649         {}
1650
1651       private:
1652         DPL::String m_lang;
1653         DPL::String m_label;
1654         bool m_properNamespace;
1655         ConfigParserData::LiveboxInfo& m_data;
1656     };
1657
1658     struct BoxIconParser : public ElementParser
1659     {
1660         virtual ActionFunc GetElementParser(const DPL::String& /*ns*/,
1661                                             const DPL::String& /*name*/)
1662         {
1663             return &IgnoringParser::Create; //ignore unknown according to w3c
1664         }
1665
1666         virtual void Accept(const XmlAttribute& attribute)
1667         {
1668             if (m_properNamespace) {
1669                 if (attribute.name == L"src") {
1670                     m_icon = attribute.value;
1671                 }
1672             }
1673         }
1674
1675         virtual void Accept(const Element& element)
1676         {
1677             if (element.ns ==
1678                 ConfigurationNamespace::TizenWebAppNamespaceName)
1679             {
1680                 m_properNamespace = true;
1681             }
1682         }
1683
1684         virtual void Accept(const Text& /*text*/)
1685         {}
1686
1687         virtual void Verify()
1688         {
1689             if (m_icon.empty()) {
1690                 ThrowMsg(Exception::ParseError,
1691                     "src attribute of box-icon element is mandatory - ignoring");
1692             }
1693             m_data.m_icon = m_icon;
1694         }
1695
1696         explicit BoxIconParser(ConfigParserData::LiveboxInfo& data) :
1697             ElementParser(),
1698             m_properNamespace(false),
1699             m_data(data)
1700         {}
1701
1702       private:
1703         DPL::String m_icon;
1704         bool m_properNamespace;
1705         ConfigParserData::LiveboxInfo& m_data;
1706     };
1707
1708     struct BoxContentParser : public ElementParser
1709     {
1710         struct BoxSizeParser : public ElementParser
1711         {
1712             virtual ActionFunc GetElementParser(const DPL::String& /*ns*/,
1713                                                 const DPL::String& /*name*/)
1714             {
1715                 return &IgnoringParser::Create; //ignore unknown according to w3c
1716             }
1717
1718             virtual void Accept(const XmlAttribute& attribute)
1719             {
1720                 if (m_properNamespace) {
1721                     if (attribute.name == L"preview") {
1722                         m_preview = attribute.value;
1723                     }
1724                     if (attribute.name == L"use-decoration") {
1725                         m_useDecoration = attribute.value;
1726                     }
1727                 }
1728             }
1729
1730             virtual void Accept(const Element& element)
1731             {
1732                 if (element.ns ==
1733                     ConfigurationNamespace::TizenWebAppNamespaceName)
1734                 {
1735                     m_properNamespace = true;
1736                 }
1737             }
1738
1739             virtual void Accept(const Text& text)
1740             {
1741                 if (m_properNamespace) {
1742                     m_size = text.value;
1743                 }
1744             }
1745
1746             virtual void Verify()
1747             {
1748                 if(m_size.empty()) {
1749                     ThrowMsg(Exception::ParseError,
1750                         "size is mandatory - ignoring");
1751                 }
1752
1753                 ConfigParserData::LiveboxInfo::BoxSizeInfo boxSizeInfo;
1754                 boxSizeInfo.m_size = m_size;
1755                 boxSizeInfo.m_preview = m_preview;
1756                 boxSizeInfo.m_useDecoration = m_useDecoration;
1757                 m_data.m_boxSize.push_back(boxSizeInfo);
1758             }
1759
1760             explicit BoxSizeParser(
1761                 ConfigParserData::LiveboxInfo::BoxContentInfo& data) :
1762                 ElementParser(),
1763                 m_properNamespace(false),
1764                 m_data(data)
1765             {}
1766
1767           private:
1768             DPL::String m_size;
1769             DPL::String m_preview;
1770             DPL::String m_useDecoration;
1771             bool m_properNamespace;
1772             ConfigParserData::LiveboxInfo::BoxContentInfo& m_data;
1773         };
1774
1775         struct PdParser : public ElementParser
1776         {
1777             virtual ActionFunc GetElementParser(const DPL::String& /*ns*/,
1778                                                 const DPL::String& /*name*/)
1779             {
1780                 return &IgnoringParser::Create; //ignore unknown according to w3c
1781             }
1782
1783             virtual void Accept(const XmlAttribute& attribute)
1784             {
1785                 if (m_properNamespace) {
1786                     if (attribute.name == L"src") {
1787                         m_src = attribute.value;
1788                     } else if (attribute.name == L"width") {
1789                         m_width = attribute.value;
1790                     } else if (attribute.name == L"height") {
1791                         m_height = attribute.value;
1792                     } else if (attribute.name == L"fast-open") {
1793                         m_fastOpen= attribute.value;
1794                     }
1795                 }
1796             }
1797
1798             virtual void Accept(const Element& element)
1799             {
1800                 if (element.ns ==
1801                     ConfigurationNamespace::TizenWebAppNamespaceName)
1802                 {
1803                     m_properNamespace = true;
1804                 }
1805             }
1806
1807             virtual void Accept(const Text& /*text*/)
1808             {}
1809
1810             virtual void Verify()
1811             {
1812                 if (m_src.empty()) {
1813                     ThrowMsg(Exception::ParseError,
1814                         "src attribute of pd element is mandatory - ignoring");
1815                 }
1816
1817                 if (m_width.empty()) {
1818                     ThrowMsg(Exception::ParseError,
1819                         "width attribute of pd element is mandatory - ignoring");
1820                 }
1821
1822                 if (m_height.empty()) {
1823                     ThrowMsg(Exception::ParseError,
1824                         "height attribute of pd element is mandatory - ignoring");
1825                 }
1826
1827                 if (ConvertToInt(m_width).IsNull()) {
1828                     ThrowMsg(Exception::ParseError,
1829                         "width attribute of pd element cannot be converted to int - ignoring. value: " << m_width);
1830                 }
1831
1832
1833                 DPL::OptionalInt height = ConvertToInt(m_height);
1834
1835                 if (height.IsNull()) {
1836                     ThrowMsg(Exception::ParseError,
1837                         "height attribute of pd element cannot be converted to int - ignoring. value: " << m_height);
1838                 }
1839
1840                 if (*height < 1) {
1841                     m_height = L"1";
1842                     LogDebug("height attribute of pd element shouldn't be less than 1. Changed to 1 from " << *height);
1843                 } else if (*height > 380){
1844                     m_height = L"380";
1845                     LogDebug("height attribute of pd element shouldn't be greater than 380. Changed to 380 from " << *height);
1846                 }
1847
1848                 m_data.m_pdSrc = m_src;
1849                 m_data.m_pdWidth = m_width;
1850                 m_data.m_pdHeight = m_height;
1851                 m_data.m_pdFastOpen = m_fastOpen;
1852             }
1853
1854             explicit PdParser(
1855                 ConfigParserData::LiveboxInfo::BoxContentInfo& data) :
1856                 ElementParser(),
1857                 m_properNamespace(false),
1858                 m_data(data)
1859             {}
1860
1861           private:
1862             DPL::OptionalInt ConvertToInt(const DPL::String& intAsString)
1863             {
1864                 char * endptr;
1865                 std::string tempStr = DPL::ToUTF8String(intAsString);
1866                 const char * intAsString_c = tempStr.c_str();
1867                 errno = 0;
1868                 long int intAsString_i = strtol(intAsString_c, &endptr, 10);
1869
1870                 if ((errno == ERANGE && (intAsString_i == LONG_MAX || intAsString_i == LONG_MIN))
1871                         || intAsString_i > INT_MAX || intAsString_i < INT_MIN
1872                         || *endptr != '\0') {
1873                     return DPL::OptionalInt::Null;
1874                 }
1875
1876                 return static_cast<int>(intAsString_i);
1877             }
1878
1879             DPL::String m_src;
1880             DPL::String m_width;
1881             DPL::String m_height;
1882             DPL::String m_fastOpen;
1883
1884             bool m_properNamespace;
1885             ConfigParserData::LiveboxInfo::BoxContentInfo& m_data;
1886         };
1887
1888         virtual ActionFunc GetElementParser(const DPL::String& /*ns*/,
1889                                             const DPL::String& name)
1890         {
1891             if (name == L"box-size") {
1892                 return DPL::MakeDelegate(
1893                            this,
1894                            &AppWidgetParser::BoxContentParser::
1895                                OnBoxSizeElement);
1896             } else if (name == L"pd") {
1897                 return DPL::MakeDelegate(
1898                            this,
1899                            &AppWidgetParser::BoxContentParser::
1900                                OnPdElement);
1901             } else {
1902                 ThrowMsg(Exception::ParseError,
1903                          "No element parser for name: " << name);
1904             }
1905         }
1906
1907         virtual void Accept(const XmlAttribute& attribute)
1908         {
1909             if (m_properNamespace) {
1910                 if (attribute.name == L"src") {
1911                     m_box.m_boxSrc = attribute.value;
1912                 }
1913                 if (attribute.name == L"mouse-event") {
1914                     m_box.m_boxMouseEvent = attribute.value;
1915                 }
1916                 if (attribute.name == L"touch-effect") {
1917                     m_box.m_boxTouchEffect = attribute.value;
1918                 }
1919             }
1920         }
1921
1922         virtual void Accept(const Element& element)
1923         {
1924             if (element.ns ==
1925                 ConfigurationNamespace::TizenWebAppNamespaceName)
1926             {
1927                 m_properNamespace = true;
1928             }
1929         }
1930
1931         virtual void Accept(const Text& /*text*/)
1932         {}
1933
1934         virtual void Verify()
1935         {
1936             if (m_box.m_boxSrc.empty()) {
1937                 ThrowMsg(Exception::ParseError,
1938                     "src attribute of box-content element is mandatory - ignoring");
1939             }
1940
1941             if (!m_box.m_boxMouseEvent.empty() &&
1942                     CheckIfNotTrueNorFalse(m_box.m_boxMouseEvent))
1943             {
1944                 ThrowMsg(Exception::ParseError,
1945                     "mouse-event attribute of box-content element should be true or false - ignoring");
1946             }
1947
1948             if (!m_box.m_boxTouchEffect.empty() &&
1949                     CheckIfNotTrueNorFalse(m_box.m_boxTouchEffect))
1950             {
1951                 ThrowMsg(Exception::ParseError,
1952                     "touch-effect attribute of box-content element should be true or false - ignoring");
1953             }
1954
1955             if (m_box.m_boxMouseEvent.empty()) {
1956                 m_box.m_boxMouseEvent = L"false";
1957             }
1958
1959             if (m_box.m_boxTouchEffect.empty()) {
1960                 m_box.m_boxTouchEffect = L"true";
1961             }
1962
1963             if (m_box.m_boxSize.empty()) {
1964                 ThrowMsg(Exception::ParseError,
1965                     "box-size element of box-content element not found - ignoring");
1966             }
1967
1968             m_data.m_boxInfo = m_box;
1969         }
1970
1971         explicit BoxContentParser(ConfigParserData::LiveboxInfo& data) :
1972             ElementParser(),
1973             m_properNamespace(false),
1974             m_data(data)
1975         {}
1976
1977         ElementParserPtr OnBoxSizeElement()
1978         {
1979             return ElementParserPtr(new BoxSizeParser(m_box));
1980         }
1981
1982         ElementParserPtr OnPdElement()
1983         {
1984             return ElementParserPtr(new PdParser(m_box));
1985         }
1986
1987       private:
1988         bool m_properNamespace;
1989         ConfigParserData::LiveboxInfo& m_data;
1990         ConfigParserData::LiveboxInfo::BoxContentInfo m_box;
1991     };
1992
1993     virtual ActionFunc GetElementParser(const DPL::String& /*ns*/,
1994                                         const DPL::String& name)
1995     {
1996         if (name == L"box-label") {
1997             return DPL::MakeDelegate(this, &AppWidgetParser::OnBoxLabelElement);
1998         } else if (name == L"box-icon") {
1999             return DPL::MakeDelegate(this, &AppWidgetParser::OnBoxIconElement);
2000         } else if (name == L"box-content") {
2001             return DPL::MakeDelegate(this, &AppWidgetParser::OnBoxContentElement);
2002         } else {
2003             return &IgnoringParser::Create; //ignore unknown according to w3c
2004         }
2005     }
2006
2007     virtual void Accept(const XmlAttribute& attribute)
2008     {
2009         if (m_properNamespace) {
2010             if (attribute.name == L"id") {
2011                 m_liveboxId = attribute.value;
2012             } else if (attribute.name == L"primary") {
2013                 m_primary = attribute.value;
2014             } else if (attribute.name == L"auto-launch") {
2015                 m_autoLaunch = attribute.value;
2016             } else if (attribute.name == L"update-period") {
2017                 m_updatePeriod = attribute.value;
2018             } else if (attribute.name == L"type") {
2019                 m_type = attribute.value;
2020             }
2021         }
2022     }
2023
2024     virtual void Accept(const Element& element)
2025     {
2026         if (element.ns ==
2027             ConfigurationNamespace::TizenWebAppNamespaceName)
2028         {
2029             m_properNamespace = true;
2030         }
2031     }
2032
2033     virtual void Accept(const Text& /*text*/)
2034     {}
2035
2036     virtual void Verify()
2037     {
2038         if (m_liveboxId.empty()) {
2039             ThrowMsg(Exception::ParseError,
2040                  "app-widget element must have id attribute");
2041         }
2042         else
2043         {
2044             pcrecpp::RE re(REGEXP_ID_STRING.c_str());
2045             if (!re.FullMatch(DPL::ToUTF8String(m_liveboxId)))
2046             {
2047                 ThrowMsg(Exception::ParseError,
2048                      "invalid format of app-widget id attribute");
2049             }
2050         }
2051
2052         if (m_primary.empty())
2053         {
2054             ThrowMsg(Exception::ParseError,
2055                  "app-widget element must have primary attribute");
2056         } else if (CheckIfNotTrueNorFalse(m_primary))
2057         {
2058             ThrowMsg(Exception::ParseError,
2059                 "auto-launch attribute of app-widget element should be true or false - ignoring");
2060         }
2061
2062         if (!m_autoLaunch.empty() &&
2063                 CheckIfNotTrueNorFalse(m_autoLaunch))
2064         {
2065             ThrowMsg(Exception::ParseError,
2066                 "auto-launch attribute of app-widget element should be true or false - ignoring");
2067         }
2068
2069         if (!m_updatePeriod.empty())
2070         {
2071             char * endptr;
2072             errno = 0;
2073             std::string tempStr = DPL::ToUTF8String(m_updatePeriod);
2074
2075             //set standard locale to fix decimal point mark - '.'
2076             std::string currentLocale = setlocale(LC_NUMERIC, NULL);
2077             if (NULL == setlocale(LC_NUMERIC, "C"))
2078                 LogWarning("Failed to change locale to \"C\"");
2079             double updatePeriod = strtod(tempStr.c_str(), &endptr);
2080
2081             //go back to previous locale
2082             if (NULL == setlocale(LC_NUMERIC, currentLocale.c_str()))
2083                 LogWarning("Failed to set previous locale");
2084
2085             if ((errno == ERANGE && (updatePeriod == -HUGE_VAL || updatePeriod == HUGE_VAL))
2086                     || *endptr != '\0') {
2087                 ThrowMsg(Exception::ParseError,
2088                     "update-period attribute of app-widget element should be a number - ignoring. current value: " << m_updatePeriod);
2089             } else if (updatePeriod < 1800.0) {
2090                 LogDebug("update-period attribute of app-widget element shouldn't be less than 1800.0 - changed to 1800 from value: " << m_updatePeriod);
2091                 m_updatePeriod = L"1800.0";
2092             }
2093         }
2094
2095         if (m_autoLaunch.empty()) {
2096             m_autoLaunch = L"false";
2097         }
2098
2099         if(m_livebox.m_label.empty()) {
2100             ThrowMsg(Exception::ParseError,
2101                 "box-label element of app-widget element not found - ignoring");
2102         }
2103
2104         if(!m_boxContentFound) {
2105             ThrowMsg(Exception::ParseError,
2106                 "box-content element of app-widget element not found - ignoring");
2107         }
2108
2109         m_livebox.m_liveboxId = m_liveboxId;
2110         m_livebox.m_primary = m_primary;
2111         m_livebox.m_autoLaunch = m_autoLaunch;
2112         m_livebox.m_updatePeriod = m_updatePeriod;
2113         m_livebox.m_type = m_type;
2114
2115         m_data.m_livebox.push_back(m_livebox);
2116     }
2117
2118     explicit AppWidgetParser(ConfigParserData& data) :
2119         ElementParser(),
2120         m_data(data),
2121         m_properNamespace(false),
2122         m_boxContentFound(false)
2123     {
2124         m_livebox = ConfigParserData::LiveboxInfo();
2125     }
2126
2127     ElementParserPtr OnBoxLabelElement()
2128     {
2129
2130         return ElementParserPtr(new BoxLabelParser(m_livebox));
2131     }
2132
2133     ElementParserPtr OnBoxIconElement()
2134     {
2135         return ElementParserPtr(new BoxIconParser(m_livebox));
2136     }
2137
2138     ElementParserPtr OnBoxContentElement()
2139     {
2140         m_boxContentFound = true;
2141         return ElementParserPtr(new BoxContentParser(m_livebox));
2142     }
2143
2144   private:
2145     static std::string REGEXP_ID_STRING;
2146     ConfigParserData& m_data;
2147     ConfigParserData::LiveboxInfo m_livebox;
2148     DPL::String m_liveboxId;
2149     DPL::String m_primary;
2150     DPL::String m_autoLaunch;
2151     DPL::String m_updatePeriod;
2152     DPL::String m_type;
2153     bool m_properNamespace;
2154     bool m_boxContentFound;
2155
2156     static bool CheckIfNotTrueNorFalse(const DPL::String &stringToCheck)
2157     {
2158         return stringToCheck.compare(L"true") != 0 && stringToCheck.compare(L"false") != 0;
2159     }
2160 };
2161
2162 std::string AppWidgetParser::REGEXP_ID_STRING = std::string(ApplicationParser::REGEXP_ID) + "\\.[0-9A-Za-z]+";
2163
2164 class AllowNavigationParser : public ElementParser
2165 {
2166   public:
2167     AllowNavigationParser(ConfigParserData& data) :
2168       ElementParser(),
2169       m_data(data),
2170       m_properNamespace(false)
2171     {}
2172
2173     virtual ActionFunc GetElementParser(const DPL::String& /*ns*/,
2174                                         const DPL::String& /*name*/)
2175     {
2176         return &IgnoringParser::Create; //ignore unknown according to w3c
2177     }
2178
2179     virtual void Accept(const Element& element)
2180     {
2181         if (element.ns == ConfigurationNamespace::TizenWebAppNamespaceName) {
2182             m_properNamespace = true;
2183         }
2184     }
2185
2186     virtual void Accept(const Text& text)
2187     {
2188         if (m_properNamespace) {
2189             m_origin = text.value;
2190         }
2191     }
2192
2193     virtual void Accept(const XmlAttribute& /*attribute*/)
2194     {
2195     }
2196
2197     virtual void Verify()
2198     {
2199         if (m_origin.IsNull()) {
2200             LogWarning("data is empty");
2201             return;
2202         }
2203
2204         char* data = strdup(DPL::ToUTF8String(*m_origin).c_str());
2205         char* ptr = strtok(data," ");
2206         while (ptr != NULL) {
2207             std::string origin = ptr;
2208             ptr = strtok(NULL," ");
2209             if(origin == "*") {
2210                 ConfigParserData::AllowNavigationInfo info(L"*", L"*");
2211                 m_data.allowNavigationInfoList.push_back(info);
2212                 continue;
2213             }
2214
2215             DPL::ScopedPtr<iri_t> iri(iri_parse(origin.c_str()));
2216             if (!iri->host || strlen(iri->host) == 0) {
2217                 // input origin should has schem and host
2218                 // in case of file scheme path is filled
2219                 // "http://"
2220                 LogWarning("input origin isn't verified");
2221                 continue;
2222             }
2223             DPL::String scheme = L"*";
2224             if (iri->scheme && strlen(iri->scheme) != 0) {
2225                 scheme = DPL::FromUTF8String(iri->scheme);
2226             }
2227             ConfigParserData::AllowNavigationInfo info(
2228                 scheme,
2229                 DPL::FromUTF8String(iri->host));
2230             m_data.allowNavigationInfoList.push_back(info);
2231         }
2232         free(data);
2233     }
2234
2235   private:
2236     DPL::OptionalString m_origin;
2237     ConfigParserData& m_data;
2238     bool m_properNamespace;
2239 };
2240
2241 class CspParser : public ElementParser
2242 {
2243   public:
2244     virtual ActionFunc GetElementParser(const DPL::String& /*ns*/,
2245                                         const DPL::String& /*name*/)
2246     {
2247         return &IgnoringParser::Create; //ignore unknown according to w3c
2248     }
2249
2250     CspParser(ConfigParserData& data) :
2251         ElementParser(),
2252         m_data(data),
2253         m_properNamespace(false)
2254     {}
2255
2256     virtual void Accept(const Element& element)
2257     {
2258         if (element.ns == ConfigurationNamespace::TizenWebAppNamespaceName) {
2259             m_properNamespace = true;
2260         }
2261     }
2262
2263     virtual void Accept(const XmlAttribute& /*attribute*/)
2264     {}
2265
2266     virtual void Accept(const Text& text)
2267     {
2268         if (m_properNamespace) {
2269             m_policy = text.value;
2270         }
2271     }
2272
2273     virtual void Verify()
2274     {
2275         if (!m_policy.IsNull()) {
2276             m_data.cspPolicy = *m_policy;
2277         }
2278     }
2279
2280   private:
2281     ConfigParserData& m_data;
2282     bool m_properNamespace;
2283     DPL::OptionalString m_policy;
2284 };
2285
2286 class CspReportOnlyParser : public ElementParser
2287 {
2288   public:
2289     virtual ActionFunc GetElementParser(const DPL::String& /*ns*/,
2290                                         const DPL::String& /*name*/)
2291     {
2292         return &IgnoringParser::Create; //ignore unknown according to w3c
2293     }
2294
2295     CspReportOnlyParser(ConfigParserData& data) :
2296         ElementParser(),
2297         m_data(data),
2298         m_properNamespace(false)
2299     {}
2300
2301     virtual void Accept(const Element& element)
2302     {
2303         if (element.ns == ConfigurationNamespace::TizenWebAppNamespaceName) {
2304             m_properNamespace = true;
2305         }
2306     }
2307
2308     virtual void Accept(const XmlAttribute& /*attribute*/)
2309     {}
2310
2311     virtual void Accept(const Text& text)
2312     {
2313         if (m_properNamespace) {
2314             m_policy = text.value;
2315         }
2316     }
2317
2318     virtual void Verify()
2319     {
2320         if (!m_policy.IsNull()) {
2321             m_data.cspPolicyReportOnly = *m_policy;
2322         }
2323     }
2324
2325   private:
2326     ConfigParserData& m_data;
2327     bool m_properNamespace;
2328     DPL::OptionalString m_policy;
2329 };
2330
2331 class AccountParser : public ElementParser
2332 {
2333   public:
2334     struct AccountProviderParser : public ElementParser
2335     {
2336       public:
2337
2338           struct IconParser : public ElementParser
2339         {
2340             public:
2341                 virtual ActionFunc GetElementParser(const DPL::String& /*ns*/,
2342                         const DPL::String& /*name*/)
2343                 {
2344                     return &IgnoringParser::Create; //ignore unknown according to w3c
2345                 }
2346
2347                 virtual void Accept(const Text& text)
2348                 {
2349                     if (text.value == L"") {
2350                         return;
2351                     }
2352                     m_value = text.value;
2353                 }
2354
2355                 virtual void Accept(const Element& /*element*/)
2356                 {}
2357
2358                 virtual void Accept(const XmlAttribute& attribute)
2359                 {
2360                     if (attribute.name == L"section") {
2361                         if (attribute.value == L"account") {
2362                             m_type = ConfigParserData::IconSectionType::DefaultIcon;
2363                         } else if (attribute.value == L"account-small") {
2364                             m_type = ConfigParserData::IconSectionType::SmallIcon;
2365                         }
2366                     }
2367                 }
2368
2369                 virtual void Verify()
2370                 {
2371                     if (m_value.IsNull() || *m_value == L"") {
2372                         return;
2373                     }
2374
2375                     std::pair<ConfigParserData::IconSectionType, DPL::String> icon;
2376                     icon.first = m_type;
2377                     icon.second = *m_value;
2378
2379                     m_data.m_iconSet.insert(icon);
2380                 }
2381
2382                 IconParser(ConfigParserData::AccountProvider& data) :
2383                     ElementParser(),
2384                     m_properNamespace(false),
2385                     m_type(ConfigParserData::DefaultIcon),
2386                     m_data(data)
2387             {}
2388
2389             private:
2390                 bool m_properNamespace;
2391                 ConfigParserData::IconSectionType m_type;
2392                 ConfigParserData::AccountProvider& m_data;
2393                 DPL::OptionalString m_value;
2394         };
2395
2396           struct DisplayNameParser : public ElementParser
2397         {
2398             public:
2399                 virtual ActionFunc GetElementParser(const DPL::String& /*ns*/,
2400                         const DPL::String& /*name*/)
2401                 {
2402                     return &IgnoringParser::Create; //ignore unknown according to w3c
2403                 }
2404
2405                 virtual void Accept(const Text& text)
2406                 {
2407                     if (text.value == L"") {
2408                         return;
2409                     }
2410                     m_value = text.value;
2411                 }
2412
2413                 virtual void Accept(const Element& element)
2414                 {
2415                     m_lang = element.lang;
2416                     m_value= L"";
2417                 }
2418
2419                 virtual void Accept(const XmlAttribute& /*attribute*/)
2420                 {}
2421
2422                 virtual void Verify()
2423                 {
2424                     if (m_value.IsNull() || *m_value == L"") {
2425                         return;
2426                     }
2427
2428                     std::pair<DPL::String, DPL::String> name;
2429                     name.first = *m_lang;
2430                     name.second = *m_value;
2431
2432                     m_data.m_displayNameSet.insert(name);
2433                 }
2434
2435                 DisplayNameParser(ConfigParserData::AccountProvider& data) :
2436                     ElementParser(),
2437                     m_properNamespace(false),
2438                     m_data(data)
2439             {}
2440
2441             private:
2442                 bool m_properNamespace;
2443                 DPL::OptionalString m_lang;
2444                 DPL::OptionalString m_value;
2445                 ConfigParserData::AccountProvider& m_data;
2446         };
2447
2448           struct CapabilityParser : public ElementParser
2449         {
2450             public:
2451                 virtual ActionFunc GetElementParser(const DPL::String& /*ns*/,
2452                         const DPL::String& /*name*/)
2453                 {
2454                     return &IgnoringParser::Create; //ignore unknown according to w3c
2455                 }
2456
2457                 virtual void Accept(const Text& text)
2458                 {
2459                     if (text.value == L"") {
2460                         return;
2461                     }
2462                     m_value = text.value;
2463                 }
2464
2465                 virtual void Accept(const Element& /*element*/)
2466                 {}
2467
2468                 virtual void Accept(const XmlAttribute& /*attribute*/)
2469                 {}
2470
2471                 virtual void Verify()
2472                 {
2473                     if (m_value.IsNull() || *m_value == L"") {
2474                         return;
2475                     }
2476                     m_data.m_capabilityList.push_back(*m_value);
2477                 }
2478
2479                 CapabilityParser(ConfigParserData::AccountProvider& data) :
2480                     ElementParser(),
2481                     m_properNamespace(false),
2482                     m_data(data)
2483             {}
2484
2485             private:
2486                 bool m_properNamespace;
2487                 DPL::OptionalString m_value;
2488                 ConfigParserData::AccountProvider& m_data;
2489         };
2490           virtual ActionFunc GetElementParser(const DPL::String& /*ns*/,
2491                   const DPL::String& name)
2492           {
2493               if (name == L"icon") {
2494                   return DPL::MakeDelegate(this, &AccountProviderParser::OnIconElement);
2495               } else if (name == L"display-name") {
2496                   return DPL::MakeDelegate(this,
2497                           &AccountProviderParser::OnDisplayNameElement);
2498               } else if (name == L"capability") {
2499                   return DPL::MakeDelegate(this, &AccountProviderParser::OnCapabilityElement);
2500               } else {
2501                   return &IgnoringParser::Create; //ignore unknown according to w3c
2502               }
2503           }
2504
2505           virtual void Accept(const Text& /*text*/)
2506           {}
2507
2508           virtual void Accept(const Element& /*element*/)
2509           {}
2510
2511           virtual void Accept(const XmlAttribute& attribute)
2512           {
2513               if (attribute.name == L"multiple-accounts-support") {
2514                   if (attribute.value == L"true") {
2515                       m_multiSupport = true;
2516                   }
2517               }
2518           }
2519
2520           virtual void Verify()
2521           {
2522               m_data.m_multiAccountSupport = m_multiSupport;
2523           }
2524
2525           ElementParserPtr OnIconElement()
2526           {
2527               return ElementParserPtr(new IconParser(m_data));
2528           }
2529
2530           ElementParserPtr OnDisplayNameElement()
2531           {
2532               return ElementParserPtr(new DisplayNameParser(m_data));
2533           }
2534
2535           ElementParserPtr OnCapabilityElement()
2536           {
2537               return ElementParserPtr(new CapabilityParser(m_data));
2538           }
2539
2540           AccountProviderParser(ConfigParserData::AccountProvider& data) :
2541               ElementParser(),
2542               m_properNamespace(false),
2543               m_multiSupport(false),
2544               m_data(data)
2545         {}
2546
2547       private:
2548           bool m_properNamespace;
2549           bool m_multiSupport;
2550           ConfigParserData::AccountProvider& m_data;
2551     };
2552
2553     virtual ActionFunc GetElementParser(const DPL::String& /*ns*/,
2554             const DPL::String& name)
2555     {
2556         if (name == L"account-provider") {
2557             return DPL::MakeDelegate(this, &AccountParser::OnProviderElement);
2558         } else {
2559             return &IgnoringParser::Create; //ignore unknown according to w3c
2560         }
2561     }
2562
2563     virtual void Accept(const Element& element)
2564     {
2565         if (element.ns == ConfigurationNamespace::TizenWebAppNamespaceName) {
2566             m_properNamespace = true;
2567         }
2568     }
2569
2570     virtual void Accept(const XmlAttribute& /*attribute*/)
2571     {}
2572
2573     virtual void Accept(const Text& /*text*/)
2574     {}
2575
2576     virtual void Verify()
2577     {}
2578
2579     ElementParserPtr OnProviderElement()
2580     {
2581         return ElementParserPtr(new AccountProviderParser(m_account));
2582     }
2583
2584     AccountParser(ConfigParserData& data) :
2585         ElementParser(),
2586         m_data(data),
2587         m_account(data.accountProvider),
2588         m_properNamespace(false),
2589         m_multiSupport(false)
2590     {}
2591
2592   private:
2593     ConfigParserData& m_data;
2594     ConfigParserData::AccountProvider& m_account;
2595     bool m_properNamespace;
2596     bool m_multiSupport;
2597 };
2598
2599 class MetadataParser : public ElementParser
2600 {
2601   public:
2602     virtual ActionFunc GetElementParser(const DPL::String& /*ns*/,
2603                                         const DPL::String& /*name*/)
2604     {
2605         return &IgnoringParser::Create; //ignore unknown according to w3c
2606     }
2607
2608     virtual void Accept(const XmlAttribute& attribute)
2609     {
2610         if (m_properNamespace) {
2611             if (attribute.name == L"key") {
2612                 m_key = attribute.value;
2613             } else if (attribute.name == L"value") {
2614                 m_value = attribute.value;
2615             }
2616         }
2617     }
2618
2619     virtual void Accept(const Element& element)
2620     {
2621         if (element.ns == ConfigurationNamespace::TizenWebAppNamespaceName) {
2622             m_properNamespace = true;
2623         }
2624     }
2625
2626     virtual void Accept(const Text& /*text*/)
2627     {
2628         ThrowMsg(Exception::ParseError, "param element must be empty");
2629     }
2630
2631     virtual void Verify()
2632     {
2633         if (m_key.IsNull()) {
2634             LogWarning("metadata element must have key attribute");
2635             return;
2636         }
2637         NormalizeString(m_key);
2638         NormalizeString(m_value);
2639         ConfigParserData::Metadata metaData(m_key, m_value);
2640         FOREACH(it, m_data.metadataList) {
2641             if (!DPL::StringCompare(*it->key, *m_key)) {
2642                 LogError("Key isn't unique");
2643                 return;
2644             }
2645         }
2646         m_data.metadataList.push_back(metaData);
2647     }
2648
2649     MetadataParser(ConfigParserData& data) :
2650         ElementParser(),
2651         m_data(data),
2652         m_properNamespace(false)
2653     {}
2654
2655   private:
2656     DPL::OptionalString m_key;
2657     DPL::OptionalString m_value;
2658     ConfigParserData& m_data;
2659     bool m_properNamespace;
2660 };
2661
2662 ElementParser::ActionFunc WidgetParser::GetElementParser(
2663     const DPL::String& /*ns*/,
2664     const DPL::String& name)
2665 {
2666     FuncMap::const_iterator it = m_map.find(name);
2667     if (it != m_map.end()) {
2668         return it->second;
2669     } else {
2670         return &IgnoringParser::Create; //ignore unknown according to w3c
2671     }
2672 }
2673
2674 WidgetParser::WidgetParser(ConfigParserData& data) :
2675     m_data(data),
2676     m_textDirection(Unicode::EMPTY)
2677 {
2678     m_map[L"name"] = DPL::MakeDelegate(this, &WidgetParser::OnNameElement);
2679     m_map[L"access"] = DPL::MakeDelegate(this, &WidgetParser::OnAccessElement);
2680     m_map[L"description"] =
2681         DPL::MakeDelegate(this, &WidgetParser::OnDescriptionElement);
2682     m_map[L"author"] = DPL::MakeDelegate(this, &WidgetParser::OnAuthorElement);
2683     m_map[L"license"] =
2684         DPL::MakeDelegate(this, &WidgetParser::OnLicenseElement);
2685     m_map[L"icon"] = DPL::MakeDelegate(this, &WidgetParser::OnIconElement);
2686     m_map[L"content"] =
2687         DPL::MakeDelegate(this, &WidgetParser::OnContentElement);
2688     m_map[L"preference"] =
2689         DPL::MakeDelegate(this, &WidgetParser::OnPreferenceElement);
2690     m_map[L"link"] = DPL::MakeDelegate(this, &WidgetParser::OnLinkElement);
2691     m_map[L"setting"] =
2692         DPL::MakeDelegate(this, &WidgetParser::OnSettingElement);
2693     m_map[L"application"] = DPL::MakeDelegate(
2694             this,
2695             &WidgetParser::
2696                 OnApplicationElement);
2697     m_map[L"splash"] = DPL::MakeDelegate(this, &WidgetParser::OnSplashElement);
2698     m_map[L"background"] = DPL::MakeDelegate(this,
2699                                              &WidgetParser::OnBackgroundElement);
2700     m_map[L"privilege"] = DPL::MakeDelegate(this,
2701                                             &WidgetParser::OnPrivilegeElement);
2702     m_map[L"app-control"] = DPL::MakeDelegate(
2703             this,
2704             &WidgetParser::
2705                 OnAppControlElement);
2706     m_map[L"category"] = DPL::MakeDelegate(this,
2707                                            &WidgetParser::OnCategoryElement);
2708     m_map[L"app-widget"] = DPL::MakeDelegate(this, &WidgetParser::OnAppWidgetElement);
2709 #ifdef CSP_ENABLED
2710     m_map[L"content-security-policy"] = DPL::MakeDelegate(
2711             this,
2712             &WidgetParser::
2713                 OnCspElement);
2714     m_map[L"content-security-policy-report-only"] = DPL::MakeDelegate(
2715             this,
2716             &WidgetParser::
2717                 OnCspReportOnlyElement);
2718 #endif
2719 #ifdef ALLOW_NAVIGATION_ENABLED
2720     m_map[L"allow-navigation"] =
2721         DPL::MakeDelegate(this, &WidgetParser::OnAllowNavigationElement);
2722 #endif
2723     m_map[L"account"] = DPL::MakeDelegate(this, &WidgetParser::OnAccountElement);
2724     m_map[L"metadata"] = DPL::MakeDelegate(this, &WidgetParser::OnMetadataElement);
2725 }
2726
2727 ElementParserPtr WidgetParser::OnNameElement()
2728 {
2729     return ElementParserPtr(new NameParser(m_textDirection, m_data));
2730 }
2731
2732 ElementParserPtr WidgetParser::OnAccessElement()
2733 {
2734     return ElementParserPtr(new AccessParser(m_data));
2735 }
2736
2737 ElementParserPtr WidgetParser::OnDescriptionElement()
2738 {
2739     return ElementParserPtr(new DescriptionParser(m_textDirection, m_data));
2740 }
2741
2742 ElementParserPtr WidgetParser::OnAuthorElement()
2743 {
2744     return ElementParserPtr(new AuthorParser(m_textDirection, m_data));
2745 }
2746
2747 ElementParserPtr WidgetParser::OnLicenseElement()
2748 {
2749     return ElementParserPtr(new LicenseParser(m_textDirection, m_data));
2750 }
2751
2752 ElementParserPtr WidgetParser::OnIconElement()
2753 {
2754     return ElementParserPtr(new IconParser(m_data));
2755 }
2756
2757 ElementParserPtr WidgetParser::OnContentElement()
2758 {
2759     return ElementParserPtr(new ContentParser(m_data));
2760 }
2761
2762 ElementParserPtr WidgetParser::OnPreferenceElement()
2763 {
2764     return ElementParserPtr(new PreferenceParser(m_data));
2765 }
2766
2767 ElementParserPtr WidgetParser::OnLinkElement()
2768 {
2769     return ElementParserPtr(new LinkParser(m_data));
2770 }
2771
2772 ElementParserPtr WidgetParser::OnSettingElement()
2773 {
2774     return ElementParserPtr(new SettingParser(m_data));
2775 }
2776
2777 ElementParserPtr WidgetParser::OnApplicationElement()
2778 {
2779     return ElementParserPtr(new ApplicationParser(m_data));
2780 }
2781
2782 ElementParserPtr WidgetParser::OnSplashElement()
2783 {
2784     return ElementParserPtr(new SplashParser(m_data));
2785 }
2786
2787 ElementParserPtr WidgetParser::OnBackgroundElement()
2788 {
2789     return ElementParserPtr(new BackgroundParser(m_data));
2790 }
2791
2792 ElementParserPtr WidgetParser::OnPrivilegeElement()
2793 {
2794     return ElementParserPtr(new PrivilegeParser(m_data));
2795 }
2796
2797 ElementParserPtr WidgetParser::OnAppControlElement()
2798 {
2799     return ElementParserPtr(new AppControlParser(m_data));
2800 }
2801
2802 ElementParserPtr WidgetParser::OnCategoryElement()
2803 {
2804     return ElementParserPtr(new CategoryParser(m_data));
2805 }
2806
2807 ElementParserPtr WidgetParser::OnAppWidgetElement()
2808 {
2809     return ElementParserPtr(new AppWidgetParser(m_data));
2810 }
2811
2812 ElementParserPtr WidgetParser::OnCspElement()
2813 {
2814     return ElementParserPtr(new CspParser(m_data));
2815 }
2816
2817 ElementParserPtr WidgetParser::OnCspReportOnlyElement()
2818 {
2819     return ElementParserPtr(new CspReportOnlyParser(m_data));
2820 }
2821
2822 ElementParserPtr WidgetParser::OnAllowNavigationElement()
2823 {
2824     return ElementParserPtr(new AllowNavigationParser(m_data));
2825 }
2826
2827 ElementParserPtr WidgetParser::OnAccountElement()
2828 {
2829     return ElementParserPtr(new AccountParser(m_data));
2830 }
2831
2832 ElementParserPtr WidgetParser::OnMetadataElement()
2833 {
2834     return ElementParserPtr(new MetadataParser(m_data));
2835 }
2836
2837 void WidgetParser::Accept(const Element& element)
2838 {
2839     if (element.ns != ConfigurationNamespace::W3CWidgetNamespaceName &&
2840         element.ns != ConfigurationNamespace::TizenWebAppNamespaceName)
2841     {
2842         ThrowMsg(Exception::ParseError,
2843                  "Wrong xml namespace for widget element");
2844     }
2845 }
2846
2847 void WidgetParser::Accept(const Text& /*text*/)
2848 {
2849     ThrowMsg(Exception::ParseError, "widged element must be empty");
2850 }
2851
2852 void WidgetParser::Accept(const XmlAttribute& attribute)
2853 {
2854     if (attribute.name == L"id") {
2855         LibIri::Wrapper iri(DPL::ToUTF8String(attribute.value).c_str());
2856         //If may important tests starts to fail this test we will have
2857         //to consider commenting this test out again.
2858         if (iri.Validate()) {
2859             m_data.widget_id = attribute.value;
2860             NormalizeString(m_data.widget_id);
2861         } else {
2862             LogWarning("Widget id validation failed: " << attribute.value);
2863         }
2864     } else if (attribute.name == L"version") {
2865         m_version = attribute.value;
2866         NormalizeString(m_version);
2867     } else if (attribute.name == L"min-version") {
2868         LogInfo("min-version attribute was found. Value: " << attribute.value);
2869         m_minVersion = attribute.value;
2870         NormalizeString(m_minVersion);
2871         m_data.minVersionRequired = m_minVersion;
2872     } else if (attribute.name == L"height") {
2873         DPL::OptionalString value = attribute.value;
2874         NormalizeString(value);
2875         std::string v = DPL::ToUTF8String(*value);
2876
2877         if (!v.empty()) {
2878             unsigned char c = v.c_str()[0];
2879             if (isdigit(c)) {
2880                 int val = 0;
2881                 for (size_t i = 0; i < v.size(); ++i) {
2882                     c = v.c_str()[i];
2883                     if (isdigit(c)) {
2884                         val *= 10;
2885                         val += (c - '0');
2886                     } else {
2887                         break;
2888                     }
2889                 }
2890                 m_data.height = val;
2891             }
2892         }
2893     } else if (attribute.name == L"width") {
2894         DPL::OptionalString value = attribute.value;
2895         NormalizeString(value);
2896         std::string v = DPL::ToUTF8String(*value);
2897
2898         if (!v.empty()) {
2899             unsigned char c = v.c_str()[0];
2900             if (c >= '0' && c <= '9') {
2901                 int val = 0;
2902                 for (size_t i = 0; i < v.size(); ++i) {
2903                     c = v.c_str()[i];
2904                     if (c >= '0' && c <= '9') {
2905                         val *= 10;
2906                         val += (c - '0');
2907                     } else {
2908                         break;
2909                     }
2910                 }
2911                 m_data.width = val;
2912             }
2913         }
2914     } else if (attribute.name == L"viewmodes") {
2915         DPL::Tokenize(attribute.value,
2916                       L" ",
2917                       std::inserter(m_windowModes,
2918                                     m_windowModes.end()),
2919                       true);
2920     } else if (attribute.name == L"dir") {
2921         m_textDirection = Unicode::ParseDirAttribute(attribute);
2922     } else if (L"defaultlocale" == attribute.name) {
2923         if (!m_defaultlocale) {
2924             m_defaultlocale = attribute.value;
2925             NormalizeString(m_defaultlocale);
2926             if (!LanguageSubtagRstTreeSingleton::Instance().ValidateLanguageTag(
2927                     DPL::ToUTF8String(*m_defaultlocale)))
2928             {
2929                 LogWarning("Language tag: " <<
2930                            m_defaultlocale << " is not valid");
2931                 m_defaultlocale = DPL::OptionalString::Null;
2932             } else {
2933                 LogDebug("Default Locale Found " << m_defaultlocale);
2934             }
2935         } else {
2936             LogWarning("Ignoring subsequent default locale");
2937         }
2938
2939         //Any other value consider as a namespace definition
2940     } else if (attribute.name == L"xmlns" || attribute.prefix == L"xmlns") {
2941         LogInfo("Namespace domain: " << attribute.name);
2942         LogInfo("Namespace value: " << attribute.value);
2943         m_nameSpaces[attribute.name] = attribute.value;
2944     } else {
2945         LogError("Unknown attirbute: namespace=" << attribute.ns <<
2946                  ", name=" << attribute.name <<
2947                  ", value=" << attribute.value);
2948     }
2949 }
2950
2951 void WidgetParser::Verify()
2952 {
2953     FOREACH(mode, m_windowModes) {
2954         if (L"windowed" == *mode || L"floating" == *mode ||
2955             L"fullscreen" == *mode || L"maximized" == *mode ||
2956             L"minimized" == *mode)
2957         {
2958             m_data.windowModes.insert(*mode);
2959         }
2960     }
2961     if (!m_version.IsNull()) {
2962         Unicode::UpdateTextWithDirectionMark(m_textDirection, &*m_version);
2963         m_data.version = m_version;
2964     }
2965     m_data.defaultlocale = m_defaultlocale;
2966     FOREACH(ns, m_nameSpaces) {
2967         m_data.nameSpaces.insert(ns->second);
2968     }
2969 }
2970