// 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 "base/bind.h"
#include "base/command_line.h"
#include "base/mac/mac_util.h"
#include "base/prefs/pref_service.h"
#include "chrome/browser/background/background_mode_manager.h"
#include "chrome/browser/browser_process.h"
#include "chrome/common/chrome_switches.h"
#include "chrome/common/pref_names.h"
#include "chrome/grit/generated_resources.h"
#include "content/public/browser/browser_thread.h"
#include "ui/base/l10n/l10n_util.h"

using content::BrowserThread;

namespace {
void SetUserRemovedLoginItemPrefOnUIThread() {
  DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
  PrefService* service = g_browser_process->local_state();
  service->SetBoolean(prefs::kUserRemovedLoginItem, true);
}

void SetCreatedLoginItemPrefOnUIThread() {
  DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
  PrefService* service = g_browser_process->local_state();
  service->SetBoolean(prefs::kChromeCreatedLoginItem, true);
}

void DisableLaunchOnStartupOnFileThread() {
  DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::FILE));
  // If the LoginItem is not hidden, it means it's user created, so don't
  // delete it.
  bool is_hidden = false;
  if (base::mac::CheckLoginItemStatus(&is_hidden) && is_hidden)
    base::mac::RemoveFromLoginItems();
}

void CheckForUserRemovedLoginItemOnFileThread() {
  DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::FILE));
  if (!base::mac::CheckLoginItemStatus(NULL)) {
    // There's no LoginItem, so set the kUserRemovedLoginItem pref.
    BrowserThread::PostTask(BrowserThread::UI, FROM_HERE,
                            base::Bind(SetUserRemovedLoginItemPrefOnUIThread));
  }
}

void EnableLaunchOnStartupOnFileThread(bool need_migration) {
  DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::FILE));
  if (need_migration) {
    // This is the first time running Chrome since the kChromeCreatedLoginItem
    // pref was added. Initialize the status of this pref based on whether
    // there is already a hidden login item.
    bool is_hidden = false;
    if (base::mac::CheckLoginItemStatus(&is_hidden)) {
      if (is_hidden) {
      // We already have a hidden login item, so set the kChromeCreatedLoginItem
      // flag.
        BrowserThread::PostTask(BrowserThread::UI, FROM_HERE,
                                base::Bind(SetCreatedLoginItemPrefOnUIThread));
      }
      // LoginItem already exists - just exit.
      return;
    }
  }

  // Check if Chrome is already a Login Item - if not, create one.
  if (!base::mac::CheckLoginItemStatus(NULL)) {
    // Call back to the UI thread to set our preference so we know that Chrome
    // created the login item (which means we are allowed to delete it later).
    // There's a race condition here if the user disables launch on startup
    // before our callback is run, but the user can manually disable
    // "Open At Login" via the dock if this happens.
    base::mac::AddToLoginItems(true);  // Hide on startup.
    BrowserThread::PostTask(BrowserThread::UI, FROM_HERE,
                            base::Bind(SetCreatedLoginItemPrefOnUIThread));
  }
}

}  // namespace

void BackgroundModeManager::EnableLaunchOnStartup(bool should_launch) {
  // LoginItems are associated with an executable, not with a specific
  // user-data-dir, so only mess with the LoginItem when running with the
  // default user-data-dir. So if a user is running multiple instances of
  // Chrome with different user-data-dirs, they won't conflict in their
  // use of LoginItems.
  if (CommandLine::ForCurrentProcess()->HasSwitch(switches::kUserDataDir))
    return;

  // There are a few cases we need to handle:
  //
  // 1) Chrome is transitioning to "launch on startup" state, and there's no
  // login item currently. We create a new item if the kUserRemovedLoginItem
  // and kChromeCreatedLoginItem flags are already false, and set the
  // kChromeCreatedLoginItem flag to true. If kChromeCreatedLoginItem is
  // already set (meaning that we created a login item that has since been
  // deleted) then we will set the kUserRemovedLoginItem so we do not create
  // login items in the future.
  //
  // 2) Chrome is transitioning to the "do not launch on startup" state. If
  // the kChromeCreatedLoginItem flag is false, we do nothing. Otherwise, we
  // will delete the login item if it's present, and not we will set
  // kUserRemovedLoginItem to true to prevent future login items from being
  // created.
  if (should_launch) {
    PrefService* service = g_browser_process->local_state();
    // If the user removed the login item, don't ever create another one.
    if (service->GetBoolean(prefs::kUserRemovedLoginItem))
      return;

    if (service->GetBoolean(prefs::kChromeCreatedLoginItem)) {
      DCHECK(service->GetBoolean(prefs::kMigratedLoginItemPref));
      // If we previously created a login item, we don't need to create
      // a new one - just check to see if the user removed it so we don't
      // ever create another one.
      BrowserThread::PostTask(BrowserThread::FILE, FROM_HERE,
                              base::Bind(
                                  CheckForUserRemovedLoginItemOnFileThread));
    } else {
      bool need_migration = !service->GetBoolean(
          prefs::kMigratedLoginItemPref);
      service->SetBoolean(prefs::kMigratedLoginItemPref, true);
      BrowserThread::PostTask(BrowserThread::FILE, FROM_HERE,
                              base::Bind(EnableLaunchOnStartupOnFileThread,
                                         need_migration));
    }
  } else {
    PrefService* service = g_browser_process->local_state();
    // If Chrome didn't create any login items, just exit.
    if (!service->GetBoolean(prefs::kChromeCreatedLoginItem))
      return;

    // Clear the pref now that we're removing the login item.
    service->ClearPref(prefs::kChromeCreatedLoginItem);

    // If the user removed our login item, note this so we don't ever create
    // another one.
    BrowserThread::PostTask(BrowserThread::FILE, FROM_HERE,
                            base::Bind(
                                CheckForUserRemovedLoginItemOnFileThread));

    // Call to the File thread to remove the login item since it requires
    // accessing the disk.
    BrowserThread::PostTask(BrowserThread::FILE, FROM_HERE,
                            base::Bind(DisableLaunchOnStartupOnFileThread));
  }
}

void BackgroundModeManager::DisplayAppInstalledNotification(
    const extensions::Extension* extension) {
  // TODO(atwilson): Display a platform-appropriate notification here.
  // http://crbug.com/74970
}

base::string16 BackgroundModeManager::GetPreferencesMenuLabel() {
  return l10n_util::GetStringUTF16(IDS_OPTIONS);
}
