16d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)// Copyright 2014 The Chromium Authors. All rights reserved.
26d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be
36d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)// found in the LICENSE file.
46d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)
56d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)#include "chrome/browser/apps/drive/drive_app_provider.h"
66d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)
76d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)#include <vector>
86d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)
96d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)#include "base/bind.h"
106d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)#include "base/bind_helpers.h"
116d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)#include "base/logging.h"
126d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)#include "base/message_loop/message_loop.h"
136d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)#include "base/stl_util.h"
146d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)#include "chrome/browser/apps/drive/drive_app_converter.h"
156d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)#include "chrome/browser/apps/drive/drive_app_mapping.h"
166d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)#include "chrome/browser/apps/drive/drive_service_bridge.h"
176d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)#include "chrome/browser/drive/drive_app_registry.h"
186d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)#include "chrome/browser/extensions/extension_service.h"
196d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)#include "chrome/browser/profiles/profile.h"
206d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)#include "chrome/common/extensions/manifest_handlers/app_launch_info.h"
216d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)#include "extensions/browser/extension_registry.h"
226d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)#include "extensions/browser/extension_registry_factory.h"
236d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)#include "extensions/browser/extension_system.h"
245f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)#include "extensions/browser/uninstall_reason.h"
256d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)#include "extensions/common/extension.h"
266d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)
276d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)using extensions::Extension;
286d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)using extensions::ExtensionRegistry;
296d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)
306d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)namespace {
316d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)
326d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)void IgnoreUninstallResult(google_apis::GDataErrorCode) {
336d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)}
346d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)
356d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)}  // namespace
366d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)
376d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)DriveAppProvider::DriveAppProvider(Profile* profile)
386d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)    : profile_(profile),
396d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)      service_bridge_(DriveServiceBridge::Create(profile).Pass()),
406d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)      mapping_(new DriveAppMapping(profile->GetPrefs())),
416d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)      weak_ptr_factory_(this) {
426d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)  service_bridge_->GetAppRegistry()->AddObserver(this);
436d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)  ExtensionRegistry::Get(profile_)->AddObserver(this);
446d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)}
456d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)
466d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)DriveAppProvider::~DriveAppProvider() {
476d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)  ExtensionRegistry::Get(profile_)->RemoveObserver(this);
486d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)  service_bridge_->GetAppRegistry()->RemoveObserver(this);
496d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)}
506d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)
516d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)// static
526d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)void DriveAppProvider::AppendDependsOnFactories(
536d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)    std::set<BrowserContextKeyedServiceFactory*>* factories) {
546d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)  factories->insert(extensions::ExtensionRegistryFactory::GetInstance());
556d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)  DriveServiceBridge::AppendDependsOnFactories(factories);
566d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)}
576d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)
586d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)void DriveAppProvider::SetDriveServiceBridgeForTest(
596d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)    scoped_ptr<DriveServiceBridge> test_bridge) {
606d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)  service_bridge_->GetAppRegistry()->RemoveObserver(this);
616d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)  service_bridge_ = test_bridge.Pass();
626d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)  service_bridge_->GetAppRegistry()->AddObserver(this);
636d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)}
646d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)
656d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)void DriveAppProvider::UpdateMappingAndExtensionSystem(
666d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)    const std::string& drive_app_id,
676d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)    const Extension* new_app,
686d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)    bool is_new_app_generated) {
696d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)  const std::string& new_chrome_app_id = new_app->id();
706d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)
716d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)  const std::string existing_chrome_app_id =
726d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)      mapping_->GetChromeApp(drive_app_id);
736d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)  if (existing_chrome_app_id == new_chrome_app_id)
746d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)    return;
756d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)
766d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)  const bool is_existing_app_generated =
776d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)      mapping_->IsChromeAppGenerated(existing_chrome_app_id);
786d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)  mapping_->Add(drive_app_id, new_chrome_app_id, is_new_app_generated);
796d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)
806d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)  const Extension* existing_app =
816d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)      ExtensionRegistry::Get(profile_)->GetExtensionById(
826d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)          existing_chrome_app_id, ExtensionRegistry::EVERYTHING);
836d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)  if (existing_app && is_existing_app_generated) {
846d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)    extensions::ExtensionSystem::Get(profile_)
856d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)        ->extension_service()
86116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch        ->UninstallExtension(existing_chrome_app_id,
875f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                             extensions::UNINSTALL_REASON_SYNC,
885f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                             base::Bind(&base::DoNothing),
89116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch                             NULL);
906d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)  }
916d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)}
926d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)
936d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)void DriveAppProvider::ProcessDeferredOnExtensionInstalled(
946d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)    const std::string drive_app_id,
956d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)    const std::string chrome_app_id) {
966d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)  const Extension* app = ExtensionRegistry::Get(profile_)->GetExtensionById(
976d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)      chrome_app_id, ExtensionRegistry::EVERYTHING);
986d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)  if (!app)
996d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)    return;
1006d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)
1016d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)  UpdateMappingAndExtensionSystem(drive_app_id, app, false);
1026d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)}
1036d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)
1046d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)void DriveAppProvider::SchedulePendingConverters() {
1056d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)  if (pending_converters_.empty())
1066d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)    return;
1076d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)
1086d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)  if (!pending_converters_.front()->IsStarted())
1096d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)    pending_converters_.front()->Start();
1106d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)}
1116d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)
1126d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)void DriveAppProvider::OnLocalAppConverted(const DriveAppConverter* converter,
1136d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)                                           bool success) {
1146d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)  DCHECK_EQ(pending_converters_.front(), converter);
1156d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)
1166d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)  if (success) {
1176d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)    const bool was_generated =
1186d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)        mapping_->GetDriveApp(converter->extension()->id()) ==
1196d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)            converter->drive_app_info().app_id &&
1206d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)        mapping_->IsChromeAppGenerated(converter->extension()->id());
1216d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)    UpdateMappingAndExtensionSystem(
1226d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)        converter->drive_app_info().app_id,
1236d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)        converter->extension(),
1246d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)        converter->is_new_install() || was_generated);
1256d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)  } else {
1266d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)    LOG(WARNING) << "Failed to convert drive app to web app, "
1276d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)                 << "drive app id= " << converter->drive_app_info().app_id
1286d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)                 << ", name=" << converter->drive_app_info().app_name;
1296d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)  }
1306d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)
1316d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)  pending_converters_.erase(pending_converters_.begin());
1326d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)  SchedulePendingConverters();
1336d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)}
1346d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)
1356d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)bool DriveAppProvider::IsMappedUrlAppUpToDate(
1366d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)    const drive::DriveAppInfo& drive_app) const {
1376d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)  const std::string& url_app_id = mapping_->GetChromeApp(drive_app.app_id);
1386d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)  if (url_app_id.empty())
1396d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)    return false;
1406d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)
1416d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)  const Extension* url_app = ExtensionRegistry::Get(profile_)->GetExtensionById(
1426d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)      url_app_id, ExtensionRegistry::EVERYTHING);
1436d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)  if (!url_app)
1446d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)    return false;
1456d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)  DCHECK(url_app->is_hosted_app() && url_app->from_bookmark());
1466d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)
1476d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)  return drive_app.app_name == url_app->name() &&
1486d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)         drive_app.create_url ==
1496d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)             extensions::AppLaunchInfo::GetLaunchWebURL(url_app);
1506d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)}
1516d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)
1526d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)void DriveAppProvider::AddOrUpdateDriveApp(
1536d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)    const drive::DriveAppInfo& drive_app) {
1546d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)  const Extension* chrome_app =
1556d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)      ExtensionRegistry::Get(profile_)->GetExtensionById(
1566d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)          drive_app.product_id, ExtensionRegistry::EVERYTHING);
1576d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)  if (chrome_app) {
1586d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)    UpdateMappingAndExtensionSystem(drive_app.app_id, chrome_app, false);
1596d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)    return;
1606d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)  }
1616d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)
1626d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)  if (IsMappedUrlAppUpToDate(drive_app))
1636d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)    return;
1646d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)
1656d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)  ScopedVector<DriveAppConverter>::iterator it = pending_converters_.begin();
1666d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)  while (it != pending_converters_.end()) {
1676d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)    if (!(*it)->IsStarted() &&
1686d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)        (*it)->drive_app_info().app_id == drive_app.app_id) {
1696d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)      it = pending_converters_.erase(it);
1706d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)    } else {
1716d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)      ++it;
1726d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)    }
1736d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)  }
1746d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)
1756d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)  pending_converters_.push_back(
1766d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)      new DriveAppConverter(profile_,
1776d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)                            drive_app,
1786d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)                            base::Bind(&DriveAppProvider::OnLocalAppConverted,
1796d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)                                       base::Unretained(this))));
1806d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)}
1816d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)
1826d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)void DriveAppProvider::ProcessRemovedDriveApp(const std::string& drive_app_id) {
1836d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)  const std::string chrome_app_id = mapping_->GetChromeApp(drive_app_id);
1846d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)  const bool is_generated = mapping_->IsChromeAppGenerated(chrome_app_id);
1856d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)  mapping_->Remove(drive_app_id);
1866d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)
1876d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)  if (chrome_app_id.empty() || !is_generated)
1886d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)    return;
1896d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)
1906d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)  const Extension* existing_app =
1916d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)      ExtensionRegistry::Get(profile_)
1926d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)          ->GetExtensionById(chrome_app_id, ExtensionRegistry::EVERYTHING);
1936d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)  if (!existing_app)
1946d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)    return;
1956d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)
1966d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)  extensions::ExtensionSystem::Get(profile_)
1976d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)      ->extension_service()
1985f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)      ->UninstallExtension(chrome_app_id,
1995f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                           extensions::UNINSTALL_REASON_SYNC,
2005f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                           base::Bind(&base::DoNothing),
2015f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                           NULL);
2026d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)}
2036d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)
2046d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)void DriveAppProvider::OnDriveAppRegistryUpdated() {
2056d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)  service_bridge_->GetAppRegistry()->GetAppList(&drive_apps_);
2066d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)
2076d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)  IdSet current_ids;
2086d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)  for (size_t i = 0; i < drive_apps_.size(); ++i)
2096d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)    current_ids.insert(drive_apps_[i].app_id);
2106d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)
2116d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)  const IdSet existing_ids = mapping_->GetDriveAppIds();
2126d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)  const IdSet ids_to_remove =
2136d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)      base::STLSetDifference<IdSet>(existing_ids, current_ids);
2146d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)  for (IdSet::const_iterator it = ids_to_remove.begin();
2156d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)       it != ids_to_remove.end();
2166d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)       ++it) {
2176d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)    ProcessRemovedDriveApp(*it);
2186d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)  }
2196d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)
2206d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)  for (size_t i = 0; i < drive_apps_.size(); ++i) {
2216d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)    AddOrUpdateDriveApp(drive_apps_[i]);
2226d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)  }
2236d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)  SchedulePendingConverters();
2246d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)}
2256d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)
2266d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)void DriveAppProvider::OnExtensionInstalled(
2276d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)    content::BrowserContext* browser_context,
228116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    const Extension* extension,
229116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    bool is_update) {
2306d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)  // Bail if the |extension| is installed from a converter. The post install
2316d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)  // processing will be handled in OnLocalAppConverted.
2326d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)  if (!pending_converters_.empty() &&
2336d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)      pending_converters_.front()->IsInstalling(extension->id())) {
2346d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)    return;
2356d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)  }
2366d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)
2376d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)  // Only user installed app reaches here. If it is mapped, make sure it is not
2386d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)  // tagged as generated.
2396d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)  const std::string drive_app_id = mapping_->GetDriveApp(extension->id());
2406d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)  if (!drive_app_id.empty() &&
2416d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)      mapping_->IsChromeAppGenerated(extension->id())) {
2426d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)    mapping_->Add(drive_app_id, extension->id(), false);
2436d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)    return;
2446d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)  }
2456d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)
2466d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)  for (size_t i = 0; i < drive_apps_.size(); ++i) {
2476d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)    if (drive_apps_[i].product_id == extension->id()) {
2486d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)      // Defer the processing because it touches the extensions system and
2496d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)      // it is better to let the current task finish to avoid unexpected
2506d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)      // incomplete status.
2516d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)      base::MessageLoop::current()->PostTask(
2526d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)          FROM_HERE,
2536d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)          base::Bind(&DriveAppProvider::ProcessDeferredOnExtensionInstalled,
2546d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)                     weak_ptr_factory_.GetWeakPtr(),
2556d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)                     drive_apps_[i].app_id,
2566d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)                     extension->id()));
2576d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)      return;
2586d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)    }
2596d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)  }
2606d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)}
2616d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)
2626d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)void DriveAppProvider::OnExtensionUninstalled(
2636d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)    content::BrowserContext* browser_context,
2645f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    const Extension* extension,
2655f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    extensions::UninstallReason reason) {
2666d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)  std::string drive_app_id = mapping_->GetDriveApp(extension->id());
2676d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)  if (drive_app_id.empty())
2686d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)    return;
2696d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)
2706d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)  service_bridge_->GetAppRegistry()->UninstallApp(
2716d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)      drive_app_id, base::Bind(&IgnoreUninstallResult));
2726d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)}
273