5f0d6ca2e064780eee433b7e56ac3d0ecdbbac1c
[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 <algorithm>
41 #include <cstdio>
42 #include <cerrno>
43
44 using namespace WrtDB;
45
46 namespace Unicode {
47 static const DPL::String UTF_LRE = L"\x0202a";
48 static const DPL::String UTF_LRO = L"\x0202d";
49 static const DPL::String UTF_RLE = L"\x0202b";
50 static const DPL::String UTF_RLO = L"\x0202e";
51 static const DPL::String UTF_PDF = L"\x0202c";
52
53 Direction ParseDirAttribute(const XmlAttribute& attribute)
54 {
55     Assert(L"dir" == attribute.name);
56     if (L"ltr" == attribute.value) {
57         return LRE;
58     } else if (L"rtl" == attribute.value) {
59         return RLE;
60     } else if (L"lro" == attribute.value) {
61         return LRO;
62     } else if (L"rlo" == attribute.value) {
63         return RLO;
64     } else {
65         LogWarning("dir attribute has wrong value:" << attribute.value);
66         return EMPTY;
67     }
68 }
69
70 void UpdateTextWithDirectionMark(Direction direction,
71                                  DPL::String* text)
72 {
73     Assert(text);
74     switch (direction) {
75     case RLO:
76         *text = UTF_RLO + *text + UTF_PDF;
77         break;
78     case RLE:
79         *text = UTF_RLE + *text + UTF_PDF;
80         break;
81     case LRE:
82         *text = UTF_LRE + *text + UTF_PDF;
83         break;
84     case LRO:
85         *text = UTF_LRO + *text + UTF_PDF;
86         break;
87     case EMPTY:
88         break;
89     default:
90         Assert(false);
91     }
92 }
93 } // namespace Unicode
94
95 class InnerElementsParser : public ElementParser
96 {
97   public:
98     virtual ActionFunc GetElementParser(const DPL::String& /*ns*/,
99                                         const DPL::String& /*name*/)
100     {
101         return DPL::MakeDelegate(this, &InnerElementsParser::Other);
102     }
103
104     virtual void Accept(const Element& /*element*/)
105     {}
106
107     virtual void Accept(const Text& text)
108     {
109         if (m_text.IsNull()) {
110             m_text = text;
111         } else {
112             m_text->value += text.value;
113         }
114     }
115
116     virtual void Accept(const XmlAttribute& attribute)
117     {
118         if (attribute.name == L"dir") {
119             m_textDirection = Unicode::ParseDirAttribute(attribute);
120         }
121     }
122
123     virtual void Verify()
124     {
125         if (!m_text.IsNull()) {
126             Unicode::UpdateTextWithDirectionMark(m_textDirection,
127                                                  &m_text->value);
128             m_parentParser->Accept(*m_text);
129         }
130     }
131
132     InnerElementsParser(ElementParserPtr parent) :
133         m_parentParser(parent),
134         m_textDirection(Unicode::EMPTY)
135     {}
136
137     ElementParserPtr Other()
138     {
139         return ElementParserPtr(new InnerElementsParser(
140                                     std::static_pointer_cast<ElementParser>(
141                                         shared_from_this())));
142     }
143
144   private:
145     DPL::Optional<Text> m_text;
146     ElementParserPtr m_parentParser;
147     Unicode::Direction m_textDirection;
148 };
149
150 class NameParser : public ElementParser
151 {
152   public:
153     virtual ActionFunc GetElementParser(const DPL::String& /*ns*/,
154                                         const DPL::String& /*name*/)
155     {
156         return DPL::MakeDelegate(this, &NameParser::Other);
157     }
158
159     virtual void Accept(const Element& element)
160     {
161         m_lang = element.lang;
162         m_name = L"";
163     }
164
165     virtual void Accept(const Text& text)
166     {
167         if (m_name.IsNull()) {
168             m_name = text.value;
169         } else {
170             *m_name += text.value;
171         }
172     }
173
174     virtual void Accept(const XmlAttribute& attribute)
175     {
176         if (attribute.name == L"short") {
177             if (m_shortName.IsNull()) {
178                 m_shortName = attribute.value;
179             }
180         } else if (attribute.name == L"dir") {
181             m_textDirection = Unicode::ParseDirAttribute(attribute);
182         }
183     }
184
185     virtual void Verify()
186     {
187         ConfigParserData::LocalizedData& data = m_data.localizedDataSet[m_lang];
188         if (data.name.IsNull()) {
189             NormalizeString(m_name);
190             NormalizeString(m_shortName);
191             if (!m_name.IsNull()) {
192                 Unicode::UpdateTextWithDirectionMark(m_textDirection, &*m_name);
193             }
194             data.name = m_name;
195             if (!m_shortName.IsNull()) {
196                 Unicode::UpdateTextWithDirectionMark(m_textDirection,
197                                                      &*m_shortName);
198             }
199             data.shortName = m_shortName;
200         }
201     }
202
203     NameParser(Unicode::Direction direction,
204                ConfigParserData& data) :
205         m_data(data),
206         m_textDirection(direction)
207     {}
208
209     ElementParserPtr Other()
210     {
211         return ElementParserPtr(new InnerElementsParser(
212                                     std::static_pointer_cast<ElementParser>(
213                                         shared_from_this())));
214     }
215
216   private:
217     ConfigParserData& m_data;
218     DPL::OptionalString m_name;
219     DPL::OptionalString m_shortName;
220     DPL::OptionalString m_dir;
221     DPL::String m_lang;
222     Unicode::Direction m_textDirection;
223 };
224
225 class AccessParser : public ElementParser
226 {
227   public:
228     enum StandardType
229     {
230         STANDARD_TYPE_NONE,
231         STANDARD_TYPE_WARP
232     };
233
234     virtual ActionFunc GetElementParser(const DPL::String& /*ns*/,
235                                         const DPL::String& /*name*/)
236     {
237         return DPL::MakeDelegate(this, &AccessParser::Other);
238     }
239
240     virtual void Accept(const Element& element)
241     {
242         // for tizen web apps WARP should be used
243         if (element.ns == ConfigurationNamespace::W3CWidgetNamespaceName ||
244             element.ns == ConfigurationNamespace::TizenWebAppNamespaceName)
245         {
246             m_standardType = STANDARD_TYPE_WARP;
247         }
248     }
249
250     virtual void Accept(const Text& /*text*/)
251     {}
252
253     void AcceptWac(const XmlAttribute& attribute)
254     {
255         if (attribute.name == L"origin") {
256             m_strIRIOrigin = attribute.value;
257             NormalizeString(m_strIRIOrigin);
258         } else if (attribute.name == L"subdomains") {
259             DPL::String normalizedValue = attribute.value;
260             NormalizeString(normalizedValue);
261
262             if (normalizedValue == L"true") {
263                 m_bSubDomainAccess = true;
264             } else if (normalizedValue == L"false") {
265                 m_bSubDomainAccess = false;
266             }
267         }
268     }
269
270     virtual void Accept(const XmlAttribute& attribute)
271     {
272         switch (m_standardType) {
273         case STANDARD_TYPE_WARP:
274             AcceptWac(attribute);
275             break;
276         default:
277             LogError("Error in Access tag - unknown standard.");
278         }
279     }
280
281     void VerifyWac()
282     {
283         WarpIRI iri;
284         iri.set(m_strIRIOrigin, false);
285
286         if (!iri.isAccessDefinition()) {
287             LogWarning("Access list element: " <<
288                        m_strIRIOrigin <<
289                        " is not acceptable by WARP" <<
290                        "standard and will be ignored!");
291             return;
292         }
293
294         ConfigParserData::AccessInfo accessInfo(m_strIRIOrigin,
295                                                 m_bSubDomainAccess);
296         std::pair <ConfigParserData::AccessInfoSet::iterator, bool> ret =
297             m_data.accessInfoSet.insert(accessInfo);
298     }
299
300     virtual void Verify()
301     {
302         switch (m_standardType) {
303         case STANDARD_TYPE_WARP:
304             VerifyWac();
305             break;
306         default:
307             LogError("Error in Access tag - unknown standard.");
308         }
309     }
310
311     AccessParser(ConfigParserData& data) :
312         ElementParser(),
313         m_bSubDomainAccess(false),
314         m_standardType(STANDARD_TYPE_NONE),
315         m_network(false),
316         m_data(data)
317     {}
318
319     ElementParserPtr Other()
320     {
321         return ElementParserPtr(new InnerElementsParser(
322                                     ElementParserPtr(shared_from_this())));
323     }
324
325   private:
326     DPL::String m_strIRIOrigin;
327     bool m_bSubDomainAccess;
328     StandardType m_standardType;
329     bool m_network;
330     ConfigParserData& m_data;
331 };
332
333 class DescriptionParser : public ElementParser
334 {
335   public:
336     virtual ActionFunc GetElementParser(const DPL::String& /*ns*/,
337                                         const DPL::String& /*name*/)
338     {
339         return DPL::MakeDelegate(this, &DescriptionParser::Other);
340     }
341
342     virtual void Accept(const Element& element)
343     {
344         m_lang = element.lang;
345         m_description = L"";
346     }
347
348     ElementParserPtr Other()
349     {
350         return ElementParserPtr(new InnerElementsParser(
351                                     std::static_pointer_cast<ElementParser>(
352                                         shared_from_this())));
353     }
354
355     virtual void Accept(const Text& text)
356     {
357         if (m_description.IsNull()) {
358             m_description = text.value;
359         } else {
360             *m_description += text.value;
361         }
362     }
363
364     virtual void Accept(const XmlAttribute& attribute)
365     {
366         if (attribute.name == L"dir") {
367             m_textDirection = Unicode::ParseDirAttribute(attribute);
368         }
369     }
370
371     virtual void Verify()
372     {
373         ConfigParserData::LocalizedData& data = m_data.localizedDataSet[m_lang];
374         if (data.description.IsNull()) {
375             if (!m_description.IsNull()) {
376                 Unicode::UpdateTextWithDirectionMark(m_textDirection,
377                                                      &*m_description);
378             }
379             data.description = m_description;
380         }
381     }
382
383     DescriptionParser(Unicode::Direction direction,
384                       ConfigParserData& data) :
385         m_data(data),
386         m_lang(),
387         m_description(),
388         m_textDirection(direction)
389     {}
390
391   private:
392     ConfigParserData& m_data;
393     DPL::String m_lang;
394     DPL::OptionalString m_description;
395     Unicode::Direction m_textDirection;
396 };
397
398 class AuthorParser : public ElementParser
399 {
400   public:
401     virtual ActionFunc GetElementParser(const DPL::String& /*ns*/,
402                                         const DPL::String& /*name*/)
403     {
404         return DPL::MakeDelegate(this, &AuthorParser::Other);
405     }
406
407     AuthorParser(Unicode::Direction direction,
408                  ConfigParserData& data) :
409         m_data(data),
410         m_textDirection(direction)
411     {}
412
413     virtual void Accept(const Element& /*element*/)
414     {
415         m_authorName = L"";
416     }
417
418     virtual void Accept(const Text& text)
419     {
420         *(m_authorName) += text.value;
421     }
422
423     virtual void Accept(const XmlAttribute& attribute)
424     {
425         if (attribute.name == L"href") {
426             //Validate href IRI and ignore it if invalid
427             //See also test: ta-argMozRiC-an
428             LibIri::Wrapper iri(DPL::ToUTF8String(attribute.value).c_str());
429             if (iri.Validate()) {
430                 m_authorHref = attribute.value;
431             }
432         } else if (attribute.name == L"email") {
433             m_authorEmail = attribute.value;
434         } else if (attribute.name == L"dir") {
435             m_textDirection = Unicode::ParseDirAttribute(attribute);
436         }
437     }
438
439     virtual void Verify()
440     {
441         if (!m_data.authorName && !m_data.authorHref && !m_data.authorEmail) {
442             NormalizeString(m_authorName);
443             NormalizeString(m_authorHref);
444             NormalizeString(m_authorEmail);
445             if (!!m_authorName) {
446                 Unicode::UpdateTextWithDirectionMark(m_textDirection,
447                                                      &*m_authorName);
448                 m_data.authorName = m_authorName;
449             }
450             if (!!m_authorHref) {
451                 m_data.authorHref = m_authorHref;
452             }
453             if (!!m_authorEmail) {
454                 m_data.authorEmail = m_authorEmail;
455             }
456         }
457     }
458
459     ElementParserPtr Other()
460     {
461         return ElementParserPtr(new InnerElementsParser(
462                                     std::static_pointer_cast<ElementParser>(
463                                         shared_from_this())));
464     }
465
466   private:
467     ConfigParserData& m_data;
468     DPL::OptionalString m_authorEmail;
469     DPL::OptionalString m_authorHref;
470     DPL::OptionalString m_authorName;
471     Unicode::Direction m_textDirection;
472 };
473
474 class LicenseParser : public ElementParser
475 {
476   public:
477     virtual ActionFunc GetElementParser(const DPL::String& /*ns*/,
478                                         const DPL::String& /*name*/)
479     {
480         return DPL::MakeDelegate(this, &LicenseParser::Other);
481     }
482
483     LicenseParser(Unicode::Direction direction,
484                   ConfigParserData& data) :
485         m_data(data),
486         m_ignore(true),
487         m_textDirection(direction)
488     {}
489
490     virtual void Accept(const Element& element)
491     {
492         if (m_license.IsNull()) {
493             m_lang = element.lang;
494             m_license = L"";
495             m_ignore = false;
496         }
497     }
498
499     virtual void Accept(const Text& text)
500     {
501         if (!m_ignore) {
502             *m_license += text.value;
503         }
504     }
505
506     virtual void Accept(const XmlAttribute& attribute)
507     {
508         if (!m_ignore) {
509             if (attribute.name == L"href" && m_licenseHref.IsNull()) {
510                 m_licenseHref = attribute.value;
511             } else if (attribute.name == L"file" && m_licenseFile.IsNull()) {
512                 m_licenseFile = attribute.value;
513             } else if (attribute.name == L"dir") {
514                 m_textDirection = Unicode::ParseDirAttribute(attribute);
515             }
516         }
517     }
518
519     virtual void Verify()
520     {
521         ConfigParserData::LocalizedData& data = m_data.localizedDataSet[m_lang];
522         if (data.license.IsNull()) {
523             if (!m_license.IsNull()) {
524                 Unicode::UpdateTextWithDirectionMark(m_textDirection,
525                                                      &*m_license);
526             }
527             data.license = m_license;
528             data.licenseHref = m_licenseHref;
529             data.licenseFile = m_licenseFile;
530         }
531     }
532
533     ElementParserPtr Other()
534     {
535         return ElementParserPtr(new InnerElementsParser(
536                                     ElementParserPtr(shared_from_this())));
537     }
538
539   private:
540     ConfigParserData& m_data;
541     DPL::String m_lang;
542     bool m_ignore;
543
544     DPL::OptionalString m_license;
545     DPL::OptionalString m_licenseFile;
546     DPL::OptionalString m_licenseHref;
547     Unicode::Direction m_textDirection;
548 };
549
550 class IconParser : public ElementParser
551 {
552     DECLARE_EXCEPTION_TYPE(ElementParser::Exception::ParseError, BadSrcError)
553
554   public:
555     virtual ActionFunc GetElementParser(const DPL::String& /*ns*/,
556                                         const DPL::String& /*name*/)
557     {
558         return &IgnoringParser::Create;
559     }
560
561     IconParser(ConfigParserData& data) : ElementParser(),
562         m_data(data)
563     {}
564
565     virtual void Accept(const Element& /*element*/)
566     {}
567
568     virtual void Accept(const XmlAttribute& attribute)
569     {
570         if (attribute.name == L"src") {
571             if (attribute.value.size() > 0) {
572                 m_src = attribute.value;
573             }
574         } else if (attribute.name == L"width") {
575             m_width = ParseSizeAttributeValue(attribute.value);
576         } else if (attribute.name == L"height") {
577             m_height = ParseSizeAttributeValue(attribute.value);
578         }
579     }
580
581     virtual void Accept(const Text& /*text*/)
582     {
583         ThrowMsg(Exception::ParseError, "Icon element must be empty");
584     }
585
586     virtual void Verify()
587     {
588         if (m_src.IsNull()) {
589             LogWarning("src attribute of icon element is mandatory - ignoring");
590             return;
591         }
592
593         Try
594         {
595             ConfigParserData::Icon icon(delocalizeSrcPath(*m_src));
596             icon.width = m_width;
597             icon.height = m_height;
598
599             ConfigParserData::IconsList::iterator it = std::find(
600                     m_data.iconsList.begin(), m_data.iconsList.end(), icon);
601             if (it == m_data.iconsList.end()) {
602                 m_data.iconsList.push_front(icon);
603             }
604         }
605         Catch(BadSrcError)
606         {
607             LogWarning("src attribute is invalid: " << m_src);
608         }
609     }
610
611   private:
612     ConfigParserData& m_data;
613     DPL::OptionalString m_src;
614     DPL::OptionalInt m_width;
615     DPL::OptionalInt m_height;
616
617     static DPL::OptionalInt ParseSizeAttributeValue(const DPL::String& value)
618     {
619         DPL::OptionalString normalizedValue = value;
620         NormalizeString(normalizedValue);
621         if (!(*normalizedValue).empty()) {
622             char* reterr = NULL;
623             errno = 0;
624             long int valueInt =
625                 strtol(DPL::ToUTF8String(value).c_str(), &reterr, 10);
626             if (errno != 0 ||
627                 std::string(reterr) == DPL::ToUTF8String(value) ||
628                 valueInt <= 0)
629             {
630                 return DPL::OptionalInt::Null;
631             } else {
632                 return valueInt;
633             }
634         }
635         return DPL::OptionalInt::Null;
636     }
637
638     /**
639      * @brief delocalizePath removes locales folder from relative path if
640      * neccessary
641      * @param source source string
642      *
643      * @throw BadSrcError if string is bad value of src attribute
644      *
645      * @return corrected string
646      */
647     static DPL::String delocalizeSrcPath(const DPL::String & source)
648     {
649         static const DPL::String localeFolder(L"locales/");
650         static const int index = localeFolder.size();
651
652         DPL::String result = source;
653
654         if (source.substr(0, index) == localeFolder) {
655             size_t pos = result.find_first_of('/', index);
656             if (pos != std::string::npos && pos + 1 < source.size()) {
657                 result = result.substr(pos + 1, source.size());
658             } else {
659                 Throw(BadSrcError);
660             }
661         }
662         return result;
663     }
664 };
665
666 class ContentParser : public ElementParser
667 {
668   public:
669     virtual ActionFunc GetElementParser(const DPL::String& /*ns*/,
670                                         const DPL::String& /*name*/)
671     {
672         return &IgnoringParser::Create;
673     }
674
675     ContentParser(ConfigParserData& data) :
676         ElementParser(),
677         m_data(data)
678     {}
679
680     virtual void Accept(const Element& /*element*/)
681     {}
682
683     virtual void Accept(const Text& /*text*/)
684     {}
685
686     virtual void Accept(const XmlAttribute& attribute)
687     {
688         DPL::String value = attribute.value;
689         NormalizeString(value);
690
691         if (attribute.name == L"src") {
692             m_src = value;
693         } else if (attribute.name == L"type") {
694             m_type = value;
695             MimeTypeUtils::MimeAttributes mimeAttributes =
696                 MimeTypeUtils::getMimeAttributes(value);
697             if (mimeAttributes.count(L"charset") > 0) {
698                 m_encoding = mimeAttributes[L"charset"];
699             }
700         } else if (attribute.name == L"encoding") {
701             if (!value.empty()) {
702                 m_encoding = value;
703             }
704         }
705     }
706
707     virtual void Verify()
708     {
709         if (m_data.startFileEncountered) {
710             LogWarning("This is not the first encountered "
711                        "'content' element - ignoring.");
712             return;
713         }
714
715         m_data.startFileEncountered = true;
716
717         //we're consciously setting startFile even if m_src is null or invalid.
718         //WidgetConfigurationManager will deal with this.
719         m_data.startFile = m_src;
720
721         if (!!m_src) {
722             m_data.startFileContentType = m_type;
723             if (!!m_encoding) {
724                 m_data.startFileEncoding = m_encoding;
725             } else {
726                 m_data.startFileEncoding = L"UTF-8";
727             }
728         }
729     }
730
731   private:
732     DPL::OptionalString m_src;
733     DPL::OptionalString m_type;
734     DPL::OptionalString m_encoding;
735     ConfigParserData& m_data;
736 };
737
738 class FeatureParser : public ElementParser
739 {
740   public:
741     struct ParamParser : public ElementParser
742     {
743         virtual ActionFunc GetElementParser(const DPL::String& /*ns*/,
744                                             const DPL::String& /*name*/)
745         {
746             return &IgnoringParser::Create;
747         }
748
749         virtual void Accept(const XmlAttribute& attribute)
750         {
751             if (attribute.name == L"name") {
752                 m_name = attribute.value;
753                 NormalizeString(m_name);
754             } else if (attribute.name == L"value") {
755                 m_value = attribute.value;
756                 NormalizeString(m_value);
757             }
758         }
759
760         virtual void Accept(const Element& /*element*/)
761         {}
762
763         virtual void Accept(const Text& /*text*/)
764         {
765             ThrowMsg(Exception::ParseError, "param element must be empty");
766         }
767
768         virtual void Verify()
769         {
770             if (m_name.IsNull() || *m_name == L"") {
771                 return;
772             }
773             if (m_value.IsNull() || *m_value == L"") {
774                 return;
775             }
776
777             ConfigParserData::Param param(*m_name);
778             param.value = *m_value;
779
780             if (m_data.paramsList.find(param) == m_data.paramsList.end()) {
781                 m_data.paramsList.insert(param);
782             }
783         }
784
785         ParamParser(ConfigParserData::Feature& data) :
786             ElementParser(),
787             m_data(data)
788         {}
789
790       private:
791         DPL::OptionalString m_name;
792         DPL::OptionalString m_value;
793         ConfigParserData::Feature& m_data;
794     };
795
796     virtual ActionFunc GetElementParser(const DPL::String& /*ns*/,
797                                         const DPL::String& name)
798     {
799         if (name == L"param") {
800             return DPL::MakeDelegate(this, &FeatureParser::OnParamElement);
801         } else {
802             return &IgnoringParser::Create;
803         }
804     }
805
806     virtual void Accept(const Text& /*text*/)
807     {}
808
809     virtual void Accept(const Element& /*element*/)
810     {}
811
812     virtual void Accept(const XmlAttribute& attribute)
813     {
814         if (attribute.name == L"name") {
815             m_feature.name = attribute.value;
816         } else if (attribute.name == L"required") {
817             if (attribute.value == L"false") {
818                 m_feature.required = false;
819             } else {
820                 m_feature.required = true;
821             }
822         }
823     }
824
825     virtual void Verify()
826     {
827         LibIri::Wrapper iri(DPL::ToUTF8String(m_feature.name).c_str());
828
829         if (m_feature.name != L"") {
830             if (iri.Validate()) {
831                 if (m_data.featuresList.find(m_feature) ==
832                     m_data.featuresList.end())
833                 {
834                     m_data.featuresList.insert(m_feature);
835                 } else {
836                     LogDebug("Ignoring feature with name" <<
837                              DPL::ToUTF8String(m_feature.name));
838                 }
839             } else {
840                 if (m_feature.required) {
841                     //Throw only if required
842                     ThrowMsg(Exception::ParseError, "invalid feature IRI");
843                 }
844             }
845         }
846     }
847
848     ElementParserPtr OnParamElement()
849     {
850         return ElementParserPtr(new ParamParser(m_feature));
851     }
852
853     FeatureParser(ConfigParserData& data) :
854         ElementParser(),
855         m_data(data),
856         m_feature(L"")
857     {}
858
859   private:
860     ConfigParserData& m_data;
861     ConfigParserData::Feature m_feature;
862 };
863
864 class PreferenceParser : public ElementParser
865 {
866   public:
867     virtual ActionFunc GetElementParser(const DPL::String& /*ns*/,
868                                         const DPL::String& /*name*/)
869     {
870         return &IgnoringParser::Create;
871     }
872
873     virtual void Accept(const XmlAttribute& attribute)
874     {
875         if (attribute.name == L"name") {
876             m_name = attribute.value;
877         } else if (attribute.name == L"value") {
878             m_value = attribute.value;
879         } else if (attribute.name == L"readonly") {
880             if (attribute.value == L"true") {
881                 m_required = true;
882             } else {
883                 m_required = false;
884             }
885         }
886     }
887
888     virtual void Accept(const Element& /*element*/)
889     {}
890
891     virtual void Accept(const Text& /*text*/)
892     {
893         ThrowMsg(Exception::ParseError, "param element must be empty");
894     }
895
896     virtual void Verify()
897     {
898         if (m_name.IsNull()) {
899             LogWarning("preference element must have name attribute");
900             return;
901         }
902         NormalizeString(m_name);
903         NormalizeString(m_value);
904         ConfigParserData::Preference preference(*m_name, m_required);
905         preference.value = m_value;
906         if (m_data.preferencesList.find(preference) ==
907             m_data.preferencesList.end())
908         {
909             m_data.preferencesList.insert(preference);
910         }
911     }
912
913     PreferenceParser(ConfigParserData& data) :
914         ElementParser(),
915         m_required(false),
916         m_data(data)
917     {}
918
919   private:
920     DPL::OptionalString m_name;
921     DPL::OptionalString m_value;
922     bool m_required;
923     ConfigParserData& m_data;
924 };
925
926 class LinkParser : public ElementParser
927 {
928   public:
929     virtual ActionFunc GetElementParser(const DPL::String& /*ns*/,
930                                         const DPL::String& /*name*/)
931     {
932         return &DenyAllParser::Create;
933     }
934
935     virtual void Accept(const XmlAttribute& attribute)
936     {
937         if (m_properNamespace) {
938             LogDebug("attribute");
939             if (attribute.name == L"rel") {
940                 if (attribute.value != L"describedby") {
941                     ThrowMsg(Exception::ParseError,
942                              "rel attribute must have describedby value");
943                 }
944             } else if (attribute.name == L"type") {} else if (attribute.name ==
945                                                               L"href")
946             {
947                 LogDebug("here is href");
948                 m_href = attribute.value;
949             } else {
950                 ThrowMsg(Exception::ParseError,
951                          "unknown attribute '" +
952                          DPL::ToUTF8String(attribute.name) +
953                          "' in link element");
954             }
955         }
956     }
957
958     virtual void Accept(const Element& element)
959     {
960         if (element.ns ==
961             ConfigurationNamespace::WacWidgetNamespaceNameForLinkElement)
962         {
963             m_properNamespace = true;
964         }
965         LogDebug("element");
966     }
967
968     virtual void Accept(const Text&)
969     {
970         if (m_properNamespace) {
971             LogDebug("text");
972             ThrowMsg(Exception::ParseError, "link element must be empty");
973         }
974     }
975
976     virtual void Verify()
977     {
978         if (!m_href) {
979             ThrowMsg(Exception::ParseError,
980                      "link element must have href attribute");
981         }
982
983         LibIri::Wrapper iri(DPL::ToUTF8String(*m_href).c_str());
984         if (!iri.Validate()) { // TODO: Better uri validator ?
985             ThrowMsg(Exception::ParseError,
986                      "href attribute must be a valid iri/uri/url");
987         }
988     }
989
990     LinkParser(ConfigParserData& data) :
991         ElementParser(),
992         m_properNamespace(false),
993         m_data(data),
994         m_href(DPL::OptionalString::Null)
995     {}
996
997   private:
998     bool m_properNamespace;
999     ConfigParserData& m_data;
1000     DPL::OptionalString m_href;
1001 };
1002
1003 class SettingParser : public ElementParser
1004 {
1005   public:
1006     virtual ActionFunc GetElementParser(const DPL::String& /*ns*/,
1007                                         const DPL::String& /*name*/)
1008     {
1009         return &IgnoringParser::Create;
1010     }
1011
1012     virtual void Accept(const Text& /*text*/)
1013     {}
1014
1015     virtual void Accept(const Element& /*element*/)
1016     {}
1017
1018     virtual void Accept(const XmlAttribute& attribute)
1019     {
1020         m_setting.m_name = attribute.name;
1021         m_setting.m_value = attribute.value;
1022         m_data.settingsList.insert(m_setting);
1023     }
1024
1025     virtual void Verify()
1026     {}
1027
1028     SettingParser(ConfigParserData& data) :
1029         ElementParser(),
1030         m_data(data),
1031         m_setting(L"", L"")
1032     {}
1033
1034   private:
1035     ConfigParserData& m_data;
1036     ConfigParserData::Setting m_setting;
1037 };
1038
1039 class AppServiceParser : public ElementParser
1040 {
1041   public:
1042     virtual ActionFunc GetElementParser(const DPL::String& /*ns*/,
1043                                         const DPL::String& /*name*/)
1044     {
1045         return &IgnoringParser::Create;
1046     }
1047
1048     virtual void Accept(const XmlAttribute& attribute)
1049     {
1050         if (attribute.name == L"src") {
1051             m_src = attribute.value;
1052         } else if (attribute.name == L"operation") {
1053             m_operation = attribute.value;
1054         } else if (attribute.name == L"scheme") {
1055             m_scheme = attribute.value;
1056         } else if (attribute.name == L"mime") {
1057             m_mime = attribute.value;
1058         }
1059     }
1060
1061     virtual void Accept(const Element& element)
1062     {
1063         LogWarning("namespace for app service = " << element.ns);
1064         if (element.ns == ConfigurationNamespace::W3CWidgetNamespaceName) {
1065             ThrowMsg(Exception::ParseError,
1066                      "Wrong xml namespace for widget element");
1067         }
1068     }
1069
1070     virtual void Accept(const Text& /*text*/)
1071     {
1072         ThrowMsg(Exception::ParseError, "param element must be empty");
1073     }
1074
1075     virtual void Verify()
1076     {
1077         if (m_src.IsNull()) {
1078             LogWarning("service element must have target attribute");
1079             return;
1080         } else if (m_operation.IsNull()) {
1081             LogWarning("service element must have operation attribute");
1082             return;
1083         }
1084         NormalizeString(m_src);
1085         NormalizeString(m_operation);
1086         NormalizeString(m_scheme);
1087         NormalizeString(m_mime);
1088
1089         // verify duplicate element
1090         DPL::String wildString(L"*/*");
1091         DPL::String nullString(L"");
1092         ConfigParserData::ServiceInfo serviceInfo(
1093             m_src.IsNull() ? nullString : *m_src,
1094             m_operation.IsNull() ? nullString : *m_operation,
1095             m_scheme.IsNull() ? nullString : *m_scheme,
1096             m_mime.IsNull() ? nullString : *m_mime);
1097
1098         FOREACH(iterator, m_data.appServiceList) {
1099             if (iterator->m_operation == serviceInfo.m_operation &&
1100                 // check scheme
1101                 (iterator->m_scheme == serviceInfo.m_scheme ||
1102                  // check input scheme is "*/*" case
1103                  (iterator->m_scheme == wildString &&
1104                   serviceInfo.m_scheme != nullString) ||
1105                  // check iterator scheme is "*/*" case
1106                  (serviceInfo.m_scheme == wildString &&
1107                   iterator->m_scheme != nullString)) &&
1108
1109                 (iterator->m_mime == serviceInfo.m_mime ||
1110                  // check input mime is "*/*" case
1111                  (iterator->m_mime == wildString &&
1112                   serviceInfo.m_mime != nullString) ||
1113                  // check iterator mime is "*/*" case
1114                  (serviceInfo.m_mime == wildString &&
1115                   iterator->m_mime != nullString)))
1116             {
1117                 ThrowMsg(Exception::ParseError,
1118                          "service operation is duplicated " +
1119                          DPL::ToUTF8String(*m_operation));
1120             }
1121         }
1122         m_data.appServiceList.push_back(serviceInfo);
1123     }
1124
1125     AppServiceParser(ConfigParserData& data) :
1126         ElementParser(),
1127         m_src(DPL::OptionalString::Null),
1128         m_operation(DPL::OptionalString::Null),
1129         m_scheme(DPL::OptionalString::Null),
1130         m_mime(DPL::OptionalString::Null),
1131         m_data(data)
1132     {}
1133
1134   private:
1135     DPL::OptionalString m_src;
1136     DPL::OptionalString m_operation;
1137     DPL::OptionalString m_scheme;
1138     DPL::OptionalString m_mime;
1139     ConfigParserData& m_data;
1140 };
1141
1142 class AppControlParser : public ElementParser
1143 {
1144   public:
1145     struct SourceParser : public ElementParser
1146     {
1147       public:
1148         virtual ActionFunc GetElementParser(const DPL::String& /*ns*/,
1149                                             const DPL::String& /*name*/)
1150         {
1151             return &IgnoringParser::Create;
1152         }
1153
1154         virtual void Accept(const Text& /*text*/)
1155         {}
1156
1157         virtual void Accept(const Element& /*element*/)
1158         {}
1159
1160         virtual void Accept(const XmlAttribute& attribute)
1161         {
1162             if (attribute.name == L"name") {
1163                 if (attribute.value.size() > 0) {
1164                     m_value = attribute.value;
1165                     NormalizeString(m_value);
1166                 }
1167             }
1168         }
1169
1170         virtual void Verify()
1171         {
1172             if (m_value.IsNull() || *m_value == L"") {
1173                 return;
1174             }
1175
1176             m_data.m_src = *m_value;
1177         }
1178
1179         SourceParser(ConfigParserData::AppControlInfo& data) :
1180             ElementParser(),
1181             m_properNamespace(false),
1182             m_data(data)
1183         {}
1184
1185       private:
1186         bool m_properNamespace;
1187         DPL::OptionalString m_value;
1188         ConfigParserData::AppControlInfo& m_data;
1189     };
1190
1191     struct OperationParser : public ElementParser
1192     {
1193       public:
1194         virtual ActionFunc GetElementParser(const DPL::String& /*ns*/,
1195                                             const DPL::String& /*name*/)
1196         {
1197             return &IgnoringParser::Create;
1198         }
1199
1200         virtual void Accept(const Text& /*text*/)
1201         {}
1202
1203         virtual void Accept(const Element& /*element*/)
1204         {}
1205
1206         virtual void Accept(const XmlAttribute& attribute)
1207         {
1208             if (attribute.name == L"name") {
1209                 if (attribute.value.size() > 0) {
1210                     m_value = attribute.value;
1211                     NormalizeString(m_value);
1212                 }
1213             }
1214         }
1215
1216         virtual void Verify()
1217         {
1218             if (m_value.IsNull() || *m_value == L"") {
1219                 return;
1220             }
1221
1222             m_data.m_operation = *m_value;
1223         }
1224
1225         OperationParser(ConfigParserData::AppControlInfo& data) :
1226             ElementParser(),
1227             m_properNamespace(false),
1228             m_data(data)
1229         {}
1230
1231       private:
1232         bool m_properNamespace;
1233         DPL::OptionalString m_value;
1234         ConfigParserData::AppControlInfo& m_data;
1235     };
1236
1237     struct UriParser : public ElementParser
1238     {
1239       public:
1240         virtual ActionFunc GetElementParser(const DPL::String& /*ns*/,
1241                                             const DPL::String& /*name*/)
1242         {
1243             return &IgnoringParser::Create;
1244         }
1245
1246         virtual void Accept(const Text& /*text*/)
1247         {}
1248
1249         virtual void Accept(const Element& /*element*/)
1250         {}
1251
1252         virtual void Accept(const XmlAttribute& attribute)
1253         {
1254             if (attribute.name == L"name") {
1255                 if (attribute.value.size() > 0) {
1256                     m_value = attribute.value;
1257                     NormalizeString(m_value);
1258                 }
1259             }
1260         }
1261
1262         virtual void Verify()
1263         {
1264             if (m_value.IsNull() || *m_value == L"") {
1265                 return;
1266             }
1267
1268             DPL::String wildString(L"*/*");
1269             if ((m_data.m_uriList.find(wildString) ==
1270                  m_data.m_uriList.end())
1271                 && (m_data.m_uriList.find(*m_value) ==
1272                     m_data.m_uriList.end()))
1273             {
1274                 m_data.m_uriList.insert(*m_value);
1275             } else {
1276                 LogDebug("Ignoring uri with name" <<
1277                          DPL::ToUTF8String(*m_value));
1278             }
1279         }
1280
1281         UriParser(ConfigParserData::AppControlInfo& data) :
1282             ElementParser(),
1283             m_properNamespace(false),
1284             m_data(data)
1285         {}
1286
1287       private:
1288         bool m_properNamespace;
1289         DPL::OptionalString m_value;
1290         ConfigParserData::AppControlInfo& m_data;
1291     };
1292
1293     struct MimeParser : public ElementParser
1294     {
1295       public:
1296         virtual ActionFunc GetElementParser(const DPL::String& /*ns*/,
1297                                             const DPL::String& /*name*/)
1298         {
1299             return &IgnoringParser::Create;
1300         }
1301
1302         virtual void Accept(const Text& /*text*/)
1303         {}
1304
1305         virtual void Accept(const Element& /*element*/)
1306         {}
1307
1308         virtual void Accept(const XmlAttribute& attribute)
1309         {
1310             if (attribute.name == L"name") {
1311                 if (attribute.value.size() > 0) {
1312                     m_value = attribute.value;
1313                     NormalizeString(m_value);
1314                 }
1315             }
1316         }
1317
1318         virtual void Verify()
1319         {
1320             if (m_value.IsNull() || *m_value == L"") {
1321                 return;
1322             }
1323
1324             DPL::String wildString(L"*/*");
1325             if ((m_data.m_mimeList.find(wildString) ==
1326                  m_data.m_mimeList.end())
1327                 && (m_data.m_mimeList.find(*m_value) ==
1328                     m_data.m_mimeList.end()))
1329             {
1330                 m_data.m_mimeList.insert(*m_value);
1331             } else {
1332                 LogDebug("Ignoring mime with name" <<
1333                          DPL::ToUTF8String(*m_value));
1334             }
1335         }
1336
1337         MimeParser(ConfigParserData::AppControlInfo& data) :
1338             ElementParser(),
1339             m_properNamespace(false),
1340             m_data(data)
1341         {}
1342
1343       private:
1344         bool m_properNamespace;
1345         DPL::OptionalString m_value;
1346         ConfigParserData::AppControlInfo& m_data;
1347     };
1348
1349     virtual ActionFunc GetElementParser(const DPL::String& /*ns*/,
1350                                         const DPL::String& name)
1351     {
1352         if (name == L"src") {
1353             return DPL::MakeDelegate(this, &AppControlParser::OnSourceElement);
1354         } else if (name == L"operation") {
1355             return DPL::MakeDelegate(this,
1356                                      &AppControlParser::OnOperationElement);
1357         } else if (name == L"uri") {
1358             return DPL::MakeDelegate(this, &AppControlParser::OnUriElement);
1359         } else if (name == L"mime") {
1360             return DPL::MakeDelegate(this, &AppControlParser::OnMimeElement);
1361         } else {
1362             return &IgnoringParser::Create;
1363         }
1364     }
1365
1366     virtual void Accept(const XmlAttribute& attribute)
1367     {}
1368
1369     virtual void Accept(const Element& element)
1370     {
1371         LogWarning("namespace for app service = " << element.ns);
1372         if (element.ns == ConfigurationNamespace::W3CWidgetNamespaceName) {
1373             ThrowMsg(Exception::ParseError,
1374                      "Wrong xml namespace for widget element");
1375         }
1376     }
1377
1378     virtual void Accept(const Text& /*text*/)
1379     {
1380         ThrowMsg(Exception::ParseError, "param element must be empty");
1381     }
1382
1383     virtual void Verify()
1384     {
1385         if (m_appControl.m_src == L"") {
1386             LogWarning("service element must have src element");
1387             return;
1388         }
1389
1390         if (m_appControl.m_operation == L"") {
1391             LogWarning("service element must have operation element");
1392             return;
1393         }
1394
1395         FOREACH(iterator, m_data.appControlList) {
1396             if (iterator->m_src == m_appControl.m_src &&
1397                 iterator->m_operation == m_appControl.m_operation)
1398             {
1399                 ThrowMsg(Exception::ParseError,
1400                          "app control element is duplicated " +
1401                          DPL::ToUTF8String(m_appControl.m_src) + ", " +
1402                          DPL::ToUTF8String(m_appControl.m_operation));
1403             }
1404         }
1405         m_data.appControlList.push_back(m_appControl);
1406     }
1407
1408     ElementParserPtr OnSourceElement()
1409     {
1410         return ElementParserPtr(new SourceParser(m_appControl));
1411     }
1412
1413     ElementParserPtr OnOperationElement()
1414     {
1415         return ElementParserPtr(new OperationParser(m_appControl));
1416     }
1417
1418     ElementParserPtr OnUriElement()
1419     {
1420         return ElementParserPtr(new UriParser(m_appControl));
1421     }
1422
1423     ElementParserPtr OnMimeElement()
1424     {
1425         return ElementParserPtr(new MimeParser(m_appControl));
1426     }
1427
1428     AppControlParser(ConfigParserData& data) :
1429         ElementParser(),
1430         m_data(data),
1431         m_appControl(L"")
1432     {}
1433
1434   private:
1435     ConfigParserData& m_data;
1436     ConfigParserData::AppControlInfo m_appControl;
1437 };
1438
1439 class ApplicationParser : public ElementParser
1440 {
1441   public:
1442     virtual ActionFunc GetElementParser(const DPL::String& /*ns*/,
1443                                         const DPL::String& /*name*/)
1444     {
1445         return &IgnoringParser::Create;
1446     }
1447
1448     virtual void Accept(const Text& text)
1449     {
1450         if (m_properNamespace) {
1451             LogDebug("text");
1452             ThrowMsg(Exception::ParseError, "application element must be empty");
1453         }
1454     }
1455
1456     virtual void Accept(const Element& element)
1457     {
1458         if (element.ns ==
1459             ConfigurationNamespace::TizenWebAppNamespaceName)
1460         {
1461             m_properNamespace = true;
1462         }
1463         LogDebug("element");
1464     }
1465
1466     virtual void Accept(const XmlAttribute& attribute)
1467     {
1468         if (m_properNamespace) {
1469             LogDebug("attribute");
1470             if (attribute.name == L"id") {
1471                 m_id = attribute.value;
1472                 NormalizeAndTrimSpaceString(m_id);
1473             } else if (attribute.name == L"package") {
1474                 m_package = attribute.value;
1475             } else if (attribute.name == L"required_version") {
1476                 m_version = attribute.value;
1477                 NormalizeString(m_version);
1478             } else {
1479                 ThrowMsg(Exception::ParseError,
1480                          "unknown attribute '" +
1481                          DPL::ToUTF8String(attribute.name) +
1482                          "' in application element");
1483             }
1484         }
1485     }
1486
1487     virtual void Verify()
1488     {
1489         if (!m_id) {
1490             ThrowMsg(Exception::ParseError,
1491                      "application element must have id attribute");
1492         }
1493
1494         if (!!m_package) {
1495             m_data.tizenPkgId = m_package;
1496         }
1497
1498         if (!m_version) {
1499             ThrowMsg(Exception::ParseError,
1500                      "application element must have required_version attribute");
1501         }
1502
1503         //TODO check if id and version format is right
1504         m_data.tizenAppId = m_id;
1505         m_data.tizenMinVersionRequired = m_version;
1506     }
1507
1508     ApplicationParser(ConfigParserData& data) :
1509         ElementParser(),
1510         m_data(data),
1511         m_id(DPL::OptionalString::Null),
1512         m_version(DPL::OptionalString::Null),
1513         m_properNamespace(false)
1514     {}
1515
1516   private:
1517     ConfigParserData& m_data;
1518     DPL::OptionalString m_id;
1519     DPL::OptionalString m_package;
1520     DPL::OptionalString m_version;
1521     bool m_properNamespace;
1522 };
1523
1524 class SplashParser : public ElementParser
1525 {
1526   public:
1527     virtual ActionFunc GetElementParser(const DPL::String& /*ns*/,
1528                                         const DPL::String& /*name*/)
1529     {
1530         return &IgnoringParser::Create;
1531     }
1532
1533     virtual void Accept(const XmlAttribute& attribute)
1534     {
1535         if (attribute.name == L"src") {
1536             if (attribute.value.size() > 0) {
1537                 m_src = attribute.value;
1538             }
1539         }
1540     }
1541
1542     virtual void Accept(const Element& element)
1543     {}
1544
1545     virtual void Accept(const Text& /*text*/)
1546     {}
1547
1548     virtual void Verify()
1549     {
1550         if (m_src.IsNull()) {
1551             LogWarning(
1552                 "src attribute of splash element is mandatory - ignoring");
1553             return;
1554         }
1555
1556         m_data.splashImgSrc = m_src;
1557     }
1558
1559     SplashParser(ConfigParserData& data) :
1560         ElementParser(),
1561         m_data(data)
1562     {}
1563
1564   private:
1565     DPL::OptionalString m_src;
1566     ConfigParserData& m_data;
1567 };
1568
1569 class BackgroundParser : public ElementParser
1570 {
1571   public:
1572     virtual ActionFunc GetElementParser(const DPL::String& /*ns*/,
1573                                         const DPL::String& /*name*/)
1574     {
1575         return &IgnoringParser::Create;
1576     }
1577
1578     virtual void Accept(const XmlAttribute& attribute)
1579     {
1580         if (attribute.name == L"src") {
1581             if (attribute.value.size() > 0) {
1582                 m_src = attribute.value;
1583             }
1584         }
1585     }
1586
1587     virtual void Accept(const Element& /*element*/)
1588     {}
1589
1590     virtual void Accept(const Text& /*text*/)
1591     {}
1592
1593     virtual void Verify()
1594     {
1595         if (m_src.IsNull()) {
1596             LogWarning(
1597                 "src attribute of background element is mandatory - ignoring");
1598             return;
1599         }
1600
1601         m_data.backgroundPage = m_src;
1602     }
1603
1604     explicit BackgroundParser(ConfigParserData& data) :
1605         m_data(data)
1606     {}
1607
1608   private:
1609     DPL::OptionalString m_src;
1610     ConfigParserData& m_data;
1611 };
1612
1613 class PrivilegeParser : public ElementParser
1614 {
1615   public:
1616     virtual ActionFunc GetElementParser(const DPL::String& /*ns*/,
1617                                         const DPL::String& name)
1618     {
1619         return &IgnoringParser::Create;
1620     }
1621
1622     virtual void Accept(const Text& /*text*/)
1623     {}
1624
1625     virtual void Accept(const Element& element)
1626     {
1627         if (element.ns ==
1628             ConfigurationNamespace::TizenWebAppNamespaceName)
1629         {
1630             m_properNamespace = true;
1631         }
1632         LogDebug("element");
1633     }
1634
1635     virtual void Accept(const XmlAttribute& attribute)
1636     {
1637         if (m_properNamespace) {
1638             if (attribute.name == L"name") {
1639                 m_feature.name = attribute.value;
1640                 m_privilege.name = attribute.value;
1641             }
1642         }
1643         m_feature.required = false;
1644     }
1645
1646     virtual void Verify()
1647     {
1648         LibIri::Wrapper iri(DPL::ToUTF8String(m_feature.name).c_str());
1649
1650         if (m_feature.name != L"") {
1651             if (iri.Validate()) {
1652                 if (m_data.featuresList.find(m_feature) ==
1653                     m_data.featuresList.end())
1654                 {
1655                     m_data.featuresList.insert(m_feature);
1656                 } else {
1657                     LogDebug("Ignoring feature with name" <<
1658                              DPL::ToUTF8String(m_feature.name));
1659                 }
1660             }
1661         }
1662
1663         LibIri::Wrapper iriPrivilege(
1664             DPL::ToUTF8String(m_privilege.name).c_str());
1665
1666         if (m_privilege.name != L"") {
1667             if (iriPrivilege.Validate()) {
1668                 if (m_data.privilegeList.find(m_privilege) ==
1669                     m_data.privilegeList.end())
1670                 {
1671                     m_data.privilegeList.insert(m_privilege);
1672                 } else {
1673                     LogDebug("Ignoring privilege with name" <<
1674                              DPL::ToUTF8String(m_privilege.name));
1675                 }
1676             }
1677         }
1678     }
1679
1680     PrivilegeParser(ConfigParserData& data) :
1681         ElementParser(),
1682         m_data(data),
1683         m_feature(L""),
1684         m_privilege(L""),
1685         m_properNamespace(false)
1686     {}
1687
1688   private:
1689     ConfigParserData& m_data;
1690     ConfigParserData::Feature m_feature;
1691     ConfigParserData::Privilege m_privilege;
1692     bool m_properNamespace;
1693 };
1694
1695 class CategoryParser : public ElementParser
1696 {
1697   public:
1698     virtual ActionFunc GetElementParser(const DPL::String& /*ns*/,
1699                                         const DPL::String& /*name*/)
1700     {
1701         return &IgnoringParser::Create;
1702     }
1703
1704     virtual void Accept(const XmlAttribute& attribute)
1705     {
1706         if (attribute.name == L"name") {
1707             if (attribute.value.size() > 0) {
1708                 m_name = attribute.value;
1709             }
1710         }
1711     }
1712
1713     virtual void Accept(const Element& /*element*/)
1714     {}
1715
1716     virtual void Accept(const Text& /*text*/)
1717     {}
1718
1719     virtual void Verify()
1720     {
1721         if (m_name.IsNull()) {
1722             LogWarning(
1723                 "name attribute of category element is mandatory - ignoring");
1724             return;
1725         }
1726
1727         if (m_data.categoryList.find(*m_name) ==
1728             m_data.categoryList.end())
1729         {
1730             m_data.categoryList.insert(*m_name);
1731         }
1732     }
1733
1734     explicit CategoryParser(ConfigParserData& data) :
1735         m_data(data)
1736     {}
1737
1738   private:
1739     DPL::OptionalString m_name;
1740     ConfigParserData& m_data;
1741 };
1742
1743 class LiveboxParser : public ElementParser
1744 {
1745   public:
1746
1747     struct BoxLabelParser : public ElementParser
1748     {
1749         virtual ActionFunc GetElementParser(const DPL::String& /*ns*/,
1750                                             const DPL::String& /*name*/)
1751         {
1752             return &IgnoringParser::Create;
1753         }
1754
1755         virtual void Accept(const XmlAttribute& attribute)
1756         {}
1757
1758         virtual void Accept(const Element& element)
1759         {
1760             if (element.ns ==
1761                 ConfigurationNamespace::TizenWebAppNamespaceName)
1762             {
1763                 m_properNamespace = true;
1764             }
1765         }
1766
1767         virtual void Accept(const Text& text)
1768         {
1769             if (m_properNamespace) {
1770                 m_label = text.value;
1771             }
1772         }
1773
1774         virtual void Verify()
1775         {
1776             m_data.m_label = m_label;
1777         }
1778
1779         BoxLabelParser(ConfigParserData::LiveboxInfo& data) :
1780             ElementParser(),
1781             m_properNamespace(false),
1782             m_data(data)
1783         {}
1784
1785       private:
1786         DPL::String m_label;
1787         bool m_properNamespace;
1788         ConfigParserData::LiveboxInfo& m_data;
1789     };
1790
1791     struct BoxIconParser : public ElementParser
1792     {
1793         virtual ActionFunc GetElementParser(const DPL::String& /*ns*/,
1794                                             const DPL::String& /*name*/)
1795         {
1796             return &IgnoringParser::Create;
1797         }
1798
1799         virtual void Accept(const XmlAttribute& attribute)
1800         {
1801             if (m_properNamespace) {
1802                 if (attribute.name == L"src") {
1803                     m_icon = attribute.value;
1804                 }
1805             }
1806         }
1807
1808         virtual void Accept(const Element& element)
1809         {
1810             if (element.ns ==
1811                 ConfigurationNamespace::TizenWebAppNamespaceName)
1812             {
1813                 m_properNamespace = true;
1814             }
1815         }
1816
1817         virtual void Accept(const Text& /*text*/)
1818         {}
1819
1820         virtual void Verify()
1821         {
1822             m_data.m_icon = m_icon;
1823         }
1824
1825         explicit BoxIconParser(ConfigParserData::LiveboxInfo& data) :
1826             ElementParser(),
1827             m_properNamespace(false),
1828             m_data(data)
1829         {}
1830
1831       private:
1832         DPL::String m_icon;
1833         bool m_properNamespace;
1834         ConfigParserData::LiveboxInfo& m_data;
1835     };
1836
1837     struct BoxContentParser : public ElementParser
1838     {
1839         struct BoxSizeParser : public ElementParser
1840         {
1841             virtual ActionFunc GetElementParser(const DPL::String& /*ns*/,
1842                                                 const DPL::String& /*name*/)
1843             {
1844                 return &IgnoringParser::Create;
1845             }
1846
1847             virtual void Accept(const XmlAttribute& attribute)
1848             {
1849                 if (m_properNamespace) {
1850                     if (attribute.name == L"preview") {
1851                         m_preview = attribute.value;
1852                     }
1853                 }
1854             }
1855
1856             virtual void Accept(const Element& element)
1857             {
1858                 if (element.ns ==
1859                     ConfigurationNamespace::TizenWebAppNamespaceName)
1860                 {
1861                     m_properNamespace = true;
1862                 }
1863             }
1864
1865             virtual void Accept(const Text& text)
1866             {
1867                 if (m_properNamespace) {
1868                     m_size = text.value;
1869                 }
1870             }
1871
1872             virtual void Verify()
1873             {
1874                 std::pair<DPL::String, DPL::String> boxSize;
1875                 boxSize.first = m_size;
1876                 boxSize.second = m_preview;
1877                 m_data.m_boxSize.push_back(boxSize);
1878             }
1879
1880             explicit BoxSizeParser(
1881                 ConfigParserData::LiveboxInfo::BoxContentInfo& data) :
1882                 ElementParser(),
1883                 m_data(data)
1884             {}
1885
1886           private:
1887             DPL::String m_size;
1888             DPL::String m_preview;
1889             bool m_properNamespace;
1890             ConfigParserData::LiveboxInfo::BoxContentInfo& m_data;
1891         };
1892
1893         struct PdParser : public ElementParser
1894         {
1895             virtual ActionFunc GetElementParser(const DPL::String& /*ns*/,
1896                                                 const DPL::String& name)
1897             {
1898                 return &IgnoringParser::Create;
1899             }
1900
1901             virtual void Accept(const XmlAttribute& attribute)
1902             {
1903                 if (m_properNamespace) {
1904                     if (attribute.name == L"src") {
1905                         m_src = attribute.value;
1906                     } else if (attribute.name == L"width") {
1907                         m_width = attribute.value;
1908                     } else if (attribute.name == L"height") {
1909                         m_height = attribute.value;
1910                     }
1911                 }
1912             }
1913
1914             virtual void Accept(const Element& element)
1915             {
1916                 if (element.ns ==
1917                     ConfigurationNamespace::TizenWebAppNamespaceName)
1918                 {
1919                     m_properNamespace = true;
1920                 }
1921             }
1922
1923             virtual void Accept(const Text& /*text*/)
1924             {}
1925
1926             virtual void Verify()
1927             {
1928                 m_data.m_pdSrc = m_src;
1929                 m_data.m_pdWidth = m_width;
1930                 m_data.m_pdHeight = m_height;
1931             }
1932
1933             explicit PdParser(
1934                 ConfigParserData::LiveboxInfo::BoxContentInfo& data) :
1935                 ElementParser(),
1936                 m_properNamespace(false),
1937                 m_data(data)
1938             {}
1939
1940           private:
1941             DPL::String m_src;
1942             DPL::String m_width;
1943             DPL::String m_height;
1944
1945             bool m_properNamespace;
1946             ConfigParserData::LiveboxInfo::BoxContentInfo& m_data;
1947         };
1948
1949         virtual ActionFunc GetElementParser(const DPL::String& /*ns*/,
1950                                             const DPL::String& name)
1951         {
1952             if (name == L"box-size") {
1953                 return DPL::MakeDelegate(
1954                            this,
1955                            &LiveboxParser::BoxContentParser::
1956                                OnBoxSizeElement);
1957             } else if (name == L"pd") {
1958                 return DPL::MakeDelegate(
1959                            this,
1960                            &LiveboxParser::BoxContentParser::
1961                                OnPdElement);
1962             } else {
1963                 ThrowMsg(Exception::ParseError,
1964                          "No element parser for name: " << name);
1965             }
1966         }
1967
1968         virtual void Accept(const XmlAttribute& attribute)
1969         {
1970             if (m_properNamespace) {
1971                 if (attribute.name == L"src") {
1972                     m_box.m_boxSrc = attribute.value;
1973                 }
1974                 if (attribute.name == L"mouse-event") {
1975                     m_box.m_boxMouseEvent = attribute.value;
1976                 }
1977             }
1978         }
1979
1980         virtual void Accept(const Element& element)
1981         {
1982             if (element.ns ==
1983                 ConfigurationNamespace::TizenWebAppNamespaceName)
1984             {
1985                 m_properNamespace = true;
1986             }
1987         }
1988
1989         virtual void Accept(const Text& /*text*/)
1990         {}
1991
1992         virtual void Verify()
1993         {
1994             m_data.m_boxInfo = m_box;
1995         }
1996
1997         explicit BoxContentParser(ConfigParserData::LiveboxInfo& data) :
1998             ElementParser(),
1999             m_properNamespace(false),
2000             m_data(data)
2001         {}
2002
2003         ElementParserPtr OnBoxSizeElement()
2004         {
2005             return ElementParserPtr(new BoxSizeParser(m_box));
2006         }
2007
2008         ElementParserPtr OnPdElement()
2009         {
2010             return ElementParserPtr(new PdParser(m_box));
2011         }
2012
2013       private:
2014         DPL::String m_src;
2015         bool m_properNamespace;
2016         ConfigParserData::LiveboxInfo& m_data;
2017         ConfigParserData::LiveboxInfo::BoxContentInfo m_box;
2018     };
2019
2020     virtual ActionFunc GetElementParser(const DPL::String& /*ns*/,
2021                                         const DPL::String& name)
2022     {
2023         if (name == L"box-label") {
2024             return DPL::MakeDelegate(this, &LiveboxParser::OnBoxLabelElement);
2025         } else if (name == L"box-icon") {
2026             return DPL::MakeDelegate(this, &LiveboxParser::OnBoxIconElement);
2027         } else if (name == L"box-content") {
2028             return DPL::MakeDelegate(this, &LiveboxParser::OnBoxContentElement);
2029         } else {
2030             return &IgnoringParser::Create;
2031         }
2032     }
2033
2034     virtual void Accept(const XmlAttribute& attribute)
2035     {
2036         if (m_properNamespace) {
2037             if (attribute.name == L"id") {
2038                 m_liveboxId = attribute.value;
2039             } else if (attribute.name == L"primary") {
2040                 m_primary = attribute.value;
2041             } else if (attribute.name == L"auto-launch") {
2042                 m_autoLaunch = attribute.value;
2043             } else if (attribute.name == L"update-period") {
2044                 m_updatePeriod = attribute.value;
2045             } else if (attribute.name == L"type") {
2046                 m_type = attribute.value;
2047             }
2048         }
2049     }
2050
2051     virtual void Accept(const Element& element)
2052     {
2053         if (element.ns ==
2054             ConfigurationNamespace::TizenWebAppNamespaceName)
2055         {
2056             m_properNamespace = true;
2057         }
2058     }
2059
2060     virtual void Accept(const Text& /*text*/)
2061     {}
2062
2063     virtual void Verify()
2064     {
2065         m_livebox.m_liveboxId = m_liveboxId;
2066         m_livebox.m_primary = m_primary;
2067         m_livebox.m_autoLaunch = m_autoLaunch;
2068         m_livebox.m_updatePeriod = m_updatePeriod;
2069         m_livebox.m_type = m_type;
2070
2071         m_data.m_livebox.push_back(m_livebox);
2072     }
2073
2074     explicit LiveboxParser(ConfigParserData& data) :
2075         ElementParser(),
2076         m_data(data),
2077         m_properNamespace(false)
2078     {
2079         m_livebox = ConfigParserData::LiveboxInfo();
2080     }
2081
2082     ElementParserPtr OnBoxLabelElement()
2083     {
2084         return ElementParserPtr(new BoxLabelParser(m_livebox));
2085     }
2086
2087     ElementParserPtr OnBoxIconElement()
2088     {
2089         return ElementParserPtr(new BoxIconParser(m_livebox));
2090     }
2091
2092     ElementParserPtr OnBoxContentElement()
2093     {
2094         return ElementParserPtr(new BoxContentParser(m_livebox));
2095     }
2096
2097   private:
2098     ConfigParserData& m_data;
2099     ConfigParserData::LiveboxInfo m_livebox;
2100     DPL::String m_liveboxId;
2101     DPL::String m_primary;
2102     DPL::String m_autoLaunch;
2103     DPL::String m_updatePeriod;
2104     DPL::String m_type;
2105     bool m_properNamespace;
2106 };
2107
2108 class CspParser : public ElementParser
2109 {
2110   public:
2111     virtual ActionFunc GetElementParser(const DPL::String& ns,
2112                                         const DPL::String& name)
2113     {
2114         return &IgnoringParser::Create;
2115     }
2116
2117     CspParser(ConfigParserData& data) :
2118         ElementParser(),
2119         m_data(data),
2120         m_properNamespace(false)
2121     {}
2122
2123     virtual void Accept(const Element& element)
2124     {
2125         if (element.ns == ConfigurationNamespace::TizenWebAppNamespaceName) {
2126             m_properNamespace = true;
2127         }
2128     }
2129
2130     virtual void Accept(const XmlAttribute& attribute)
2131     {}
2132
2133     virtual void Accept(const Text& text)
2134     {
2135         if (m_properNamespace) {
2136             m_policy = text.value;
2137         }
2138     }
2139
2140     virtual void Verify()
2141     {
2142         if (!m_policy.IsNull()) {
2143             m_data.cspPolicy = *m_policy;
2144         }
2145     }
2146
2147   private:
2148     ConfigParserData& m_data;
2149     bool m_properNamespace;
2150     DPL::OptionalString m_policy;
2151 };
2152
2153 ElementParser::ActionFunc WidgetParser::GetElementParser(
2154     const DPL::String& /*ns*/,
2155     const DPL::String&
2156     name)
2157 {
2158     FuncMap::const_iterator it = m_map.find(name);
2159     if (it != m_map.end()) {
2160         return it->second;
2161     } else {
2162         return &IgnoringParser::Create;
2163     }
2164 }
2165
2166 WidgetParser::WidgetParser(ConfigParserData& data) :
2167     m_data(data),
2168     m_textDirection(Unicode::EMPTY)
2169 {
2170     m_map[L"name"] = DPL::MakeDelegate(this, &WidgetParser::OnNameElement);
2171     m_map[L"access"] = DPL::MakeDelegate(this, &WidgetParser::OnAccessElement);
2172     m_map[L"description"] =
2173         DPL::MakeDelegate(this, &WidgetParser::OnDescriptionElement);
2174     m_map[L"author"] = DPL::MakeDelegate(this, &WidgetParser::OnAuthorElement);
2175     m_map[L"license"] =
2176         DPL::MakeDelegate(this, &WidgetParser::OnLicenseElement);
2177     m_map[L"icon"] = DPL::MakeDelegate(this, &WidgetParser::OnIconElement);
2178     m_map[L"content"] =
2179         DPL::MakeDelegate(this, &WidgetParser::OnContentElement);
2180     m_map[L"feature"] =
2181         DPL::MakeDelegate(this, &WidgetParser::OnFeatureElement);
2182     m_map[L"preference"] =
2183         DPL::MakeDelegate(this, &WidgetParser::OnPreferenceElement);
2184     m_map[L"link"] = DPL::MakeDelegate(this, &WidgetParser::OnLinkElement);
2185     m_map[L"setting"] =
2186         DPL::MakeDelegate(this, &WidgetParser::OnSettingElement);
2187     // TODO: appservice will be removed
2188     m_map[L"appservice"] = DPL::MakeDelegate(this,
2189                                              &WidgetParser::OnAppServiceElement);
2190     m_map[L"application"] = DPL::MakeDelegate(
2191             this,
2192             &WidgetParser::
2193                 OnApplicationElement);
2194     m_map[L"splash"] = DPL::MakeDelegate(this, &WidgetParser::OnSplashElement);
2195     m_map[L"background"] = DPL::MakeDelegate(this,
2196                                              &WidgetParser::OnBackgroundElement);
2197     m_map[L"privilege"] = DPL::MakeDelegate(this,
2198                                             &WidgetParser::OnPrivilegeElement);
2199     m_map[L"app-control"] = DPL::MakeDelegate(
2200             this,
2201             &WidgetParser::
2202                 OnAppControlElement);
2203     m_map[L"category"] = DPL::MakeDelegate(this,
2204                                            &WidgetParser::OnCategoryElement);
2205     m_map[L"livebox"] = DPL::MakeDelegate(this, &WidgetParser::OnLiveboxElement);
2206 #ifdef CSP_ENABLED
2207     m_map[L"Content-Security-Policy"] = DPL::MakeDelegate(
2208             this,
2209             &WidgetParser::
2210                 OnCspElement);
2211 #endif
2212 }
2213
2214 ElementParserPtr WidgetParser::OnNameElement()
2215 {
2216     return ElementParserPtr(new NameParser(m_textDirection, m_data));
2217 }
2218
2219 ElementParserPtr WidgetParser::OnAccessElement()
2220 {
2221     return ElementParserPtr(new AccessParser(m_data));
2222 }
2223
2224 ElementParserPtr WidgetParser::OnDescriptionElement()
2225 {
2226     return ElementParserPtr(new DescriptionParser(m_textDirection, m_data));
2227 }
2228
2229 ElementParserPtr WidgetParser::OnAuthorElement()
2230 {
2231     return ElementParserPtr(new AuthorParser(m_textDirection, m_data));
2232 }
2233
2234 ElementParserPtr WidgetParser::OnLicenseElement()
2235 {
2236     return ElementParserPtr(new LicenseParser(m_textDirection, m_data));
2237 }
2238
2239 ElementParserPtr WidgetParser::OnIconElement()
2240 {
2241     return ElementParserPtr(new IconParser(m_data));
2242 }
2243
2244 ElementParserPtr WidgetParser::OnContentElement()
2245 {
2246     return ElementParserPtr(new ContentParser(m_data));
2247 }
2248
2249 ElementParserPtr WidgetParser::OnFeatureElement()
2250 {
2251     return ElementParserPtr(new FeatureParser(m_data));
2252 }
2253
2254 ElementParserPtr WidgetParser::OnPreferenceElement()
2255 {
2256     return ElementParserPtr(new PreferenceParser(m_data));
2257 }
2258
2259 ElementParserPtr WidgetParser::OnLinkElement()
2260 {
2261     return ElementParserPtr(new LinkParser(m_data));
2262 }
2263
2264 ElementParserPtr WidgetParser::OnSettingElement()
2265 {
2266     return ElementParserPtr(new SettingParser(m_data));
2267 }
2268
2269 ElementParserPtr WidgetParser::OnApplicationElement()
2270 {
2271     return ElementParserPtr(new ApplicationParser(m_data));
2272 }
2273
2274 ElementParserPtr WidgetParser::OnSplashElement()
2275 {
2276     return ElementParserPtr(new SplashParser(m_data));
2277 }
2278
2279 ElementParserPtr WidgetParser::OnBackgroundElement()
2280 {
2281     return ElementParserPtr(new BackgroundParser(m_data));
2282 }
2283
2284 ElementParserPtr WidgetParser::OnPrivilegeElement()
2285 {
2286     return ElementParserPtr(new PrivilegeParser(m_data));
2287 }
2288
2289 ElementParserPtr WidgetParser::OnAppServiceElement()
2290 {
2291     return ElementParserPtr(new AppServiceParser(m_data));
2292 }
2293
2294 ElementParserPtr WidgetParser::OnAppControlElement()
2295 {
2296     return ElementParserPtr(new AppControlParser(m_data));
2297 }
2298
2299 ElementParserPtr WidgetParser::OnCategoryElement()
2300 {
2301     return ElementParserPtr(new CategoryParser(m_data));
2302 }
2303
2304 ElementParserPtr WidgetParser::OnLiveboxElement()
2305 {
2306     return ElementParserPtr(new LiveboxParser(m_data));
2307 }
2308
2309 ElementParserPtr WidgetParser::OnCspElement()
2310 {
2311     return ElementParserPtr(new CspParser(m_data));
2312 }
2313
2314 void WidgetParser::Accept(const Element& element)
2315 {
2316     if (element.ns != ConfigurationNamespace::W3CWidgetNamespaceName &&
2317         element.ns != ConfigurationNamespace::TizenWebAppNamespaceName)
2318     {
2319         ThrowMsg(Exception::ParseError,
2320                  "Wrong xml namespace for widget element");
2321     }
2322 }
2323
2324 void WidgetParser::Accept(const Text& /*text*/)
2325 {
2326     ThrowMsg(Exception::ParseError, "widged element must be empty");
2327 }
2328
2329 void WidgetParser::Accept(const XmlAttribute& attribute)
2330 {
2331     if (attribute.name == L"id") {
2332         LibIri::Wrapper iri(DPL::ToUTF8String(attribute.value).c_str());
2333         //If may important tests starts to fail this test we will have
2334         //to consider commenting this test out again.
2335         if (iri.Validate()) {
2336             m_data.widget_id = attribute.value;
2337             NormalizeString(m_data.widget_id);
2338         } else {
2339             LogWarning("Widget id validation failed: " << attribute.value);
2340         }
2341     } else if (attribute.name == L"version") {
2342         m_version = attribute.value;
2343         NormalizeString(m_version);
2344     } else if (attribute.name == L"min-version") {
2345         LogInfo("min-version attribute was found. Value: " << attribute.value);
2346         m_minVersion = attribute.value;
2347         NormalizeString(m_minVersion);
2348         m_data.minVersionRequired = m_minVersion;
2349     } else if (attribute.name == L"height") {
2350         DPL::OptionalString value = attribute.value;
2351         NormalizeString(value);
2352         std::string v = DPL::ToUTF8String(*value);
2353
2354         if (!v.empty()) {
2355             unsigned char c = v.c_str()[0];
2356             if (c >= '0' && c <= '9') {
2357                 int val = 0;
2358                 for (size_t i = 0; i < v.size(); ++i) {
2359                     c = v.c_str()[i];
2360                     if (c >= '0' && c <= '9') {
2361                         val *= 10;
2362                         val += (c - '0');
2363                     } else {
2364                         break;
2365                     }
2366                 }
2367                 m_data.height = val;
2368             }
2369         }
2370     } else if (attribute.name == L"width") {
2371         DPL::OptionalString value = attribute.value;
2372         NormalizeString(value);
2373         std::string v = DPL::ToUTF8String(*value);
2374
2375         if (!v.empty()) {
2376             unsigned char c = v.c_str()[0];
2377             if (c >= '0' && c <= '9') {
2378                 int val = 0;
2379                 for (size_t i = 0; i < v.size(); ++i) {
2380                     c = v.c_str()[i];
2381                     if (c >= '0' && c <= '9') {
2382                         val *= 10;
2383                         val += (c - '0');
2384                     } else {
2385                         break;
2386                     }
2387                 }
2388                 m_data.width = val;
2389             }
2390         }
2391     } else if (attribute.name == L"viewmodes") {
2392         DPL::Tokenize(attribute.value,
2393                       L" ",
2394                       std::inserter(m_windowModes,
2395                                     m_windowModes.end()),
2396                       true);
2397     } else if (attribute.name == L"dir") {
2398         m_textDirection = Unicode::ParseDirAttribute(attribute);
2399     } else if (L"defaultlocale" == attribute.name) {
2400         if (!m_defaultlocale) {
2401             m_defaultlocale = attribute.value;
2402             NormalizeString(m_defaultlocale);
2403             if (!LanguageSubtagRstTreeSingleton::Instance().ValidateLanguageTag(
2404                     DPL::ToUTF8String(*m_defaultlocale)))
2405             {
2406                 LogWarning("Language tag: " <<
2407                            m_defaultlocale << " is not valid");
2408                 m_defaultlocale = DPL::OptionalString::Null;
2409             } else {
2410                 LogDebug("Default Locale Found " << m_defaultlocale);
2411             }
2412         } else {
2413             LogWarning("Ignoring subsequent default locale");
2414         }
2415
2416         //Any other value consider as a namespace definition
2417     } else if (attribute.name == L"xmlns" || attribute.prefix == L"xmlns") {
2418         LogInfo("Namespace domain: " << attribute.name);
2419         LogInfo("Namespace value: " << attribute.value);
2420         m_nameSpaces[attribute.name] = attribute.value;
2421     } else {
2422         LogError("Unknown attirbute: namespace=" << attribute.ns <<
2423                  ", name=" << attribute.name <<
2424                  ", value=" << attribute.value);
2425     }
2426 }
2427
2428 void WidgetParser::Verify()
2429 {
2430     FOREACH(mode, m_windowModes) {
2431         if (L"windowed" == *mode || L"floating" == *mode ||
2432             L"fullscreen" == *mode || L"maximized" == *mode ||
2433             L"minimized" == *mode)
2434         {
2435             m_data.windowModes.insert(*mode);
2436         }
2437     }
2438     if (!m_version.IsNull()) {
2439         Unicode::UpdateTextWithDirectionMark(m_textDirection, &*m_version);
2440         m_data.version = m_version;
2441     }
2442     m_data.defaultlocale = m_defaultlocale;
2443     FOREACH(ns, m_nameSpaces) {
2444         m_data.nameSpaces.insert(ns->second);
2445     }
2446 }
2447