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