sbArticlesData.cpp
Go to the documentation of this file.
1 /*
2 //
3 // BEGIN SONGBIRD GPL
4 //
5 // This file is part of the Songbird web player.
6 //
7 // Copyright(c) 2005-2008 POTI, Inc.
8 // http://songbirdnest.com
9 //
10 // This file may be licensed under the terms of of the
11 // GNU General Public License Version 2 (the "GPL").
12 //
13 // Software distributed under the License is distributed
14 // on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, either
15 // express or implied. See the GPL for the specific language
16 // governing rights and limitations.
17 //
18 // You should have received a copy of the GPL along with this
19 // program. If not, go to http://www.gnu.org/licenses/gpl.html
20 // or write to the Free Software Foundation, Inc.,
21 // 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
22 //
23 // END SONGBIRD GPL
24 //
25 */
26 
27 #include <nsCOMPtr.h>
28 #include <nsIConverterInputStream.h>
29 #include <nsServiceManagerUtils.h>
30 #include <nsIObserverService.h>
31 #include <nsIURI.h>
32 #include <nsIURL.h>
33 #include <nsNetUtil.h>
34 #include <nsIDOMParser.h>
35 #include <nsIDOMDocument.h>
36 #include <nsIDOMElement.h>
37 #include <nsIDOMNode.h>
38 #include <nsIDOMNodeList.h>
39 #include <nsIDOMNamedNodeMap.h>
40 #include <nsUnicharUtils.h>
41 #include "sbArticlesData.h"
42 
43 #define DATA_URL "chrome://songbird/content/intl/sbArticleRemoval.xml"
44 #define DOCUMENT_DATA "sb-article-removal-document"
45 #define LANGUAGE_DATA "article-removal-data"
46 #define ARTICLE_DATA "article"
47 
48 #define CONVERTER_BUFFER_SIZE 8192
49 
51 
54 
55 NS_IMPL_ISUPPORTS0(sbArticlesData::sbArticle)
56 NS_IMPL_ISUPPORTS0(sbArticlesData::sbArticleLanguageData)
57 
59 : mArticlesLoaded(PR_FALSE)
60 {
61 }
62 
64 {
66 }
67 
69  return LoadArticles();
70 }
71 
72 nsCOMPtr<sbArticlesDataObserver> gArticlesDataObserver;
73 
74 nsresult sbArticlesData::AddObserver() {
76  return NS_OK;
77 
78  nsresult rv;
79 
80  nsCOMPtr<nsIObserverService> observerService =
81  do_GetService(NS_OBSERVERSERVICE_CONTRACTID, &rv);
82  NS_ENSURE_SUCCESS(rv, rv);
83 
84  nsRefPtr<sbArticlesDataObserver> observer = new sbArticlesDataObserver();
85  gArticlesDataObserver = do_QueryInterface(observer, &rv);
86  NS_ENSURE_SUCCESS(rv, rv);
87 
88  // "xpcom-shutdown" is called right before the app will terminate
89  rv = observerService->AddObserver(gArticlesDataObserver,
90  NS_XPCOM_SHUTDOWN_OBSERVER_ID,
91  PR_FALSE);
92  NS_WARN_IF_FALSE(NS_SUCCEEDED(rv), "Failed to add shutdown observer");
93 
94  return NS_OK;
95 }
96 
97 nsresult sbArticlesData::RemoveObserver() {
99  return NS_OK;
100 
101  nsresult rv;
102  nsCOMPtr<nsIObserverService> observerService =
103  do_GetService(NS_OBSERVERSERVICE_CONTRACTID, &rv);
104  NS_ENSURE_SUCCESS(rv, rv);
105 
106  rv = observerService->RemoveObserver(gArticlesDataObserver,
107  NS_XPCOM_SHUTDOWN_OBSERVER_ID);
108  NS_WARN_IF_FALSE(NS_SUCCEEDED(rv),
109  "Failed to remove shutdown observer");
110 
111  gArticlesDataObserver = NULL;
112 
113  return NS_OK;
114 }
115 
117  if (mArticlesLoaded)
118  return NS_OK;
119 
120  nsresult rv = AddObserver();
121  NS_ENSURE_SUCCESS(rv, rv);
122 
123  // load articles data from chrome url
124 
125  nsCOMPtr<nsIURI> dataURI;
126  rv = NS_NewURI(getter_AddRefs(dataURI), NS_LITERAL_CSTRING(DATA_URL));
127  NS_ENSURE_SUCCESS(rv, rv);
128 
129  nsCOMPtr<nsIInputStream> input;
130  rv = NS_OpenURI(getter_AddRefs(input), dataURI);
131  NS_ENSURE_SUCCESS(rv, rv);
132 
133  nsCOMPtr<nsIConverterInputStream> converterStream =
134  do_CreateInstance("@mozilla.org/intl/converter-input-stream;1", &rv);
135  NS_ENSURE_SUCCESS(rv, rv);
136 
137  rv = converterStream->Init(input,
138  "UTF-8",
140  nsIConverterInputStream::DEFAULT_REPLACEMENT_CHARACTER);
141  NS_ENSURE_SUCCESS(rv, rv);
142 
143  nsCOMPtr<nsIUnicharInputStream> unichar =
144  do_QueryInterface(converterStream, &rv);
145  NS_ENSURE_SUCCESS(rv, rv);
146 
147  PRUint32 read = 0;
148  nsString response;
149  rv = unichar->ReadString(PR_UINT32_MAX, response, &read);
150  NS_ENSURE_SUCCESS(rv, rv);
151 
152  // parse document
153 
154  nsCOMPtr<nsIDOMParser> parser =
155  do_CreateInstance(NS_DOMPARSER_CONTRACTID, &rv);
156  NS_ENSURE_SUCCESS(rv, rv);
157 
158  nsCOMPtr<nsIDOMDocument> doc;
159  rv = parser->ParseFromString(response.get(), "text/xml", getter_AddRefs(doc));
160  NS_ENSURE_SUCCESS(rv, rv);
161 
162  // get top element
163 
164  nsCOMPtr<nsIDOMElement> top;
165  rv = doc->GetDocumentElement(getter_AddRefs(top));
166  NS_ENSURE_SUCCESS(rv, rv);
167 
168  nsCOMPtr<nsIDOMNode> topNode;
169  topNode = do_QueryInterface(top, &rv);
170  NS_ENSURE_SUCCESS(rv, rv);
171 
172  // check that we support it
173  nsString topLocalName;
174  rv = topNode->GetLocalName(topLocalName);
175  NS_ENSURE_SUCCESS(rv, rv);
176 
177  if (!topLocalName.EqualsLiteral(DOCUMENT_DATA)) {
178  // wrong document element localname, fail.
179  return NS_ERROR_FAILURE;
180  }
181 
182  // for each valid child element, load language data
183 
184  nsCOMPtr<nsIDOMNodeList> childNodes;
185  rv = topNode->GetChildNodes(getter_AddRefs(childNodes));
186  NS_ENSURE_SUCCESS(rv, rv);
187 
188  PRUint32 nchildren;
189  rv = childNodes->GetLength(&nchildren);
190  NS_ENSURE_SUCCESS(rv, rv);
191 
192  for (PRUint32 i=0;i<nchildren; i++) {
193 
194  // get child node
195 
196  nsCOMPtr<nsIDOMNode> childNode;
197  rv = childNodes->Item(i, getter_AddRefs(childNode));
198  NS_ENSURE_SUCCESS(rv, rv);
199 
200  PRUint16 nodeType;
201  rv = childNode->GetNodeType(&nodeType);
202  NS_ENSURE_SUCCESS(rv, rv);
203 
204  // check that it's a language node
205  if (nodeType == nsIDOMNode::ELEMENT_NODE) {
206 
207  nsString localName;
208  rv = childNode->GetLocalName(localName);
209  NS_ENSURE_SUCCESS(rv, rv);
210 
211  if (localName.EqualsLiteral(LANGUAGE_DATA)) {
212 
213  // Load language data
214  nsString language;
215  nsTArray<nsRefPtr<sbArticle> > data;
216 
217  // get the node attributes
218  nsCOMPtr<nsIDOMNamedNodeMap> attrs;
219  rv = childNode->GetAttributes(getter_AddRefs(attrs));
220  NS_ENSURE_SUCCESS(rv, rv);
221 
222  // get "lang" attribute
223  nsCOMPtr<nsIDOMNode> lang;
224  rv = attrs->GetNamedItem(NS_LITERAL_STRING("lang"), getter_AddRefs(lang));
225  NS_ENSURE_SUCCESS(rv, rv);
226 
227  // get its value
228  rv = lang->GetNodeValue(language);
229  NS_ENSURE_SUCCESS(rv, rv);
230 
231  // for every children, read article entry
232 
233  nsCOMPtr<nsIDOMNodeList> articleNodes;
234  rv = childNode->GetChildNodes(getter_AddRefs(articleNodes));
235  NS_ENSURE_SUCCESS(rv, rv);
236 
237  PRUint32 narticles;
238  rv = articleNodes->GetLength(&narticles);
239  NS_ENSURE_SUCCESS(rv, rv);
240 
241  for (PRUint32 j=0; j<narticles; j++) {
242 
243  // get article child node
244 
245  nsCOMPtr<nsIDOMNode> articleNode;
246  rv = articleNodes->Item(j, getter_AddRefs(articleNode));
247  NS_ENSURE_SUCCESS(rv, rv);
248 
249  PRUint16 articleNodeType;
250  rv = articleNode->GetNodeType(&articleNodeType);
251  NS_ENSURE_SUCCESS(rv, rv);
252 
253  // check that it's an article node
254  if (nodeType == nsIDOMNode::ELEMENT_NODE) {
255  nsString pattern;
256 
257  nsString articleLocalName;
258  rv = articleNode->GetLocalName(articleLocalName);
259  NS_ENSURE_SUCCESS(rv, rv);
260 
261  if (articleLocalName.EqualsLiteral(ARTICLE_DATA)) {
262  nsString prefix;
263  nsString suffix;
264 
265  // get attributes list
266  nsCOMPtr<nsIDOMNamedNodeMap> artAttrs;
267  rv = articleNode->GetAttributes(getter_AddRefs(artAttrs));
268  NS_ENSURE_SUCCESS(rv, rv);
269 
270  // get "pattern" attribute
271  nsCOMPtr<nsIDOMNode> patt;
272  rv = artAttrs->GetNamedItem(NS_LITERAL_STRING("pattern"), getter_AddRefs(patt));
273  NS_ENSURE_SUCCESS(rv, rv);
274 
275  // get its value
276  rv = patt->GetNodeValue(pattern);
277  NS_ENSURE_SUCCESS(rv, rv);
278 
279  // parse pattern
280  rv = ParsePattern(pattern, prefix, suffix);
281  NS_ENSURE_SUCCESS(rv, rv);
282 
283  // store it
284  nsRefPtr<sbArticle> art =
285  new sbArticle(prefix, suffix);
286  NS_ENSURE_TRUE(art, NS_ERROR_OUT_OF_MEMORY);
287 
288  data.AppendElement(art);
289  }
290  }
291  }
292 
293  nsRefPtr<sbArticleLanguageData> ldata =
294  new sbArticleLanguageData(language, data);
295  NS_ENSURE_TRUE(ldata, NS_ERROR_OUT_OF_MEMORY);
296 
297  mLanguages.AppendElement(ldata);
298  }
299 
300  }
301 
302  }
303 
304  mArticlesLoaded = PR_TRUE;
305 
306  return NS_OK;
307 }
308 
310  if (!mArticlesLoaded)
311  return NS_OK;
312 
313  nsresult rv = RemoveObserver();
314  NS_ENSURE_SUCCESS(rv, rv);
315 
316  // free articles data
317  mLanguages.Clear();
318 
319  mArticlesLoaded = PR_FALSE;
320 
321  return NS_OK;
322 }
323 
324 NS_IMETHODIMP
325 sbArticlesDataObserver::Observe(nsISupports* aSubject,
326  const char* aTopic,
327  const PRUnichar* aData) {
328 
329  if (strcmp(aTopic, NS_XPCOM_SHUTDOWN_OBSERVER_ID) == 0) {
330  if (gArticlesData) {
331  gArticlesData->UnloadArticles();
332  delete gArticlesData;
333  gArticlesData = NULL;
334  }
335  }
336 
337  return NS_OK;
338 }
339 
341  if (gArticlesData)
342  return NS_OK;
343 
344  gArticlesData = new sbArticlesData();
345 
346  if (!gArticlesData)
347  return NS_ERROR_OUT_OF_MEMORY;
348 
349  return gArticlesData->Init();
350 }
351 
352 nsresult sbArticlesData::RemoveArticles(const nsAString & aInput,
353  const nsAString & aLanguage,
354  nsAString &_retval) {
355  nsresult rv = EnsureLoaded();
356  NS_ENSURE_SUCCESS(rv, rv);
357 
358  return gArticlesData->_RemoveArticles(aInput, aLanguage, _retval);
359 }
360 
361 nsresult sbArticlesData::ParsePattern(const nsAString &aPattern,
362  nsAString &aPrefix,
363  nsAString &aSuffix) {
364 
365 
366  PRInt32 pos = aPattern.FindChar('*');
367  if (pos == -1)
368  return NS_ERROR_ILLEGAL_VALUE;
369 
370  const nsAString& left = Substring(aPattern, 0, pos);
371  const nsAString& right = Substring(aPattern, pos+1);
372 
373  aPrefix = left;
374  aSuffix = right;
375 
376  return NS_OK;
377 }
378 
379 nsresult sbArticlesData::_RemoveArticles(const nsAString & aInput,
380  const nsAString & aLanguage,
381  nsAString &_retval) {
382 
383  nsString val;
384  val = aInput;
385  PRUint32 nlang = mLanguages.Length();
386  PRBool abort = PR_FALSE;
387  for (PRUint32 i=0;i<nlang && !abort;i++) {
388  sbArticleLanguageData *lang = mLanguages[i];
389  if (aLanguage.IsEmpty() ||
390  aLanguage.Equals(lang->mLanguage)) {
391  PRUint32 narticles = lang->mArticles.Length();
392  for (PRUint32 j=0;j<narticles;j++) {
393  nsString newVal;
394 
395  nsresult rv = RemoveArticle(val, lang->mArticles[j], newVal);
396  NS_ENSURE_SUCCESS(rv, rv);
397 
398  if (newVal.IsEmpty()) {
399  abort = PR_TRUE;
400  break;
401  }
402  val = newVal;
403  }
404  }
405  }
406 
407  _retval = val;
408 
409  return NS_OK;
410 }
411 
412 nsresult sbArticlesData::RemoveArticle(const nsAString & aInput,
413  const sbArticle * aArticle,
414  nsAString &_retval) {
415  nsString val;
416  val = aInput;
417 
418  if (!aArticle->mPrefix.IsEmpty()) {
419  const nsAString &left = Substring(val, 0, aArticle->mPrefix.Length());
420  if (left.Equals(aArticle->mPrefix, CaseInsensitiveCompare)) {
421  val = Substring(val, left.Length());
422  }
423  }
424  if (!aArticle->mSuffix.IsEmpty()) {
425  const nsAString &right = Substring(val, val.Length() - aArticle->mSuffix.Length());
426  if (right.Equals(aArticle->mSuffix, CaseInsensitiveCompare)) {
427  val = Substring(val, 0, val.Length()-right.Length());
428  }
429  }
430 
431  _retval = val;
432 
433  return NS_OK;
434 }
nsCOMPtr< sbArticlesDataObserver > gArticlesDataObserver
return NS_OK
sbArticlesData * gArticlesData
static nsCOMPtr< nsIObserverService > observerService
Definition: UnityProxy.cpp:6
_dialogDatepicker pos
function doc() browser.contentDocument
function right(ele) rect(ele).right
friend class sbArticlesDataObserver
var language
Definition: Info.js:44
#define LANGUAGE_DATA
static nsresult EnsureLoaded()
NS_IMPL_THREADSAFE_ISUPPORTS1(sbArticlesDataObserver, nsIObserver) sbArticlesData
this _dialogInput val(dateText)
#define DOCUMENT_DATA
#define CONVERTER_BUFFER_SIZE
nsresult LoadArticles()
const PR_UINT32_MAX
Definition: httpd.js:55
#define ARTICLE_DATA
#define DATA_URL
observe data
Definition: FeedWriter.js:1329
_getSelectedPageStyle s i
let observer
nsresult UnloadArticles()
_updateTextAndScrollDataForFrame aData
static nsresult RemoveArticles(const nsAString &aInput, const nsAString &aLanguage, nsAString &_retval)