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