// 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_contents_service.h"

#include "base/basictypes.h"
#include "base/command_line.h"
#include "base/string_util.h"
#include "base/utf_string_conversions.h"
#include "base/values.h"
#include "chrome/browser/background_contents_service_factory.h"
#include "chrome/browser/browser_process.h"
#include "chrome/browser/extensions/extension_host.h"
#include "chrome/browser/extensions/extension_service.h"
#include "chrome/browser/notifications/desktop_notification_service.h"
#include "chrome/browser/notifications/notification.h"
#include "chrome/browser/notifications/notification_ui_manager.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/ui/browser.h"
#include "chrome/browser/ui/browser_list.h"
#include "chrome/common/chrome_switches.h"
#include "chrome/common/extensions/extension.h"
#include "chrome/common/pref_names.h"
#include "content/browser/renderer_host/render_view_host.h"
#include "content/browser/site_instance.h"
#include "content/browser/tab_contents/tab_contents.h"
#include "content/common/notification_service.h"
#include "content/common/notification_type.h"
#include "grit/generated_resources.h"
#include "ui/base/l10n/l10n_util.h"

namespace {

const char kNotificationPrefix[] = "app.background.crashed.";

void CloseBalloon(const std::string id) {
  g_browser_process->notification_ui_manager()->CancelById(id);
}

void ScheduleCloseBalloon(const std::string& extension_id) {
  MessageLoop::current()->PostTask(FROM_HERE,
      NewRunnableFunction(&CloseBalloon,
          kNotificationPrefix + extension_id));
}

class CrashNotificationDelegate : public NotificationDelegate {
 public:
  CrashNotificationDelegate(Profile* profile, const Extension* extension)
      : profile_(profile),
        is_hosted_app_(extension->is_hosted_app()),
        extension_id_(extension->id()) {
  }

  ~CrashNotificationDelegate() {
  }

  void Display() {}

  void Error() {}

  void Close(bool by_user) {}

  void Click() {
    if (is_hosted_app_) {
      BackgroundContentsServiceFactory::GetForProfile(profile_)->
          LoadBackgroundContentsForExtension(profile_, extension_id_);
    } else {
      profile_->GetExtensionService()->ReloadExtension(extension_id_);
    }

    // Closing the balloon here should be OK, but it causes a crash on Mac
    // http://crbug.com/78167
    ScheduleCloseBalloon(extension_id_);
  }

  std::string id() const {
    return kNotificationPrefix + extension_id_;
  }

 private:
  Profile* profile_;
  bool is_hosted_app_;
  std::string extension_id_;

  DISALLOW_COPY_AND_ASSIGN(CrashNotificationDelegate);
};

void ShowBalloon(const Extension* extension, Profile* profile) {
  string16 message = l10n_util::GetStringFUTF16(
      extension->is_hosted_app() ?  IDS_BACKGROUND_CRASHED_APP_BALLOON_MESSAGE :
      IDS_BACKGROUND_CRASHED_EXTENSION_BALLOON_MESSAGE,
      UTF8ToUTF16(extension->name()));
  string16 content_url = DesktopNotificationService::CreateDataUrl(
      extension->GetIconURL(Extension::EXTENSION_ICON_SMALLISH,
                            ExtensionIconSet::MATCH_BIGGER),
      string16(), message, WebKit::WebTextDirectionDefault);
  Notification notification(
      extension->url(), GURL(content_url), string16(), string16(),
      new CrashNotificationDelegate(profile, extension));
  g_browser_process->notification_ui_manager()->Add(notification, profile);
}

}

// Keys for the information we store about individual BackgroundContents in
// prefs. There is one top-level DictionaryValue (stored at
// prefs::kRegisteredBackgroundContents). Information about each
// BackgroundContents is stored under that top-level DictionaryValue, keyed
// by the parent application ID for easy lookup.
//
// kRegisteredBackgroundContents:
//    DictionaryValue {
//       <appid_1>: { "url": <url1>, "name": <frame_name> },
//       <appid_2>: { "url": <url2>, "name": <frame_name> },
//         ... etc ...
//    }
const char kUrlKey[] = "url";
const char kFrameNameKey[] = "name";

BackgroundContentsService::BackgroundContentsService(
    Profile* profile, const CommandLine* command_line)
    : prefs_(NULL) {
  // Don't load/store preferences if the proper switch is not enabled, or if
  // the parent profile is incognito.
  if (!profile->IsOffTheRecord() &&
      !command_line->HasSwitch(switches::kDisableRestoreBackgroundContents))
    prefs_ = profile->GetPrefs();

  // Listen for events to tell us when to load/unload persisted background
  // contents.
  StartObserving(profile);
}

BackgroundContentsService::~BackgroundContentsService() {
  // BackgroundContents should be shutdown before we go away, as otherwise
  // our browser process refcount will be off.
  DCHECK(contents_map_.empty());
}

std::vector<BackgroundContents*>
BackgroundContentsService::GetBackgroundContents() const
{
  std::vector<BackgroundContents*> contents;
  for (BackgroundContentsMap::const_iterator it = contents_map_.begin();
       it != contents_map_.end(); ++it)
    contents.push_back(it->second.contents);
  return contents;
}

void BackgroundContentsService::StartObserving(Profile* profile) {
  // On startup, load our background pages after extension-apps have loaded.
  registrar_.Add(this, NotificationType::EXTENSIONS_READY,
                 Source<Profile>(profile));

  // Track the lifecycle of all BackgroundContents in the system to allow us
  // to store an up-to-date list of the urls. Start tracking contents when they
  // have been opened via CreateBackgroundContents(), and stop tracking them
  // when they are closed by script.
  registrar_.Add(this, NotificationType::BACKGROUND_CONTENTS_CLOSED,
                 Source<Profile>(profile));

  // Stop tracking BackgroundContents when they have been deleted (happens
  // during shutdown or if the render process dies).
  registrar_.Add(this, NotificationType::BACKGROUND_CONTENTS_DELETED,
                 Source<Profile>(profile));

  // Track when the BackgroundContents navigates to a new URL so we can update
  // our persisted information as appropriate.
  registrar_.Add(this, NotificationType::BACKGROUND_CONTENTS_NAVIGATED,
                 Source<Profile>(profile));

  // Listen for new extension installs so that we can load any associated
  // background page.
  registrar_.Add(this, NotificationType::EXTENSION_LOADED,
                 Source<Profile>(profile));

  // Track when the extensions crash so that the user can be notified
  // about it, and the crashed contents can be restarted.
  registrar_.Add(this, NotificationType::EXTENSION_PROCESS_TERMINATED,
                 Source<Profile>(profile));
  registrar_.Add(this, NotificationType::BACKGROUND_CONTENTS_TERMINATED,
                 Source<Profile>(profile));

  // Listen for extensions to be unloaded so we can shutdown associated
  // BackgroundContents.
  registrar_.Add(this, NotificationType::EXTENSION_UNLOADED,
                 Source<Profile>(profile));

  // Make sure the extension-crash balloons are removed when the extension is
  // uninstalled/reloaded. We cannot do this from UNLOADED since a crashed
  // extension is unloaded immediately after the crash, not when user reloads or
  // uninstalls the extension.
  registrar_.Add(this, NotificationType::EXTENSION_UNINSTALLED,
                 Source<Profile>(profile));
}

void BackgroundContentsService::Observe(NotificationType type,
                                        const NotificationSource& source,
                                        const NotificationDetails& details) {
  switch (type.value) {
    case NotificationType::EXTENSIONS_READY:
      LoadBackgroundContentsFromManifests(Source<Profile>(source).ptr());
      LoadBackgroundContentsFromPrefs(Source<Profile>(source).ptr());
      break;
    case NotificationType::BACKGROUND_CONTENTS_DELETED:
      BackgroundContentsShutdown(Details<BackgroundContents>(details).ptr());
      break;
    case NotificationType::BACKGROUND_CONTENTS_CLOSED:
      DCHECK(IsTracked(Details<BackgroundContents>(details).ptr()));
      UnregisterBackgroundContents(Details<BackgroundContents>(details).ptr());
      break;
    case NotificationType::BACKGROUND_CONTENTS_NAVIGATED: {
      DCHECK(IsTracked(Details<BackgroundContents>(details).ptr()));

      // Do not register in the pref if the extension has a manifest-specified
      // background page.
      BackgroundContents* bgcontents =
          Details<BackgroundContents>(details).ptr();
      Profile* profile = Source<Profile>(source).ptr();
      const string16& appid = GetParentApplicationId(bgcontents);
      ExtensionService* extension_service = profile->GetExtensionService();
      // extension_service can be NULL when running tests.
      if (extension_service) {
        const Extension* extension =
            extension_service->GetExtensionById(UTF16ToUTF8(appid), false);
        if (extension && extension->background_url().is_valid())
          break;
      }
      RegisterBackgroundContents(Details<BackgroundContents>(details).ptr());
      break;
    }
    case NotificationType::EXTENSION_LOADED: {
      const Extension* extension = Details<const Extension>(details).ptr();
      Profile* profile = Source<Profile>(source).ptr();
      if (extension->is_hosted_app() &&
          extension->background_url().is_valid()) {
        // If there is a background page specified in the manifest for a hosted
        // app, then blow away registered urls in the pref.
        ShutdownAssociatedBackgroundContents(ASCIIToUTF16(extension->id()));

        ExtensionService* service = profile->GetExtensionService();
        if (service && service->is_ready()) {
          // Now load the manifest-specified background page. If service isn't
          // ready, then the background page will be loaded from the
          // EXTENSIONS_READY callback.
          LoadBackgroundContents(profile, extension->background_url(),
              ASCIIToUTF16("background"), UTF8ToUTF16(extension->id()));
        }
      }

      // Remove any "This extension has crashed" balloons.
      ScheduleCloseBalloon(extension->id());
      break;
    }
    case NotificationType::EXTENSION_PROCESS_TERMINATED:
    case NotificationType::BACKGROUND_CONTENTS_TERMINATED: {
      Profile* profile = Source<Profile>(source).ptr();
      const Extension* extension = NULL;
      if (type.value == NotificationType::BACKGROUND_CONTENTS_TERMINATED) {
        BackgroundContents* bg =
            Details<BackgroundContents>(details).ptr();
        std::string extension_id = UTF16ToASCII(
            BackgroundContentsServiceFactory::GetForProfile(profile)->
                GetParentApplicationId(bg));
        extension =
          profile->GetExtensionService()->GetExtensionById(extension_id, false);
      } else {
        ExtensionHost* extension_host = Details<ExtensionHost>(details).ptr();
        extension = extension_host->extension();
      }
      if (!extension)
        break;

      // When an extension crashes, EXTENSION_PROCESS_TERMINATED is followed by
      // an EXTENSION_UNLOADED notification. This UNLOADED signal causes all the
      // notifications for this extension to be cancelled by
      // DesktopNotificationService. For this reason, instead of showing the
      // balloon right now, we schedule it to show a little later.
      MessageLoop::current()->PostTask(FROM_HERE,
          NewRunnableFunction(&ShowBalloon, extension, profile));
      break;
    }
    case NotificationType::EXTENSION_UNLOADED:
      switch (Details<UnloadedExtensionInfo>(details)->reason) {
        case UnloadedExtensionInfo::DISABLE:  // Intentionally fall through.
        case UnloadedExtensionInfo::UNINSTALL:
          ShutdownAssociatedBackgroundContents(
              ASCIIToUTF16(
                  Details<UnloadedExtensionInfo>(details)->extension->id()));
          break;
        case UnloadedExtensionInfo::UPDATE: {
          // If there is a manifest specified background page, then shut it down
          // here, since if the updated extension still has the background page,
          // then it will be loaded from LOADED callback. Otherwise, leave
          // BackgroundContents in place.
          const Extension* extension =
              Details<UnloadedExtensionInfo>(details)->extension;
          if (extension->background_url().is_valid())
            ShutdownAssociatedBackgroundContents(ASCIIToUTF16(extension->id()));
          break;
        }
        default:
          NOTREACHED();
          ShutdownAssociatedBackgroundContents(
              ASCIIToUTF16(
                  Details<UnloadedExtensionInfo>(details)->extension->id()));
          break;
      }
      break;

    case NotificationType::EXTENSION_UNINSTALLED: {
      // Remove any "This extension has crashed" balloons.
      const UninstalledExtensionInfo* uninstalled_extension =
          Details<const UninstalledExtensionInfo>(details).ptr();
      ScheduleCloseBalloon(uninstalled_extension->extension_id);
      break;
    }

    default:
      NOTREACHED();
      break;
  }
}

// Loads all background contents whose urls have been stored in prefs.
void BackgroundContentsService::LoadBackgroundContentsFromPrefs(
    Profile* profile) {
  if (!prefs_)
    return;
  const DictionaryValue* contents =
      prefs_->GetDictionary(prefs::kRegisteredBackgroundContents);
  if (!contents)
    return;
  ExtensionService* extensions_service = profile->GetExtensionService();
  DCHECK(extensions_service);
  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 (!extension) {
      // We should never reach here - it should not be possible for an app
      // to become uninstalled without the associated BackgroundContents being
      // unregistered via the EXTENSIONS_UNLOADED notification, unless there's a
      // crash before we could save our prefs.
      NOTREACHED() << "No extension found for BackgroundContents - id = "
                   << *it;
      return;
    }
    LoadBackgroundContentsFromDictionary(profile, *it, contents);
  }
}

void BackgroundContentsService::LoadBackgroundContentsForExtension(
    Profile* profile,
    const std::string& extension_id) {
  // First look if the manifest specifies a background page.
  const Extension* extension =
      profile->GetExtensionService()->GetExtensionById(extension_id, false);
  DCHECK(!extension || extension->is_hosted_app());
  if (extension && extension->background_url().is_valid()) {
    LoadBackgroundContents(profile,
                           extension->background_url(),
                           ASCIIToUTF16("background"),
                           UTF8ToUTF16(extension->id()));
    return;
  }

  // Now look in the prefs.
  if (!prefs_)
    return;
  const DictionaryValue* contents =
      prefs_->GetDictionary(prefs::kRegisteredBackgroundContents);
  if (!contents)
    return;
  LoadBackgroundContentsFromDictionary(profile, extension_id, contents);
}

void BackgroundContentsService::LoadBackgroundContentsFromDictionary(
    Profile* profile,
    const std::string& extension_id,
    const DictionaryValue* contents) {
  ExtensionService* extensions_service = profile->GetExtensionService();
  DCHECK(extensions_service);

  DictionaryValue* dict;
  contents->GetDictionaryWithoutPathExpansion(extension_id, &dict);
  if (dict == NULL)
    return;
  string16 frame_name;
  std::string url;
  dict->GetString(kUrlKey, &url);
  dict->GetString(kFrameNameKey, &frame_name);
  LoadBackgroundContents(profile,
                         GURL(url),
                         frame_name,
                         UTF8ToUTF16(extension_id));
}

void BackgroundContentsService::LoadBackgroundContentsFromManifests(
    Profile* profile) {
  const ExtensionList* extensions =
      profile->GetExtensionService()->extensions();
  ExtensionList::const_iterator iter = extensions->begin();
  for (; iter != extensions->end(); ++iter) {
    const Extension* extension = *iter;
    if (extension->is_hosted_app() &&
        extension->background_url().is_valid()) {
      LoadBackgroundContents(profile,
                             extension->background_url(),
                             ASCIIToUTF16("background"),
                             UTF8ToUTF16(extension->id()));
    }
  }
}

void BackgroundContentsService::LoadBackgroundContents(
    Profile* profile,
    const GURL& url,
    const string16& frame_name,
    const string16& application_id) {
  // We are depending on the fact that we will initialize before any user
  // actions or session restore can take place, so no BackgroundContents should
  // be running yet for the passed application_id.
  DCHECK(!GetAppBackgroundContents(application_id));
  DCHECK(!application_id.empty());
  DCHECK(url.is_valid());
  DVLOG(1) << "Loading background content url: " << url;

  BackgroundContents* contents = CreateBackgroundContents(
      SiteInstance::CreateSiteInstanceForURL(profile, url),
      MSG_ROUTING_NONE,
      profile,
      frame_name,
      application_id);

  RenderViewHost* render_view_host = contents->render_view_host();
  // TODO(atwilson): Create RenderViews asynchronously to avoid increasing
  // startup latency (http://crbug.com/47236).
  render_view_host->CreateRenderView(frame_name);
  render_view_host->NavigateToURL(url);
}

BackgroundContents* BackgroundContentsService::CreateBackgroundContents(
    SiteInstance* site,
    int routing_id,
    Profile* profile,
    const string16& frame_name,
    const string16& application_id) {
  BackgroundContents* contents = new BackgroundContents(site, routing_id, this);

  // Register the BackgroundContents internally, then send out a notification
  // to external listeners.
  BackgroundContentsOpenedDetails details = {contents,
                                             frame_name,
                                             application_id};
  BackgroundContentsOpened(&details);
  NotificationService::current()->Notify(
      NotificationType::BACKGROUND_CONTENTS_OPENED,
      Source<Profile>(profile),
      Details<BackgroundContentsOpenedDetails>(&details));
  return contents;
}

void BackgroundContentsService::RegisterBackgroundContents(
    BackgroundContents* background_contents) {
  DCHECK(IsTracked(background_contents));
  if (!prefs_)
    return;

  // We store the first URL we receive for a given application. If there's
  // already an entry for this application, no need to do anything.
  // TODO(atwilson): Verify that this is the desired behavior based on developer
  // feedback (http://crbug.com/47118).
  DictionaryPrefUpdate update(prefs_, prefs::kRegisteredBackgroundContents);
  DictionaryValue* pref = update.Get();
  const string16& appid = GetParentApplicationId(background_contents);
  DictionaryValue* current;
  if (pref->GetDictionaryWithoutPathExpansion(UTF16ToUTF8(appid), &current))
    return;

  // No entry for this application yet, so add one.
  DictionaryValue* dict = new DictionaryValue();
  dict->SetString(kUrlKey, background_contents->GetURL().spec());
  dict->SetString(kFrameNameKey, contents_map_[appid].frame_name);
  pref->SetWithoutPathExpansion(UTF16ToUTF8(appid), dict);
  prefs_->ScheduleSavePersistentPrefs();
}

void BackgroundContentsService::UnregisterBackgroundContents(
    BackgroundContents* background_contents) {
  if (!prefs_)
    return;
  DCHECK(IsTracked(background_contents));
  const string16 appid = GetParentApplicationId(background_contents);
  DictionaryPrefUpdate update(prefs_, prefs::kRegisteredBackgroundContents);
  update.Get()->RemoveWithoutPathExpansion(UTF16ToUTF8(appid), NULL);
  prefs_->ScheduleSavePersistentPrefs();
}

void BackgroundContentsService::ShutdownAssociatedBackgroundContents(
    const string16& appid) {
  BackgroundContents* contents = GetAppBackgroundContents(appid);
  if (contents) {
    UnregisterBackgroundContents(contents);
    // Background contents destructor shuts down the renderer.
    delete contents;
  }
}

void BackgroundContentsService::BackgroundContentsOpened(
    BackgroundContentsOpenedDetails* details) {
  // Add the passed object to our list. Should not already be tracked.
  DCHECK(!IsTracked(details->contents));
  DCHECK(!details->application_id.empty());
  contents_map_[details->application_id].contents = details->contents;
  contents_map_[details->application_id].frame_name = details->frame_name;
}

// Used by test code and debug checks to verify whether a given
// BackgroundContents is being tracked by this instance.
bool BackgroundContentsService::IsTracked(
    BackgroundContents* background_contents) const {
  return !GetParentApplicationId(background_contents).empty();
}

void BackgroundContentsService::BackgroundContentsShutdown(
    BackgroundContents* background_contents) {
  // Remove the passed object from our list.
  DCHECK(IsTracked(background_contents));
  string16 appid = GetParentApplicationId(background_contents);
  contents_map_.erase(appid);
}

BackgroundContents* BackgroundContentsService::GetAppBackgroundContents(
    const string16& application_id) {
  BackgroundContentsMap::const_iterator it = contents_map_.find(application_id);
  return (it != contents_map_.end()) ? it->second.contents : NULL;
}

const string16& BackgroundContentsService::GetParentApplicationId(
    BackgroundContents* contents) const {
  for (BackgroundContentsMap::const_iterator it = contents_map_.begin();
       it != contents_map_.end(); ++it) {
    if (contents == it->second.contents)
      return it->first;
  }
  return EmptyString16();
}

// static
void BackgroundContentsService::RegisterUserPrefs(PrefService* prefs) {
  prefs->RegisterDictionaryPref(prefs::kRegisteredBackgroundContents);
}

void BackgroundContentsService::AddTabContents(
    TabContents* new_contents,
    WindowOpenDisposition disposition,
    const gfx::Rect& initial_pos,
    bool user_gesture) {
  Browser* browser = BrowserList::GetLastActiveWithProfile(
      new_contents->profile());
  if (!browser)
    return;
  browser->AddTabContents(new_contents, disposition, initial_pos, user_gesture);
}
