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

#include "app/l10n_util.h"
#include "base/command_line.h"
#include "base/message_loop.h"
#include "base/string_number_conversions.h"
#include "base/values.h"
#include "chrome/browser/importer/firefox_importer_utils.h"
#include "chrome/browser/importer/importer_messages.h"
#include "chrome/common/chrome_switches.h"
#include "grit/generated_resources.h"
#include "ipc/ipc_switches.h"

ProfileImportProcessHost::ProfileImportProcessHost(
    ResourceDispatcherHost* resource_dispatcher,
    ImportProcessClient* import_process_client,
    BrowserThread::ID thread_id)
    : BrowserChildProcessHost(PROFILE_IMPORT_PROCESS, resource_dispatcher),
      import_process_client_(import_process_client),
      thread_id_(thread_id) {
}

ProfileImportProcessHost::~ProfileImportProcessHost() {
}

bool ProfileImportProcessHost::StartProfileImportProcess(
    const importer::ProfileInfo& profile_info, int items,
    bool import_to_bookmark_bar) {
  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
  if (!StartProcess())
    return false;

  // Dictionary of all localized strings that could be needed by the importer
  // in the external process.
  DictionaryValue localized_strings;
  localized_strings.SetString(
      base::IntToString(IDS_BOOKMARK_GROUP_FROM_FIREFOX),
      l10n_util::GetStringUTF8(IDS_BOOKMARK_GROUP_FROM_FIREFOX));
  localized_strings.SetString(
      base::IntToString(IDS_BOOKMARK_GROUP_FROM_SAFARI),
      l10n_util::GetStringUTF8(IDS_BOOKMARK_GROUP_FROM_SAFARI));
  localized_strings.SetString(
      base::IntToString(IDS_IMPORT_FROM_FIREFOX),
      l10n_util::GetStringUTF8(IDS_IMPORT_FROM_FIREFOX));
  localized_strings.SetString(
      base::IntToString(IDS_IMPORT_FROM_GOOGLE_TOOLBAR),
      l10n_util::GetStringUTF8(IDS_IMPORT_FROM_GOOGLE_TOOLBAR));
  localized_strings.SetString(
      base::IntToString(IDS_IMPORT_FROM_SAFARI),
      l10n_util::GetStringUTF8(IDS_IMPORT_FROM_SAFARI));

  Send(new ProfileImportProcessMsg_StartImport(
      profile_info, items, localized_strings, import_to_bookmark_bar));
  return true;
}

bool ProfileImportProcessHost::CancelProfileImportProcess() {
  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
  Send(new ProfileImportProcessMsg_CancelImport());
  return true;
}

bool ProfileImportProcessHost::ReportImportItemFinished(
    importer::ImportItem item) {
  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
  Send(new ProfileImportProcessMsg_ReportImportItemFinished(item));
  return true;
}

FilePath ProfileImportProcessHost::GetProfileImportProcessCmd() {
  return GetChildPath(true);
}

bool ProfileImportProcessHost::StartProcess() {
  set_name(L"profile import process");

  if (!CreateChannel())
    return false;

  FilePath exe_path = GetProfileImportProcessCmd();
  if (exe_path.empty()) {
    NOTREACHED() << "Unable to get profile import process binary name.";
    return false;
  }

  CommandLine* cmd_line = new CommandLine(exe_path);
  cmd_line->AppendSwitchASCII(switches::kProcessType,
                              switches::kProfileImportProcess);
  cmd_line->AppendSwitchASCII(switches::kProcessChannelID, channel_id());

  SetCrashReporterCommandLine(cmd_line);

  const CommandLine& browser_command_line = *CommandLine::ForCurrentProcess();
  if (browser_command_line.HasSwitch(switches::kChromeFrame))
    cmd_line->AppendSwitch(switches::kChromeFrame);

#if defined(OS_MACOSX)
  base::environment_vector env;
  std::string dylib_path = GetFirefoxDylibPath().value();
  if (!dylib_path.empty())
    env.push_back(std::make_pair("DYLD_FALLBACK_LIBRARY_PATH", dylib_path));

  Launch(false, env, cmd_line);
#elif defined(OS_WIN)
  FilePath no_exposed_directory;

  Launch(no_exposed_directory, cmd_line);
#else
  base::environment_vector env;

  Launch(false, env, cmd_line);
#endif

  return true;
}

void ProfileImportProcessHost::OnMessageReceived(const IPC::Message& message) {
  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
  BrowserThread::PostTask(
      thread_id_, FROM_HERE,
      NewRunnableMethod(import_process_client_.get(),
                        &ImportProcessClient::OnMessageReceived,
                        message));
}

void ProfileImportProcessHost::OnProcessCrashed() {
  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
  BrowserThread::PostTask(
      thread_id_, FROM_HERE,
      NewRunnableMethod(import_process_client_.get(),
                        &ImportProcessClient::OnProcessCrashed));
}

bool ProfileImportProcessHost::CanShutdown() {
  return true;
}

URLRequestContext* ProfileImportProcessHost::GetRequestContext(
    uint32 request_id,
    const ViewHostMsg_Resource_Request& request_data) {
  return NULL;
}

ProfileImportProcessHost::ImportProcessClient::ImportProcessClient() {}

ProfileImportProcessHost::ImportProcessClient::~ImportProcessClient() {}

void ProfileImportProcessHost::ImportProcessClient::OnMessageReceived(
    const IPC::Message& message) {
  IPC_BEGIN_MESSAGE_MAP(ProfileImportProcessHost, message)
    // Notification messages about the state of the import process.
    IPC_MESSAGE_HANDLER(ProfileImportProcessHostMsg_Import_Started,
                        ImportProcessClient::OnImportStart)
    IPC_MESSAGE_HANDLER(ProfileImportProcessHostMsg_Import_Finished,
                        ImportProcessClient::OnImportFinished)
    IPC_MESSAGE_HANDLER(ProfileImportProcessHostMsg_ImportItem_Started,
                        ImportProcessClient::OnImportItemStart)
    IPC_MESSAGE_HANDLER(ProfileImportProcessHostMsg_ImportItem_Finished,
                        ImportProcessClient::OnImportItemFinished)

    // Data messages containing items to be written to the user profile.
    IPC_MESSAGE_HANDLER(ProfileImportProcessHostMsg_NotifyHistoryImportStart,
                        ImportProcessClient::OnHistoryImportStart)
    IPC_MESSAGE_HANDLER(ProfileImportProcessHostMsg_NotifyHistoryImportGroup,
                        ImportProcessClient::OnHistoryImportGroup)
    IPC_MESSAGE_HANDLER(ProfileImportProcessHostMsg_NotifyHomePageImportReady,
                        ImportProcessClient::OnHomePageImportReady)
    IPC_MESSAGE_HANDLER(ProfileImportProcessHostMsg_NotifyBookmarksImportStart,
                        ImportProcessClient::OnBookmarksImportStart)
    IPC_MESSAGE_HANDLER(ProfileImportProcessHostMsg_NotifyBookmarksImportGroup,
                        ImportProcessClient::OnBookmarksImportGroup)
    IPC_MESSAGE_HANDLER(ProfileImportProcessHostMsg_NotifyFavIconsImportStart,
                        ImportProcessClient::OnFavIconsImportStart)
    IPC_MESSAGE_HANDLER(ProfileImportProcessHostMsg_NotifyFavIconsImportGroup,
                        ImportProcessClient::OnFavIconsImportGroup)
    IPC_MESSAGE_HANDLER(ProfileImportProcessHostMsg_NotifyPasswordFormReady,
                        ImportProcessClient::OnPasswordFormImportReady)
    IPC_MESSAGE_HANDLER(ProfileImportProcessHostMsg_NotifyKeywordsReady,
                        ImportProcessClient::OnKeywordsImportReady)
  IPC_END_MESSAGE_MAP_EX()
}