intl/strres/src/nsStringBundleTextOverride.cpp

changeset 0
6474c204b198
equal deleted inserted replaced
-1:000000000000 0:27565335adea
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /* This Source Code Form is subject to the terms of the Mozilla Public
3 * License, v. 2.0. If a copy of the MPL was not distributed with this
4 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
5
6
7 #include "nsStringBundleTextOverride.h"
8 #include "nsString.h"
9
10 #include "nsNetUtil.h"
11 #include "nsAppDirectoryServiceDefs.h"
12
13 // first we need a simple class which wraps a nsIPropertyElement and
14 // cuts out the leading URL from the key
15 class URLPropertyElement : public nsIPropertyElement
16 {
17 public:
18 URLPropertyElement(nsIPropertyElement *aRealElement, uint32_t aURLLength) :
19 mRealElement(aRealElement),
20 mURLLength(aURLLength)
21 { }
22 virtual ~URLPropertyElement() {}
23
24 NS_DECL_ISUPPORTS
25 NS_DECL_NSIPROPERTYELEMENT
26
27 private:
28 nsCOMPtr<nsIPropertyElement> mRealElement;
29 uint32_t mURLLength;
30 };
31
32 NS_IMPL_ISUPPORTS(URLPropertyElement, nsIPropertyElement)
33
34 // we'll tweak the key on the way through, and remove the url prefix
35 NS_IMETHODIMP
36 URLPropertyElement::GetKey(nsACString& aKey)
37 {
38 nsresult rv = mRealElement->GetKey(aKey);
39 if (NS_FAILED(rv)) return rv;
40
41 // chop off the url
42 aKey.Cut(0, mURLLength);
43
44 return NS_OK;
45 }
46
47 // values are unaffected
48 NS_IMETHODIMP
49 URLPropertyElement::GetValue(nsAString& aValue)
50 {
51 return mRealElement->GetValue(aValue);
52 }
53
54 // setters are kind of strange, hopefully we'll never be called
55 NS_IMETHODIMP
56 URLPropertyElement::SetKey(const nsACString& aKey)
57 {
58 // this is just wrong - ideally you'd take the key, append it to
59 // the url, and set that as the key. However, that would require
60 // us to hold onto a copy of the string, and that's a waste,
61 // considering nobody should ever be calling this.
62 NS_ERROR("This makes no sense!");
63 return NS_ERROR_NOT_IMPLEMENTED;
64 }
65
66 NS_IMETHODIMP
67 URLPropertyElement::SetValue(const nsAString& aValue)
68 {
69 return mRealElement->SetValue(aValue);
70 }
71
72
73 // this is a special enumerator which returns only the elements which
74 // are prefixed with a particular url
75 class nsPropertyEnumeratorByURL : public nsISimpleEnumerator
76 {
77 public:
78 nsPropertyEnumeratorByURL(const nsACString& aURL,
79 nsISimpleEnumerator* aOuter) :
80 mOuter(aOuter),
81 mURL(aURL)
82 {
83 // prepare the url once so we can use its value later
84 // persistent properties uses ":" as a delimiter, so escape
85 // that character
86 mURL.ReplaceSubstring(":", "%3A");
87 // there is always a # between the url and the real key
88 mURL.Append('#');
89 }
90
91 NS_DECL_ISUPPORTS
92 NS_DECL_NSISIMPLEENUMERATOR
93
94 virtual ~nsPropertyEnumeratorByURL() {}
95 private:
96
97 // actual enumerator of all strings from nsIProperties
98 nsCOMPtr<nsISimpleEnumerator> mOuter;
99
100 // the current element that is valid for this url
101 nsCOMPtr<nsIPropertyElement> mCurrent;
102
103 // the url in question, pre-escaped and with the # already in it
104 nsCString mURL;
105 };
106
107 //
108 // nsStringBundleTextOverride implementation
109 //
110 NS_IMPL_ISUPPORTS(nsStringBundleTextOverride,
111 nsIStringBundleOverride)
112
113 nsresult
114 nsStringBundleTextOverride::Init()
115 {
116 nsresult rv;
117
118 // check for existence of custom-strings.txt
119
120 nsCOMPtr<nsIFile> customStringsFile;
121 rv = NS_GetSpecialDirectory(NS_APP_CHROME_DIR,
122 getter_AddRefs(customStringsFile));
123
124 if (NS_FAILED(rv)) return rv;
125
126 // bail if not found - this will cause the service creation to
127 // bail as well, and cause this object to go away
128
129 customStringsFile->AppendNative(NS_LITERAL_CSTRING("custom-strings.txt"));
130
131 bool exists;
132 rv = customStringsFile->Exists(&exists);
133 if (NS_FAILED(rv) || !exists)
134 return NS_ERROR_FAILURE;
135
136 NS_WARNING("Using custom-strings.txt to override string bundles.");
137 // read in the custom bundle. Keys are in the form
138 // chrome://package/locale/foo.properties:keyname
139
140 nsAutoCString customStringsURLSpec;
141 rv = NS_GetURLSpecFromFile(customStringsFile, customStringsURLSpec);
142 if (NS_FAILED(rv)) return rv;
143
144 nsCOMPtr<nsIURI> uri;
145 rv = NS_NewURI(getter_AddRefs(uri), customStringsURLSpec);
146 if (NS_FAILED(rv)) return rv;
147
148 nsCOMPtr<nsIInputStream> in;
149 rv = NS_OpenURI(getter_AddRefs(in), uri);
150 if (NS_FAILED(rv)) return rv;
151
152 static NS_DEFINE_CID(kPersistentPropertiesCID, NS_IPERSISTENTPROPERTIES_CID);
153 mValues = do_CreateInstance(kPersistentPropertiesCID, &rv);
154 if (NS_FAILED(rv)) return rv;
155
156 rv = mValues->Load(in);
157
158 // turn this on to see the contents of custom-strings.txt
159 #ifdef DEBUG_alecf
160 nsCOMPtr<nsISimpleEnumerator> enumerator;
161 mValues->Enumerate(getter_AddRefs(enumerator));
162 NS_ASSERTION(enumerator, "no enumerator!\n");
163
164 printf("custom-strings.txt contains:\n");
165 printf("----------------------------\n");
166
167 bool hasMore;
168 enumerator->HasMoreElements(&hasMore);
169 do {
170 nsCOMPtr<nsISupports> sup;
171 enumerator->GetNext(getter_AddRefs(sup));
172
173 nsCOMPtr<nsIPropertyElement> prop = do_QueryInterface(sup);
174
175 nsAutoCString key;
176 nsAutoString value;
177 prop->GetKey(key);
178 prop->GetValue(value);
179
180 printf("%s = '%s'\n", key.get(), NS_ConvertUTF16toUTF8(value).get());
181
182 enumerator->HasMoreElements(&hasMore);
183 } while (hasMore);
184 #endif
185
186 return rv;
187 }
188
189 NS_IMETHODIMP
190 nsStringBundleTextOverride::GetStringFromName(const nsACString& aURL,
191 const nsACString& key,
192 nsAString& aResult)
193 {
194 // concatenate url#key to get the key to read
195 nsAutoCString combinedURL(aURL + NS_LITERAL_CSTRING("#") + key);
196
197 // persistent properties uses ":" as a delimiter, so escape that character
198 combinedURL.ReplaceSubstring(":", "%3A");
199
200 return mValues->GetStringProperty(combinedURL, aResult);
201 }
202
203 NS_IMETHODIMP
204 nsStringBundleTextOverride::EnumerateKeysInBundle(const nsACString& aURL,
205 nsISimpleEnumerator** aResult)
206 {
207 // enumerate all strings, and let the enumerator know
208 nsCOMPtr<nsISimpleEnumerator> enumerator;
209 mValues->Enumerate(getter_AddRefs(enumerator));
210
211 // make the enumerator wrapper and pass it off
212 nsPropertyEnumeratorByURL* propEnum =
213 new nsPropertyEnumeratorByURL(aURL, enumerator);
214
215 if (!propEnum) return NS_ERROR_OUT_OF_MEMORY;
216
217 NS_ADDREF(*aResult = propEnum);
218
219 return NS_OK;
220 }
221
222
223 //
224 // nsPropertyEnumeratorByURL implementation
225 //
226
227
228 NS_IMPL_ISUPPORTS(nsPropertyEnumeratorByURL, nsISimpleEnumerator)
229
230 NS_IMETHODIMP
231 nsPropertyEnumeratorByURL::GetNext(nsISupports **aResult)
232 {
233 if (!mCurrent) return NS_ERROR_UNEXPECTED;
234
235 // wrap mCurrent instead of returning it
236 *aResult = new URLPropertyElement(mCurrent, mURL.Length());
237 NS_ADDREF(*aResult);
238
239 // release it so we don't return it twice
240 mCurrent = nullptr;
241
242 return NS_OK;
243 }
244
245 NS_IMETHODIMP
246 nsPropertyEnumeratorByURL::HasMoreElements(bool * aResult)
247 {
248 bool hasMore;
249 mOuter->HasMoreElements(&hasMore);
250 while (hasMore) {
251
252 nsCOMPtr<nsISupports> supports;
253 mOuter->GetNext(getter_AddRefs(supports));
254
255 mCurrent = do_QueryInterface(supports);
256
257 if (mCurrent) {
258 nsAutoCString curKey;
259 mCurrent->GetKey(curKey);
260
261 if (StringBeginsWith(curKey, mURL))
262 break;
263 }
264
265 mOuter->HasMoreElements(&hasMore);
266 }
267
268 if (!hasMore)
269 mCurrent = nullptr;
270
271 *aResult = mCurrent ? true : false;
272
273 return NS_OK;
274 }

mercurial