1# This Source Code Form is subject to the terms of the Mozilla Public
2# License, v. 2.0. If a copy of the MPL was not distributed with this file,
3# You can obtain one at http://mozilla.org/MPL/2.0/.
4
5# -----------------
6# DEPRECATED module
7# -----------------
8# Replace its use in tests when Firefox 45 ESR support ends with
9# marionette_driver.localization.L10n
10
11from __future__ import absolute_import
12
13import copy
14
15from marionette_driver.errors import (
16    NoSuchElementException,
17    UnknownCommandException,
18)
19from marionette_driver.localization import L10n as L10nMarionette
20
21from firefox_puppeteer.base import BaseLib
22
23
24class L10n(BaseLib):
25    """An API which allows Marionette to handle localized content.
26
27    .. deprecated:: 52.2.0
28       Use the localization module from :py:mod:`marionette_driver` instead.
29
30    The `localization`_ of UI elements in Gecko based applications is done via
31    entities and properties. For static values entities are used, which are located
32    in .dtd files. Whereby for dynamically updated content the values come from
33    .property files. Both types of elements can be identifed via a unique id,
34    and the translated content retrieved.
35
36    .. _localization: https://mzl.la/2eUMjyF
37    """
38
39    def __init__(self, marionette):
40        super(L10n, self).__init__(marionette)
41
42        self._l10nMarionette = L10nMarionette(self.marionette)
43
44    def localize_entity(self, dtd_urls, entity_id):
45        """Returns the localized string for the specified DTD entity id.
46
47        To find the entity all given DTD files will be searched for the id.
48
49        :param dtd_urls: A list of dtd files to search.
50        :param entity_id: The id to retrieve the value from.
51
52        :returns: The localized string for the requested entity.
53
54        :raises NoSuchElementException: When entity id is not found in dtd_urls.
55        """
56        # Add xhtml11.dtd to prevent missing entity errors with XHTML files
57        try:
58            return self._l10nMarionette.localize_entity(dtd_urls, entity_id)
59        except UnknownCommandException:
60            dtds = copy.copy(dtd_urls)
61            dtds.append("resource:///res/dtd/xhtml11.dtd")
62
63            dtd_refs = ''
64            for index, item in enumerate(dtds):
65                dtd_id = 'dtd_%s' % index
66                dtd_refs += '<!ENTITY %% %s SYSTEM "%s">%%%s;' % \
67                    (dtd_id, item, dtd_id)
68
69            contents = """<?xml version="1.0"?>
70                <!DOCTYPE elem [%s]>
71
72                <elem id="entity">&%s;</elem>""" % (dtd_refs, entity_id)
73
74            with self.marionette.using_context('chrome'):
75                value = self.marionette.execute_script("""
76                    var parser = Components.classes["@mozilla.org/xmlextras/domparser;1"]
77                                 .createInstance(Components.interfaces.nsIDOMParser);
78                    var doc = parser.parseFromString(arguments[0], "text/xml");
79                    var node = doc.querySelector("elem[id='entity']");
80
81                    return node ? node.textContent : null;
82                """, script_args=[contents])
83
84            if not value:
85                raise NoSuchElementException('DTD Entity not found: %s' % entity_id)
86
87            return value
88
89    def localize_property(self, property_urls, property_id):
90        """Returns the localized string for the specified property id.
91
92        To find the property all given property files will be searched for
93        the id.
94
95        :param property_urls: A list of property files to search.
96        :param property_id: The id to retrieve the value from.
97
98        :returns: The localized string for the requested entity.
99
100        :raises NoSuchElementException: When property id is not found in
101            property_urls.
102        """
103        try:
104            return self._l10nMarionette.localize_property(property_urls, property_id)
105        except UnknownCommandException:
106            with self.marionette.using_context('chrome'):
107                value = self.marionette.execute_script("""
108                    let property = null;
109                    let property_id = arguments[1];
110
111                    arguments[0].some(aUrl => {
112                      let bundle = Services.strings.createBundle(aUrl);
113
114                      try {
115                        property = bundle.GetStringFromName(property_id);
116                        return true;
117                      }
118                      catch (ex) { }
119                    });
120
121                    return property;
122                """, script_args=[property_urls, property_id])
123
124            if not value:
125                raise NoSuchElementException('Property not found: %s' % property_id)
126
127            return value
128