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