sbDeviceFirmwareUpdater.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 <nsILocalFile.h>
28 #include <nsIMutableArray.h>
29 #include <nsIObserverService.h>
30 #include <nsISupportsPrimitives.h>
31 #include <nsIVariant.h>
32 
33 #include <sbIDevice.h>
34 #include <sbIDeviceEvent.h>
35 #include <sbIDeviceEventTarget.h>
36 #include <sbIDeviceFirmwareHandler.h>
37 #include <sbILibraryManager.h>
38 
39 #include <nsAutoLock.h>
40 #include <nsAutoPtr.h>
41 #include <nsArrayUtils.h>
42 #include <nsComponentManagerUtils.h>
43 #include <prlog.h>
44 
46 #include "sbDeviceFirmwareUpdate.h"
47 
52 #ifdef PR_LOGGING
53 static PRLogModuleInfo* gDeviceFirmwareUpdater = nsnull;
54 #define TRACE(args) PR_LOG(gDeviceFirmwareUpdater, PR_LOG_DEBUG, args)
55 #define LOG(args) PR_LOG(gDeviceFirmwareUpdater, PR_LOG_WARN, args)
56 #else
57 #define TRACE(args) /* nothing */
58 #define LOG(args) /* nothing */
59 #endif
60 
61 #define MIN_RUNNING_HANDLERS (2)
62 
63 #define FIRMWARE_FILE_PREF "firmware.cache.file"
64 #define FIRMWARE_VERSION_PREF "firmware.cache.version"
65 #define FIRMWARE_READABLE_PREF "firmware.cache.readableVersion"
66 
71 
73 : mMonitor(nsnull)
74 , mIsShutdown(PR_FALSE)
75 {
76 #ifdef PR_LOGGING
77  if(!gDeviceFirmwareUpdater) {
78  gDeviceFirmwareUpdater = PR_NewLogModule("sbDeviceFirmwareUpdater");
79  }
80 #endif
81 }
82 
83 sbDeviceFirmwareUpdater::~sbDeviceFirmwareUpdater()
84 {
85  if(mMonitor) {
86  nsAutoMonitor::DestroyMonitor(mMonitor);
87  }
88 }
89 
90 nsresult
92 {
93  LOG(("[sbDeviceFirmwareUpdater] - Init"));
94 
95  mMonitor = nsAutoMonitor::NewMonitor("sbDeviceFirmwareUpdater::mMonitor");
96  NS_ENSURE_TRUE(mMonitor, NS_ERROR_OUT_OF_MEMORY);
97 
98  nsresult rv = NS_ERROR_UNEXPECTED;
99  nsCOMPtr<nsISimpleEnumerator> categoryEnum;
100 
101  nsCOMPtr<nsICategoryManager> cm =
102  do_GetService(NS_CATEGORYMANAGER_CONTRACTID, &rv);
103  NS_ENSURE_SUCCESS(rv, rv);
104 
105  rv = cm->EnumerateCategory(SB_DEVICE_FIRMWARE_HANDLER_CATEGORY,
106  getter_AddRefs(categoryEnum));
107  NS_ENSURE_SUCCESS(rv, rv);
108 
109  PRBool hasMore = PR_FALSE;
110  while (NS_SUCCEEDED(categoryEnum->HasMoreElements(&hasMore)) &&
111  hasMore) {
112 
113  nsCOMPtr<nsISupports> ptr;
114  if (NS_SUCCEEDED(categoryEnum->GetNext(getter_AddRefs(ptr))) &&
115  ptr) {
116 
117  nsCOMPtr<nsISupportsCString> stringValue(do_QueryInterface(ptr));
118 
119  nsCString factoryName;
120  if (stringValue &&
121  NS_SUCCEEDED(stringValue->GetData(factoryName))) {
122 
123  nsCString contractId;
124  rv = cm->GetCategoryEntry(SB_DEVICE_FIRMWARE_HANDLER_CATEGORY,
125  factoryName.get(), getter_Copies(contractId));
126  NS_ENSURE_SUCCESS(rv, rv);
127 
128  {
129  nsAutoMonitor mon(mMonitor);
130  nsCString *element =
131  mFirmwareHandlers.AppendElement(contractId);
132  NS_ENSURE_TRUE(element, NS_ERROR_OUT_OF_MEMORY);
133 
134  LOG(("[sbDeviceFirmwareUpdater] - Init - Adding %s as a firmware handler",
135  contractId.BeginReading()));
136  }
137  }
138  }
139  }
140 
141  PRBool success = mRunningHandlers.Init(MIN_RUNNING_HANDLERS);
142  NS_ENSURE_TRUE(success, NS_ERROR_OUT_OF_MEMORY);
143 
145  NS_ENSURE_TRUE(success, NS_ERROR_OUT_OF_MEMORY);
146 
147  success = mHandlerStatus.Init(MIN_RUNNING_HANDLERS);
148  NS_ENSURE_TRUE(success, NS_ERROR_OUT_OF_MEMORY);
149 
150  success = mDownloaders.Init(MIN_RUNNING_HANDLERS);
151  NS_ENSURE_TRUE(success, NS_ERROR_OUT_OF_MEMORY);
152 
153  nsCOMPtr<nsIEventTarget> threadPool =
154  do_GetService("@songbirdnest.com/Songbird/ThreadPoolService;1", &rv);
155  NS_ENSURE_SUCCESS(rv, rv);
156 
157  threadPool.swap(mThreadPool);
158 
159  nsCOMPtr<nsIObserverService> observerService =
160  do_GetService(NS_OBSERVERSERVICE_CONTRACTID, &rv);
161  NS_ENSURE_SUCCESS(rv, rv);
162 
163  rv = observerService->AddObserver(this, SB_LIBRARY_MANAGER_SHUTDOWN_TOPIC,
164  PR_FALSE);
165  NS_WARN_IF_FALSE(NS_SUCCEEDED(rv), "Failed to add library manager observer");
166 
167  return NS_OK;
168 }
169 
170 nsresult
172 {
173  NS_ENSURE_TRUE(mMonitor, NS_ERROR_NOT_INITIALIZED);
174  NS_ENSURE_FALSE(mIsShutdown, NS_ERROR_ILLEGAL_DURING_SHUTDOWN);
175 
176  nsAutoMonitor mon(mMonitor);
177 
178  // Even if we fail to shutdown we will report ourselves as shutdown.
179  // This is done on purpose to avoid new operations coming into play
180  // during the shutdown sequence under error conditions.
181  mIsShutdown = PR_TRUE;
182 
183  nsresult rv = NS_ERROR_UNEXPECTED;
184  nsCOMPtr<nsIMutableArray> mutableArray =
185  do_CreateInstance("@songbirdnest.com/moz/xpcom/threadsafe-array;1", &rv);
186  NS_ENSURE_SUCCESS(rv, rv);
187 
188  mRunningHandlers.EnumerateRead(sbDeviceFirmwareUpdater::EnumerateIntoArrayISupportsKey,
189  mutableArray.get());
190 
191  PRUint32 length = 0;
192  rv = mutableArray->GetLength(&length);
193  NS_ENSURE_SUCCESS(rv, rv);
194 
195  for(PRUint32 current = 0; current < length; ++current) {
196  nsCOMPtr<sbIDeviceFirmwareHandler> handler =
197  do_QueryElementAt(mutableArray, current, &rv);
198  NS_WARN_IF_FALSE(NS_SUCCEEDED(rv), "Bad object in hashtable!");
199  if(NS_FAILED(rv)) {
200  continue;
201  }
202 
203  sbDeviceFirmwareHandlerStatus *handlerStatus = GetHandlerStatus(handler);
204  NS_ENSURE_TRUE(handlerStatus, NS_ERROR_OUT_OF_MEMORY);
205 
208  rv = handlerStatus->GetStatus(&status);
209  NS_ENSURE_SUCCESS(rv, rv);
210 
213 
214  rv = handler->Cancel();
215  NS_WARN_IF_FALSE(NS_SUCCEEDED(rv),
216  "Failed to cancel, may not shutdown cleanly!");
217  }
218  }
219 
220  mRunningHandlers.Clear();
221  mRecoveryModeHandlers.Clear();
222  mHandlerStatus.Clear();
223  mDownloaders.Clear();
224 
225  return NS_OK;
226 }
227 
228 already_AddRefed<sbIDeviceFirmwareHandler>
230 {
231  NS_ENSURE_TRUE(aDevice, nsnull);
232 
233  sbIDeviceFirmwareHandler *_retval = nsnull;
234 
235  nsCOMPtr<sbIDeviceFirmwareHandler> handler;
236  if(mRunningHandlers.Get(aDevice, getter_AddRefs(handler))) {
237  handler.forget(&_retval);
238  }
239 
240  return _retval;
241 }
242 
243 already_AddRefed<sbIDeviceFirmwareHandler>
245  PRUint32 aVendorID,
246  PRUint32 aProductID,
247  sbIDeviceEventListener *aListener,
248  PRBool aCreate)
249 {
250  NS_ENSURE_TRUE(aDevice, nsnull);
251 
252  sbIDeviceFirmwareHandler *_retval = nsnull;
253 
254  nsCOMPtr<sbIDeviceFirmwareHandler> handler;
255  if(!mRunningHandlers.Get(aDevice, getter_AddRefs(handler)) && aCreate) {
256  nsresult rv = GetHandler(aDevice,
257  aVendorID,
258  aProductID,
259  getter_AddRefs(handler));
260  NS_ENSURE_SUCCESS(rv, nsnull);
261 
262  rv = handler->Bind(aDevice, aListener);
263  NS_ENSURE_SUCCESS(rv, nsnull);
264 
265  rv = PutRunningHandler(aDevice, handler);
266  NS_ENSURE_SUCCESS(rv, nsnull);
267  }
268 
269  if(handler) {
270  handler.forget(&_retval);
271  }
272 
273  return _retval;
274 }
275 
276 nsresult
278  sbIDeviceFirmwareHandler *aHandler)
279 {
280  NS_ENSURE_ARG_POINTER(aDevice);
281  NS_ENSURE_ARG_POINTER(aHandler);
282 
283  nsCOMPtr<sbIDeviceFirmwareHandler> handler;
284  if(!mRunningHandlers.Get(aDevice, getter_AddRefs(handler))) {
285  PRBool success = mRunningHandlers.Put(aDevice, aHandler);
286  NS_ENSURE_TRUE(success, NS_ERROR_OUT_OF_MEMORY);
287  }
288 #if defined PR_LOGGING
289  else {
290  NS_WARN_IF_FALSE(handler == aHandler,
291  "Attempting to replace a running firmware handler!");
292  }
293 #endif
294 
295  return NS_OK;
296 }
297 
300 {
301  NS_ENSURE_TRUE(mMonitor, nsnull);
302  NS_ENSURE_TRUE(aHandler, nsnull);
303 
304  nsAutoMonitor mon(mMonitor);
305  sbDeviceFirmwareHandlerStatus *_retval = nsnull;
306 
307  if(!mHandlerStatus.Get(aHandler, &_retval)) {
308  nsAutoPtr<sbDeviceFirmwareHandlerStatus> status(new sbDeviceFirmwareHandlerStatus);
309 
310  nsresult rv = status->Init();
311  NS_ENSURE_SUCCESS(rv, nsnull);
312 
313  PRBool success = mHandlerStatus.Put(aHandler, status);
314  NS_ENSURE_TRUE(success, nsnull);
315 
316  _retval = status.forget();
317  }
318 
319  return _retval;
320 }
321 
322 nsresult
324  sbIDeviceFirmwareHandler *aHandler)
325 {
326  NS_ENSURE_TRUE(mMonitor, NS_ERROR_NOT_INITIALIZED);
327  NS_ENSURE_ARG_POINTER(aDevice);
328  NS_ENSURE_ARG_POINTER(aHandler);
329 
330  PRBool needsRecoveryMode = PR_FALSE;
331 
332  nsresult rv = aHandler->GetNeedsRecoveryMode(&needsRecoveryMode);
333  NS_ENSURE_SUCCESS(rv, rv);
334 
335  if(needsRecoveryMode && !mRecoveryModeHandlers.Get(aDevice, nsnull)) {
336  PRBool success = mRecoveryModeHandlers.Put(aDevice, aHandler);
337  NS_ENSURE_TRUE(success, NS_ERROR_OUT_OF_MEMORY);
338  }
339 
340  return NS_OK;
341 }
342 
343 nsresult
345  sbIDeviceFirmwareUpdate **aUpdate)
346 {
347  nsCOMPtr<nsIVariant> firmwareVersion;
348  nsresult rv =
349  aDevice->GetPreference(NS_LITERAL_STRING(FIRMWARE_VERSION_PREF),
350  getter_AddRefs(firmwareVersion));
351  NS_ENSURE_SUCCESS(rv, rv);
352 
353  PRUint32 prefVersion = 0;
354  rv = firmwareVersion->GetAsUint32(&prefVersion);
355  NS_ENSURE_SUCCESS(rv, rv);
356 
357  rv = aDevice->GetPreference(NS_LITERAL_STRING(FIRMWARE_READABLE_PREF),
358  getter_AddRefs(firmwareVersion));
359 
360  nsString prefReadableVersion;
361  rv = firmwareVersion->GetAsAString(prefReadableVersion);
362  NS_ENSURE_SUCCESS(rv, rv);
363 
364  nsCOMPtr<nsIVariant> firmwareFilePath;
365  rv = aDevice->GetPreference(NS_LITERAL_STRING(FIRMWARE_FILE_PREF),
366  getter_AddRefs(firmwareFilePath));
367  NS_ENSURE_SUCCESS(rv, rv);
368 
369  nsString filePath;
370  rv = firmwareFilePath->GetAsAString(filePath);
371  NS_ENSURE_SUCCESS(rv, rv);
372 
373  nsCOMPtr<nsILocalFile> localFile;
374  rv = NS_NewLocalFile(filePath, PR_FALSE, getter_AddRefs(localFile));
375 
376  PRBool exists = PR_FALSE;
377  rv = localFile->Exists(&exists);
378  NS_ENSURE_SUCCESS(rv, rv);
379 
380  if(!exists) {
381  *aUpdate = nsnull;
382  return NS_OK;
383  }
384 
385  nsCOMPtr<sbIDeviceFirmwareUpdate> firmwareUpdate =
386  do_CreateInstance(SB_DEVICEFIRMWAREUPDATE_CONTRACTID, &rv);
387  NS_ENSURE_SUCCESS(rv, rv);
388 
389  rv = firmwareUpdate->Init(localFile,
390  prefReadableVersion,
391  prefVersion);
392  NS_ENSURE_SUCCESS(rv, rv);
393 
394  firmwareUpdate.forget(aUpdate);
395 
396  return NS_OK;
397 }
398 
399 NS_IMETHODIMP
400 sbDeviceFirmwareUpdater::CheckForUpdate(sbIDevice *aDevice,
401  PRUint32 aDeviceVendorID,
402  PRUint32 aDeviceProductID,
403  sbIDeviceEventListener *aListener)
404 {
405  LOG(("[sbDeviceFirmwareUpdater] - CheckForUpdate"));
406 
407  NS_ENSURE_TRUE(mMonitor, NS_ERROR_NOT_INITIALIZED);
408  NS_ENSURE_FALSE(mIsShutdown, NS_ERROR_ILLEGAL_DURING_SHUTDOWN);
409  NS_ENSURE_ARG_POINTER(aDevice);
410 
411  nsresult rv = NS_ERROR_UNEXPECTED;
412 
413  nsCOMPtr<sbIDeviceFirmwareHandler> handler =
414  GetRunningHandler(aDevice,
415  aDeviceVendorID,
416  aDeviceProductID,
417  aListener,
418  PR_TRUE);
419 
420  NS_ENSURE_TRUE(handler, NS_ERROR_UNEXPECTED);
421 
422  PRBool canUpdate;
423  rv = handler->CanUpdate(aDevice,
424  aDeviceVendorID,
425  aDeviceProductID,
426  &canUpdate);
427  NS_ENSURE_SUCCESS(rv, rv);
428  NS_ENSURE_TRUE(canUpdate, NS_ERROR_NOT_IMPLEMENTED);
429 
430  nsAutoMonitor mon(mMonitor);
431 
432  sbDeviceFirmwareHandlerStatus *handlerStatus = GetHandlerStatus(handler);
433  NS_ENSURE_TRUE(handlerStatus, NS_ERROR_OUT_OF_MEMORY);
434 
437  rv = handlerStatus->GetStatus(&status);
438  NS_ENSURE_SUCCESS(rv, rv);
439 
442  return NS_ERROR_FAILURE;
443  }
444 
445 
446  nsCOMPtr<sbIDeviceEventTarget> eventTarget = do_QueryInterface(aDevice, &rv);
447  NS_ENSURE_SUCCESS(rv, rv);
448 
449  rv = eventTarget->AddEventListener(this);
450  NS_ENSURE_SUCCESS(rv, rv);
451 
452  rv = PutRunningHandler(aDevice, handler);
453  NS_ENSURE_SUCCESS(rv, rv);
454 
456  NS_ENSURE_SUCCESS(rv, rv);
457 
459  NS_ENSURE_SUCCESS(rv, rv);
460 
461  mon.Exit();
462 
463  rv = handler->RefreshInfo();
464  NS_ENSURE_SUCCESS(rv, rv);
465 
466  return NS_OK;
467 }
468 
469 NS_IMETHODIMP
470 sbDeviceFirmwareUpdater::DownloadUpdate(sbIDevice *aDevice,
471  PRBool aVerifyFirmwareUpdate,
472  sbIDeviceEventListener *aListener)
473 {
474  LOG(("[sbDeviceFirmwareUpdater] - DownloadUpdate"));
475 
476  NS_ENSURE_TRUE(mMonitor, NS_ERROR_NOT_INITIALIZED);
477  NS_ENSURE_FALSE(mIsShutdown, NS_ERROR_ILLEGAL_DURING_SHUTDOWN);
478  NS_ENSURE_ARG_POINTER(aDevice);
479 
480  nsresult rv = NS_ERROR_UNEXPECTED;
481 
482  nsCOMPtr<sbIDeviceFirmwareHandler> handler =
483  GetRunningHandler(aDevice, 0, 0, aListener, PR_TRUE);
484 
485  nsString deviceModel;
486  rv = handler->GetDeviceModelNumber(deviceModel);
487  NS_ENSURE_SUCCESS(rv, rv);
488 
489  nsString deviceVendor;
490  rv = handler->GetDeviceVendor(deviceVendor);
491  NS_ENSURE_SUCCESS(rv, rv);
492 
493  nsAutoMonitor mon(mMonitor);
494 
495  sbDeviceFirmwareHandlerStatus *handlerStatus = GetHandlerStatus(handler);
496  NS_ENSURE_TRUE(handlerStatus, NS_ERROR_OUT_OF_MEMORY);
497 
500  rv = handlerStatus->GetStatus(&status);
501  NS_ENSURE_SUCCESS(rv, rv);
502 
505  return NS_ERROR_FAILURE;
506  }
507 
508  nsCOMPtr<sbIDeviceEventTarget> eventTarget = do_QueryInterface(aDevice, &rv);
509  NS_ENSURE_SUCCESS(rv, rv);
510 
511  rv = eventTarget->AddEventListener(this);
512  NS_ENSURE_SUCCESS(rv, rv);
513 
514  rv = PutRunningHandler(aDevice, handler);
515  NS_ENSURE_SUCCESS(rv, rv);
516 
518  NS_ENSURE_SUCCESS(rv, rv);
519 
521  NS_ENSURE_SUCCESS(rv, rv);
522 
523  mon.Exit();
524 
525  nsRefPtr<sbDeviceFirmwareDownloader> downloader;
526  NS_NEWXPCOM(downloader, sbDeviceFirmwareDownloader);
527  NS_ENSURE_TRUE(downloader, NS_ERROR_OUT_OF_MEMORY);
528 
529  if(deviceModel.IsVoid() || deviceVendor.IsVoid()) {
530  rv = downloader->Init(aDevice,
531  aListener,
532  handler);
533  NS_ENSURE_SUCCESS(rv, rv);
534  }
535  else {
536  nsString deviceCacheDirName(deviceVendor);
537  deviceCacheDirName.AppendLiteral(" ");
538  deviceCacheDirName += deviceModel;
539 
540  rv = downloader->Init(aDevice,
541  deviceCacheDirName,
542  aListener,
543  handler);
544  NS_ENSURE_SUCCESS(rv, rv);
545  }
546 
547  // Firmware Downloader is responsible for sending all necessary events.
548  rv = downloader->Start();
549  NS_ENSURE_SUCCESS(rv, rv);
550 
551  nsCOMPtr<sbIFileDownloaderListener> listener;
552  if(mDownloaders.Get(aDevice, getter_AddRefs(listener))) {
553  sbDeviceFirmwareDownloader *downloader =
554  reinterpret_cast<sbDeviceFirmwareDownloader *>(listener.get());
555 
556  rv = downloader->Cancel();
557  NS_ENSURE_SUCCESS(rv, rv);
558 
559  mDownloaders.Remove(aDevice);
560  }
561 
562  PRBool success = mDownloaders.Put(aDevice, downloader);
563  NS_ENSURE_TRUE(success, NS_ERROR_OUT_OF_MEMORY);
564 
565  return NS_OK;
566 }
567 
568 NS_IMETHODIMP
569 sbDeviceFirmwareUpdater::VerifyUpdate(sbIDevice *aDevice,
570  sbIDeviceFirmwareUpdate *aFirmwareUpdate,
571  sbIDeviceEventListener *aListener)
572 {
573  LOG(("[sbDeviceFirmwareUpdater] - VerifyUpdate"));
574 
575  NS_ENSURE_TRUE(mMonitor, NS_ERROR_NOT_INITIALIZED);
576  NS_ENSURE_FALSE(mIsShutdown, NS_ERROR_ILLEGAL_DURING_SHUTDOWN);
577  NS_ENSURE_ARG_POINTER(aDevice);
578  NS_ENSURE_ARG_POINTER(aFirmwareUpdate);
579 
580  return NS_ERROR_NOT_IMPLEMENTED;
581 }
582 
583 NS_IMETHODIMP
584 sbDeviceFirmwareUpdater::ApplyUpdate(sbIDevice *aDevice,
585  sbIDeviceFirmwareUpdate *aFirmwareUpdate,
586  sbIDeviceEventListener *aListener)
587 {
588  LOG(("[sbDeviceFirmwareUpdater] - ApplyUpdate"));
589 
590  NS_ENSURE_TRUE(mMonitor, NS_ERROR_NOT_INITIALIZED);
591  NS_ENSURE_FALSE(mIsShutdown, NS_ERROR_ILLEGAL_DURING_SHUTDOWN);
592  NS_ENSURE_ARG_POINTER(aDevice);
593  NS_ENSURE_ARG_POINTER(aFirmwareUpdate);
594 
595  nsresult rv = NS_ERROR_UNEXPECTED;
596 
597  nsCOMPtr<sbIDeviceFirmwareHandler> handler =
598  GetRunningHandler(aDevice, 0, 0, aListener, PR_TRUE);
599 
600  nsAutoMonitor mon(mMonitor);
601 
602  sbDeviceFirmwareHandlerStatus *handlerStatus = GetHandlerStatus(handler);
603  NS_ENSURE_TRUE(handlerStatus, NS_ERROR_OUT_OF_MEMORY);
604 
607  rv = handlerStatus->GetStatus(&status);
608  NS_ENSURE_SUCCESS(rv, rv);
609 
612  return NS_ERROR_FAILURE;
613  }
614 
615 
616  nsCOMPtr<sbIDeviceEventTarget> eventTarget = do_QueryInterface(aDevice, &rv);
617  NS_ENSURE_SUCCESS(rv, rv);
618 
619  rv = eventTarget->AddEventListener(this);
620  NS_ENSURE_SUCCESS(rv, rv);
621 
622  rv = PutRunningHandler(aDevice, handler);
623  NS_ENSURE_SUCCESS(rv, rv);
624 
626  NS_ENSURE_SUCCESS(rv, rv);
627 
629  NS_ENSURE_SUCCESS(rv, rv);
630 
631  mon.Exit();
632 
633  nsRefPtr<sbDeviceFirmwareUpdaterRunner> runner;
634  NS_NEWXPCOM(runner, sbDeviceFirmwareUpdaterRunner);
635  NS_ENSURE_TRUE(runner, NS_ERROR_OUT_OF_MEMORY);
636 
637  rv = runner->Init(aDevice, aFirmwareUpdate, handler);
638  NS_ENSURE_SUCCESS(rv, rv);
639 
640  rv = mThreadPool->Dispatch(runner, NS_DISPATCH_NORMAL);
641  NS_ENSURE_SUCCESS(rv, rv);
642 
643  return NS_OK;
644 }
645 
646 NS_IMETHODIMP
647 sbDeviceFirmwareUpdater::RecoveryUpdate(sbIDevice *aDevice,
648  sbIDeviceFirmwareUpdate *aFirmwareUpdate,
649  PRUint32 aDeviceVendorID,
650  PRUint32 aDeviceProductID,
651  sbIDeviceEventListener *aListener)
652 {
653  LOG(("[sbDeviceFirmwareUpdater] - RecoveryUpdate"));
654 
655  NS_ENSURE_TRUE(mMonitor, NS_ERROR_NOT_INITIALIZED);
656  NS_ENSURE_FALSE(mIsShutdown, NS_ERROR_ILLEGAL_DURING_SHUTDOWN);
657  NS_ENSURE_ARG_POINTER(aDevice);
658 
659  nsresult rv = NS_ERROR_UNEXPECTED;
660 
661  nsCOMPtr<sbIDeviceFirmwareHandler> handler =
662  GetRunningHandler(aDevice,
663  aDeviceVendorID,
664  aDeviceProductID,
665  aListener,
666  PR_TRUE);
667 
668  nsAutoMonitor mon(mMonitor);
669 
670  sbDeviceFirmwareHandlerStatus *handlerStatus = GetHandlerStatus(handler);
671  NS_ENSURE_TRUE(handlerStatus, NS_ERROR_OUT_OF_MEMORY);
672 
675  rv = handlerStatus->GetStatus(&status);
676  NS_ENSURE_SUCCESS(rv, rv);
677 
680  return NS_ERROR_FAILURE;
681  }
682 
683  nsCOMPtr<sbIDeviceEventTarget> eventTarget = do_QueryInterface(aDevice, &rv);
684  NS_ENSURE_SUCCESS(rv, rv);
685 
686  rv = eventTarget->AddEventListener(this);
687  NS_ENSURE_SUCCESS(rv, rv);
688 
689  rv = PutRunningHandler(aDevice, handler);
690  NS_ENSURE_SUCCESS(rv, rv);
691 
693  NS_ENSURE_SUCCESS(rv, rv);
694 
696  NS_ENSURE_SUCCESS(rv, rv);
697 
698  mon.Exit();
699 
700  // This will determine if we need to cache the firmware update
701  // or if it's already cached.
702  PRBool needsCaching = PR_FALSE;
703 
704  // This will be the actual final firmware update we use.
705  nsCOMPtr<sbIDeviceFirmwareUpdate> firmwareUpdate;
706 
707  // 'Default' firmware update, this may end up being the firmware update
708  // passed in as an argument
709  nsCOMPtr<sbIDeviceFirmwareUpdate> defaultFirmwareUpdate;
710 
711  // Cached firmware update
712  nsCOMPtr<sbIDeviceFirmwareUpdate> cachedFirmwareUpdate;
713  rv = GetCachedFirmwareUpdate(aDevice, getter_AddRefs(cachedFirmwareUpdate));
714  LOG(("Using cached firmware update? %s",
715  NS_SUCCEEDED(rv) ? "true" : "false"));
716 
717  // No firmware update passed, use default one.
718  if(!aFirmwareUpdate) {
719  rv = handler->GetDefaultFirmwareUpdate(getter_AddRefs(defaultFirmwareUpdate));
720  NS_ENSURE_SUCCESS(rv, rv);
721  }
722  else {
723  //
724  // Use specific firmware updated passed. In this case we assume
725  // it's available and has already been cached into the firmware cache
726  // via a download.
727  //
728  // This isn't totally awesome, it would be nice to instead check the path
729  // of the firmware image and see if it's in the firmware cache path already
730  // or not. But even then one would have to make sure it's in the exact
731  // path for the firmware cache for the device.
732  //
733  firmwareUpdate = aFirmwareUpdate;
734  needsCaching = PR_FALSE;
735  }
736 
737  // Check to make sure the cached firmware image is the same name
738  // as the default one. If not, we need to delete the cached one and use
739  // the default one. We'll also check the filesizes, if they don't match
740  // we're going to prefer the default firmware instead.
741  if(cachedFirmwareUpdate && defaultFirmwareUpdate) {
742  nsCOMPtr<nsIFile> cachedFile;
743  rv = cachedFirmwareUpdate->GetFirmwareImageFile(getter_AddRefs(cachedFile));
744  NS_ENSURE_SUCCESS(rv, rv);
745 
746  nsCOMPtr<nsIFile> defaultFile;
747  rv = defaultFirmwareUpdate->GetFirmwareImageFile(getter_AddRefs(defaultFile));
748  NS_ENSURE_SUCCESS(rv, rv);
749 
750  nsString cachedFileName, defaultFileName;
751  rv = cachedFile->GetLeafName(cachedFileName);
752  NS_ENSURE_SUCCESS(rv, rv);
753 
754  rv = defaultFile->GetLeafName(defaultFileName);
755  NS_ENSURE_SUCCESS(rv, rv);
756 
757  PRInt64 cachedFileSize = 0;
758  rv = cachedFile->GetFileSize(&cachedFileSize);
759  NS_ENSURE_SUCCESS(rv, rv);
760 
761  PRInt64 defaultFileSize = 0;
762  rv = defaultFile->GetFileSize(&defaultFileSize);
763  NS_ENSURE_SUCCESS(rv, rv);
764 
765  if((cachedFileName != defaultFileName) ||
766  (cachedFileName == defaultFileName && cachedFileSize != defaultFileSize)) {
767  nsCOMPtr<nsIFile> cacheDir;
768  rv = cachedFile->GetParent(getter_AddRefs(cacheDir));
769  NS_ENSURE_SUCCESS(rv, rv);
770 
771  rv = cachedFile->Remove(PR_FALSE);
772  NS_ENSURE_SUCCESS(rv, rv);
773 
774  nsCOMPtr<nsISimpleEnumerator> cacheDirEntries;
775  rv = cacheDir->GetDirectoryEntries(getter_AddRefs(cacheDirEntries));
776  NS_ENSURE_SUCCESS(rv, rv);
777 
778  PRBool hasMore = PR_FALSE;
779  rv = cacheDirEntries->HasMoreElements(&hasMore);
780  NS_ENSURE_SUCCESS(rv, rv);
781 
782  while(hasMore) {
783  nsCOMPtr<nsIFile> file;
784  rv = cacheDirEntries->GetNext(getter_AddRefs(file));
785  NS_ENSURE_SUCCESS(rv, rv);
786 
787  PRBool isFile = PR_FALSE;
788  rv = file->IsFile(&isFile);
789  NS_ENSURE_SUCCESS(rv, rv);
790 
791  if(isFile) {
792  rv = file->Remove(PR_FALSE);
793  NS_ENSURE_SUCCESS(rv, rv);
794  }
795 
796  rv = cacheDirEntries->HasMoreElements(&hasMore);
797  NS_ENSURE_SUCCESS(rv, rv);
798  }
799 
800  firmwareUpdate = defaultFirmwareUpdate;
801  needsCaching = PR_TRUE;
802  }
803  else {
804  firmwareUpdate = cachedFirmwareUpdate;
805  needsCaching = PR_FALSE;
806  }
807  }
808  else if(cachedFirmwareUpdate) {
809  firmwareUpdate = cachedFirmwareUpdate;
810  }
811  else if(defaultFirmwareUpdate) {
812  firmwareUpdate = defaultFirmwareUpdate;
813  needsCaching = PR_TRUE;
814  }
815  else {
816  return NS_ERROR_UNEXPECTED;
817  }
818 
819  //
820  // This isn't great to have to do this on the Main Thread
821  // but the components required to cache the firmware update
822  // are inherently NOT thread-safe and proxying to the main
823  // thread causes A LOT of badness as it pumps the main thread
824  // at a really bad time almost EVERYTIME.
825  //
826  // Long term we'd probably want to do this copy in an async
827  // manner and then call this method again after the file has been cached.
828  //
829  // Yes, this sucks if it's a 100MB firmware image. But that's really, really
830  // really, really rare :)
831  //
832  if(needsCaching) {
833  nsString deviceModel;
834  rv = handler->GetDeviceModelNumber(deviceModel);
835  NS_ENSURE_SUCCESS(rv, rv);
836 
837  nsString deviceVendor;
838  rv = handler->GetDeviceVendor(deviceVendor);
839  NS_ENSURE_SUCCESS(rv, rv);
840 
841  if(deviceModel.IsVoid() || deviceVendor.IsVoid()) {
842  nsCOMPtr<sbIDeviceFirmwareUpdate> cachedFirmwareUpdate;
844  firmwareUpdate,
845  getter_AddRefs(cachedFirmwareUpdate));
846  NS_ENSURE_SUCCESS(rv, rv);
847  }
848  else {
849  nsString deviceCacheDirName(deviceVendor);
850  deviceCacheDirName.AppendLiteral(" ");
851  deviceCacheDirName += deviceModel;
852 
853  nsCOMPtr<sbIDeviceFirmwareUpdate> cachedFirmwareUpdate;
855  deviceCacheDirName,
856  firmwareUpdate,
857  getter_AddRefs(cachedFirmwareUpdate));
858  NS_ENSURE_SUCCESS(rv, rv);
859  }
860 
861  cachedFirmwareUpdate.swap(firmwareUpdate);
862  }
863 
864  nsRefPtr<sbDeviceFirmwareUpdaterRunner> runner;
865  NS_NEWXPCOM(runner, sbDeviceFirmwareUpdaterRunner);
866  NS_ENSURE_TRUE(runner, NS_ERROR_OUT_OF_MEMORY);
867 
868  rv = runner->Init(aDevice, firmwareUpdate, handler, PR_TRUE);
869  NS_ENSURE_SUCCESS(rv, rv);
870 
871  rv = mThreadPool->Dispatch(runner, NS_DISPATCH_NORMAL);
872  NS_ENSURE_SUCCESS(rv, rv);
873 
874  return NS_OK;
875 }
876 
877 NS_IMETHODIMP
878 sbDeviceFirmwareUpdater::ContinueUpdate(sbIDevice *aDevice,
879  sbIDeviceEventListener *aListener,
880  PRBool *_retval)
881 {
882  LOG(("[sbDeviceFirmwareUpdater] - ContinueUpdate"));
883 
884  NS_ENSURE_TRUE(mMonitor, NS_ERROR_NOT_INITIALIZED);
885  NS_ENSURE_FALSE(mIsShutdown, NS_ERROR_ILLEGAL_DURING_SHUTDOWN);
886  NS_ENSURE_ARG_POINTER(aDevice);
887  NS_ENSURE_ARG_POINTER(_retval);
888 
889  nsresult rv = NS_ERROR_UNEXPECTED;
890 
891  *_retval = PR_FALSE;
892 
893  nsCOMPtr<nsIMutableArray> mutableArray =
894  do_CreateInstance("@songbirdnest.com/moz/xpcom/threadsafe-array;1", &rv);
895  NS_ENSURE_SUCCESS(rv, rv);
896 
897  mRecoveryModeHandlers.EnumerateRead(
898  sbDeviceFirmwareUpdater::EnumerateIntoArrayISupportsKey,
899  mutableArray.get());
900 
901  PRUint32 length = 0;
902  rv = mutableArray->GetLength(&length);
903  NS_ENSURE_SUCCESS(rv, rv);
904 
905  for(PRUint32 current = 0; current < length; ++current) {
906  nsCOMPtr<sbIDeviceFirmwareHandler> handler =
907  do_QueryElementAt(mutableArray, current, &rv);
908  NS_WARN_IF_FALSE(NS_SUCCEEDED(rv), "Bad object in hashtable!");
909  if(NS_FAILED(rv)) {
910  continue;
911  }
912 
913  nsCOMPtr<sbIDevice> oldDevice;
914  rv = handler->GetBoundDevice(getter_AddRefs(oldDevice));
915  NS_ENSURE_SUCCESS(rv, rv);
916 
917  PRBool success = PR_FALSE;
918  rv = handler->Rebind(aDevice, aListener, &success);
919  NS_ENSURE_SUCCESS(rv, rv);
920 
921  if(success) {
922  if (oldDevice) {
923  mRecoveryModeHandlers.Remove(oldDevice);
924  mRunningHandlers.Remove(oldDevice);
925  }
926 
927  rv = PutRunningHandler(aDevice, handler);
928  NS_ENSURE_SUCCESS(rv, rv);
929 
930  *_retval = PR_TRUE;
931 #ifdef PR_LOGGING
932  nsString contractId;
933  rv = handler->GetContractId(contractId);
934  NS_ENSURE_SUCCESS(rv, rv);
935 
936  LOG(("[%s] continueUpdate successful", __FUNCTION__));
937  LOG(("Handler with contract id %s will continue the update",
938  NS_ConvertUTF16toUTF8(contractId).BeginReading()));
939 #endif
940  return NS_OK;
941  }
942  }
943 
944  return NS_OK;
945 }
946 
947 NS_IMETHODIMP
948 sbDeviceFirmwareUpdater::FinalizeUpdate(sbIDevice *aDevice)
949 {
950  LOG(("[sbDeviceFirmwareUpdater] - FinalizeUpdate"));
951 
952  NS_ENSURE_TRUE(mMonitor, NS_ERROR_NOT_INITIALIZED);
953  NS_ENSURE_FALSE(mIsShutdown, NS_ERROR_ILLEGAL_DURING_SHUTDOWN);
954  NS_ENSURE_ARG_POINTER(aDevice);
955 
956  nsCOMPtr<sbIDeviceFirmwareHandler> handler = GetRunningHandler(aDevice);
957  NS_ENSURE_TRUE(handler, NS_OK);
958 
959  nsAutoMonitor mon(mMonitor);
960 
961  mRunningHandlers.Remove(aDevice);
962  mRecoveryModeHandlers.Remove(aDevice);
963  mHandlerStatus.Remove(handler);
964 
965  nsCOMPtr<sbIFileDownloaderListener> listener;
966  if(mDownloaders.Get(aDevice, getter_AddRefs(listener))) {
967  sbDeviceFirmwareDownloader *downloader =
968  reinterpret_cast<sbDeviceFirmwareDownloader *>(listener.get());
969 
970  nsresult rv = downloader->Cancel();
971  NS_ENSURE_SUCCESS(rv, rv);
972 
973  mDownloaders.Remove(aDevice);
974  }
975 
976  return NS_OK;
977 }
978 
979 NS_IMETHODIMP
980 sbDeviceFirmwareUpdater::VerifyDevice(sbIDevice *aDevice,
981  sbIDeviceEventListener *aListener)
982 {
983  LOG(("[sbDeviceFirmwareUpdater] - VerifyDevice"));
984 
985  NS_ENSURE_TRUE(mMonitor, NS_ERROR_NOT_INITIALIZED);
986  NS_ENSURE_FALSE(mIsShutdown, NS_ERROR_ILLEGAL_DURING_SHUTDOWN);
987  NS_ENSURE_ARG_POINTER(aDevice);
988 
989  return NS_ERROR_NOT_IMPLEMENTED;
990 }
991 
992 NS_IMETHODIMP
993 sbDeviceFirmwareUpdater::RegisterHandler(sbIDeviceFirmwareHandler *aFirmwareHandler)
994 {
995  LOG(("[sbDeviceFirmwareUpdater] - RegisterHandler"));
996 
997  NS_ENSURE_TRUE(mMonitor, NS_ERROR_NOT_INITIALIZED);
998  NS_ENSURE_FALSE(mIsShutdown, NS_ERROR_ILLEGAL_DURING_SHUTDOWN);
999  NS_ENSURE_ARG_POINTER(aFirmwareHandler);
1000 
1001  nsString contractId;
1002  nsresult rv = aFirmwareHandler->GetContractId(contractId);
1003  NS_ENSURE_SUCCESS(rv, rv);
1004 
1005  NS_ConvertUTF16toUTF8 contractId8(contractId);
1006 
1007  nsAutoMonitor mon(mMonitor);
1008  if(!mFirmwareHandlers.Contains(contractId8)) {
1009  nsCString *element = mFirmwareHandlers.AppendElement(contractId8);
1010  NS_ENSURE_TRUE(element, NS_ERROR_OUT_OF_MEMORY);
1011  }
1012 
1013  return NS_OK;
1014 }
1015 
1016 NS_IMETHODIMP
1017 sbDeviceFirmwareUpdater::UnregisterHandler(sbIDeviceFirmwareHandler *aFirmwareHandler)
1018 {
1019  LOG(("[sbDeviceFirmwareUpdater] - UnregisterHandler"));
1020 
1021  NS_ENSURE_TRUE(mMonitor, NS_ERROR_NOT_INITIALIZED);
1022  NS_ENSURE_FALSE(mIsShutdown, NS_ERROR_ILLEGAL_DURING_SHUTDOWN);
1023  NS_ENSURE_ARG_POINTER(aFirmwareHandler);
1024 
1025  nsString contractId;
1026  nsresult rv = aFirmwareHandler->GetContractId(contractId);
1027  NS_ENSURE_SUCCESS(rv, rv);
1028 
1029  NS_ConvertUTF16toUTF8 contractId8(contractId);
1030 
1031  nsAutoMonitor mon(mMonitor);
1032  firmwarehandlers_t::index_type index =
1033  mFirmwareHandlers.IndexOf(contractId8);
1034 
1035  if(index != firmwarehandlers_t::NoIndex) {
1036  mFirmwareHandlers.RemoveElementAt(index);
1037  }
1038 
1039  return NS_OK;
1040 }
1041 
1042 NS_IMETHODIMP
1043 sbDeviceFirmwareUpdater::HasHandler(sbIDevice *aDevice,
1044  PRUint32 aDeviceVendorID,
1045  PRUint32 aDeviceProductID,
1046  PRBool *_retval)
1047 {
1048  LOG(("[sbDeviceFirmwareUpdater] - HasHandler"));
1049 
1050  NS_ENSURE_TRUE(mMonitor, NS_ERROR_NOT_INITIALIZED);
1051  NS_ENSURE_FALSE(mIsShutdown, NS_ERROR_ILLEGAL_DURING_SHUTDOWN);
1052  NS_ENSURE_ARG_POINTER(aDevice);
1053  NS_ENSURE_ARG_POINTER(_retval);
1054 
1055  nsCOMPtr<sbIDeviceFirmwareHandler> handler;
1056  nsresult rv = GetHandler(aDevice,
1057  aDeviceVendorID,
1058  aDeviceProductID,
1059  getter_AddRefs(handler));
1060 
1061  *_retval = PR_FALSE;
1062  if(NS_SUCCEEDED(rv)) {
1063  *_retval = PR_TRUE;
1064  }
1065 
1066  return NS_OK;
1067 }
1068 
1069 NS_IMETHODIMP
1070 sbDeviceFirmwareUpdater::GetHandler(sbIDevice *aDevice,
1071  PRUint32 aDeviceVendorID,
1072  PRUint32 aDeviceProductID,
1073  sbIDeviceFirmwareHandler **_retval)
1074 {
1075  LOG(("[sbDeviceFirmwareUpdater] - GetHandler"));
1076 
1077  NS_ENSURE_TRUE(mMonitor, NS_ERROR_NOT_INITIALIZED);
1078  NS_ENSURE_FALSE(mIsShutdown, NS_ERROR_ILLEGAL_DURING_SHUTDOWN);
1079  NS_ENSURE_ARG_POINTER(_retval);
1080 
1081  firmwarehandlers_t firmwareHandlers;
1082 
1083  // Because our data set is pretty small, it's much nicer to copy it
1084  // rather than operating on it for a long period of time with the
1085  // monitor held.
1086  {
1087  nsAutoMonitor mon(mMonitor);
1088  nsCString *element = firmwareHandlers.AppendElements(mFirmwareHandlers);
1089  NS_ENSURE_TRUE(element, NS_ERROR_OUT_OF_MEMORY);
1090  }
1091 
1092  nsresult rv = NS_ERROR_UNEXPECTED;
1093  firmwarehandlers_t::size_type length = firmwareHandlers.Length();
1094  for(firmwarehandlers_t::size_type i = 0; i < length; ++i) {
1095  nsCOMPtr<sbIDeviceFirmwareHandler> handler =
1096  do_CreateInstance(firmwareHandlers[i].BeginReading(), &rv);
1097  if(NS_FAILED(rv)) {
1098  continue;
1099  }
1100 
1101  PRBool canHandleDevice = PR_FALSE;
1102  rv = handler->CanUpdate(aDevice,
1103  aDeviceVendorID,
1104  aDeviceProductID,
1105  &canHandleDevice);
1106  if(NS_FAILED(rv)) {
1107  continue;
1108  }
1109 
1110  // We assume there is only one device firmware handler
1111  // that can handle a device. In the future this may be
1112  // extended to put the handlers to a vote so that we may
1113  // pick the one that's most certain about its ability to
1114  // handle the device.
1115  if(canHandleDevice) {
1116  handler.forget(_retval);
1117  return NS_OK;
1118  }
1119  }
1120 
1121  return NS_ERROR_NOT_AVAILABLE;
1122 }
1123 
1124 NS_IMETHODIMP
1125 sbDeviceFirmwareUpdater::GetActiveHandler(sbIDevice *aDevice,
1126  sbIDeviceFirmwareHandler **_retval)
1127 {
1128  NS_ENSURE_TRUE(mMonitor, NS_ERROR_NOT_INITIALIZED);
1129  NS_ENSURE_FALSE(mIsShutdown, NS_ERROR_ILLEGAL_DURING_SHUTDOWN);
1130  NS_ENSURE_ARG_POINTER(aDevice);
1131  NS_ENSURE_ARG_POINTER(_retval);
1132 
1133  nsCOMPtr<sbIDeviceFirmwareHandler> handler = GetRunningHandler(aDevice);
1134  if(handler) {
1135  handler.forget(_retval);
1136  return NS_OK;
1137  }
1138 
1139  return NS_ERROR_NOT_AVAILABLE;
1140 }
1141 
1142 NS_IMETHODIMP
1143 sbDeviceFirmwareUpdater::Cancel(sbIDevice *aDevice)
1144 {
1145  NS_ENSURE_TRUE(mMonitor, NS_ERROR_NOT_INITIALIZED);
1146  NS_ENSURE_FALSE(mIsShutdown, NS_ERROR_ILLEGAL_DURING_SHUTDOWN);
1147  NS_ENSURE_ARG_POINTER(aDevice);
1148 
1149  nsAutoMonitor mon(mMonitor);
1150 
1151  nsCOMPtr<sbIDeviceFirmwareHandler> handler = GetRunningHandler(aDevice);
1152 
1153  if(handler) {
1154  nsresult rv = handler->Cancel();
1155  NS_ENSURE_SUCCESS(rv, rv);
1156 
1157  rv = handler->Unbind();
1158  NS_ENSURE_SUCCESS(rv, rv);
1159 
1160  mRunningHandlers.Remove(aDevice);
1161  mHandlerStatus.Remove(handler);
1162  }
1163 
1164  return NS_OK;
1165 }
1166 
1167 NS_IMETHODIMP
1168 sbDeviceFirmwareUpdater::RequireRecovery(sbIDevice *aDevice)
1169 {
1170  NS_ENSURE_TRUE(mMonitor, NS_ERROR_NOT_INITIALIZED);
1171  NS_ENSURE_ARG_POINTER(aDevice);
1172 
1173  nsCOMPtr<sbIDeviceFirmwareHandler> handler = GetRunningHandler(aDevice);
1174 
1175  PRBool success = mRecoveryModeHandlers.Put(aDevice, handler);
1176  NS_ENSURE_TRUE(success, NS_ERROR_OUT_OF_MEMORY);
1177 
1178  return NS_OK;
1179 }
1180 
1181 NS_IMETHODIMP
1182 sbDeviceFirmwareUpdater::OnDeviceEvent(sbIDeviceEvent *aEvent)
1183 {
1184  LOG(("[sbDeviceFirmwareUpdater] - OnDeviceEvent"));
1185 
1186  NS_ENSURE_ARG_POINTER(aEvent);
1187 
1188  nsCOMPtr<sbIDevice> device;
1189  nsresult rv = aEvent->GetOrigin(getter_AddRefs(device));
1190  NS_ENSURE_SUCCESS(rv, rv);
1191 
1192  LOG(("[sbDeviceFirmwareUpdater] - Origin Device 0x%X", device.get()));
1193 
1194  nsCOMPtr<sbIDeviceFirmwareHandler> handler = GetRunningHandler(device);
1195  NS_ENSURE_TRUE(handler, NS_OK);
1196 
1197  PRUint32 eventType = 0;
1198  rv = aEvent->GetType(&eventType);
1199  NS_ENSURE_SUCCESS(rv, rv);
1200 
1201  nsAutoMonitor mon(mMonitor);
1202  sbDeviceFirmwareHandlerStatus *handlerStatus = GetHandlerStatus(handler);
1203  NS_ENSURE_TRUE(handlerStatus, NS_ERROR_UNEXPECTED);
1204 
1207  rv = handlerStatus->GetOperation(&operation);
1208  NS_ENSURE_SUCCESS(rv, rv);
1209 
1212  rv = handlerStatus->GetStatus(&status);
1213  NS_ENSURE_SUCCESS(rv, rv);
1214 
1215  PRBool removeListener = PR_FALSE;
1216 
1217  switch(operation) {
1219  LOG(("[sbDeviceFirmwareUpdater] - OP_REFRESH"));
1220 
1221  if(eventType == sbIDeviceEvent::EVENT_FIRMWARE_CFU_START &&
1224  NS_ENSURE_SUCCESS(rv, rv);
1225  }
1226  else if((eventType == sbIDeviceEvent::EVENT_FIRMWARE_CFU_END ||
1230  NS_ENSURE_SUCCESS(rv, rv);
1231 
1232  removeListener = PR_TRUE;
1233 
1234  // Check to see if the device requires recovery mode
1235  rv = RequiresRecoveryMode(device, handler);
1236  NS_ENSURE_SUCCESS(rv, rv);
1237  }
1238  }
1239  break;
1240 
1242  LOG(("[sbDeviceFirmwareUpdater] - OP_DOWNLOAD"));
1243 
1247  NS_ENSURE_SUCCESS(rv, rv);
1248  }
1249  else if(eventType == sbIDeviceEvent::EVENT_FIRMWARE_DOWNLOAD_END &&
1252  NS_ENSURE_SUCCESS(rv, rv);
1253 
1254  removeListener = PR_TRUE;
1255  }
1256  }
1257  break;
1258 
1261  LOG(("[sbDeviceFirmwareUpdater] - OP_UPDATE or OP_RECOVERY"));
1262 
1266  NS_ENSURE_SUCCESS(rv, rv);
1267  }
1268  else if(eventType == sbIDeviceEvent::EVENT_FIRMWARE_UPDATE_END &&
1271  NS_ENSURE_SUCCESS(rv, rv);
1272 
1273  removeListener = PR_TRUE;
1274  }
1275  else if(eventType == sbIDeviceEvent::EVENT_FIRMWARE_NEEDREC_ERROR) {
1276  // Reset status when we get a NEED RECOVERY error to enable normal
1277  // operation after device is reconnected in recovery mode.
1279  NS_ENSURE_SUCCESS(rv, rv);
1280  }
1281  }
1282  break;
1283 
1284  default:
1285  NS_WARNING("Unsupported operation");
1286  }
1287 
1288  mon.Exit();
1289 
1290  if(removeListener) {
1291  nsCOMPtr<sbIDeviceEventTarget> eventTarget =
1292  do_QueryInterface(device, &rv);
1293  NS_ENSURE_SUCCESS(rv, rv);
1294 
1295  rv = eventTarget->RemoveEventListener(this);
1296  NS_ENSURE_SUCCESS(rv, rv);
1297  }
1298 
1299  return NS_OK;
1300 }
1301 
1302 template<class T>
1303 PLDHashOperator appendElementToArray(T* aData, void* aArray)
1304 {
1305  nsIMutableArray *array = (nsIMutableArray*)aArray;
1306  nsresult rv;
1307  nsCOMPtr<nsISupports> supports = do_QueryInterface(aData, &rv);
1308  NS_ENSURE_SUCCESS(rv, PL_DHASH_STOP);
1309 
1310  rv = array->AppendElement(aData, false);
1311  NS_ENSURE_SUCCESS(rv, PL_DHASH_STOP);
1312 
1313  return PL_DHASH_NEXT;
1314 }
1315 
1316 template<class T>
1317 PLDHashOperator sbDeviceFirmwareUpdater::EnumerateIntoArrayISupportsKey(
1318  nsISupports* aKey,
1319  T* aData,
1320  void* aArray)
1321 {
1322  TRACE(("sbDeviceFirmwareUpdater[0x%x] - EnumerateIntoArray (nsISupports)"));
1323  return appendElementToArray(aData, aArray);
1324 }
1325 
1326 // ----------------------------------------------------------------------------
1327 // nsIObserver
1328 // ----------------------------------------------------------------------------
1329 NS_IMETHODIMP
1330 sbDeviceFirmwareUpdater::Observe(nsISupports* aSubject,
1331  const char* aTopic,
1332  const PRUnichar* aData)
1333 {
1334  LOG(("[sbDeviceFirmwareUpdater] - Observe: %s", this, aTopic));
1335 
1336  nsresult rv;
1337  nsCOMPtr<nsIObserverService> observerService =
1338  do_GetService(NS_OBSERVERSERVICE_CONTRACTID, &rv);
1339  NS_ENSURE_SUCCESS(rv, rv);
1340 
1341  if (strcmp(aTopic, SB_LIBRARY_MANAGER_SHUTDOWN_TOPIC) == 0) {
1342  rv = observerService->RemoveObserver(this, SB_LIBRARY_MANAGER_SHUTDOWN_TOPIC);
1343  NS_WARN_IF_FALSE(NS_SUCCEEDED(rv), "Failed to remove shutdown observer");
1344 
1345  rv = Shutdown();
1346  NS_ENSURE_SUCCESS(rv, rv);
1347  }
1348 
1349  return NS_OK;
1350 }
1351 
1352 // ----------------------------------------------------------------------------
1353 // sbDeviceFirmwareHandlerStatus
1354 // ----------------------------------------------------------------------------
1355 
1357 : mMonitor(nsnull)
1358 , mOperation(OP_NONE)
1359 , mStatus(STATUS_NONE)
1360 {
1361 }
1362 
1364 {
1365  if(mMonitor) {
1366  nsAutoMonitor::DestroyMonitor(mMonitor);
1367  }
1368 }
1369 
1370 nsresult
1372 {
1373  mMonitor = nsAutoMonitor::NewMonitor("sbDeviceFirmwareHandlerStatus::mMonitor");
1374  NS_ENSURE_TRUE(mMonitor, NS_ERROR_OUT_OF_MEMORY);
1375 
1376  return NS_OK;
1377 }
1378 
1379 nsresult
1381 {
1382  NS_ENSURE_TRUE(mMonitor, NS_ERROR_NOT_INITIALIZED);
1383  NS_ENSURE_ARG_POINTER(aOperation);
1384 
1385  nsAutoMonitor mon(mMonitor);
1386  *aOperation = mOperation;
1387 
1388  return NS_OK;
1389 }
1390 
1391 nsresult
1393 {
1394  NS_ENSURE_TRUE(mMonitor, NS_ERROR_NOT_INITIALIZED);
1395 
1396  nsAutoMonitor mon(mMonitor);
1397  mOperation = aOperation;
1398 
1399  return NS_OK;
1400 }
1401 
1402 nsresult
1404 {
1405  NS_ENSURE_TRUE(mMonitor, NS_ERROR_NOT_INITIALIZED);
1406  NS_ENSURE_ARG_POINTER(aStatus);
1407 
1408  nsAutoMonitor mon(mMonitor);
1409  *aStatus = mStatus;
1410 
1411  return NS_OK;
1412 }
1413 
1414 nsresult
1416 {
1417  NS_ENSURE_TRUE(mMonitor, NS_ERROR_NOT_INITIALIZED);
1418 
1419  nsAutoMonitor mon(mMonitor);
1420  mStatus = aStatus;
1421 
1422  return NS_OK;
1423 }
1424 
1425 // -----------------------------------------------------------------------------
1426 // sbDeviceFirmwareUpdaterRunner
1427 // -----------------------------------------------------------------------------
1429  nsIRunnable);
1430 
1432 : mRecovery(PR_FALSE)
1433 {
1434 }
1435 
1436 /*virtual*/
1437 sbDeviceFirmwareUpdaterRunner::~sbDeviceFirmwareUpdaterRunner()
1438 {
1439 }
1440 
1441 nsresult
1443  sbIDeviceFirmwareUpdate *aUpdate,
1444  sbIDeviceFirmwareHandler *aHandler,
1445  PRBool aRecovery /*= PR_FALSE*/)
1446 {
1447  NS_ENSURE_ARG_POINTER(aDevice);
1448  NS_ENSURE_ARG_POINTER(aUpdate);
1449  NS_ENSURE_ARG_POINTER(aHandler);
1450 
1451  mDevice = aDevice;
1452  mFirmwareUpdate = aUpdate;
1453  mHandler = aHandler;
1454 
1455  mRecovery = aRecovery;
1456 
1457  return NS_OK;
1458 }
1459 
1460 NS_IMETHODIMP
1461 sbDeviceFirmwareUpdaterRunner::Run()
1462 {
1463  NS_ENSURE_STATE(mHandler);
1464  NS_ENSURE_STATE(mFirmwareUpdate);
1465 
1466  nsresult rv = NS_ERROR_UNEXPECTED;
1467 
1468  if(mRecovery) {
1469  rv = mHandler->Recover(mFirmwareUpdate);
1470  NS_ENSURE_SUCCESS(rv, rv);
1471  }
1472  else {
1473  rv = mHandler->Update(mFirmwareUpdate);
1474  NS_ENSURE_SUCCESS(rv, rv);
1475  }
1476 
1477  return NS_OK;
1478 }
nsresult GetOperation(handleroperation_t *aOperation)
nsCOMPtr< nsIEventTarget > mThreadPool
const unsigned long EVENT_FIRMWARE_DOWNLOAD_END
Firmware download end.
return NS_OK
nsresult RequiresRecoveryMode(sbIDevice *aDevice, sbIDeviceFirmwareHandler *aHandler)
static nsCOMPtr< nsIObserverService > observerService
Definition: UnityProxy.cpp:6
static nsresult CacheFirmwareUpdate(sbIDevice *aDevice, sbIDeviceFirmwareUpdate *aFirmwareUpdate, sbIDeviceFirmwareUpdate **aCachedFirmwareUpdate)
#define SB_LIBRARY_MANAGER_SHUTDOWN_TOPIC
const unsigned long EVENT_FIRMWARE_NEEDREC_ERROR
Firmware update requires recovery mode to be put on the device.
NS_DECL_ISUPPORTS NS_DECL_NSIRUNNABLE sbDeviceFirmwareUpdaterRunner()
inArray array
#define MIN_RUNNING_HANDLERS
nsresult PutRunningHandler(sbIDevice *aDevice, sbIDeviceFirmwareHandler *aHandler)
NS_IMPL_THREADSAFE_ISUPPORTS1(sbDeviceFirmwareUpdaterRunner, nsIRunnable)
#define SB_DEVICEFIRMWAREUPDATE_CONTRACTID
const unsigned long EVENT_FIRMWARE_CFU_END
Check for update end.
const unsigned long EVENT_FIRMWARE_UPDATE_END
Firmware update end.
nsCOMPtr< sbIDeviceFirmwareHandler > mHandler
PRUint32 mOperation
#define TRACE(args)
#define FIRMWARE_READABLE_PREF
const unsigned long EVENT_FIRMWARE_CFU_START
Check for update start.
nsresult Init(sbIDevice *aDevice, sbIDeviceFirmwareUpdate *aUpdate, sbIDeviceFirmwareHandler *aHandler, PRBool aRecovery=PR_FALSE)
const unsigned long EVENT_FIRMWARE_CFU_ERROR
Check for update error.
#define LOG(args)
nsresult SetStatus(handlerstatus_t aStatus)
nsresult GetStatus(handlerstatus_t *aStatus)
nsCOMPtr< sbIDeviceFirmwareUpdate > mFirmwareUpdate
runninghandlers_t mRecoveryModeHandlers
NS_IMPL_THREADSAFE_ISUPPORTS3(sbDeviceFirmwareUpdater, sbIDeviceFirmwareUpdater, sbIDeviceEventListener, nsIObserver) sbDeviceFirmwareUpdater
nsresult SetOperation(handleroperation_t aOperation)
#define FIRMWARE_VERSION_PREF
StringArrayEnumerator prototype hasMore
#define FIRMWARE_FILE_PREF
#define SB_DEVICE_FIRMWARE_HANDLER_CATEGORY
nsTArray< nsCString > firmwarehandlers_t
nsresult GetCachedFirmwareUpdate(sbIDevice *aDevice, sbIDeviceFirmwareUpdate **aUpdate)
PLDHashOperator appendElementToArray(T *aData, void *aArray)
_getSelectedPageStyle s i
already_AddRefed< sbIDeviceFirmwareHandler > GetRunningHandler(sbIDevice *aDevice)
GstMessage gpointer data sbGStreamerMessageHandler * handler
sbDeviceFirmwareHandlerStatus * GetHandlerStatus(sbIDeviceFirmwareHandler *aHandler)
const unsigned long EVENT_FIRMWARE_UPDATE_START
Firmware update start.
firmwarehandlers_t mFirmwareHandlers
var cm
_updateTextAndScrollDataForFrame aData
const unsigned long EVENT_FIRMWARE_DOWNLOAD_START
Firmware download start.
var file