// Copyright (c) 2012 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "chrome/browser/background/background_application_list_model.h"

#include <algorithm>
#include <set>

#include "base/sha1.h"
#include "base/stl_util.h"
#include "base/strings/string_number_conversions.h"
#include "base/strings/utf_string_conversions.h"
#include "chrome/app/chrome_command_ids.h"
#include "chrome/browser/background/background_contents_service.h"
#include "chrome/browser/background/background_contents_service_factory.h"
#include "chrome/browser/background/background_mode_manager.h"
#include "chrome/browser/browser_process.h"
#include "chrome/browser/chrome_notification_types.h"
#include "chrome/browser/extensions/extension_prefs.h"
#include "chrome/browser/extensions/extension_service.h"
#include "chrome/browser/extensions/extension_system.h"
#include "chrome/browser/extensions/image_loader.h"
#include "chrome/browser/profiles/profile.h"
#include "chrome/common/extensions/extension_constants.h"
#include "chrome/common/extensions/extension_icon_set.h"
#include "chrome/common/extensions/manifest_handlers/icons_handler.h"
#include "content/public/browser/notification_details.h"
#include "content/public/browser/notification_source.h"
#include "extensions/common/extension.h"
#include "extensions/common/extension_resource.h"
#include "extensions/common/manifest_handlers/background_info.h"
#include "extensions/common/permissions/permission_set.h"
#include "ui/base/l10n/l10n_util_collator.h"
#include "ui/gfx/image/image.h"
#include "ui/gfx/image/image_skia.h"

using extensions::APIPermission;
using extensions::Extension;
using extensions::ExtensionList;
using extensions::PermissionSet;
using extensions::UnloadedExtensionInfo;
using extensions::UpdatedExtensionPermissionsInfo;

class ExtensionNameComparator {
 public:
  explicit ExtensionNameComparator(icu::Collator* collator);
  bool operator()(const scoped_refptr<const Extension>& x,
                  const scoped_refptr<const Extension>& y);

 private:
  icu::Collator* collator_;
};

ExtensionNameComparator::ExtensionNameComparator(icu::Collator* collator)
  : collator_(collator) {
}

bool ExtensionNameComparator::operator()(
    const scoped_refptr<const Extension>& x,
    const scoped_refptr<const Extension>& y) {
  return l10n_util::StringComparator<string16>(collator_)(
      UTF8ToUTF16(x->name()), UTF8ToUTF16(y->name()));
}

// Background application representation, private to the
// BackgroundApplicationListModel class.
class BackgroundApplicationListModel::Application
    : public base::SupportsWeakPtr<Application> {
 public:
  Application(BackgroundApplicationListModel* model,
              const Extension* an_extension);

  virtual ~Application();

  // Invoked when a request icon is available.
  void OnImageLoaded(const gfx::Image& image);

  // Uses the FILE thread to request this extension's icon, sized
  // appropriately.
  void RequestIcon(extension_misc::ExtensionIcons size);

  const Extension* extension_;
  scoped_ptr<gfx::ImageSkia> icon_;
  BackgroundApplicationListModel* model_;
};

namespace {
void GetServiceApplications(ExtensionService* service,
                            ExtensionList* applications_result) {
  const ExtensionSet* extensions = service->extensions();

  for (ExtensionSet::const_iterator cursor = extensions->begin();
       cursor != extensions->end();
       ++cursor) {
    const Extension* extension = cursor->get();
    if (BackgroundApplicationListModel::IsBackgroundApp(*extension,
                                                        service->profile())) {
      applications_result->push_back(extension);
    }
  }

  // Walk the list of terminated extensions also (just because an extension
  // crashed doesn't mean we should ignore it).
  extensions = service->terminated_extensions();
  for (ExtensionSet::const_iterator cursor = extensions->begin();
       cursor != extensions->end();
       ++cursor) {
    const Extension* extension = cursor->get();
    if (BackgroundApplicationListModel::IsBackgroundApp(*extension,
                                                        service->profile())) {
      applications_result->push_back(extension);
    }
  }

  std::string locale = g_browser_process->GetApplicationLocale();
  icu::Locale loc(locale.c_str());
  UErrorCode error = U_ZERO_ERROR;
  scoped_ptr<icu::Collator> collator(icu::Collator::createInstance(loc, error));
  std::sort(applications_result->begin(), applications_result->end(),
       ExtensionNameComparator(collator.get()));
}

}  // namespace

void
BackgroundApplicationListModel::Observer::OnApplicationDataChanged(
    const Extension* extension, Profile* profile) {
}

void
BackgroundApplicationListModel::Observer::OnApplicationListChanged(
    Profile* profile) {
}

BackgroundApplicationListModel::Observer::~Observer() {
}

BackgroundApplicationListModel::Application::~Application() {
}

BackgroundApplicationListModel::Application::Application(
    BackgroundApplicationListModel* model,
    const Extension* extension)
    : extension_(extension), model_(model) {}

void BackgroundApplicationListModel::Application::OnImageLoaded(
    const gfx::Image& image) {
  if (image.IsEmpty())
    return;
  icon_.reset(image.CopyImageSkia());
  model_->SendApplicationDataChangedNotifications(extension_);
}

void BackgroundApplicationListModel::Application::RequestIcon(
    extension_misc::ExtensionIcons size) {
  extensions::ExtensionResource resource =
      extensions::IconsInfo::GetIconResource(
          extension_, size, ExtensionIconSet::MATCH_BIGGER);
  extensions::ImageLoader::Get(model_->profile_)->LoadImageAsync(
      extension_, resource, gfx::Size(size, size),
      base::Bind(&Application::OnImageLoaded, AsWeakPtr()));
}

BackgroundApplicationListModel::~BackgroundApplicationListModel() {
  STLDeleteContainerPairSecondPointers(applications_.begin(),
                                       applications_.end());
}

BackgroundApplicationListModel::BackgroundApplicationListModel(Profile* profile)
    : profile_(profile) {
  DCHECK(profile_);
  registrar_.Add(this,
                 chrome::NOTIFICATION_EXTENSION_LOADED,
                 content::Source<Profile>(profile));
  registrar_.Add(this,
                 chrome::NOTIFICATION_EXTENSION_UNLOADED,
                 content::Source<Profile>(profile));
  registrar_.Add(this,
                 chrome::NOTIFICATION_EXTENSIONS_READY,
                 content::Source<Profile>(profile));
  registrar_.Add(this,
                 chrome::NOTIFICATION_EXTENSION_PERMISSIONS_UPDATED,
                 content::Source<Profile>(profile));
  registrar_.Add(this,
                 chrome::NOTIFICATION_BACKGROUND_CONTENTS_SERVICE_CHANGED,
                 content::Source<Profile>(profile));
  ExtensionService* service = extensions::ExtensionSystem::Get(profile)->
      extension_service();
  if (service && service->is_ready())
    Update();
}

void BackgroundApplicationListModel::AddObserver(Observer* observer) {
  observers_.AddObserver(observer);
}

void BackgroundApplicationListModel::AssociateApplicationData(
    const Extension* extension) {
  DCHECK(IsBackgroundApp(*extension, profile_));
  Application* application = FindApplication(extension);
  if (!application) {
    // App position is used as a dynamic command and so must be less than any
    // predefined command id.
    if (applications_.size() >= IDC_MinimumLabelValue) {
      LOG(ERROR) << "Background application limit of " << IDC_MinimumLabelValue
                 << " exceeded.  Ignoring.";
      return;
    }
    application = new Application(this, extension);
    applications_[extension->id()] = application;
    Update();
    application->RequestIcon(extension_misc::EXTENSION_ICON_BITTY);
  }
}

void BackgroundApplicationListModel::DissociateApplicationData(
    const Extension* extension) {
  ApplicationMap::iterator found = applications_.find(extension->id());
  if (found != applications_.end()) {
    delete found->second;
    applications_.erase(found);
  }
}

const Extension* BackgroundApplicationListModel::GetExtension(
    int position) const {
  DCHECK(position >= 0 && static_cast<size_t>(position) < extensions_.size());
  return extensions_[position].get();
}

const BackgroundApplicationListModel::Application*
BackgroundApplicationListModel::FindApplication(
    const Extension* extension) const {
  const std::string& id = extension->id();
  ApplicationMap::const_iterator found = applications_.find(id);
  return (found == applications_.end()) ? NULL : found->second;
}

BackgroundApplicationListModel::Application*
BackgroundApplicationListModel::FindApplication(
    const Extension* extension) {
  const std::string& id = extension->id();
  ApplicationMap::iterator found = applications_.find(id);
  return (found == applications_.end()) ? NULL : found->second;
}

const gfx::ImageSkia* BackgroundApplicationListModel::GetIcon(
    const Extension* extension) {
  const Application* application = FindApplication(extension);
  if (application)
    return application->icon_.get();
  AssociateApplicationData(extension);
  return NULL;
}

int BackgroundApplicationListModel::GetPosition(
    const Extension* extension) const {
  int position = 0;
  const std::string& id = extension->id();
  for (ExtensionList::const_iterator cursor = extensions_.begin();
       cursor != extensions_.end();
       ++cursor, ++position) {
    if (id == cursor->get()->id())
      return position;
  }
  NOTREACHED();
  return -1;
}

// static
bool BackgroundApplicationListModel::RequiresBackgroundModeForPushMessaging(
    const Extension& extension) {
  // No PushMessaging permission - does not require the background mode.
  if (!extension.HasAPIPermission(APIPermission::kPushMessaging))
    return false;

  // If in the whitelist, then does not require background mode even if
  // uses push messaging.
  // TODO(dimich): remove this whitelist once we have a better way to keep
  // listening for GCM. http://crbug.com/311268
  std::string id_hash = base::SHA1HashString(extension.id());
  std::string hexencoded_id_hash = base::HexEncode(id_hash.c_str(),
                                                   id_hash.length());
  // The id starting from "9A04..." is a one from unit test.
  if (hexencoded_id_hash == "C41AD9DCD670210295614257EF8C9945AD68D86E" ||
      hexencoded_id_hash == "9A0417016F345C934A1A88F55CA17C05014EEEBA")
     return false;

   return true;
 }

// static
bool BackgroundApplicationListModel::IsBackgroundApp(
    const Extension& extension, Profile* profile) {
  // An extension is a "background app" if it has the "background API"
  // permission, and meets one of the following criteria:
  // 1) It is an extension (not a hosted app).
  // 2) It is a hosted app, and has a background contents registered or in the
  //    manifest.

  // Not a background app if we don't have the background permission or
  // the push messaging permission
  if (!extension.HasAPIPermission(APIPermission::kBackground) &&
      !RequiresBackgroundModeForPushMessaging(extension))
    return false;

  // Extensions and packaged apps with background permission are always treated
  // as background apps.
  if (!extension.is_hosted_app())
    return true;

  // Hosted apps with manifest-provided background pages are background apps.
  if (extensions::BackgroundInfo::HasBackgroundPage(&extension))
    return true;

  BackgroundContentsService* service =
      BackgroundContentsServiceFactory::GetForProfile(profile);
  base::string16 app_id = ASCIIToUTF16(extension.id());
  // If we have an active or registered background contents for this app, then
  // it's a background app. This covers the cases where the app has created its
  // background contents, but it hasn't navigated yet, or the background
  // contents crashed and hasn't yet been restarted - in both cases we still
  // want to treat the app as a background app.
  if (service->GetAppBackgroundContents(app_id) ||
      service->HasRegisteredBackgroundContents(app_id)) {
    return true;
  }

  // Doesn't meet our criteria, so it's not a background app.
  return false;
}

void BackgroundApplicationListModel::Observe(
    int type,
    const content::NotificationSource& source,
    const content::NotificationDetails& details) {
  if (type == chrome::NOTIFICATION_EXTENSIONS_READY) {
    Update();
    return;
  }
  ExtensionService* service = extensions::ExtensionSystem::Get(profile_)->
      extension_service();
  if (!service || !service->is_ready())
    return;

  switch (type) {
    case chrome::NOTIFICATION_EXTENSION_LOADED:
      OnExtensionLoaded(content::Details<Extension>(details).ptr());
      break;
    case chrome::NOTIFICATION_EXTENSION_UNLOADED:
      OnExtensionUnloaded(
          content::Details<UnloadedExtensionInfo>(details)->extension);
      break;
    case chrome::NOTIFICATION_EXTENSION_PERMISSIONS_UPDATED:
      OnExtensionPermissionsUpdated(
          content::Details<UpdatedExtensionPermissionsInfo>(details)->extension,
          content::Details<UpdatedExtensionPermissionsInfo>(details)->reason,
          content::Details<UpdatedExtensionPermissionsInfo>(details)->
              permissions);
      break;
    case chrome::NOTIFICATION_BACKGROUND_CONTENTS_SERVICE_CHANGED:
      Update();
      break;
    default:
      NOTREACHED() << "Received unexpected notification";
  }
}

void BackgroundApplicationListModel::SendApplicationDataChangedNotifications(
    const Extension* extension) {
  FOR_EACH_OBSERVER(Observer, observers_, OnApplicationDataChanged(extension,
                                                                   profile_));
}

void BackgroundApplicationListModel::OnExtensionLoaded(
    const Extension* extension) {
  // We only care about extensions that are background applications
  if (!IsBackgroundApp(*extension, profile_))
    return;
  AssociateApplicationData(extension);
}

void BackgroundApplicationListModel::OnExtensionUnloaded(
    const Extension* extension) {
  if (!IsBackgroundApp(*extension, profile_))
    return;
  Update();
  DissociateApplicationData(extension);
}

void BackgroundApplicationListModel::OnExtensionPermissionsUpdated(
    const Extension* extension,
    UpdatedExtensionPermissionsInfo::Reason reason,
    const PermissionSet* permissions) {
  if (permissions->HasAPIPermission(APIPermission::kBackground)) {
    switch (reason) {
      case UpdatedExtensionPermissionsInfo::ADDED:
        DCHECK(IsBackgroundApp(*extension, profile_));
        OnExtensionLoaded(extension);
        break;
      case UpdatedExtensionPermissionsInfo::REMOVED:
        DCHECK(!IsBackgroundApp(*extension, profile_));
        Update();
        DissociateApplicationData(extension);
        break;
      default:
        NOTREACHED();
    }
  }
}

void BackgroundApplicationListModel::RemoveObserver(Observer* observer) {
  observers_.RemoveObserver(observer);
}

// Update queries the extensions service of the profile with which the model was
// initialized to determine the current set of background applications.  If that
// differs from the old list, it generates OnApplicationListChanged events for
// each observer.
void BackgroundApplicationListModel::Update() {
  ExtensionService* service = extensions::ExtensionSystem::Get(profile_)->
      extension_service();

  // Discover current background applications, compare with previous list, which
  // is consistently sorted, and notify observers if they differ.
  ExtensionList extensions;
  GetServiceApplications(service, &extensions);
  ExtensionList::const_iterator old_cursor = extensions_.begin();
  ExtensionList::const_iterator new_cursor = extensions.begin();
  while (old_cursor != extensions_.end() &&
         new_cursor != extensions.end() &&
         (*old_cursor)->name() == (*new_cursor)->name() &&
         (*old_cursor)->id() == (*new_cursor)->id()) {
    ++old_cursor;
    ++new_cursor;
  }
  if (old_cursor != extensions_.end() || new_cursor != extensions.end()) {
    extensions_ = extensions;
    FOR_EACH_OBSERVER(Observer, observers_, OnApplicationListChanged(profile_));
  }
}
