Content tag parsing fix
[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             if (m_label.empty()) {
1632                 ThrowMsg(Exception::ParseError,
1633                         "box-label element cannot be empty - ignoring");
1634             }
1635             std::pair<DPL::String, DPL::String> boxLabel;
1636             boxLabel.first = m_lang;
1637             boxLabel.second = m_label;
1638             m_data.m_label.push_back(boxLabel);
1639         }
1640
1641         BoxLabelParser(ConfigParserData::LiveboxInfo& data) :
1642             ElementParser(),
1643             m_properNamespace(false),
1644             m_data(data)
1645         {}
1646
1647       private:
1648         DPL::String m_lang;
1649         DPL::String m_label;
1650         bool m_properNamespace;
1651         ConfigParserData::LiveboxInfo& m_data;
1652     };
1653
1654     struct BoxIconParser : public ElementParser
1655     {
1656         virtual ActionFunc GetElementParser(const DPL::String& /*ns*/,
1657                                             const DPL::String& /*name*/)
1658         {
1659             return &IgnoringParser::Create; //ignore unknown according to w3c
1660         }
1661
1662         virtual void Accept(const XmlAttribute& attribute)
1663         {
1664             if (m_properNamespace) {
1665                 if (attribute.name == L"src") {
1666                     m_icon = attribute.value;
1667                 }
1668             }
1669         }
1670
1671         virtual void Accept(const Element& element)
1672         {
1673             if (element.ns ==
1674                 ConfigurationNamespace::TizenWebAppNamespaceName)
1675             {
1676                 m_properNamespace = true;
1677             }
1678         }
1679
1680         virtual void Accept(const Text& /*text*/)
1681         {}
1682
1683         virtual void Verify()
1684         {
1685             if (m_icon.empty()) {
1686                 ThrowMsg(Exception::ParseError,
1687                     "src attribute of box-icon element is mandatory - ignoring");
1688             }
1689             m_data.m_icon = m_icon;
1690         }
1691
1692         explicit BoxIconParser(ConfigParserData::LiveboxInfo& data) :
1693             ElementParser(),
1694             m_properNamespace(false),
1695             m_data(data)
1696         {}
1697
1698       private:
1699         DPL::String m_icon;
1700         bool m_properNamespace;
1701         ConfigParserData::LiveboxInfo& m_data;
1702     };
1703
1704     struct BoxContentParser : public ElementParser
1705     {
1706         struct BoxSizeParser : public ElementParser
1707         {
1708             virtual ActionFunc GetElementParser(const DPL::String& /*ns*/,
1709                                                 const DPL::String& /*name*/)
1710             {
1711                 return &IgnoringParser::Create; //ignore unknown according to w3c
1712             }
1713
1714             virtual void Accept(const XmlAttribute& attribute)
1715             {
1716                 if (m_properNamespace) {
1717                     if (attribute.name == L"preview") {
1718                         m_preview = attribute.value;
1719                     }
1720                 }
1721             }
1722
1723             virtual void Accept(const Element& element)
1724             {
1725                 if (element.ns ==
1726                     ConfigurationNamespace::TizenWebAppNamespaceName)
1727                 {
1728                     m_properNamespace = true;
1729                 }
1730             }
1731
1732             virtual void Accept(const Text& text)
1733             {
1734                 if (m_properNamespace) {
1735                     m_size = text.value;
1736                 }
1737             }
1738
1739             virtual void Verify()
1740             {
1741                 if(m_size.empty()) {
1742                     ThrowMsg(Exception::ParseError,
1743                         "size is mandatory - ignoring");
1744                 }
1745
1746                 std::pair<DPL::String, DPL::String> boxSize;
1747                 boxSize.first = m_size;
1748                 boxSize.second = m_preview;
1749                 m_data.m_boxSize.push_back(boxSize);
1750             }
1751
1752             explicit BoxSizeParser(
1753                 ConfigParserData::LiveboxInfo::BoxContentInfo& data) :
1754                 ElementParser(),
1755                 m_properNamespace(false),
1756                 m_data(data)
1757             {}
1758
1759           private:
1760             DPL::String m_size;
1761             DPL::String m_preview;
1762             bool m_properNamespace;
1763             ConfigParserData::LiveboxInfo::BoxContentInfo& m_data;
1764         };
1765
1766         struct PdParser : public ElementParser
1767         {
1768             virtual ActionFunc GetElementParser(const DPL::String& /*ns*/,
1769                                                 const DPL::String& /*name*/)
1770             {
1771                 return &IgnoringParser::Create; //ignore unknown according to w3c
1772             }
1773
1774             virtual void Accept(const XmlAttribute& attribute)
1775             {
1776                 if (m_properNamespace) {
1777                     if (attribute.name == L"src") {
1778                         m_src = attribute.value;
1779                     } else if (attribute.name == L"width") {
1780                         m_width = attribute.value;
1781                     } else if (attribute.name == L"height") {
1782                         m_height = attribute.value;
1783                     } else if (attribute.name == L"fast-open") {
1784                         m_fastOpen= attribute.value;
1785                     }
1786                 }
1787             }
1788
1789             virtual void Accept(const Element& element)
1790             {
1791                 if (element.ns ==
1792                     ConfigurationNamespace::TizenWebAppNamespaceName)
1793                 {
1794                     m_properNamespace = true;
1795                 }
1796             }
1797
1798             virtual void Accept(const Text& /*text*/)
1799             {}
1800
1801             virtual void Verify()
1802             {
1803                 if (m_src.empty()) {
1804                     ThrowMsg(Exception::ParseError,
1805                         "src attribute of pd element is mandatory - ignoring");
1806                 }
1807
1808                 if (m_width.empty()) {
1809                     ThrowMsg(Exception::ParseError,
1810                         "width attribute of pd element is mandatory - ignoring");
1811                 }
1812
1813                 if (m_height.empty()) {
1814                     ThrowMsg(Exception::ParseError,
1815                         "height attribute of pd element is mandatory - ignoring");
1816                 }
1817
1818                 if (ConvertToInt(m_width).IsNull()) {
1819                     ThrowMsg(Exception::ParseError,
1820                         "width attribute of pd element cannot be converted to int - ignoring. value: " << m_width);
1821                 }
1822
1823
1824                 DPL::OptionalInt height = ConvertToInt(m_height);
1825
1826                 if (height.IsNull()) {
1827                     ThrowMsg(Exception::ParseError,
1828                         "height attribute of pd element cannot be converted to int - ignoring. value: " << m_height);
1829                 }
1830
1831                 if (*height < 1) {
1832                     m_height = L"1";
1833                     LogDebug("height attribute of pd element shouldn't be less than 1. Changed to 1 from " << *height);
1834                 } else if (*height > 380){
1835                     m_height = L"380";
1836                     LogDebug("height attribute of pd element shouldn't be greater than 380. Changed to 380 from " << *height);
1837                 }
1838
1839                 m_data.m_pdSrc = m_src;
1840                 m_data.m_pdWidth = m_width;
1841                 m_data.m_pdHeight = m_height;
1842                 m_data.m_pdFastOpen = m_fastOpen;
1843             }
1844
1845             explicit PdParser(
1846                 ConfigParserData::LiveboxInfo::BoxContentInfo& data) :
1847                 ElementParser(),
1848                 m_properNamespace(false),
1849                 m_data(data)
1850             {}
1851
1852           private:
1853             DPL::OptionalInt ConvertToInt(const DPL::String& intAsString)
1854             {
1855                 char * endptr;
1856                 std::string tempStr = DPL::ToUTF8String(intAsString);
1857                 const char * intAsString_c = tempStr.c_str();
1858                 errno = 0;
1859                 long int intAsString_i = strtol(intAsString_c, &endptr, 10);
1860
1861                 if ((errno == ERANGE && (intAsString_i == LONG_MAX || intAsString_i == LONG_MIN))
1862                         || intAsString_i > INT_MAX || intAsString_i < INT_MIN
1863                         || *endptr != '\0') {
1864                     return DPL::OptionalInt::Null;
1865                 }
1866
1867                 return static_cast<int>(intAsString_i);
1868             }
1869
1870             DPL::String m_src;
1871             DPL::String m_width;
1872             DPL::String m_height;
1873             DPL::String m_fastOpen;
1874
1875             bool m_properNamespace;
1876             ConfigParserData::LiveboxInfo::BoxContentInfo& m_data;
1877         };
1878
1879         virtual ActionFunc GetElementParser(const DPL::String& /*ns*/,
1880                                             const DPL::String& name)
1881         {
1882             if (name == L"box-size") {
1883                 return DPL::MakeDelegate(
1884                            this,
1885                            &AppWidgetParser::BoxContentParser::
1886                                OnBoxSizeElement);
1887             } else if (name == L"pd") {
1888                 return DPL::MakeDelegate(
1889                            this,
1890                            &AppWidgetParser::BoxContentParser::
1891                                OnPdElement);
1892             } else {
1893                 ThrowMsg(Exception::ParseError,
1894                          "No element parser for name: " << name);
1895             }
1896         }
1897
1898         virtual void Accept(const XmlAttribute& attribute)
1899         {
1900             if (m_properNamespace) {
1901                 if (attribute.name == L"src") {
1902                     m_box.m_boxSrc = attribute.value;
1903                 }
1904                 if (attribute.name == L"mouse-event") {
1905                     m_box.m_boxMouseEvent = attribute.value;
1906                 }
1907                 if (attribute.name == L"touch-effect") {
1908                     m_box.m_boxTouchEffect = attribute.value;
1909                 }
1910             }
1911         }
1912
1913         virtual void Accept(const Element& element)
1914         {
1915             if (element.ns ==
1916                 ConfigurationNamespace::TizenWebAppNamespaceName)
1917             {
1918                 m_properNamespace = true;
1919             }
1920         }
1921
1922         virtual void Accept(const Text& /*text*/)
1923         {}
1924
1925         virtual void Verify()
1926         {
1927             if (m_box.m_boxSrc.empty()) {
1928                 ThrowMsg(Exception::ParseError,
1929                     "src attribute of box-content element is mandatory - ignoring");
1930             }
1931
1932             if (!m_box.m_boxMouseEvent.empty() &&
1933                     CheckIfNotTrueNorFalse(m_box.m_boxMouseEvent))
1934             {
1935                 ThrowMsg(Exception::ParseError,
1936                     "mouse-event attribute of box-content element should be true or false - ignoring");
1937             }
1938
1939             if (!m_box.m_boxTouchEffect.empty() &&
1940                     CheckIfNotTrueNorFalse(m_box.m_boxTouchEffect))
1941             {
1942                 ThrowMsg(Exception::ParseError,
1943                     "touch-effect attribute of box-content element should be true or false - ignoring");
1944             }
1945
1946             if (m_box.m_boxMouseEvent.empty()) {
1947                 m_box.m_boxMouseEvent = L"false";
1948             }
1949
1950             if (m_box.m_boxTouchEffect.empty()) {
1951                 m_box.m_boxTouchEffect = L"true";
1952             }
1953
1954             if (m_box.m_boxSize.empty()) {
1955                 ThrowMsg(Exception::ParseError,
1956                     "box-size element of box-content element not found - ignoring");
1957             }
1958
1959             m_data.m_boxInfo = m_box;
1960         }
1961
1962         explicit BoxContentParser(ConfigParserData::LiveboxInfo& data) :
1963             ElementParser(),
1964             m_properNamespace(false),
1965             m_data(data)
1966         {}
1967
1968         ElementParserPtr OnBoxSizeElement()
1969         {
1970             return ElementParserPtr(new BoxSizeParser(m_box));
1971         }
1972
1973         ElementParserPtr OnPdElement()
1974         {
1975             return ElementParserPtr(new PdParser(m_box));
1976         }
1977
1978       private:
1979         bool m_properNamespace;
1980         ConfigParserData::LiveboxInfo& m_data;
1981         ConfigParserData::LiveboxInfo::BoxContentInfo m_box;
1982     };
1983
1984     virtual ActionFunc GetElementParser(const DPL::String& /*ns*/,
1985                                         const DPL::String& name)
1986     {
1987         if (name == L"box-label") {
1988             return DPL::MakeDelegate(this, &AppWidgetParser::OnBoxLabelElement);
1989         } else if (name == L"box-icon") {
1990             return DPL::MakeDelegate(this, &AppWidgetParser::OnBoxIconElement);
1991         } else if (name == L"box-content") {
1992             return DPL::MakeDelegate(this, &AppWidgetParser::OnBoxContentElement);
1993         } else {
1994             return &IgnoringParser::Create; //ignore unknown according to w3c
1995         }
1996     }
1997
1998     virtual void Accept(const XmlAttribute& attribute)
1999     {
2000         if (m_properNamespace) {
2001             if (attribute.name == L"id") {
2002                 m_liveboxId = attribute.value;
2003             } else if (attribute.name == L"primary") {
2004                 m_primary = attribute.value;
2005             } else if (attribute.name == L"auto-launch") {
2006                 m_autoLaunch = attribute.value;
2007             } else if (attribute.name == L"update-period") {
2008                 m_updatePeriod = attribute.value;
2009             } else if (attribute.name == L"type") {
2010                 m_type = attribute.value;
2011             }
2012         }
2013     }
2014
2015     virtual void Accept(const Element& element)
2016     {
2017         if (element.ns ==
2018             ConfigurationNamespace::TizenWebAppNamespaceName)
2019         {
2020             m_properNamespace = true;
2021         }
2022     }
2023
2024     virtual void Accept(const Text& /*text*/)
2025     {}
2026
2027     virtual void Verify()
2028     {
2029         if (m_liveboxId.empty()) {
2030             ThrowMsg(Exception::ParseError,
2031                  "app-widget element must have id attribute");
2032         }
2033         else
2034         {
2035             pcrecpp::RE re(REGEXP_ID_STRING.c_str());
2036             if (!re.FullMatch(DPL::ToUTF8String(m_liveboxId)))
2037             {
2038                 ThrowMsg(Exception::ParseError,
2039                      "invalid format of app-widget id attribute");
2040             }
2041         }
2042
2043         if (m_primary.empty())
2044         {
2045             ThrowMsg(Exception::ParseError,
2046                  "app-widget element must have primary attribute");
2047         } else if (CheckIfNotTrueNorFalse(m_primary))
2048         {
2049             ThrowMsg(Exception::ParseError,
2050                 "auto-launch attribute of app-widget element should be true or false - ignoring");
2051         }
2052
2053         if (!m_autoLaunch.empty() &&
2054                 CheckIfNotTrueNorFalse(m_autoLaunch))
2055         {
2056             ThrowMsg(Exception::ParseError,
2057                 "auto-launch attribute of app-widget element should be true or false - ignoring");
2058         }
2059
2060         if (!m_updatePeriod.empty())
2061         {
2062             char * endptr;
2063             errno = 0;
2064             std::string tempStr = DPL::ToUTF8String(m_updatePeriod);
2065
2066             //set standard locale to fix decimal point mark - '.'
2067             std::string currentLocale = setlocale(LC_NUMERIC, NULL);
2068             if (NULL == setlocale(LC_NUMERIC, "C"))
2069                 LogWarning("Failed to change locale to \"C\"");
2070             double updatePeriod = strtod(tempStr.c_str(), &endptr);
2071
2072             //go back to previous locale
2073             if (NULL == setlocale(LC_NUMERIC, currentLocale.c_str()))
2074                 LogWarning("Failed to set previous locale");
2075
2076             if ((errno == ERANGE && (updatePeriod == -HUGE_VAL || updatePeriod == HUGE_VAL))
2077                     || *endptr != '\0') {
2078                 ThrowMsg(Exception::ParseError,
2079                     "update-period attribute of app-widget element should be a number - ignoring. current value: " << m_updatePeriod);
2080             } else if (updatePeriod < 1800.0) {
2081                 LogDebug("update-period attribute of app-widget element shouldn't be less than 1800.0 - changed to 1800 from value: " << m_updatePeriod);
2082                 m_updatePeriod = L"1800.0";
2083             }
2084         }
2085
2086         if (m_autoLaunch.empty()) {
2087             m_autoLaunch = L"false";
2088         }
2089
2090         if(m_livebox.m_label.empty()) {
2091             ThrowMsg(Exception::ParseError,
2092                 "box-label element of app-widget element not found - ignoring");
2093         }
2094
2095         if(!m_boxContentFound) {
2096             ThrowMsg(Exception::ParseError,
2097                 "box-content element of app-widget element not found - ignoring");
2098         }
2099
2100         m_livebox.m_liveboxId = m_liveboxId;
2101         m_livebox.m_primary = m_primary;
2102         m_livebox.m_autoLaunch = m_autoLaunch;
2103         m_livebox.m_updatePeriod = m_updatePeriod;
2104         m_livebox.m_type = m_type;
2105
2106         m_data.m_livebox.push_back(m_livebox);
2107     }
2108
2109     explicit AppWidgetParser(ConfigParserData& data) :
2110         ElementParser(),
2111         m_data(data),
2112         m_properNamespace(false),
2113         m_boxContentFound(false)
2114     {
2115         m_livebox = ConfigParserData::LiveboxInfo();
2116     }
2117
2118     ElementParserPtr OnBoxLabelElement()
2119     {
2120
2121         return ElementParserPtr(new BoxLabelParser(m_livebox));
2122     }
2123
2124     ElementParserPtr OnBoxIconElement()
2125     {
2126         return ElementParserPtr(new BoxIconParser(m_livebox));
2127     }
2128
2129     ElementParserPtr OnBoxContentElement()
2130     {
2131         m_boxContentFound = true;
2132         return ElementParserPtr(new BoxContentParser(m_livebox));
2133     }
2134
2135   private:
2136     static std::string REGEXP_ID_STRING;
2137     ConfigParserData& m_data;
2138     ConfigParserData::LiveboxInfo m_livebox;
2139     DPL::String m_liveboxId;
2140     DPL::String m_primary;
2141     DPL::String m_autoLaunch;
2142     DPL::String m_updatePeriod;
2143     DPL::String m_type;
2144     bool m_properNamespace;
2145     bool m_boxContentFound;
2146
2147     static bool CheckIfNotTrueNorFalse(const DPL::String &stringToCheck)
2148     {
2149         return stringToCheck.compare(L"true") != 0 && stringToCheck.compare(L"false") != 0;
2150     }
2151 };
2152
2153 std::string AppWidgetParser::REGEXP_ID_STRING = std::string(ApplicationParser::REGEXP_ID) + "\\.[0-9A-Za-z]+";
2154
2155 class AllowNavigationParser : public ElementParser
2156 {
2157   public:
2158     AllowNavigationParser(ConfigParserData& data) :
2159       ElementParser(),
2160       m_data(data),
2161       m_properNamespace(false)
2162     {}
2163
2164     virtual ActionFunc GetElementParser(const DPL::String& /*ns*/,
2165                                         const DPL::String& /*name*/)
2166     {
2167         return &IgnoringParser::Create; //ignore unknown according to w3c
2168     }
2169
2170     virtual void Accept(const Element& element)
2171     {
2172         if (element.ns == ConfigurationNamespace::TizenWebAppNamespaceName) {
2173             m_properNamespace = true;
2174         }
2175     }
2176
2177     virtual void Accept(const Text& text)
2178     {
2179         if (m_properNamespace) {
2180             m_origin = text.value;
2181         }
2182     }
2183
2184     virtual void Accept(const XmlAttribute& /*attribute*/)
2185     {
2186     }
2187
2188     virtual void Verify()
2189     {
2190         if (m_origin.IsNull()) {
2191             LogWarning("data is empty");
2192             return;
2193         }
2194
2195         char* data = strdup(DPL::ToUTF8String(*m_origin).c_str());
2196         char* ptr = strtok(data," ");
2197         while (ptr != NULL) {
2198             std::string origin = ptr;
2199             ptr = strtok(NULL," ");
2200             if(origin == "*") {
2201                 ConfigParserData::AllowNavigationInfo info(L"*", L"*");
2202                 m_data.allowNavigationInfoList.push_back(info);
2203                 continue;
2204             }
2205
2206             DPL::ScopedPtr<iri_t> iri(iri_parse(origin.c_str()));
2207             if (!iri->host || strlen(iri->host) == 0) {
2208                 // input origin should has schem and host
2209                 // in case of file scheme path is filled
2210                 // "http://"
2211                 LogWarning("input origin isn't verified");
2212                 continue;
2213             }
2214             DPL::String scheme = L"*";
2215             if (iri->scheme && strlen(iri->scheme) != 0) {
2216                 scheme = DPL::FromUTF8String(iri->scheme);
2217             }
2218             ConfigParserData::AllowNavigationInfo info(
2219                 scheme,
2220                 DPL::FromUTF8String(iri->host));
2221             m_data.allowNavigationInfoList.push_back(info);
2222         }
2223         free(data);
2224     }
2225
2226   private:
2227     DPL::OptionalString m_origin;
2228     ConfigParserData& m_data;
2229     bool m_properNamespace;
2230 };
2231
2232 class CspParser : public ElementParser
2233 {
2234   public:
2235     virtual ActionFunc GetElementParser(const DPL::String& /*ns*/,
2236                                         const DPL::String& /*name*/)
2237     {
2238         return &IgnoringParser::Create; //ignore unknown according to w3c
2239     }
2240
2241     CspParser(ConfigParserData& data) :
2242         ElementParser(),
2243         m_data(data),
2244         m_properNamespace(false)
2245     {}
2246
2247     virtual void Accept(const Element& element)
2248     {
2249         if (element.ns == ConfigurationNamespace::TizenWebAppNamespaceName) {
2250             m_properNamespace = true;
2251         }
2252     }
2253
2254     virtual void Accept(const XmlAttribute& /*attribute*/)
2255     {}
2256
2257     virtual void Accept(const Text& text)
2258     {
2259         if (m_properNamespace) {
2260             m_policy = text.value;
2261         }
2262     }
2263
2264     virtual void Verify()
2265     {
2266         if (!m_policy.IsNull()) {
2267             m_data.cspPolicy = *m_policy;
2268         }
2269     }
2270
2271   private:
2272     ConfigParserData& m_data;
2273     bool m_properNamespace;
2274     DPL::OptionalString m_policy;
2275 };
2276
2277 class CspReportOnlyParser : public ElementParser
2278 {
2279   public:
2280     virtual ActionFunc GetElementParser(const DPL::String& /*ns*/,
2281                                         const DPL::String& /*name*/)
2282     {
2283         return &IgnoringParser::Create; //ignore unknown according to w3c
2284     }
2285
2286     CspReportOnlyParser(ConfigParserData& data) :
2287         ElementParser(),
2288         m_data(data),
2289         m_properNamespace(false)
2290     {}
2291
2292     virtual void Accept(const Element& element)
2293     {
2294         if (element.ns == ConfigurationNamespace::TizenWebAppNamespaceName) {
2295             m_properNamespace = true;
2296         }
2297     }
2298
2299     virtual void Accept(const XmlAttribute& /*attribute*/)
2300     {}
2301
2302     virtual void Accept(const Text& text)
2303     {
2304         if (m_properNamespace) {
2305             m_policy = text.value;
2306         }
2307     }
2308
2309     virtual void Verify()
2310     {
2311         if (!m_policy.IsNull()) {
2312             m_data.cspPolicyReportOnly = *m_policy;
2313         }
2314     }
2315
2316   private:
2317     ConfigParserData& m_data;
2318     bool m_properNamespace;
2319     DPL::OptionalString m_policy;
2320 };
2321
2322 class AccountParser : public ElementParser
2323 {
2324   public:
2325     struct AccountProviderParser : public ElementParser
2326     {
2327       public:
2328
2329           struct IconParser : public ElementParser
2330         {
2331             public:
2332                 virtual ActionFunc GetElementParser(const DPL::String& /*ns*/,
2333                         const DPL::String& /*name*/)
2334                 {
2335                     return &IgnoringParser::Create; //ignore unknown according to w3c
2336                 }
2337
2338                 virtual void Accept(const Text& text)
2339                 {
2340                     if (text.value == L"") {
2341                         return;
2342                     }
2343                     m_value = text.value;
2344                 }
2345
2346                 virtual void Accept(const Element& /*element*/)
2347                 {}
2348
2349                 virtual void Accept(const XmlAttribute& attribute)
2350                 {
2351                     if (attribute.name == L"section") {
2352                         if (attribute.value == L"account") {
2353                             m_type = ConfigParserData::IconSectionType::DefaultIcon;
2354                         } else if (attribute.value == L"account-small") {
2355                             m_type = ConfigParserData::IconSectionType::SmallIcon;
2356                         }
2357                     }
2358                 }
2359
2360                 virtual void Verify()
2361                 {
2362                     if (m_value.IsNull() || *m_value == L"") {
2363                         return;
2364                     }
2365
2366                     std::pair<ConfigParserData::IconSectionType, DPL::String> icon;
2367                     icon.first = m_type;
2368                     icon.second = *m_value;
2369
2370                     m_data.m_iconSet.insert(icon);
2371                 }
2372
2373                 IconParser(ConfigParserData::AccountProvider& data) :
2374                     ElementParser(),
2375                     m_properNamespace(false),
2376                     m_type(ConfigParserData::DefaultIcon),
2377                     m_data(data)
2378             {}
2379
2380             private:
2381                 bool m_properNamespace;
2382                 ConfigParserData::IconSectionType m_type;
2383                 ConfigParserData::AccountProvider& m_data;
2384                 DPL::OptionalString m_value;
2385         };
2386
2387           struct DisplayNameParser : public ElementParser
2388         {
2389             public:
2390                 virtual ActionFunc GetElementParser(const DPL::String& /*ns*/,
2391                         const DPL::String& /*name*/)
2392                 {
2393                     return &IgnoringParser::Create; //ignore unknown according to w3c
2394                 }
2395
2396                 virtual void Accept(const Text& text)
2397                 {
2398                     if (text.value == L"") {
2399                         return;
2400                     }
2401                     m_value = text.value;
2402                 }
2403
2404                 virtual void Accept(const Element& element)
2405                 {
2406                     m_lang = element.lang;
2407                     m_value= L"";
2408                 }
2409
2410                 virtual void Accept(const XmlAttribute& /*attribute*/)
2411                 {}
2412
2413                 virtual void Verify()
2414                 {
2415                     if (m_value.IsNull() || *m_value == L"") {
2416                         return;
2417                     }
2418
2419                     std::pair<DPL::String, DPL::String> name;
2420                     name.first = *m_lang;
2421                     name.second = *m_value;
2422
2423                     m_data.m_displayNameSet.insert(name);
2424                 }
2425
2426                 DisplayNameParser(ConfigParserData::AccountProvider& data) :
2427                     ElementParser(),
2428                     m_properNamespace(false),
2429                     m_data(data)
2430             {}
2431
2432             private:
2433                 bool m_properNamespace;
2434                 DPL::OptionalString m_lang;
2435                 DPL::OptionalString m_value;
2436                 ConfigParserData::AccountProvider& m_data;
2437         };
2438
2439           struct CapabilityParser : public ElementParser
2440         {
2441             public:
2442                 virtual ActionFunc GetElementParser(const DPL::String& /*ns*/,
2443                         const DPL::String& /*name*/)
2444                 {
2445                     return &IgnoringParser::Create; //ignore unknown according to w3c
2446                 }
2447
2448                 virtual void Accept(const Text& text)
2449                 {
2450                     if (text.value == L"") {
2451                         return;
2452                     }
2453                     m_value = text.value;
2454                 }
2455
2456                 virtual void Accept(const Element& /*element*/)
2457                 {}
2458
2459                 virtual void Accept(const XmlAttribute& /*attribute*/)
2460                 {}
2461
2462                 virtual void Verify()
2463                 {
2464                     if (m_value.IsNull() || *m_value == L"") {
2465                         return;
2466                     }
2467                     m_data.m_capabilityList.push_back(*m_value);
2468                 }
2469
2470                 CapabilityParser(ConfigParserData::AccountProvider& data) :
2471                     ElementParser(),
2472                     m_properNamespace(false),
2473                     m_data(data)
2474             {}
2475
2476             private:
2477                 bool m_properNamespace;
2478                 DPL::OptionalString m_value;
2479                 ConfigParserData::AccountProvider& m_data;
2480         };
2481           virtual ActionFunc GetElementParser(const DPL::String& /*ns*/,
2482                   const DPL::String& name)
2483           {
2484               if (name == L"icon") {
2485                   return DPL::MakeDelegate(this, &AccountProviderParser::OnIconElement);
2486               } else if (name == L"display-name") {
2487                   return DPL::MakeDelegate(this,
2488                           &AccountProviderParser::OnDisplayNameElement);
2489               } else if (name == L"capability") {
2490                   return DPL::MakeDelegate(this, &AccountProviderParser::OnCapabilityElement);
2491               } else {
2492                   return &IgnoringParser::Create; //ignore unknown according to w3c
2493               }
2494           }
2495
2496           virtual void Accept(const Text& /*text*/)
2497           {}
2498
2499           virtual void Accept(const Element& /*element*/)
2500           {}
2501
2502           virtual void Accept(const XmlAttribute& attribute)
2503           {
2504               if (attribute.name == L"multiple-accounts-support") {
2505                   if (attribute.value == L"true") {
2506                       m_multiSupport = true;
2507                   }
2508               }
2509           }
2510
2511           virtual void Verify()
2512           {
2513               m_data.m_multiAccountSupport = m_multiSupport;
2514           }
2515
2516           ElementParserPtr OnIconElement()
2517           {
2518               return ElementParserPtr(new IconParser(m_data));
2519           }
2520
2521           ElementParserPtr OnDisplayNameElement()
2522           {
2523               return ElementParserPtr(new DisplayNameParser(m_data));
2524           }
2525
2526           ElementParserPtr OnCapabilityElement()
2527           {
2528               return ElementParserPtr(new CapabilityParser(m_data));
2529           }
2530
2531           AccountProviderParser(ConfigParserData::AccountProvider& data) :
2532               ElementParser(),
2533               m_properNamespace(false),
2534               m_multiSupport(false),
2535               m_data(data)
2536         {}
2537
2538       private:
2539           bool m_properNamespace;
2540           bool m_multiSupport;
2541           ConfigParserData::AccountProvider& m_data;
2542     };
2543
2544     virtual ActionFunc GetElementParser(const DPL::String& /*ns*/,
2545             const DPL::String& name)
2546     {
2547         if (name == L"account-provider") {
2548             return DPL::MakeDelegate(this, &AccountParser::OnProviderElement);
2549         } else {
2550             return &IgnoringParser::Create; //ignore unknown according to w3c
2551         }
2552     }
2553
2554     virtual void Accept(const Element& element)
2555     {
2556         if (element.ns == ConfigurationNamespace::TizenWebAppNamespaceName) {
2557             m_properNamespace = true;
2558         }
2559     }
2560
2561     virtual void Accept(const XmlAttribute& /*attribute*/)
2562     {}
2563
2564     virtual void Accept(const Text& /*text*/)
2565     {}
2566
2567     virtual void Verify()
2568     {}
2569
2570     ElementParserPtr OnProviderElement()
2571     {
2572         return ElementParserPtr(new AccountProviderParser(m_account));
2573     }
2574
2575     AccountParser(ConfigParserData& data) :
2576         ElementParser(),
2577         m_data(data),
2578         m_account(data.accountProvider),
2579         m_properNamespace(false),
2580         m_multiSupport(false)
2581     {}
2582
2583   private:
2584     ConfigParserData& m_data;
2585     ConfigParserData::AccountProvider& m_account;
2586     bool m_properNamespace;
2587     bool m_multiSupport;
2588 };
2589
2590 class MetadataParser : public ElementParser
2591 {
2592   public:
2593     virtual ActionFunc GetElementParser(const DPL::String& /*ns*/,
2594                                         const DPL::String& /*name*/)
2595     {
2596         return &IgnoringParser::Create; //ignore unknown according to w3c
2597     }
2598
2599     virtual void Accept(const XmlAttribute& attribute)
2600     {
2601         if (m_properNamespace) {
2602             if (attribute.name == L"key") {
2603                 m_key = attribute.value;
2604             } else if (attribute.name == L"value") {
2605                 m_value = attribute.value;
2606             }
2607         }
2608     }
2609
2610     virtual void Accept(const Element& element)
2611     {
2612         if (element.ns == ConfigurationNamespace::TizenWebAppNamespaceName) {
2613             m_properNamespace = true;
2614         }
2615     }
2616
2617     virtual void Accept(const Text& /*text*/)
2618     {
2619         ThrowMsg(Exception::ParseError, "param element must be empty");
2620     }
2621
2622     virtual void Verify()
2623     {
2624         if (m_key.IsNull()) {
2625             LogWarning("metadata element must have key attribute");
2626             return;
2627         }
2628         NormalizeString(m_key);
2629         NormalizeString(m_value);
2630         ConfigParserData::Metadata metaData(*m_key, *m_value);
2631         FOREACH(it, m_data.metadataList) {
2632             if (!DPL::StringCompare(it->key, *m_key)) {
2633                 LogError("Key isn't unique");
2634                 return;
2635             }
2636         }
2637         m_data.metadataList.push_back(metaData);
2638     }
2639
2640     MetadataParser(ConfigParserData& data) :
2641         ElementParser(),
2642         m_data(data),
2643         m_properNamespace(false)
2644     {}
2645
2646   private:
2647     DPL::OptionalString m_key;
2648     DPL::OptionalString m_value;
2649     ConfigParserData& m_data;
2650     bool m_properNamespace;
2651 };
2652
2653 ElementParser::ActionFunc WidgetParser::GetElementParser(
2654     const DPL::String& /*ns*/,
2655     const DPL::String& name)
2656 {
2657     FuncMap::const_iterator it = m_map.find(name);
2658     if (it != m_map.end()) {
2659         return it->second;
2660     } else {
2661         return &IgnoringParser::Create; //ignore unknown according to w3c
2662     }
2663 }
2664
2665 WidgetParser::WidgetParser(ConfigParserData& data) :
2666     m_data(data),
2667     m_textDirection(Unicode::EMPTY)
2668 {
2669     m_map[L"name"] = DPL::MakeDelegate(this, &WidgetParser::OnNameElement);
2670     m_map[L"access"] = DPL::MakeDelegate(this, &WidgetParser::OnAccessElement);
2671     m_map[L"description"] =
2672         DPL::MakeDelegate(this, &WidgetParser::OnDescriptionElement);
2673     m_map[L"author"] = DPL::MakeDelegate(this, &WidgetParser::OnAuthorElement);
2674     m_map[L"license"] =
2675         DPL::MakeDelegate(this, &WidgetParser::OnLicenseElement);
2676     m_map[L"icon"] = DPL::MakeDelegate(this, &WidgetParser::OnIconElement);
2677     m_map[L"content"] =
2678         DPL::MakeDelegate(this, &WidgetParser::OnContentElement);
2679     m_map[L"preference"] =
2680         DPL::MakeDelegate(this, &WidgetParser::OnPreferenceElement);
2681     m_map[L"link"] = DPL::MakeDelegate(this, &WidgetParser::OnLinkElement);
2682     m_map[L"setting"] =
2683         DPL::MakeDelegate(this, &WidgetParser::OnSettingElement);
2684     m_map[L"application"] = DPL::MakeDelegate(
2685             this,
2686             &WidgetParser::
2687                 OnApplicationElement);
2688     m_map[L"splash"] = DPL::MakeDelegate(this, &WidgetParser::OnSplashElement);
2689     m_map[L"background"] = DPL::MakeDelegate(this,
2690                                              &WidgetParser::OnBackgroundElement);
2691     m_map[L"privilege"] = DPL::MakeDelegate(this,
2692                                             &WidgetParser::OnPrivilegeElement);
2693     m_map[L"app-control"] = DPL::MakeDelegate(
2694             this,
2695             &WidgetParser::
2696                 OnAppControlElement);
2697     m_map[L"category"] = DPL::MakeDelegate(this,
2698                                            &WidgetParser::OnCategoryElement);
2699     m_map[L"app-widget"] = DPL::MakeDelegate(this, &WidgetParser::OnAppWidgetElement);
2700 #ifdef CSP_ENABLED
2701     m_map[L"content-security-policy"] = DPL::MakeDelegate(
2702             this,
2703             &WidgetParser::
2704                 OnCspElement);
2705     m_map[L"content-security-policy-report-only"] = DPL::MakeDelegate(
2706             this,
2707             &WidgetParser::
2708                 OnCspReportOnlyElement);
2709 #endif
2710 #ifdef ALLOW_NAVIGATION_ENABLED
2711     m_map[L"allow-navigation"] =
2712         DPL::MakeDelegate(this, &WidgetParser::OnAllowNavigationElement);
2713 #endif
2714     m_map[L"account"] = DPL::MakeDelegate(this, &WidgetParser::OnAccountElement);
2715     m_map[L"metadata"] = DPL::MakeDelegate(this, &WidgetParser::OnMetadataElement);
2716 }
2717
2718 ElementParserPtr WidgetParser::OnNameElement()
2719 {
2720     return ElementParserPtr(new NameParser(m_textDirection, m_data));
2721 }
2722
2723 ElementParserPtr WidgetParser::OnAccessElement()
2724 {
2725     return ElementParserPtr(new AccessParser(m_data));
2726 }
2727
2728 ElementParserPtr WidgetParser::OnDescriptionElement()
2729 {
2730     return ElementParserPtr(new DescriptionParser(m_textDirection, m_data));
2731 }
2732
2733 ElementParserPtr WidgetParser::OnAuthorElement()
2734 {
2735     return ElementParserPtr(new AuthorParser(m_textDirection, m_data));
2736 }
2737
2738 ElementParserPtr WidgetParser::OnLicenseElement()
2739 {
2740     return ElementParserPtr(new LicenseParser(m_textDirection, m_data));
2741 }
2742
2743 ElementParserPtr WidgetParser::OnIconElement()
2744 {
2745     return ElementParserPtr(new IconParser(m_data));
2746 }
2747
2748 ElementParserPtr WidgetParser::OnContentElement()
2749 {
2750     return ElementParserPtr(new ContentParser(m_data));
2751 }
2752
2753 ElementParserPtr WidgetParser::OnPreferenceElement()
2754 {
2755     return ElementParserPtr(new PreferenceParser(m_data));
2756 }
2757
2758 ElementParserPtr WidgetParser::OnLinkElement()
2759 {
2760     return ElementParserPtr(new LinkParser(m_data));
2761 }
2762
2763 ElementParserPtr WidgetParser::OnSettingElement()
2764 {
2765     return ElementParserPtr(new SettingParser(m_data));
2766 }
2767
2768 ElementParserPtr WidgetParser::OnApplicationElement()
2769 {
2770     return ElementParserPtr(new ApplicationParser(m_data));
2771 }
2772
2773 ElementParserPtr WidgetParser::OnSplashElement()
2774 {
2775     return ElementParserPtr(new SplashParser(m_data));
2776 }
2777
2778 ElementParserPtr WidgetParser::OnBackgroundElement()
2779 {
2780     return ElementParserPtr(new BackgroundParser(m_data));
2781 }
2782
2783 ElementParserPtr WidgetParser::OnPrivilegeElement()
2784 {
2785     return ElementParserPtr(new PrivilegeParser(m_data));
2786 }
2787
2788 ElementParserPtr WidgetParser::OnAppControlElement()
2789 {
2790     return ElementParserPtr(new AppControlParser(m_data));
2791 }
2792
2793 ElementParserPtr WidgetParser::OnCategoryElement()
2794 {
2795     return ElementParserPtr(new CategoryParser(m_data));
2796 }
2797
2798 ElementParserPtr WidgetParser::OnAppWidgetElement()
2799 {
2800     return ElementParserPtr(new AppWidgetParser(m_data));
2801 }
2802
2803 ElementParserPtr WidgetParser::OnCspElement()
2804 {
2805     return ElementParserPtr(new CspParser(m_data));
2806 }
2807
2808 ElementParserPtr WidgetParser::OnCspReportOnlyElement()
2809 {
2810     return ElementParserPtr(new CspReportOnlyParser(m_data));
2811 }
2812
2813 ElementParserPtr WidgetParser::OnAllowNavigationElement()
2814 {
2815     return ElementParserPtr(new AllowNavigationParser(m_data));
2816 }
2817
2818 ElementParserPtr WidgetParser::OnAccountElement()
2819 {
2820     return ElementParserPtr(new AccountParser(m_data));
2821 }
2822
2823 ElementParserPtr WidgetParser::OnMetadataElement()
2824 {
2825     return ElementParserPtr(new MetadataParser(m_data));
2826 }
2827
2828 void WidgetParser::Accept(const Element& element)
2829 {
2830     if (element.ns != ConfigurationNamespace::W3CWidgetNamespaceName &&
2831         element.ns != ConfigurationNamespace::TizenWebAppNamespaceName)
2832     {
2833         ThrowMsg(Exception::ParseError,
2834                  "Wrong xml namespace for widget element");
2835     }
2836 }
2837
2838 void WidgetParser::Accept(const Text& /*text*/)
2839 {
2840     ThrowMsg(Exception::ParseError, "widged element must be empty");
2841 }
2842
2843 void WidgetParser::Accept(const XmlAttribute& attribute)
2844 {
2845     if (attribute.name == L"id") {
2846         LibIri::Wrapper iri(DPL::ToUTF8String(attribute.value).c_str());
2847         //If may important tests starts to fail this test we will have
2848         //to consider commenting this test out again.
2849         if (iri.Validate()) {
2850             m_data.widget_id = attribute.value;
2851             NormalizeString(m_data.widget_id);
2852         } else {
2853             LogWarning("Widget id validation failed: " << attribute.value);
2854         }
2855     } else if (attribute.name == L"version") {
2856         m_version = attribute.value;
2857         NormalizeString(m_version);
2858     } else if (attribute.name == L"min-version") {
2859         LogInfo("min-version attribute was found. Value: " << attribute.value);
2860         m_minVersion = attribute.value;
2861         NormalizeString(m_minVersion);
2862         m_data.minVersionRequired = m_minVersion;
2863     } else if (attribute.name == L"height") {
2864         DPL::OptionalString value = attribute.value;
2865         NormalizeString(value);
2866         std::string v = DPL::ToUTF8String(*value);
2867
2868         if (!v.empty()) {
2869             unsigned char c = v.c_str()[0];
2870             if (isdigit(c)) {
2871                 int val = 0;
2872                 for (size_t i = 0; i < v.size(); ++i) {
2873                     c = v.c_str()[i];
2874                     if (isdigit(c)) {
2875                         val *= 10;
2876                         val += (c - '0');
2877                     } else {
2878                         break;
2879                     }
2880                 }
2881                 m_data.height = val;
2882             }
2883         }
2884     } else if (attribute.name == L"width") {
2885         DPL::OptionalString value = attribute.value;
2886         NormalizeString(value);
2887         std::string v = DPL::ToUTF8String(*value);
2888
2889         if (!v.empty()) {
2890             unsigned char c = v.c_str()[0];
2891             if (c >= '0' && c <= '9') {
2892                 int val = 0;
2893                 for (size_t i = 0; i < v.size(); ++i) {
2894                     c = v.c_str()[i];
2895                     if (c >= '0' && c <= '9') {
2896                         val *= 10;
2897                         val += (c - '0');
2898                     } else {
2899                         break;
2900                     }
2901                 }
2902                 m_data.width = val;
2903             }
2904         }
2905     } else if (attribute.name == L"viewmodes") {
2906         DPL::Tokenize(attribute.value,
2907                       L" ",
2908                       std::inserter(m_windowModes,
2909                                     m_windowModes.end()),
2910                       true);
2911     } else if (attribute.name == L"dir") {
2912         m_textDirection = Unicode::ParseDirAttribute(attribute);
2913     } else if (L"defaultlocale" == attribute.name) {
2914         if (!m_defaultlocale) {
2915             m_defaultlocale = attribute.value;
2916             NormalizeString(m_defaultlocale);
2917             if (!LanguageSubtagRstTreeSingleton::Instance().ValidateLanguageTag(
2918                     DPL::ToUTF8String(*m_defaultlocale)))
2919             {
2920                 LogWarning("Language tag: " <<
2921                            m_defaultlocale << " is not valid");
2922                 m_defaultlocale = DPL::OptionalString::Null;
2923             } else {
2924                 LogDebug("Default Locale Found " << m_defaultlocale);
2925             }
2926         } else {
2927             LogWarning("Ignoring subsequent default locale");
2928         }
2929
2930         //Any other value consider as a namespace definition
2931     } else if (attribute.name == L"xmlns" || attribute.prefix == L"xmlns") {
2932         LogInfo("Namespace domain: " << attribute.name);
2933         LogInfo("Namespace value: " << attribute.value);
2934         m_nameSpaces[attribute.name] = attribute.value;
2935     } else {
2936         LogError("Unknown attirbute: namespace=" << attribute.ns <<
2937                  ", name=" << attribute.name <<
2938                  ", value=" << attribute.value);
2939     }
2940 }
2941
2942 void WidgetParser::Verify()
2943 {
2944     FOREACH(mode, m_windowModes) {
2945         if (L"windowed" == *mode || L"floating" == *mode ||
2946             L"fullscreen" == *mode || L"maximized" == *mode ||
2947             L"minimized" == *mode)
2948         {
2949             m_data.windowModes.insert(*mode);
2950         }
2951     }
2952     if (!m_version.IsNull()) {
2953         Unicode::UpdateTextWithDirectionMark(m_textDirection, &*m_version);
2954         m_data.version = m_version;
2955     }
2956     m_data.defaultlocale = m_defaultlocale;
2957     FOREACH(ns, m_nameSpaces) {
2958         m_data.nameSpaces.insert(ns->second);
2959     }
2960 }
2961