Bug 470455 - test_database_sync_embed_visits.js leaks, r=sdwilsh
[wine-gecko.git] / intl / strres / src / nsStringBundleTextOverride.cpp
blob5075d6f3c741480f348ce431b0d7ed4c046e0d3f
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /* ***** BEGIN LICENSE BLOCK *****
3 * Version: MPL 1.1/GPL 2.0/LGPL 2.1
5 * The contents of this file are subject to the Mozilla Public License Version
6 * 1.1 (the "License"); you may not use this file except in compliance with
7 * the License. You may obtain a copy of the License at
8 * http://www.mozilla.org/MPL/
10 * Software distributed under the License is distributed on an "AS IS" basis,
11 * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
12 * for the specific language governing rights and limitations under the
13 * License.
15 * The Original Code is the string bundle override service.
17 * The Initial Developer of the Original Code is
18 * Netscape Communications Corp.
19 * Portions created by the Initial Developer are Copyright (C) 2002
20 * the Initial Developer. All Rights Reserved.
22 * Contributor(s):
23 * Alec Flett <alecf@netscape.com>
25 * Alternatively, the contents of this file may be used under the terms of
26 * either the GNU General Public License Version 2 or later (the "GPL"), or
27 * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
28 * in which case the provisions of the GPL or the LGPL are applicable instead
29 * of those above. If you wish to allow use of your version of this file only
30 * under the terms of either the GPL or the LGPL, and not to allow others to
31 * use your version of this file under the terms of the MPL, indicate your
32 * decision by deleting the provisions above and replace them with the notice
33 * and other provisions required by the GPL or the LGPL. If you do not delete
34 * the provisions above, a recipient may use your version of this file under
35 * the terms of any one of the MPL, the GPL or the LGPL.
37 * ***** END LICENSE BLOCK ***** */
40 #include "nsStringBundleTextOverride.h"
41 #include "nsString.h"
42 #include "nsEscape.h"
44 #include "nsNetUtil.h"
45 #include "nsAppDirectoryServiceDefs.h"
47 static NS_DEFINE_CID(kPersistentPropertiesCID, NS_IPERSISTENTPROPERTIES_CID);
50 // first we need a simple class which wraps a nsIPropertyElement and
51 // cuts out the leading URL from the key
52 class URLPropertyElement : public nsIPropertyElement
54 public:
55 URLPropertyElement(nsIPropertyElement *aRealElement, PRUint32 aURLLength) :
56 mRealElement(aRealElement),
57 mURLLength(aURLLength)
58 { }
59 virtual ~URLPropertyElement() {}
61 NS_DECL_ISUPPORTS
62 NS_DECL_NSIPROPERTYELEMENT
64 private:
65 nsCOMPtr<nsIPropertyElement> mRealElement;
66 PRUint32 mURLLength;
69 NS_IMPL_ISUPPORTS1(URLPropertyElement, nsIPropertyElement)
71 // we'll tweak the key on the way through, and remove the url prefix
72 NS_IMETHODIMP
73 URLPropertyElement::GetKey(nsACString& aKey)
75 nsresult rv = mRealElement->GetKey(aKey);
76 if (NS_FAILED(rv)) return rv;
78 // chop off the url
79 aKey.Cut(0, mURLLength);
81 return NS_OK;
84 // values are unaffected
85 NS_IMETHODIMP
86 URLPropertyElement::GetValue(nsAString& aValue)
88 return mRealElement->GetValue(aValue);
91 // setters are kind of strange, hopefully we'll never be called
92 NS_IMETHODIMP
93 URLPropertyElement::SetKey(const nsACString& aKey)
95 // this is just wrong - ideally you'd take the key, append it to
96 // the url, and set that as the key. However, that would require
97 // us to hold onto a copy of the string, and that's a waste,
98 // considering nobody should ever be calling this.
99 NS_ASSERTION(0, "This makes no sense!");
100 return NS_ERROR_NOT_IMPLEMENTED;
103 NS_IMETHODIMP
104 URLPropertyElement::SetValue(const nsAString& aValue)
106 return mRealElement->SetValue(aValue);
110 // this is a special enumerator which returns only the elements which
111 // are prefixed with a particular url
112 class nsPropertyEnumeratorByURL : public nsISimpleEnumerator
114 public:
115 nsPropertyEnumeratorByURL(const nsACString& aURL,
116 nsISimpleEnumerator* aOuter) :
117 mOuter(aOuter),
118 mURL(aURL)
120 // prepare the url once so we can use its value later
121 // persistent properties uses ":" as a delimiter, so escape
122 // that character
123 mURL.ReplaceSubstring(":", "%3A");
124 // there is always a # between the url and the real key
125 mURL.Append('#');
128 NS_DECL_ISUPPORTS
129 NS_DECL_NSISIMPLEENUMERATOR
131 virtual ~nsPropertyEnumeratorByURL() {}
132 private:
134 // actual enumerator of all strings from nsIProperties
135 nsCOMPtr<nsISimpleEnumerator> mOuter;
137 // the current element that is valid for this url
138 nsCOMPtr<nsIPropertyElement> mCurrent;
140 // the url in question, pre-escaped and with the # already in it
141 nsCString mURL;
145 // nsStringBundleTextOverride implementation
147 NS_IMPL_ISUPPORTS1(nsStringBundleTextOverride,
148 nsIStringBundleOverride)
150 nsresult
151 nsStringBundleTextOverride::Init()
153 nsresult rv;
155 // check for existence of custom-strings.txt
157 nsCOMPtr<nsIFile> customStringsFile;
158 rv = NS_GetSpecialDirectory(NS_APP_CHROME_DIR,
159 getter_AddRefs(customStringsFile));
161 if (NS_FAILED(rv)) return rv;
163 // bail if not found - this will cause the service creation to
164 // bail as well, and cause this object to go away
166 customStringsFile->AppendNative(NS_LITERAL_CSTRING("custom-strings.txt"));
168 PRBool exists;
169 rv = customStringsFile->Exists(&exists);
170 if (NS_FAILED(rv) || !exists)
171 return NS_ERROR_FAILURE;
173 NS_WARNING("Using custom-strings.txt to override string bundles.");
174 // read in the custom bundle. Keys are in the form
175 // chrome://package/locale/foo.properties:keyname
177 nsCAutoString customStringsURLSpec;
178 rv = NS_GetURLSpecFromFile(customStringsFile, customStringsURLSpec);
179 if (NS_FAILED(rv)) return rv;
181 nsCOMPtr<nsIURI> uri;
182 rv = NS_NewURI(getter_AddRefs(uri), customStringsURLSpec);
183 if (NS_FAILED(rv)) return rv;
185 nsCOMPtr<nsIInputStream> in;
186 rv = NS_OpenURI(getter_AddRefs(in), uri);
187 if (NS_FAILED(rv)) return rv;
189 mValues = do_CreateInstance(kPersistentPropertiesCID, &rv);
190 if (NS_FAILED(rv)) return rv;
192 rv = mValues->Load(in);
194 // turn this on to see the contents of custom-strings.txt
195 #ifdef DEBUG_alecf
196 nsCOMPtr<nsISimpleEnumerator> enumerator;
197 mValues->Enumerate(getter_AddRefs(enumerator));
198 NS_ASSERTION(enumerator, "no enumerator!\n");
200 printf("custom-strings.txt contains:\n");
201 printf("----------------------------\n");
203 PRBool hasMore;
204 enumerator->HasMoreElements(&hasMore);
205 do {
206 nsCOMPtr<nsISupports> sup;
207 enumerator->GetNext(getter_AddRefs(sup));
209 nsCOMPtr<nsIPropertyElement> prop = do_QueryInterface(sup);
211 nsCAutoString key;
212 nsAutoString value;
213 prop->GetKey(key);
214 prop->GetValue(value);
216 printf("%s = '%s'\n", key.get(), NS_ConvertUTF16toUTF8(value).get());
218 enumerator->HasMoreElements(&hasMore);
219 } while (hasMore);
220 #endif
222 return rv;
225 NS_IMETHODIMP
226 nsStringBundleTextOverride::GetStringFromName(const nsACString& aURL,
227 const nsACString& key,
228 nsAString& aResult)
230 // concatenate url#key to get the key to read
231 nsCAutoString combinedURL(aURL + NS_LITERAL_CSTRING("#") + key);
233 // persistent properties uses ":" as a delimiter, so escape that character
234 combinedURL.ReplaceSubstring(":", "%3A");
236 return mValues->GetStringProperty(combinedURL, aResult);
239 NS_IMETHODIMP
240 nsStringBundleTextOverride::EnumerateKeysInBundle(const nsACString& aURL,
241 nsISimpleEnumerator** aResult)
243 // enumerate all strings, and let the enumerator know
244 nsCOMPtr<nsISimpleEnumerator> enumerator;
245 mValues->Enumerate(getter_AddRefs(enumerator));
247 // make the enumerator wrapper and pass it off
248 nsPropertyEnumeratorByURL* propEnum =
249 new nsPropertyEnumeratorByURL(aURL, enumerator);
251 if (!propEnum) return NS_ERROR_OUT_OF_MEMORY;
253 NS_ADDREF(*aResult = propEnum);
255 return NS_OK;
260 // nsPropertyEnumeratorByURL implementation
264 NS_IMPL_ISUPPORTS1(nsPropertyEnumeratorByURL, nsISimpleEnumerator)
266 NS_IMETHODIMP
267 nsPropertyEnumeratorByURL::GetNext(nsISupports **aResult)
269 if (!mCurrent) return NS_ERROR_UNEXPECTED;
271 // wrap mCurrent instead of returning it
272 *aResult = new URLPropertyElement(mCurrent, mURL.Length());
273 NS_ADDREF(*aResult);
275 // release it so we don't return it twice
276 mCurrent = nsnull;
278 return NS_OK;
281 NS_IMETHODIMP
282 nsPropertyEnumeratorByURL::HasMoreElements(PRBool * aResult)
284 PRBool hasMore;
285 mOuter->HasMoreElements(&hasMore);
286 while (hasMore) {
288 nsCOMPtr<nsISupports> supports;
289 mOuter->GetNext(getter_AddRefs(supports));
291 mCurrent = do_QueryInterface(supports);
293 if (mCurrent) {
294 nsCAutoString curKey;
295 mCurrent->GetKey(curKey);
297 if (StringBeginsWith(curKey, mURL))
298 break;
301 mOuter->HasMoreElements(&hasMore);
304 if (!hasMore)
305 mCurrent = PR_FALSE;
307 *aResult = mCurrent ? PR_TRUE : PR_FALSE;
309 return NS_OK;