tizen beta release
[framework/web/wrt-installer.git] / src / configuration_parser / widget_parser.cpp
1 /*
2  * Copyright (c) 2011 Samsung Electronics Co., Ltd All Rights Reserved
3  *
4  *    Licensed under the Apache License, Version 2.0 (the "License");
5  *    you may not use this file except in compliance with the License.
6  *    You may obtain a copy of the License at
7  *
8  *        http://www.apache.org/licenses/LICENSE-2.0
9  *
10  *    Unless required by applicable law or agreed to in writing, software
11  *    distributed under the License is distributed on an "AS IS" BASIS,
12  *    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  *    See the License for the specific language governing permissions and
14  *    limitations under the License.
15  */
16  /**
17  * This file  have been implemented in compliance with  W3C WARP SPEC.
18  * but there are some patent issue between  W3C WARP SPEC and APPLE.
19  * so if you want to use this file, refer to the README file in root directory
20  */
21 /**
22  * @file        widget_parser.cpp
23  * @author      Lukasz Wrzosek (l.wrzosek@samsung.com)
24  * @version     0.1
25  * @brief
26  */
27 #include "widget_parser.h"
28 #include "ignoring_parser.h"
29 #include "deny_all_parser.h"
30 #include <dpl/wrt-dao-ro/config_parser_data.h>
31 #include "libiriwrapper.h"
32 #include <dpl/utils/warp_iri.h>
33 #include <dpl/utils/mime_type_utils.h>
34 #include <language_subtag_rst_tree.h>
35 #include <ewk_main.h>
36
37 #include <iri.h>
38 #include <dpl/log/log.h>
39 #include <dpl/fast_delegate.h>
40 #include <dpl/foreach.h>
41 #include <algorithm>
42 #include <cstdio>
43 #include <cerrno>
44
45 using namespace WrtDB;
46
47 namespace Unicode {
48 static const DPL::String UTF_LRE = L"\x0202a";
49 static const DPL::String UTF_LRO = L"\x0202d";
50 static const DPL::String UTF_RLE = L"\x0202b";
51 static const DPL::String UTF_RLO = L"\x0202e";
52 static const DPL::String UTF_PDF = L"\x0202c";
53
54 Direction ParseDirAttribute(const XmlAttribute& attribute)
55 {
56     Assert(L"dir" == attribute.name);
57     if (L"ltr" == attribute.value) {
58         return LRE;
59     } else if (L"rtl" == attribute.value) {
60         return RLE;
61     } else if (L"lro" == attribute.value) {
62         return LRO;
63     } else if (L"rlo" == attribute.value) {
64         return RLO;
65     } else {
66         LogWarning("dir attribute has wrong value:" << attribute.value);
67         return EMPTY;
68     }
69 }
70
71 void UpdateTextWithDirectionMark(Direction direction,
72         DPL::String* text)
73 {
74     Assert(text);
75     switch (direction) {
76     case RLO:
77         *text = UTF_RLO + *text + UTF_PDF;
78         break;
79     case RLE:
80         *text = UTF_RLE + *text + UTF_PDF;
81         break;
82     case LRE:
83         *text = UTF_LRE + *text + UTF_PDF;
84         break;
85     case LRO:
86         *text = UTF_LRO + *text + UTF_PDF;
87         break;
88     case EMPTY:
89         break;
90     default:
91         Assert(false);
92     }
93 }
94 } // namespace Unicode
95
96 class InnerElementsParser : public ElementParser
97 {
98   public:
99     virtual ActionFunc GetElementParser(const DPL::String& /*ns*/,
100             const DPL::String& /*name*/)
101     {
102         return DPL::MakeDelegate(this, &InnerElementsParser::Other);
103     }
104
105     virtual void Accept(const Element& /*element*/)
106     {
107     }
108
109     virtual void Accept(const Text& text)
110     {
111         if (m_text.IsNull()) {
112             m_text = text;
113         } else {
114             m_text->value += text.value;
115         }
116     }
117
118     virtual void Accept(const XmlAttribute& attribute)
119     {
120         if (attribute.name == L"dir") {
121             m_textDirection = Unicode::ParseDirAttribute(attribute);
122         }
123     }
124
125     virtual void Verify()
126     {
127         if (!m_text.IsNull()) {
128             Unicode::UpdateTextWithDirectionMark(m_textDirection,
129                                                  &m_text->value);
130             m_parentParser->Accept(*m_text);
131         }
132     }
133
134     InnerElementsParser(ElementParserPtr parent) :
135         m_parentParser(parent),
136         m_textDirection(Unicode::EMPTY)
137     {
138     }
139
140     ElementParserPtr Other()
141     {
142         return ElementParserPtr(new InnerElementsParser(
143                                     DPL::StaticPointerCast<ElementParser>(
144                                         SharedFromThis())));
145     }
146
147   private:
148     DPL::Optional<Text> m_text;
149     ElementParserPtr m_parentParser;
150     Unicode::Direction m_textDirection;
151 };
152
153 class NameParser : public ElementParser
154 {
155   public:
156     virtual ActionFunc GetElementParser(const DPL::String& /*ns*/,
157             const DPL::String& /*name*/)
158     {
159         return DPL::MakeDelegate(this, &NameParser::Other);
160     }
161
162     virtual void Accept(const Element& element)
163     {
164         m_lang = element.lang;
165         m_name = L"";
166     }
167
168     virtual void Accept(const Text& text)
169     {
170         if (m_name.IsNull()) {
171             m_name = text.value;
172         } else {
173             *m_name += text.value;
174         }
175     }
176
177     virtual void Accept(const XmlAttribute& attribute)
178     {
179         if (attribute.name == L"short") {
180             if (m_shortName.IsNull()) {
181                 m_shortName = attribute.value;
182             }
183         } else if (attribute.name == L"dir") {
184             m_textDirection = Unicode::ParseDirAttribute(attribute);
185         }
186     }
187
188     virtual void Verify()
189     {
190         ConfigParserData::LocalizedData& data = m_data.localizedDataSet[m_lang];
191         if (data.name.IsNull()) {
192             NormalizeString(m_name);
193             NormalizeString(m_shortName);
194             if (!m_name.IsNull()) {
195                 Unicode::UpdateTextWithDirectionMark(m_textDirection, &*m_name);
196             }
197             data.name = m_name;
198             if (!m_shortName.IsNull()) {
199                 Unicode::UpdateTextWithDirectionMark(m_textDirection,
200                                                      &*m_shortName);
201             }
202             data.shortName = m_shortName;
203         }
204     }
205
206     NameParser(Unicode::Direction direction,
207             ConfigParserData& data) :
208         m_data(data),
209         m_textDirection(direction)
210     {
211     }
212
213     ElementParserPtr Other()
214     {
215         return ElementParserPtr(new InnerElementsParser(
216                                     DPL::StaticPointerCast<ElementParser>(
217                                         SharedFromThis())));
218     }
219
220   private:
221     ConfigParserData& m_data;
222     DPL::OptionalString m_name;
223     DPL::OptionalString m_shortName;
224     DPL::OptionalString m_dir;
225     DPL::String m_lang;
226     Unicode::Direction m_textDirection;
227 };
228
229 class AccessParser : public ElementParser
230 {
231   public:
232     enum StandardType
233     {
234         STANDARD_TYPE_NONE,
235         STANDARD_TYPE_JIL,
236         STANDARD_TYPE_WARP
237     };
238
239     virtual ActionFunc GetElementParser(const DPL::String& /*ns*/,
240             const DPL::String& /*name*/)
241     {
242         return DPL::MakeDelegate(this, &AccessParser::Other);
243     }
244
245     virtual void Accept(const Element& element)
246     {
247         if (element.ns == ConfigurationNamespace::W3CWidgetNamespaceName) {
248             m_standardType = STANDARD_TYPE_WARP;
249         }
250         if (element.ns == ConfigurationNamespace::JilWidgetNamespaceName) {
251             m_standardType = STANDARD_TYPE_JIL;
252         }
253     }
254
255     virtual void Accept(const Text& /*text*/)
256     {
257     }
258
259     void AcceptWac(const XmlAttribute& attribute)
260     {
261         if (attribute.name == L"origin") {
262             m_strIRIOrigin = attribute.value;
263             NormalizeString(m_strIRIOrigin);
264         } else if (attribute.name == L"subdomains") {
265             DPL::String normalizedValue = attribute.value;
266             NormalizeString(normalizedValue);
267
268             if (normalizedValue == L"true") {
269                 m_bSubDomainAccess = true;
270             } else if (normalizedValue == L"false") {
271                 m_bSubDomainAccess = false;
272             }
273         }
274     }
275
276     void AcceptJil(const XmlAttribute& attribute)
277     {
278         if (attribute.name == DPL::FromASCIIString("network")) {
279             if (attribute.value == DPL::FromASCIIString("true")) {
280                 m_network = true;
281             } else {
282                 m_network = false;
283             }
284         }
285     }
286
287     virtual void Accept(const XmlAttribute& attribute)
288     {
289         switch (m_standardType) {
290         case STANDARD_TYPE_WARP:
291             AcceptWac(attribute);
292             break;
293         case STANDARD_TYPE_JIL:
294             AcceptJil(attribute);
295             break;
296         default:
297             LogError("Error in Access tag - unknown standard.");
298         }
299     }
300
301     void VerifyWac()
302     {
303         WarpIRI iri;
304         iri.set(m_strIRIOrigin, false);
305
306         if (!iri.isAccessDefinition()) {
307             LogWarning("Access list element: " <<
308                        m_strIRIOrigin <<
309                        " is not acceptable by WARP" <<
310                        "standard and will be ignored!");
311             return;
312         }
313
314         ConfigParserData::AccessInfo accessInfo(m_strIRIOrigin,
315                                                 m_bSubDomainAccess);
316         std::pair <ConfigParserData::AccessInfoSet::iterator, bool> ret =
317             m_data.accessInfoSet.insert(accessInfo);
318     }
319
320     void VerifyJil()
321     {
322         m_data.accessNetwork = m_network;
323     }
324
325     virtual void Verify()
326     {
327         switch (m_standardType) {
328         case STANDARD_TYPE_WARP:
329             VerifyWac();
330             break;
331         case STANDARD_TYPE_JIL:
332             VerifyJil();
333             break;
334         default:
335             LogError("Error in Access tag - unknown standard.");
336         }
337     }
338
339     AccessParser(ConfigParserData& data) :
340         ElementParser(),
341         m_bSubDomainAccess(false),
342         m_standardType(STANDARD_TYPE_NONE),
343         m_network(false),
344         m_data(data)
345     {
346     }
347
348     ElementParserPtr Other()
349     {
350         return ElementParserPtr(new InnerElementsParser(
351                                     ElementParserPtr(SharedFromThis())));
352     }
353
354   private:
355     DPL::String m_strIRIOrigin;
356     bool m_bSubDomainAccess;
357     StandardType m_standardType;
358     bool m_network;
359     ConfigParserData& m_data;
360 };
361
362 class PkgnameParser : public ElementParser
363 {
364   public:
365     virtual ActionFunc GetElementParser(const DPL::String& /*ns*/,
366             const DPL::String& /*name*/)
367     {
368        return &DenyAllParser::Create;
369     }
370
371     virtual void Accept(const Element& element)
372     {
373         if (element.ns == ConfigurationNamespace::TizenWebAppNamespaceName) {
374             m_properNamespace = true;
375         }
376
377         LogDebug("element pkgname");
378     }
379
380     ElementParserPtr Other()
381     {
382         return ElementParserPtr(new InnerElementsParser(
383                                     DPL::StaticPointerCast<ElementParser>(
384                                         SharedFromThis())));
385     }
386
387     virtual void Accept(const Text& text)
388     {
389         if(m_properNamespace) {
390             m_pkgname = text.value;
391             LogDebug("Pkgname value: " << m_pkgname);
392         }
393     }
394
395     virtual void Accept(const XmlAttribute& attribute)
396     {
397         if (m_properNamespace) {
398             ThrowMsg(Exception::ParseError,
399                      "attirubte: '" + DPL::ToUTF8String(attribute.name) +
400                      "' in pkgname element not allowed");
401         }
402     }
403
404     virtual void Verify()
405     {
406         if (m_properNamespace) {
407             if (m_pkgname.IsNull()) {
408                 ThrowMsg(Exception::ParseError,
409                          "pkgname element must have value");
410             }
411             m_data.pkgname = m_pkgname;
412             LogDebug("Pkgname = " << m_pkgname);
413         }
414     }
415
416     PkgnameParser(ConfigParserData& data) :
417         m_properNamespace(false),
418         m_data(data),
419         m_pkgname()
420     {
421     }
422
423   private:
424     bool m_properNamespace;
425     ConfigParserData& m_data;
426     DPL::OptionalString m_pkgname;
427 };
428
429 class DescriptionParser : public ElementParser
430 {
431   public:
432     virtual ActionFunc GetElementParser(const DPL::String& /*ns*/,
433             const DPL::String& /*name*/)
434     {
435         return DPL::MakeDelegate(this, &DescriptionParser::Other);
436     }
437
438     virtual void Accept(const Element& element)
439     {
440         m_lang = element.lang;
441         m_description = L"";
442     }
443
444     ElementParserPtr Other()
445     {
446         return ElementParserPtr(new InnerElementsParser(
447                                     DPL::StaticPointerCast<ElementParser>(
448                                         SharedFromThis())));
449     }
450
451     virtual void Accept(const Text& text)
452     {
453         if (m_description.IsNull()) {
454             m_description = text.value;
455         } else {
456             *m_description += text.value;
457         }
458     }
459
460     virtual void Accept(const XmlAttribute& attribute)
461     {
462         if (attribute.name == L"dir") {
463             m_textDirection = Unicode::ParseDirAttribute(attribute);
464         }
465     }
466
467     virtual void Verify()
468     {
469         ConfigParserData::LocalizedData& data = m_data.localizedDataSet[m_lang];
470         if (data.description.IsNull()) {
471             if (!m_description.IsNull()) {
472                 Unicode::UpdateTextWithDirectionMark(m_textDirection,
473                                                      &*m_description);
474             }
475             data.description = m_description;
476         }
477     }
478
479     DescriptionParser(Unicode::Direction direction,
480             ConfigParserData& data) :
481         m_data(data),
482         m_lang(),
483         m_description(),
484         m_textDirection(direction)
485     {
486     }
487
488   private:
489     ConfigParserData& m_data;
490     DPL::String m_lang;
491     DPL::OptionalString m_description;
492     Unicode::Direction m_textDirection;
493 };
494
495 class AuthorParser : public ElementParser
496 {
497   public:
498     virtual ActionFunc GetElementParser(const DPL::String& /*ns*/,
499             const DPL::String& /*name*/)
500     {
501         return DPL::MakeDelegate(this, &AuthorParser::Other);
502     }
503
504     AuthorParser(Unicode::Direction direction,
505             ConfigParserData& data) :
506         m_data(data),
507         m_textDirection(direction)
508     {
509     }
510
511     virtual void Accept(const Element& /*element*/)
512     {
513         m_authorName = L"";
514     }
515
516     virtual void Accept(const Text& text)
517     {
518         *(m_authorName) += text.value;
519     }
520
521     virtual void Accept(const XmlAttribute& attribute)
522     {
523         if (attribute.name == L"href") {
524             //Validate href IRI and ignore it if invalid
525             //See also test: ta-argMozRiC-an
526             LibIri::Wrapper iri(DPL::ToUTF8String(attribute.value).c_str());
527             if (iri.Validate()) {
528                 m_authorHref = attribute.value;
529             }
530         } else if (attribute.name == L"email") {
531             m_authorEmail = attribute.value;
532         } else if (attribute.name == L"dir") {
533             m_textDirection = Unicode::ParseDirAttribute(attribute);
534         }
535     }
536
537     virtual void Verify()
538     {
539         if (!m_data.authorName && !m_data.authorHref && !m_data.authorEmail) {
540             NormalizeString(m_authorName);
541             NormalizeString(m_authorHref);
542             NormalizeString(m_authorEmail);
543             if (!!m_authorName) {
544                 Unicode::UpdateTextWithDirectionMark(m_textDirection,
545                                                      &*m_authorName);
546                 m_data.authorName = m_authorName;
547             }
548             if (!!m_authorHref) {
549                 m_data.authorHref = m_authorHref;
550             }
551             if (!!m_authorEmail) {
552                 m_data.authorEmail = m_authorEmail;
553             }
554         }
555     }
556
557     ElementParserPtr Other()
558     {
559         return ElementParserPtr(new InnerElementsParser(
560                                     DPL::StaticPointerCast<ElementParser>(
561                                         SharedFromThis())));
562     }
563
564   private:
565     ConfigParserData& m_data;
566     DPL::OptionalString m_authorEmail;
567     DPL::OptionalString m_authorHref;
568     DPL::OptionalString m_authorName;
569     Unicode::Direction m_textDirection;
570 };
571
572 class LicenseParser : public ElementParser
573 {
574   public:
575     virtual ActionFunc GetElementParser(const DPL::String& /*ns*/,
576             const DPL::String& /*name*/)
577     {
578         return DPL::MakeDelegate(this, &LicenseParser::Other);
579     }
580
581     LicenseParser(Unicode::Direction direction,
582             ConfigParserData& data) :
583         m_data(data),
584         m_ignore(true),
585         m_textDirection(direction)
586     {
587     }
588
589     virtual void Accept(const Element& element)
590     {
591         if (m_license.IsNull()) {
592             m_lang = element.lang;
593             m_license = L"";
594             m_ignore = false;
595         }
596     }
597
598     virtual void Accept(const Text& text)
599     {
600         if (!m_ignore) {
601             *m_license += text.value;
602         }
603     }
604
605     virtual void Accept(const XmlAttribute& attribute)
606     {
607         if (!m_ignore) {
608             if (attribute.name == L"href" && m_licenseHref.IsNull()) {
609                 m_licenseHref = attribute.value;
610             } else if (attribute.name == L"file" && m_licenseFile.IsNull()) {
611                 m_licenseFile = attribute.value;
612             } else if (attribute.name == L"dir") {
613                 m_textDirection = Unicode::ParseDirAttribute(attribute);
614             }
615         }
616     }
617
618     virtual void Verify()
619     {
620         ConfigParserData::LocalizedData& data = m_data.localizedDataSet[m_lang];
621         if (data.license.IsNull()) {
622             if (!m_license.IsNull()) {
623                 Unicode::UpdateTextWithDirectionMark(m_textDirection,
624                                                      &*m_license);
625             }
626             data.license = m_license;
627             data.licenseHref = m_licenseHref;
628             data.licenseFile = m_licenseFile;
629         }
630     }
631
632     ElementParserPtr Other()
633     {
634         return ElementParserPtr(new InnerElementsParser(
635                                     ElementParserPtr(SharedFromThis())));
636     }
637
638   private:
639     ConfigParserData& m_data;
640     DPL::String m_lang;
641     bool m_ignore;
642
643     DPL::OptionalString m_license;
644     DPL::OptionalString m_licenseFile;
645     DPL::OptionalString m_licenseHref;
646     Unicode::Direction m_textDirection;
647 };
648
649 class IconParser : public ElementParser
650 {
651   public:
652     virtual ActionFunc GetElementParser(const DPL::String& /*ns*/,
653             const DPL::String& /*name*/)
654     {
655         return &IgnoringParser::Create;
656     }
657
658     IconParser(ConfigParserData& data) : ElementParser(),
659         m_data(data)
660     {
661     }
662
663     virtual void Accept(const Element& /*element*/)
664     {
665     }
666
667     virtual void Accept(const XmlAttribute& attribute)
668     {
669         if (attribute.name == L"src") {
670             if (attribute.value.size() > 0) {
671                 m_src = attribute.value;
672             }
673         } else if (attribute.name == L"width") {
674             m_width = ParseSizeAttributeValue(attribute.value);
675         } else if (attribute.name == L"height") {
676             m_height = ParseSizeAttributeValue(attribute.value);
677         }
678     }
679
680     virtual void Accept(const Text& /*text*/)
681     {
682         ThrowMsg(Exception::ParseError, "Icon element must be empty");
683     }
684
685     virtual void Verify()
686     {
687         if (m_src.IsNull()) {
688             LogWarning("src attribute of icon element is mandatory - ignoring");
689             return;
690         }
691
692         ConfigParserData::Icon icon(*m_src);
693         icon.width = m_width;
694         icon.height = m_height;
695
696         ConfigParserData::IconsList::iterator it = std::find(
697                 m_data.iconsList.begin(), m_data.iconsList.end(), icon);
698         if (it == m_data.iconsList.end()) {
699             m_data.iconsList.push_front(icon);
700         }
701     }
702
703   private:
704     ConfigParserData& m_data;
705     DPL::OptionalString m_src;
706     DPL::OptionalInt m_width;
707     DPL::OptionalInt m_height;
708
709     static DPL::OptionalInt ParseSizeAttributeValue(const DPL::String& value)
710     {
711         DPL::OptionalString normalizedValue = value;
712         NormalizeString(normalizedValue);
713         if (!(*normalizedValue).empty()) {
714             char* reterr = NULL;
715             errno = 0;
716             long int valueInt =
717                 strtol(DPL::ToUTF8String(value).c_str(), &reterr, 10);
718             if (errno != 0 ||
719                 std::string(reterr) == DPL::ToUTF8String(value) ||
720                 valueInt <= 0) {
721                 return DPL::OptionalInt::Null;
722             } else {
723                 return valueInt;
724             }
725         }
726         return DPL::OptionalInt::Null;
727     }
728 };
729
730 class ContentParser : public ElementParser
731 {
732   public:
733     virtual ActionFunc GetElementParser(const DPL::String& /*ns*/,
734             const DPL::String& /*name*/)
735     {
736         return &IgnoringParser::Create;
737     }
738
739     ContentParser(ConfigParserData& data) :
740         ElementParser(),
741         m_data(data)
742     {
743     }
744
745     virtual void Accept(const Element& /*element*/)
746     {
747     }
748
749     virtual void Accept(const Text& /*text*/)
750     {
751     }
752
753     virtual void Accept(const XmlAttribute& attribute)
754     {
755         DPL::String value = attribute.value;
756         NormalizeString(value);
757
758         if (attribute.name == L"src") {
759             m_src = value;
760         } else if (attribute.name == L"type") {
761             m_type = value;
762             MimeTypeUtils::MimeAttributes mimeAttributes =
763                 MimeTypeUtils::getMimeAttributes(value);
764             if (mimeAttributes.count(L"charset") > 0) {
765                 m_encoding = mimeAttributes[L"charset"];
766             }
767         } else if (attribute.name == L"encoding") {
768             if (!value.empty()) {
769                 m_encoding = value;
770             }
771         }
772     }
773
774     virtual void Verify()
775     {
776         if (m_data.startFileEncountered) {
777             LogWarning("This is not the first encountered "
778                        "'content' element - ignoring.");
779             return;
780         }
781
782         m_data.startFileEncountered = true;
783
784         //we're consciously setting startFile even if m_src is null or invalid.
785         //WidgetConfigurationManager will deal with this.
786         m_data.startFile = m_src;
787
788         if (!!m_src) {
789             m_data.startFileContentType = m_type;
790             if (!!m_encoding && ewk_text_encoding_is_valid(
791                     DPL::ToUTF8String(*m_encoding).c_str())) {
792                 m_data.startFileEncoding = m_encoding;
793             } else {
794                 m_data.startFileEncoding = L"UTF-8";
795             }
796         }
797     }
798
799   private:
800     DPL::OptionalString m_src;
801     DPL::OptionalString m_type;
802     DPL::OptionalString m_encoding;
803     ConfigParserData& m_data;
804 };
805
806 class FeatureParser : public ElementParser
807 {
808   public:
809     struct ParamParser : public ElementParser
810     {
811         virtual ActionFunc GetElementParser(const DPL::String& /*ns*/,
812                 const DPL::String& /*name*/)
813         {
814             return &IgnoringParser::Create;
815         }
816
817         virtual void Accept(const XmlAttribute& attribute)
818         {
819             if (attribute.name == L"name") {
820                 m_name = attribute.value;
821                 NormalizeString(m_name);
822             } else if (attribute.name == L"value") {
823                 m_value = attribute.value;
824                 NormalizeString(m_value);
825             }
826         }
827
828         virtual void Accept(const Element& /*element*/)
829         {
830         }
831
832         virtual void Accept(const Text& /*text*/)
833         {
834             ThrowMsg(Exception::ParseError, "param element must be empty");
835         }
836
837         virtual void Verify()
838         {
839             if (m_name.IsNull() || *m_name == L"") {
840                 return;
841             }
842             if (m_value.IsNull() || *m_value == L"") {
843                 return;
844             }
845
846             ConfigParserData::Param param(*m_name);
847             param.value = *m_value;
848
849             if (m_data.paramsList.find(param) == m_data.paramsList.end()) {
850                 m_data.paramsList.insert(param);
851             }
852         }
853
854         ParamParser(ConfigParserData::Feature& data) :
855             ElementParser(),
856             m_data(data)
857         {
858         }
859
860       private:
861         DPL::OptionalString m_name;
862         DPL::OptionalString m_value;
863         ConfigParserData::Feature& m_data;
864     };
865
866     virtual ActionFunc GetElementParser(const DPL::String& /*ns*/,
867             const DPL::String& name)
868     {
869         if (name == L"param") {
870             return DPL::MakeDelegate(this, &FeatureParser::OnParamElement);
871         } else {
872             return &IgnoringParser::Create;
873         }
874     }
875
876     virtual void Accept(const Text& /*text*/)
877     {
878     }
879
880     virtual void Accept(const Element& /*element*/)
881     {
882     }
883
884     virtual void Accept(const XmlAttribute& attribute)
885     {
886         if (attribute.name == L"name") {
887             m_feature.name = attribute.value;
888         } else if (attribute.name == L"required") {
889             if (attribute.value == L"false") {
890                 m_feature.required = false;
891             } else {
892                 m_feature.required = true;
893             }
894         }
895     }
896
897     virtual void Verify()
898     {
899         LibIri::Wrapper iri(DPL::ToUTF8String(m_feature.name).c_str());
900
901         if (m_feature.name != L"") {
902             if (iri.Validate()) {
903                 if (m_data.featuresList.find(m_feature) ==
904                     m_data.featuresList.end()) {
905                     m_data.featuresList.insert(m_feature);
906                 } else {
907                     LogDebug("Ignoring feature with name" <<
908                              DPL::ToUTF8String(m_feature.name));
909                 }
910             } else {
911                 if (m_feature.required) {
912                     //Throw only if required
913                     ThrowMsg(Exception::ParseError, "invalid feature IRI");
914                 }
915             }
916         }
917     }
918
919     ElementParserPtr OnParamElement()
920     {
921         return ElementParserPtr(new ParamParser(m_feature));
922     }
923
924     FeatureParser(ConfigParserData& data) :
925         ElementParser(),
926         m_data(data),
927         m_feature(L"")
928     {
929     }
930
931   private:
932     ConfigParserData& m_data;
933     ConfigParserData::Feature m_feature;
934 };
935
936 class PreferenceParser : public ElementParser
937 {
938   public:
939     virtual ActionFunc GetElementParser(const DPL::String& /*ns*/,
940             const DPL::String& /*name*/)
941     {
942         return &IgnoringParser::Create;
943     }
944
945     virtual void Accept(const XmlAttribute& attribute)
946     {
947         if (attribute.name == L"name") {
948             m_name = attribute.value;
949         } else if (attribute.name == L"value") {
950             m_value = attribute.value;
951         } else if (attribute.name == L"readonly") {
952             if (attribute.value == L"true") {
953                 m_required = true;
954             } else {
955                 m_required = false;
956             }
957         }
958     }
959
960     virtual void Accept(const Element& /*element*/)
961     {
962     }
963
964     virtual void Accept(const Text& /*text*/)
965     {
966         ThrowMsg(Exception::ParseError, "param element must be empty");
967     }
968
969     virtual void Verify()
970     {
971         if (m_name.IsNull()) {
972             LogWarning("preference element must have name attribute");
973             return;
974         }
975         NormalizeString(m_name);
976         NormalizeString(m_value);
977         ConfigParserData::Preference preference(*m_name, m_required);
978         preference.value = m_value;
979         if (m_data.preferencesList.find(preference) ==
980             m_data.preferencesList.end()) {
981             m_data.preferencesList.insert(preference);
982         }
983     }
984
985     PreferenceParser(ConfigParserData& data) :
986         ElementParser(),
987         m_required(false),
988         m_data(data)
989     {
990     }
991
992   private:
993     DPL::OptionalString m_name;
994     DPL::OptionalString m_value;
995     bool m_required;
996     ConfigParserData& m_data;
997 };
998
999 class FlashParser : public ElementParser
1000 {
1001   public:
1002     virtual ActionFunc GetElementParser(const DPL::String& /*ns*/,
1003             const DPL::String& /*name*/)
1004     {
1005         return &IgnoringParser::Create;
1006     }
1007
1008     virtual void Accept(const XmlAttribute& attribute)
1009     {
1010         if (attribute.name == L"needed") {
1011             if (attribute.value == L"true") {
1012                 m_flashNeeded = true;
1013             } else {
1014                 m_flashNeeded = false;
1015             }
1016         }
1017     }
1018
1019     virtual void Accept(const Element& /*element*/)
1020     {
1021         //if empty flash element will be passed, we say true
1022         m_data.flashNeeded = true;
1023     }
1024
1025     virtual void Accept(const Text& /*text*/)
1026     {
1027         ThrowMsg(Exception::ParseError, "flash element must be empty");
1028     }
1029
1030     virtual void Verify()
1031     {
1032         m_data.flashNeeded = m_flashNeeded;
1033     }
1034
1035     FlashParser(ConfigParserData& data) :
1036         ElementParser(),
1037         m_flashNeeded(false),
1038         m_data(data)
1039     {
1040     }
1041
1042   private:
1043     bool m_flashNeeded;
1044     ConfigParserData& m_data;
1045 };
1046
1047 class LinkParser : public ElementParser
1048 {
1049   public:
1050     virtual ActionFunc GetElementParser(const DPL::String& /*ns*/,
1051             const DPL::String& /*name*/)
1052     {
1053         return &DenyAllParser::Create;
1054     }
1055
1056     virtual void Accept(const XmlAttribute& attribute)
1057     {
1058         if (m_properNamespace) {
1059             LogDebug("attribute");
1060             if (attribute.name == L"rel") {
1061                 if (attribute.value != L"describedby") {
1062                     ThrowMsg(Exception::ParseError,
1063                              "rel attribute must have describedby value");
1064                 }
1065             } else if (attribute.name == L"type") {
1066             } else if (attribute.name == L"href") {
1067                 LogDebug("here is href");
1068                 m_href = attribute.value;
1069             } else {
1070                 ThrowMsg(Exception::ParseError,
1071                          "unknown attribute '" +
1072                          DPL::ToUTF8String(attribute.name) +
1073                          "' in link element");
1074             }
1075         }
1076     }
1077
1078     virtual void Accept(const Element& element)
1079     {
1080         if (element.ns ==
1081             ConfigurationNamespace::WacWidgetNamespaceNameForLinkElement)
1082         {
1083             m_properNamespace = true;
1084         }
1085         LogDebug("element");
1086     }
1087
1088     virtual void Accept(const Text&)
1089     {
1090         if (m_properNamespace) {
1091             LogDebug("text");
1092             ThrowMsg(Exception::ParseError, "link element must be empty");
1093         }
1094     }
1095
1096     virtual void Verify()
1097     {
1098         if (!m_href) {
1099             ThrowMsg(Exception::ParseError,
1100                      "link element must have href attribute");
1101         }
1102
1103         LibIri::Wrapper iri(DPL::ToUTF8String(*m_href).c_str());
1104         if (!iri.Validate()) { // TODO: Better uri validator ?
1105             ThrowMsg(Exception::ParseError,
1106                      "href attribute must be a valid iri/uri/url");
1107         }
1108
1109         m_data.powderDescriptionLinks.insert(*m_href);
1110     }
1111
1112     LinkParser(ConfigParserData& data) :
1113         ElementParser(),
1114         m_properNamespace(false),
1115         m_data(data),
1116         m_href(DPL::OptionalString::Null)
1117     {
1118     }
1119
1120   private:
1121     bool m_properNamespace;
1122     ConfigParserData& m_data;
1123     DPL::OptionalString m_href;
1124 };
1125
1126 class MinVersionParser : public ElementParser
1127 {
1128   public:
1129     virtual ActionFunc GetElementParser(const DPL::String& /*ns*/,
1130             const DPL::String& /*name*/)
1131     {
1132         return &DenyAllParser::Create;
1133     }
1134
1135     virtual void Accept(const XmlAttribute& attribute)
1136     {
1137         if (m_properNamespace) {
1138             ThrowMsg(Exception::ParseError,
1139                      "attirubte: '" + DPL::ToUTF8String(attribute.name) +
1140                      "' in min-version element not allowed");
1141         }
1142     }
1143
1144     virtual void Accept(const Element& element)
1145     {
1146         if (element.ns == ConfigurationNamespace::WacWidgetNamespaceName) {
1147             m_properNamespace = true;
1148         }
1149
1150         LogDebug("element min-version");
1151     }
1152
1153     virtual void Accept(const Text& text)
1154     {
1155         if (m_properNamespace) {
1156             m_minVersion = text.value;
1157             LogDebug("min-version value: " << m_minVersion);
1158         }
1159     }
1160
1161     virtual void Verify()
1162     {
1163         if (m_properNamespace) {
1164             if (m_minVersion.IsNull()) {
1165                 ThrowMsg(Exception::ParseError,
1166                          "min-version element must have value");
1167             }
1168
1169             DPL::OptionalFloat version = ParseMinVersion(*m_minVersion);
1170             if (version.IsNull()) {
1171                 ThrowMsg(Exception::ParseError,
1172                          "min-version element must have value"
1173                          " that can be parsed to float");
1174             }
1175
1176             if (m_data.minVersionRequiredFound.IsNull()) {
1177                 m_data.minVersionRequiredFound = 1;
1178                 m_data.minVersionRequired = version;
1179                 LogDebug("MinVersionRequired = " << version);
1180             } else {
1181                 ThrowMsg(Exception::ParseError,
1182                          "multiple min-version elements not allowed");
1183             }
1184         }
1185     }
1186
1187     MinVersionParser(ConfigParserData& data) :
1188         ElementParser(),
1189         m_properNamespace(false),
1190         m_data(data),
1191         m_minVersion()
1192     {
1193         LogDebug("MinVersionParser created");
1194     }
1195
1196   private:
1197     bool m_properNamespace;
1198     ConfigParserData& m_data;
1199     DPL::OptionalString m_minVersion;
1200
1201     static DPL::OptionalFloat ParseMinVersion(const DPL::String& value)
1202     {
1203         DPL::OptionalString normalizedValue = value;
1204         NormalizeString(normalizedValue);
1205         if (!(*normalizedValue).empty()) {
1206             char* reterr = NULL;
1207             errno = 0;
1208             float valueFloat =
1209                 strtof(DPL::ToUTF8String(value).c_str(), &reterr);
1210             if (errno != 0 ||
1211                 std::string(reterr) == DPL::ToUTF8String(value) ||
1212                 valueFloat <= 0.0) {
1213                 return DPL::OptionalFloat::Null;
1214             } else {
1215                 return valueFloat;
1216             }
1217         }
1218         return DPL::OptionalFloat::Null;
1219     }
1220 };
1221
1222 // tag: <back supported=true>
1223 class BackParser : public ElementParser
1224 {
1225   public:
1226     virtual ActionFunc GetElementParser(const DPL::String& /*ns*/,
1227             const DPL::String& /*name*/)
1228     {
1229         return &IgnoringParser::Create;
1230     }
1231
1232     virtual void Accept(const XmlAttribute& attribute)
1233     {
1234         LogDebug("attribute");
1235         if (attribute.name == L"supported") {
1236             if (attribute.value == L"true") {
1237                 m_backSupported = true;
1238             } else {
1239                 m_backSupported = false;
1240             }
1241         }
1242     }
1243
1244     virtual void Accept(const Element&)
1245     {
1246         LogDebug("element");
1247         //if empty back element will be passed, we say true
1248         m_data.backSupported = true;
1249     }
1250
1251     virtual void Accept(const Text&)
1252     {
1253         LogDebug("text");
1254         ThrowMsg(Exception::ParseError, "back element must be empty");
1255     }
1256
1257     virtual void Verify()
1258     {
1259         m_data.backSupported = m_backSupported;
1260     }
1261
1262     BackParser(ConfigParserData& data) :
1263         ElementParser(),
1264         m_backSupported(false),
1265         m_data(data)
1266     {
1267     }
1268
1269   private:
1270     bool m_backSupported;
1271     ConfigParserData& m_data;
1272 };
1273
1274 class SettingParser : public ElementParser
1275 {
1276   public:
1277     virtual ActionFunc GetElementParser(const DPL::String& /*ns*/,
1278             const DPL::String& /*name*/)
1279     {
1280         return &IgnoringParser::Create;
1281     }
1282
1283     virtual void Accept(const Text& /*text*/)
1284     {
1285     }
1286
1287     virtual void Accept(const Element& /*element*/)
1288     {
1289     }
1290
1291     virtual void Accept(const XmlAttribute& attribute)
1292     {
1293         m_setting.m_name = attribute.name;
1294         m_setting.m_value = attribute.value;
1295         m_data.settingsList.insert(m_setting);
1296     }
1297
1298     virtual void Verify()
1299     {
1300     }
1301
1302     SettingParser(ConfigParserData& data) :
1303         ElementParser(),
1304         m_data(data),
1305         m_setting(L"", L"")
1306     {
1307     }
1308
1309   private:
1310     ConfigParserData& m_data;
1311     ConfigParserData::Setting m_setting;
1312 };
1313
1314 class ServiceParser : public ElementParser
1315 {
1316   public:
1317     virtual ActionFunc GetElementParser(const DPL::String& /*ns*/,
1318                                         const DPL::String& /*name*/)
1319     {
1320         return &IgnoringParser::Create;
1321     }
1322
1323     virtual void Accept(const XmlAttribute& attribute)
1324     {
1325         if (attribute.name == L"src") {
1326             m_src = attribute.value;
1327         } else if (attribute.name == L"operation") {
1328             m_operation = attribute.value;
1329         } else if (attribute.name == L"scheme") {
1330             m_scheme = attribute.value;
1331         } else if (attribute.name == L"mime") {
1332             m_mime = attribute.value;
1333         }
1334     }
1335
1336     virtual void Accept(const Element& element)
1337     {
1338         LogWarning("namespace for app service = " << element.ns);
1339         if (element.ns == ConfigurationNamespace::W3CWidgetNamespaceName) {
1340             ThrowMsg(Exception::ParseError,
1341                 "Wrong xml namespace for widget element");
1342         }
1343     }
1344
1345     virtual void Accept(const Text& /*text*/)
1346     {
1347         ThrowMsg(Exception::ParseError, "param element must be empty");
1348     }
1349
1350     virtual void Verify()
1351     {
1352         if (m_src.IsNull()) {
1353             LogWarning("service element must have target attribute");
1354             return;
1355         } else if (m_operation.IsNull()) {
1356             LogWarning("service element must have operation attribute");
1357             return;
1358         }
1359         NormalizeString(m_src);
1360         NormalizeString(m_operation);
1361         NormalizeString(m_scheme);
1362         NormalizeString(m_mime);
1363
1364         // verify duplicate element
1365         DPL::String wildString(L"*/*");
1366         DPL::String nullString(L"");
1367         ConfigParserData::ServiceInfo serviceInfo(
1368             m_src.IsNull()       ? nullString:*m_src,
1369             m_operation.IsNull() ? nullString:*m_operation,
1370             m_scheme.IsNull()    ? nullString:*m_scheme,
1371             m_mime.IsNull()      ? nullString:*m_mime);
1372
1373         FOREACH(iterator, m_data.appServiceList) {
1374             if (iterator->m_operation == serviceInfo.m_operation &&
1375                 // check scheme
1376                 (iterator->m_scheme == serviceInfo.m_scheme ||
1377                 // check input scheme is "*/*" case
1378                 (iterator->m_scheme == wildString &&
1379                  serviceInfo.m_scheme != nullString) ||
1380                 // check iterator scheme is "*/*" case
1381                 (serviceInfo.m_scheme == wildString &&
1382                  iterator->m_scheme != nullString)) &&
1383
1384                 (iterator->m_mime == serviceInfo.m_mime ||
1385                 // check input mime is "*/*" case
1386                 (iterator->m_mime == wildString &&
1387                  serviceInfo.m_mime != nullString) ||
1388                 // check iterator mime is "*/*" case
1389                 (serviceInfo.m_mime == wildString &&
1390                  iterator->m_mime != nullString)))
1391             {
1392                 ThrowMsg(Exception::ParseError,
1393                     "service operation is duplicated " +
1394                     DPL::ToUTF8String(*m_operation));
1395             }
1396         }
1397         m_data.appServiceList.push_back(serviceInfo);
1398     }
1399
1400     ServiceParser(ConfigParserData& data) :
1401         ElementParser(),
1402         m_src(DPL::OptionalString::Null),
1403         m_operation(DPL::OptionalString::Null),
1404         m_scheme(DPL::OptionalString::Null),
1405         m_mime(DPL::OptionalString::Null),
1406         m_data(data)
1407     {
1408     }
1409
1410   private:
1411     DPL::OptionalString m_src;
1412     DPL::OptionalString m_operation;
1413     DPL::OptionalString m_scheme;
1414     DPL::OptionalString m_mime;
1415     ConfigParserData& m_data;
1416 };
1417
1418 ElementParser::ActionFunc WidgetParser::GetElementParser(const DPL::String& /*ns*/,
1419         const DPL::String& name)
1420 {
1421     FuncMap::const_iterator it = m_map.find(name);
1422     if (it != m_map.end()) {
1423         return it->second;
1424     } else {
1425         return &IgnoringParser::Create;
1426     }
1427 }
1428
1429 WidgetParser::WidgetParser(ConfigParserData& data) :
1430     m_data(data),
1431     m_textDirection(Unicode::EMPTY)
1432 {
1433     m_map[L"name"] = DPL::MakeDelegate(this, &WidgetParser::OnNameElement);
1434     m_map[L"access"] = DPL::MakeDelegate(this, &WidgetParser::OnAccessElement);
1435     m_map[L"description"] =
1436         DPL::MakeDelegate(this, &WidgetParser::OnDescriptionElement);
1437     m_map[L"author"] = DPL::MakeDelegate(this, &WidgetParser::OnAuthorElement);
1438     m_map[L"license"] =
1439         DPL::MakeDelegate(this, &WidgetParser::OnLicenseElement);
1440     m_map[L"icon"] = DPL::MakeDelegate(this, &WidgetParser::OnIconElement);
1441     m_map[L"content"] =
1442         DPL::MakeDelegate(this, &WidgetParser::OnContentElement);
1443     m_map[L"feature"] =
1444         DPL::MakeDelegate(this, &WidgetParser::OnFeatureElement);
1445     m_map[L"preference"] =
1446         DPL::MakeDelegate(this, &WidgetParser::OnPreferenceElement);
1447     m_map[L"flash"] = DPL::MakeDelegate(this, &WidgetParser::OnFlashElement);
1448     m_map[L"link"] = DPL::MakeDelegate(this, &WidgetParser::OnLinkElement);
1449     m_map[L"min-version"] =
1450         DPL::MakeDelegate(this, &WidgetParser::OnMinVersionElement);
1451     m_map[L"back"] = DPL::MakeDelegate(this, &WidgetParser::OnBackElement);
1452     m_map[L"pkgname"] = DPL::MakeDelegate(this, &WidgetParser::OnPkgnameElement);
1453     m_map[L"setting"] =
1454         DPL::MakeDelegate(this, &WidgetParser::OnSettingElement);
1455     m_map[L"appservice"] = DPL::MakeDelegate(this, &WidgetParser::OnServiceElement);
1456 }
1457
1458 ElementParserPtr WidgetParser::OnNameElement()
1459 {
1460     return ElementParserPtr(new NameParser(m_textDirection, m_data));
1461 }
1462
1463 ElementParserPtr WidgetParser::OnAccessElement()
1464 {
1465     return ElementParserPtr(new AccessParser(m_data));
1466 }
1467
1468 ElementParserPtr WidgetParser::OnDescriptionElement()
1469 {
1470     return ElementParserPtr(new DescriptionParser(m_textDirection, m_data));
1471 }
1472
1473 ElementParserPtr WidgetParser::OnAuthorElement()
1474 {
1475     return ElementParserPtr(new AuthorParser(m_textDirection, m_data));
1476 }
1477
1478 ElementParserPtr WidgetParser::OnLicenseElement()
1479 {
1480     return ElementParserPtr(new LicenseParser(m_textDirection, m_data));
1481 }
1482
1483 ElementParserPtr WidgetParser::OnIconElement()
1484 {
1485     return ElementParserPtr(new IconParser(m_data));
1486 }
1487
1488 ElementParserPtr WidgetParser::OnContentElement()
1489 {
1490     return ElementParserPtr(new ContentParser(m_data));
1491 }
1492
1493 ElementParserPtr WidgetParser::OnFeatureElement()
1494 {
1495     return ElementParserPtr(new FeatureParser(m_data));
1496 }
1497
1498 ElementParserPtr WidgetParser::OnPreferenceElement()
1499 {
1500     return ElementParserPtr(new PreferenceParser(m_data));
1501 }
1502
1503 ElementParserPtr WidgetParser::OnFlashElement()
1504 {
1505     return ElementParserPtr(new FlashParser(m_data));
1506 }
1507
1508 ElementParserPtr WidgetParser::OnLinkElement()
1509 {
1510     return ElementParserPtr(new LinkParser(m_data));
1511 }
1512
1513 ElementParserPtr WidgetParser::OnMinVersionElement()
1514 {
1515     return ElementParserPtr(new MinVersionParser(m_data));
1516 }
1517
1518 ElementParserPtr WidgetParser::OnBackElement()
1519 {
1520     return ElementParserPtr(new BackParser(m_data));
1521 }
1522
1523 ElementParserPtr WidgetParser::OnPkgnameElement()
1524 {
1525     return ElementParserPtr(new PkgnameParser(m_data));
1526 }
1527
1528 ElementParserPtr WidgetParser::OnSettingElement()
1529 {
1530     return ElementParserPtr(new SettingParser(m_data));
1531 }
1532
1533 ElementParserPtr WidgetParser::OnServiceElement()
1534 {
1535     return ElementParserPtr(new ServiceParser(m_data));
1536 }
1537
1538 void WidgetParser::Accept(const Element& element)
1539 {
1540     if (element.ns != ConfigurationNamespace::W3CWidgetNamespaceName) {
1541         ThrowMsg(Exception::ParseError,
1542                  "Wrong xml namespace for widget element");
1543     }
1544 }
1545
1546 void WidgetParser::Accept(const Text& /*text*/)
1547 {
1548     ThrowMsg(Exception::ParseError, "widged element must be empty");
1549 }
1550
1551 void WidgetParser::Accept(const XmlAttribute& attribute)
1552 {
1553     if (attribute.name == L"id") {
1554         LibIri::Wrapper iri(DPL::ToUTF8String(attribute.value).c_str());
1555         //If may important tests starts to fail this test we will have
1556         //to consider commenting this test out again.
1557         if (iri.Validate()) {
1558             m_data.widget_id = attribute.value;
1559             NormalizeString(m_data.widget_id);
1560         }
1561     } else if (attribute.name == L"version") {
1562         m_version = attribute.value;
1563         NormalizeString(m_version);
1564     } else if (attribute.name == L"height") {
1565         DPL::OptionalString value = attribute.value;
1566         NormalizeString(value);
1567         std::string v = DPL::ToUTF8String(*value);
1568
1569         if (!v.empty()) {
1570             unsigned char c = v.c_str()[0];
1571             if (c >= '0' && c <= '9') {
1572                 int val = 0;
1573                 for (size_t i = 0; i < v.size(); ++i) {
1574                     c = v.c_str()[i];
1575                     if (c >= '0' && c <= '9') {
1576                         val *= 10;
1577                         val += (c - '0');
1578                     } else {
1579                         break;
1580                     }
1581                 }
1582                 m_data.height = val;
1583             }
1584         }
1585     } else if (attribute.name == L"width") {
1586         DPL::OptionalString value = attribute.value;
1587         NormalizeString(value);
1588         std::string v = DPL::ToUTF8String(*value);
1589
1590         if (!v.empty()) {
1591             unsigned char c = v.c_str()[0];
1592             if (c >= '0' && c <= '9') {
1593                 int val = 0;
1594                 for (size_t i = 0; i < v.size(); ++i) {
1595                     c = v.c_str()[i];
1596                     if (c >= '0' && c <= '9') {
1597                         val *= 10;
1598                         val += (c - '0');
1599                     } else {
1600                         break;
1601                     }
1602                 }
1603                 m_data.width = val;
1604             }
1605         }
1606     } else if (attribute.name == L"viewmodes") {
1607         DPL::Tokenize(attribute.value,
1608                       L" ",
1609                       std::inserter(m_windowModes,
1610                                     m_windowModes.end()),
1611                       true);
1612     } else if (attribute.name == L"dir") {
1613         m_textDirection = Unicode::ParseDirAttribute(attribute);
1614     } else if (L"defaultlocale" == attribute.name) {
1615         if (!m_defaultlocale) {
1616             m_defaultlocale = attribute.value;
1617             NormalizeString(m_defaultlocale);
1618             if (!LanguageSubtagRstTreeSingleton::Instance().ValidateLanguageTag(
1619                     DPL::ToUTF8String(*m_defaultlocale))) {
1620                 LogWarning("Language tag: " <<
1621                            m_defaultlocale << " is not valid");
1622                 m_defaultlocale = DPL::OptionalString::Null;
1623             }
1624             else
1625                 LogDebug("Default Locale Found " << m_defaultlocale);
1626         } else {
1627             LogWarning("Ignoring subsequent default locale");
1628         }
1629     } else if (DPL::StringCompare(L"xmlns", attribute.name) < 0) {
1630         LogWarning("namespace domain" << attribute.name);
1631         LogWarning("namespace value  " << attribute.value);
1632         DPL::OptionalString ns = attribute.value;
1633
1634         if (attribute.name == L"xmlns:wac") {
1635             m_nameSpaces.push_back(attribute.value);
1636         } else if (attribute.name == L"xmlns:tizen") {
1637             m_nameSpaces.push_back(attribute.value);
1638         } else if (attribute.name == L"xmlns:jil") {
1639             m_nameSpaces.push_back(attribute.value);
1640         }
1641     }
1642 }
1643
1644 void WidgetParser::Verify()
1645 {
1646     FOREACH(mode, m_windowModes) {
1647         if (L"windowed" == *mode || L"floating" == *mode ||
1648             L"fullscreen" == *mode || L"maximized" == *mode ||
1649             L"minimized" == *mode) {
1650             m_data.windowModes.insert(*mode);
1651         }
1652     }
1653     if (!m_version.IsNull()) {
1654         Unicode::UpdateTextWithDirectionMark(m_textDirection, &*m_version);
1655         m_data.version = m_version;
1656     }
1657     m_data.defaultlocale = m_defaultlocale;
1658     FOREACH(ns, m_nameSpaces) {
1659         m_data.nameSpaces.insert(*ns);
1660     }
1661 }
1662