sbLocalDatabaseLibraryLoader.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 <nsICategoryManager.h>
28 #include <nsIAppStartup.h>
29 #include <nsIFile.h>
30 #include <nsIGenericFactory.h>
31 #include <nsILocalFile.h>
32 #include <nsIObserverService.h>
33 #include <nsIIOService.h>
34 #include <nsIPrefBranch.h>
35 #include <nsIPrefService.h>
36 #include <nsIPromptService.h>
37 #include <nsIProperties.h>
38 #include <nsIPropertyBag2.h>
39 #include <nsIStringBundle.h>
40 #include <nsISupportsPrimitives.h>
41 #include <nsIURI.h>
42 #include <nsIURL.h>
43 #include <sbILibrary.h>
44 #include <sbIMediaList.h>
45 #ifdef METRICS_ENABLED
46 #include <sbIMetrics.h>
47 #endif
48 
49 #include <nsAutoPtr.h>
50 #include <nsComponentManagerUtils.h>
51 #include <nsServiceManagerUtils.h>
52 #include <nsMemory.h>
53 #include <nsNetUtil.h>
54 #include <nsServiceManagerUtils.h>
55 #include <nsTHashtable.h>
56 #include <nsXPCOMCID.h>
57 #include <nsXPFEComponentsCID.h>
58 #include <prlog.h>
59 #include <sbLibraryManager.h>
60 #include <sbMemoryUtils.h>
61 #include <sbDebugUtils.h>
62 #include "sbLocalDatabaseCID.h"
64 
65 #include <DatabaseQuery.h>
66 #include <sbIPropertyManager.h>
67 #include <sbPropertiesCID.h>
68 #include <sbStandardProperties.h>
69 #include <sbStringBundle.h>
70 
71 #define PROPERTY_KEY_DATABASEFILE "databaseFile"
72 
78 #define NS_APPSTARTUP_CATEGORY "app-startup"
79 #define NS_FINAL_UI_STARTUP_CATEGORY "final-ui-startup"
80 
81 #define PREFBRANCH_LOADER SB_PREFBRANCH_LIBRARY "loader."
82 
83 // These are on PREFBRANCH_LOADER.[index]
84 #define PREF_DATABASE_GUID "databaseGUID"
85 #define PREF_DATABASE_LOCATION "databaseLocation"
86 #define PREF_LOAD_AT_STARTUP "loadAtStartup"
87 #define PREF_RESOURCE_GUID "resourceGUID"
88 
89 // This is the pref for the URL on inaccessible library
90 #define PREF_SUPPORT_INACCESSIBLE_LIBRARY "songbird.url.support.inaccessiblelibrary"
91 
92 #define MINIMUM_LIBRARY_COUNT 2
93 #define LOADERINFO_VALUE_COUNT 4
94 
95 // XXXAus: If you change these, you must change them in DatabaseEngine.cpp
96 // as well. Failure to do so will break corrupt database recovery!
97 #define DBENGINE_GUID_MAIN_LIBRARY "main@library.songbirdnest.com"
98 #define DBENGINE_GUID_WEB_LIBRARY "web@library.songbirdnest.com"
99 #define DBENGINE_GUID_PLAYQUEUE_LIBRARY "playqueue@library.songbirdnest.com"
100 
101 // XXXben These should be renamed and standardized somehow.
102 #define SB_NAMEKEY_MAIN_LIBRARY \
103  "&chrome://songbird/locale/songbird.properties#servicesource.library"
104 #define SB_NAMEKEY_WEB_LIBRARY \
105  "&chrome://songbird/locale/songbird.properties#device.weblibrary"
106 #define SB_NAMEKEY_PLAYQUEUE_LIBRARY \
107  "&chrome://songbird/locale/songbird.properties#playqueue.library"
108 
109 #define SB_CUSTOMTYPE_MAIN_LIBRARY \
110  "local"
111 #define SB_CUSTOMTYPE_WEB_LIBRARY \
112  "web"
113 #define SB_CUSTOMTYPE_PLAYQUEUE_LIBRARY \
114  "playqueue"
115 
116 #define DEFAULT_COLUMNSPEC_WEB_LIBRARY \
117  NS_LL("http://songbirdnest.com/data/1.0#trackName 264 ") \
118  NS_LL("http://songbirdnest.com/data/1.0#duration 56 ") \
119  NS_LL("http://songbirdnest.com/data/1.0#artistName 209 ") \
120  NS_LL("http://songbirdnest.com/data/1.0#originPageImage 44 ") \
121  NS_LL("http://songbirdnest.com/data/1.0#created 119 d ") \
122  NS_LL("http://songbirdnest.com/data/1.0#downloadButton 83")
123 
124 
127 : m_DetectedCorruptLibrary(PR_FALSE)
128 , m_DeleteLibrariesAtShutdown(PR_FALSE)
129 {
131 
132  TRACE("sbLocalDatabaseLibraryLoader[0x%x] - Created", this);
133 }
134 
135 sbLocalDatabaseLibraryLoader::~sbLocalDatabaseLibraryLoader()
136 {
137  TRACE("sbLocalDatabaseLibraryLoader[0x%x] - Destroyed", this);
138 }
139 
143 nsresult
145 {
146  TRACE("sbLocalDatabaseLibraryLoader[0x%x] - Init", this);
147 
148  nsresult rv;
149 
150  nsCOMPtr<nsIObserverService> observerService =
151  do_GetService("@mozilla.org/observer-service;1", &rv);
152  if (NS_SUCCEEDED(rv)) {
153  rv = observerService->AddObserver(this, NS_FINAL_UI_STARTUP_CATEGORY,
154  PR_FALSE);
155  NS_ENSURE_SUCCESS(rv, rv);
156  rv = observerService->AddObserver(this, NS_XPCOM_SHUTDOWN_OBSERVER_ID,
157  PR_FALSE);
158  NS_ENSURE_SUCCESS(rv, rv);
159  }
160 
161  nsCOMPtr<nsIPrefService> prefService =
162  do_GetService(NS_PREFSERVICE_CONTRACTID, &rv);
163  NS_ENSURE_SUCCESS(rv, rv);
164 
165  mRootBranch = do_QueryInterface(prefService, &rv);
166  NS_ENSURE_SUCCESS(rv, rv);
167 
168  PRUint32 libraryKeysCount;
169  char** libraryKeys;
170 
171  rv = mRootBranch->GetChildList(PREFBRANCH_LOADER, &libraryKeysCount,
172  &libraryKeys);
173  NS_ENSURE_SUCCESS(rv, rv);
174 
175  sbAutoFreeXPCOMArray<char**> autoFree(libraryKeysCount, libraryKeys);
176 
177  PRBool success =
178  mLibraryInfoTable.Init(PR_MAX(MINIMUM_LIBRARY_COUNT,
179  libraryKeysCount / LOADERINFO_VALUE_COUNT));
180  NS_ENSURE_TRUE(success, NS_ERROR_FAILURE);
181 
182  for (PRUint32 index = 0; index < libraryKeysCount; index++) {
183  // Should be something like "songbird.library.loader.2.loadAtStartup".
184  nsCAutoString pref(libraryKeys[index]);
185  NS_ASSERTION(StringBeginsWith(pref, NS_LITERAL_CSTRING(PREFBRANCH_LOADER)),
186  "Bad pref string!");
187 
188  PRUint32 branchLength = NS_LITERAL_CSTRING(PREFBRANCH_LOADER).Length();
189 
190  PRInt32 firstDotIndex = pref.FindChar('.', branchLength);
191  NS_ASSERTION(firstDotIndex != -1, "Bad pref string!");
192 
193  PRUint32 keyLength = firstDotIndex - branchLength;
194  NS_ASSERTION(keyLength > 0, "Bad pref string!");
195 
196  // Should be something like "1".
197  nsCAutoString keyString(Substring(pref, branchLength, keyLength));
198  PRUint32 libraryKey = keyString.ToInteger(&rv);
199  NS_ENSURE_SUCCESS(rv, rv);
200 
201  // Should be something like "songbird.library.loader.13.".
202  nsCAutoString branchString(Substring(pref, 0, branchLength + keyLength + 1));
203  NS_ASSERTION(StringEndsWith(branchString, NS_LITERAL_CSTRING(".")),
204  "Bad pref string!");
205 
206  if (!mLibraryInfoTable.Get(libraryKey, nsnull)) {
207  nsAutoPtr<sbLibraryLoaderInfo> newLibraryInfo(new sbLibraryLoaderInfo());
208  NS_ENSURE_TRUE(newLibraryInfo, NS_ERROR_OUT_OF_MEMORY);
209 
210  rv = newLibraryInfo->Init(branchString);
211  NS_ENSURE_SUCCESS(rv, rv);
212 
213  success = mLibraryInfoTable.Put(libraryKey, newLibraryInfo);
214  NS_ENSURE_TRUE(success, NS_ERROR_FAILURE);
215 
216  newLibraryInfo.forget();
217  }
218  }
219 
220  mLibraryInfoTable.Enumerate(VerifyEntriesCallback, nsnull);
221 
222  return NS_OK;
223 }
224 
225 nsresult
226 sbLocalDatabaseLibraryLoader::EnsureDefaultLibraries()
227 {
228  PRBool databasesOkay = PR_TRUE;
229  nsresult retval = NS_OK;
230 
231  nsresult rv =
232  EnsureDefaultLibrary(NS_LITERAL_CSTRING(SB_PREF_MAIN_LIBRARY),
233  NS_LITERAL_STRING(DBENGINE_GUID_MAIN_LIBRARY),
234  NS_LITERAL_STRING(SB_NAMEKEY_MAIN_LIBRARY),
235  NS_LITERAL_STRING(SB_CUSTOMTYPE_MAIN_LIBRARY),
236  EmptyString());
237  if (NS_FAILED(rv)) {
238  databasesOkay = PR_FALSE;
239  retval = rv;
240  }
241 
242  rv = EnsureDefaultLibrary(NS_LITERAL_CSTRING(SB_PREF_WEB_LIBRARY),
243  NS_LITERAL_STRING(DBENGINE_GUID_WEB_LIBRARY),
244  NS_LITERAL_STRING(SB_NAMEKEY_WEB_LIBRARY),
245  NS_LITERAL_STRING(SB_CUSTOMTYPE_WEB_LIBRARY),
246  NS_MULTILINE_LITERAL_STRING(DEFAULT_COLUMNSPEC_WEB_LIBRARY));
247  if (NS_FAILED(rv)) {
248  databasesOkay = PR_FALSE;
249  retval = rv;
250  }
251 
252  rv = EnsureDefaultLibrary(NS_LITERAL_CSTRING(SB_PREF_PLAYQUEUE_LIBRARY),
253  NS_LITERAL_STRING(DBENGINE_GUID_PLAYQUEUE_LIBRARY),
254  NS_LITERAL_STRING(SB_NAMEKEY_PLAYQUEUE_LIBRARY),
255  NS_LITERAL_STRING(SB_CUSTOMTYPE_PLAYQUEUE_LIBRARY),
256  EmptyString());
257  if (NS_FAILED(rv)) {
258  databasesOkay = PR_FALSE;
259  retval = rv;
260  }
261 
262  if (! databasesOkay) {
263  // Bad database problem. Later we'll prompt the user. Now is so early
264  // that they would see the prompt again after a silent restart, like
265  // the ones that happen on firstrun - component registration, etc.
266  // (see Observe() for the prompt call.)
267  m_DetectedCorruptLibrary = PR_TRUE;
268 
269 #ifdef METRICS_ENABLED
270  // metric: corrupt database at startup
271  nsCOMPtr<sbIMetrics> metrics =
272  do_CreateInstance("@songbirdnest.com/Songbird/Metrics;1", &rv);
273  NS_ASSERTION(NS_SUCCEEDED(rv), "Failed to get metrics service");
274  if (NS_SUCCEEDED(rv)) {
275  nsString metricsCategory = NS_LITERAL_STRING("app");
276  nsString metricsId = NS_LITERAL_STRING("library.error");
277  rv = metrics->MetricsInc(metricsCategory, metricsId, EmptyString());
278  NS_ASSERTION(NS_SUCCEEDED(rv), "Failed to post metric");
279  }
280 #endif // METRICS_ENABLED
281 
282  }
283 
284  return retval;
285 }
286 
287 nsresult
288 sbLocalDatabaseLibraryLoader::EnsureDefaultLibrary(const nsACString& aLibraryGUIDPref,
289  const nsAString& aDefaultDatabaseGUID,
290  const nsAString& aLibraryNameKey,
291  const nsAString& aCustomType,
292  const nsAString& aDefaultColumnSpec)
293 {
294  nsCAutoString resourceGUIDPrefKey(aLibraryGUIDPref);
295 
296  // Figure out the GUID for this library.
297  nsAutoString resourceGUID;
298  PRInt32 libraryInfoIndex = -1;
299 
300  // The prefs here should point to a library resourceGUID.
301  nsCOMPtr<nsISupportsString> supportsString;
302  nsresult rv = mRootBranch->GetComplexValue(resourceGUIDPrefKey.get(),
303  NS_GET_IID(nsISupportsString),
304  getter_AddRefs(supportsString));
305  if (NS_SUCCEEDED(rv)) {
306  // Use the value stored in the prefs.
307  rv = supportsString->GetData(resourceGUID);
308  NS_ENSURE_SUCCESS(rv, rv);
309 
310  NS_ASSERTION(!resourceGUID.IsEmpty(), "Should have a resource GUID here!");
311 
312  // See if this library already exists in the hashtable.
313  sbLibraryExistsInfo existsInfo(resourceGUID);
314  mLibraryInfoTable.EnumerateRead(LibraryExistsCallback, &existsInfo);
315 
316  libraryInfoIndex = existsInfo.index;
317  }
318 
319  sbLibraryLoaderInfo* libraryInfo;
320  if ((libraryInfoIndex == -1) ||
321  (!mLibraryInfoTable.Get(libraryInfoIndex, &libraryInfo))) {
322  // The library wasn't in our hashtable, so make a new sbLibraryLoaderInfo
323  // object. That will take care of setting the prefs up correctly.
324  PRUint32 index = GetNextLibraryIndex();
325 
326  nsCAutoString prefKey(PREFBRANCH_LOADER);
327  prefKey.AppendInt(index);
328  prefKey.AppendLiteral(".");
329 
330  nsAutoPtr<sbLibraryLoaderInfo>
331  newLibraryInfo(CreateDefaultLibraryInfo(prefKey, aDefaultDatabaseGUID,
332  nsnull, aLibraryNameKey));
333  if (!newLibraryInfo || !mLibraryInfoTable.Put(index, newLibraryInfo)) {
334  return NS_ERROR_FAILURE;
335  }
336 
337  // Set the resource GUID into the prefs.
338  newLibraryInfo->GetResourceGUID(resourceGUID);
339  NS_ENSURE_FALSE(resourceGUID.IsEmpty(), NS_ERROR_UNEXPECTED);
340 
341  supportsString = do_CreateInstance(NS_SUPPORTS_STRING_CONTRACTID, &rv);
342  NS_ENSURE_SUCCESS(rv, rv);
343 
344  rv = supportsString->SetData(resourceGUID);
345  NS_ENSURE_SUCCESS(rv, rv);
346 
347  rv = mRootBranch->SetComplexValue(resourceGUIDPrefKey.get(),
348  NS_GET_IID(nsISupportsString),
349  supportsString);
350  NS_ENSURE_SUCCESS(rv, rv);
351 
352  libraryInfo = newLibraryInfo.forget();
353  }
354 
355 #ifdef DEBUG
356  nsAutoString guid;
357  libraryInfo->GetDatabaseGUID(guid);
358  NS_ASSERTION(!guid.IsEmpty(), "Empty GUID!");
359 #endif
360 
361  // Make sure this library loads at startup.
362  if (!libraryInfo->GetLoadAtStartup()) {
363  rv = libraryInfo->SetLoadAtStartup(PR_TRUE);
364  NS_ENSURE_SUCCESS(rv, rv);
365  }
366 
367  // And make sure that the database file actually exists and is accessible.
368  nsCOMPtr<nsILocalFile> location = libraryInfo->GetDatabaseLocation();
369  NS_ENSURE_TRUE(location, NS_ERROR_UNEXPECTED);
370 
371  nsCOMPtr<sbILibraryFactory> localDatabaseLibraryFactory =
372  do_GetService(SB_LOCALDATABASE_LIBRARYFACTORY_CONTRACTID, &rv);
373  NS_ENSURE_SUCCESS(rv, rv);
374 
375  sbLocalDatabaseLibraryFactory *libraryFactory =
376  reinterpret_cast<sbLocalDatabaseLibraryFactory *>(localDatabaseLibraryFactory.get());
377 
378  nsCOMPtr<sbILibrary> library;
379  rv = libraryFactory->CreateLibraryFromDatabase(location,
380  getter_AddRefs(library),
381  nsnull,
382  resourceGUID);
383  if (NS_FAILED(rv)) {
384  // We can't access this required database file. For now we're going to
385  // simply make a new blank database in the default location and switch
386  // the preferences to use it.
387  location = libraryFactory->GetFileForGUID(aDefaultDatabaseGUID);
388  NS_ENSURE_TRUE(location, NS_ERROR_FAILURE);
389 
390  // Make sure we can access this one.
391  rv = libraryFactory->CreateLibraryFromDatabase(location,
392  getter_AddRefs(library));
393  NS_ENSURE_SUCCESS(rv, rv);
394 
395  // And update the libraryInfo object.
396  rv = libraryInfo->SetDatabaseGUID(aDefaultDatabaseGUID);
397  NS_ENSURE_SUCCESS(rv, rv);
398 
399  rv = libraryInfo->SetDatabaseLocation(location);
400  NS_ENSURE_SUCCESS(rv, rv);
401 
402  rv = library->GetGuid(resourceGUID);
403  NS_ENSURE_SUCCESS(rv, rv);
404 
405  rv = libraryInfo->SetResourceGUID(resourceGUID);
406  NS_ENSURE_SUCCESS(rv, rv);
407  }
408 
409  // Set the name.
410  rv = library->SetName(aLibraryNameKey);
411  NS_ENSURE_SUCCESS(rv, rv);
412 
413  rv = library->SetProperty(NS_LITERAL_STRING(SB_PROPERTY_CUSTOMTYPE),
414  aCustomType);
415  NS_ENSURE_SUCCESS(rv, rv);
416 
417  rv = library->SetProperty(NS_LITERAL_STRING(SB_PROPERTY_ISSORTABLE),
418  NS_LITERAL_STRING("1"));
419  NS_ENSURE_SUCCESS(rv, rv);
420 
421  if (!aDefaultColumnSpec.IsEmpty()) {
422  rv = library->SetProperty(NS_LITERAL_STRING(SB_PROPERTY_DEFAULTCOLUMNSPEC),
423  aDefaultColumnSpec);
424  NS_ENSURE_SUCCESS(rv, rv);
425  }
426 
427  return NS_OK;
428 }
429 
434 sbLocalDatabaseLibraryLoader::CreateDefaultLibraryInfo(const nsACString& aPrefKey,
435  const nsAString& aDatabaseGUID,
436  nsILocalFile* aDatabaseFile,
437  const nsAString& aLibraryNameKey)
438 {
439  nsAutoPtr<sbLibraryLoaderInfo> newLibraryInfo(new sbLibraryLoaderInfo());
440  NS_ENSURE_TRUE(newLibraryInfo, nsnull);
441 
442  nsresult rv = newLibraryInfo->Init(aPrefKey);
443  NS_ENSURE_SUCCESS(rv, nsnull);
444 
445  nsCOMPtr<sbILibraryFactory> localDatabaseLibraryFactory =
446  do_GetService(SB_LOCALDATABASE_LIBRARYFACTORY_CONTRACTID, &rv);
447  NS_ENSURE_SUCCESS(rv, nsnull);
448 
449  sbLocalDatabaseLibraryFactory *libraryFactory =
450  reinterpret_cast<sbLocalDatabaseLibraryFactory *>(localDatabaseLibraryFactory.get());
451 
452  nsAutoString databaseGUID;
453 
454  if (!aDatabaseGUID.IsEmpty()) {
455  databaseGUID.Assign(aDatabaseGUID);
456  }
457  else {
458  NS_ASSERTION(aDatabaseFile, "You must supply either the GUID or file!");
459 
460  // Figure out the GUID from the filename.
461  libraryFactory->GetGUIDFromFile(aDatabaseFile, databaseGUID);
462  NS_ENSURE_FALSE(databaseGUID.IsEmpty(), nsnull);
463  }
464 
465  rv = newLibraryInfo->SetDatabaseGUID(databaseGUID);
466  NS_ENSURE_SUCCESS(rv, nsnull);
467 
468  nsCOMPtr<nsILocalFile> location;
469 
470  if (aDatabaseFile) {
471  location = aDatabaseFile;
472  }
473  else {
474  NS_ASSERTION(!aDatabaseGUID.IsEmpty(),
475  "You must specify either the GUID or file!");
476 
477  // Figure out the file from the GUID.
478  location = libraryFactory->GetFileForGUID(aDatabaseGUID);
479  NS_ENSURE_TRUE(location, nsnull);
480  }
481 
482  rv = newLibraryInfo->SetDatabaseLocation(location);
483  NS_ENSURE_SUCCESS(rv, nsnull);
484 
485  rv = newLibraryInfo->SetLoadAtStartup(PR_TRUE);
486  NS_ENSURE_SUCCESS(rv, nsnull);
487 
488  // The resource GUID is unknown at this point. Load the library and get it.
489  nsCOMPtr<sbILibrary> library;
490  rv = libraryFactory->CreateLibraryFromDatabase(location,
491  getter_AddRefs(library));
492  NS_ENSURE_SUCCESS(rv, nsnull);
493 
494  if (!aLibraryNameKey.IsEmpty()) {
495  nsCOMPtr<sbIMediaList> mediaList = do_QueryInterface(library, &rv);
496  NS_ENSURE_SUCCESS(rv, nsnull);
497 
498  // Set the name.
499  rv = mediaList->SetName(aLibraryNameKey);
500  NS_ENSURE_SUCCESS(rv, nsnull);
501  }
502 
503  nsAutoString resourceGUID;
504  rv = library->GetGuid(resourceGUID);
505  NS_ENSURE_SUCCESS(rv, nsnull);
506 
507  rv = newLibraryInfo->SetResourceGUID(resourceGUID);
508  NS_ENSURE_SUCCESS(rv, nsnull);
509 
510  nsCOMPtr<nsIPrefService> prefService = do_QueryInterface(mRootBranch, &rv);
511  NS_ENSURE_SUCCESS(rv, nsnull);
512 
513  rv = prefService->SavePrefFile(nsnull);
514  NS_ENSURE_SUCCESS(rv, nsnull);
515 
516  return newLibraryInfo.forget();
517 }
518 
519 
520 /*
521  * Something bad has happened to the user's database(s). Prompt to
522  * tell them that we need to delete their libraries. If the user says
523  * OK, set a flag and shut down the app; the actual deletion is done
524  * in the Observe() method at shutdown time.
525  */
526 NS_METHOD
527 sbLocalDatabaseLibraryLoader::PromptToDeleteLibraries()
528 {
529  nsresult rv;
530 
531  nsCOMPtr<nsIPromptService> promptService =
532  do_GetService("@mozilla.org/embedcomp/prompt-service;1", &rv);
533  NS_ENSURE_SUCCESS(rv, rv);
534 
535  PRUint32 buttons = nsIPromptService::BUTTON_POS_0 * nsIPromptService::BUTTON_TITLE_IS_STRING +
536  nsIPromptService::BUTTON_POS_1 * nsIPromptService::BUTTON_TITLE_IS_STRING +
537  nsIPromptService::BUTTON_POS_1_DEFAULT;
538 
539  PRInt32 promptResult;
540 
541  // get dialog strings
543 
544  nsAutoString dialogTitle = bundle.Get("corruptdatabase.dialog.title");
545 
546  nsAutoString dialogText = bundle.Get("corruptdatabase.dialog.text");
547 
548  nsAutoString deleteText = bundle.Get("corruptdatabase.dialog.buttons.delete");
549 
550  nsAutoString continueText =
551  bundle.Get("corruptdatabase.dialog.buttons.cancel");
552 
553 
554  // prompt.
555  rv = promptService->ConfirmEx(nsnull,
556  dialogTitle.BeginReading(),
557  dialogText.BeginReading(),
558  buttons,
559  deleteText.BeginReading(), // button 0
560  continueText.BeginReading(), // button 1
561  nsnull, // button 2
562  nsnull, // no checkbox
563  nsnull, // no check value
564  &promptResult);
565  NS_ENSURE_SUCCESS(rv, rv);
566 
567  // "Delete" means delete & restart. "Continue" means let the app
568  // start anyway.
569  if (promptResult == 0) {
570  m_DeleteLibrariesAtShutdown = PR_TRUE;
571 
572 #ifdef METRICS_ENABLED
573  // metric: user chose to delete corrupt library
574  nsCOMPtr<sbIMetrics> metrics =
575  do_CreateInstance("@songbirdnest.com/Songbird/Metrics;1", &rv);
576  NS_ASSERTION(NS_SUCCEEDED(rv), "Failed to get metrics service");
577 
578  // Metrics may not be available.
579  if (metrics) {
580  nsString metricsCategory = NS_LITERAL_STRING("app");
581  nsString metricsId = NS_LITERAL_STRING("library.error.reset");
582  rv = metrics->MetricsInc(metricsCategory, metricsId, EmptyString());
583  NS_ASSERTION(NS_SUCCEEDED(rv), "Failed to post metric");
584  }
585 #endif // METRICS_ENABLED
586 
587  // now attempt to quit/restart.
588  nsCOMPtr<nsIAppStartup> appStartup =
589  (do_GetService(NS_APPSTARTUP_CONTRACTID, &rv));
590  NS_ENSURE_SUCCESS(rv, rv);
591 
592  appStartup->Quit(nsIAppStartup::eForceQuit | nsIAppStartup::eRestart);
593  }
594 
595  return NS_OK;
596 }
597 
598 NS_METHOD
599 sbLocalDatabaseLibraryLoader::PromptInaccessibleLibraries()
600 {
601  nsresult rv;
602 
603  nsCOMPtr<nsIPromptService> promptService =
604  do_GetService("@mozilla.org/embedcomp/prompt-service;1", &rv);
605  NS_ENSURE_SUCCESS(rv, rv);
606 
607  PRUint32 buttons = nsIPromptService::BUTTON_POS_0 * nsIPromptService::BUTTON_TITLE_IS_STRING +
608  nsIPromptService::BUTTON_POS_0_DEFAULT;
609 
610  PRInt32 promptResult;
611 
612  // get dialog strings
614 
615  nsTArray<nsString> params;
616  nsCOMPtr<nsIProperties> dirService =
617  do_GetService("@mozilla.org/file/directory_service;1", &rv);
618  NS_ENSURE_SUCCESS(rv, rv);
619 
620  nsCOMPtr<nsIFile> profileDir;
621  rv = dirService->Get("ProfD",
622  NS_GET_IID(nsIFile),
623  getter_AddRefs(profileDir));
624  NS_ENSURE_SUCCESS(rv, rv);
625 
626  nsString profilePath;
627  rv = profileDir->GetPath(profilePath);
628  NS_ENSURE_SUCCESS(rv, rv);
629 
630  params.AppendElement(profilePath);
631 
632  nsCOMPtr<nsIPrefBranch> prefBranch =
633  do_GetService(NS_PREFSERVICE_CONTRACTID, &rv);
634  NS_ENSURE_SUCCESS(rv, rv);
635 
636  nsString url;
637  char* urlBuffer = nsnull;
638  rv = prefBranch->GetCharPref(PREF_SUPPORT_INACCESSIBLE_LIBRARY, &urlBuffer);
639  if (NS_SUCCEEDED(rv)) {
640  url.Assign(NS_ConvertUTF8toUTF16(nsCString(urlBuffer)));
641  NS_Free(urlBuffer);
642  } else {
643  #if PR_LOGGING
644  nsresult __rv = rv;
645  NS_ENSURE_SUCCESS_BODY(rv, rv);
646  #endif /* PR_LOGGING */
647  url = bundle.Get("database.inaccessible.dialog.url", "<error>");
648  }
649  params.AppendElement(url);
650 
651  nsAutoString dialogTitle = bundle.Get("database.inaccessible.dialog.title");
652  nsAutoString dialogText = bundle.Format("database.inaccessible.dialog.text",
653  params);
654  nsAutoString buttonText = bundle.Get("database.inaccessible.dialog.buttons.quit");
655 
656  // prompt.
657  rv = promptService->ConfirmEx(nsnull,
658  dialogTitle.BeginReading(),
659  dialogText.BeginReading(),
660  buttons,
661  buttonText.BeginReading(), // button 0
662  nsnull, // button 1
663  nsnull, // button 2
664  nsnull, // no checkbox
665  nsnull, // no check value
666  &promptResult);
667  NS_ENSURE_SUCCESS(rv, rv);
668 
669  // now attempt to quit/restart.
670  nsCOMPtr<nsIAppStartup> appStartup =
671  (do_GetService(NS_APPSTARTUP_CONTRACTID, &rv));
672  NS_ENSURE_SUCCESS(rv, rv);
673 
674  appStartup->Quit(nsIAppStartup::eForceQuit);
675 
676  return NS_OK;
677 }
678 
679 /* static */ void
680 sbLocalDatabaseLibraryLoader::RemovePrefBranch(const nsACString& aPrefBranch)
681 {
682  nsresult rv;
683  nsCOMPtr<nsIPrefService> prefService =
684  do_GetService(NS_PREFSERVICE_CONTRACTID, &rv);
685  NS_ENSURE_SUCCESS(rv,);
686 
687  nsCAutoString prefBranch(aPrefBranch);
688 
689  nsCOMPtr<nsIPrefBranch> doomedBranch;
690  rv = prefService->GetBranch(prefBranch.get(), getter_AddRefs(doomedBranch));
691  NS_ENSURE_SUCCESS(rv,);
692 
693  rv = doomedBranch->DeleteBranch("");
694  NS_ENSURE_SUCCESS(rv,);
695 
696  rv = prefService->SavePrefFile(nsnull);
697  NS_ENSURE_SUCCESS(rv,);
698 }
699 
700 PRUint32
701 sbLocalDatabaseLibraryLoader::GetNextLibraryIndex()
702 {
703  for (PRUint32 index = 0; ; index++) {
704  if (!mLibraryInfoTable.Get(index, nsnull)) {
705  return index;
706  }
707  }
708  NS_NOTREACHED("Shouldn't be here!");
709  return 0;
710 }
711 
712 /* static */ PLDHashOperator PR_CALLBACK
713 sbLocalDatabaseLibraryLoader::LoadLibrariesCallback(nsUint32HashKey::KeyType aKey,
714  sbLibraryLoaderInfo* aEntry,
715  void* aUserData)
716 {
717  sbLoaderInfo* loaderInfo = static_cast<sbLoaderInfo*>(aUserData);
718  NS_ASSERTION(loaderInfo, "Doh, how did this happen?!");
719 
720  if (!aEntry->GetLoadAtStartup()) {
721  return PL_DHASH_NEXT;
722  }
723 
724  nsCOMPtr<nsILocalFile> databaseFile = aEntry->GetDatabaseLocation();
725  NS_ASSERTION(databaseFile, "Must have a file here!");
726 
727  nsCOMPtr<sbILibrary> library;
728  nsresult rv =
729  loaderInfo->libraryFactory->CreateLibraryFromDatabase(databaseFile,
730  getter_AddRefs(library));
731  NS_ENSURE_SUCCESS(rv, PL_DHASH_NEXT);
732 
733  rv = loaderInfo->libraryManager->RegisterLibrary(library, PR_TRUE);
734  NS_ENSURE_SUCCESS(rv, PL_DHASH_NEXT);
735 
736  return PL_DHASH_NEXT;
737 }
738 
739 /* static */ PLDHashOperator PR_CALLBACK
740 sbLocalDatabaseLibraryLoader::LibraryExistsCallback(nsUint32HashKey::KeyType aKey,
741  sbLibraryLoaderInfo* aEntry,
742  void* aUserData)
743 {
744  sbLibraryExistsInfo* existsInfo =
745  static_cast<sbLibraryExistsInfo*>(aUserData);
746  NS_ASSERTION(existsInfo, "Doh, how did this happen?!");
747 
748  nsAutoString resourceGUID;
749  aEntry->GetResourceGUID(resourceGUID);
750  NS_ASSERTION(!resourceGUID.IsEmpty(), "GUID can't be empty here!");
751 
752  if (resourceGUID.Equals(existsInfo->resourceGUID)) {
753  existsInfo->index = (PRInt32)aKey;
754  return PL_DHASH_STOP;
755  }
756 
757  return PL_DHASH_NEXT;
758 }
759 
760 /* static */ PLDHashOperator PR_CALLBACK
761 sbLocalDatabaseLibraryLoader::VerifyEntriesCallback(nsUint32HashKey::KeyType aKey,
762  nsAutoPtr<sbLibraryLoaderInfo>& aEntry,
763  void* aUserData)
764 {
765  nsCAutoString prefBranch;
766  aEntry->GetPrefBranch(prefBranch);
767  NS_ASSERTION(!prefBranch.IsEmpty(), "This can't be empty!");
768 
769  nsAutoString databaseGUID;
770  aEntry->GetDatabaseGUID(databaseGUID);
771  if (databaseGUID.IsEmpty()) {
772  NS_WARNING("One of the libraries was missing a database GUID and will be removed.");
773  RemovePrefBranch(prefBranch);
774  return PL_DHASH_REMOVE;
775  }
776 
777  nsAutoString resourceGUID;
778  aEntry->GetResourceGUID(resourceGUID);
779  if (resourceGUID.IsEmpty()) {
780  NS_WARNING("One of the libraries was missing a resource GUID and will be removed.");
781  RemovePrefBranch(prefBranch);
782  return PL_DHASH_REMOVE;
783  }
784 
785  nsCOMPtr<nsILocalFile> location = aEntry->GetDatabaseLocation();
786  if (!location) {
787  NS_WARNING("One of the libraries had no location and will be removed.");
788  RemovePrefBranch(prefBranch);
789  return PL_DHASH_REMOVE;
790  }
791 
792  return PL_DHASH_NEXT;
793 }
794 
798 NS_IMETHODIMP
799 sbLocalDatabaseLibraryLoader::OnRegisterStartupLibraries(sbILibraryManager* aLibraryManager)
800 {
801  TRACE("sbLocalDatabaseLibraryLoader[0x%x] - LoadLibraries", this);
802 
803  nsresult rv = Init();
804  NS_ENSURE_SUCCESS(rv, rv);
805 
806  rv = EnsureDefaultLibraries();
807  NS_ENSURE_SUCCESS(rv, rv);
808 
809  nsCOMPtr<sbILibraryFactory> localDatabaseLibraryFactory =
810  do_GetService(SB_LOCALDATABASE_LIBRARYFACTORY_CONTRACTID, &rv);
811  NS_ENSURE_SUCCESS(rv, rv);
812 
813  sbLocalDatabaseLibraryFactory *libraryFactory =
814  reinterpret_cast<sbLocalDatabaseLibraryFactory *>(localDatabaseLibraryFactory.get());
815 
816  sbLoaderInfo info(aLibraryManager, libraryFactory);
817 
818  PRUint32 SB_UNUSED_IN_RELEASE(enumeratedLibraries) =
819  mLibraryInfoTable.EnumerateRead(LoadLibrariesCallback, &info);
820  NS_ASSERTION(enumeratedLibraries >= MINIMUM_LIBRARY_COUNT, "Too few libraries enumerated!");
821 
822  return NS_OK;
823 }
824 
825 NS_IMETHODIMP
826 sbLocalDatabaseLibraryLoader::OnLibraryStartupModified(sbILibrary* aLibrary,
827  PRBool aLoadAtStartup)
828 {
829  NS_ENSURE_ARG_POINTER(aLibrary);
830 
831  // See if we support this library type.
832  nsCOMPtr<sbILibraryFactory> factory;
833  nsresult rv = aLibrary->GetFactory(getter_AddRefs(factory));
834  NS_ENSURE_SUCCESS(rv, rv);
835 
836  nsAutoString factoryType;
837  rv = factory->GetType(factoryType);
838  NS_ENSURE_SUCCESS(rv, rv);
839 
840  NS_ENSURE_TRUE(factoryType.EqualsLiteral(SB_LOCALDATABASE_LIBRARYFACTORY_TYPE),
841  NS_ERROR_NOT_AVAILABLE);
842 
843  // See if this library already exists in the hashtable.
844  nsAutoString resourceGUID;
845  rv = aLibrary->GetGuid(resourceGUID);
846  NS_ENSURE_SUCCESS(rv, rv);
847 
848  sbLibraryExistsInfo existsInfo(resourceGUID);
849  mLibraryInfoTable.EnumerateRead(LibraryExistsCallback, &existsInfo);
850 
851  sbLibraryLoaderInfo* libraryInfo;
852  if ((existsInfo.index == -1) ||
853  (!mLibraryInfoTable.Get(existsInfo.index, &libraryInfo))) {
854 
855  // The library wasn't in the hashtable so make sure that we can recreate
856  // it.
857  nsCOMPtr<nsIPropertyBag2> creationParameters;
858  rv = aLibrary->GetCreationParameters(getter_AddRefs(creationParameters));
859  NS_ENSURE_SUCCESS(rv, rv);
860 
861  NS_NAMED_LITERAL_STRING(fileKey, PROPERTY_KEY_DATABASEFILE);
862  nsCOMPtr<nsILocalFile> databaseFile;
863  rv = creationParameters->GetPropertyAsInterface(fileKey,
864  NS_GET_IID(nsILocalFile),
865  getter_AddRefs(databaseFile));
866  NS_ENSURE_SUCCESS(rv, rv);
867 
868  NS_ASSERTION(databaseFile, "This can't be null!");
869 
870  // Make a new sbLibraryLoaderInfo object.
871  PRUint32 index = GetNextLibraryIndex();
872 
873  nsCAutoString prefKey(PREFBRANCH_LOADER);
874  prefKey.AppendInt(index);
875  prefKey.AppendLiteral(".");
876 
877  nsAutoPtr<sbLibraryLoaderInfo>
878  newLibraryInfo(CreateDefaultLibraryInfo(prefKey, EmptyString(),
879  databaseFile));
880  if (!newLibraryInfo || !mLibraryInfoTable.Put(index, newLibraryInfo)) {
881  return NS_ERROR_FAILURE;
882  }
883 
884  rv = newLibraryInfo->SetDatabaseLocation(databaseFile);
885  NS_ENSURE_SUCCESS(rv, rv);
886 
887  libraryInfo = newLibraryInfo.forget();
888  }
889 
890  rv = libraryInfo->SetLoadAtStartup(aLoadAtStartup);
891  NS_ENSURE_SUCCESS(rv, rv);
892 
893  return NS_OK;
894 }
895 
896 
897 NS_IMETHODIMP
898 sbLocalDatabaseLibraryLoader::Observe(nsISupports *aSubject,
899  const char *aTopic,
900  const PRUnichar *aData)
901 {
902  nsresult rv;
903 
904  if (strcmp(aTopic, NS_FINAL_UI_STARTUP_CATEGORY) == 0) {
905  if (m_DetectedCorruptLibrary) {
906  /* check to see if the prefs file is writable, to recover from people
907  * running the app with sudo :(
908  */
909  nsCOMPtr<nsIProperties> dirService =
910  do_GetService("@mozilla.org/file/directory_service;1", &rv);
911  NS_ENSURE_SUCCESS(rv, rv);
912 
913  nsCOMPtr<nsIFile> prefFile;
914  rv = dirService->Get("PrefF",
915  NS_GET_IID(nsIFile),
916  getter_AddRefs(prefFile));
917  NS_ENSURE_SUCCESS(rv, rv);
918 
919  PRBool prefExists;
920  /* if the pref file is missing we go through the normal first-run process
921  * and therefore don't need to care about this
922  */
923  PRBool prefWritable = PR_TRUE;
924  rv = prefFile->Exists(&prefExists);
925  if (NS_SUCCEEDED(rv) && prefExists) {
926  rv = prefFile->IsWritable(&prefWritable);
927  NS_ENSURE_SUCCESS(rv, rv);
928  }
929 
930  if (prefWritable) {
931  rv = PromptToDeleteLibraries();
932  NS_ENSURE_SUCCESS(rv, rv);
933  } else {
934  // database file is not writable, just bail
935  rv = PromptInaccessibleLibraries();
936  NS_ENSURE_SUCCESS(rv, rv);
937  }
938  }
939  } else if (strcmp(aTopic, NS_XPCOM_SHUTDOWN_OBSERVER_ID) == 0) {
940  // By now, databases should all be closed so it is safe to delete
941  // the db directory.
942  if (m_DeleteLibrariesAtShutdown) {
943  // get profile directory
944  nsCOMPtr<nsIProperties> directoryService(
945  do_GetService(NS_DIRECTORY_SERVICE_CONTRACTID, &rv));
946  NS_ENSURE_SUCCESS(rv, rv);
947 
948  nsCOMPtr<nsIFile> siteDBDir;
949  rv = directoryService->Get("ProfD", NS_GET_IID(nsIFile),
950  getter_AddRefs(siteDBDir));
951  NS_ENSURE_SUCCESS(rv, rv);
952 
953  // append the database dir name
954  siteDBDir->Append(NS_LITERAL_STRING("db"));
955 
956 
957  // Delete all the databases but the metrics DB. (which hopefully
958  // is not corrupt)
959  nsCOMPtr<nsISimpleEnumerator> dirEnumerator;
960  rv = siteDBDir->GetDirectoryEntries(getter_AddRefs(dirEnumerator));
961  NS_ENSURE_SUCCESS(rv, rv);
962 
963  PRBool hasMore;
964  dirEnumerator->HasMoreElements(&hasMore);
965  while (hasMore && NS_SUCCEEDED(rv)) {
966  nsCOMPtr<nsISupports> aSupport;
967  rv = dirEnumerator->GetNext(getter_AddRefs(aSupport));
968  if (NS_FAILED(rv)) break;
969  nsCOMPtr<nsIFile> curFile(do_QueryInterface(aSupport, &rv));
970  if (NS_FAILED(rv)) break;
971 
972  nsString leafName;
973  rv = curFile->GetLeafName(leafName);
974  if (NS_FAILED(rv)) break;
975 
976 #ifdef METRICS_ENABLED
977  if (leafName.Compare(NS_LITERAL_STRING("metrics.db")) != 0) {
978  rv = curFile->Remove(false);
979  NS_WARN_IF_FALSE(NS_SUCCEEDED(rv), "Unable to delete file");
980  }
981 #else
982  rv = curFile->Remove(false);
983  NS_WARN_IF_FALSE(NS_SUCCEEDED(rv), "Unable to delete file");
984 #endif
985 
986  dirEnumerator->HasMoreElements(&hasMore);
987  }
988 
989  // We want to prompt the user to rescan on restart.
990  nsCAutoString scancompleteBranch("songbird.firstrun.scancomplete");
991  sbLocalDatabaseLibraryLoader::RemovePrefBranch(scancompleteBranch);
992 
993  // And delete all the library prefs, so they get recreated on
994  // startup. (It would be nice to not need to do this, so that
995  // users could delete their db directory by hand and restart, but
996  // bad things happen due to prefs and it's not worth putting time
997  // into.)
998  nsCAutoString prefBranch(PREFBRANCH_LOADER);
999  sbLocalDatabaseLibraryLoader::RemovePrefBranch(prefBranch);
1000  }
1001  }
1002 
1003  return NS_OK;
1004 }
1005 
1006 
1007 
1011 nsresult
1012 sbLibraryLoaderInfo::Init(const nsACString& aPrefKey)
1013 {
1014  nsresult rv;
1015  nsCOMPtr<nsIPrefService> prefService =
1016  do_GetService(NS_PREFSERVICE_CONTRACTID, &rv);
1017  NS_ENSURE_SUCCESS(rv, rv);
1018 
1019  nsCAutoString prefBranchString(aPrefKey);
1020  rv = prefService->GetBranch(prefBranchString.get(),
1021  getter_AddRefs(mPrefBranch));
1022  NS_ENSURE_SUCCESS(rv, rv);
1023 
1024  mDatabaseGUIDKey.Assign(PREF_DATABASE_GUID);
1025  mLocationKey.Assign(PREF_DATABASE_LOCATION);
1026  mStartupKey.Assign(PREF_LOAD_AT_STARTUP);
1027  mResourceGUIDKey.Assign(PREF_RESOURCE_GUID);
1028 
1029  // Now ensure that the key exists.
1030  PRBool exists;
1031  rv = mPrefBranch->PrefHasUserValue(mStartupKey.get(), &exists);
1032  NS_ENSURE_SUCCESS(rv, rv);
1033 
1034  if (!exists) {
1035  rv = SetLoadAtStartup(PR_FALSE);
1036  NS_ENSURE_SUCCESS(rv, rv);
1037  }
1038 
1039  return NS_OK;
1040 }
1041 
1042 nsresult
1044 {
1045  NS_ENSURE_FALSE(aGUID.IsEmpty(), NS_ERROR_INVALID_ARG);
1046 
1047  nsresult rv;
1048  nsCOMPtr<nsISupportsString> supportsString =
1049  do_CreateInstance(NS_SUPPORTS_STRING_CONTRACTID, &rv);
1050  NS_ENSURE_SUCCESS(rv, rv);
1051 
1052  rv = supportsString->SetData(aGUID);
1053  NS_ENSURE_SUCCESS(rv, rv);
1054 
1055  rv = mPrefBranch->SetComplexValue(mDatabaseGUIDKey.get(),
1056  NS_GET_IID(nsISupportsString),
1057  supportsString);
1058 
1059  return NS_OK;
1060 }
1061 
1062 void
1064 {
1065  _retval.Truncate();
1066 
1067  nsCOMPtr<nsISupportsString> supportsString;
1068  nsresult rv = mPrefBranch->GetComplexValue(mDatabaseGUIDKey.get(),
1069  NS_GET_IID(nsISupportsString),
1070  getter_AddRefs(supportsString));
1071  NS_ENSURE_SUCCESS(rv,);
1072 
1073  rv = supportsString->GetData(_retval);
1074  NS_ENSURE_SUCCESS(rv,);
1075 }
1076 
1077 nsresult
1079 {
1080  NS_ENSURE_ARG_POINTER(aLocation);
1081 
1082  nsresult rv;
1083  nsCOMPtr<nsIFile> file = do_QueryInterface(aLocation, &rv);
1084  NS_ENSURE_SUCCESS(rv, rv);
1085 
1086  nsCAutoString filePath;
1087  rv = file->GetNativePath(filePath);
1088  NS_ENSURE_SUCCESS(rv, rv);
1089 
1090  rv = mPrefBranch->SetCharPref(mLocationKey.get(), filePath.get());
1091  NS_ENSURE_SUCCESS(rv, rv);
1092 
1093  return NS_OK;
1094 }
1095 
1096 already_AddRefed<nsILocalFile>
1098 {
1099  nsresult rv;
1100  nsCOMPtr<nsILocalFile> location = do_CreateInstance(NS_LOCAL_FILE_CONTRACTID, &rv);
1101  NS_ENSURE_SUCCESS(rv, nsnull);
1102 
1103  nsCAutoString filePath;
1104  rv = mPrefBranch->GetCharPref(mLocationKey.get(), getter_Copies(filePath));
1105  NS_ENSURE_SUCCESS(rv, nsnull);
1106 
1107  rv = location->InitWithNativePath(filePath);
1108  NS_ENSURE_SUCCESS(rv, nsnull);
1109 
1110  nsILocalFile* _retval;
1111  NS_ADDREF(_retval = location);
1112  return _retval;
1113 }
1114 
1115 nsresult
1117 {
1118  nsresult rv = mPrefBranch->SetBoolPref(mStartupKey.get(), aLoadAtStartup);
1119  NS_ENSURE_SUCCESS(rv, rv);
1120 
1121  return NS_OK;
1122 }
1123 
1124 PRBool
1126 {
1127  PRBool loadAtStartup;
1128  nsresult rv = mPrefBranch->GetBoolPref(mStartupKey.get(), &loadAtStartup);
1129  NS_ENSURE_SUCCESS(rv, PR_FALSE);
1130 
1131  return loadAtStartup;
1132 }
1133 
1134 nsresult
1136 {
1137  NS_ENSURE_FALSE(aGUID.IsEmpty(), NS_ERROR_INVALID_ARG);
1138 
1139  nsresult rv;
1140  nsCOMPtr<nsISupportsString> supportsString =
1141  do_CreateInstance(NS_SUPPORTS_STRING_CONTRACTID, &rv);
1142  NS_ENSURE_SUCCESS(rv, rv);
1143 
1144  rv = supportsString->SetData(aGUID);
1145  NS_ENSURE_SUCCESS(rv, rv);
1146 
1147  rv = mPrefBranch->SetComplexValue(mResourceGUIDKey.get(),
1148  NS_GET_IID(nsISupportsString),
1149  supportsString);
1150 
1151  return NS_OK;
1152 }
1153 
1154 void
1156 {
1157  _retval.Truncate();
1158 
1159  nsCOMPtr<nsISupportsString> supportsString;
1160  nsresult rv = mPrefBranch->GetComplexValue(mResourceGUIDKey.get(),
1161  NS_GET_IID(nsISupportsString),
1162  getter_AddRefs(supportsString));
1163  NS_ENSURE_SUCCESS(rv,);
1164 
1165  rv = supportsString->GetData(_retval);
1166  NS_ENSURE_SUCCESS(rv,);
1167 }
1168 
1169 void
1171 {
1172  _retval.Truncate();
1173 
1174  nsCAutoString prefBranch;
1175  nsresult rv = mPrefBranch->GetRoot(getter_Copies(prefBranch));
1176  NS_ENSURE_SUCCESS(rv,);
1177 
1178  _retval.Assign(prefBranch);
1179 }
#define DBENGINE_GUID_MAIN_LIBRARY
nsresult Init(const nsACString &aPrefKey)
#define SB_PRLOG_SETUP(x)
Definition: sbDebugUtils.h:115
return NS_OK
#define MINIMUM_LIBRARY_COUNT
#define PREF_DATABASE_LOCATION
static nsCOMPtr< nsIObserverService > observerService
Definition: UnityProxy.cpp:6
var pref
Definition: openLocation.js:44
const NS_PREFSERVICE_CONTRACTID
already_AddRefed< nsILocalFile > GetDatabaseLocation()
nsString Get(const nsAString &aKey, const nsAString &aDefault=SBVoidString())
nsString Format(const nsAString &aKey, nsTArray< nsString > &aParams, const nsAString &aDefault=SBVoidString())
#define SB_CUSTOMTYPE_PLAYQUEUE_LIBRARY
void GetGUIDFromFile(nsILocalFile *aFile, nsAString &aGUID)
#define LOADERINFO_VALUE_COUNT
Songbird Library Manager Definition.
#define SB_PROPERTY_ISSORTABLE
NS_IMPL_ISUPPORTS2(sbAlbumArtService, sbIAlbumArtService, nsIObserver) NS_IMETHODIMP sbAlbumArtService
nsresult SetLoadAtStartup(PRBool aLoadAtStartup)
#define PREF_RESOURCE_GUID
#define PREFBRANCH_LOADER
#define SB_LOCALDATABASE_LIBRARYFACTORY_CONTRACTID
Manages the lifecycle of libraries in the system.
#define PROPERTY_KEY_DATABASEFILE
var bundle
#define SB_CUSTOMTYPE_MAIN_LIBRARY
function TRACE(s)
already_AddRefed< nsILocalFile > GetFileForGUID(const nsAString &aGUID)
#define SB_PREF_PLAYQUEUE_LIBRARY
#define SB_NAMEKEY_MAIN_LIBRARY
#define SB_PROPERTY_DEFAULTCOLUMNSPEC
#define SB_CUSTOMTYPE_WEB_LIBRARY
#define DEFAULT_COLUMNSPEC_WEB_LIBRARY
nsresult SetDatabaseLocation(nsILocalFile *aLocation)
void GetPrefBranch(nsACString &_retval)
#define NS_FINAL_UI_STARTUP_CATEGORY
#define PREF_LOAD_AT_STARTUP
Media library abstraction.
Definition: sbILibrary.idl:82
void GetResourceGUID(nsAString &_retval)
Songbird String Bundle Definitions.
#define SB_PREF_MAIN_LIBRARY
#define SB_NAMEKEY_PLAYQUEUE_LIBRARY
#define DBENGINE_GUID_PLAYQUEUE_LIBRARY
function url(spec)
#define PREF_SUPPORT_INACCESSIBLE_LIBRARY
#define DBENGINE_GUID_WEB_LIBRARY
StringArrayEnumerator prototype hasMore
#define SB_PREF_WEB_LIBRARY
[USER CODE SHOULD NOT REFERENCE THIS CLASS]
let promptService
void GetDatabaseGUID(nsAString &_retval)
#define SB_LOCALDATABASE_LIBRARYFACTORY_TYPE
nsresult SetDatabaseGUID(const nsAString &aGUID)
nsresult CreateLibraryFromDatabase(nsIFile *aDatabase, sbILibrary **_retval, nsIPropertyBag2 *aCreationParameters=nsnull, nsString aResourceGUID=EmptyString())
const nsISupportsString
#define SB_PROPERTY_CUSTOMTYPE
var profileDir
#define SB_NAMEKEY_WEB_LIBRARY
nsresult SetResourceGUID(const nsAString &aGUID)
#define SB_UNUSED_IN_RELEASE(decl)
Definition: sbDebugUtils.h:55
#define PREF_DATABASE_GUID
_updateTextAndScrollDataForFrame aData
var file
Songbird Database Object Definition.