Bumping gaia.json for 2 gaia revision(s) a=gaia-bump
[gecko.git] / intl / strres / nsStringBundleTextOverride.cpp
blobec32543d8d5ea049f23ae149ae441b074dd63629
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/. */
7 #include "nsStringBundleTextOverride.h"
8 #include "nsString.h"
10 #include "nsNetUtil.h"
11 #include "nsAppDirectoryServiceDefs.h"
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
17 public:
18 URLPropertyElement(nsIPropertyElement *aRealElement, uint32_t aURLLength) :
19 mRealElement(aRealElement),
20 mURLLength(aURLLength)
21 { }
23 NS_DECL_ISUPPORTS
24 NS_DECL_NSIPROPERTYELEMENT
26 private:
27 nsCOMPtr<nsIPropertyElement> mRealElement;
28 uint32_t mURLLength;
30 virtual ~URLPropertyElement() {}
33 NS_IMPL_ISUPPORTS(URLPropertyElement, nsIPropertyElement)
35 // we'll tweak the key on the way through, and remove the url prefix
36 NS_IMETHODIMP
37 URLPropertyElement::GetKey(nsACString& aKey)
39 nsresult rv = mRealElement->GetKey(aKey);
40 if (NS_FAILED(rv)) return rv;
42 // chop off the url
43 aKey.Cut(0, mURLLength);
45 return NS_OK;
48 // values are unaffected
49 NS_IMETHODIMP
50 URLPropertyElement::GetValue(nsAString& aValue)
52 return mRealElement->GetValue(aValue);
55 // setters are kind of strange, hopefully we'll never be called
56 NS_IMETHODIMP
57 URLPropertyElement::SetKey(const nsACString& aKey)
59 // this is just wrong - ideally you'd take the key, append it to
60 // the url, and set that as the key. However, that would require
61 // us to hold onto a copy of the string, and that's a waste,
62 // considering nobody should ever be calling this.
63 NS_ERROR("This makes no sense!");
64 return NS_ERROR_NOT_IMPLEMENTED;
67 NS_IMETHODIMP
68 URLPropertyElement::SetValue(const nsAString& aValue)
70 return mRealElement->SetValue(aValue);
74 // this is a special enumerator which returns only the elements which
75 // are prefixed with a particular url
76 class nsPropertyEnumeratorByURL : public nsISimpleEnumerator
78 public:
79 nsPropertyEnumeratorByURL(const nsACString& aURL,
80 nsISimpleEnumerator* aOuter) :
81 mOuter(aOuter),
82 mURL(aURL)
84 // prepare the url once so we can use its value later
85 // persistent properties uses ":" as a delimiter, so escape
86 // that character
87 mURL.ReplaceSubstring(":", "%3A");
88 // there is always a # between the url and the real key
89 mURL.Append('#');
92 NS_DECL_ISUPPORTS
93 NS_DECL_NSISIMPLEENUMERATOR
95 private:
97 // actual enumerator of all strings from nsIProperties
98 nsCOMPtr<nsISimpleEnumerator> mOuter;
100 // the current element that is valid for this url
101 nsCOMPtr<nsIPropertyElement> mCurrent;
103 // the url in question, pre-escaped and with the # already in it
104 nsCString mURL;
106 virtual ~nsPropertyEnumeratorByURL() {}
110 // nsStringBundleTextOverride implementation
112 NS_IMPL_ISUPPORTS(nsStringBundleTextOverride,
113 nsIStringBundleOverride)
115 nsresult
116 nsStringBundleTextOverride::Init()
118 nsresult rv;
120 // check for existence of custom-strings.txt
122 nsCOMPtr<nsIFile> customStringsFile;
123 rv = NS_GetSpecialDirectory(NS_APP_CHROME_DIR,
124 getter_AddRefs(customStringsFile));
126 if (NS_FAILED(rv)) return rv;
128 // bail if not found - this will cause the service creation to
129 // bail as well, and cause this object to go away
131 customStringsFile->AppendNative(NS_LITERAL_CSTRING("custom-strings.txt"));
133 bool exists;
134 rv = customStringsFile->Exists(&exists);
135 if (NS_FAILED(rv) || !exists)
136 return NS_ERROR_FAILURE;
138 NS_WARNING("Using custom-strings.txt to override string bundles.");
139 // read in the custom bundle. Keys are in the form
140 // chrome://package/locale/foo.properties:keyname
142 nsAutoCString customStringsURLSpec;
143 rv = NS_GetURLSpecFromFile(customStringsFile, customStringsURLSpec);
144 if (NS_FAILED(rv)) return rv;
146 nsCOMPtr<nsIURI> uri;
147 rv = NS_NewURI(getter_AddRefs(uri), customStringsURLSpec);
148 if (NS_FAILED(rv)) return rv;
150 nsCOMPtr<nsIInputStream> in;
151 rv = NS_OpenURI(getter_AddRefs(in), uri);
152 if (NS_FAILED(rv)) return rv;
154 static NS_DEFINE_CID(kPersistentPropertiesCID, NS_IPERSISTENTPROPERTIES_CID);
155 mValues = do_CreateInstance(kPersistentPropertiesCID, &rv);
156 if (NS_FAILED(rv)) return rv;
158 rv = mValues->Load(in);
160 // turn this on to see the contents of custom-strings.txt
161 #ifdef DEBUG_alecf
162 nsCOMPtr<nsISimpleEnumerator> enumerator;
163 mValues->Enumerate(getter_AddRefs(enumerator));
164 NS_ASSERTION(enumerator, "no enumerator!\n");
166 printf("custom-strings.txt contains:\n");
167 printf("----------------------------\n");
169 bool hasMore;
170 enumerator->HasMoreElements(&hasMore);
171 do {
172 nsCOMPtr<nsISupports> sup;
173 enumerator->GetNext(getter_AddRefs(sup));
175 nsCOMPtr<nsIPropertyElement> prop = do_QueryInterface(sup);
177 nsAutoCString key;
178 nsAutoString value;
179 prop->GetKey(key);
180 prop->GetValue(value);
182 printf("%s = '%s'\n", key.get(), NS_ConvertUTF16toUTF8(value).get());
184 enumerator->HasMoreElements(&hasMore);
185 } while (hasMore);
186 #endif
188 return rv;
191 NS_IMETHODIMP
192 nsStringBundleTextOverride::GetStringFromName(const nsACString& aURL,
193 const nsACString& key,
194 nsAString& aResult)
196 // concatenate url#key to get the key to read
197 nsAutoCString combinedURL(aURL + NS_LITERAL_CSTRING("#") + key);
199 // persistent properties uses ":" as a delimiter, so escape that character
200 combinedURL.ReplaceSubstring(":", "%3A");
202 return mValues->GetStringProperty(combinedURL, aResult);
205 NS_IMETHODIMP
206 nsStringBundleTextOverride::EnumerateKeysInBundle(const nsACString& aURL,
207 nsISimpleEnumerator** aResult)
209 // enumerate all strings, and let the enumerator know
210 nsCOMPtr<nsISimpleEnumerator> enumerator;
211 mValues->Enumerate(getter_AddRefs(enumerator));
213 // make the enumerator wrapper and pass it off
214 nsPropertyEnumeratorByURL* propEnum =
215 new nsPropertyEnumeratorByURL(aURL, enumerator);
217 if (!propEnum) return NS_ERROR_OUT_OF_MEMORY;
219 NS_ADDREF(*aResult = propEnum);
221 return NS_OK;
226 // nsPropertyEnumeratorByURL implementation
230 NS_IMPL_ISUPPORTS(nsPropertyEnumeratorByURL, nsISimpleEnumerator)
232 NS_IMETHODIMP
233 nsPropertyEnumeratorByURL::GetNext(nsISupports **aResult)
235 if (!mCurrent) return NS_ERROR_UNEXPECTED;
237 // wrap mCurrent instead of returning it
238 *aResult = new URLPropertyElement(mCurrent, mURL.Length());
239 NS_ADDREF(*aResult);
241 // release it so we don't return it twice
242 mCurrent = nullptr;
244 return NS_OK;
247 NS_IMETHODIMP
248 nsPropertyEnumeratorByURL::HasMoreElements(bool * aResult)
250 bool hasMore;
251 mOuter->HasMoreElements(&hasMore);
252 while (hasMore) {
254 nsCOMPtr<nsISupports> supports;
255 mOuter->GetNext(getter_AddRefs(supports));
257 mCurrent = do_QueryInterface(supports);
259 if (mCurrent) {
260 nsAutoCString curKey;
261 mCurrent->GetKey(curKey);
263 if (StringBeginsWith(curKey, mURL))
264 break;
267 mOuter->HasMoreElements(&hasMore);
270 if (!hasMore)
271 mCurrent = nullptr;
273 *aResult = mCurrent ? true : false;
275 return NS_OK;