Bumping gaia.json for 2 gaia revision(s) a=gaia-bump
[gecko.git] / intl / strres / nsStringBundleTextOverride.cpp
blob49306f52102c0216b9924f8e02b450069d90d06d
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"
12 #include "nsContentUtils.h"
14 // first we need a simple class which wraps a nsIPropertyElement and
15 // cuts out the leading URL from the key
16 class URLPropertyElement : public nsIPropertyElement
18 public:
19 URLPropertyElement(nsIPropertyElement *aRealElement, uint32_t aURLLength) :
20 mRealElement(aRealElement),
21 mURLLength(aURLLength)
22 { }
24 NS_DECL_ISUPPORTS
25 NS_DECL_NSIPROPERTYELEMENT
27 private:
28 nsCOMPtr<nsIPropertyElement> mRealElement;
29 uint32_t mURLLength;
31 virtual ~URLPropertyElement() {}
34 NS_IMPL_ISUPPORTS(URLPropertyElement, nsIPropertyElement)
36 // we'll tweak the key on the way through, and remove the url prefix
37 NS_IMETHODIMP
38 URLPropertyElement::GetKey(nsACString& aKey)
40 nsresult rv = mRealElement->GetKey(aKey);
41 if (NS_FAILED(rv)) return rv;
43 // chop off the url
44 aKey.Cut(0, mURLLength);
46 return NS_OK;
49 // values are unaffected
50 NS_IMETHODIMP
51 URLPropertyElement::GetValue(nsAString& aValue)
53 return mRealElement->GetValue(aValue);
56 // setters are kind of strange, hopefully we'll never be called
57 NS_IMETHODIMP
58 URLPropertyElement::SetKey(const nsACString& aKey)
60 // this is just wrong - ideally you'd take the key, append it to
61 // the url, and set that as the key. However, that would require
62 // us to hold onto a copy of the string, and that's a waste,
63 // considering nobody should ever be calling this.
64 NS_ERROR("This makes no sense!");
65 return NS_ERROR_NOT_IMPLEMENTED;
68 NS_IMETHODIMP
69 URLPropertyElement::SetValue(const nsAString& aValue)
71 return mRealElement->SetValue(aValue);
75 // this is a special enumerator which returns only the elements which
76 // are prefixed with a particular url
77 class nsPropertyEnumeratorByURL : public nsISimpleEnumerator
79 public:
80 nsPropertyEnumeratorByURL(const nsACString& aURL,
81 nsISimpleEnumerator* aOuter) :
82 mOuter(aOuter),
83 mURL(aURL)
85 // prepare the url once so we can use its value later
86 // persistent properties uses ":" as a delimiter, so escape
87 // that character
88 mURL.ReplaceSubstring(":", "%3A");
89 // there is always a # between the url and the real key
90 mURL.Append('#');
93 NS_DECL_ISUPPORTS
94 NS_DECL_NSISIMPLEENUMERATOR
96 private:
98 // actual enumerator of all strings from nsIProperties
99 nsCOMPtr<nsISimpleEnumerator> mOuter;
101 // the current element that is valid for this url
102 nsCOMPtr<nsIPropertyElement> mCurrent;
104 // the url in question, pre-escaped and with the # already in it
105 nsCString mURL;
107 virtual ~nsPropertyEnumeratorByURL() {}
111 // nsStringBundleTextOverride implementation
113 NS_IMPL_ISUPPORTS(nsStringBundleTextOverride,
114 nsIStringBundleOverride)
116 nsresult
117 nsStringBundleTextOverride::Init()
119 nsresult rv;
121 // check for existence of custom-strings.txt
123 nsCOMPtr<nsIFile> customStringsFile;
124 rv = NS_GetSpecialDirectory(NS_APP_CHROME_DIR,
125 getter_AddRefs(customStringsFile));
127 if (NS_FAILED(rv)) return rv;
129 // bail if not found - this will cause the service creation to
130 // bail as well, and cause this object to go away
132 customStringsFile->AppendNative(NS_LITERAL_CSTRING("custom-strings.txt"));
134 bool exists;
135 rv = customStringsFile->Exists(&exists);
136 if (NS_FAILED(rv) || !exists)
137 return NS_ERROR_FAILURE;
139 NS_WARNING("Using custom-strings.txt to override string bundles.");
140 // read in the custom bundle. Keys are in the form
141 // chrome://package/locale/foo.properties:keyname
143 nsAutoCString customStringsURLSpec;
144 rv = NS_GetURLSpecFromFile(customStringsFile, customStringsURLSpec);
145 if (NS_FAILED(rv)) return rv;
147 nsCOMPtr<nsIURI> uri;
148 rv = NS_NewURI(getter_AddRefs(uri), customStringsURLSpec);
149 NS_ENSURE_SUCCESS(rv, rv);
151 nsCOMPtr<nsIChannel> channel;
152 rv = NS_NewChannel(getter_AddRefs(channel),
153 uri,
154 nsContentUtils::GetSystemPrincipal(),
155 nsILoadInfo::SEC_NORMAL,
156 nsIContentPolicy::TYPE_OTHER);
158 NS_ENSURE_SUCCESS(rv, rv);
159 nsCOMPtr<nsIInputStream> in;
160 rv = channel->Open(getter_AddRefs(in));
161 NS_ENSURE_SUCCESS(rv, rv);
163 static NS_DEFINE_CID(kPersistentPropertiesCID, NS_IPERSISTENTPROPERTIES_CID);
164 mValues = do_CreateInstance(kPersistentPropertiesCID, &rv);
165 if (NS_FAILED(rv)) return rv;
167 rv = mValues->Load(in);
169 // turn this on to see the contents of custom-strings.txt
170 #ifdef DEBUG_alecf
171 nsCOMPtr<nsISimpleEnumerator> enumerator;
172 mValues->Enumerate(getter_AddRefs(enumerator));
173 NS_ASSERTION(enumerator, "no enumerator!\n");
175 printf("custom-strings.txt contains:\n");
176 printf("----------------------------\n");
178 bool hasMore;
179 enumerator->HasMoreElements(&hasMore);
180 do {
181 nsCOMPtr<nsISupports> sup;
182 enumerator->GetNext(getter_AddRefs(sup));
184 nsCOMPtr<nsIPropertyElement> prop = do_QueryInterface(sup);
186 nsAutoCString key;
187 nsAutoString value;
188 prop->GetKey(key);
189 prop->GetValue(value);
191 printf("%s = '%s'\n", key.get(), NS_ConvertUTF16toUTF8(value).get());
193 enumerator->HasMoreElements(&hasMore);
194 } while (hasMore);
195 #endif
197 return rv;
200 NS_IMETHODIMP
201 nsStringBundleTextOverride::GetStringFromName(const nsACString& aURL,
202 const nsACString& key,
203 nsAString& aResult)
205 // concatenate url#key to get the key to read
206 nsAutoCString combinedURL(aURL + NS_LITERAL_CSTRING("#") + key);
208 // persistent properties uses ":" as a delimiter, so escape that character
209 combinedURL.ReplaceSubstring(":", "%3A");
211 return mValues->GetStringProperty(combinedURL, aResult);
214 NS_IMETHODIMP
215 nsStringBundleTextOverride::EnumerateKeysInBundle(const nsACString& aURL,
216 nsISimpleEnumerator** aResult)
218 // enumerate all strings, and let the enumerator know
219 nsCOMPtr<nsISimpleEnumerator> enumerator;
220 mValues->Enumerate(getter_AddRefs(enumerator));
222 // make the enumerator wrapper and pass it off
223 nsPropertyEnumeratorByURL* propEnum =
224 new nsPropertyEnumeratorByURL(aURL, enumerator);
226 if (!propEnum) return NS_ERROR_OUT_OF_MEMORY;
228 NS_ADDREF(*aResult = propEnum);
230 return NS_OK;
235 // nsPropertyEnumeratorByURL implementation
239 NS_IMPL_ISUPPORTS(nsPropertyEnumeratorByURL, nsISimpleEnumerator)
241 NS_IMETHODIMP
242 nsPropertyEnumeratorByURL::GetNext(nsISupports **aResult)
244 if (!mCurrent) return NS_ERROR_UNEXPECTED;
246 // wrap mCurrent instead of returning it
247 *aResult = new URLPropertyElement(mCurrent, mURL.Length());
248 NS_ADDREF(*aResult);
250 // release it so we don't return it twice
251 mCurrent = nullptr;
253 return NS_OK;
256 NS_IMETHODIMP
257 nsPropertyEnumeratorByURL::HasMoreElements(bool * aResult)
259 bool hasMore;
260 mOuter->HasMoreElements(&hasMore);
261 while (hasMore) {
263 nsCOMPtr<nsISupports> supports;
264 mOuter->GetNext(getter_AddRefs(supports));
266 mCurrent = do_QueryInterface(supports);
268 if (mCurrent) {
269 nsAutoCString curKey;
270 mCurrent->GetKey(curKey);
272 if (StringBeginsWith(curKey, mURL))
273 break;
276 mOuter->HasMoreElements(&hasMore);
279 if (!hasMore)
280 mCurrent = nullptr;
282 *aResult = mCurrent ? true : false;
284 return NS_OK;