sbAlbumArtService.cpp
Go to the documentation of this file.
1 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 /* vim: set sw=2 :miv */
3 /*
4 //
5 // BEGIN SONGBIRD GPL
6 //
7 // This file is part of the Songbird web player.
8 //
9 // Copyright(c) 2005-2008 POTI, Inc.
10 // http://songbirdnest.com
11 //
12 // This file may be licensed under the terms of of the
13 // GNU General Public License Version 2 (the "GPL").
14 //
15 // Software distributed under the License is distributed
16 // on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, either
17 // express or implied. See the GPL for the specific language
18 // governing rights and limitations.
19 //
20 // You should have received a copy of the GPL along with this
21 // program. If not, go to http://www.gnu.org/licenses/gpl.html
22 // or write to the Free Software Foundation, Inc.,
23 // 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
24 //
25 // END SONGBIRD GPL
26 //
27 */
28 
29 //------------------------------------------------------------------------------
30 //------------------------------------------------------------------------------
31 //
32 // Songbird album art service.
33 //
34 //------------------------------------------------------------------------------
35 //------------------------------------------------------------------------------
36 
42 //------------------------------------------------------------------------------
43 //
44 // Songbird album art service imported services.
45 //
46 //------------------------------------------------------------------------------
47 
48 // Self imports.
49 #include "sbAlbumArtService.h"
50 
51 // Songbird imports.
52 #include <sbILibrary.h>
53 #include <sbILibraryManager.h>
54 #include <sbIAlbumArtFetcherSet.h>
55 #include <sbIPropertyArray.h>
56 #include <sbStandardProperties.h>
57 #include <sbVariantUtils.h>
58 
59 // Mozilla imports.
60 #include <nsComponentManagerUtils.h>
61 #include <nsIBinaryOutputStream.h>
62 #include <nsICategoryManager.h>
63 #include <nsIConverterInputStream.h>
64 #include <nsIConverterOutputStream.h>
65 #include <nsICryptoHash.h>
66 #include <nsIFileURL.h>
67 #include <nsIMutableArray.h>
68 #include <nsIProperties.h>
69 #include <nsIProtocolHandler.h>
70 #include <nsIProxyObjectManager.h>
71 #include <nsIResProtocolHandler.h>
72 #include <nsISupportsPrimitives.h>
73 #include <nsIUnicharLineInputStream.h>
74 #include <nsIUnicharOutputStream.h>
75 #include <nsServiceManagerUtils.h>
76 #include <prprf.h>
77 
78 
79 //------------------------------------------------------------------------------
80 //
81 // Songbird album art service configuration.
82 //
83 //------------------------------------------------------------------------------
84 
85 // Default size for the temporary cache used by various fetchers
86 #define TEMPORARY_CACHE_SIZE 1000
87 
88 // Time before clearing the temporary cache (in ms)
89 #define TEMPORARY_CACHE_CLEAR_TIME 60000
90 
91 // The resouce:// protocol prefix (host part) for album art cache
92 #define SB_RES_PROTO_PREFIX "sb-artwork"
93 
94 // Interval for checking if any files need to be removed from the album art
95 // cache folder (in ms).
96 #define ALBUM_ART_CACHE_CLEANUP_INTERVAL 10000
97 
98 //
99 // sbAlbumArtServiceValidExtensionList List of valid album art file extensions.
100 //
101 
103 {
104  "jpg",
105  "jpeg",
106  "gif",
107  "png"
108 };
109 
116 #include "prlog.h"
117 #ifdef PR_LOGGING
118 static PRLogModuleInfo* gAlbumArtServiceLog = nsnull;
119 #define TRACE(args) PR_LOG(gAlbumArtServiceLog, PR_LOG_DEBUG, args)
120 #define LOG(args) PR_LOG(gAlbumArtServiceLog, PR_LOG_WARN, args)
121 #else
122 #define TRACE(args) /* nothing */
123 #define LOG(args) /* nothing */
124 #endif /* PR_LOGGING */
125 
126 
127 //------------------------------------------------------------------------------
128 //
129 // nsISupports implementation.
130 //
131 //------------------------------------------------------------------------------
132 
135  nsIObserver)
136 
137 //------------------------------------------------------------------------------
138 //
139 // sbIAlbumArtService implementation.
140 //
141 //------------------------------------------------------------------------------
142 
143 
152 NS_IMETHODIMP
153 sbAlbumArtService::GetFetcherList(PRUint32 aType,
154  PRBool aIncludeDisabled,
155  nsIArray** _retval)
156 {
157  TRACE(("sbAlbumArtService[0x%8.x] - GetFetcherList", this));
158  // Validate arguments.
159  NS_ENSURE_ARG_POINTER(_retval);
160 
161  // Function variables.
162  nsresult rv;
163 
164  // Update the fetcher information first so our priorities are correct
165  rv = UpdateAlbumArtFetcherInfo();
166  NS_ENSURE_SUCCESS(rv, rv);
167 
168  // Create the fetcher list array.
169  nsCOMPtr<nsIMutableArray>
170  fetcherList = do_CreateInstance
171  ("@songbirdnest.com/moz/xpcom/threadsafe-array;1", &rv);
172  NS_ENSURE_SUCCESS(rv, rv);
173 
174  // Add each fetcher contract ID to fetcher list.
175  PRUint32 fetcherCount = mFetcherInfoList.Length();
176  for (PRUint32 i = 0; i < fetcherCount; i++) {
177  // Append the fetcher to the list only if it is enabled and the caller
178  // only wants enabled ones.
179  if (!mFetcherInfoList[i].enabled && !aIncludeDisabled) {
180  continue;
181  }
182 
183  // Check if the types match
184  switch (aType) {
186  if (!mFetcherInfoList[i].local) {
187  continue;
188  }
189  break;
191  if (mFetcherInfoList[i].local) {
192  continue;
193  }
194  break;
195  }
196 
197  // Ok we can add this fetcher to the list
198  nsCOMPtr<nsIVariant>
199  contractID = sbNewVariant(mFetcherInfoList[i].contractID).get();
200  NS_ENSURE_TRUE(contractID, NS_ERROR_OUT_OF_MEMORY);
201 
202  rv = fetcherList->AppendElement(contractID, PR_FALSE);
203  NS_ENSURE_SUCCESS(rv, rv);
204  }
205 
206  // Return results.
207  NS_ADDREF(*_retval = fetcherList);
208 
209  return NS_OK;
210 }
211 
212 
225 NS_IMETHODIMP
226 sbAlbumArtService::ImageIsValidAlbumArt(const nsACString& aMimeType,
227  const PRUint8* aData,
228  PRUint32 aDataLen,
229  PRBool* _retval)
230 {
231  TRACE(("sbAlbumArtService[0x%8.x] - ImageIsValidAlbumArt", this));
232  // Validate arguments.
233  NS_ENSURE_ARG_POINTER(_retval);
234 
235  // Function variables.
236  nsresult rv;
237 
238  // Ensure image is not empty.
239  if (!aData || !aDataLen) {
240  *_retval = PR_FALSE;
241  return NS_OK;
242  }
243 
244  // Ensure a valid album art file extension can be obtained for the image.
245  nsCAutoString fileExtension;
246  rv = GetAlbumArtFileExtension(aMimeType, fileExtension);
247  if (NS_FAILED(rv)) {
248  *_retval = PR_FALSE;
249  return NS_OK;
250  }
251 
252  // Image is valid.
253  *_retval = PR_TRUE;
254 
255  return NS_OK;
256 }
257 
258 
271 #define NS_FILE_OUTPUT_STREAM_OPEN_DEFAULT -1
272 
273 NS_IMETHODIMP
274 sbAlbumArtService::CacheImage(const nsACString& aMimeType,
275  const PRUint8* aData,
276  PRUint32 aDataLen,
277  nsIURI** _retval)
278 {
279  TRACE(("sbAlbumArtService[0x%8.x] - CacheImage", this));
280  // Validate arguments.
281  NS_ENSURE_ARG_POINTER(aData);
282  NS_ENSURE_ARG_POINTER(_retval);
283  // We need to be sure that mAlbumArtCacheDir is not null.
284  NS_ENSURE_TRUE(mAlbumArtCacheDir, NS_ERROR_NOT_INITIALIZED);
285 
286  // Function variables.
287  nsresult rv;
288 
289  // Get the image cache file base name.
290  nsCAutoString fileBaseName;
291  rv = GetCacheFileBaseName(aData, aDataLen, fileBaseName);
292  NS_ENSURE_SUCCESS(rv, rv);
293 
294  // Get the image cache file extension.
295  nsCAutoString fileExtension;
296  rv = GetAlbumArtFileExtension(aMimeType, fileExtension);
297  NS_ENSURE_SUCCESS(rv, rv);
298 
299  // Produce the image cache URL
300  nsCString fileName;
301  fileName.Assign(fileBaseName);
302  fileName.AppendLiteral(".");
303  fileName.Append(fileExtension);
304 
305  nsCString cacheDummySpec("resource://" SB_RES_PROTO_PREFIX "/dummy");
306  nsCOMPtr<nsIURI> cacheFileURI;
307  rv = mIOService->NewURI(cacheDummySpec, nsnull, nsnull, getter_AddRefs(cacheFileURI));
308  NS_ENSURE_SUCCESS(rv, rv);
309 
310  // Get the mapped file on disc
311  nsCOMPtr<nsIFileURL> cacheFileURL = do_QueryInterface(cacheFileURI, &rv);
312  NS_ENSURE_SUCCESS(rv, rv);
313  rv = cacheFileURL->SetFileName(fileName);
314  NS_ENSURE_SUCCESS(rv, rv);
315 
316  nsCOMPtr<nsIFile> cacheFile;
317  rv = cacheFileURL->GetFile(getter_AddRefs(cacheFile));
318  NS_ENSURE_SUCCESS(rv, rv);
319 
320  // If cache file already exists, return it.
321  PRBool exists;
322  rv = cacheFile->Exists(&exists);
323  NS_ENSURE_SUCCESS(rv, rv);
324  if (exists) {
325  cacheFileURI.forget(_retval);
326  return NS_OK;
327  }
328 
329  // Open a file output stream to the cache file and set to auto-close.
330  nsCOMPtr<nsIFileOutputStream> fileOutputStream =
331  do_CreateInstance("@mozilla.org/network/file-output-stream;1", &rv);
332  NS_ENSURE_SUCCESS(rv, rv);
333  rv = fileOutputStream->Init(cacheFile,
336  0);
337  NS_ENSURE_SUCCESS(rv, rv);
338  sbAutoFileOutputStream autoFileOutputStream(fileOutputStream);
339 
340  // Write the cache file.
341  nsCOMPtr<nsIBinaryOutputStream> binaryOutputStream =
342  do_CreateInstance("@mozilla.org/binaryoutputstream;1", &rv);
343  NS_ENSURE_SUCCESS(rv, rv);
344  rv = binaryOutputStream->SetOutputStream(fileOutputStream);
345  NS_ENSURE_SUCCESS(rv, rv);
346  rv = binaryOutputStream->WriteByteArray((PRUint8*) aData, aDataLen);
347  NS_ENSURE_SUCCESS(rv, rv);
348 
349  // Return results.
350  cacheFileURI.forget(_retval);
351 
352  return NS_OK;
353 }
354 
355 
356 
370 NS_IMETHODIMP
371 sbAlbumArtService::CacheTemporaryData(const nsAString& aKey,
372  nsISupports* aData)
373 {
374  TRACE(("sbAlbumArtService[0x%8.x] - CacheTemporaryData", this));
375  NS_ENSURE_ARG_POINTER(aData);
376  NS_ENSURE_TRUE(mInitialized, NS_ERROR_NOT_INITIALIZED);
377 
378  PRBool succeeded = mTemporaryCache.Put(aKey, aData);
379  NS_ENSURE_TRUE(succeeded, NS_ERROR_FAILURE);
380 
381  // Start a timer empty out the cache at some point
382  if (!mCacheFlushTimer) {
383  nsresult rv = NS_OK;
384  mCacheFlushTimer = do_CreateInstance(NS_TIMER_CONTRACTID, &rv);
385  NS_ENSURE_SUCCESS(rv, rv);
386 
387  rv = mCacheFlushTimer->Init(this,
389  nsITimer::TYPE_ONE_SHOT);
390  NS_ENSURE_SUCCESS(rv, rv);
391  }
392 
393  return NS_OK;
394 }
395 
396 
397 
406 NS_IMETHODIMP
407 sbAlbumArtService::RetrieveTemporaryData(const nsAString& aKey,
408  nsISupports** _retval)
409 {
410  TRACE(("sbAlbumArtService[0x%8.x] - RetrieveTemporaryData", this));
411  NS_ENSURE_ARG_POINTER(_retval);
412  NS_ENSURE_TRUE(mInitialized, NS_ERROR_NOT_INITIALIZED);
413  *_retval = nsnull;
414  PRBool succeeded = mTemporaryCache.Get(aKey, _retval);
415  return succeeded ? NS_OK : NS_ERROR_NOT_AVAILABLE;
416 }
417 
418 //------------------------------------------------------------------------------
419 //
420 // nsIObserver implementation.
421 //
422 //------------------------------------------------------------------------------
423 
442 NS_IMETHODIMP
443 sbAlbumArtService::Observe(nsISupports* aSubject,
444  const char* aTopic,
445  const PRUnichar* aData)
446 {
447  TRACE(("sbAlbumArtService[0x%8.x] - Observe", this));
448  nsresult rv;
449 
450  // Dispatch processing of event.
451  if (!strcmp(aTopic, "app-startup")) {
452  // Add observers for other events.
453  nsCOMPtr<nsIObserverService> obsSvc = do_GetService(
454  "@mozilla.org/observer-service;1", &rv);
455  NS_ENSURE_SUCCESS(rv, rv);
456 
457  // Add observers.
458  rv = obsSvc->AddObserver(this,
459  "profile-after-change",
460  PR_FALSE);
461  NS_ENSURE_SUCCESS(rv, rv);
462  rv = obsSvc->AddObserver(this,
464  PR_FALSE);
465  NS_ENSURE_SUCCESS(rv, rv);
466  } else if (!strcmp(aTopic, "profile-after-change")) {
467  // Initialize, now that we're able to read our preferences/etc.
468  rv = Initialize();
469  NS_ENSURE_SUCCESS(rv, rv);
470  } else if (!strcmp(aTopic, SB_LIBRARY_MANAGER_BEFORE_SHUTDOWN_TOPIC)) {
471  // Finalize the album art service.
472  Finalize();
473  } else if (!strcmp(NS_TIMER_CALLBACK_TOPIC, aTopic)) {
474  nsCOMPtr<nsITimer> aObserveTimer = do_QueryInterface(aSubject, &rv);
475  NS_ENSURE_SUCCESS(rv, rv);
476  if (aObserveTimer == mCacheFlushTimer) {
477  // Time to flush the cache
478  rv = mCacheFlushTimer->Cancel();
479  NS_ASSERTION(NS_SUCCEEDED(rv), "Failed to cancel the cache timer");
480  mCacheFlushTimer = nsnull;
481 
482  // Expire cached data
483  mTemporaryCache.Clear();
484  }
485  }
486 
487  return NS_OK;
488 }
489 
490 //------------------------------------------------------------------------------
491 //
492 // Public services.
493 //
494 //------------------------------------------------------------------------------
495 
501  mInitialized(PR_FALSE),
502  mCacheFlushTimer(nsnull)
503 {
504 #ifdef PR_LOGGING
505  if (!gAlbumArtServiceLog) {
506  gAlbumArtServiceLog = PR_NewLogModule("sbAlbumArtService");
507  }
508 #endif
509 }
510 
511 
517 {
518  Finalize();
519 }
520 
521 
526 nsresult
528 {
529  TRACE(("sbAlbumArtService[0x%8.x] - Initialize", this));
530  nsresult rv;
531 
532  // Do nothing if already initialized.
533  if (mInitialized)
534  return NS_OK;
535 
536  // Get the I/O service
537  mIOService = do_GetService("@mozilla.org/network/io-service;1", &rv);
538  NS_ENSURE_SUCCESS(rv, rv);
539 
540  // Get the MIME service.
541  mMIMEService = do_GetService("@mozilla.org/mime;1", &rv);
542  NS_ENSURE_SUCCESS(rv, rv);
543 
544  // Set up the valid extension list.
545  for (PRUint32 i = 0;
546  i < NS_ARRAY_LENGTH(sbAlbumArtServiceValidExtensionList);
547  i++) {
548  mValidExtensionList.AppendElement(sbAlbumArtServiceValidExtensionList[i]);
549  }
550 
551  // Get the album art fetcher info.
552  rv = GetAlbumArtFetcherInfo();
553  NS_ENSURE_SUCCESS(rv, rv);
554 
555  // Get the album art cache directory.
556  rv = GetAlbumArtCacheDir();
557  NS_ENSURE_SUCCESS(rv, rv);
558 
559  // Add the resolver for resource://sb-albumart/
560  nsCOMPtr<nsIIOService> ioservice =
561  do_GetService("@mozilla.org/network/io-service;1", &rv);
562  NS_ENSURE_SUCCESS(rv, rv);
563  nsCOMPtr<nsIProtocolHandler> protoHandler;
564  rv = ioservice->GetProtocolHandler("resource", getter_AddRefs(protoHandler));
565  NS_ENSURE_SUCCESS(rv, rv);
566  nsCOMPtr<nsIResProtocolHandler> resProtoHandler =
567  do_QueryInterface(protoHandler, &rv);
568  NS_ENSURE_SUCCESS(rv, rv);
569  PRBool hasSubstitution;
570  rv = resProtoHandler->HasSubstitution(NS_LITERAL_CSTRING(SB_RES_PROTO_PREFIX),
571  &hasSubstitution);
572  NS_ENSURE_SUCCESS(rv, rv);
573  if (!hasSubstitution) {
574  nsCOMPtr<nsIURI> cacheURI;
575  rv = ioservice->NewFileURI(mAlbumArtCacheDir, getter_AddRefs(cacheURI));
576  NS_ENSURE_SUCCESS(rv, rv);
577  rv = resProtoHandler->SetSubstitution(NS_LITERAL_CSTRING(SB_RES_PROTO_PREFIX),
578  cacheURI);
579  NS_ENSURE_SUCCESS(rv, rv);
580  }
581 
582  // Set up the arbitrary data cache
583  PRBool succeeded = mTemporaryCache.Init(TEMPORARY_CACHE_SIZE);
584  NS_ENSURE_TRUE(succeeded, NS_ERROR_FAILURE);
585 
586  // Mark component as initialized.
587  mInitialized = PR_TRUE;
588 
589  return NS_OK;
590 }
591 
592 
593 //------------------------------------------------------------------------------
594 //
595 // Internal services.
596 //
597 //------------------------------------------------------------------------------
598 
603 void
604 sbAlbumArtService::Finalize()
605 {
606  TRACE(("sbAlbumArtService[0x%8.x] - Finalize", this));
607  nsresult rv;
608 
609  if (!mInitialized) {
610  // Not initialized or already finalized.
611  // note that this is expected, since this gets called both on library
612  // manager shutdown and when component manager releases services
613  // SB_LIBRARY_MANAGER_BEFORE_SHUTDOWN_TOPIC and when the component manager releases services
614  return;
615  }
616 
617  mInitialized = PR_FALSE;
618 
619  // Clear the fetcher info.
620  mFetcherInfoList.Clear();
621 
622  // Clear any cache info
623  mTemporaryCache.Clear();
624 
625  // Remove observers.
626  nsCOMPtr<nsIObserverService> obsSvc = do_GetService(
627  "@mozilla.org/observer-service;1", &rv);
628  obsSvc->RemoveObserver(this, "profile-after-change");
629  obsSvc->RemoveObserver(this, SB_LIBRARY_MANAGER_BEFORE_SHUTDOWN_TOPIC);
630 
631  if (mCacheFlushTimer) {
632  rv = mCacheFlushTimer->Cancel();
633  NS_ASSERTION(NS_SUCCEEDED(rv), "Failed to cancel a cache timer");
634  mCacheFlushTimer = nsnull;
635  }
636 }
637 
638 
643 nsresult
644 sbAlbumArtService::GetAlbumArtCacheDir()
645 {
646  TRACE(("sbAlbumArtService[0x%8.x] - GetAlbumArtCacheDir", this));
647  nsresult rv;
648 
649  // Get the album art cache directory.
650  nsCOMPtr<nsIProperties>
651  directoryService = do_GetService(NS_DIRECTORY_SERVICE_CONTRACTID, &rv);
652  NS_ENSURE_SUCCESS(rv, rv);
653  rv = directoryService->Get("ProfLD",
654  NS_GET_IID(nsIFile),
655  getter_AddRefs(mAlbumArtCacheDir));
656  NS_ENSURE_SUCCESS(rv, rv);
657  rv = mAlbumArtCacheDir->Append(NS_LITERAL_STRING("artwork"));
658  NS_ENSURE_SUCCESS(rv, rv);
659 
660  // Create the album art cache directory if it doesn't exist.
661  PRBool exists;
662  rv = mAlbumArtCacheDir->Exists(&exists);
663  NS_ENSURE_SUCCESS(rv, rv);
664  if (!exists) {
665  nsCOMPtr<nsIFile> parent;
666  rv = mAlbumArtCacheDir->GetParent(getter_AddRefs(parent));
667  NS_ENSURE_SUCCESS(rv, rv);
668  PRUint32 permissions;
669  rv = parent->GetPermissions(&permissions);
670  NS_ENSURE_SUCCESS(rv, rv);
671  rv = mAlbumArtCacheDir->Create(nsIFile::DIRECTORY_TYPE, permissions);
672  NS_ENSURE_SUCCESS(rv, rv);
673  }
674 
675  return NS_OK;
676 }
677 
678 
683 nsresult
684 sbAlbumArtService::GetAlbumArtFetcherInfo()
685 {
686  TRACE(("sbAlbumArtService[0x%8.x] - GetAlbumArtFetcherInfo", this));
687  nsresult rv;
688 
689  // Get the category manager.
690  nsCOMPtr<nsICategoryManager>
691  categoryManager = do_GetService("@mozilla.org/categorymanager;1", &rv);
692  NS_ENSURE_SUCCESS(rv, rv);
693 
694  // Get the enumeration of album art fetchers.
695  nsCOMPtr<nsISimpleEnumerator> albumArtFetcherEnum;
696  rv = categoryManager->EnumerateCategory(SB_ALBUM_ART_FETCHER_CATEGORY,
697  getter_AddRefs(albumArtFetcherEnum));
698  NS_ENSURE_SUCCESS(rv, rv);
699 
700  // Get each album art fetcher info.
701  while (1) {
702  // Check if there are any more album art fetchers.
703  PRBool hasMoreElements;
704  rv = albumArtFetcherEnum->HasMoreElements(&hasMoreElements);
705  NS_ENSURE_SUCCESS(rv, rv);
706  if (!hasMoreElements) {
707  break;
708  }
709 
710  // Get the next album art fetcher category entry name.
711  nsCOMPtr<nsISupports> entryNameSupports;
712  nsCOMPtr<nsISupportsCString> entryNameSupportsCString;
713  nsCAutoString entryName;
714  rv = albumArtFetcherEnum->GetNext(getter_AddRefs(entryNameSupports));
715  NS_ENSURE_SUCCESS(rv, rv);
716  entryNameSupportsCString = do_QueryInterface(entryNameSupports, &rv);
717  NS_ENSURE_SUCCESS(rv, rv);
718  rv = entryNameSupportsCString->GetData(entryName);
719  NS_ENSURE_SUCCESS(rv, rv);
720 
721  // Get the next album art fetcher.
722  char* contractID;
723  rv = categoryManager->GetCategoryEntry(SB_ALBUM_ART_FETCHER_CATEGORY,
724  entryName.get(),
725  &contractID);
726  NS_ENSURE_SUCCESS(rv, rv);
727  TRACE(("sbAlbumArtService::GetAlbumArtFetcherInfo - Found fetcher [%s]", contractID));
728  sbAutoNSMemPtr autoContractID(contractID);
729  nsCOMPtr<sbIAlbumArtFetcher> albumArtFetcher = do_CreateInstance(contractID,
730  &rv);
731  NS_ENSURE_SUCCESS(rv, rv);
732 
733  PRInt32 priority = 0;
734  albumArtFetcher->GetPriority(&priority);
735 
736  PRBool isEnabled = PR_FALSE;
737  albumArtFetcher->GetIsEnabled(&isEnabled);
738 
739  PRBool isLocal = PR_FALSE;
740  albumArtFetcher->GetIsLocal(&isLocal);
741 
742  // Add the album art fetcher info to the list.
743  FetcherInfo fetcherInfo;
744  fetcherInfo.contractID.Assign(contractID);
745  fetcherInfo.priority = priority;
746  fetcherInfo.enabled = isEnabled;
747  fetcherInfo.local = isLocal;
748 
749  NS_ENSURE_TRUE(mFetcherInfoList.AppendElement(fetcherInfo),
750  NS_ERROR_OUT_OF_MEMORY);
751  }
752 
753  // Sort the album art fetcher info.
754  mFetcherInfoList.Sort();
755 
756  return NS_OK;
757 }
758 
759 
763 nsresult
764 sbAlbumArtService::UpdateAlbumArtFetcherInfo()
765 {
766  TRACE(("sbAlbumArtService[0x%8.x] - UpdateAlbumArtFetcherInfo", this));
767  nsresult rv;
768 
769  // Update each fetcher in the fetcher list.
770  for (PRUint32 i = 0; i < mFetcherInfoList.Length(); i++) {
771  nsCOMPtr<sbIAlbumArtFetcher> albumArtFetcher =
772  do_CreateInstance(mFetcherInfoList[i].contractID.get(), &rv);
773  NS_ENSURE_SUCCESS(rv, rv);
774 
775  PRInt32 priority = 0;
776  albumArtFetcher->GetPriority(&priority);
777 
778  PRBool isEnabled = PR_FALSE;
779  albumArtFetcher->GetIsEnabled(&isEnabled);
780 
781  mFetcherInfoList[i].priority = priority;
782  mFetcherInfoList[i].enabled = isEnabled;
783  }
784 
785  mFetcherInfoList.Sort();
786 
787  return NS_OK;
788 }
789 
790 
800 nsresult
801 sbAlbumArtService::GetCacheFileBaseName(const PRUint8* aData,
802  PRUint32 aDataLen,
803  nsACString& aFileBaseName)
804 {
805  TRACE(("sbAlbumArtService[0x%8.x] - GetCacheFileBaseName", this));
806  // Validate arguments.
807  NS_ASSERTION(aData, "aData is null");
808 
809  // Function variables.
810  nsresult rv;
811 
812  // Clear file base name.
813  aFileBaseName.Truncate();
814 
815  // Generate a hash of the image data.
816  nsCAutoString hashValue;
817  nsCOMPtr<nsICryptoHash>
818  cryptoHash = do_CreateInstance("@mozilla.org/security/hash;1", &rv);
819  NS_ENSURE_SUCCESS(rv, rv);
820  rv = cryptoHash->Init(nsICryptoHash::MD5);
821  NS_ENSURE_SUCCESS(rv, rv);
822  rv = cryptoHash->Update(aData, aDataLen);
823  NS_ENSURE_SUCCESS(rv, rv);
824  rv = cryptoHash->Finish(PR_FALSE, hashValue);
825  NS_ENSURE_SUCCESS(rv, rv);
826 
827  // Produce the image cache file base name.
828  PRUint32 hashLength = hashValue.Length();
829  PRUint8* hashData = (PRUint8*) hashValue.get();
830  for (PRUint32 i = 0; i < hashLength; i++) {
831  char hexValue[3];
832  PR_snprintf(hexValue, 3, "%02x", hashData[i]);
833  aFileBaseName.AppendLiteral(hexValue);
834  }
835 
836  return NS_OK;
837 }
838 
839 
848 nsresult
849 sbAlbumArtService::GetAlbumArtFileExtension(const nsACString& aMimeType,
850  nsACString& aFileExtension)
851 {
852  TRACE(("sbAlbumArtService[0x%8.x] - GetAlbumArtFileExtension", this));
853  nsresult rv;
854 
855  // Look up the file extension from the MIME type.
856  rv = mMIMEService->GetPrimaryExtension(aMimeType,
857  NS_LITERAL_CSTRING(""),
858  aFileExtension);
859  if (NS_FAILED(rv))
860  aFileExtension.Truncate();
861 
862  // Extract the file extension from the MIME type.
863  if (aFileExtension.IsEmpty()) {
864  PRInt32 mimeSubTypeIndex = aMimeType.RFind("/");
865  if (mimeSubTypeIndex >= 0) {
866  aFileExtension.Assign(nsDependentCSubstring(aMimeType,
867  mimeSubTypeIndex + 1));
868  } else {
869  aFileExtension.Assign(aMimeType);
870  }
871  }
872 
873  // Convert file extension to lower-case.
874  ToLowerCase(aFileExtension);
875 
876  // Validate the extension.
877  if (!mValidExtensionList.Contains(aFileExtension))
878  return NS_ERROR_FAILURE;
879 
880  return NS_OK;
881 }
882 
NS_DECL_ISUPPORTS NS_DECL_SBIALBUMARTSERVICE NS_DECL_NSIOBSERVER sbAlbumArtService()
return NS_OK
function succeeded(ch, cx, status, data)
nsIVariant * get() const
sbDeviceFirmwareAutoCheckForUpdate prototype contractID
#define SB_RES_PROTO_PREFIX
Songbird Variant Utility Definitions.
NS_IMPL_ISUPPORTS2(sbAlbumArtService, sbIAlbumArtService, nsIObserver) NS_IMETHODIMP sbAlbumArtService
#define TEMPORARY_CACHE_SIZE
#define TEMPORARY_CACHE_CLEAR_TIME
const unsigned long TYPE_LOCAL
Interface for the album art service. Instantiate as a component service.
static const char * sbAlbumArtServiceValidExtensionList[]
#define SB_ALBUM_ART_FETCHER_CATEGORY
#define TRACE(args)
#define NS_FILE_OUTPUT_STREAM_OPEN_DEFAULT
Write the album art image specified by aData and aDataLen of type specified by aMimeType to a cache f...
SimpleArrayEnumerator prototype hasMoreElements
Songbird Album Art Service Definitions.
_getSelectedPageStyle s i
const unsigned long TYPE_REMOTE
const SB_LIBRARY_MANAGER_BEFORE_SHUTDOWN_TOPIC
_updateTextAndScrollDataForFrame aData