Add support for uninstalling components and use it in SupervisedUserWhitelistInstaller.

[email protected]

BUG=436459

Review URL: https://codereview.chromium.org/879993005

Cr-Commit-Position: refs/heads/master@{#315246}
diff --git a/components/component_updater/component_updater_service.cc b/components/component_updater/component_updater_service.cc
index 89195c4..4bfc2d7e 100644
--- a/components/component_updater/component_updater_service.cc
+++ b/components/component_updater/component_updater_service.cc
@@ -100,6 +100,7 @@
   Status Start() override;
   Status Stop() override;
   Status RegisterComponent(const CrxComponent& component) override;
+  Status UnregisterComponent(const std::string& crx_id) override;
   std::vector<std::string> GetComponentIDs() const override;
   OnDemandUpdater& GetOnDemandUpdater() override;
   void MaybeThrottle(const std::string& crx_id,
@@ -154,6 +155,9 @@
 
   void ProcessPendingItems();
 
+  // Uninstall and remove all unregistered work items.
+  void UninstallUnregisteredItems();
+
   // Find a component that is ready to update.
   CrxUpdateItem* FindReadyComponent() const;
 
@@ -432,6 +436,7 @@
   CrxUpdateItem* uit = FindUpdateItemById(id);
   if (uit) {
     uit->component = component;
+    uit->unregistered = false;
     return kReplaced;
   }
 
@@ -461,6 +466,19 @@
   return kOk;
 }
 
+ComponentUpdateService::Status CrxUpdateService::UnregisterComponent(
+    const std::string& crx_id) {
+  auto it = std::find_if(work_items_.begin(), work_items_.end(),
+                         CrxUpdateItem::FindById(crx_id));
+  if (it == work_items_.end())
+    return kError;
+
+  (*it)->unregistered = true;
+
+  ScheduleNextRun(kStepDelayShort);
+  return kOk;
+}
+
 std::vector<std::string> CrxUpdateService::GetComponentIDs() const {
   DCHECK(thread_checker_.CalledOnValidThread());
   std::vector<std::string> component_ids;
@@ -492,7 +510,7 @@
 
 scoped_refptr<base::SequencedTaskRunner>
 CrxUpdateService::GetSequencedTaskRunner() {
-  return config_->GetSequencedTaskRunner();
+  return blocking_task_runner_;
 }
 
 bool CrxUpdateService::GetComponentDetails(const std::string& component_id,
@@ -524,10 +542,26 @@
     return;
   }
 
+  UninstallUnregisteredItems();
+
   if (!CheckForUpdates())
     ScheduleNextRun(kStepDelayLong);
 }
 
+void CrxUpdateService::UninstallUnregisteredItems() {
+  std::vector<CrxUpdateItem*> new_work_items;
+  for (CrxUpdateItem* item : work_items_) {
+    scoped_ptr<CrxUpdateItem> owned_item(item);
+    if (owned_item->unregistered) {
+      const bool success = owned_item->component.installer->Uninstall();
+      DCHECK(success);
+    } else {
+      new_work_items.push_back(owned_item.release());
+    }
+  }
+  new_work_items.swap(work_items_);
+}
+
 CrxUpdateItem* CrxUpdateService::FindReadyComponent() const {
   class Helper {
    public:
@@ -781,6 +815,7 @@
   DCHECK(thread_checker_.CalledOnValidThread());
 
   CrxUpdateItem* crx = FindUpdateItemById(crx_context->id);
+
   DCHECK(crx->status == CrxUpdateItem::kDownloadingDiff ||
          crx->status == CrxUpdateItem::kDownloading);
 
@@ -895,6 +930,7 @@
   const bool is_success = error == ComponentUnpacker::kNone;
 
   CrxUpdateItem* item = FindUpdateItemById(component_id);
+
   if (item->status == CrxUpdateItem::kUpdatingDiff && !is_success) {
     item->diff_error_category = error_category;
     item->diff_error_code = error;