sbLocalDatabaseMediaListBase.cpp
Go to the documentation of this file.
1 /*
2  *=BEGIN SONGBIRD GPL
3  *
4  * This file is part of the Songbird web player.
5  *
6  * Copyright(c) 2005-2010 POTI, Inc.
7  * http://www.songbirdnest.com
8  *
9  * This file may be licensed under the terms of of the
10  * GNU General Public License Version 2 (the ``GPL'').
11  *
12  * Software distributed under the License is distributed
13  * on an ``AS IS'' basis, WITHOUT WARRANTY OF ANY KIND, either
14  * express or implied. See the GPL for the specific language
15  * governing rights and limitations.
16  *
17  * You should have received a copy of the GPL along with this
18  * program. If not, go to http://www.gnu.org/licenses/gpl.html
19  * or write to the Free Software Foundation, Inc.,
20  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
21  *
22  *=END SONGBIRD GPL
23  */
24 
26 
27 #include <nsIMutableArray.h>
28 #include <nsIStringBundle.h>
29 #include <nsISimpleEnumerator.h>
30 #include <nsIStringEnumerator.h>
31 #include <nsIURI.h>
32 #include <nsIVariant.h>
33 #include <sbICascadeFilterSet.h>
34 #include <sbIDatabaseQuery.h>
35 #include <sbIDatabaseResult.h>
36 #include <sbIDevice.h>
37 #include <sbIDeviceManager.h>
38 #include <sbIFilterableMediaListView.h>
39 #include <sbILibrary.h>
40 #include <sbILocalDatabaseGUIDArray.h>
41 #include <sbILocalDatabaseLibrary.h>
42 #include <sbIMediaList.h>
43 #include <sbIMediaListListener.h>
44 #include <sbIMediaListView.h>
45 #include <sbIPropertyArray.h>
46 #include <sbIPropertyInfo.h>
47 #include <sbIPropertyManager.h>
48 #include <sbISearchableMediaListView.h>
49 #include <sbISortableMediaListView.h>
50 
51 #include <DatabaseQuery.h>
52 #include <nsAutoLock.h>
53 #include <nsComponentManagerUtils.h>
54 #include <nsServiceManagerUtils.h>
55 #include <nsHashKeys.h>
56 #include <nsMemory.h>
57 #include <nsNetUtil.h>
58 #include <pratom.h>
59 #include <sbSQLBuilderCID.h>
61 #include <sbPropertiesCID.h>
62 #include <sbStandardProperties.h>
63 #include <sbDebugUtils.h>
64 
66 #include "sbLocalDatabaseCID.h"
68 #include "sbLocalDatabaseLibrary.h"
71 
72 #define DEFAULT_PROPERTIES_URL "chrome://songbird/locale/songbird.properties"
73 
77 
79 : mFullArrayMonitor(nsnull),
80  mListContentType(sbIMediaList::CONTENTTYPE_NONE),
81  mLockedEnumerationActive(PR_FALSE)
82 {
83 }
84 
86 {
87  if (mFullArrayMonitor) {
88  nsAutoMonitor::DestroyMonitor(mFullArrayMonitor);
89  }
90 }
91 
92 nsresult
94  const nsAString& aGuid,
95  PRBool aOwnsLibrary)
96 {
98  nsAutoMonitor::NewMonitor("sbLocalDatabaseMediaListBase::mFullArrayMonitor");
99  NS_ENSURE_TRUE(mFullArrayMonitor, NS_ERROR_OUT_OF_MEMORY);
100 
101  // Initialize our base classes
103  NS_ENSURE_SUCCESS(rv, rv);
104 
105  rv = sbLocalDatabaseMediaItem::Init(aLibrary, aGuid, aOwnsLibrary);
106  NS_ENSURE_SUCCESS(rv, rv);
107 
108  PRBool success = mFilteredProperties.Init();
109  NS_ENSURE_TRUE(success, NS_ERROR_OUT_OF_MEMORY);
110 
111  nsStringHashKey *key = mFilteredProperties.PutEntry(NS_LITERAL_STRING(SB_PROPERTY_CONTENTURL));
112  NS_ENSURE_TRUE(key, NS_ERROR_OUT_OF_MEMORY);
113 
114  key = mFilteredProperties.PutEntry(NS_LITERAL_STRING(SB_PROPERTY_CREATED));
115  NS_ENSURE_TRUE(key, NS_ERROR_OUT_OF_MEMORY);
116 
117  key = mFilteredProperties.PutEntry(NS_LITERAL_STRING(SB_PROPERTY_UPDATED));
118  NS_ENSURE_TRUE(key, NS_ERROR_OUT_OF_MEMORY);
119 
120  key = mFilteredProperties.PutEntry(NS_LITERAL_STRING(SB_PROPERTY_GUID));
121  NS_ENSURE_TRUE(key, NS_ERROR_OUT_OF_MEMORY);
122 
123  key = mFilteredProperties.PutEntry(NS_LITERAL_STRING(SB_PROPERTY_HASH));
124  NS_ENSURE_TRUE(key, NS_ERROR_OUT_OF_MEMORY);
125 
126  return NS_OK;
127 }
128 
129 already_AddRefed<sbLocalDatabaseLibrary>
131 {
132  NS_ASSERTION(mLibrary, "mLibrary is null!");
134  NS_ADDREF(result);
135  return result;
136 }
137 
139 {
140  mFullArray = aArray;
141 }
142 
153 /* static */ PLDHashOperator PR_CALLBACK
154 sbLocalDatabaseMediaListBase::AddFilterToGUIDArrayCallback(nsStringHashKey::KeyType aKey,
155  sbStringArray* aEntry,
156  void* aUserData)
157 {
158  NS_ASSERTION(aEntry, "Null entry in the hash?!");
159  NS_ASSERTION(aUserData, "Null userData!");
160 
161  // Make a string enumerator for the string array.
162  nsCOMPtr<nsIStringEnumerator> valueEnum =
163  new sbTArrayStringEnumerator(aEntry);
164 
165  // If we failed then we're probably out of memory. Hope we do better on the
166  // next key?
167  NS_ENSURE_TRUE(valueEnum, PL_DHASH_NEXT);
168 
169  // Unbox the guidArray.
170  nsCOMPtr<sbILocalDatabaseGUIDArray> guidArray =
171  static_cast<sbILocalDatabaseGUIDArray*>(aUserData);
172 
173  // Set the filter.
174  nsresult SB_UNUSED_IN_RELEASE(rv) =
175  guidArray->AddFilter(aKey, valueEnum, PR_FALSE);
176  NS_WARN_IF_FALSE(NS_SUCCEEDED(rv), "AddFilter failed!");
177 
178  return PL_DHASH_NEXT;
179 }
180 
184 nsresult
185 sbLocalDatabaseMediaListBase::EnumerateAllItemsInternal(sbIMediaListEnumerationListener* aEnumerationListener)
186 {
187  sbGUIDArrayEnumerator enumerator(mLibrary, mFullArray);
188  return EnumerateItemsInternal(&enumerator, aEnumerationListener);
189 }
190 
194 nsresult
195 sbLocalDatabaseMediaListBase::EnumerateItemsByPropertyInternal(const nsAString& aID,
196  nsIStringEnumerator* aValueEnum,
197  sbIMediaListEnumerationListener* aEnumerationListener)
198 {
199  // Make a new GUID array to talk to the database.
200  nsCOMPtr<sbILocalDatabaseGUIDArray> guidArray;
201  nsresult rv = mFullArray->Clone(getter_AddRefs(guidArray));
202  NS_ENSURE_SUCCESS(rv, rv);
203 
204  // Clone copies the filters... which we don't want.
205  rv = guidArray->ClearFilters();
206  NS_ENSURE_SUCCESS(rv, rv);
207 
208  // Set the filter.
209  rv = guidArray->AddFilter(aID, aValueEnum, PR_FALSE);
210  NS_ENSURE_SUCCESS(rv, rv);
211 
212  // And make an enumerator to return the filtered items.
213  sbGUIDArrayEnumerator enumerator(mLibrary, guidArray);
214 
215  return EnumerateItemsInternal(&enumerator, aEnumerationListener);
216 }
217 
221 nsresult
222 sbLocalDatabaseMediaListBase::EnumerateItemsByPropertiesInternal(sbStringArrayHash* aPropertiesHash,
223  sbIMediaListEnumerationListener* aEnumerationListener)
224 {
225  nsCOMPtr<sbILocalDatabaseGUIDArray> guidArray;
226  nsresult rv = mFullArray->Clone(getter_AddRefs(guidArray));
227  NS_ENSURE_SUCCESS(rv, rv);
228 
229  // Clone copies the filters... which we don't want.
230  rv = guidArray->ClearFilters();
231  NS_ENSURE_SUCCESS(rv, rv);
232 
233  // Now that our hash table is set up we call AddFilter for each property
234  // id and all its associated values.
235  PRUint32 filterCount =
236  aPropertiesHash->EnumerateRead(AddFilterToGUIDArrayCallback, guidArray);
237 
238  // Make sure we actually added some filters here. Otherwise something went
239  // wrong and the results are not going to be what the caller expects.
240  PRUint32 hashCount = aPropertiesHash->Count();
241  NS_ENSURE_TRUE(filterCount == hashCount, NS_ERROR_UNEXPECTED);
242 
243  // Finally make an enumerator to return the filtered items.
244  sbGUIDArrayEnumerator enumerator(mLibrary, guidArray);
245  return EnumerateItemsInternal(&enumerator, aEnumerationListener);
246 }
247 
248 nsresult
250 {
251  nsresult rv;
252  nsCOMPtr<sbIDatabaseQuery> query =
253  do_CreateInstance(SONGBIRD_DATABASEQUERY_CONTRACTID, &rv);
254  NS_ENSURE_SUCCESS(rv, rv);
255 
256  nsAutoString databaseGuid;
257  rv = mLibrary->GetDatabaseGuid(databaseGuid);
258  NS_ENSURE_SUCCESS(rv, rv);
259 
260  rv = query->SetDatabaseGUID(databaseGuid);
261  NS_ENSURE_SUCCESS(rv, rv);
262 
263  nsCOMPtr<nsIURI> databaseLocation;
264  rv = mLibrary->GetDatabaseLocation(getter_AddRefs(databaseLocation));
265  NS_ENSURE_SUCCESS(rv, rv);
266 
267  if (databaseLocation) {
268  rv = query->SetDatabaseLocation(databaseLocation);
269  NS_ENSURE_SUCCESS(rv, rv);
270  }
271 
272  rv = query->SetAsyncQuery(PR_FALSE);
273  NS_ENSURE_SUCCESS(rv, rv);
274 
275  NS_ADDREF(*_retval = query);
276  return NS_OK;
277 }
278 
279 nsresult
281  sbIPropertyArray** _retval)
282 {
283  NS_ASSERTION(aProperties, "aProperties is null");
284  NS_ASSERTION(_retval, "_retval is null");
285 
286  nsresult rv;
287  nsCOMPtr<sbIMutablePropertyArray> mutableArray =
288  do_CreateInstance(SB_MUTABLEPROPERTYARRAY_CONTRACTID, &rv);
289  NS_ENSURE_SUCCESS(rv, rv);
290 
291  nsCOMPtr<sbILibrary> library;
292  rv = GetLibrary(getter_AddRefs(library));
293  NS_ENSURE_SUCCESS(rv, rv);
294 
295  PRBool hasContentType = PR_FALSE;
296  PRUint32 length;
297  rv = aProperties->GetLength(&length);
298  NS_ENSURE_SUCCESS(rv, rv);
299 
300  for (PRUint32 i = 0; i < length; i++) {
301  nsCOMPtr<sbIProperty> property;
302  rv = aProperties->GetPropertyAt(i, getter_AddRefs(property));
303  NS_ENSURE_SUCCESS(rv, rv);
304 
305  nsString id;
306  rv = property->GetId(id);
307  NS_ENSURE_SUCCESS(rv, rv);
308 
309  // We never want these properties to be copied to a new item.
310  if (mFilteredProperties.GetEntry(id)) {
311  continue;
312  }
313 
314  nsString value;
315  rv = property->GetValue(value);
316  NS_ENSURE_SUCCESS(rv, rv);
317 
318  rv = mutableArray->AppendProperty(id, value);
319  NS_ENSURE_SUCCESS(rv, rv);
320 
321  if (id.EqualsLiteral(SB_PROPERTY_CONTENTTYPE)) {
322  hasContentType = PR_TRUE;
323  }
324  }
325 
326  if (!hasContentType) {
327  // no content type given; assume audio
328  rv = mutableArray->AppendProperty(NS_LITERAL_STRING(SB_PROPERTY_CONTENTTYPE),
329  NS_LITERAL_STRING("audio"));
330  }
331 
332  NS_ADDREF(*_retval = mutableArray);
333  return NS_OK;
334 }
335 
336 /* static */ nsresult
338  sbIMediaItem * aSourceItem,
339  sbIMutablePropertyArray * aProperties)
340 {
341  NS_ENSURE_ARG_POINTER(aSourceItem);
342  NS_ENSURE_ARG_POINTER(aProperties);
343 
344  nsresult rv;
345 
346  // Determine whether the target list belongs to a device:
347  nsCOMPtr<sbIDeviceManager2> deviceMgr =
348  do_GetService("@songbirdnest.com/Songbird/DeviceManager;2", &rv);
349  NS_ENSURE_SUCCESS(rv, rv);
350 
351  nsCOMPtr<sbIDevice> targetDev;
352  rv = deviceMgr->GetDeviceForItem(static_cast<sbIMediaList *>(this),
353  getter_AddRefs(targetDev));
354  NS_WARN_IF_FALSE(NS_SUCCEEDED(rv), "GetDeviceForItem() failed");
355 
356  // We only set SB_PROPERTY_ORIGIN_IS_IN_MAIN_LIBRARY where it is maintained
357  // and currently there are only main library listeners in place to update the
358  // property in device libraries, so set SB_PROPERTY_ORIGIN_IS_IN_MAIN_LIBRARY
359  // only if the the target list belongs to a device.
360  PRBool targetIsDevice = (NS_SUCCEEDED(rv) && (targetDev != NULL));
361 
362  // Get the origin library:
363  nsCOMPtr<sbILibrary> originLib;
364  rv = aSourceItem->GetLibrary(getter_AddRefs(originLib));
365  NS_ENSURE_SUCCESS(rv, rv);
366 
367  // Get the main library:
368  nsCOMPtr<sbILibrary> mainLib;
369  rv = GetMainLibrary(getter_AddRefs(mainLib));
370  NS_ENSURE_SUCCESS(rv, rv);
371 
372  // Ensure there is no conflicting value for
373  // SB_PROPERTY_ORIGIN_IS_IN_MAIN_LIBRARY:
374  rv = RemoveProperty(
375  aProperties,
376  NS_LITERAL_STRING(SB_PROPERTY_ORIGIN_IS_IN_MAIN_LIBRARY));
377  NS_ENSURE_SUCCESS(rv, rv);
378 
379  // Set SB_PROPERTY_ORIGIN_IS_IN_MAIN_LIBRARY and remove any existing
380  // origin guids if the origin library is the main library. This will
381  // force the code below to regenerate the origin guids whenever an
382  // item is copied from the main library:
383  if (originLib == mainLib) {
384  // Remove SB_PROPERTY_ORIGINLIBRARYGUID:
385  rv = RemoveProperty(aProperties,
386  NS_LITERAL_STRING(SB_PROPERTY_ORIGINLIBRARYGUID));
387  NS_ENSURE_SUCCESS(rv, rv);
388 
389  // Remove SB_PROPERTY_ORIGINITEMGUID:
390  rv = RemoveProperty(aProperties,
391  NS_LITERAL_STRING(SB_PROPERTY_ORIGINITEMGUID));
392  NS_ENSURE_SUCCESS(rv, rv);
393 
394  // Set SB_PROPERTY_ORIGIN_IS_IN_MAIN_LIBRARY if the target is a
395  // device library:
396  if (targetIsDevice) {
397  rv = aProperties->AppendProperty(
398  NS_LITERAL_STRING(SB_PROPERTY_ORIGIN_IS_IN_MAIN_LIBRARY),
399  NS_LITERAL_STRING("1"));
400  NS_ENSURE_SUCCESS(rv, rv);
401  }
402  }
403  else if (targetIsDevice) {
404  // The source library is not the main library, but our target is a device.
405  // We need to verify SB_PROPERTY_ORIGIN_IS_IN_MAIN_LIBRARY by checking if
406  // an item with a guid matching this item's originItemGuid is in the main
407  // library.
408  rv = sbLibraryUtils::FindOriginalsByID(aSourceItem,
409  mainLib,
410  nsnull);
411  if (NS_SUCCEEDED(rv)) {
412  // We found the original item in the main library, set the
413  // SB_PROPERTY_ORIGIN_IS_IN_MAIN_LIBRARY flag to true
414  rv = aProperties->AppendProperty(
415  NS_LITERAL_STRING(SB_PROPERTY_ORIGIN_IS_IN_MAIN_LIBRARY),
416  NS_LITERAL_STRING("1"));
417  NS_ENSURE_SUCCESS(rv, rv);
418  }
419  else {
420  // We could not find the original item in the main library, set the
421  // SB_PROPERTY_ORIGIN_IS_IN_MAIN_LIBRARY flag to false
422  rv = aProperties->AppendProperty(
423  NS_LITERAL_STRING(SB_PROPERTY_ORIGIN_IS_IN_MAIN_LIBRARY),
424  NS_LITERAL_STRING("0"));
425  NS_ENSURE_SUCCESS(rv, rv);
426  }
427  }
428 
429  nsCOMPtr<sbILibrary> thisLibrary;
430  rv = GetLibrary(getter_AddRefs(thisLibrary));
431  NS_ENSURE_SUCCESS(rv, rv);
432 
433  PRBool copyingToMainLibrary;
434  rv = thisLibrary->Equals(mainLib, &copyingToMainLibrary);
435  NS_ENSURE_SUCCESS(rv, rv);
436 
437  // If we're not copying to the main library set the origin guids
438  if (!copyingToMainLibrary) {
439  // Set SB_PROPERTY_ORIGINLIBRARYGUID if it is not already set:
440  nsAutoString originLibGuid;
441  rv = aProperties->GetPropertyValue(
442  NS_LITERAL_STRING(SB_PROPERTY_ORIGINLIBRARYGUID),
443  originLibGuid);
444  if (rv == NS_ERROR_NOT_AVAILABLE || originLibGuid.IsEmpty()) {
445  rv = originLib->GetGuid(originLibGuid);
446  NS_ENSURE_SUCCESS(rv, rv);
447  rv = aProperties->AppendProperty(
448  NS_LITERAL_STRING(SB_PROPERTY_ORIGINLIBRARYGUID),
449  originLibGuid);
450  NS_ENSURE_SUCCESS(rv, rv);
451  }
452  else {
453  NS_ENSURE_SUCCESS(rv, rv);
454  }
455 
456  // Set SB_PROPERTY_ORIGINITEMGUID if it is not already set:
457  nsAutoString originItemGuid;
458  rv = aProperties->GetPropertyValue(
459  NS_LITERAL_STRING(SB_PROPERTY_ORIGINITEMGUID),
460  originItemGuid);
461  if (rv == NS_ERROR_NOT_AVAILABLE || originItemGuid.IsEmpty()) {
462  rv = aSourceItem->GetGuid(originItemGuid);
463  NS_ENSURE_SUCCESS(rv, rv);
464  rv = aProperties->AppendProperty(
465  NS_LITERAL_STRING(SB_PROPERTY_ORIGINITEMGUID),
466  originItemGuid);
467  NS_ENSURE_SUCCESS(rv, rv);
468  }
469  else {
470  NS_ENSURE_SUCCESS(rv, rv);
471  }
472  }
473  return NS_OK;
474 }
475 
476 /* static */ nsresult
477 sbLocalDatabaseMediaListBase::RemoveProperty(
478  sbIMutablePropertyArray * aPropertyArray,
479  const nsAString & aProperty)
480 {
481  NS_ENSURE_ARG_POINTER(aPropertyArray);
482 
483  nsresult rv;
484 
485  // Get the nsIMutableArray for access to RemoveElementAt():
486  nsCOMPtr<nsIMutableArray> mutableArray =
487  do_QueryInterface(aPropertyArray, &rv);
488  NS_ENSURE_SUCCESS(rv, rv);
489 
490  PRUint32 length;
491  rv = aPropertyArray->GetLength(&length);
492  NS_ENSURE_SUCCESS(rv, rv);
493 
494  // Iterate over the array and remove any elements with the
495  // given property id:
496  PRUint32 i = 0;
497  while (i < length) {
498  nsCOMPtr<sbIProperty> prop;
499  rv = aPropertyArray->GetPropertyAt(i, getter_AddRefs(prop));
500  NS_ENSURE_SUCCESS(rv, rv);
501 
502  nsAutoString id;
503  rv = prop->GetId(id);
504  NS_ENSURE_SUCCESS(rv, rv);
505 
506  // If the property ID matches the given ID, remove it. The index
507  // does not advance in this case, but the length decreases.
508  // Otherwise, advance to the next element:
509  if (id == aProperty) {
510  rv = mutableArray->RemoveElementAt(i);
511  NS_ENSURE_SUCCESS(rv, rv);
512  --length;
513  }
514  else {
515  i++;
516  }
517  }
518 
519  return NS_OK;
520 }
521 
525 nsresult
526 sbLocalDatabaseMediaListBase::EnumerateItemsInternal(sbGUIDArrayEnumerator* aEnumerator,
528 {
529  // Loop until we explicitly return.
530  while (PR_TRUE) {
531 
532  PRBool hasMore;
533  nsresult rv = aEnumerator->HasMoreElements(&hasMore);
534  NS_ENSURE_SUCCESS(rv, rv);
535 
536  if (!hasMore) {
537  return NS_OK;
538  }
539 
540  nsCOMPtr<nsISupports> supports;
541  rv = aEnumerator->GetNext(getter_AddRefs(supports));
542  NS_ENSURE_SUCCESS(rv, rv);
543 
544  nsCOMPtr<sbIMediaItem> item = do_QueryInterface(supports, &rv);
545  NS_ENSURE_SUCCESS(rv, rv);
546 
547  PRUint16 stepResult;
548  rv = aListener->OnEnumeratedItem(this, item, &stepResult);
549  NS_ENSURE_SUCCESS(rv, rv);
550 
551  // Stop enumerating if the listener requested it.
552  if (stepResult == sbIMediaListEnumerationListener::CANCEL) {
553  return NS_ERROR_ABORT;
554  }
555  }
556 
557  NS_NOTREACHED("Uh, how'd we get here?");
558  return NS_ERROR_UNEXPECTED;
559 }
560 
561 NS_IMETHODIMP
562 sbLocalDatabaseMediaListBase::GetName(nsAString& aName)
563 {
564  nsAutoString unlocalizedName;
565  nsresult rv = GetProperty(NS_LITERAL_STRING(SB_PROPERTY_MEDIALISTNAME),
566  unlocalizedName);
567  NS_ENSURE_SUCCESS(rv, rv);
568 
569  // If the property doesn't exist just return an empty string.
570  if (unlocalizedName.IsEmpty()) {
571  aName.Assign(unlocalizedName);
572  return NS_OK;
573  }
574 
575  // See if this string should be localized. The basic format we're looking for
576  // is:
577  //
578  // &[chrome://songbird/songbird.properties#]library.name
579  //
580  // The url (followed by '#') is optional.
581 
582  const PRUnichar *start, *end;
583  PRUint32 length = unlocalizedName.BeginReading(&start, &end);
584 
585  static const PRUnichar sAmp = '&';
586 
587  // Bail out if this can't be a localizable string.
588  if (length <= 1 || *start != sAmp) {
589  aName.Assign(unlocalizedName);
590  return NS_OK;
591  }
592 
593  // Skip the ampersand
594  start++;
595  nsDependentSubstring stringKey(start, end - start), propertiesURL;
596 
597  static const PRUnichar sHash = '#';
598 
599  for (const PRUnichar* current = start; current < end; current++) {
600  if (*current == sHash) {
601  stringKey.Rebind(current + 1, end - current - 1);
602  propertiesURL.Rebind(start, current - start);
603 
604  break;
605  }
606  }
607 
608  nsCOMPtr<nsIStringBundleService> bundleService =
609  do_GetService("@mozilla.org/intl/stringbundle;1", &rv);
610  NS_ENSURE_SUCCESS(rv, rv);
611 
612  nsCOMPtr<nsIStringBundle> bundle;
613 
614  if (!propertiesURL.IsEmpty()) {
615  nsCOMPtr<nsIURI> propertiesURI;
616  rv = NS_NewURI(getter_AddRefs(propertiesURI), propertiesURL);
617 
618  if (NS_SUCCEEDED(rv)) {
619  PRBool schemeIsChrome;
620  rv = propertiesURI->SchemeIs("chrome", &schemeIsChrome);
621 
622  if (NS_SUCCEEDED(rv) && schemeIsChrome) {
623  nsCAutoString propertiesSpec;
624  rv = propertiesURI->GetSpec(propertiesSpec);
625 
626  if (NS_SUCCEEDED(rv)) {
627  rv = bundleService->CreateBundle(propertiesSpec.get(),
628  getter_AddRefs(bundle));
629  }
630  }
631  }
632  }
633 
634  if (!bundle) {
635  rv = bundleService->CreateBundle(DEFAULT_PROPERTIES_URL,
636  getter_AddRefs(bundle));
637  }
638 
639  if (NS_SUCCEEDED(rv)) {
640  nsAutoString localizedName;
641  rv = bundle->GetStringFromName(stringKey.BeginReading(),
642  getter_Copies(localizedName));
643  if (NS_SUCCEEDED(rv)) {
644  aName.Assign(localizedName);
645  return NS_OK;
646  }
647  }
648 
649  aName.Assign(unlocalizedName);
650  return NS_OK;
651 }
652 
653 NS_IMETHODIMP
654 sbLocalDatabaseMediaListBase::SetName(const nsAString& aName)
655 {
656  nsresult rv = SetProperty(NS_LITERAL_STRING(SB_PROPERTY_MEDIALISTNAME), aName);
657  NS_ENSURE_SUCCESS(rv, rv);
658 
659  return NS_OK;
660 }
661 
662 NS_IMETHODIMP
663 sbLocalDatabaseMediaListBase::GetType(nsAString& aType)
664 {
665  NS_NOTREACHED("Not meant to be implemented in this base class");
666  return NS_ERROR_NOT_IMPLEMENTED;
667 }
668 
669 NS_IMETHODIMP
670 sbLocalDatabaseMediaListBase::GetLength(PRUint32* aLength)
671 {
672  NS_ENSURE_ARG_POINTER(aLength);
673 
674  NS_ENSURE_TRUE(mFullArrayMonitor, NS_ERROR_FAILURE);
675  nsAutoMonitor mon(mFullArrayMonitor);
676 
677  nsresult rv = mFullArray->GetLength(aLength);
678  NS_ENSURE_SUCCESS(rv, rv);
679 
680  return NS_OK;
681 }
682 
683 NS_IMETHODIMP
684 sbLocalDatabaseMediaListBase::GetItemByGuid(const nsAString& aGuid,
685  sbIMediaItem** _retval)
686 {
687  NS_ENSURE_ARG_POINTER(_retval);
688 
689  nsCOMPtr<sbIMediaItem> item;
690  nsresult rv = mLibrary->GetMediaItem(aGuid, getter_AddRefs(item));
691  NS_ENSURE_SUCCESS(rv, rv);
692 
693  NS_ADDREF(*_retval = item);
694  return NS_OK;
695 }
696 
697 NS_IMETHODIMP
698 sbLocalDatabaseMediaListBase::GetItemByIndex(PRUint32 aIndex,
699  sbIMediaItem** _retval)
700 {
701  NS_ENSURE_ARG_POINTER(_retval);
702 
703  nsresult rv;
704 
705  nsAutoString guid;
706  {
707  NS_ENSURE_TRUE(mFullArrayMonitor, NS_ERROR_FAILURE);
708  nsAutoMonitor mon(mFullArrayMonitor);
709 
710  rv = mFullArray->GetGuidByIndex(aIndex, guid);
711  NS_ENSURE_SUCCESS(rv, rv);
712  }
713 
714  nsCOMPtr<sbIMediaItem> item;
715  rv = mLibrary->GetMediaItem(guid, getter_AddRefs(item));
716  NS_ENSURE_SUCCESS(rv, rv);
717 
718  NS_ADDREF(*_retval = item);
719  return NS_OK;
720 }
721 
722 NS_IMETHODIMP
723 sbLocalDatabaseMediaListBase::GetListContentType(PRUint16* aContentType)
724 {
725  NS_ENSURE_ARG_POINTER(aContentType);
726 
727  // Cached list content type is available. No need to go further.
729  *aContentType = mListContentType;
730  return NS_OK;
731  }
732 
733  // Set the default value.
734  *aContentType = sbIMediaList::CONTENTTYPE_NONE;
735 
736  // Do some quick check on some types of lists that not belongs to
737  nsAutoString customType;
738  nsresult rv = GetProperty(NS_LITERAL_STRING(SB_PROPERTY_CUSTOMTYPE),
739  customType);
740  NS_ENSURE_SUCCESS(rv, rv);
741  if (customType.Equals(NS_LITERAL_STRING("download")))
742  return NS_OK;
743 
744  // "video-togo" list is always video
745  if (customType.Equals(NS_LITERAL_STRING("video-togo"))) {
746  *aContentType = sbIMediaList::CONTENTTYPE_VIDEO;
747  return NS_OK;
748  }
749 
750  PRUint32 length;
751  rv = mFullArray->GetLength(&length);
752  NS_ENSURE_SUCCESS(rv, rv);
753 
754  // Empty list == audio list.
755  if (!length) {
756  *aContentType = sbIMediaList::CONTENTTYPE_AUDIO;
758  return NS_OK;
759  }
760 
761  PRUint32 audioLength = 0, videoLength = 0;
762  rv = GetItemCountByProperty(NS_LITERAL_STRING(SB_PROPERTY_CONTENTTYPE),
763  NS_LITERAL_STRING("audio"),
764  &audioLength);
765  NS_ENSURE_SUCCESS(rv, rv);
766 
767  rv = GetItemCountByProperty(NS_LITERAL_STRING(SB_PROPERTY_CONTENTTYPE),
768  NS_LITERAL_STRING("video"),
769  &videoLength);
770  NS_ENSURE_SUCCESS(rv, rv);
771 
772  // audio | video == mix
773  if (audioLength > 0) {
774  *aContentType |= sbIMediaList::CONTENTTYPE_AUDIO;
775  }
776 
777  if (videoLength > 0) {
778  *aContentType |= sbIMediaList::CONTENTTYPE_VIDEO;
779  }
780 
781  mListContentType = *aContentType;
782 
783  return NS_OK;
784 }
785 
789 NS_IMETHODIMP
790 sbLocalDatabaseMediaListBase::EnumerateAllItems(sbIMediaListEnumerationListener* aEnumerationListener,
791  PRUint16 aEnumerationType)
792 {
793  NS_ENSURE_ARG_POINTER(aEnumerationListener);
794 
795  nsresult rv;
796 
797  switch (aEnumerationType) {
798 
800  NS_ENSURE_TRUE(mFullArrayMonitor, NS_ERROR_FAILURE);
801  nsAutoMonitor mon(mFullArrayMonitor);
802 
803  // Don't reenter!
804  NS_ENSURE_FALSE(mLockedEnumerationActive, NS_ERROR_FAILURE);
805  mLockedEnumerationActive = PR_TRUE;
806 
807  PRUint16 stepResult;
808  rv = aEnumerationListener->OnEnumerationBegin(this, &stepResult);
809 
810  if (NS_SUCCEEDED(rv)) {
811  if (stepResult == sbIMediaListEnumerationListener::CONTINUE) {
812  rv = EnumerateAllItemsInternal(aEnumerationListener);
813  }
814  else {
815  // The user cancelled the enumeration.
816  rv = NS_ERROR_ABORT;
817  }
818  }
819 
820  mLockedEnumerationActive = PR_FALSE;
821 
822  } break; // ENUMERATIONTYPE_LOCKING
823 
825  PRUint16 stepResult;
826  rv = aEnumerationListener->OnEnumerationBegin(this, &stepResult);
827 
828  if (NS_SUCCEEDED(rv)) {
829  if (stepResult == sbIMediaListEnumerationListener::CONTINUE) {
830  rv = EnumerateAllItemsInternal(aEnumerationListener);
831  }
832  else {
833  // The user cancelled the enumeration.
834  rv = NS_ERROR_ABORT;
835  }
836  }
837  } break; // ENUMERATIONTYPE_SNAPSHOT
838 
839  default: {
840  NS_NOTREACHED("Invalid enumeration type");
841  rv = NS_ERROR_INVALID_ARG;
842  } break;
843  }
844 
845  aEnumerationListener->OnEnumerationEnd(this, rv);
846  return NS_OK;
847 }
848 
852 NS_IMETHODIMP
853 sbLocalDatabaseMediaListBase::EnumerateItemsByProperty(const nsAString& aID,
854  const nsAString& aValue,
855  sbIMediaListEnumerationListener* aEnumerationListener,
856  PRUint16 aEnumerationType)
857 {
858  NS_ENSURE_ARG_POINTER(aEnumerationListener);
859 
860  nsresult rv = NS_ERROR_UNEXPECTED;
861 
862  // A property id must be specified.
863  NS_ENSURE_TRUE(!aID.IsEmpty(), NS_ERROR_INVALID_ARG);
864 
865  // Get the sortable format of the value
866  nsCOMPtr<sbIPropertyManager> propMan =
867  do_GetService(SB_PROPERTYMANAGER_CONTRACTID, &rv);
868  NS_ENSURE_SUCCESS(rv, rv);
869 
870  nsCOMPtr<sbIPropertyInfo> info;
871  rv = propMan->GetPropertyInfo(aID, getter_AddRefs(info));
872  NS_ENSURE_SUCCESS(rv, rv);
873 
874  nsAutoString sortableValue;
875  rv = info->MakeSortable(aValue, sortableValue);
876  NS_ENSURE_SUCCESS(rv, rv);
877 
878  // Make a single-item string array to hold our property value.
879  sbStringArray valueArray(1);
880  nsString* value = valueArray.AppendElement(sortableValue);
881  NS_ENSURE_TRUE(value, NS_ERROR_OUT_OF_MEMORY);
882 
883  // Make a string enumerator for it.
884  nsCOMPtr<nsIStringEnumerator> valueEnum =
885  new sbTArrayStringEnumerator(&valueArray);
886  NS_ENSURE_TRUE(valueEnum, NS_ERROR_OUT_OF_MEMORY);
887 
888  switch (aEnumerationType) {
889 
891  NS_ENSURE_TRUE(mFullArrayMonitor, NS_ERROR_FAILURE);
892  nsAutoMonitor mon(mFullArrayMonitor);
893 
894  // Don't reenter!
895  NS_ENSURE_FALSE(mLockedEnumerationActive, NS_ERROR_FAILURE);
896  mLockedEnumerationActive = PR_TRUE;
897 
898  PRUint16 stepResult;
899  rv = aEnumerationListener->OnEnumerationBegin(this, &stepResult);
900 
901  if (NS_SUCCEEDED(rv)) {
902  if (stepResult == sbIMediaListEnumerationListener::CONTINUE) {
903  rv = EnumerateItemsByPropertyInternal(aID, valueEnum,
904  aEnumerationListener);
905  }
906  else {
907  // The user cancelled the enumeration.
908  rv = NS_ERROR_ABORT;
909  }
910  }
911 
912  mLockedEnumerationActive = PR_FALSE;
913 
914  } break; // ENUMERATIONTYPE_LOCKING
915 
917  PRUint16 stepResult;
918  rv = aEnumerationListener->OnEnumerationBegin(this, &stepResult);
919 
920  if (NS_SUCCEEDED(rv)) {
921  if (stepResult == sbIMediaListEnumerationListener::CONTINUE) {
922  rv = EnumerateItemsByPropertyInternal(aID, valueEnum,
923  aEnumerationListener);
924  }
925  else {
926  // The user cancelled the enumeration.
927  rv = NS_ERROR_ABORT;
928  }
929  }
930  } break; // ENUMERATIONTYPE_SNAPSHOT
931 
932  default: {
933  NS_NOTREACHED("Invalid enumeration type");
934  rv = NS_ERROR_INVALID_ARG;
935  } break;
936  }
937 
938  aEnumerationListener->OnEnumerationEnd(this, rv);
939  return NS_OK;
940 }
941 
945 NS_IMETHODIMP
946 sbLocalDatabaseMediaListBase::EnumerateItemsByProperties(sbIPropertyArray* aProperties,
947  sbIMediaListEnumerationListener* aEnumerationListener,
948  PRUint16 aEnumerationType)
949 {
950  NS_ENSURE_ARG_POINTER(aProperties);
951  NS_ENSURE_ARG_POINTER(aEnumerationListener);
952 
953  PRUint32 propertyCount;
954  nsresult rv = aProperties->GetLength(&propertyCount);
955  NS_ENSURE_SUCCESS(rv, rv);
956 
957  // It doesn't make sense to call this method without specifying any properties
958  // so it is probably a caller error if we have none.
959  NS_ENSURE_STATE(propertyCount);
960 
961  // The guidArray needs AddFilter called only once per property with an
962  // enumerator that contains all the values. We were given an array of
963  // id/value pairs, so this is a little tricky. We make a hash table that
964  // uses the property id for a key and an array of values as its data. Then
965  // we load the arrays in a loop and finally call AddFilter as an enumeration
966  // function.
967 
968  sbStringArrayHash propertyHash;
969 
970  // Init with the propertyCount as the number of buckets to create. This will
971  // probably be too many, but it's likely less than the default of 16.
972  propertyHash.Init(propertyCount);
973 
974  nsCOMPtr<sbIPropertyManager> propMan =
975  do_GetService(SB_PROPERTYMANAGER_CONTRACTID, &rv);
976  NS_ENSURE_SUCCESS(rv, rv);
977 
978  // Load the hash table with properties from the array.
979  for (PRUint32 index = 0; index < propertyCount; index++) {
980 
981  // Get the property.
982  nsCOMPtr<sbIProperty> property;
983  rv = aProperties->GetPropertyAt(index, getter_AddRefs(property));
985 
986  // Get the id of the property. This will be the key for the hash table.
987  nsString propertyID;
988  rv = property->GetId(propertyID);
990 
991  // Get the string array associated with the key. If it doesn't yet exist
992  // then we need to create it.
993  sbStringArray* stringArray;
994  PRBool arrayExists = propertyHash.Get(propertyID, &stringArray);
995  if (!arrayExists) {
996  NS_NEWXPCOM(stringArray, sbStringArray);
997  SB_CONTINUE_IF_FALSE(stringArray);
998 
999  // Try to add the array to the hash table.
1000  PRBool success = propertyHash.Put(propertyID, stringArray);
1001  if (!success) {
1002  NS_WARNING("Failed to add string array to property hash!");
1003 
1004  // Make sure to delete the new array, otherwise it will leak.
1005  NS_DELETEXPCOM(stringArray);
1006  continue;
1007  }
1008  }
1009  NS_ASSERTION(stringArray, "Must have a valid pointer here!");
1010 
1011  // Now we need a slot for the property value.
1012  nsString* valueString = stringArray->AppendElement();
1013  SB_CONTINUE_IF_FALSE(valueString);
1014 
1015  // Make the value sortable and assign it
1016  nsCOMPtr<sbIPropertyInfo> info;
1017  rv = propMan->GetPropertyInfo(propertyID, getter_AddRefs(info));
1019 
1020  nsAutoString value;
1021  rv = property->GetValue(value);
1023 
1024  nsAutoString sortableValue;
1025  rv = info->MakeSortable(value, *valueString);
1027  }
1028 
1029  switch (aEnumerationType) {
1030 
1032  NS_ENSURE_TRUE(mFullArrayMonitor, NS_ERROR_FAILURE);
1033  nsAutoMonitor mon(mFullArrayMonitor);
1034 
1035  // Don't reenter!
1036  NS_ENSURE_FALSE(mLockedEnumerationActive, NS_ERROR_FAILURE);
1037  mLockedEnumerationActive = PR_TRUE;
1038 
1039  PRUint16 stepResult;
1040  rv = aEnumerationListener->OnEnumerationBegin(this, &stepResult);
1041 
1042  if (NS_SUCCEEDED(rv)) {
1043  if (stepResult == sbIMediaListEnumerationListener::CONTINUE) {
1044  rv = EnumerateItemsByPropertiesInternal(&propertyHash,
1045  aEnumerationListener);
1046  }
1047  else {
1048  // The user cancelled the enumeration.
1049  rv = NS_ERROR_ABORT;
1050  }
1051  }
1052 
1053  mLockedEnumerationActive = PR_FALSE;
1054 
1055  } break; // ENUMERATIONTYPE_LOCKING
1056 
1058  PRUint16 stepResult;
1059  rv = aEnumerationListener->OnEnumerationBegin(this, &stepResult);
1060 
1061  if (NS_SUCCEEDED(rv)) {
1062  if (stepResult == sbIMediaListEnumerationListener::CONTINUE) {
1063  rv = EnumerateItemsByPropertiesInternal(&propertyHash,
1064  aEnumerationListener);
1065  }
1066  else {
1067  // The user cancelled the enumeration.
1068  rv = NS_ERROR_ABORT;
1069  }
1070  }
1071  } break; // ENUMERATIONTYPE_SNAPSHOT
1072 
1073  default: {
1074  NS_NOTREACHED("Invalid enumeration type");
1075  rv = NS_ERROR_INVALID_ARG;
1076  } break;
1077  }
1078 
1079  aEnumerationListener->OnEnumerationEnd(this, rv);
1080  return NS_OK;
1081 }
1082 
1083 
1084 NS_IMETHODIMP
1085 sbLocalDatabaseMediaListBase::GetItemsByProperty(const nsAString & aPropertyID,
1086  const nsAString & aPropertyValue,
1087  nsIArray **_retval)
1088 {
1089  NS_ENSURE_ARG_POINTER(_retval);
1090 
1091  nsRefPtr<sbLocalMediaListBaseEnumerationListener> enumerator;
1092  NS_NEWXPCOM(enumerator, sbLocalMediaListBaseEnumerationListener);
1093  NS_ENSURE_TRUE(enumerator, NS_ERROR_OUT_OF_MEMORY);
1094 
1095  nsresult rv = enumerator->Init();
1096  NS_ENSURE_SUCCESS(rv, rv);
1097 
1098  rv = EnumerateItemsByProperty(aPropertyID,
1099  aPropertyValue,
1100  enumerator,
1102  NS_ENSURE_SUCCESS(rv, rv);
1103 
1104  return enumerator->GetArray(_retval);
1105 }
1106 
1107 NS_IMETHODIMP
1108 sbLocalDatabaseMediaListBase::GetItemCountByProperty(const nsAString & aPropertyID,
1109  const nsAString & aPropertyValue,
1110  PRUint32 *_retval)
1111 {
1112  NS_ENSURE_ARG_POINTER(_retval);
1113 
1114  nsRefPtr<sbLocalMediaListBaseEnumerationListener> enumerator;
1115  NS_NEWXPCOM(enumerator, sbLocalMediaListBaseEnumerationListener);
1116  NS_ENSURE_TRUE(enumerator, NS_ERROR_OUT_OF_MEMORY);
1117 
1118  nsresult rv = enumerator->Init();
1119  NS_ENSURE_SUCCESS(rv, rv);
1120 
1121  rv = EnumerateItemsByProperty(aPropertyID,
1122  aPropertyValue,
1123  enumerator,
1125  NS_ENSURE_SUCCESS(rv, rv);
1126 
1127  return enumerator->GetArrayLength(_retval);
1128 }
1129 
1130 NS_IMETHODIMP
1131 sbLocalDatabaseMediaListBase::GetItemsByProperties(sbIPropertyArray *aProperties,
1132  nsIArray **_retval)
1133 {
1134  NS_ENSURE_ARG_POINTER(aProperties);
1135  NS_ENSURE_ARG_POINTER(_retval);
1136 
1137  nsRefPtr<sbLocalMediaListBaseEnumerationListener> enumerator;
1138  NS_NEWXPCOM(enumerator, sbLocalMediaListBaseEnumerationListener);
1139  NS_ENSURE_TRUE(enumerator, NS_ERROR_OUT_OF_MEMORY);
1140 
1141  nsresult rv = enumerator->Init();
1142  NS_ENSURE_SUCCESS(rv, rv);
1143 
1144  rv = EnumerateItemsByProperties(aProperties,
1145  enumerator,
1147  NS_ENSURE_SUCCESS(rv, rv);
1148 
1149  rv = enumerator->GetArray(_retval);
1150  NS_ENSURE_SUCCESS(rv, rv);
1151 
1152  return NS_OK;
1153 }
1154 
1155 NS_IMETHODIMP
1156 sbLocalDatabaseMediaListBase::IndexOf(sbIMediaItem* aMediaItem,
1157  PRUint32 aStartFrom,
1158  PRUint32* _retval)
1159 {
1160  NS_ENSURE_ARG_POINTER(aMediaItem);
1161  NS_ENSURE_ARG_POINTER(_retval);
1162 
1163  PRUint32 count;
1164 
1165  NS_ENSURE_TRUE(mFullArrayMonitor, NS_ERROR_FAILURE);
1166  nsAutoMonitor mon(mFullArrayMonitor);
1167 
1168  nsresult rv = mFullArray->GetLength(&count);
1169  NS_ENSURE_SUCCESS(rv, rv);
1170 
1171  // Do some sanity checking.
1172  NS_ENSURE_TRUE(count > 0, NS_ERROR_NOT_AVAILABLE);
1173  NS_ENSURE_ARG_MAX(aStartFrom, count - 1);
1174 
1175  nsAutoString testGUID;
1176  rv = aMediaItem->GetGuid(testGUID);
1177  NS_ENSURE_SUCCESS(rv, rv);
1178 
1179  for (PRUint32 index = aStartFrom; index < count; index++) {
1180  nsAutoString itemGUID;
1181  rv = mFullArray->GetGuidByIndex(index, itemGUID);
1183 
1184  if (testGUID.Equals(itemGUID)) {
1185  *_retval = index;
1186  return NS_OK;
1187  }
1188  }
1189 
1190  return NS_ERROR_NOT_AVAILABLE;
1191 }
1192 
1193 NS_IMETHODIMP
1194 sbLocalDatabaseMediaListBase::LastIndexOf(sbIMediaItem* aMediaItem,
1195  PRUint32 aStartFrom,
1196  PRUint32* _retval)
1197 {
1198  NS_ENSURE_ARG_POINTER(aMediaItem);
1199  NS_ENSURE_ARG_POINTER(_retval);
1200 
1201  NS_ENSURE_TRUE(mFullArrayMonitor, NS_ERROR_FAILURE);
1202  nsAutoMonitor mon(mFullArrayMonitor);
1203 
1204  PRUint32 count;
1205  nsresult rv = mFullArray->GetLength(&count);
1206  NS_ENSURE_SUCCESS(rv, rv);
1207 
1208  // Do some sanity checking.
1209  NS_ENSURE_TRUE(count > 0, NS_ERROR_UNEXPECTED);
1210  NS_ENSURE_ARG_MAX(aStartFrom, count - 1);
1211 
1212  nsAutoString testGUID;
1213  rv = aMediaItem->GetGuid(testGUID);
1214  NS_ENSURE_SUCCESS(rv, rv);
1215 
1216  for (PRUint32 index = count - 1; index >= aStartFrom; index--) {
1217  nsAutoString itemGUID;
1218  rv = mFullArray->GetGuidByIndex(index, itemGUID);
1220 
1221  if (testGUID.Equals(itemGUID)) {
1222  *_retval = index;
1223  return NS_OK;
1224  }
1225  }
1226  return NS_ERROR_NOT_AVAILABLE;
1227 }
1228 
1229 NS_IMETHODIMP
1230 sbLocalDatabaseMediaListBase::Contains(sbIMediaItem* aMediaItem,
1231  PRBool* _retval)
1232 {
1233  return NS_ERROR_NOT_IMPLEMENTED;
1234 }
1235 
1236 NS_IMETHODIMP
1237 sbLocalDatabaseMediaListBase::GetIsEmpty(PRBool* aIsEmpty)
1238 {
1239  NS_ENSURE_ARG_POINTER(aIsEmpty);
1240 
1241  NS_ENSURE_TRUE(mFullArrayMonitor, NS_ERROR_FAILURE);
1242  nsAutoMonitor mon(mFullArrayMonitor);
1243 
1244  PRUint32 length;
1245  nsresult rv = mFullArray->GetLength(&length);
1246  NS_ENSURE_SUCCESS(rv, rv);
1247 
1248  *aIsEmpty = length == 0;
1249  return NS_OK;
1250 }
1251 
1252 NS_IMETHODIMP
1253 sbLocalDatabaseMediaListBase::GetUserEditableContent(PRBool* aUserEditableContent)
1254 {
1255  NS_ENSURE_ARG_POINTER(aUserEditableContent);
1256 
1257  // Item is readonly if it contains a "1" in the corresponding property.
1258 
1259  nsAutoString str;
1260  nsresult rv = GetProperty(NS_LITERAL_STRING(SB_PROPERTY_ISCONTENTREADONLY), str);
1261  NS_ENSURE_SUCCESS(rv, rv);
1262 
1263  *aUserEditableContent = !str.EqualsLiteral("1");
1264 
1265  return NS_OK;
1266 }
1267 
1268 NS_IMETHODIMP
1269 sbLocalDatabaseMediaListBase::Add(sbIMediaItem* aMediaItem)
1270 {
1271  NS_NOTREACHED("Not meant to be implemented in this base class");
1272  return NS_ERROR_NOT_IMPLEMENTED;
1273 }
1274 
1275 NS_IMETHODIMP
1276 sbLocalDatabaseMediaListBase::AddItem(sbIMediaItem* aMediaItem,
1277  sbIMediaItem ** aNewMediaItem)
1278 {
1279  NS_NOTREACHED("Not meant to be implemented in this base class");
1280  return NS_ERROR_NOT_IMPLEMENTED;
1281 }
1282 
1283 NS_IMETHODIMP
1284 sbLocalDatabaseMediaListBase::AddAll(sbIMediaList* aMediaList)
1285 {
1286  NS_NOTREACHED("Not meant to be implemented in this base class");
1287  return NS_ERROR_NOT_IMPLEMENTED;
1288 }
1289 
1290 NS_IMETHODIMP
1291 sbLocalDatabaseMediaListBase::AddSome(nsISimpleEnumerator* aMediaItems)
1292 {
1293  NS_NOTREACHED("Not meant to be implemented in this base class");
1294  return NS_ERROR_NOT_IMPLEMENTED;
1295 }
1296 
1297 NS_IMETHODIMP
1298 sbLocalDatabaseMediaListBase::AddMediaItems(nsISimpleEnumerator* aMediaItems,
1299  sbIAddMediaItemsListener * aListener,
1300  PRBool aAsync)
1301 {
1302  NS_NOTREACHED("Not meant to be implemented in this base class");
1303  return NS_ERROR_NOT_IMPLEMENTED;
1304 }
1305 
1306 NS_IMETHODIMP
1307 sbLocalDatabaseMediaListBase::Remove(sbIMediaItem* aMediaItem)
1308 {
1309  NS_NOTREACHED("Not meant to be implemented in this base class");
1310  return NS_ERROR_NOT_IMPLEMENTED;
1311 }
1312 
1313 NS_IMETHODIMP
1314 sbLocalDatabaseMediaListBase::RemoveByIndex(PRUint32 aIndex)
1315 {
1316  NS_NOTREACHED("Not meant to be implemented in this base class");
1317  return NS_ERROR_NOT_IMPLEMENTED;
1318 }
1319 
1320 NS_IMETHODIMP
1321 sbLocalDatabaseMediaListBase::RemoveSome(nsISimpleEnumerator* aMediaItems)
1322 {
1323  NS_NOTREACHED("Not meant to be implemented in this base class");
1324  return NS_ERROR_NOT_IMPLEMENTED;
1325 }
1326 
1327 NS_IMETHODIMP
1328 sbLocalDatabaseMediaListBase::Clear()
1329 {
1330  NS_NOTREACHED("Not meant to be implemented in this base class");
1331  return NS_ERROR_NOT_IMPLEMENTED;
1332 }
1333 
1334 NS_IMETHODIMP
1336  PRBool aOwnsWeak,
1337  PRUint32 aFlags,
1338  sbIPropertyArray* aPropertyFilter)
1339 {
1341  aListener,
1342  aOwnsWeak,
1343  aFlags,
1344  aPropertyFilter);
1345 }
1346 
1347 NS_IMETHODIMP
1349 {
1350  return sbLocalDatabaseMediaListListener::RemoveListener(this, aListener);
1351 }
1352 
1353 NS_IMETHODIMP
1354 sbLocalDatabaseMediaListBase::CreateView(sbIMediaListViewState* aState,
1355  sbIMediaListView** _retval)
1356 {
1357  NS_NOTREACHED("Not meant to be implemented in this base class");
1358  return NS_ERROR_NOT_IMPLEMENTED;
1359 }
1360 
1361 NS_IMETHODIMP
1362 sbLocalDatabaseMediaListBase::GetDistinctValuesForProperty(const nsAString& aPropertyID,
1363  nsIStringEnumerator** _retval)
1364 {
1365  NS_ENSURE_ARG_POINTER(_retval);
1366 
1367  nsCOMPtr<sbILocalDatabaseGUIDArray> guidArray;
1368  nsresult rv = mFullArray->Clone(getter_AddRefs(guidArray));
1369  NS_ENSURE_SUCCESS(rv, rv);
1370 
1371  rv = guidArray->SetIsDistinct(PR_TRUE);
1372  NS_ENSURE_SUCCESS(rv, rv);
1373 
1374  rv = guidArray->ClearSorts();
1375  NS_ENSURE_SUCCESS(rv, rv);
1376 
1377  rv = guidArray->AddSort(aPropertyID, PR_TRUE);
1378  NS_ENSURE_SUCCESS(rv, rv);
1379 
1380  sbGUIDArrayValueEnumerator* enumerator =
1381  new sbGUIDArrayValueEnumerator(guidArray);
1382  NS_ENSURE_TRUE(enumerator, NS_ERROR_OUT_OF_MEMORY);
1383 
1384  NS_ADDREF(*_retval = enumerator);
1385  return NS_OK;
1386 }
1387 
1388 NS_IMETHODIMP
1389 sbLocalDatabaseMediaListBase::RunInBatchMode(sbIMediaListBatchCallback* aCallback,
1390  nsISupports* aUserData)
1391 {
1392  NS_ENSURE_ARG_POINTER(aCallback);
1393 
1394  sbAutoBatchHelper helper(*this);
1395 
1396  return aCallback->RunBatched(aUserData);
1397 }
1398 
1400 
1402  mArray(aArray),
1403  mLength(0),
1404  mNextIndex(0)
1405 {
1406  NS_ASSERTION(aArray, "Null value passed to ctor");
1407 
1408  nsresult SB_UNUSED_IN_RELEASE(rv) = mArray->GetLength(&mLength);
1409  NS_ASSERTION(NS_SUCCEEDED(rv), "Could not get length");
1410 }
1411 
1413 {
1414 }
1415 
1416 NS_IMETHODIMP
1417 sbGUIDArrayValueEnumerator::HasMore(PRBool *_retval)
1418 {
1419  NS_ENSURE_ARG_POINTER(_retval);
1420 
1421  *_retval = mNextIndex < mLength;
1422  return NS_OK;
1423 }
1424 
1425 NS_IMETHODIMP
1426 sbGUIDArrayValueEnumerator::GetNext(nsAString& _retval)
1427 {
1428  nsresult rv = mArray->GetSortPropertyValueByIndex(mNextIndex, _retval);
1429  NS_ENSURE_SUCCESS(rv, rv);
1430 
1431  mNextIndex++;
1432 
1433  return NS_OK;
1434 }
function start(ch)
nsresult GetOriginProperties(sbIMediaItem *aSourceItem, sbIMutablePropertyArray *aProperties)
sbLocalDatabaseLibrary * mLibrary
return NS_OK
nsresult Init(sbLocalDatabaseLibrary *aLibrary, const nsAString &aGuid, PRBool aOwnsLibrary=PR_TRUE)
Initializes the media item.
#define SB_PROPERTY_MEDIALISTNAME
#define SONGBIRD_DATABASEQUERY_CONTRACTID
Definition: DatabaseQuery.h:63
#define SB_PROPERTY_ORIGINLIBRARYGUID
#define SB_PROPERTY_HASH
NS_IMPL_ISUPPORTS_INHERITED1(sbLocalDatabaseMediaListBase, sbLocalDatabaseMediaItem, sbIMediaList) sbLocalDatabaseMediaListBase
Interface used to enumerate the items in a media list.
menuItem id
Definition: FeedWriter.js:971
onPageChanged aValue
Definition: FeedWriter.js:1395
NS_IMPL_ISUPPORTS1(sbDeviceCapabilitiesUtils, sbIDeviceCapabilitiesUtils) sbDeviceCapabilitiesUtils
nsTArray< nsString > sbStringArray
[USER CODE SHOULD NOT REFERENCE THIS CLASS]
#define SB_PROPERTY_ISCONTENTREADONLY
nsresult AddListener(sbIMediaListListener *aListener, PRBool aOwnsWeak=PR_FALSE, PRUint32 aFlags=0)
const NS_ERROR_ABORT
readonly attribute sbILibrary library
The library that this media item is contained in.
#define DEFAULT_PROPERTIES_URL
#define SB_MUTABLEPROPERTYARRAY_CONTRACTID
void SetArray(sbILocalDatabaseGUIDArray *aArray)
A brief description of the contents of this interface.
nsresult RemoveListener(sbLocalDatabaseMediaListBase *aList, sbIMediaListListener *aListener)
const unsigned short CONTENTTYPE_AUDIO
A distinct view on a given media list.
Simple class to make sure we notify listeners that a batch operation has completed every time they ar...
readonly attribute AString guid
The guid of this resource.
#define SB_PROPERTYMANAGER_CONTRACTID
nsresult AddListener(sbLocalDatabaseMediaListBase *aList, sbIMediaListListener *aListener, PRBool aOwnsWeak=PR_FALSE, PRUint32 aFlags=sbIMediaList::LISTENER_FLAGS_ALL, sbIPropertyArray *aPropertyFilter=nsnull)
Interface used to listen to changes to a media list.
An interface to carry around arrays of nsIProperty instances Note that implementations of the interfa...
readonly attribute unsigned long length
Returns the length of the list.
Saved state of a media list view.
var bundle
var count
Definition: test_bug7406.js:32
#define SB_PROPERTY_CREATED
#define SB_PROPERTY_UPDATED
#define SB_PROPERTY_CONTENTTYPE
const unsigned short CONTENTTYPE_VIDEO
const unsigned short ENUMERATIONTYPE_SNAPSHOT
This flag means that the list being enumerated is a copy that may become out of date.
static nsresult GetProperty(nsIPropertyBag2 *aProperties, nsAString const &aProp, nsAString &aValue)
#define SB_CONTINUE_IF_FAILED(_rv)
#define SB_PROPERTY_GUID
const unsigned short CONTENTTYPE_NONE
These flags specify the contentType of the media list.
already_AddRefed< sbLocalDatabaseLibrary > GetNativeLibrary()
#define SB_PROPERTY_ORIGIN_IS_IN_MAIN_LIBRARY
static nsresult FindOriginalsByID(sbIMediaItem *aMediaItem, sbIMediaList *aList, nsIMutableArray *aCopies)
_updateCookies aName
StringArrayEnumerator prototype hasMore
countRef value
Definition: FeedWriter.js:1423
nsresult MakeStandardQuery(sbIDatabaseQuery **_retval)
An object responsible for executing SQL queries on the database.
#define SB_CONTINUE_IF_FALSE(_expr)
nsresult GetMainLibrary(sbILibrary **aMainLibrary)
Interface that defines a single item of media in the system.
#define SB_PROPERTY_CUSTOMTYPE
restoreWindow aState
#define SB_PROPERTY_CONTENTURL
An interface to carry around arrays of nsIProperty instances. Users of this interface should only QI ...
#define SB_PROPERTY_ORIGINITEMGUID
_getSelectedPageStyle s i
nsTHashtable< nsStringHashKey > mFilteredProperties
#define SB_UNUSED_IN_RELEASE(decl)
Definition: sbDebugUtils.h:55
const unsigned short ENUMERATIONTYPE_LOCKING
This flag means that the list is protected from changes by other threads during the enumeration...
nsresult GetFilteredPropertiesForNewItem(sbIPropertyArray *aProperties, sbIPropertyArray **_retval)
Songbird Database Object Definition.