// Copyright (c) 2011 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_page_tracker.h"

#include <set>
#include <string>
#include <vector>

#include "base/command_line.h"
#include "base/utf_string_conversions.h"
#include "base/values.h"
#include "chrome/browser/background_application_list_model.h"
#include "chrome/browser/background_contents_service.h"
#include "chrome/browser/background_contents_service_factory.h"
#include "chrome/browser/background_mode_manager.h"
#include "chrome/browser/browser_process.h"
#include "chrome/browser/extensions/extension_service.h"
#include "chrome/browser/prefs/pref_service.h"
#include "chrome/browser/prefs/scoped_user_pref_update.h"
#include "chrome/browser/profiles/profile.h"
#include "chrome/browser/profiles/profile_manager.h"
#include "chrome/common/extensions/extension.h"
#include "chrome/common/pref_names.h"
#include "content/common/notification_service.h"
#include "content/common/notification_type.h"

///////////////////////////////////////////////////////////////////////////////
// BackgroundPageTracker keeps a single DictionaryValue (stored at
// prefs::kKnownBackgroundPages). We keep only two pieces of information for
// each background page: the parent application/extension ID, and a boolean
// flag that is true if the user has acknowledged this page.
//
// kKnownBackgroundPages:
//    DictionaryValue {
//       <appid_1>: false,
//       <appid_2>: true,
//         ... etc ...
//    }

// static
void BackgroundPageTracker::RegisterPrefs(PrefService* prefs) {
  prefs->RegisterDictionaryPref(prefs::kKnownBackgroundPages);
}

// static
BackgroundPageTracker* BackgroundPageTracker::GetInstance() {
  return Singleton<BackgroundPageTracker>::get();
}

int BackgroundPageTracker::GetBackgroundPageCount() {
  if (!IsEnabled())
    return 0;

  PrefService* prefs = GetPrefService();
  const DictionaryValue* contents =
      prefs->GetDictionary(prefs::kKnownBackgroundPages);
  return contents ? contents->size() : 0;
}

int BackgroundPageTracker::GetUnacknowledgedBackgroundPageCount() {
  if (!IsEnabled())
    return 0;
  PrefService* prefs = GetPrefService();
  const DictionaryValue* contents =
      prefs->GetDictionary(prefs::kKnownBackgroundPages);
  if (!contents)
    return 0;
  int count = 0;
  for (DictionaryValue::key_iterator it = contents->begin_keys();
       it != contents->end_keys(); ++it) {
    Value* value;
    bool found = contents->GetWithoutPathExpansion(*it, &value);
    DCHECK(found);
    bool acknowledged = true;
    bool valid = value->GetAsBoolean(&acknowledged);
    DCHECK(valid);
    if (!acknowledged)
      count++;
  }
  return count;
}

void BackgroundPageTracker::AcknowledgeBackgroundPages() {
  if (!IsEnabled())
    return;
  PrefService* prefs = GetPrefService();
  DictionaryPrefUpdate update(prefs, prefs::kKnownBackgroundPages);
  DictionaryValue* contents = update.Get();
  bool prefs_modified = false;
  for (DictionaryValue::key_iterator it = contents->begin_keys();
       it != contents->end_keys(); ++it) {
    contents->SetWithoutPathExpansion(*it, Value::CreateBooleanValue(true));
    prefs_modified = true;
  }
  if (prefs_modified) {
    prefs->ScheduleSavePersistentPrefs();
    SendChangeNotification();
  }
}

BackgroundPageTracker::BackgroundPageTracker() {
  // If background mode is disabled, just exit - don't load information from
  // prefs or listen for any notifications so we will act as if there are no
  // background pages, effectively disabling any associated badging.
  if (!IsEnabled())
    return;

  // Check to make sure all of the extensions are loaded - once they are loaded
  // we can update the list.
  Profile* profile = g_browser_process->profile_manager()->GetDefaultProfile();
  if (profile->GetExtensionService() &&
      profile->GetExtensionService()->is_ready()) {
    UpdateExtensionList();
    // We do not send any change notifications here, because the object was
    // just created (it doesn't seem appropriate to send a change notification
    // at initialization time). Also, since this is a singleton object, sending
    // a notification in the constructor can lead to deadlock if one of the
    // observers tries to get the singleton.
  } else {
    // Extensions aren't loaded yet - register to be notified when they are
    // ready.
    registrar_.Add(this, NotificationType::EXTENSIONS_READY,
                   NotificationService::AllSources());
  }
}

BackgroundPageTracker::~BackgroundPageTracker() {
}

PrefService* BackgroundPageTracker::GetPrefService() {
  PrefService* service = g_browser_process->local_state();
  DCHECK(service);
  return service;
}

bool BackgroundPageTracker::IsEnabled() {
  // Disable the background page tracker for unittests.
  if (!g_browser_process->local_state())
    return false;

  // BackgroundPageTracker is enabled if background mode is enabled.
  CommandLine* command_line = CommandLine::ForCurrentProcess();
  return BackgroundModeManager::IsBackgroundModeEnabled(command_line);
}

void BackgroundPageTracker::Observe(NotificationType type,
                                    const NotificationSource& source,
                                    const NotificationDetails& details) {
  switch (type.value) {
    case NotificationType::EXTENSIONS_READY:
      if (UpdateExtensionList())
        SendChangeNotification();
      break;
    case NotificationType::BACKGROUND_CONTENTS_OPENED: {
      std::string id = UTF16ToUTF8(
          Details<BackgroundContentsOpenedDetails>(details)->application_id);
      OnBackgroundPageLoaded(id);
      break;
    }
    case NotificationType::EXTENSION_LOADED: {
      const Extension* extension = Details<const Extension>(details).ptr();
      if (!extension->is_hosted_app() &&
          extension->background_url().is_valid())
        OnBackgroundPageLoaded(extension->id());
      break;
    }
    case NotificationType::EXTENSION_UNLOADED: {
      std::string id = Details<UnloadedExtensionInfo>(details)->extension->id();
      OnExtensionUnloaded(id);
      break;
    }
    default:
      NOTREACHED();
  }
}

bool BackgroundPageTracker::UpdateExtensionList() {
  // Extensions are loaded - update our list.
  Profile* profile = g_browser_process->profile_manager()->GetDefaultProfile();
  ExtensionService* extensions_service = profile->GetExtensionService();
  DCHECK(extensions_service);

  // We will make two passes to update the list:
  // 1) Walk our list, and make sure that there's a corresponding extension for
  //    each item in the list. If not, delete it (extension was uninstalled).
  // 2) Walk the set of currently loaded extensions and background contents, and
  //    make sure there's an entry in our list for each one. If not, create one.

  PrefService* prefs = GetPrefService();
  std::set<std::string> keys_to_delete;
  bool pref_modified = false;
  // If we've never set any prefs, then this is the first launch ever, so we
  // want to automatically mark all existing extensions as acknowledged.
  bool first_launch =
      prefs->GetDictionary(prefs::kKnownBackgroundPages) == NULL;
  DictionaryPrefUpdate update(prefs, prefs::kKnownBackgroundPages);
  DictionaryValue* contents = update.Get();
  for (DictionaryValue::key_iterator it = contents->begin_keys();
       it != contents->end_keys(); ++it) {
    // Check to make sure that the parent extension is still enabled.
    const Extension* extension = extensions_service->GetExtensionById(
        *it, false);
    // If the extension is not loaded, add the id to our list of keys to delete
    // later (can't delete now since we're still iterating).
    if (!extension) {
      keys_to_delete.insert(*it);
      pref_modified = true;
    }
  }

  for (std::set<std::string>::const_iterator iter = keys_to_delete.begin();
       iter != keys_to_delete.end();
       ++iter) {
    contents->RemoveWithoutPathExpansion(*iter, NULL);
  }

  // Look for new extensions/background contents.
  const ExtensionList* list = extensions_service->extensions();
  for (ExtensionList::const_iterator iter = list->begin();
       iter != list->begin();
       ++iter) {
    // Any extension with a background page should be in our list.
    if ((*iter)->background_url().is_valid()) {
      // If we have not seen this extension ID before, add it to our list.
      if (!contents->HasKey((*iter)->id())) {
        contents->SetWithoutPathExpansion(
            (*iter)->id(), Value::CreateBooleanValue(first_launch));
        pref_modified = true;
      }
    }
  }

  // Add all apps with background contents also.
  BackgroundContentsService* background_contents_service =
      BackgroundContentsServiceFactory::GetForProfile(profile);
  std::vector<BackgroundContents*> background_contents =
      background_contents_service->GetBackgroundContents();
  for (std::vector<BackgroundContents*>::const_iterator iter =
           background_contents.begin();
       iter != background_contents.end();
       ++iter) {
     std::string application_id = UTF16ToUTF8(
         background_contents_service->GetParentApplicationId(*iter));
     if (!contents->HasKey(application_id)) {
        contents->SetWithoutPathExpansion(
            application_id, Value::CreateBooleanValue(first_launch));
        pref_modified = true;
     }
  }

  // Register for when new pages are loaded/unloaded so we can update our list.
  registrar_.Add(this, NotificationType::EXTENSION_LOADED,
                 NotificationService::AllSources());
  registrar_.Add(this, NotificationType::EXTENSION_UNLOADED,
                 NotificationService::AllSources());
  registrar_.Add(this, NotificationType::BACKGROUND_CONTENTS_OPENED,
                 NotificationService::AllSources());

  // If we modified the list, save it to prefs and let our caller know.
  if (pref_modified)
    prefs->ScheduleSavePersistentPrefs();
  return pref_modified;
}

void BackgroundPageTracker::OnBackgroundPageLoaded(const std::string& id) {
  DCHECK(IsEnabled());
  PrefService* prefs = GetPrefService();
  DictionaryPrefUpdate update(prefs, prefs::kKnownBackgroundPages);
  DictionaryValue* contents = update.Get();
  // No need to update our list if this extension was already known.
  if (contents->HasKey(id))
    return;

  // Update our list with this new as-yet-unacknowledged page.
  contents->SetWithoutPathExpansion(id, Value::CreateBooleanValue(false));
  prefs->ScheduleSavePersistentPrefs();
  SendChangeNotification();
}

void BackgroundPageTracker::OnExtensionUnloaded(const std::string& id) {
  DCHECK(IsEnabled());
  PrefService* prefs = GetPrefService();
  DictionaryPrefUpdate update(prefs, prefs::kKnownBackgroundPages);
  DictionaryValue* contents = update.Get();

  if (!contents->HasKey(id))
    return;

  contents->RemoveWithoutPathExpansion(id, NULL);
  prefs->ScheduleSavePersistentPrefs();
  SendChangeNotification();
}

void BackgroundPageTracker::SendChangeNotification() {
  NotificationService::current()->Notify(
      NotificationType::BACKGROUND_PAGE_TRACKER_CHANGED,
      Source<BackgroundPageTracker>(this),
      NotificationService::NoDetails());
}
