// Copyright 2013 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/automation/testing_automation_provider.h"

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

#include "base/bind.h"
#include "base/bind_helpers.h"
#include "base/command_line.h"
#include "base/files/file_path.h"
#include "base/json/json_reader.h"
#include "base/json/json_writer.h"
#include "base/json/string_escape.h"
#include "base/path_service.h"
#include "base/prefs/pref_service.h"
#include "base/process/process.h"
#include "base/process/process_iterator.h"
#include "base/sequenced_task_runner.h"
#include "base/strings/stringprintf.h"
#include "base/strings/utf_string_conversions.h"
#include "base/threading/thread_restrictions.h"
#include "base/time/time.h"
#include "chrome/app/chrome_command_ids.h"
#include "chrome/browser/autocomplete/autocomplete_controller.h"
#include "chrome/browser/autocomplete/autocomplete_match.h"
#include "chrome/browser/autocomplete/autocomplete_result.h"
#include "chrome/browser/automation/automation_browser_tracker.h"
#include "chrome/browser/automation/automation_provider_json.h"
#include "chrome/browser/automation/automation_provider_list.h"
#include "chrome/browser/automation/automation_provider_observers.h"
#include "chrome/browser/automation/automation_tab_tracker.h"
#include "chrome/browser/automation/automation_util.h"
#include "chrome/browser/automation/automation_window_tracker.h"
#include "chrome/browser/bookmarks/bookmark_model.h"
#include "chrome/browser/bookmarks/bookmark_model_factory.h"
#include "chrome/browser/bookmarks/bookmark_storage.h"
#include "chrome/browser/browser_process.h"
#include "chrome/browser/browser_shutdown.h"
#include "chrome/browser/chrome_notification_types.h"
#include "chrome/browser/content_settings/host_content_settings_map.h"
#include "chrome/browser/devtools/devtools_window.h"
#include "chrome/browser/download/download_prefs.h"
#include "chrome/browser/download/download_service.h"
#include "chrome/browser/download/download_service_factory.h"
#include "chrome/browser/download/download_shelf.h"
#include "chrome/browser/download/save_package_file_picker.h"
#include "chrome/browser/extensions/browser_action_test_util.h"
#include "chrome/browser/extensions/crx_installer.h"
#include "chrome/browser/extensions/extension_action.h"
#include "chrome/browser/extensions/extension_action_manager.h"
#include "chrome/browser/extensions/extension_host.h"
#include "chrome/browser/extensions/extension_process_manager.h"
#include "chrome/browser/extensions/extension_service.h"
#include "chrome/browser/extensions/extension_system.h"
#include "chrome/browser/extensions/extension_tab_util.h"
#include "chrome/browser/extensions/extension_util.h"
#include "chrome/browser/extensions/unpacked_installer.h"
#include "chrome/browser/extensions/updater/extension_updater.h"
#include "chrome/browser/history/history_service_factory.h"
#include "chrome/browser/history/top_sites.h"
#include "chrome/browser/infobars/confirm_infobar_delegate.h"
#include "chrome/browser/infobars/infobar_service.h"
#include "chrome/browser/lifetime/application_lifetime.h"
#include "chrome/browser/notifications/balloon.h"
#include "chrome/browser/notifications/balloon_collection.h"
#include "chrome/browser/notifications/balloon_notification_ui_manager.h"
#include "chrome/browser/notifications/notification.h"
#include "chrome/browser/password_manager/password_store.h"
#include "chrome/browser/password_manager/password_store_change.h"
#include "chrome/browser/password_manager/password_store_factory.h"
#include "chrome/browser/platform_util.h"
#include "chrome/browser/plugins/plugin_prefs.h"
#include "chrome/browser/profiles/profile.h"
#include "chrome/browser/profiles/profile_info_cache.h"
#include "chrome/browser/profiles/profile_manager.h"
#include "chrome/browser/profiles/profile_window.h"
#include "chrome/browser/profiles/profiles_state.h"
#include "chrome/browser/search_engines/template_url.h"
#include "chrome/browser/search_engines/template_url_service.h"
#include "chrome/browser/search_engines/template_url_service_factory.h"
#include "chrome/browser/sessions/session_service_factory.h"
#include "chrome/browser/sessions/session_tab_helper.h"
#include "chrome/browser/ui/app_modal_dialogs/app_modal_dialog.h"
#include "chrome/browser/ui/app_modal_dialogs/app_modal_dialog_queue.h"
#include "chrome/browser/ui/app_modal_dialogs/javascript_app_modal_dialog.h"
#include "chrome/browser/ui/app_modal_dialogs/native_app_modal_dialog.h"
#include "chrome/browser/ui/bookmarks/bookmark_bar.h"
#include "chrome/browser/ui/browser_commands.h"
#include "chrome/browser/ui/browser_finder.h"
#include "chrome/browser/ui/browser_iterator.h"
#include "chrome/browser/ui/browser_list.h"
#include "chrome/browser/ui/browser_tabstrip.h"
#include "chrome/browser/ui/browser_window.h"
#include "chrome/browser/ui/extensions/application_launch.h"
#include "chrome/browser/ui/find_bar/find_bar.h"
#include "chrome/browser/ui/find_bar/find_bar_controller.h"
#include "chrome/browser/ui/fullscreen/fullscreen_controller.h"
#include "chrome/browser/ui/fullscreen/fullscreen_exit_bubble_type.h"
#include "chrome/browser/ui/host_desktop.h"
#include "chrome/browser/ui/login/login_prompt.h"
#include "chrome/browser/ui/omnibox/location_bar.h"
#include "chrome/browser/ui/omnibox/omnibox_edit_model.h"
#include "chrome/browser/ui/omnibox/omnibox_view.h"
#include "chrome/browser/ui/search_engines/keyword_editor_controller.h"
#include "chrome/browser/ui/startup/startup_types.h"
#include "chrome/common/automation_constants.h"
#include "chrome/common/automation_messages.h"
#include "chrome/common/chrome_constants.h"
#include "chrome/common/chrome_paths.h"
#include "chrome/common/chrome_switches.h"
#include "chrome/common/extensions/background_info.h"
#include "chrome/common/extensions/extension.h"
#include "chrome/common/extensions/manifest_url_handler.h"
#include "chrome/common/extensions/permissions/permissions_data.h"
#include "chrome/common/pref_names.h"
#include "chrome/common/render_messages.h"
#include "content/public/browser/browser_child_process_host_iterator.h"
#include "content/public/browser/child_process_data.h"
#include "content/public/browser/favicon_status.h"
#include "content/public/browser/geolocation_provider.h"
#include "content/public/browser/interstitial_page.h"
#include "content/public/browser/interstitial_page_delegate.h"
#include "content/public/browser/navigation_entry.h"
#include "content/public/browser/notification_service.h"
#include "content/public/browser/plugin_service.h"
#include "content/public/browser/render_process_host.h"
#include "content/public/browser/render_view_host.h"
#include "content/public/browser/render_widget_host_view.h"
#include "content/public/browser/web_contents.h"
#include "content/public/common/child_process_host.h"
#include "content/public/common/common_param_traits.h"
#include "content/public/common/drop_data.h"
#include "content/public/common/geoposition.h"
#include "content/public/common/ssl_status.h"
#include "content/public/common/webplugininfo.h"
#include "extensions/browser/view_type_utils.h"
#include "extensions/common/permissions/permission_set.h"
#include "extensions/common/url_pattern.h"
#include "extensions/common/url_pattern_set.h"
#include "net/cookies/cookie_store.h"
#include "third_party/WebKit/public/web/WebInputEvent.h"
#include "ui/base/ui_base_types.h"
#include "ui/events/event_constants.h"
#include "ui/events/keycodes/keyboard_codes.h"

#if defined(ENABLE_CONFIGURATION_POLICY)
#include "chrome/browser/policy/policy_service.h"
#endif

#if defined(OS_CHROMEOS)
#include "chromeos/dbus/dbus_thread_manager.h"
#endif

#if defined(OS_MACOSX)
#include <mach/mach.h>
#include <mach/mach_vm.h>
#endif

using automation_util::SendErrorIfModalDialogActive;
using content::BrowserChildProcessHostIterator;
using content::BrowserContext;
using content::BrowserThread;
using content::ChildProcessHost;
using content::DownloadItem;
using content::DownloadManager;
using content::InterstitialPage;
using content::NativeWebKeyboardEvent;
using content::NavigationController;
using content::NavigationEntry;
using content::OpenURLParams;
using content::PluginService;
using content::Referrer;
using content::RenderViewHost;
using content::SSLStatus;
using content::WebContents;
using extensions::Extension;
using extensions::ExtensionActionManager;
using extensions::ExtensionList;
using extensions::Manifest;

namespace {

// Helper to reply asynchronously if |automation| is still valid.
void SendSuccessReply(base::WeakPtr<AutomationProvider> automation,
                      IPC::Message* reply_message) {
  if (automation.get())
    AutomationJSONReply(automation.get(), reply_message).SendSuccess(NULL);
}

// Helper to process the result of CanEnablePlugin.
void DidEnablePlugin(base::WeakPtr<AutomationProvider> automation,
                     IPC::Message* reply_message,
                     const base::FilePath::StringType& path,
                     const std::string& error_msg,
                     bool did_enable) {
  if (did_enable) {
    SendSuccessReply(automation, reply_message);
  } else {
    if (automation.get()) {
      AutomationJSONReply(automation.get(), reply_message)
          .SendError(base::StringPrintf(error_msg.c_str(), path.c_str()));
    }
  }
}

// Helper to resolve the overloading of PostTask.
void PostTask(BrowserThread::ID id, const base::Closure& callback) {
  BrowserThread::PostTask(id, FROM_HERE, callback);
}

class AutomationInterstitialPage : public content::InterstitialPageDelegate {
 public:
  AutomationInterstitialPage(WebContents* tab,
                             const GURL& url,
                             const std::string& contents)
      : contents_(contents) {
    interstitial_page_ = InterstitialPage::Create(tab, true, url, this);
    interstitial_page_->Show();
  }

  virtual std::string GetHTMLContents() OVERRIDE { return contents_; }

 private:
  const std::string contents_;
  InterstitialPage* interstitial_page_;  // Owns us.

  DISALLOW_COPY_AND_ASSIGN(AutomationInterstitialPage);
};

}  // namespace

const int TestingAutomationProvider::kSynchronousCommands[] = {
  IDC_HOME,
  IDC_SELECT_NEXT_TAB,
  IDC_SELECT_PREVIOUS_TAB,
  IDC_SHOW_BOOKMARK_MANAGER,
};

TestingAutomationProvider::TestingAutomationProvider(Profile* profile)
    : AutomationProvider(profile) {
  BrowserList::AddObserver(this);
  registrar_.Add(this, chrome::NOTIFICATION_SESSION_END,
                 content::NotificationService::AllSources());
#if defined(OS_CHROMEOS)
  AddChromeosObservers();
#endif
}

TestingAutomationProvider::~TestingAutomationProvider() {
#if defined(OS_CHROMEOS)
  RemoveChromeosObservers();
#endif
  BrowserList::RemoveObserver(this);
}

IPC::Channel::Mode TestingAutomationProvider::GetChannelMode(
    bool use_named_interface) {
  if (use_named_interface)
#if defined(OS_POSIX)
    return IPC::Channel::MODE_OPEN_NAMED_SERVER;
#else
    return IPC::Channel::MODE_NAMED_SERVER;
#endif
  else
    return IPC::Channel::MODE_CLIENT;
}

void TestingAutomationProvider::OnBrowserAdded(Browser* browser) {
}

void TestingAutomationProvider::OnBrowserRemoved(Browser* browser) {
#if !defined(OS_CHROMEOS) && !defined(OS_MACOSX)
  // For backwards compatibility with the testing automation interface, we
  // want the automation provider (and hence the process) to go away when the
  // last browser goes away.
  // The automation layer doesn't support non-native desktops.
  if (BrowserList::GetInstance(chrome::HOST_DESKTOP_TYPE_NATIVE)->empty() &&
      !CommandLine::ForCurrentProcess()->HasSwitch(
          switches::kKeepAliveForTest)) {
    // If you change this, update Observer for chrome::SESSION_END
    // below.
    base::MessageLoop::current()->PostTask(
        FROM_HERE,
        base::Bind(&TestingAutomationProvider::OnRemoveProvider, this));
  }
#endif  // !defined(OS_CHROMEOS) && !defined(OS_MACOSX)
}

void TestingAutomationProvider::Observe(
    int type,
    const content::NotificationSource& source,
    const content::NotificationDetails& details) {
  DCHECK(type == chrome::NOTIFICATION_SESSION_END);
  // OnBrowserRemoved does a ReleaseLater. When session end is received we exit
  // before the task runs resulting in this object not being deleted. This
  // Release balance out the Release scheduled by OnBrowserRemoved.
  Release();
}

bool TestingAutomationProvider::OnMessageReceived(
    const IPC::Message& message) {
  base::ThreadRestrictions::ScopedAllowWait allow_wait;
  bool handled = true;
  bool deserialize_success = true;
  IPC_BEGIN_MESSAGE_MAP_EX(TestingAutomationProvider,
                           message,
                           deserialize_success)
    IPC_MESSAGE_HANDLER_DELAY_REPLY(AutomationMsg_CloseBrowser, CloseBrowser)
    IPC_MESSAGE_HANDLER(AutomationMsg_ActivateTab, ActivateTab)
    IPC_MESSAGE_HANDLER_DELAY_REPLY(AutomationMsg_AppendTab, AppendTab)
    IPC_MESSAGE_HANDLER(AutomationMsg_GetMachPortCount, GetMachPortCount)
    IPC_MESSAGE_HANDLER(AutomationMsg_ActiveTabIndex, GetActiveTabIndex)
    IPC_MESSAGE_HANDLER_DELAY_REPLY(AutomationMsg_CloseTab, CloseTab)
    IPC_MESSAGE_HANDLER(AutomationMsg_GetCookies, GetCookies)
    IPC_MESSAGE_HANDLER_DELAY_REPLY(
        AutomationMsg_NavigateToURLBlockUntilNavigationsComplete,
        NavigateToURLBlockUntilNavigationsComplete)
    IPC_MESSAGE_HANDLER(AutomationMsg_NavigationAsync, NavigationAsync)
    IPC_MESSAGE_HANDLER_DELAY_REPLY(AutomationMsg_Reload, Reload)
    IPC_MESSAGE_HANDLER(AutomationMsg_BrowserWindowCount, GetBrowserWindowCount)
    IPC_MESSAGE_HANDLER(AutomationMsg_NormalBrowserWindowCount,
                        GetNormalBrowserWindowCount)
    IPC_MESSAGE_HANDLER(AutomationMsg_BrowserWindow, GetBrowserWindow)
    IPC_MESSAGE_HANDLER(AutomationMsg_WindowExecuteCommandAsync,
                        ExecuteBrowserCommandAsync)
    IPC_MESSAGE_HANDLER_DELAY_REPLY(AutomationMsg_WindowExecuteCommand,
                        ExecuteBrowserCommand)
    IPC_MESSAGE_HANDLER(AutomationMsg_TerminateSession, TerminateSession)
    IPC_MESSAGE_HANDLER(AutomationMsg_WindowViewBounds, WindowGetViewBounds)
    IPC_MESSAGE_HANDLER(AutomationMsg_SetWindowBounds, SetWindowBounds)
    IPC_MESSAGE_HANDLER(AutomationMsg_TabCount, GetTabCount)
    IPC_MESSAGE_HANDLER(AutomationMsg_Type, GetType)
    IPC_MESSAGE_HANDLER(AutomationMsg_Tab, GetTab)
    IPC_MESSAGE_HANDLER(AutomationMsg_TabTitle, GetTabTitle)
    IPC_MESSAGE_HANDLER(AutomationMsg_TabIndex, GetTabIndex)
    IPC_MESSAGE_HANDLER(AutomationMsg_TabURL, GetTabURL)
    IPC_MESSAGE_HANDLER_DELAY_REPLY(AutomationMsg_DomOperation,
                                    ExecuteJavascript)
    IPC_MESSAGE_HANDLER_DELAY_REPLY(AutomationMsg_OpenNewBrowserWindowOfType,
                                    OpenNewBrowserWindowOfType)
    IPC_MESSAGE_HANDLER(AutomationMsg_WindowForBrowser, GetWindowForBrowser)
    IPC_MESSAGE_HANDLER(AutomationMsg_GetMetricEventDuration,
                        GetMetricEventDuration)
    IPC_MESSAGE_HANDLER(AutomationMsg_BringBrowserToFront, BringBrowserToFront)
    IPC_MESSAGE_HANDLER(AutomationMsg_FindWindowVisibility,
                        GetFindWindowVisibility)
    IPC_MESSAGE_HANDLER_DELAY_REPLY(AutomationMsg_WaitForBookmarkModelToLoad,
                                    WaitForBookmarkModelToLoad)
    IPC_MESSAGE_HANDLER_DELAY_REPLY(
        AutomationMsg_WaitForBrowserWindowCountToBecome,
        WaitForBrowserWindowCountToBecome)
    IPC_MESSAGE_HANDLER_DELAY_REPLY(
        AutomationMsg_GoBackBlockUntilNavigationsComplete,
        GoBackBlockUntilNavigationsComplete)
    IPC_MESSAGE_HANDLER_DELAY_REPLY(
        AutomationMsg_GoForwardBlockUntilNavigationsComplete,
        GoForwardBlockUntilNavigationsComplete)
    IPC_MESSAGE_HANDLER_DELAY_REPLY(AutomationMsg_SendJSONRequest,
                                    SendJSONRequestWithBrowserIndex)
    IPC_MESSAGE_HANDLER_DELAY_REPLY(
        AutomationMsg_SendJSONRequestWithBrowserHandle,
        SendJSONRequestWithBrowserHandle)
    IPC_MESSAGE_HANDLER_DELAY_REPLY(AutomationMsg_WaitForTabCountToBecome,
                                    WaitForTabCountToBecome)
    IPC_MESSAGE_HANDLER_DELAY_REPLY(AutomationMsg_WaitForInfoBarCount,
                                    WaitForInfoBarCount)
    IPC_MESSAGE_HANDLER_DELAY_REPLY(
        AutomationMsg_WaitForProcessLauncherThreadToGoIdle,
        WaitForProcessLauncherThreadToGoIdle)

    IPC_MESSAGE_UNHANDLED(
        handled = AutomationProvider::OnMessageReceived(message))
  IPC_END_MESSAGE_MAP_EX()
  if (!deserialize_success)
    OnMessageDeserializationFailure();
  return handled;
}

void TestingAutomationProvider::OnChannelError() {
  if (!reinitialize_on_channel_error_ &&
      browser_shutdown::GetShutdownType() == browser_shutdown::NOT_VALID) {
    chrome::AttemptExit();
  }
  AutomationProvider::OnChannelError();
}

void TestingAutomationProvider::CloseBrowser(int browser_handle,
                                             IPC::Message* reply_message) {
  if (!browser_tracker_->ContainsHandle(browser_handle))
    return;

  Browser* browser = browser_tracker_->GetResource(browser_handle);
  new BrowserClosedNotificationObserver(browser, this, reply_message, false);
  browser->window()->Close();
}

void TestingAutomationProvider::ActivateTab(int handle,
                                            int at_index,
                                            int* status) {
  *status = -1;
  if (browser_tracker_->ContainsHandle(handle) && at_index > -1) {
    Browser* browser = browser_tracker_->GetResource(handle);
    if (at_index >= 0 && at_index < browser->tab_strip_model()->count()) {
      browser->tab_strip_model()->ActivateTabAt(at_index, true);
      *status = 0;
    }
  }
}

void TestingAutomationProvider::AppendTab(int handle,
                                          const GURL& url,
                                          IPC::Message* reply_message) {
  int append_tab_response = -1;  // -1 is the error code
  TabAppendedNotificationObserver* observer = NULL;

  if (browser_tracker_->ContainsHandle(handle)) {
    Browser* browser = browser_tracker_->GetResource(handle);
    observer = new TabAppendedNotificationObserver(browser, this,
                                                   reply_message, false);
    WebContents* contents =
        chrome::AddSelectedTabWithURL(browser, url,
                                      content::PAGE_TRANSITION_TYPED);
    if (contents) {
      append_tab_response = GetIndexForNavigationController(
          &contents->GetController(), browser);
    }
  }

  if (append_tab_response < 0) {
    // Appending tab failed. Clean up and send failure response.

    if (observer)
      delete observer;

    AutomationMsg_AppendTab::WriteReplyParams(reply_message,
                                              append_tab_response);
    Send(reply_message);
  }
}

void TestingAutomationProvider::GetMachPortCount(int* port_count) {
#if defined(OS_MACOSX)
  mach_port_name_array_t names;
  mach_msg_type_number_t names_count;
  mach_port_type_array_t types;
  mach_msg_type_number_t types_count;

  mach_port_t port = mach_task_self();

  // A friendlier interface would allow NULL buffers to only get the counts.
  kern_return_t kr = mach_port_names(port, &names, &names_count,
                                     &types, &types_count);
  if (kr != KERN_SUCCESS) {
    *port_count = 0;
    return;
  }

  // The documentation states this is an invariant.
  DCHECK_EQ(names_count, types_count);
  *port_count = names_count;

  mach_vm_deallocate(port, reinterpret_cast<mach_vm_address_t>(names),
      names_count * sizeof(mach_port_name_array_t));
  mach_vm_deallocate(port, reinterpret_cast<mach_vm_address_t>(types),
      types_count * sizeof(mach_port_type_array_t));
#else
  *port_count = 0;
#endif
}

void TestingAutomationProvider::GetActiveTabIndex(int handle,
                                                  int* active_tab_index) {
  *active_tab_index = -1;  // -1 is the error code
  if (browser_tracker_->ContainsHandle(handle)) {
    Browser* browser = browser_tracker_->GetResource(handle);
    *active_tab_index = browser->tab_strip_model()->active_index();
  }
}

void TestingAutomationProvider::CloseTab(int tab_handle,
                                         bool wait_until_closed,
                                         IPC::Message* reply_message) {
  if (tab_tracker_->ContainsHandle(tab_handle)) {
    NavigationController* controller = tab_tracker_->GetResource(tab_handle);
    Browser* browser = chrome::FindBrowserWithWebContents(
        controller->GetWebContents());
    DCHECK(browser);
    new TabClosedNotificationObserver(this, wait_until_closed, reply_message,
                                      false);
    chrome::CloseWebContents(browser, controller->GetWebContents(), false);
    return;
  }

  AutomationMsg_CloseTab::WriteReplyParams(reply_message, false);
  Send(reply_message);
}

void TestingAutomationProvider::GetCookies(const GURL& url, int handle,
                                           int* value_size,
                                           std::string* value) {
  WebContents* contents = tab_tracker_->ContainsHandle(handle) ?
      tab_tracker_->GetResource(handle)->GetWebContents() : NULL;
  automation_util::GetCookies(url, contents, value_size, value);
}

void TestingAutomationProvider::NavigateToURLBlockUntilNavigationsComplete(
    int handle, const GURL& url, int number_of_navigations,
    IPC::Message* reply_message) {
  if (tab_tracker_->ContainsHandle(handle)) {
    NavigationController* tab = tab_tracker_->GetResource(handle);

    // Simulate what a user would do. Activate the tab and then navigate.
    // We could allow navigating in a background tab in future.
    Browser* browser = FindAndActivateTab(tab);

    if (browser) {
      new NavigationNotificationObserver(tab, this, reply_message,
                                         number_of_navigations, false, false);

      // TODO(darin): avoid conversion to GURL.
      OpenURLParams params(
          url, Referrer(), CURRENT_TAB,
          content::PageTransitionFromInt(
              content::PAGE_TRANSITION_TYPED |
              content::PAGE_TRANSITION_FROM_ADDRESS_BAR),
          false);
      browser->OpenURL(params);
      return;
    }
  }

  AutomationMsg_NavigateToURLBlockUntilNavigationsComplete::WriteReplyParams(
      reply_message, AUTOMATION_MSG_NAVIGATION_ERROR);
  Send(reply_message);
}

void TestingAutomationProvider::NavigationAsync(int handle,
                                                const GURL& url,
                                                bool* status) {
  *status = false;

  if (tab_tracker_->ContainsHandle(handle)) {
    NavigationController* tab = tab_tracker_->GetResource(handle);

    // Simulate what a user would do. Activate the tab and then navigate.
    // We could allow navigating in a background tab in future.
    Browser* browser = FindAndActivateTab(tab);

    if (browser) {
      // Don't add any listener unless a callback mechanism is desired.
      // TODO(vibhor): Do this if such a requirement arises in future.
      OpenURLParams params(
          url, Referrer(), CURRENT_TAB,
          content::PageTransitionFromInt(
              content::PAGE_TRANSITION_TYPED |
              content::PAGE_TRANSITION_FROM_ADDRESS_BAR),
          false);
      browser->OpenURL(params);
      *status = true;
    }
  }
}

void TestingAutomationProvider::Reload(int handle,
                                       IPC::Message* reply_message) {
  if (tab_tracker_->ContainsHandle(handle)) {
    NavigationController* tab = tab_tracker_->GetResource(handle);
    Browser* browser = FindAndActivateTab(tab);
    if (chrome::IsCommandEnabled(browser, IDC_RELOAD)) {
      new NavigationNotificationObserver(
          tab, this, reply_message, 1, false, false);
      chrome::ExecuteCommand(browser, IDC_RELOAD);
      return;
    }
  }

  AutomationMsg_Reload::WriteReplyParams(
      reply_message, AUTOMATION_MSG_NAVIGATION_ERROR);
  Send(reply_message);
}

void TestingAutomationProvider::GetBrowserWindowCount(int* window_count) {
  // The automation layer doesn't support non-native desktops.
  *window_count = static_cast<int>(BrowserList::GetInstance(
                      chrome::HOST_DESKTOP_TYPE_NATIVE)->size());
}

void TestingAutomationProvider::GetNormalBrowserWindowCount(int* window_count) {
  *window_count = static_cast<int>(chrome::GetTabbedBrowserCount(
                      profile_, chrome::HOST_DESKTOP_TYPE_NATIVE));
}

void TestingAutomationProvider::GetBrowserWindow(int index, int* handle) {
  *handle = 0;
  Browser* browser = automation_util::GetBrowserAt(index);
  if (browser)
    *handle = browser_tracker_->Add(browser);
}

void TestingAutomationProvider::ExecuteBrowserCommandAsync(int handle,
                                                           int command,
                                                           bool* success) {
  *success = false;
  if (!browser_tracker_->ContainsHandle(handle)) {
    LOG(WARNING) << "Browser tracker does not contain handle: " << handle;
    return;
  }
  Browser* browser = browser_tracker_->GetResource(handle);
  if (!chrome::SupportsCommand(browser, command)) {
    LOG(WARNING) << "Browser does not support command: " << command;
    return;
  }
  if (!chrome::IsCommandEnabled(browser, command)) {
    LOG(WARNING) << "Browser command not enabled: " << command;
    return;
  }
  chrome::ExecuteCommand(browser, command);
  *success = true;
}

void TestingAutomationProvider::ExecuteBrowserCommand(
    int handle, int command, IPC::Message* reply_message) {
  if (browser_tracker_->ContainsHandle(handle)) {
    Browser* browser = browser_tracker_->GetResource(handle);
    if (chrome::SupportsCommand(browser, command) &&
        chrome::IsCommandEnabled(browser, command)) {
      // First check if we can handle the command without using an observer.
      for (size_t i = 0; i < arraysize(kSynchronousCommands); i++) {
        if (command == kSynchronousCommands[i]) {
          chrome::ExecuteCommand(browser, command);
          AutomationMsg_WindowExecuteCommand::WriteReplyParams(reply_message,
                                                               true);
          Send(reply_message);
          return;
        }
      }

      // Use an observer if we have one, otherwise fail.
      if (ExecuteBrowserCommandObserver::CreateAndRegisterObserver(
          this, browser, command, reply_message, false)) {
        chrome::ExecuteCommand(browser, command);
        return;
      }
    }
  }
  AutomationMsg_WindowExecuteCommand::WriteReplyParams(reply_message, false);
  Send(reply_message);
}

void TestingAutomationProvider::WebkitMouseClick(DictionaryValue* args,
                                                 IPC::Message* reply_message) {
  if (SendErrorIfModalDialogActive(this, reply_message))
    return;

  RenderViewHost* view;
  std::string error;
  if (!GetRenderViewFromJSONArgs(args, profile(), &view, &error)) {
    AutomationJSONReply(this, reply_message).SendError(error);
    return;
  }

  WebKit::WebMouseEvent mouse_event;
  if (!args->GetInteger("x", &mouse_event.x) ||
      !args->GetInteger("y", &mouse_event.y)) {
    AutomationJSONReply(this, reply_message)
        .SendError("(X,Y) coordinates missing or invalid");
    return;
  }

  int button;
  if (!args->GetInteger("button", &button)) {
    AutomationJSONReply(this, reply_message)
        .SendError("Mouse button missing or invalid");
    return;
  }
  if (button == automation::kLeftButton) {
    mouse_event.button = WebKit::WebMouseEvent::ButtonLeft;
  } else if (button == automation::kRightButton) {
    mouse_event.button = WebKit::WebMouseEvent::ButtonRight;
  } else if (button == automation::kMiddleButton) {
    mouse_event.button = WebKit::WebMouseEvent::ButtonMiddle;
  } else {
    AutomationJSONReply(this, reply_message)
        .SendError("Invalid button press requested");
    return;
  }

  mouse_event.type = WebKit::WebInputEvent::MouseDown;
  mouse_event.clickCount = 1;

  view->ForwardMouseEvent(mouse_event);

  mouse_event.type = WebKit::WebInputEvent::MouseUp;
  new InputEventAckNotificationObserver(this, reply_message, mouse_event.type,
                                        1);
  view->ForwardMouseEvent(mouse_event);
}

void TestingAutomationProvider::WebkitMouseMove(
    DictionaryValue* args, IPC::Message* reply_message) {
  if (SendErrorIfModalDialogActive(this, reply_message))
    return;

  RenderViewHost* view;
  std::string error;
  if (!GetRenderViewFromJSONArgs(args, profile(), &view, &error)) {
    AutomationJSONReply(this, reply_message).SendError(error);
    return;
  }

  WebKit::WebMouseEvent mouse_event;
  if (!args->GetInteger("x", &mouse_event.x) ||
      !args->GetInteger("y", &mouse_event.y)) {
    AutomationJSONReply(this, reply_message)
        .SendError("(X,Y) coordinates missing or invalid");
    return;
  }

  mouse_event.type = WebKit::WebInputEvent::MouseMove;
  new InputEventAckNotificationObserver(this, reply_message, mouse_event.type,
                                        1);
  view->ForwardMouseEvent(mouse_event);
}

void TestingAutomationProvider::WebkitMouseDrag(DictionaryValue* args,
                                                IPC::Message* reply_message) {
  if (SendErrorIfModalDialogActive(this, reply_message))
    return;

  RenderViewHost* view;
  std::string error;
  if (!GetRenderViewFromJSONArgs(args, profile(), &view, &error)) {
    AutomationJSONReply(this, reply_message).SendError(error);
    return;
  }

  WebKit::WebMouseEvent mouse_event;
  int start_x, start_y, end_x, end_y;
  if (!args->GetInteger("start_x", &start_x) ||
      !args->GetInteger("start_y", &start_y) ||
      !args->GetInteger("end_x", &end_x) ||
      !args->GetInteger("end_y", &end_y)) {
    AutomationJSONReply(this, reply_message)
        .SendError("Invalid start/end positions");
    return;
  }

  mouse_event.type = WebKit::WebInputEvent::MouseMove;
  // Step 1- Move the mouse to the start position.
  mouse_event.x = start_x;
  mouse_event.y = start_y;
  view->ForwardMouseEvent(mouse_event);

  // Step 2- Left click mouse down, the mouse button is fixed.
  mouse_event.type = WebKit::WebInputEvent::MouseDown;
  mouse_event.button = WebKit::WebMouseEvent::ButtonLeft;
  mouse_event.clickCount = 1;
  view->ForwardMouseEvent(mouse_event);

  // Step 3 - Move the mouse to the end position.
  mouse_event.type = WebKit::WebInputEvent::MouseMove;
  mouse_event.x = end_x;
  mouse_event.y = end_y;
  mouse_event.clickCount = 0;
  view->ForwardMouseEvent(mouse_event);

  // Step 4 - Release the left mouse button.
  mouse_event.type = WebKit::WebInputEvent::MouseUp;
  mouse_event.clickCount = 1;
  new InputEventAckNotificationObserver(this, reply_message, mouse_event.type,
                                        1);
  view->ForwardMouseEvent(mouse_event);
}

void TestingAutomationProvider::WebkitMouseButtonDown(
    DictionaryValue* args, IPC::Message* reply_message) {
  if (SendErrorIfModalDialogActive(this, reply_message))
    return;

  RenderViewHost* view;
  std::string error;
  if (!GetRenderViewFromJSONArgs(args, profile(), &view, &error)) {
    AutomationJSONReply(this, reply_message).SendError(error);
    return;
  }

  WebKit::WebMouseEvent mouse_event;
  if (!args->GetInteger("x", &mouse_event.x) ||
      !args->GetInteger("y", &mouse_event.y)) {
    AutomationJSONReply(this, reply_message)
        .SendError("(X,Y) coordinates missing or invalid");
    return;
  }

  mouse_event.type = WebKit::WebInputEvent::MouseDown;
  mouse_event.button = WebKit::WebMouseEvent::ButtonLeft;
  mouse_event.clickCount = 1;
  new InputEventAckNotificationObserver(this, reply_message, mouse_event.type,
                                        1);
  view->ForwardMouseEvent(mouse_event);
}

void TestingAutomationProvider::WebkitMouseButtonUp(
    DictionaryValue* args, IPC::Message* reply_message) {
  if (SendErrorIfModalDialogActive(this, reply_message))
    return;

  RenderViewHost* view;
  std::string error;
  if (!GetRenderViewFromJSONArgs(args, profile(), &view, &error)) {
    AutomationJSONReply(this, reply_message).SendError(error);
    return;
  }

  WebKit::WebMouseEvent mouse_event;
  if (!args->GetInteger("x", &mouse_event.x) ||
      !args->GetInteger("y", &mouse_event.y)) {
    AutomationJSONReply(this, reply_message)
        .SendError("(X,Y) coordinates missing or invalid");
    return;
  }

  mouse_event.type = WebKit::WebInputEvent::MouseUp;
  mouse_event.button = WebKit::WebMouseEvent::ButtonLeft;
  mouse_event.clickCount = 1;
  new InputEventAckNotificationObserver(this, reply_message, mouse_event.type,
                                        1);
  view->ForwardMouseEvent(mouse_event);
}

void TestingAutomationProvider::WebkitMouseDoubleClick(
    DictionaryValue* args, IPC::Message* reply_message) {
  if (SendErrorIfModalDialogActive(this, reply_message))
    return;

  RenderViewHost* view;
  std::string error;
  if (!GetRenderViewFromJSONArgs(args, profile(), &view, &error)) {
    AutomationJSONReply(this, reply_message).SendError(error);
    return;
  }

  WebKit::WebMouseEvent mouse_event;
  if (!args->GetInteger("x", &mouse_event.x) ||
      !args->GetInteger("y", &mouse_event.y)) {
    AutomationJSONReply(this, reply_message)
        .SendError("(X,Y) coordinates missing or invalid");
    return;
  }

  mouse_event.type = WebKit::WebInputEvent::MouseDown;
  mouse_event.button = WebKit::WebMouseEvent::ButtonLeft;
  mouse_event.clickCount = 1;
  view->ForwardMouseEvent(mouse_event);

  mouse_event.type = WebKit::WebInputEvent::MouseUp;
  new InputEventAckNotificationObserver(this, reply_message, mouse_event.type,
                                        2);
  view->ForwardMouseEvent(mouse_event);

  mouse_event.type = WebKit::WebInputEvent::MouseDown;
  mouse_event.clickCount = 2;
  view->ForwardMouseEvent(mouse_event);

  mouse_event.type = WebKit::WebInputEvent::MouseUp;
  view->ForwardMouseEvent(mouse_event);
}

void TestingAutomationProvider::DragAndDropFilePaths(
    DictionaryValue* args, IPC::Message* reply_message) {
  if (SendErrorIfModalDialogActive(this, reply_message))
    return;

  RenderViewHost* view;
  std::string error;
  if (!GetRenderViewFromJSONArgs(args, profile(), &view, &error)) {
    AutomationJSONReply(this, reply_message).SendError(error);
    return;
  }

  int x, y;
  if (!args->GetInteger("x", &x) || !args->GetInteger("y", &y)) {
    AutomationJSONReply(this, reply_message)
        .SendError("(X,Y) coordinates missing or invalid");
    return;
  }

  ListValue* paths = NULL;
  if (!args->GetList("paths", &paths)) {
    AutomationJSONReply(this, reply_message)
        .SendError("'paths' missing or invalid");
    return;
  }

  // Emulate drag and drop to set the file paths to the file upload control.
  content::DropData drop_data;
  for (size_t path_index = 0; path_index < paths->GetSize(); ++path_index) {
    string16 path;
    if (!paths->GetString(path_index, &path)) {
      AutomationJSONReply(this, reply_message)
          .SendError("'paths' contains a non-string type");
      return;
    }

    drop_data.filenames.push_back(
        content::DropData::FileInfo(path, string16()));
  }

  const gfx::Point client(x, y);
  // We don't set any values in screen variable because DragTarget*** ignore the
  // screen argument.
  const gfx::Point screen;

  int operations = 0;
  operations |= WebKit::WebDragOperationCopy;
  operations |= WebKit::WebDragOperationLink;
  operations |= WebKit::WebDragOperationMove;

  view->DragTargetDragEnter(
      drop_data, client, screen,
      static_cast<WebKit::WebDragOperationsMask>(operations), 0);
  new DragTargetDropAckNotificationObserver(this, reply_message);
  view->DragTargetDrop(client, screen, 0);
}

void TestingAutomationProvider::GetTabCount(int handle, int* tab_count) {
  *tab_count = -1;  // -1 is the error code

  if (browser_tracker_->ContainsHandle(handle)) {
    Browser* browser = browser_tracker_->GetResource(handle);
    *tab_count = browser->tab_strip_model()->count();
  }
}

void TestingAutomationProvider::GetType(int handle, int* type_as_int) {
  *type_as_int = -1;  // -1 is the error code

  if (browser_tracker_->ContainsHandle(handle)) {
    Browser* browser = browser_tracker_->GetResource(handle);
    *type_as_int = static_cast<int>(browser->type());
  }
}

void TestingAutomationProvider::GetTab(int win_handle,
                                       int tab_index,
                                       int* tab_handle) {
  *tab_handle = 0;
  if (browser_tracker_->ContainsHandle(win_handle) && (tab_index >= 0)) {
    Browser* browser = browser_tracker_->GetResource(win_handle);
    if (tab_index < browser->tab_strip_model()->count()) {
      WebContents* web_contents =
          browser->tab_strip_model()->GetWebContentsAt(tab_index);
      *tab_handle = tab_tracker_->Add(&web_contents->GetController());
    }
  }
}

void TestingAutomationProvider::GetTabTitle(int handle,
                                            int* title_string_size,
                                            std::wstring* title) {
  *title_string_size = -1;  // -1 is the error code
  if (tab_tracker_->ContainsHandle(handle)) {
    NavigationController* tab = tab_tracker_->GetResource(handle);
    NavigationEntry* entry = tab->GetActiveEntry();
    if (entry != NULL) {
      *title = UTF16ToWideHack(entry->GetTitleForDisplay(std::string()));
    } else {
      *title = std::wstring();
    }
    *title_string_size = static_cast<int>(title->size());
  }
}

void TestingAutomationProvider::GetTabIndex(int handle, int* tabstrip_index) {
  *tabstrip_index = -1;  // -1 is the error code

  if (tab_tracker_->ContainsHandle(handle)) {
    NavigationController* tab = tab_tracker_->GetResource(handle);
    Browser* browser = chrome::FindBrowserWithWebContents(
        tab->GetWebContents());
    *tabstrip_index = browser->tab_strip_model()->GetIndexOfWebContents(
        tab->GetWebContents());
  }
}

void TestingAutomationProvider::GetTabURL(int handle,
                                          bool* success,
                                          GURL* url) {
  *success = false;
  if (tab_tracker_->ContainsHandle(handle)) {
    NavigationController* tab = tab_tracker_->GetResource(handle);
    // Return what the user would see in the location bar.
    *url = tab->GetActiveEntry()->GetVirtualURL();
    *success = true;
  }
}

void TestingAutomationProvider::ExecuteJavascriptInRenderViewFrame(
    const string16& frame_xpath,
    const string16& script,
    IPC::Message* reply_message,
    RenderViewHost* render_view_host) {
  // Set the routing id of this message with the controller.
  // This routing id needs to be remembered for the reverse
  // communication while sending back the response of
  // this javascript execution.
  render_view_host->ExecuteJavascriptInWebFrame(
      frame_xpath,
      UTF8ToUTF16("window.domAutomationController.setAutomationId(0);"));
  render_view_host->ExecuteJavascriptInWebFrame(
      frame_xpath, script);
}

void TestingAutomationProvider::ExecuteJavascript(
    int handle,
    const std::wstring& frame_xpath,
    const std::wstring& script,
    IPC::Message* reply_message) {
  WebContents* web_contents = GetWebContentsForHandle(handle, NULL);
  if (!web_contents) {
    AutomationMsg_DomOperation::WriteReplyParams(reply_message, std::string());
    Send(reply_message);
    return;
  }

  new DomOperationMessageSender(this, reply_message, false);
  ExecuteJavascriptInRenderViewFrame(WideToUTF16Hack(frame_xpath),
                                     WideToUTF16Hack(script), reply_message,
                                     web_contents->GetRenderViewHost());
}

// Sample json input: { "command": "OpenNewBrowserWindowWithNewProfile" }
// Sample output: {}
void TestingAutomationProvider::OpenNewBrowserWindowWithNewProfile(
    base::DictionaryValue* args, IPC::Message* reply_message) {
  ProfileManager* profile_manager = g_browser_process->profile_manager();
  new BrowserOpenedWithNewProfileNotificationObserver(this, reply_message);
  profile_manager->CreateMultiProfileAsync(
      string16(), string16(), ProfileManager::CreateCallback(), std::string());
}

// Sample json input: { "command": "GetMultiProfileInfo" }
// See GetMultiProfileInfo() in pyauto.py for sample output.
void TestingAutomationProvider::GetMultiProfileInfo(
    base::DictionaryValue* args, IPC::Message* reply_message) {
  scoped_ptr<DictionaryValue> return_value(new DictionaryValue);
  ProfileManager* profile_manager = g_browser_process->profile_manager();
  const ProfileInfoCache& profile_info_cache =
      profile_manager->GetProfileInfoCache();
  return_value->SetBoolean("enabled", profiles::IsMultipleProfilesEnabled());

  ListValue* profiles = new ListValue;
  for (size_t index = 0; index < profile_info_cache.GetNumberOfProfiles();
       ++index) {
    DictionaryValue* item = new DictionaryValue;
    item->SetString("name", profile_info_cache.GetNameOfProfileAtIndex(index));
    item->SetString("path",
                    profile_info_cache.GetPathOfProfileAtIndex(index).value());
    profiles->Append(item);
  }
  return_value->Set("profiles", profiles);
  AutomationJSONReply(this, reply_message).SendSuccess(return_value.get());
}

void TestingAutomationProvider::OpenNewBrowserWindowOfType(
    int type, bool show, IPC::Message* reply_message) {
  new BrowserOpenedNotificationObserver(this, reply_message, false);
  // We may have no current browser windows open so don't rely on
  // asking an existing browser to execute the IDC_NEWWINDOW command.
  Browser* browser = new Browser(
      Browser::CreateParams(static_cast<Browser::Type>(type), profile_,
                            chrome::HOST_DESKTOP_TYPE_NATIVE));
  chrome::AddBlankTabAt(browser, -1, true);
  if (show)
    browser->window()->Show();
}

void TestingAutomationProvider::OpenNewBrowserWindow(
    base::DictionaryValue* args,
    IPC::Message* reply_message) {
  bool show;
  if (!args->GetBoolean("show", &show)) {
    AutomationJSONReply(this, reply_message)
        .SendError("'show' missing or invalid.");
    return;
  }
  new BrowserOpenedNotificationObserver(this, reply_message, true);
  Browser* browser = new Browser(
      Browser::CreateParams(Browser::TYPE_TABBED, profile_,
                            chrome::HOST_DESKTOP_TYPE_NATIVE));
  chrome::AddBlankTabAt(browser, -1, true);
  if (show)
    browser->window()->Show();
}

void TestingAutomationProvider::GetBrowserWindowCountJSON(
    base::DictionaryValue* args,
    IPC::Message* reply_message) {
  DictionaryValue dict;
  // The automation layer doesn't support non-native desktops.
  dict.SetInteger("count",
                  static_cast<int>(BrowserList::GetInstance(
                      chrome::HOST_DESKTOP_TYPE_NATIVE)->size()));
  AutomationJSONReply(this, reply_message).SendSuccess(&dict);
}

void TestingAutomationProvider::CloseBrowserWindow(
    base::DictionaryValue* args,
    IPC::Message* reply_message) {
  AutomationJSONReply reply(this, reply_message);
  Browser* browser;
  std::string error_msg;
  if (!GetBrowserFromJSONArgs(args, &browser, &error_msg)) {
    reply.SendError(error_msg);
    return;
  }
  new BrowserClosedNotificationObserver(browser, this, reply_message, true);
  browser->window()->Close();
}

void TestingAutomationProvider::OpenProfileWindow(
    base::DictionaryValue* args, IPC::Message* reply_message) {
  ProfileManager* profile_manager = g_browser_process->profile_manager();
  base::FilePath::StringType path;
  if (!args->GetString("path", &path)) {
    AutomationJSONReply(this, reply_message).SendError(
        "Invalid or missing arg: 'path'");
    return;
  }
  Profile* profile = profile_manager->GetProfileByPath(base::FilePath(path));
  if (!profile) {
    AutomationJSONReply(this, reply_message).SendError(
        base::StringPrintf("Invalid profile path: %s", path.c_str()));
    return;
  }
  int num_loads;
  if (!args->GetInteger("num_loads", &num_loads)) {
    AutomationJSONReply(this, reply_message).SendError(
        "Invalid or missing arg: 'num_loads'");
    return;
  }
  new BrowserOpenedWithExistingProfileNotificationObserver(
      this, reply_message, num_loads);
  profiles::FindOrCreateNewWindowForProfile(
      profile,
      chrome::startup::IS_NOT_PROCESS_STARTUP,
      chrome::startup::IS_NOT_FIRST_RUN,
      chrome::HOST_DESKTOP_TYPE_NATIVE,
      false);
  }

void TestingAutomationProvider::GetWindowForBrowser(int browser_handle,
                                                    bool* success,
                                                    int* handle) {
  *success = false;
  *handle = 0;

  if (browser_tracker_->ContainsHandle(browser_handle)) {
    Browser* browser = browser_tracker_->GetResource(browser_handle);
    gfx::NativeWindow win = browser->window()->GetNativeWindow();
    // Add() returns the existing handle for the resource if any.
    *handle = window_tracker_->Add(win);
    *success = true;
  }
}

void TestingAutomationProvider::GetMetricEventDuration(
    const std::string& event_name,
    int* duration_ms) {
  *duration_ms = metric_event_duration_observer_->GetEventDurationMs(
      event_name);
}

void TestingAutomationProvider::BringBrowserToFront(int browser_handle,
                                                    bool* success) {
  *success = false;
  if (browser_tracker_->ContainsHandle(browser_handle)) {
    Browser* browser = browser_tracker_->GetResource(browser_handle);
    browser->window()->Activate();
    *success = true;
  }
}

void TestingAutomationProvider::GetFindWindowVisibility(int handle,
                                                        bool* visible) {
  *visible = false;
  Browser* browser = browser_tracker_->GetResource(handle);
  if (browser) {
    FindBarTesting* find_bar =
        browser->GetFindBarController()->find_bar()->GetFindBarTesting();
    find_bar->GetFindBarWindowInfo(NULL, visible);
  }
}

// Bookmark bar visibility is based on the pref (e.g. is it in the toolbar).
// Presence in the NTP is signalled in |detached|.
void TestingAutomationProvider::GetBookmarkBarStatus(
    DictionaryValue* args,
    IPC::Message* reply_message) {
  AutomationJSONReply reply(this, reply_message);
  Browser* browser;
  std::string error_msg;
  if (!GetBrowserFromJSONArgs(args, &browser, &error_msg)) {
    reply.SendError(error_msg);
    return;
  }
  // browser->window()->IsBookmarkBarVisible() is not consistent across
  // platforms. bookmark_bar_state() also follows prefs::kShowBookmarkBar
  // and has a shared implementation on all platforms.
  DictionaryValue dict;
  dict.SetBoolean("visible",
                  browser->bookmark_bar_state() == BookmarkBar::SHOW);
  dict.SetBoolean("animating", browser->window()->IsBookmarkBarAnimating());
  dict.SetBoolean("detached",
                  browser->bookmark_bar_state() == BookmarkBar::DETACHED);
  reply.SendSuccess(&dict);
}

void TestingAutomationProvider::GetBookmarksAsJSON(
    DictionaryValue* args,
    IPC::Message* reply_message) {
  AutomationJSONReply reply(this, reply_message);
  Browser* browser;
  std::string error_msg, bookmarks_as_json;
  if (!GetBrowserFromJSONArgs(args, &browser, &error_msg)) {
    reply.SendError(error_msg);
    return;
  }
  BookmarkModel* bookmark_model =
      BookmarkModelFactory::GetForProfile(browser->profile());
  if (!bookmark_model->loaded()) {
    reply.SendError("Bookmark model is not loaded");
    return;
  }
  scoped_refptr<BookmarkStorage> storage(
      new BookmarkStorage(browser->profile(),
                          bookmark_model,
                          browser->profile()->GetIOTaskRunner().get()));
  if (!storage->SerializeData(&bookmarks_as_json)) {
    reply.SendError("Failed to serialize bookmarks");
    return;
  }
  DictionaryValue dict;
  dict.SetString("bookmarks_as_json", bookmarks_as_json);
  reply.SendSuccess(&dict);
}

void TestingAutomationProvider::WaitForBookmarkModelToLoad(
    int handle,
    IPC::Message* reply_message) {
  if (browser_tracker_->ContainsHandle(handle)) {
    Browser* browser = browser_tracker_->GetResource(handle);
    BookmarkModel* model =
        BookmarkModelFactory::GetForProfile(browser->profile());
    AutomationProviderBookmarkModelObserver* observer =
        new AutomationProviderBookmarkModelObserver(this, reply_message,
                                                    model, false);
    if (model->loaded()) {
      observer->ReleaseReply();
      delete observer;
      AutomationMsg_WaitForBookmarkModelToLoad::WriteReplyParams(
          reply_message, true);
      Send(reply_message);
    }
  }
}

void TestingAutomationProvider::WaitForBookmarkModelToLoadJSON(
    DictionaryValue* args,
    IPC::Message* reply_message) {
  Browser* browser;
  std::string error_msg;
  if (!GetBrowserFromJSONArgs(args, &browser, &error_msg)) {
    AutomationJSONReply(this, reply_message).SendError(error_msg);
    return;
  }
  BookmarkModel* model =
      BookmarkModelFactory::GetForProfile(browser->profile());
  AutomationProviderBookmarkModelObserver* observer =
      new AutomationProviderBookmarkModelObserver(this, reply_message, model,
                                                  true);
  if (model->loaded()) {
    observer->ReleaseReply();
    delete observer;
    AutomationJSONReply(this, reply_message).SendSuccess(NULL);
    return;
  }
}

void TestingAutomationProvider::AddBookmark(
    DictionaryValue* args,
    IPC::Message* reply_message) {
  AutomationJSONReply reply(this, reply_message);
  Browser* browser;
  std::string error_msg, url;
  string16 title;
  int parent_id, index;
  bool folder;
  if (!GetBrowserFromJSONArgs(args, &browser, &error_msg)) {
    reply.SendError(error_msg);
    return;
  }
  if (!args->GetBoolean("is_folder", &folder)) {
    reply.SendError("'is_folder' missing or invalid");
    return;
  }
  if (!folder && !args->GetString("url", &url)) {
    reply.SendError("'url' missing or invalid");
    return;
  }
  if (!args->GetInteger("parent_id", &parent_id)) {
    reply.SendError("'parent_id' missing or invalid");
    return;
  }
  if (!args->GetInteger("index", &index)) {
    reply.SendError("'index' missing or invalid");
    return;
  }
  if (!args->GetString("title", &title)) {
    reply.SendError("'title' missing or invalid");
    return;
  }
  BookmarkModel* model =
      BookmarkModelFactory::GetForProfile(browser->profile());
  if (!model->loaded()) {
    reply.SendError("Bookmark model is not loaded");
    return;
  }
  const BookmarkNode* parent = model->GetNodeByID(parent_id);
  if (!parent) {
    reply.SendError("Failed to get parent bookmark node");
    return;
  }
  const BookmarkNode* child;
  if (folder) {
    child = model->AddFolder(parent, index, title);
  } else {
    child = model->AddURL(parent, index, title, GURL(url));
  }
  if (!child) {
    reply.SendError("Failed to add bookmark");
    return;
  }
  reply.SendSuccess(NULL);
}

void TestingAutomationProvider::ReparentBookmark(DictionaryValue* args,
                                                 IPC::Message* reply_message) {
  AutomationJSONReply reply(this, reply_message);
  Browser* browser;
  std::string error_msg;
  int new_parent_id, id, index;
  if (!GetBrowserFromJSONArgs(args, &browser, &error_msg)) {
    reply.SendError(error_msg);
    return;
  }
  if (!args->GetInteger("id", &id)) {
    reply.SendError("'id' missing or invalid");
    return;
  }
  if (!args->GetInteger("new_parent_id", &new_parent_id)) {
    reply.SendError("'new_parent_id' missing or invalid");
    return;
  }
  if (!args->GetInteger("index", &index)) {
    reply.SendError("'index' missing or invalid");
    return;
  }
  BookmarkModel* model =
      BookmarkModelFactory::GetForProfile(browser->profile());
  if (!model->loaded()) {
    reply.SendError("Bookmark model is not loaded");
    return;
  }
  const BookmarkNode* node = model->GetNodeByID(id);
  const BookmarkNode* new_parent = model->GetNodeByID(new_parent_id);
  if (!node) {
    reply.SendError("Failed to get bookmark node");
    return;
  }
  if (!new_parent) {
    reply.SendError("Failed to get new parent bookmark node");
    return;
  }
  model->Move(node, new_parent, index);
  reply.SendSuccess(NULL);
}

void TestingAutomationProvider::SetBookmarkTitle(DictionaryValue* args,
                                                 IPC::Message* reply_message) {
  AutomationJSONReply reply(this, reply_message);
  Browser* browser;
  std::string error_msg;
  string16 title;
  int id;
  if (!GetBrowserFromJSONArgs(args, &browser, &error_msg)) {
    reply.SendError(error_msg);
    return;
  }
  if (!args->GetInteger("id", &id)) {
    reply.SendError("'id' missing or invalid");
    return;
  }
  if (!args->GetString("title", &title)) {
    reply.SendError("'title' missing or invalid");
    return;
  }
  BookmarkModel* model =
      BookmarkModelFactory::GetForProfile(browser->profile());
  if (!model->loaded()) {
    reply.SendError("Bookmark model is not loaded");
    return;
  }
  const BookmarkNode* node = model->GetNodeByID(id);
  if (!node) {
    reply.SendError("Failed to get bookmark node");
    return;
  }
  model->SetTitle(node, title);
  reply.SendSuccess(NULL);
}

void TestingAutomationProvider::SetBookmarkURL(DictionaryValue* args,
                                               IPC::Message* reply_message) {
  AutomationJSONReply reply(this, reply_message);
  Browser* browser;
  std::string error_msg, url;
  int id;
  if (!GetBrowserFromJSONArgs(args, &browser, &error_msg)) {
    reply.SendError(error_msg);
    return;
  }
  if (!args->GetInteger("id", &id)) {
    reply.SendError("'id' missing or invalid");
    return;
  }
  if (!args->GetString("url", &url)) {
    reply.SendError("'url' missing or invalid");
    return;
  }
  BookmarkModel* model =
      BookmarkModelFactory::GetForProfile(browser->profile());
  if (!model->loaded()) {
    reply.SendError("Bookmark model is not loaded");
    return;
  }
  const BookmarkNode* node = model->GetNodeByID(id);
  if (!node) {
    reply.SendError("Failed to get bookmark node");
    return;
  }
  model->SetURL(node, GURL(url));
  reply.SendSuccess(NULL);
}

void TestingAutomationProvider::RemoveBookmark(DictionaryValue* args,
                                               IPC::Message* reply_message) {
  AutomationJSONReply reply(this, reply_message);
  Browser* browser;
  std::string error_msg;
  int id;
  if (!GetBrowserFromJSONArgs(args, &browser, &error_msg)) {
    reply.SendError(error_msg);
    return;
  }
  if (!args->GetInteger("id", &id)) {
    reply.SendError("'id' missing or invalid");
    return;
  }
  BookmarkModel* model =
      BookmarkModelFactory::GetForProfile(browser->profile());
  if (!model->loaded()) {
    reply.SendError("Bookmark model is not loaded");
    return;
  }
  const BookmarkNode* node = model->GetNodeByID(id);
  if (!node) {
    reply.SendError("Failed to get bookmark node");
    return;
  }
  const BookmarkNode* parent = node->parent();
  if (!parent) {
    reply.SendError("Failed to get parent bookmark node");
    return;
  }
  model->Remove(parent, parent->GetIndexOf(node));
  reply.SendSuccess(NULL);
}

void TestingAutomationProvider::WaitForBrowserWindowCountToBecome(
    int target_count,
    IPC::Message* reply_message) {
  // The automation layer doesn't support non-native desktops.
  int current_count = static_cast<int>(BrowserList::GetInstance(
                          chrome::HOST_DESKTOP_TYPE_NATIVE)->size());
  if (current_count == target_count) {
    AutomationMsg_WaitForBrowserWindowCountToBecome::WriteReplyParams(
        reply_message, true);
    Send(reply_message);
    return;
  }

  // Set up an observer (it will delete itself).
  new BrowserCountChangeNotificationObserver(target_count, this, reply_message);
}

void TestingAutomationProvider::GoBackBlockUntilNavigationsComplete(
    int handle, int number_of_navigations, IPC::Message* reply_message) {
  if (tab_tracker_->ContainsHandle(handle)) {
    NavigationController* tab = tab_tracker_->GetResource(handle);
    Browser* browser = FindAndActivateTab(tab);
    if (chrome::IsCommandEnabled(browser, IDC_BACK)) {
      new NavigationNotificationObserver(tab, this, reply_message,
                                         number_of_navigations, false, false);
      chrome::ExecuteCommand(browser, IDC_BACK);
      return;
    }
  }

  AutomationMsg_GoBackBlockUntilNavigationsComplete::WriteReplyParams(
      reply_message, AUTOMATION_MSG_NAVIGATION_ERROR);
  Send(reply_message);
}

void TestingAutomationProvider::GoForwardBlockUntilNavigationsComplete(
    int handle, int number_of_navigations, IPC::Message* reply_message) {
  if (tab_tracker_->ContainsHandle(handle)) {
    NavigationController* tab = tab_tracker_->GetResource(handle);
    Browser* browser = FindAndActivateTab(tab);
    if (chrome::IsCommandEnabled(browser, IDC_FORWARD)) {
      new NavigationNotificationObserver(tab, this, reply_message,
                                         number_of_navigations, false, false);
      chrome::ExecuteCommand(browser, IDC_FORWARD);
      return;
    }
  }

  AutomationMsg_GoForwardBlockUntilNavigationsComplete::WriteReplyParams(
      reply_message, AUTOMATION_MSG_NAVIGATION_ERROR);
  Send(reply_message);
}

void TestingAutomationProvider::BuildJSONHandlerMaps() {
  // Map json commands to their handlers.
  handler_map_["ApplyAccelerator"] =
      &TestingAutomationProvider::ExecuteBrowserCommandAsyncJSON;
  handler_map_["RunCommand"] =
      &TestingAutomationProvider::ExecuteBrowserCommandJSON;
  handler_map_["IsMenuCommandEnabled"] =
      &TestingAutomationProvider::IsMenuCommandEnabledJSON;
  handler_map_["ActivateTab"] =
      &TestingAutomationProvider::ActivateTabJSON;
  handler_map_["BringBrowserToFront"] =
      &TestingAutomationProvider::BringBrowserToFrontJSON;
  handler_map_["GetIndicesFromTab"] =
      &TestingAutomationProvider::GetIndicesFromTab;
  handler_map_["NavigateToURL"] =
      &TestingAutomationProvider::NavigateToURL;
  handler_map_["GetActiveTabIndex"] =
      &TestingAutomationProvider::GetActiveTabIndexJSON;
  handler_map_["AppendTab"] =
      &TestingAutomationProvider::AppendTabJSON;
  handler_map_["OpenNewBrowserWindow"] =
      &TestingAutomationProvider::OpenNewBrowserWindow;
  handler_map_["CloseBrowserWindow"] =
      &TestingAutomationProvider::CloseBrowserWindow;
  handler_map_["WaitUntilNavigationCompletes"] =
      &TestingAutomationProvider::WaitUntilNavigationCompletes;
  handler_map_["GetLocalStatePrefsInfo"] =
      &TestingAutomationProvider::GetLocalStatePrefsInfo;
  handler_map_["SetLocalStatePrefs"] =
      &TestingAutomationProvider::SetLocalStatePrefs;
  handler_map_["GetPrefsInfo"] = &TestingAutomationProvider::GetPrefsInfo;
  handler_map_["SetPrefs"] = &TestingAutomationProvider::SetPrefs;
  handler_map_["ExecuteJavascript"] =
      &TestingAutomationProvider::ExecuteJavascriptJSON;
  handler_map_["AddDomEventObserver"] =
      &TestingAutomationProvider::AddDomEventObserver;
  handler_map_["RemoveEventObserver"] =
      &TestingAutomationProvider::RemoveEventObserver;
  handler_map_["GetNextEvent"] =
      &TestingAutomationProvider::GetNextEvent;
  handler_map_["ClearEventQueue"] =
      &TestingAutomationProvider::ClearEventQueue;
  handler_map_["ExecuteJavascriptInRenderView"] =
      &TestingAutomationProvider::ExecuteJavascriptInRenderView;
  handler_map_["GoForward"] =
      &TestingAutomationProvider::GoForward;
  handler_map_["GoBack"] =
      &TestingAutomationProvider::GoBack;
  handler_map_["Reload"] =
      &TestingAutomationProvider::ReloadJSON;
  handler_map_["OpenFindInPage"] =
      &TestingAutomationProvider::OpenFindInPage;
  handler_map_["IsFindInPageVisible"] =
      &TestingAutomationProvider::IsFindInPageVisible;
  handler_map_["SetDownloadShelfVisible"] =
      &TestingAutomationProvider::SetDownloadShelfVisibleJSON;
  handler_map_["IsDownloadShelfVisible"] =
      &TestingAutomationProvider::IsDownloadShelfVisibleJSON;
  handler_map_["GetDownloadDirectory"] =
      &TestingAutomationProvider::GetDownloadDirectoryJSON;
  handler_map_["GetCookies"] =
      &TestingAutomationProvider::GetCookiesJSON;
  handler_map_["DeleteCookie"] =
      &TestingAutomationProvider::DeleteCookieJSON;
  handler_map_["SetCookie"] =
      &TestingAutomationProvider::SetCookieJSON;
  handler_map_["GetCookiesInBrowserContext"] =
      &TestingAutomationProvider::GetCookiesInBrowserContext;
  handler_map_["DeleteCookieInBrowserContext"] =
      &TestingAutomationProvider::DeleteCookieInBrowserContext;
  handler_map_["SetCookieInBrowserContext"] =
      &TestingAutomationProvider::SetCookieInBrowserContext;

  handler_map_["WaitForBookmarkModelToLoad"] =
      &TestingAutomationProvider::WaitForBookmarkModelToLoadJSON;
  handler_map_["GetBookmarksAsJSON"] =
      &TestingAutomationProvider::GetBookmarksAsJSON;
  handler_map_["GetBookmarkBarStatus"] =
      &TestingAutomationProvider::GetBookmarkBarStatus;
  handler_map_["AddBookmark"] =
      &TestingAutomationProvider::AddBookmark;
  handler_map_["ReparentBookmark"] =
      &TestingAutomationProvider::ReparentBookmark;
  handler_map_["SetBookmarkTitle"] =
      &TestingAutomationProvider::SetBookmarkTitle;
  handler_map_["SetBookmarkURL"] =
      &TestingAutomationProvider::SetBookmarkURL;
  handler_map_["RemoveBookmark"] =
      &TestingAutomationProvider::RemoveBookmark;

  handler_map_["GetTabIds"] =
      &TestingAutomationProvider::GetTabIds;
  handler_map_["IsTabIdValid"] =
      &TestingAutomationProvider::IsTabIdValid;
  handler_map_["CloseTab"] =
      &TestingAutomationProvider::CloseTabJSON;
  handler_map_["SetViewBounds"] =
      &TestingAutomationProvider::SetViewBounds;
  handler_map_["MaximizeView"] =
      &TestingAutomationProvider::MaximizeView;
  handler_map_["WebkitMouseMove"] =
      &TestingAutomationProvider::WebkitMouseMove;
  handler_map_["WebkitMouseClick"] =
      &TestingAutomationProvider::WebkitMouseClick;
  handler_map_["WebkitMouseDrag"] =
      &TestingAutomationProvider::WebkitMouseDrag;
  handler_map_["WebkitMouseButtonUp"] =
      &TestingAutomationProvider::WebkitMouseButtonUp;
  handler_map_["WebkitMouseButtonDown"] =
      &TestingAutomationProvider::WebkitMouseButtonDown;
  handler_map_["WebkitMouseDoubleClick"] =
      &TestingAutomationProvider::WebkitMouseDoubleClick;
  handler_map_["DragAndDropFilePaths"] =
      &TestingAutomationProvider::DragAndDropFilePaths;
  handler_map_["SendWebkitKeyEvent"] =
      &TestingAutomationProvider::SendWebkitKeyEvent;
  handler_map_["ActivateTab"] =
      &TestingAutomationProvider::ActivateTabJSON;
  handler_map_["GetAppModalDialogMessage"] =
      &TestingAutomationProvider::GetAppModalDialogMessage;
  handler_map_["AcceptOrDismissAppModalDialog"] =
      &TestingAutomationProvider::AcceptOrDismissAppModalDialog;
  handler_map_["ActionOnSSLBlockingPage"] =
      &TestingAutomationProvider::ActionOnSSLBlockingPage;
  handler_map_["GetSecurityState"] =
      &TestingAutomationProvider::GetSecurityState;
  handler_map_["IsPageActionVisible"] =
      &TestingAutomationProvider::IsPageActionVisible;
  handler_map_["CreateNewAutomationProvider"] =
      &TestingAutomationProvider::CreateNewAutomationProvider;
  handler_map_["GetBrowserWindowCount"] =
      &TestingAutomationProvider::GetBrowserWindowCountJSON;
  handler_map_["GetBrowserInfo"] =
      &TestingAutomationProvider::GetBrowserInfo;
  handler_map_["GetTabInfo"] =
      &TestingAutomationProvider::GetTabInfo;
  handler_map_["GetTabCount"] =
      &TestingAutomationProvider::GetTabCountJSON;
  handler_map_["OpenNewBrowserWindowWithNewProfile"] =
      &TestingAutomationProvider::OpenNewBrowserWindowWithNewProfile;
  handler_map_["GetMultiProfileInfo"] =
      &TestingAutomationProvider::GetMultiProfileInfo;
  handler_map_["OpenProfileWindow"] =
      &TestingAutomationProvider::OpenProfileWindow;
  handler_map_["GetProcessInfo"] =
      &TestingAutomationProvider::GetProcessInfo;
  handler_map_["RefreshPolicies"] =
      &TestingAutomationProvider::RefreshPolicies;
  handler_map_["InstallExtension"] =
      &TestingAutomationProvider::InstallExtension;
  handler_map_["GetExtensionsInfo"] =
      &TestingAutomationProvider::GetExtensionsInfo;
  handler_map_["UninstallExtensionById"] =
      &TestingAutomationProvider::UninstallExtensionById;
  handler_map_["SetExtensionStateById"] =
      &TestingAutomationProvider::SetExtensionStateById;
  handler_map_["TriggerPageActionById"] =
      &TestingAutomationProvider::TriggerPageActionById;
  handler_map_["TriggerBrowserActionById"] =
      &TestingAutomationProvider::TriggerBrowserActionById;
  handler_map_["UpdateExtensionsNow"] =
      &TestingAutomationProvider::UpdateExtensionsNow;
  handler_map_["OverrideGeoposition"] =
      &TestingAutomationProvider::OverrideGeoposition;
  handler_map_["SimulateAsanMemoryBug"] =
      &TestingAutomationProvider::SimulateAsanMemoryBug;

#if defined(OS_CHROMEOS)
  handler_map_["AcceptOOBENetworkScreen"] =
      &TestingAutomationProvider::AcceptOOBENetworkScreen;
  handler_map_["AcceptOOBEEula"] = &TestingAutomationProvider::AcceptOOBEEula;
  handler_map_["CancelOOBEUpdate"] =
      &TestingAutomationProvider::CancelOOBEUpdate;
  handler_map_["PickUserImage"] = &TestingAutomationProvider::PickUserImage;
  handler_map_["SkipToLogin"] = &TestingAutomationProvider::SkipToLogin;
  handler_map_["GetOOBEScreenInfo"] =
      &TestingAutomationProvider::GetOOBEScreenInfo;

  handler_map_["GetLoginInfo"] = &TestingAutomationProvider::GetLoginInfo;
  handler_map_["ShowCreateAccountUI"] =
      &TestingAutomationProvider::ShowCreateAccountUI;
  handler_map_["ExecuteJavascriptInOOBEWebUI"] =
      &TestingAutomationProvider::ExecuteJavascriptInOOBEWebUI;
  handler_map_["LoginAsGuest"] = &TestingAutomationProvider::LoginAsGuest;
  handler_map_["SubmitLoginForm"] =
      &TestingAutomationProvider::SubmitLoginForm;
  handler_map_["AddLoginEventObserver"] =
      &TestingAutomationProvider::AddLoginEventObserver;
  handler_map_["SignOut"] = &TestingAutomationProvider::SignOut;

  handler_map_["LockScreen"] = &TestingAutomationProvider::LockScreen;
  handler_map_["UnlockScreen"] = &TestingAutomationProvider::UnlockScreen;
  handler_map_["SignoutInScreenLocker"] =
      &TestingAutomationProvider::SignoutInScreenLocker;

  handler_map_["GetBatteryInfo"] = &TestingAutomationProvider::GetBatteryInfo;

  handler_map_["EnableSpokenFeedback"] =
      &TestingAutomationProvider::EnableSpokenFeedback;
  handler_map_["IsSpokenFeedbackEnabled"] =
      &TestingAutomationProvider::IsSpokenFeedbackEnabled;

  handler_map_["GetTimeInfo"] = &TestingAutomationProvider::GetTimeInfo;
  handler_map_["SetTimezone"] = &TestingAutomationProvider::SetTimezone;

  handler_map_["UpdateCheck"] = &TestingAutomationProvider::UpdateCheck;

  handler_map_["GetVolumeInfo"] = &TestingAutomationProvider::GetVolumeInfo;
  handler_map_["SetVolume"] = &TestingAutomationProvider::SetVolume;
  handler_map_["SetMute"] = &TestingAutomationProvider::SetMute;

  handler_map_["OpenCrosh"] = &TestingAutomationProvider::OpenCrosh;

  browser_handler_map_["GetTimeInfo"] =
      &TestingAutomationProvider::GetTimeInfo;
#endif  // defined(OS_CHROMEOS)

  browser_handler_map_["DisablePlugin"] =
      &TestingAutomationProvider::DisablePlugin;
  browser_handler_map_["EnablePlugin"] =
      &TestingAutomationProvider::EnablePlugin;
  browser_handler_map_["GetPluginsInfo"] =
      &TestingAutomationProvider::GetPluginsInfo;

  browser_handler_map_["GetNavigationInfo"] =
      &TestingAutomationProvider::GetNavigationInfo;

  browser_handler_map_["PerformActionOnInfobar"] =
      &TestingAutomationProvider::PerformActionOnInfobar;

  browser_handler_map_["GetHistoryInfo"] =
      &TestingAutomationProvider::GetHistoryInfo;

  browser_handler_map_["GetOmniboxInfo"] =
      &TestingAutomationProvider::GetOmniboxInfo;
  browser_handler_map_["SetOmniboxText"] =
      &TestingAutomationProvider::SetOmniboxText;
  browser_handler_map_["OmniboxAcceptInput"] =
      &TestingAutomationProvider::OmniboxAcceptInput;
  browser_handler_map_["OmniboxMovePopupSelection"] =
      &TestingAutomationProvider::OmniboxMovePopupSelection;

  browser_handler_map_["LoadSearchEngineInfo"] =
      &TestingAutomationProvider::LoadSearchEngineInfo;
  browser_handler_map_["GetSearchEngineInfo"] =
      &TestingAutomationProvider::GetSearchEngineInfo;
  browser_handler_map_["AddOrEditSearchEngine"] =
      &TestingAutomationProvider::AddOrEditSearchEngine;
  browser_handler_map_["PerformActionOnSearchEngine"] =
      &TestingAutomationProvider::PerformActionOnSearchEngine;

  browser_handler_map_["SetWindowDimensions"] =
      &TestingAutomationProvider::SetWindowDimensions;

  browser_handler_map_["GetDownloadsInfo"] =
      &TestingAutomationProvider::GetDownloadsInfo;
  browser_handler_map_["WaitForAllDownloadsToComplete"] =
      &TestingAutomationProvider::WaitForAllDownloadsToComplete;
  browser_handler_map_["PerformActionOnDownload"] =
      &TestingAutomationProvider::PerformActionOnDownload;

  browser_handler_map_["GetInitialLoadTimes"] =
      &TestingAutomationProvider::GetInitialLoadTimes;

  browser_handler_map_["SaveTabContents"] =
      &TestingAutomationProvider::SaveTabContents;

  browser_handler_map_["AddSavedPassword"] =
      &TestingAutomationProvider::AddSavedPassword;
  browser_handler_map_["RemoveSavedPassword"] =
      &TestingAutomationProvider::RemoveSavedPassword;
  browser_handler_map_["GetSavedPasswords"] =
      &TestingAutomationProvider::GetSavedPasswords;

  browser_handler_map_["FindInPage"] = &TestingAutomationProvider::FindInPage;

  browser_handler_map_["GetAllNotifications"] =
      &TestingAutomationProvider::GetAllNotifications;
  browser_handler_map_["CloseNotification"] =
      &TestingAutomationProvider::CloseNotification;
  browser_handler_map_["WaitForNotificationCount"] =
      &TestingAutomationProvider::WaitForNotificationCount;

  browser_handler_map_["GetNTPInfo"] =
      &TestingAutomationProvider::GetNTPInfo;
  browser_handler_map_["RemoveNTPMostVisitedThumbnail"] =
      &TestingAutomationProvider::RemoveNTPMostVisitedThumbnail;
  browser_handler_map_["RestoreAllNTPMostVisitedThumbnails"] =
      &TestingAutomationProvider::RestoreAllNTPMostVisitedThumbnails;

  browser_handler_map_["KillRendererProcess"] =
      &TestingAutomationProvider::KillRendererProcess;

  browser_handler_map_["LaunchApp"] = &TestingAutomationProvider::LaunchApp;
  browser_handler_map_["SetAppLaunchType"] =
      &TestingAutomationProvider::SetAppLaunchType;

  browser_handler_map_["GetV8HeapStats"] =
      &TestingAutomationProvider::GetV8HeapStats;
  browser_handler_map_["GetFPS"] =
      &TestingAutomationProvider::GetFPS;

  browser_handler_map_["IsFullscreenForBrowser"] =
      &TestingAutomationProvider::IsFullscreenForBrowser;
  browser_handler_map_["IsFullscreenForTab"] =
      &TestingAutomationProvider::IsFullscreenForTab;
  browser_handler_map_["IsMouseLocked"] =
      &TestingAutomationProvider::IsMouseLocked;
  browser_handler_map_["IsMouseLockPermissionRequested"] =
      &TestingAutomationProvider::IsMouseLockPermissionRequested;
  browser_handler_map_["IsFullscreenPermissionRequested"] =
      &TestingAutomationProvider::IsFullscreenPermissionRequested;
  browser_handler_map_["IsFullscreenBubbleDisplayed"] =
      &TestingAutomationProvider::IsFullscreenBubbleDisplayed;
  browser_handler_map_["IsFullscreenBubbleDisplayingButtons"] =
      &TestingAutomationProvider::IsFullscreenBubbleDisplayingButtons;
  browser_handler_map_["AcceptCurrentFullscreenOrMouseLockRequest"] =
      &TestingAutomationProvider::AcceptCurrentFullscreenOrMouseLockRequest;
  browser_handler_map_["DenyCurrentFullscreenOrMouseLockRequest"] =
      &TestingAutomationProvider::DenyCurrentFullscreenOrMouseLockRequest;
}

scoped_ptr<DictionaryValue> TestingAutomationProvider::ParseJSONRequestCommand(
    const std::string& json_request,
    std::string* command,
    std::string* error) {
  scoped_ptr<DictionaryValue> dict_value;
  scoped_ptr<Value> values(base::JSONReader::ReadAndReturnError(json_request,
      base::JSON_ALLOW_TRAILING_COMMAS, NULL, error));
  if (values.get()) {
    // Make sure input is a dict with a string command.
    if (values->GetType() != Value::TYPE_DICTIONARY) {
      *error = "Command dictionary is not a dictionary.";
    } else {
      dict_value.reset(static_cast<DictionaryValue*>(values.release()));
      if (!dict_value->GetStringASCII("command", command)) {
        *error = "Command key string missing from dictionary.";
        dict_value.reset(NULL);
      }
    }
  }
  return dict_value.Pass();
}

void TestingAutomationProvider::SendJSONRequestWithBrowserHandle(
    int handle,
    const std::string& json_request,
    IPC::Message* reply_message) {
  Browser* browser = NULL;
  if (browser_tracker_->ContainsHandle(handle))
    browser = browser_tracker_->GetResource(handle);
  if (browser || handle < 0) {
    SendJSONRequest(browser, json_request, reply_message);
  } else {
    AutomationJSONReply(this, reply_message).SendError(
        "The browser window does not exist.");
  }
}

void TestingAutomationProvider::SendJSONRequestWithBrowserIndex(
    int index,
    const std::string& json_request,
    IPC::Message* reply_message) {
  Browser* browser = index < 0 ? NULL : automation_util::GetBrowserAt(index);
  if (!browser && index >= 0) {
    AutomationJSONReply(this, reply_message).SendError(base::StringPrintf(
        "Browser window with index=%d does not exist.", index));
  } else {
    SendJSONRequest(browser, json_request, reply_message);
  }
}

void TestingAutomationProvider::SendJSONRequest(Browser* browser,
                                                const std::string& json_request,
                                                IPC::Message* reply_message) {
  std::string command, error_string;
  scoped_ptr<DictionaryValue> dict_value(
      ParseJSONRequestCommand(json_request, &command, &error_string));
  if (!dict_value.get() || command.empty()) {
    AutomationJSONReply(this, reply_message).SendError(error_string);
    return;
  }

  if (handler_map_.empty() || browser_handler_map_.empty())
    BuildJSONHandlerMaps();

  // Look for command in handlers that take a Browser.
  if (browser_handler_map_.find(std::string(command)) !=
      browser_handler_map_.end() && browser) {
    (this->*browser_handler_map_[command])(browser, dict_value.get(),
                                           reply_message);
  // Look for command in handlers that don't take a Browser.
  } else if (handler_map_.find(std::string(command)) != handler_map_.end()) {
    (this->*handler_map_[command])(dict_value.get(), reply_message);
  // Command has no handler.
  } else {
    error_string = base::StringPrintf("Unknown command '%s'. Options: ",
                                      command.c_str());
    for (std::map<std::string, JsonHandler>::const_iterator it =
         handler_map_.begin(); it != handler_map_.end(); ++it) {
      error_string += it->first + ", ";
    }
    for (std::map<std::string, BrowserJsonHandler>::const_iterator it =
         browser_handler_map_.begin(); it != browser_handler_map_.end(); ++it) {
      error_string += it->first + ", ";
    }
    AutomationJSONReply(this, reply_message).SendError(error_string);
  }
}

void TestingAutomationProvider::BringBrowserToFrontJSON(
    DictionaryValue* args,
    IPC::Message* reply_message) {
  AutomationJSONReply reply(this, reply_message);
  Browser* browser;
  std::string error_msg;
  if (!GetBrowserFromJSONArgs(args, &browser, &error_msg)) {
    reply.SendError(error_msg);
    return;
  }
  browser->window()->Activate();
  reply.SendSuccess(NULL);
}

// Sample json input: { "command": "SetWindowDimensions",
//                      "x": 20,         # optional
//                      "y": 20,         # optional
//                      "width": 800,    # optional
//                      "height": 600 }  # optional
void TestingAutomationProvider::SetWindowDimensions(
    Browser* browser,
    DictionaryValue* args,
    IPC::Message* reply_message) {
  gfx::Rect rect = browser->window()->GetRestoredBounds();
  int x, y, width, height;
  if (args->GetInteger("x", &x))
    rect.set_x(x);
  if (args->GetInteger("y", &y))
    rect.set_y(y);
  if (args->GetInteger("width", &width))
    rect.set_width(width);
  if (args->GetInteger("height", &height))
    rect.set_height(height);
  browser->window()->SetBounds(rect);
  AutomationJSONReply(this, reply_message).SendSuccess(NULL);
}

ListValue* TestingAutomationProvider::GetInfobarsInfo(WebContents* wc) {
  // Each infobar may have different properties depending on the type.
  ListValue* infobars = new ListValue;
  InfoBarService* infobar_service = InfoBarService::FromWebContents(wc);
  for (size_t i = 0; i < infobar_service->infobar_count(); ++i) {
    DictionaryValue* infobar_item = new DictionaryValue;
    InfoBarDelegate* infobar = infobar_service->infobar_at(i);
    switch (infobar->GetInfoBarAutomationType()) {
      case InfoBarDelegate::CONFIRM_INFOBAR:
        infobar_item->SetString("type", "confirm_infobar");
        break;
      case InfoBarDelegate::PASSWORD_INFOBAR:
        infobar_item->SetString("type", "password_infobar");
        break;
      case InfoBarDelegate::RPH_INFOBAR:
        infobar_item->SetString("type", "rph_infobar");
        break;
      case InfoBarDelegate::UNKNOWN_INFOBAR:
        infobar_item->SetString("type", "unknown_infobar");
        break;
    }
    if (infobar->AsConfirmInfoBarDelegate()) {
      // Also covers ThemeInstalledInfoBarDelegate.
      ConfirmInfoBarDelegate* confirm_infobar =
        infobar->AsConfirmInfoBarDelegate();
      infobar_item->SetString("text", confirm_infobar->GetMessageText());
      infobar_item->SetString("link_text", confirm_infobar->GetLinkText());
      ListValue* buttons_list = new ListValue;
      int buttons = confirm_infobar->GetButtons();
      if (buttons & ConfirmInfoBarDelegate::BUTTON_OK) {
        StringValue* button_label = new StringValue(
            confirm_infobar->GetButtonLabel(
              ConfirmInfoBarDelegate::BUTTON_OK));
        buttons_list->Append(button_label);
      }
      if (buttons & ConfirmInfoBarDelegate::BUTTON_CANCEL) {
        StringValue* button_label = new StringValue(
            confirm_infobar->GetButtonLabel(
              ConfirmInfoBarDelegate::BUTTON_CANCEL));
        buttons_list->Append(button_label);
      }
      infobar_item->Set("buttons", buttons_list);
    } else if (infobar->AsExtensionInfoBarDelegate()) {
      infobar_item->SetString("type", "extension_infobar");
    } else {
      infobar_item->SetString("type", "unknown_infobar");
    }
    infobars->Append(infobar_item);
  }
  return infobars;
}

// Sample json input: { "command": "PerformActionOnInfobar",
//                      "action": "dismiss",
//                      "infobar_index": 0,
//                      "tab_index": 0 }
// Sample output: {}
void TestingAutomationProvider::PerformActionOnInfobar(
    Browser* browser,
    DictionaryValue* args,
    IPC::Message* reply_message) {
  AutomationJSONReply reply(this, reply_message);
  int tab_index;
  int infobar_index_int;
  std::string action;
  if (!args->GetInteger("tab_index", &tab_index) ||
      !args->GetInteger("infobar_index", &infobar_index_int) ||
      !args->GetString("action", &action)) {
    reply.SendError("Invalid or missing args");
    return;
  }
  size_t infobar_index = static_cast<size_t>(infobar_index_int);

  WebContents* web_contents =
      browser->tab_strip_model()->GetWebContentsAt(tab_index);
  if (!web_contents) {
    reply.SendError(base::StringPrintf("No such tab at index %d", tab_index));
    return;
  }

  InfoBarService* infobar_service =
      InfoBarService::FromWebContents(web_contents);
  if (infobar_index >= infobar_service->infobar_count()) {
    reply.SendError(base::StringPrintf("No such infobar at index %" PRIuS,
                                       infobar_index));
    return;
  }
  InfoBarDelegate* infobar_delegate =
      infobar_service->infobar_at(infobar_index);

  if (action == "dismiss") {
    infobar_delegate->InfoBarDismissed();
    infobar_service->RemoveInfoBar(infobar_delegate);
    reply.SendSuccess(NULL);
    return;
  }
  if ((action == "accept") || (action == "cancel")) {
    ConfirmInfoBarDelegate* confirm_infobar_delegate =
        infobar_delegate->AsConfirmInfoBarDelegate();
    if (!confirm_infobar_delegate) {
      reply.SendError("Not a confirm infobar");
      return;
    }
    if ((action == "accept") ?
        confirm_infobar_delegate->Accept() : confirm_infobar_delegate->Cancel())
      infobar_service->RemoveInfoBar(infobar_delegate);
    reply.SendSuccess(NULL);
    return;
  }

  reply.SendError("Invalid action");
}

namespace {

// Gets info about BrowserChildProcessHost. Must run on IO thread to
// honor the semantics of BrowserChildProcessHostIterator.
// Used by AutomationProvider::GetBrowserInfo().
void GetChildProcessHostInfo(ListValue* child_processes) {
  for (BrowserChildProcessHostIterator iter; !iter.Done(); ++iter) {
    // Only add processes which are already started, since we need their handle.
    if (iter.GetData().handle == base::kNullProcessHandle)
      continue;
    DictionaryValue* item = new DictionaryValue;
    item->SetString("name", iter.GetData().name);
    item->SetString(
        "type",
        content::GetProcessTypeNameInEnglish(iter.GetData().process_type));
    item->SetInteger("pid", base::GetProcId(iter.GetData().handle));
    child_processes->Append(item);
  }
}

}  // namespace

// Sample json input: { "command": "GetBrowserInfo" }
// Refer to GetBrowserInfo() in chrome/test/pyautolib/pyauto.py for
// sample json output.
void TestingAutomationProvider::GetBrowserInfo(
    DictionaryValue* args,
    IPC::Message* reply_message) {
  base::ThreadRestrictions::ScopedAllowIO allow_io;  // needed for PathService
  DictionaryValue* properties = new DictionaryValue;
  properties->SetString("ChromeVersion", chrome::kChromeVersion);
  properties->SetString("BrowserProcessExecutableName",
                        chrome::kBrowserProcessExecutableName);
  properties->SetString("HelperProcessExecutableName",
                        chrome::kHelperProcessExecutableName);
  properties->SetString("BrowserProcessExecutablePath",
                        chrome::kBrowserProcessExecutablePath);
  properties->SetString("HelperProcessExecutablePath",
                        chrome::kHelperProcessExecutablePath);
  properties->SetString("command_line_string",
      CommandLine::ForCurrentProcess()->GetCommandLineString());
  base::FilePath dumps_path;
  PathService::Get(chrome::DIR_CRASH_DUMPS, &dumps_path);
  properties->SetString("DIR_CRASH_DUMPS", dumps_path.value());
#if defined(USE_AURA)
  properties->SetBoolean("aura", true);
#else
  properties->SetBoolean("aura", false);
#endif

  std::string branding;
#if defined(GOOGLE_CHROME_BUILD)
  branding = "Google Chrome";
#elif defined(CHROMIUM_BUILD)
  branding = "Chromium";
#else
  branding = "Unknown Branding";
#endif
  properties->SetString("branding", branding);

  bool is_official_build = false;
#if defined(OFFICIAL_BUILD)
  is_official_build = true;
#endif
  properties->SetBoolean("is_official", is_official_build);

  scoped_ptr<DictionaryValue> return_value(new DictionaryValue);
  return_value->Set("properties", properties);

  return_value->SetInteger("browser_pid", base::GetCurrentProcId());
  // Add info about all windows in a list of dictionaries, one dictionary
  // item per window.
  ListValue* windows = new ListValue;
  int windex = 0;

  for (chrome::BrowserIterator it; !it.done(); it.Next(), ++windex) {
    DictionaryValue* browser_item = new DictionaryValue;
    Browser* browser = *it;
    browser_item->SetInteger("index", windex);
    // Window properties
    gfx::Rect rect = browser->window()->GetRestoredBounds();
    browser_item->SetInteger("x", rect.x());
    browser_item->SetInteger("y", rect.y());
    browser_item->SetInteger("width", rect.width());
    browser_item->SetInteger("height", rect.height());
    browser_item->SetBoolean("fullscreen",
                             browser->window()->IsFullscreen());
    ListValue* visible_page_actions = new ListValue;
    // Add info about all visible page actions. Skipped on panels, which do not
    // have a location bar.
    LocationBar* loc_bar = browser->window()->GetLocationBar();
    if (loc_bar) {
      LocationBarTesting* loc_bar_test =
          loc_bar->GetLocationBarForTesting();
      size_t page_action_visible_count =
          static_cast<size_t>(loc_bar_test->PageActionVisibleCount());
      for (size_t i = 0; i < page_action_visible_count; ++i) {
        StringValue* extension_id = new StringValue(
            loc_bar_test->GetVisiblePageAction(i)->extension_id());
        visible_page_actions->Append(extension_id);
      }
    }
    browser_item->Set("visible_page_actions", visible_page_actions);
    browser_item->SetInteger("selected_tab",
                             browser->tab_strip_model()->active_index());
    browser_item->SetBoolean("incognito",
                             browser->profile()->IsOffTheRecord());
    browser_item->SetString("profile_path",
        browser->profile()->GetPath().BaseName().MaybeAsASCII());
    std::string type;
    switch (browser->type()) {
      case Browser::TYPE_TABBED:
        type = "tabbed";
        break;
      case Browser::TYPE_POPUP:
        type = "popup";
        break;
      default:
        type = "unknown";
        break;
    }
    browser_item->SetString("type", type);
    // For each window, add info about all tabs in a list of dictionaries,
    // one dictionary item per tab.
    ListValue* tabs = new ListValue;
    for (int i = 0; i < browser->tab_strip_model()->count(); ++i) {
      WebContents* wc = browser->tab_strip_model()->GetWebContentsAt(i);
      DictionaryValue* tab = new DictionaryValue;
      tab->SetInteger("index", i);
      tab->SetString("url", wc->GetURL().spec());
      tab->SetInteger("renderer_pid",
                      base::GetProcId(wc->GetRenderProcessHost()->GetHandle()));
      tab->Set("infobars", GetInfobarsInfo(wc));
      tab->SetBoolean("pinned", browser->tab_strip_model()->IsTabPinned(i));
      tabs->Append(tab);
    }
    browser_item->Set("tabs", tabs);

    windows->Append(browser_item);
  }
  return_value->Set("windows", windows);

#if defined(OS_LINUX)
  int flags = ChildProcessHost::CHILD_ALLOW_SELF;
#else
  int flags = ChildProcessHost::CHILD_NORMAL;
#endif

  // Add all extension processes in a list of dictionaries, one dictionary
  // item per extension process.
  ListValue* extension_views = new ListValue;
  ProfileManager* profile_manager = g_browser_process->profile_manager();
  std::vector<Profile*> profiles(profile_manager->GetLoadedProfiles());
  for (size_t i = 0; i < profiles.size(); ++i) {
    ExtensionProcessManager* process_manager =
        extensions::ExtensionSystem::Get(profiles[i])->process_manager();
    if (!process_manager)
      continue;
    const ExtensionProcessManager::ViewSet view_set =
        process_manager->GetAllViews();
    for (ExtensionProcessManager::ViewSet::const_iterator jt =
             view_set.begin();
         jt != view_set.end(); ++jt) {
      content::RenderViewHost* render_view_host = *jt;
      // Don't add dead extension processes.
      if (!render_view_host->IsRenderViewLive())
        continue;
      // Don't add views for which we can't obtain an extension.
      // TODO(benwells): work out why this happens. It only happens for one
      // test, and only on the bots.
      const Extension* extension =
          process_manager->GetExtensionForRenderViewHost(render_view_host);
      if (!extension)
        continue;
      DictionaryValue* item = new DictionaryValue;
      item->SetString("name", extension->name());
      item->SetString("extension_id", extension->id());
      item->SetInteger(
          "pid",
          base::GetProcId(render_view_host->GetProcess()->GetHandle()));
      DictionaryValue* view = new DictionaryValue;
      view->SetInteger(
          "render_process_id",
          render_view_host->GetProcess()->GetID());
      view->SetInteger(
          "render_view_id",
          render_view_host->GetRoutingID());
      item->Set("view", view);
      std::string type;
      WebContents* web_contents =
          WebContents::FromRenderViewHost(render_view_host);
      extensions::ViewType view_type = extensions::GetViewType(web_contents);
      switch (view_type) {
        case extensions::VIEW_TYPE_EXTENSION_BACKGROUND_PAGE:
          type = "EXTENSION_BACKGROUND_PAGE";
          break;
        case extensions::VIEW_TYPE_EXTENSION_POPUP:
          type = "EXTENSION_POPUP";
          break;
        case extensions::VIEW_TYPE_EXTENSION_INFOBAR:
          type = "EXTENSION_INFOBAR";
          break;
        case extensions::VIEW_TYPE_EXTENSION_DIALOG:
          type = "EXTENSION_DIALOG";
          break;
        case extensions::VIEW_TYPE_APP_SHELL:
          type = "APP_SHELL";
          break;
        case extensions::VIEW_TYPE_PANEL:
          type = "PANEL";
          break;
        default:
          type = "unknown";
          break;
      }
      item->SetString("view_type", type);
      item->SetString("url", web_contents->GetURL().spec());
      item->SetBoolean("loaded", !render_view_host->IsLoading());
      extension_views->Append(item);
    }
  }
  return_value->Set("extension_views", extension_views);

  return_value->SetString("child_process_path",
                          ChildProcessHost::GetChildPath(flags).value());
  // Child processes are the processes for plugins and other workers.
  // Add all child processes in a list of dictionaries, one dictionary item
  // per child process.
  ListValue* child_processes = new ListValue;
  return_value->Set("child_processes", child_processes);
  BrowserThread::PostTaskAndReply(
      BrowserThread::IO, FROM_HERE,
      base::Bind(&GetChildProcessHostInfo, child_processes),
      base::Bind(&AutomationJSONReply::SendSuccess,
                 base::Owned(new AutomationJSONReply(this, reply_message)),
                 base::Owned(return_value.release())));
}

// Sample json input: { "command": "GetProcessInfo" }
// Refer to GetProcessInfo() in chrome/test/pyautolib/pyauto.py for
// sample json output.
void TestingAutomationProvider::GetProcessInfo(
    DictionaryValue* args,
    IPC::Message* reply_message) {
  scoped_refptr<ProcessInfoObserver>
      proc_observer(new ProcessInfoObserver(this, reply_message));
  // TODO(jamescook): Maybe this shouldn't update UMA stats?
  proc_observer->StartFetch(MemoryDetails::UPDATE_USER_METRICS);
}

// Sample json input: { "command": "GetNavigationInfo" }
// Refer to GetNavigationInfo() in chrome/test/pyautolib/pyauto.py for
// sample json output.
void TestingAutomationProvider::GetNavigationInfo(
    Browser* browser,
    DictionaryValue* args,
    IPC::Message* reply_message) {
  AutomationJSONReply reply(this, reply_message);
  int tab_index;
  WebContents* web_contents = NULL;
  if (!args->GetInteger("tab_index", &tab_index) ||
      !(web_contents =
            browser->tab_strip_model()->GetWebContentsAt(tab_index))) {
    reply.SendError("tab_index missing or invalid.");
    return;
  }
  scoped_ptr<DictionaryValue> return_value(new DictionaryValue);
  const NavigationController& controller = web_contents->GetController();
  NavigationEntry* nav_entry = controller.GetActiveEntry();
  DCHECK(nav_entry);

  // Security info.
  DictionaryValue* ssl = new DictionaryValue;
  std::map<content::SecurityStyle, std::string> style_to_string;
  style_to_string[content::SECURITY_STYLE_UNKNOWN] = "SECURITY_STYLE_UNKNOWN";
  style_to_string[content::SECURITY_STYLE_UNAUTHENTICATED] =
      "SECURITY_STYLE_UNAUTHENTICATED";
  style_to_string[content::SECURITY_STYLE_AUTHENTICATION_BROKEN] =
      "SECURITY_STYLE_AUTHENTICATION_BROKEN";
  style_to_string[content::SECURITY_STYLE_AUTHENTICATED] =
      "SECURITY_STYLE_AUTHENTICATED";

  SSLStatus ssl_status = nav_entry->GetSSL();
  ssl->SetString("security_style",
                 style_to_string[ssl_status.security_style]);
  ssl->SetBoolean("ran_insecure_content",
      !!(ssl_status.content_status & SSLStatus::RAN_INSECURE_CONTENT));
  ssl->SetBoolean("displayed_insecure_content",
      !!(ssl_status.content_status & SSLStatus::DISPLAYED_INSECURE_CONTENT));
  return_value->Set("ssl", ssl);

  // Page type.
  std::map<content::PageType, std::string> pagetype_to_string;
  pagetype_to_string[content::PAGE_TYPE_NORMAL] = "NORMAL_PAGE";
  pagetype_to_string[content::PAGE_TYPE_ERROR] = "ERROR_PAGE";
  pagetype_to_string[content::PAGE_TYPE_INTERSTITIAL] =
      "INTERSTITIAL_PAGE";
  return_value->SetString("page_type",
                          pagetype_to_string[nav_entry->GetPageType()]);

  return_value->SetString("favicon_url", nav_entry->GetFavicon().url.spec());
  reply.SendSuccess(return_value.get());
}

// Sample json input: { "command": "GetHistoryInfo",
//                      "search_text": "some text" }
// Refer chrome/test/pyautolib/history_info.py for sample json output.
void TestingAutomationProvider::GetHistoryInfo(Browser* browser,
                                               DictionaryValue* args,
                                               IPC::Message* reply_message) {
  consumer_.CancelAllRequests();

  string16 search_text;
  args->GetString("search_text", &search_text);

  // Fetch history.
  HistoryService* hs = HistoryServiceFactory::GetForProfile(
      browser->profile(), Profile::EXPLICIT_ACCESS);
  history::QueryOptions options;
  // The observer owns itself.  It deletes itself after it fetches history.
  AutomationProviderHistoryObserver* history_observer =
      new AutomationProviderHistoryObserver(this, reply_message);
  hs->QueryHistory(
      search_text,
      options,
      &consumer_,
      base::Bind(&AutomationProviderHistoryObserver::HistoryQueryComplete,
                 base::Unretained(history_observer)));
}

// Sample json input: { "command": "GetDownloadsInfo" }
// Refer chrome/test/pyautolib/download_info.py for sample json output.
void TestingAutomationProvider::GetDownloadsInfo(Browser* browser,
                                                 DictionaryValue* args,
                                                 IPC::Message* reply_message) {
  AutomationJSONReply reply(this, reply_message);
  scoped_ptr<DictionaryValue> return_value(new DictionaryValue);
  ListValue* list_of_downloads = new ListValue;

  DownloadService* download_service(
      DownloadServiceFactory::GetForBrowserContext(browser->profile()));

  if (download_service->HasCreatedDownloadManager()) {
    std::vector<DownloadItem*> downloads;
    BrowserContext::GetDownloadManager(browser->profile())->GetAllDownloads(
        &downloads);

    for (std::vector<DownloadItem*>::iterator it = downloads.begin();
         it != downloads.end();
         it++) {  // Fill info about each download item.
      list_of_downloads->Append(GetDictionaryFromDownloadItem(
          *it, browser->profile()->IsOffTheRecord()));
    }
  }
  return_value->Set("downloads", list_of_downloads);
  reply.SendSuccess(return_value.get());
}

void TestingAutomationProvider::WaitForAllDownloadsToComplete(
    Browser* browser,
    DictionaryValue* args,
    IPC::Message* reply_message) {
  ListValue* pre_download_ids = NULL;

  if (!args->GetList("pre_download_ids", &pre_download_ids)) {
    AutomationJSONReply(this, reply_message)
        .SendError(
            base::StringPrintf("List of IDs of previous downloads required."));
    return;
  }

  DownloadService* download_service =
      DownloadServiceFactory::GetForBrowserContext(browser->profile());
  if (!download_service->HasCreatedDownloadManager()) {
    // No download manager, so no downloads to wait for.
    AutomationJSONReply(this, reply_message).SendSuccess(NULL);
    return;
  }

  // This observer will delete itself.
  new AllDownloadsCompleteObserver(
      this, reply_message,
      BrowserContext::GetDownloadManager(browser->profile()),
      pre_download_ids);
}

// See PerformActionOnDownload() in chrome/test/pyautolib/pyauto.py for sample
// json input and output.
void TestingAutomationProvider::PerformActionOnDownload(
    Browser* browser,
    DictionaryValue* args,
    IPC::Message* reply_message) {
  int id;
  std::string action;

  DownloadService* download_service =
      DownloadServiceFactory::GetForBrowserContext(browser->profile());
  if (!download_service->HasCreatedDownloadManager()) {
    AutomationJSONReply(this, reply_message).SendError("No download manager.");
    return;
  }
  if (!args->GetInteger("id", &id) || !args->GetString("action", &action)) {
    AutomationJSONReply(this, reply_message)
        .SendError("Must include int id and string action.");
    return;
  }

  DownloadManager* download_manager =
      BrowserContext::GetDownloadManager(browser->profile());
  DownloadItem* selected_item = download_manager->GetDownload(id);
  if (!selected_item) {
    AutomationJSONReply(this, reply_message)
        .SendError(base::StringPrintf("No download with an id of %d\n", id));
    return;
  }

  DownloadItem::DownloadState download_state = selected_item->GetState();

  // We need to be IN_PROGRESS for these actions.
  if ((action == "pause" || action == "resume" || action == "cancel") &&
      download_state != DownloadItem::IN_PROGRESS) {
    AutomationJSONReply(this, reply_message)
        .SendError(base::StringPrintf(
            "Action '%s' called on download that is not in progress.",
            action.c_str()));
    return;
  }

  if (action == "open") {
    selected_item->AddObserver(
        new AutomationProviderDownloadUpdatedObserver(
            this, reply_message, true, browser->profile()->IsOffTheRecord()));
    selected_item->OpenDownload();
  } else if (action == "toggle_open_files_like_this") {
    DownloadPrefs* prefs =
        DownloadPrefs::FromBrowserContext(selected_item->GetBrowserContext());
    base::FilePath path = selected_item->GetTargetFilePath();
    if (!selected_item->ShouldOpenFileBasedOnExtension())
      prefs->EnableAutoOpenBasedOnExtension(path);
    else
      prefs->DisableAutoOpenBasedOnExtension(path);
    AutomationJSONReply(this, reply_message).SendSuccess(NULL);
  } else if (action == "remove") {
    new AutomationProviderDownloadModelChangedObserver(
        this, reply_message, download_manager);
    selected_item->Remove();
  } else if (action == "decline_dangerous_download") {
    new AutomationProviderDownloadModelChangedObserver(
        this, reply_message, download_manager);
    selected_item->Remove();
  } else if (action == "save_dangerous_download") {
    selected_item->AddObserver(new AutomationProviderDownloadUpdatedObserver(
        this, reply_message, false, browser->profile()->IsOffTheRecord()));
    selected_item->ValidateDangerousDownload();
  } else if (action == "pause") {
    if (selected_item->IsPaused()) {
      // Action would be a no-op; respond right from here.  No-op implies
      // the test is poorly written or failing, so make it an error return.
      AutomationJSONReply(this, reply_message)
          .SendError("Action 'pause' called on already paused download.");
    } else {
      selected_item->AddObserver(new AutomationProviderDownloadUpdatedObserver(
          this, reply_message, false, browser->profile()->IsOffTheRecord()));
      selected_item->Pause();
    }
  } else if (action == "resume") {
    if (!selected_item->IsPaused()) {
      // Action would be a no-op; respond right from here.  No-op implies
      // the test is poorly written or failing, so make it an error return.
      AutomationJSONReply(this, reply_message)
          .SendError("Action 'resume' called on unpaused download.");
    } else {
      selected_item->AddObserver(new AutomationProviderDownloadUpdatedObserver(
          this, reply_message, false, browser->profile()->IsOffTheRecord()));
      selected_item->Resume();
    }
  } else if (action == "cancel") {
    selected_item->AddObserver(new AutomationProviderDownloadUpdatedObserver(
        this, reply_message, false, browser->profile()->IsOffTheRecord()));
    selected_item->Cancel(true);
  } else {
    AutomationJSONReply(this, reply_message)
        .SendError(
            base::StringPrintf("Invalid action '%s' given.", action.c_str()));
  }
}

void TestingAutomationProvider::SetDownloadShelfVisibleJSON(
    DictionaryValue* args,
    IPC::Message* reply_message) {
  AutomationJSONReply reply(this, reply_message);
  Browser* browser;
  std::string error_msg;
  bool is_visible;
  if (!GetBrowserFromJSONArgs(args, &browser, &error_msg)) {
    reply.SendError(error_msg);
    return;
  }
  if (!args->GetBoolean("is_visible", &is_visible)) {
    reply.SendError("'is_visible' missing or invalid.");
    return;
  }
  if (is_visible) {
    browser->window()->GetDownloadShelf()->Show();
  } else {
    browser->window()->GetDownloadShelf()->Close(DownloadShelf::AUTOMATIC);
  }
  reply.SendSuccess(NULL);
}

void TestingAutomationProvider::IsDownloadShelfVisibleJSON(
    DictionaryValue* args,
    IPC::Message* reply_message) {
  AutomationJSONReply reply(this, reply_message);
  Browser* browser;
  std::string error_msg;
  if (!GetBrowserFromJSONArgs(args, &browser, &error_msg)) {
    reply.SendError(error_msg);
    return;
  }
  DictionaryValue dict;
  dict.SetBoolean("is_visible", browser->window()->IsDownloadShelfVisible());
  reply.SendSuccess(&dict);
}

void TestingAutomationProvider::GetDownloadDirectoryJSON(
    DictionaryValue* args,
    IPC::Message* reply_message) {
  AutomationJSONReply reply(this, reply_message);
  WebContents* web_contents;
  std::string error;
  if (!GetTabFromJSONArgs(args, &web_contents, &error)) {
    reply.SendError(error);
    return;
  }
  DownloadManager* dlm =
      BrowserContext::GetDownloadManager(
          web_contents->GetController().GetBrowserContext());
  DictionaryValue dict;
  dict.SetString("path",
      DownloadPrefs::FromDownloadManager(dlm)->DownloadPath().value());
  reply.SendSuccess(&dict);
}

// Sample JSON input { "command": "LoadSearchEngineInfo" }
void TestingAutomationProvider::LoadSearchEngineInfo(
    Browser* browser,
    DictionaryValue* args,
    IPC::Message* reply_message) {
  TemplateURLService* url_model =
      TemplateURLServiceFactory::GetForProfile(browser->profile());
  if (url_model->loaded()) {
    AutomationJSONReply(this, reply_message).SendSuccess(NULL);
    return;
  }
  url_model->AddObserver(new AutomationProviderSearchEngineObserver(
      this, browser->profile(), reply_message));
  url_model->Load();
}

// Sample JSON input { "command": "GetSearchEngineInfo" }
// Refer to pyauto.py for sample output.
void TestingAutomationProvider::GetSearchEngineInfo(
    Browser* browser,
    DictionaryValue* args,
    IPC::Message* reply_message) {
  TemplateURLService* url_model =
      TemplateURLServiceFactory::GetForProfile(browser->profile());
  scoped_ptr<DictionaryValue> return_value(new DictionaryValue);
  ListValue* search_engines = new ListValue;
  TemplateURLService::TemplateURLVector template_urls =
      url_model->GetTemplateURLs();
  for (TemplateURLService::TemplateURLVector::const_iterator it =
       template_urls.begin(); it != template_urls.end(); ++it) {
    DictionaryValue* search_engine = new DictionaryValue;
    search_engine->SetString("short_name", UTF16ToUTF8((*it)->short_name()));
    search_engine->SetString("keyword", UTF16ToUTF8((*it)->keyword()));
    search_engine->SetBoolean("in_default_list", (*it)->ShowInDefaultList());
    search_engine->SetBoolean("is_default",
        (*it) == url_model->GetDefaultSearchProvider());
    search_engine->SetBoolean("is_valid", (*it)->url_ref().IsValid());
    search_engine->SetBoolean("supports_replacement",
                              (*it)->url_ref().SupportsReplacement());
    search_engine->SetString("url", (*it)->url());
    search_engine->SetString("host", (*it)->url_ref().GetHost());
    search_engine->SetString("path", (*it)->url_ref().GetPath());
    search_engine->SetString("display_url",
                             UTF16ToUTF8((*it)->url_ref().DisplayURL()));
    search_engines->Append(search_engine);
  }
  return_value->Set("search_engines", search_engines);
  AutomationJSONReply(this, reply_message).SendSuccess(return_value.get());
}

// Refer to pyauto.py for sample JSON input.
void TestingAutomationProvider::AddOrEditSearchEngine(
    Browser* browser,
    DictionaryValue* args,
    IPC::Message* reply_message) {
  TemplateURLService* url_model =
      TemplateURLServiceFactory::GetForProfile(browser->profile());
  string16 new_title;
  string16 new_keyword;
  std::string new_url;
  std::string keyword;
  if (!args->GetString("new_title", &new_title) ||
      !args->GetString("new_keyword", &new_keyword) ||
      !args->GetString("new_url", &new_url)) {
    AutomationJSONReply(this, reply_message).SendError(
        "One or more inputs invalid");
    return;
  }
  std::string new_ref_url = TemplateURLRef::DisplayURLToURLRef(
      UTF8ToUTF16(new_url));
  scoped_ptr<KeywordEditorController> controller(
      new KeywordEditorController(browser->profile()));
  if (args->GetString("keyword", &keyword)) {
    TemplateURL* template_url =
        url_model->GetTemplateURLForKeyword(UTF8ToUTF16(keyword));
    if (template_url == NULL) {
      AutomationJSONReply(this, reply_message).SendError(
          "No match for keyword: " + keyword);
      return;
    }
    url_model->AddObserver(new AutomationProviderSearchEngineObserver(
        this, browser->profile(), reply_message));
    controller->ModifyTemplateURL(template_url, new_title, new_keyword,
                                  new_ref_url);
  } else {
    url_model->AddObserver(new AutomationProviderSearchEngineObserver(
        this, browser->profile(), reply_message));
    controller->AddTemplateURL(new_title, new_keyword, new_ref_url);
  }
}

// Sample json input: { "command": "PerformActionOnSearchEngine",
//                      "keyword": keyword, "action": action }
void TestingAutomationProvider::PerformActionOnSearchEngine(
    Browser* browser,
    DictionaryValue* args,
    IPC::Message* reply_message) {
  TemplateURLService* url_model =
      TemplateURLServiceFactory::GetForProfile(browser->profile());
  std::string keyword;
  std::string action;
  if (!args->GetString("keyword", &keyword) ||
      !args->GetString("action", &action)) {
    AutomationJSONReply(this, reply_message).SendError(
        "One or more inputs invalid");
    return;
  }
  TemplateURL* template_url =
      url_model->GetTemplateURLForKeyword(UTF8ToUTF16(keyword));
  if (template_url == NULL) {
    AutomationJSONReply(this, reply_message).SendError(
        "No match for keyword: " + keyword);
    return;
  }
  if (action == "delete") {
    url_model->AddObserver(new AutomationProviderSearchEngineObserver(
      this, browser->profile(), reply_message));
    url_model->Remove(template_url);
  } else if (action == "default") {
    url_model->AddObserver(new AutomationProviderSearchEngineObserver(
      this, browser->profile(), reply_message));
    url_model->SetDefaultSearchProvider(template_url);
  } else {
    AutomationJSONReply(this, reply_message).SendError(
        "Invalid action: " + action);
  }
}

// Sample json input: { "command": "GetLocalStatePrefsInfo" }
// Refer chrome/test/pyautolib/prefs_info.py for sample json output.
void TestingAutomationProvider::GetLocalStatePrefsInfo(
    DictionaryValue* args,
    IPC::Message* reply_message) {
  scoped_ptr<DictionaryValue> items(
      g_browser_process->local_state()->GetPreferenceValues());
  scoped_ptr<DictionaryValue> return_value(new DictionaryValue);
  return_value->Set("prefs", items.release());  // return_value owns items.
  AutomationJSONReply(this, reply_message).SendSuccess(return_value.get());
}

// Sample json input: { "command": "SetLocalStatePrefs", "path": path,
//                      "value": value }
void TestingAutomationProvider::SetLocalStatePrefs(
    DictionaryValue* args,
    IPC::Message* reply_message) {
  std::string path;
  Value* val = NULL;
  AutomationJSONReply reply(this, reply_message);
  if (args->GetString("path", &path) && args->Get("value", &val)) {
    PrefService* pref_service = g_browser_process->local_state();
    const PrefService::Preference* pref =
        pref_service->FindPreference(path.c_str());
    if (!pref) {  // Not a registered pref.
      reply.SendError("pref not registered.");
      return;
    } else if (pref->IsManaged()) {  // Do not attempt to change a managed pref.
      reply.SendError("pref is managed. cannot be changed.");
      return;
    } else {  // Set the pref.
      pref_service->Set(path.c_str(), *val);
    }
  } else {
    reply.SendError("no pref path or value given.");
    return;
  }

  reply.SendSuccess(NULL);
}

// Sample json input: { "command": "GetPrefsInfo", "windex": 0 }
// Refer chrome/test/pyautolib/prefs_info.py for sample json output.
void TestingAutomationProvider::GetPrefsInfo(DictionaryValue* args,
                                             IPC::Message* reply_message) {
  AutomationJSONReply reply(this, reply_message);
  Browser* browser;
  std::string error_msg;
  if (!GetBrowserFromJSONArgs(args, &browser, &error_msg)) {
    reply.SendError(error_msg);
    return;
  }
  scoped_ptr<DictionaryValue> items(
      browser->profile()->GetPrefs()->GetPreferenceValues());

  scoped_ptr<DictionaryValue> return_value(new DictionaryValue);
  return_value->Set("prefs", items.release());  // return_value owns items.
  reply.SendSuccess(return_value.get());
}

// Sample json input:
// { "command": "SetPrefs",
//   "windex": 0,
//   "path": path,
//   "value": value }
void TestingAutomationProvider::SetPrefs(DictionaryValue* args,
                                         IPC::Message* reply_message) {
  AutomationJSONReply reply(this, reply_message);
  Browser* browser;
  std::string error_msg;
  if (!GetBrowserFromJSONArgs(args, &browser, &error_msg)) {
    reply.SendError(error_msg);
    return;
  }
  std::string path;
  Value* val = NULL;
  if (args->GetString("path", &path) && args->Get("value", &val)) {
    PrefService* pref_service = browser->profile()->GetPrefs();
    const PrefService::Preference* pref =
        pref_service->FindPreference(path.c_str());
    if (!pref) {  // Not a registered pref.
      reply.SendError("pref not registered.");
      return;
    } else if (pref->IsManaged()) {  // Do not attempt to change a managed pref.
      reply.SendError("pref is managed. cannot be changed.");
      return;
    } else {  // Set the pref.
      pref_service->Set(path.c_str(), *val);
    }
  } else {
    reply.SendError("no pref path or value given.");
    return;
  }

  reply.SendSuccess(NULL);
}

// Sample json input: { "command": "GetOmniboxInfo" }
// Refer chrome/test/pyautolib/omnibox_info.py for sample json output.
void TestingAutomationProvider::GetOmniboxInfo(Browser* browser,
                                               DictionaryValue* args,
                                               IPC::Message* reply_message) {
  scoped_ptr<DictionaryValue> return_value(new DictionaryValue);
  AutomationJSONReply reply(this, reply_message);

  LocationBar* loc_bar = browser->window()->GetLocationBar();
  if (!loc_bar) {
    reply.SendError("The specified browser does not have a location bar.");
    return;
  }
  const OmniboxView* omnibox_view = loc_bar->GetLocationEntry();
  const OmniboxEditModel* model = omnibox_view->model();

  // Fill up matches.
  ListValue* matches = new ListValue;
  const AutocompleteResult& result = model->result();
  for (AutocompleteResult::const_iterator i(result.begin()); i != result.end();
       ++i) {
    const AutocompleteMatch& match = *i;
    DictionaryValue* item = new DictionaryValue;  // owned by return_value
    item->SetString("type", AutocompleteMatchType::ToString(match.type));
    item->SetBoolean("starred", match.starred);
    item->SetString("destination_url", match.destination_url.spec());
    item->SetString("contents", match.contents);
    item->SetString("description", match.description);
    matches->Append(item);
  }
  return_value->Set("matches", matches);

  // Fill up other properties.
  DictionaryValue* properties = new DictionaryValue;  // owned by return_value
  properties->SetBoolean("has_focus", model->has_focus());
  properties->SetBoolean("query_in_progress",
                         !model->autocomplete_controller()->done());
  properties->SetString("keyword", model->keyword());
  properties->SetString("text", omnibox_view->GetText());
  return_value->Set("properties", properties);

  reply.SendSuccess(return_value.get());
}

// Sample json input: { "command": "SetOmniboxText",
//                      "text": "goog" }
void TestingAutomationProvider::SetOmniboxText(Browser* browser,
                                               DictionaryValue* args,
                                               IPC::Message* reply_message) {
  string16 text;
  AutomationJSONReply reply(this, reply_message);
  if (!args->GetString("text", &text)) {
    reply.SendError("text missing");
    return;
  }
  chrome::FocusLocationBar(browser);
  LocationBar* loc_bar = browser->window()->GetLocationBar();
  if (!loc_bar) {
    reply.SendError("The specified browser does not have a location bar.");
    return;
  }
  OmniboxView* omnibox_view = loc_bar->GetLocationEntry();
  omnibox_view->model()->OnSetFocus(false);
  omnibox_view->SetUserText(text);
  reply.SendSuccess(NULL);
}

// Sample json input: { "command": "OmniboxMovePopupSelection",
//                      "count": 1 }
// Negative count implies up, positive implies down. Count values will be
// capped by the size of the popup list.
void TestingAutomationProvider::OmniboxMovePopupSelection(
    Browser* browser,
    DictionaryValue* args,
    IPC::Message* reply_message) {
  int count;
  AutomationJSONReply reply(this, reply_message);
  if (!args->GetInteger("count", &count)) {
    reply.SendError("count missing");
    return;
  }
  LocationBar* loc_bar = browser->window()->GetLocationBar();
  if (!loc_bar) {
    reply.SendError("The specified browser does not have a location bar.");
    return;
  }
  loc_bar->GetLocationEntry()->model()->OnUpOrDownKeyPressed(count);
  reply.SendSuccess(NULL);
}

// Sample json input: { "command": "OmniboxAcceptInput" }
void TestingAutomationProvider::OmniboxAcceptInput(
    Browser* browser,
    DictionaryValue* args,
    IPC::Message* reply_message) {
  NavigationController& controller =
      browser->tab_strip_model()->GetActiveWebContents()->GetController();
  LocationBar* loc_bar = browser->window()->GetLocationBar();
  if (!loc_bar) {
    AutomationJSONReply(this, reply_message).SendError(
        "The specified browser does not have a location bar.");
    return;
  }
  new OmniboxAcceptNotificationObserver(&controller, this, reply_message);
  loc_bar->AcceptInput();
}

// Sample json input: { "command": "GetInitialLoadTimes" }
// Refer to InitialLoadObserver::GetTimingInformation() for sample output.
void TestingAutomationProvider::GetInitialLoadTimes(
    Browser*,
    DictionaryValue*,
    IPC::Message* reply_message) {
  scoped_ptr<DictionaryValue> return_value(
      initial_load_observer_->GetTimingInformation());

  std::string json_return;
  base::JSONWriter::Write(return_value.get(), &json_return);
  AutomationMsg_SendJSONRequest::WriteReplyParams(
      reply_message, json_return, true);
  Send(reply_message);
}

// Sample json input: { "command": "GetPluginsInfo" }
// Refer chrome/test/pyautolib/plugins_info.py for sample json output.
void TestingAutomationProvider::GetPluginsInfo(
    Browser* browser,
    DictionaryValue* args,
    IPC::Message* reply_message) {
  PluginService::GetInstance()->GetPlugins(
      base::Bind(&TestingAutomationProvider::GetPluginsInfoCallback,
          this, browser, args, reply_message));
}

void TestingAutomationProvider::GetPluginsInfoCallback(
    Browser* browser,
    DictionaryValue* args,
    IPC::Message* reply_message,
    const std::vector<content::WebPluginInfo>& plugins) {
  PluginPrefs* plugin_prefs =
      PluginPrefs::GetForProfile(browser->profile()).get();
  ListValue* items = new ListValue;
  for (std::vector<content::WebPluginInfo>::const_iterator it =
           plugins.begin();
       it != plugins.end();
       ++it) {
    DictionaryValue* item = new DictionaryValue;
    item->SetString("name", it->name);
    item->SetString("path", it->path.value());
    item->SetString("version", it->version);
    item->SetString("desc", it->desc);
    item->SetBoolean("enabled", plugin_prefs->IsPluginEnabled(*it));
    // Add info about mime types.
    ListValue* mime_types = new ListValue();
    for (std::vector<content::WebPluginMimeType>::const_iterator type_it =
             it->mime_types.begin();
         type_it != it->mime_types.end();
         ++type_it) {
      DictionaryValue* mime_type = new DictionaryValue();
      mime_type->SetString("mimeType", type_it->mime_type);
      mime_type->SetString("description", type_it->description);

      ListValue* file_extensions = new ListValue();
      for (std::vector<std::string>::const_iterator ext_it =
               type_it->file_extensions.begin();
           ext_it != type_it->file_extensions.end();
           ++ext_it) {
        file_extensions->Append(new StringValue(*ext_it));
      }
      mime_type->Set("fileExtensions", file_extensions);

      mime_types->Append(mime_type);
    }
    item->Set("mimeTypes", mime_types);
    items->Append(item);
  }
  scoped_ptr<DictionaryValue> return_value(new DictionaryValue);
  return_value->Set("plugins", items);  // return_value owns items.

  AutomationJSONReply(this, reply_message).SendSuccess(return_value.get());
}

// Sample json input:
//    { "command": "EnablePlugin",
//      "path": "/Library/Internet Plug-Ins/Flash Player.plugin" }
void TestingAutomationProvider::EnablePlugin(Browser* browser,
                                             DictionaryValue* args,
                                             IPC::Message* reply_message) {
  base::FilePath::StringType path;
  if (!args->GetString("path", &path)) {
    AutomationJSONReply(this, reply_message).SendError("path not specified.");
    return;
  }
  PluginPrefs* plugin_prefs =
      PluginPrefs::GetForProfile(browser->profile()).get();
  plugin_prefs->EnablePlugin(
      true,
      base::FilePath(path),
      base::Bind(&DidEnablePlugin,
                 AsWeakPtr(),
                 reply_message,
                 path,
                 "Could not enable plugin for path %s."));
}

// Sample json input:
//    { "command": "DisablePlugin",
//      "path": "/Library/Internet Plug-Ins/Flash Player.plugin" }
void TestingAutomationProvider::DisablePlugin(Browser* browser,
                                              DictionaryValue* args,
                                              IPC::Message* reply_message) {
  base::FilePath::StringType path;
  if (!args->GetString("path", &path)) {
    AutomationJSONReply(this, reply_message).SendError("path not specified.");
    return;
  }
  PluginPrefs* plugin_prefs =
      PluginPrefs::GetForProfile(browser->profile()).get();
  plugin_prefs->EnablePlugin(
      false,
      base::FilePath(path),
      base::Bind(&DidEnablePlugin,
                 AsWeakPtr(),
                 reply_message,
                 path,
                 "Could not disable plugin for path %s."));
}

// Sample json input:
//    { "command": "SaveTabContents",
//      "tab_index": 0,
//      "filename": <a full pathname> }
// Sample json output:
//    {}
void TestingAutomationProvider::SaveTabContents(
    Browser* browser,
    DictionaryValue* args,
    IPC::Message* reply_message) {
  int tab_index = 0;
  base::FilePath::StringType filename;
  base::FilePath::StringType parent_directory;
  WebContents* web_contents = NULL;

  if (!args->GetInteger("tab_index", &tab_index) ||
      !args->GetString("filename", &filename)) {
    AutomationJSONReply(this, reply_message)
        .SendError("tab_index or filename param missing");
    return;
  } else {
    web_contents = browser->tab_strip_model()->GetWebContentsAt(tab_index);
    if (!web_contents) {
      AutomationJSONReply(this, reply_message).SendError("no tab at tab_index");
      return;
    }
  }
  // We're doing a SAVE_AS_ONLY_HTML so the the directory path isn't
  // used.  Nevertheless, SavePackage requires it be valid.  Sigh.
  parent_directory = base::FilePath(filename).DirName().value();
  if (!web_contents->SavePage(
          base::FilePath(filename),
          base::FilePath(parent_directory),
          content::SAVE_PAGE_TYPE_AS_ONLY_HTML)) {
    AutomationJSONReply(this, reply_message).SendError(
        "Could not initiate SavePage");
    return;
  }
  // The observer will delete itself when done.
  new SavePackageNotificationObserver(
      BrowserContext::GetDownloadManager(browser->profile()),
      this, reply_message);
}

namespace {

// Translates a dictionary password to a PasswordForm struct.
autofill::PasswordForm GetPasswordFormFromDict(
    const DictionaryValue& password_dict) {

  // If the time is specified, change time to the specified time.
  base::Time time = base::Time::Now();
  int it;
  double dt;
  if (password_dict.GetInteger("time", &it))
    time = base::Time::FromTimeT(it);
  else if (password_dict.GetDouble("time", &dt))
    time = base::Time::FromDoubleT(dt);

  std::string signon_realm;
  string16 username_value;
  string16 password_value;
  string16 origin_url_text;
  string16 username_element;
  string16 password_element;
  string16 submit_element;
  string16 action_target_text;
  bool blacklist;
  string16 old_password_element;
  string16 old_password_value;

  // We don't care if any of these fail - they are either optional or checked
  // before this function is called.
  password_dict.GetString("signon_realm", &signon_realm);
  password_dict.GetString("username_value", &username_value);
  password_dict.GetString("password_value", &password_value);
  password_dict.GetString("origin_url", &origin_url_text);
  password_dict.GetString("username_element", &username_element);
  password_dict.GetString("password_element", &password_element);
  password_dict.GetString("submit_element", &submit_element);
  password_dict.GetString("action_target", &action_target_text);
  if (!password_dict.GetBoolean("blacklist", &blacklist))
    blacklist = false;

  GURL origin_gurl(origin_url_text);
  GURL action_target(action_target_text);

  autofill::PasswordForm password_form;
  password_form.signon_realm = signon_realm;
  password_form.username_value = username_value;
  password_form.password_value = password_value;
  password_form.origin = origin_gurl;
  password_form.username_element = username_element;
  password_form.password_element = password_element;
  password_form.submit_element = submit_element;
  password_form.action = action_target;
  password_form.blacklisted_by_user = blacklist;
  password_form.date_created = time;

  return password_form;
}

}  // namespace

// See AddSavedPassword() in chrome/test/functional/pyauto.py for sample json
// input.
// Sample json output: { "password_added": true }
void TestingAutomationProvider::AddSavedPassword(
    Browser* browser,
    DictionaryValue* args,
    IPC::Message* reply_message) {
  DictionaryValue* password_dict = NULL;
  if (!args->GetDictionary("password", &password_dict)) {
    AutomationJSONReply(this, reply_message).SendError(
        "Must specify a password dictionary.");
    return;
  }

  // The "signon realm" is effectively the primary key and must be included.
  // Check here before calling GetPasswordFormFromDict.
  if (!password_dict->HasKey("signon_realm")) {
    AutomationJSONReply(this, reply_message).SendError(
        "Password must include a value for 'signon_realm.'");
    return;
  }

  autofill::PasswordForm new_password =
      GetPasswordFormFromDict(*password_dict);

  // Use IMPLICIT_ACCESS since new passwords aren't added in incognito mode.
  PasswordStore* password_store = PasswordStoreFactory::GetForProfile(
      browser->profile(), Profile::IMPLICIT_ACCESS).get();

  // The password store does not exist for an incognito window.
  if (password_store == NULL) {
    scoped_ptr<DictionaryValue> return_value(new DictionaryValue);
    return_value->SetBoolean("password_added", false);
    AutomationJSONReply(this, reply_message).SendSuccess(return_value.get());
    return;
  }

  // This observer will delete itself.
  PasswordStoreLoginsChangedObserver* observer =
      new PasswordStoreLoginsChangedObserver(this, reply_message,
                                             PasswordStoreChange::ADD,
                                             "password_added");
  observer->Init();
  password_store->AddLogin(new_password);
}

// See RemoveSavedPassword() in chrome/test/functional/pyauto.py for sample
// json input.
// Sample json output: {}
void TestingAutomationProvider::RemoveSavedPassword(
    Browser* browser,
    DictionaryValue* args,
    IPC::Message* reply_message) {
  DictionaryValue* password_dict = NULL;

  if (!args->GetDictionary("password", &password_dict)) {
    AutomationJSONReply(this, reply_message).SendError(
        "Must specify a password dictionary.");
    return;
  }

  // The "signon realm" is effectively the primary key and must be included.
  // Check here before calling GetPasswordFormFromDict.
  if (!password_dict->HasKey("signon_realm")) {
    AutomationJSONReply(this, reply_message).SendError(
        "Password must include a value for 'signon_realm.'");
    return;
  }
  autofill::PasswordForm to_remove =
      GetPasswordFormFromDict(*password_dict);

  // Use EXPLICIT_ACCESS since passwords can be removed in incognito mode.
  PasswordStore* password_store = PasswordStoreFactory::GetForProfile(
      browser->profile(), Profile::EXPLICIT_ACCESS).get();
  if (password_store == NULL) {
    AutomationJSONReply(this, reply_message).SendError(
        "Unable to get password store.");
    return;
  }

  // This observer will delete itself.
  PasswordStoreLoginsChangedObserver* observer =
      new PasswordStoreLoginsChangedObserver(
          this, reply_message, PasswordStoreChange::REMOVE, std::string());
  observer->Init();

  password_store->RemoveLogin(to_remove);
}

// Sample json input: { "command": "GetSavedPasswords" }
// Refer to GetSavedPasswords() in chrome/test/pyautolib/pyauto.py for sample
// json output.
void TestingAutomationProvider::GetSavedPasswords(
    Browser* browser,
    DictionaryValue* args,
    IPC::Message* reply_message) {
  // Use EXPLICIT_ACCESS since saved passwords can be retrieved in
  // incognito mode.
  PasswordStore* password_store = PasswordStoreFactory::GetForProfile(
      browser->profile(), Profile::EXPLICIT_ACCESS).get();

  if (password_store == NULL) {
    AutomationJSONReply reply(this, reply_message);
    reply.SendError("Unable to get password store.");
    return;
  }
  password_store->GetAutofillableLogins(
      new AutomationProviderGetPasswordsObserver(this, reply_message));
  // Observer deletes itself after sending the result.
}

namespace {

// Get the WebContents from a dictionary of arguments.
WebContents* GetWebContentsFromDict(const Browser* browser,
                                    const DictionaryValue* args,
                                    std::string* error_message) {
  int tab_index;
  if (!args->GetInteger("tab_index", &tab_index)) {
    *error_message = "Must include tab_index.";
    return NULL;
  }

  WebContents* web_contents =
      browser->tab_strip_model()->GetWebContentsAt(tab_index);
  if (!web_contents) {
    *error_message = base::StringPrintf("No tab at index %d.", tab_index);
    return NULL;
  }
  return web_contents;
}

}  // namespace

void TestingAutomationProvider::FindInPage(
    Browser* browser,
    DictionaryValue* args,
    IPC::Message* reply_message) {
  std::string error_message;
  WebContents* web_contents =
      GetWebContentsFromDict(browser, args, &error_message);
  if (!web_contents) {
    AutomationJSONReply(this, reply_message).SendError(error_message);
    return;
  }
  string16 search_string;
  bool forward;
  bool match_case;
  bool find_next;
  if (!args->GetString("search_string", &search_string)) {
    AutomationJSONReply(this, reply_message).
        SendError("Must include search_string string.");
    return;
  }
  if (!args->GetBoolean("forward", &forward)) {
    AutomationJSONReply(this, reply_message).
        SendError("Must include forward boolean.");
    return;
  }
  if (!args->GetBoolean("match_case", &match_case)) {
    AutomationJSONReply(this, reply_message).
        SendError("Must include match_case boolean.");
    return;
  }
  if (!args->GetBoolean("find_next", &find_next)) {
    AutomationJSONReply(this, reply_message).
        SendError("Must include find_next boolean.");
    return;
  }
  SendFindRequest(web_contents,
                  true,
                  search_string,
                  forward,
                  match_case,
                  find_next,
                  reply_message);
}

void TestingAutomationProvider::OpenFindInPage(
    DictionaryValue* args,
    IPC::Message* reply_message) {
  AutomationJSONReply reply(this, reply_message);
  Browser* browser;
  std::string error_msg;
  if (!GetBrowserFromJSONArgs(args, &browser, &error_msg)) {
    reply.SendError(error_msg);
    return;
  }
  chrome::FindInPage(browser, false, false);
  reply.SendSuccess(NULL);
}

void TestingAutomationProvider::IsFindInPageVisible(
    DictionaryValue* args,
    IPC::Message* reply_message) {
  AutomationJSONReply reply(this, reply_message);
  bool visible;
  Browser* browser;
  std::string error_msg;
  if (!GetBrowserFromJSONArgs(args, &browser, &error_msg)) {
    reply.SendError(error_msg);
    return;
  }
  FindBarTesting* find_bar =
      browser->GetFindBarController()->find_bar()->GetFindBarTesting();
  find_bar->GetFindBarWindowInfo(NULL, &visible);
  DictionaryValue dict;
  dict.SetBoolean("is_visible", visible);
  reply.SendSuccess(&dict);
}

void TestingAutomationProvider::InstallExtension(
    DictionaryValue* args, IPC::Message* reply_message) {
  base::FilePath::StringType path_string;
  bool with_ui;
  bool from_webstore = false;
  Browser* browser;
  content::WebContents* tab;
  std::string error_msg;
  if (!GetBrowserAndTabFromJSONArgs(args, &browser, &tab, &error_msg)) {
    AutomationJSONReply(this, reply_message).SendError(error_msg);
    return;
  }
  if (!args->GetString("path", &path_string)) {
    AutomationJSONReply(this, reply_message).SendError(
        "Missing or invalid 'path'");
    return;
  }
  if (!args->GetBoolean("with_ui", &with_ui)) {
    AutomationJSONReply(this, reply_message).SendError(
        "Missing or invalid 'with_ui'");
    return;
  }
  args->GetBoolean("from_webstore", &from_webstore);

  ExtensionService* service = extensions::ExtensionSystem::Get(
      browser->profile())->extension_service();
  ExtensionProcessManager* manager =
      extensions::ExtensionSystem::Get(browser->profile())->process_manager();
  if (service && manager) {
    // The observer will delete itself when done.
    new ExtensionReadyNotificationObserver(
        manager,
        service,
        this,
        reply_message);

    base::FilePath extension_path(path_string);
    // If the given path has a 'crx' extension, assume it is a packed extension
    // and install it. Otherwise load it as an unpacked extension.
    if (extension_path.MatchesExtension(FILE_PATH_LITERAL(".crx"))) {
      scoped_ptr<ExtensionInstallPrompt> client(
          with_ui ? new ExtensionInstallPrompt(tab) : NULL);
      scoped_refptr<extensions::CrxInstaller> installer(
          extensions::CrxInstaller::Create(service, client.Pass()));
      if (!with_ui)
        installer->set_allow_silent_install(true);
      installer->set_install_cause(extension_misc::INSTALL_CAUSE_AUTOMATION);
      if (from_webstore)
        installer->set_creation_flags(Extension::FROM_WEBSTORE);
      installer->InstallCrx(extension_path);
    } else {
      scoped_refptr<extensions::UnpackedInstaller> installer(
          extensions::UnpackedInstaller::Create(service));
      installer->set_prompt_for_plugins(with_ui);
      installer->Load(extension_path);
    }
  } else {
    AutomationJSONReply(this, reply_message).SendError(
        "Extensions service/process manager is not available");
  }
}

namespace {

ListValue* GetHostPermissions(const Extension* ext, bool effective_perm) {
  extensions::URLPatternSet pattern_set;
  if (effective_perm) {
    pattern_set =
        extensions::PermissionsData::GetEffectiveHostPermissions(ext);
  } else {
    pattern_set = ext->GetActivePermissions()->explicit_hosts();
  }

  ListValue* permissions = new ListValue;
  for (extensions::URLPatternSet::const_iterator perm = pattern_set.begin();
       perm != pattern_set.end(); ++perm) {
    permissions->Append(new StringValue(perm->GetAsString()));
  }

  return permissions;
}

ListValue* GetAPIPermissions(const Extension* ext) {
  ListValue* permissions = new ListValue;
  std::set<std::string> perm_list =
      ext->GetActivePermissions()->GetAPIsAsStrings();
  for (std::set<std::string>::const_iterator perm = perm_list.begin();
       perm != perm_list.end(); ++perm) {
    permissions->Append(new StringValue(perm->c_str()));
  }
  return permissions;
}

}  // namespace

// Sample json input: { "command": "GetExtensionsInfo" }
// See GetExtensionsInfo() in chrome/test/pyautolib/pyauto.py for sample json
// output.
void TestingAutomationProvider::GetExtensionsInfo(DictionaryValue* args,
                                                  IPC::Message* reply_message) {
  AutomationJSONReply reply(this, reply_message);
  Browser* browser;
  std::string error_msg;
  if (!GetBrowserFromJSONArgs(args, &browser, &error_msg)) {
    reply.SendError(error_msg);
    return;
  }
  ExtensionService* service = extensions::ExtensionSystem::Get(
      browser->profile())->extension_service();
  if (!service) {
    reply.SendError("No extensions service.");
    return;
  }
  scoped_ptr<DictionaryValue> return_value(new DictionaryValue);
  ListValue* extensions_values = new ListValue;
  const ExtensionSet* extensions = service->extensions();
  const ExtensionSet* disabled_extensions = service->disabled_extensions();
  ExtensionList all;
  all.insert(all.end(),
             extensions->begin(),
             extensions->end());
  all.insert(all.end(),
             disabled_extensions->begin(),
             disabled_extensions->end());
  ExtensionActionManager* extension_action_manager =
      ExtensionActionManager::Get(browser->profile());
  for (ExtensionList::const_iterator it = all.begin();
       it != all.end(); ++it) {
    const Extension* extension = it->get();
    std::string id = extension->id();
    DictionaryValue* extension_value = new DictionaryValue;
    extension_value->SetString("id", id);
    extension_value->SetString("version", extension->VersionString());
    extension_value->SetString("name", extension->name());
    extension_value->SetString("public_key", extension->public_key());
    extension_value->SetString("description", extension->description());
    extension_value->SetString(
        "background_url",
        extensions::BackgroundInfo::GetBackgroundURL(extension).spec());
    extension_value->SetString("options_url",
        extensions::ManifestURL::GetOptionsPage(extension).spec());
    extension_value->Set("host_permissions",
                         GetHostPermissions(extension, false));
    extension_value->Set("effective_host_permissions",
                         GetHostPermissions(extension, true));
    extension_value->Set("api_permissions", GetAPIPermissions(extension));
    Manifest::Location location = extension->location();
    extension_value->SetBoolean("is_component",
                                location == Manifest::COMPONENT);
    extension_value->SetBoolean("is_internal",
                                location == Manifest::INTERNAL);
    extension_value->SetBoolean("is_user_installed",
        location == Manifest::INTERNAL ||
        Manifest::IsUnpackedLocation(location));
    extension_value->SetBoolean("is_enabled", service->IsExtensionEnabled(id));
    extension_value->SetBoolean("allowed_in_incognito",
        extension_util::IsIncognitoEnabled(id, service));
    extension_value->SetBoolean(
        "has_page_action",
        extension_action_manager->GetPageAction(*extension) != NULL);
    extensions_values->Append(extension_value);
  }
  return_value->Set("extensions", extensions_values);
  reply.SendSuccess(return_value.get());
}

// See UninstallExtensionById() in chrome/test/pyautolib/pyauto.py for sample
// json input.
// Sample json output: {}
void TestingAutomationProvider::UninstallExtensionById(
    DictionaryValue* args,
    IPC::Message* reply_message) {
  const Extension* extension;
  std::string error;
  Browser* browser;
  if (!GetBrowserFromJSONArgs(args, &browser, &error)) {
    AutomationJSONReply(this, reply_message).SendError(error);
    return;
  }
  if (!GetExtensionFromJSONArgs(
          args, "id", browser->profile(), &extension, &error)) {
    AutomationJSONReply(this, reply_message).SendError(error);
    return;
  }
  ExtensionService* service = extensions::ExtensionSystem::Get(
      browser->profile())->extension_service();
  if (!service) {
    AutomationJSONReply(this, reply_message).SendError(
        "No extensions service.");
    return;
  }

  // Wait for a notification indicating that the extension with the given ID
  // has been uninstalled.  This observer will delete itself.
  new ExtensionUninstallObserver(this, reply_message, extension->id());
  service->UninstallExtension(extension->id(), false, NULL);
}

// See SetExtensionStateById() in chrome/test/pyautolib/pyauto.py
// for sample json input.
void TestingAutomationProvider::SetExtensionStateById(
    DictionaryValue* args,
    IPC::Message* reply_message) {
  const Extension* extension;
  std::string error;
  Browser* browser;
  if (!GetBrowserFromJSONArgs(args, &browser, &error)) {
    AutomationJSONReply(this, reply_message).SendError(error);
    return;
  }
  if (!GetExtensionFromJSONArgs(
          args, "id", browser->profile(), &extension, &error)) {
    AutomationJSONReply(this, reply_message).SendError(error);
    return;
  }

  bool enable;
  if (!args->GetBoolean("enable", &enable)) {
    AutomationJSONReply(this, reply_message)
        .SendError("Missing or invalid key: enable");
    return;
  }

  bool allow_in_incognito;
  if (!args->GetBoolean("allow_in_incognito", &allow_in_incognito)) {
    AutomationJSONReply(this, reply_message)
        .SendError("Missing or invalid key: allow_in_incognito");
    return;
  }

  if (allow_in_incognito && !enable) {
    AutomationJSONReply(this, reply_message)
        .SendError("Invalid state: Disabled extension "
                    "cannot be allowed in incognito mode.");
    return;
  }

  ExtensionService* service = extensions::ExtensionSystem::Get(
      browser->profile())->extension_service();
  ExtensionProcessManager* manager =
      extensions::ExtensionSystem::Get(browser->profile())->process_manager();
  if (!service) {
    AutomationJSONReply(this, reply_message)
        .SendError("No extensions service or process manager.");
    return;
  }

  if (enable) {
    if (!service->IsExtensionEnabled(extension->id())) {
      new ExtensionReadyNotificationObserver(
          manager,
          service,
          this,
          reply_message);
      service->EnableExtension(extension->id());
    } else {
      AutomationJSONReply(this, reply_message).SendSuccess(NULL);
    }
  } else {
    service->DisableExtension(extension->id(),
                              Extension::DISABLE_USER_ACTION);
    AutomationJSONReply(this, reply_message).SendSuccess(NULL);
  }

  extension_util::SetIsIncognitoEnabled(
      extension->id(), service, allow_in_incognito);
}

// See TriggerPageActionById() in chrome/test/pyautolib/pyauto.py
// for sample json input.
void TestingAutomationProvider::TriggerPageActionById(
    DictionaryValue* args,
    IPC::Message* reply_message) {
  std::string error;
  Browser* browser;
  WebContents* tab;
  if (!GetBrowserAndTabFromJSONArgs(args, &browser, &tab, &error)) {
    AutomationJSONReply(this, reply_message).SendError(error);
    return;
  }
  const Extension* extension;
  if (!GetEnabledExtensionFromJSONArgs(
          args, "id", browser->profile(), &extension, &error)) {
    AutomationJSONReply(this, reply_message).SendError(error);
    return;
  }
  ExtensionAction* page_action =
      ExtensionActionManager::Get(browser->profile())->
      GetPageAction(*extension);
  if (!page_action) {
    AutomationJSONReply(this, reply_message).SendError(
        "Extension doesn't have any page action.");
    return;
  }
  EnsureTabSelected(browser, tab);

  bool pressed = false;
  LocationBarTesting* loc_bar =
      browser->window()->GetLocationBar()->GetLocationBarForTesting();
  size_t page_action_visible_count =
      static_cast<size_t>(loc_bar->PageActionVisibleCount());
  for (size_t i = 0; i < page_action_visible_count; ++i) {
    if (loc_bar->GetVisiblePageAction(i) == page_action) {
      loc_bar->TestPageActionPressed(i);
      pressed = true;
      break;
    }
  }
  if (!pressed) {
    AutomationJSONReply(this, reply_message).SendError(
        "Extension's page action is not visible.");
    return;
  }

  if (page_action->HasPopup(ExtensionTabUtil::GetTabId(tab))) {
    // This observer will delete itself.
    new ExtensionPopupObserver(
        this, reply_message, extension->id());
  } else {
    AutomationJSONReply(this, reply_message).SendSuccess(NULL);
  }
}

// See TriggerBrowserActionById() in chrome/test/pyautolib/pyauto.py
// for sample json input.
void TestingAutomationProvider::TriggerBrowserActionById(
    DictionaryValue* args,
    IPC::Message* reply_message) {
  std::string error;
  Browser* browser;
  WebContents* tab;
  if (!GetBrowserAndTabFromJSONArgs(args, &browser, &tab, &error)) {
    AutomationJSONReply(this, reply_message).SendError(error);
    return;
  }
  const Extension* extension;
  if (!GetEnabledExtensionFromJSONArgs(
          args, "id", browser->profile(), &extension, &error)) {
    AutomationJSONReply(this, reply_message).SendError(error);
    return;
  }
  ExtensionAction* action = ExtensionActionManager::Get(browser->profile())->
      GetBrowserAction(*extension);
  if (!action) {
    AutomationJSONReply(this, reply_message).SendError(
        "Extension doesn't have any browser action.");
    return;
  }
  EnsureTabSelected(browser, tab);

  BrowserActionTestUtil browser_actions(browser);
  int num_browser_actions = browser_actions.NumberOfBrowserActions();
  int action_index = -1;
#if defined(TOOLKIT_VIEWS)
  for (int i = 0; i < num_browser_actions; ++i) {
    if (extension->id() == browser_actions.GetExtensionId(i)) {
      action_index = i;
      break;
    }
  }
#else
  // TODO(kkania): Implement the platform-specific GetExtensionId() in
  // BrowserActionTestUtil.
  if (num_browser_actions != 1) {
    AutomationJSONReply(this, reply_message).SendError(base::StringPrintf(
        "Found %d browser actions. Only one browser action must be active.",
        num_browser_actions));
    return;
  }
  // This extension has a browser action, and there's only one action, so this
  // must be the first one.
  action_index = 0;
#endif
  if (action_index == -1) {
    AutomationJSONReply(this, reply_message).SendError(
        "Extension's browser action is not visible.");
    return;
  }
  browser_actions.Press(action_index);

  if (action->HasPopup(ExtensionTabUtil::GetTabId(tab))) {
    // This observer will delete itself.
    new ExtensionPopupObserver(
        this, reply_message, extension->id());
  } else {
    AutomationJSONReply(this, reply_message).SendSuccess(NULL);
  }
}

void TestingAutomationProvider::ActionOnSSLBlockingPage(
    DictionaryValue* args,
    IPC::Message* reply_message) {
  WebContents* web_contents;
  bool proceed;
  std::string error;
  if (!GetTabFromJSONArgs(args, &web_contents, &error)) {
    AutomationJSONReply(this, reply_message).SendError(error);
    return;
  }
  if (!args->GetBoolean("proceed", &proceed)) {
    AutomationJSONReply(this, reply_message).SendError(
        "'proceed' is missing or invalid");
    return;
  }
  NavigationController& controller = web_contents->GetController();
  NavigationEntry* entry = controller.GetActiveEntry();
  if (entry->GetPageType() == content::PAGE_TYPE_INTERSTITIAL) {
    InterstitialPage* ssl_blocking_page =
        InterstitialPage::GetInterstitialPage(web_contents);
    if (ssl_blocking_page) {
      if (proceed) {
        new NavigationNotificationObserver(&controller, this, reply_message, 1,
                                           false, true);
        ssl_blocking_page->Proceed();
        return;
      }
      ssl_blocking_page->DontProceed();
      AutomationJSONReply(this, reply_message).SendSuccess(NULL);
      return;
    }
  }
  AutomationJSONReply(this, reply_message).SendError(error);
}

void TestingAutomationProvider::GetSecurityState(DictionaryValue* args,
                                                 IPC::Message* reply_message) {
  AutomationJSONReply reply(this, reply_message);
  WebContents* web_contents;
  std::string error;
  if (!GetTabFromJSONArgs(args, &web_contents, &error)) {
    reply.SendError(error);
    return;
  }
  NavigationEntry* entry = web_contents->GetController().GetActiveEntry();
  DictionaryValue dict;
  dict.SetInteger("security_style",
                  static_cast<int>(entry->GetSSL().security_style));
  dict.SetInteger("ssl_cert_status",
                  static_cast<int>(entry->GetSSL().cert_status));
  dict.SetInteger("insecure_content_status",
                  static_cast<int>(entry->GetSSL().content_status));
  reply.SendSuccess(&dict);
}

// Sample json input: { "command": "UpdateExtensionsNow" }
// Sample json output: {}
void TestingAutomationProvider::UpdateExtensionsNow(
    DictionaryValue* args,
    IPC::Message* reply_message) {
  std::string error;
  Browser* browser;
  if (!GetBrowserFromJSONArgs(args, &browser, &error)) {
    AutomationJSONReply(this, reply_message).SendError(error);
    return;
  }
  ExtensionService* service = extensions::ExtensionSystem::Get(
      browser->profile())->extension_service();
  if (!service) {
    AutomationJSONReply(this, reply_message).SendError(
        "No extensions service.");
    return;
  }

  extensions::ExtensionUpdater* updater = service->updater();
  if (!updater) {
    AutomationJSONReply(this, reply_message).SendError(
        "No updater for extensions service.");
    return;
  }

  ExtensionProcessManager* manager =
      extensions::ExtensionSystem::Get(browser->profile())->process_manager();
  if (!manager) {
    AutomationJSONReply(this, reply_message).SendError(
        "No extension process manager.");
    return;
  }

  // Create a new observer that waits until the extensions have been fully
  // updated (we should not send the reply until after all extensions have
  // been updated).  This observer will delete itself.
  ExtensionsUpdatedObserver* observer = new ExtensionsUpdatedObserver(
      manager, this, reply_message);
  extensions::ExtensionUpdater::CheckParams params;
  params.install_immediately = true;
  params.callback = base::Bind(&ExtensionsUpdatedObserver::UpdateCheckFinished,
                               base::Unretained(observer));
  updater->CheckNow(params);
}

namespace {

void SendSuccessIfAlive(
    base::WeakPtr<AutomationProvider> provider,
    IPC::Message* reply_message) {
  if (provider.get())
    AutomationJSONReply(provider.get(), reply_message).SendSuccess(NULL);
}

}  // namespace

void TestingAutomationProvider::OverrideGeoposition(
    base::DictionaryValue* args,
    IPC::Message* reply_message) {
  double latitude, longitude, altitude;
  if (!args->GetDouble("latitude", &latitude) ||
      !args->GetDouble("longitude", &longitude) ||
      !args->GetDouble("altitude", &altitude)) {
    AutomationJSONReply(this, reply_message).SendError(
        "Missing or invalid geolocation parameters");
    return;
  }
  content::Geoposition position;
  position.latitude = latitude;
  position.longitude = longitude;
  position.altitude = altitude;
  position.accuracy = 0.;
  position.timestamp = base::Time::Now();

  content::GeolocationProvider::OverrideLocationForTesting(
      position,
      base::Bind(&SendSuccessIfAlive, AsWeakPtr(), reply_message));
}

// Refer to GetAllNotifications() in chrome/test/pyautolib/pyauto.py for
// sample json input/output.
void TestingAutomationProvider::GetAllNotifications(
    Browser* browser,
    DictionaryValue* args,
    IPC::Message* reply_message) {
  new GetAllNotificationsObserver(this, reply_message);
}

// Refer to CloseNotification() in chrome/test/pyautolib/pyauto.py for
// sample json input.
// Returns empty json message.
void TestingAutomationProvider::CloseNotification(
    Browser* browser,
    DictionaryValue* args,
    IPC::Message* reply_message) {
  int index;
  if (!args->GetInteger("index", &index)) {
    AutomationJSONReply(this, reply_message)
        .SendError("'index' missing or invalid.");
    return;
  }
  BalloonNotificationUIManager* manager =
      BalloonNotificationUIManager::GetInstanceForTesting();
  BalloonCollection* collection = manager->balloon_collection();
  const BalloonCollection::Balloons& balloons = collection->GetActiveBalloons();
  int balloon_count = static_cast<int>(balloons.size());
  if (index < 0 || index >= balloon_count) {
    AutomationJSONReply(this, reply_message)
        .SendError(base::StringPrintf("No notification at index %d", index));
    return;
  }
  std::vector<const Notification*> queued_notes;
  manager->GetQueuedNotificationsForTesting(&queued_notes);
  if (queued_notes.empty()) {
    new OnNotificationBalloonCountObserver(
        this, reply_message, balloon_count - 1);
  } else {
    new NewNotificationBalloonObserver(this, reply_message);
  }
  manager->CancelById(balloons[index]->notification().notification_id());
}

// Refer to WaitForNotificationCount() in chrome/test/pyautolib/pyauto.py for
// sample json input.
// Returns empty json message.
void TestingAutomationProvider::WaitForNotificationCount(
    Browser* browser,
    DictionaryValue* args,
    IPC::Message* reply_message) {
  int count;
  if (!args->GetInteger("count", &count)) {
    AutomationJSONReply(this, reply_message)
        .SendError("'count' missing or invalid.");
    return;
  }
  // This will delete itself when finished.
  new OnNotificationBalloonCountObserver(this, reply_message, count);
}

// Sample JSON input: { "command": "GetNTPInfo" }
// For output, refer to chrome/test/pyautolib/ntp_model.py.
void TestingAutomationProvider::GetNTPInfo(
    Browser* browser,
    DictionaryValue* args,
    IPC::Message* reply_message) {
  // This observer will delete itself.
  new NTPInfoObserver(this, reply_message);
}

void TestingAutomationProvider::RemoveNTPMostVisitedThumbnail(
    Browser* browser,
    DictionaryValue* args,
    IPC::Message* reply_message) {
  AutomationJSONReply reply(this, reply_message);
  std::string url;
  if (!args->GetString("url", &url)) {
    reply.SendError("Missing or invalid 'url' key.");
    return;
  }
  history::TopSites* top_sites = browser->profile()->GetTopSites();
  if (!top_sites) {
    reply.SendError("TopSites service is not initialized.");
    return;
  }
  top_sites->AddBlacklistedURL(GURL(url));
  reply.SendSuccess(NULL);
}

void TestingAutomationProvider::RestoreAllNTPMostVisitedThumbnails(
    Browser* browser,
    DictionaryValue* args,
    IPC::Message* reply_message) {
  AutomationJSONReply reply(this, reply_message);
  history::TopSites* top_sites = browser->profile()->GetTopSites();
  if (!top_sites) {
    reply.SendError("TopSites service is not initialized.");
    return;
  }
  top_sites->ClearBlacklistedURLs();
  reply.SendSuccess(NULL);
}

void TestingAutomationProvider::KillRendererProcess(
    Browser* browser,
    DictionaryValue* args,
    IPC::Message* reply_message) {
  int pid;
  uint32 kAccessFlags = base::kProcessAccessTerminate |
                        base::kProcessAccessWaitForTermination |
                        base::kProcessAccessQueryInformation;

  if (!args->GetInteger("pid", &pid)) {
    AutomationJSONReply(this, reply_message)
        .SendError("'pid' key missing or invalid.");
    return;
  }
  base::ProcessHandle process;
  if (!base::OpenProcessHandleWithAccess(static_cast<base::ProcessId>(pid),
                                         kAccessFlags,
                                         &process)) {
    AutomationJSONReply(this, reply_message).SendError(base::StringPrintf(
        "Failed to open process handle for pid %d", pid));
    return;
  }
  new RendererProcessClosedObserver(this, reply_message);
  base::KillProcess(process, 0, false);
  base::CloseProcessHandle(process);
}

bool TestingAutomationProvider::BuildWebKeyEventFromArgs(
    DictionaryValue* args,
    std::string* error,
    NativeWebKeyboardEvent* event) {
  int type, modifiers;
  bool is_system_key;
  string16 unmodified_text, text;
  std::string key_identifier;
  if (!args->GetInteger("type", &type)) {
    *error = "'type' missing or invalid.";
    return false;
  }
  if (!args->GetBoolean("isSystemKey", &is_system_key)) {
    *error = "'isSystemKey' missing or invalid.";
    return false;
  }
  if (!args->GetString("unmodifiedText", &unmodified_text)) {
    *error = "'unmodifiedText' missing or invalid.";
    return false;
  }
  if (!args->GetString("text", &text)) {
    *error = "'text' missing or invalid.";
    return false;
  }
  if (!args->GetInteger("nativeKeyCode", &event->nativeKeyCode)) {
    *error = "'nativeKeyCode' missing or invalid.";
    return false;
  }
  if (!args->GetInteger("windowsKeyCode", &event->windowsKeyCode)) {
    *error = "'windowsKeyCode' missing or invalid.";
    return false;
  }
  if (!args->GetInteger("modifiers", &modifiers)) {
    *error = "'modifiers' missing or invalid.";
    return false;
  }
  if (args->GetString("keyIdentifier", &key_identifier)) {
    base::strlcpy(event->keyIdentifier,
                  key_identifier.c_str(),
                  WebKit::WebKeyboardEvent::keyIdentifierLengthCap);
  } else {
    *error = "'keyIdentifier' missing or invalid.";
    return false;
  }

  if (type == automation::kRawKeyDownType) {
    event->type = WebKit::WebInputEvent::RawKeyDown;
  } else if (type == automation::kKeyDownType) {
    event->type = WebKit::WebInputEvent::KeyDown;
  } else if (type == automation::kKeyUpType) {
    event->type = WebKit::WebInputEvent::KeyUp;
  } else if (type == automation::kCharType) {
    event->type = WebKit::WebInputEvent::Char;
  } else {
    *error = "'type' refers to an unrecognized keyboard event type";
    return false;
  }

  string16 unmodified_text_truncated = unmodified_text.substr(
      0, WebKit::WebKeyboardEvent::textLengthCap - 1);
  memcpy(event->unmodifiedText,
         unmodified_text_truncated.c_str(),
         unmodified_text_truncated.length() + 1);
  string16 text_truncated = text.substr(
      0, WebKit::WebKeyboardEvent::textLengthCap - 1);
  memcpy(event->text, text_truncated.c_str(), text_truncated.length() + 1);

  event->modifiers = 0;
  if (modifiers & automation::kShiftKeyMask)
    event->modifiers |= WebKit::WebInputEvent::ShiftKey;
  if (modifiers & automation::kControlKeyMask)
    event->modifiers |= WebKit::WebInputEvent::ControlKey;
  if (modifiers & automation::kAltKeyMask)
    event->modifiers |= WebKit::WebInputEvent::AltKey;
  if (modifiers & automation::kMetaKeyMask)
    event->modifiers |= WebKit::WebInputEvent::MetaKey;

  event->isSystemKey = is_system_key;
  event->timeStampSeconds = base::Time::Now().ToDoubleT();
  event->skip_in_browser = true;
  return true;
}

void TestingAutomationProvider::SendWebkitKeyEvent(
    DictionaryValue* args,
    IPC::Message* reply_message) {
  if (SendErrorIfModalDialogActive(this, reply_message))
    return;

  NativeWebKeyboardEvent event;
  // In the event of an error, BuildWebKeyEventFromArgs handles telling what
  // went wrong and sending the reply message; if it fails, we just have to
  // stop here.
  std::string error;
  if (!BuildWebKeyEventFromArgs(args, &error, &event)) {
    AutomationJSONReply(this, reply_message).SendError(error);
    return;
  }

  RenderViewHost* view;
  if (!GetRenderViewFromJSONArgs(args, profile(), &view, &error)) {
    AutomationJSONReply(this, reply_message).SendError(error);
    return;
  }
  new InputEventAckNotificationObserver(this, reply_message, event.type, 1);
  view->ForwardKeyboardEvent(event);
}

namespace {

// Gets the active JavaScript modal dialog, or NULL if none.
JavaScriptAppModalDialog* GetActiveJavaScriptModalDialog(
    std::string* error_msg) {
  AppModalDialogQueue* dialog_queue = AppModalDialogQueue::GetInstance();
  if (!dialog_queue->HasActiveDialog() ||
      !dialog_queue->active_dialog()->IsJavaScriptModalDialog()) {
    *error_msg = "No JavaScriptModalDialog open";
    return NULL;
  }
  return static_cast<JavaScriptAppModalDialog*>(dialog_queue->active_dialog());
}

}  // namespace

void TestingAutomationProvider::GetAppModalDialogMessage(
    DictionaryValue* args, IPC::Message* reply_message) {
  AutomationJSONReply reply(this, reply_message);
  std::string error_msg;
  JavaScriptAppModalDialog* dialog = GetActiveJavaScriptModalDialog(&error_msg);
  if (!dialog) {
    reply.SendError(error_msg);
    return;
  }
  DictionaryValue result_dict;
  result_dict.SetString("message", UTF16ToUTF8(dialog->message_text()));
  reply.SendSuccess(&result_dict);
}

void TestingAutomationProvider::AcceptOrDismissAppModalDialog(
    DictionaryValue* args, IPC::Message* reply_message) {
  AutomationJSONReply reply(this, reply_message);
  bool accept;
  if (!args->GetBoolean("accept", &accept)) {
    reply.SendError("Missing or invalid 'accept'");
    return;
  }

  std::string error_msg;
  JavaScriptAppModalDialog* dialog = GetActiveJavaScriptModalDialog(&error_msg);
  if (!dialog) {
    reply.SendError(error_msg);
    return;
  }
  if (accept) {
    std::string prompt_text;
    if (args->GetString("prompt_text", &prompt_text))
      dialog->SetOverridePromptText(UTF8ToUTF16(prompt_text));
    dialog->native_dialog()->AcceptAppModalDialog();
  } else {
    dialog->native_dialog()->CancelAppModalDialog();
  }
  reply.SendSuccess(NULL);
}

// Sample JSON input: { "command": "LaunchApp",
//                      "id": "ahfgeienlihckogmohjhadlkjgocpleb" }
// Sample JSON output: {}
void TestingAutomationProvider::LaunchApp(
    Browser* browser,
    DictionaryValue* args,
    IPC::Message* reply_message) {
  std::string id;
  if (!args->GetString("id", &id)) {
    AutomationJSONReply(this, reply_message).SendError(
        "Must include string id.");
    return;
  }

  ExtensionService* service = extensions::ExtensionSystem::Get(
      browser->profile())->extension_service();
  if (!service) {
    AutomationJSONReply(this, reply_message).SendError(
        "No extensions service.");
    return;
  }

  const Extension* extension = service->GetExtensionById(
      id, false  /* do not include disabled extensions */);
  if (!extension) {
    AutomationJSONReply(this, reply_message).SendError(
        base::StringPrintf(
            "Extension with ID '%s' doesn't exist or is disabled.",
            id.c_str()));
    return;
  }

  WebContents* old_contents =
      browser->tab_strip_model()->GetActiveWebContents();
  if (!old_contents) {
    AutomationJSONReply(this, reply_message).SendError(
        "Cannot identify selected tab contents.");
    return;
  }

  AppLaunchParams launch_params(profile(), extension, CURRENT_TAB);
  // This observer will delete itself.
  new AppLaunchObserver(&old_contents->GetController(), this, reply_message,
                        launch_params.container);
  OpenApplication(launch_params);
}

// Sample JSON input: { "command": "SetAppLaunchType",
//                      "id": "ahfgeienlihckogmohjhadlkjgocpleb",
//                      "launch_type": "pinned" }
// Sample JSON output: {}
void TestingAutomationProvider::SetAppLaunchType(
    Browser* browser,
    DictionaryValue* args,
    IPC::Message* reply_message) {
  AutomationJSONReply reply(this, reply_message);

  std::string id;
  if (!args->GetString("id", &id)) {
    reply.SendError("Must include string id.");
    return;
  }

  std::string launch_type_str;
  if (!args->GetString("launch_type", &launch_type_str)) {
    reply.SendError("Must specify app launch type.");
    return;
  }

  ExtensionService* service = extensions::ExtensionSystem::Get(
      browser->profile())->extension_service();
  if (!service) {
    reply.SendError("No extensions service.");
    return;
  }

  const Extension* extension = service->GetExtensionById(
      id, true  /* include disabled extensions */);
  if (!extension) {
    reply.SendError(base::StringPrintf(
        "Extension with ID '%s' doesn't exist.", id.c_str()));
    return;
  }

  extensions::ExtensionPrefs::LaunchType launch_type;
  if (launch_type_str == "pinned") {
    launch_type = extensions::ExtensionPrefs::LAUNCH_PINNED;
  } else if (launch_type_str == "regular") {
    launch_type = extensions::ExtensionPrefs::LAUNCH_REGULAR;
  } else if (launch_type_str == "fullscreen") {
    launch_type = extensions::ExtensionPrefs::LAUNCH_FULLSCREEN;
  } else if (launch_type_str == "window") {
    launch_type = extensions::ExtensionPrefs::LAUNCH_WINDOW;
  } else {
    reply.SendError(base::StringPrintf(
        "Unexpected launch type '%s'.", launch_type_str.c_str()));
    return;
  }

  service->extension_prefs()->SetLaunchType(extension->id(), launch_type);
  reply.SendSuccess(NULL);
}

// Sample json input: { "command": "GetV8HeapStats",
//                      "tab_index": 0 }
// Refer to GetV8HeapStats() in chrome/test/pyautolib/pyauto.py for
// sample json output.
void TestingAutomationProvider::GetV8HeapStats(
    Browser* browser,
    DictionaryValue* args,
    IPC::Message* reply_message) {
  WebContents* web_contents;
  int tab_index;

  if (!args->GetInteger("tab_index", &tab_index)) {
    AutomationJSONReply(this, reply_message).SendError(
        "Missing 'tab_index' argument.");
    return;
  }

  web_contents = browser->tab_strip_model()->GetWebContentsAt(tab_index);
  if (!web_contents) {
    AutomationJSONReply(this, reply_message).SendError(base::StringPrintf(
        "Could not get WebContents at tab index %d", tab_index));
    return;
  }

  RenderViewHost* render_view = web_contents->GetRenderViewHost();

  // This observer will delete itself.
  new V8HeapStatsObserver(
      this, reply_message,
      base::GetProcId(render_view->GetProcess()->GetHandle()));
  render_view->Send(new ChromeViewMsg_GetV8HeapStats);
}

// Sample json input: { "command": "GetFPS",
//                      "tab_index": 0 }
// Refer to GetFPS() in chrome/test/pyautolib/pyauto.py for
// sample json output.
void TestingAutomationProvider::GetFPS(
    Browser* browser,
    DictionaryValue* args,
    IPC::Message* reply_message) {
  WebContents* web_contents;
  int tab_index;

  if (!args->GetInteger("tab_index", &tab_index)) {
    AutomationJSONReply(this, reply_message).SendError(
        "Missing 'tab_index' argument.");
    return;
  }

  web_contents = browser->tab_strip_model()->GetWebContentsAt(tab_index);
  if (!web_contents) {
    AutomationJSONReply(this, reply_message).SendError(base::StringPrintf(
        "Could not get WebContents at tab index %d", tab_index));
    return;
  }

  RenderViewHost* render_view = web_contents->GetRenderViewHost();
  int routing_id = render_view->GetRoutingID();

  // This observer will delete itself.
  new FPSObserver(
      this, reply_message,
      base::GetProcId(render_view->GetProcess()->GetHandle()),
      routing_id);
  render_view->Send(new ChromeViewMsg_GetFPS(routing_id));
}

void TestingAutomationProvider::IsFullscreenForBrowser(Browser* browser,
    base::DictionaryValue* args,
    IPC::Message* reply_message) {
  DictionaryValue dict;
  dict.SetBoolean("result",
                  browser->fullscreen_controller()->IsFullscreenForBrowser());
  AutomationJSONReply(this, reply_message).SendSuccess(&dict);
}

void TestingAutomationProvider::IsFullscreenForTab(Browser* browser,
    base::DictionaryValue* args,
    IPC::Message* reply_message) {
  DictionaryValue dict;
  dict.SetBoolean("result",
      browser->fullscreen_controller()->IsFullscreenForTabOrPending());
  AutomationJSONReply(this, reply_message).SendSuccess(&dict);
}

void TestingAutomationProvider::IsMouseLocked(Browser* browser,
    base::DictionaryValue* args,
    IPC::Message* reply_message) {
  DictionaryValue dict;
  dict.SetBoolean("result", browser->tab_strip_model()->GetActiveWebContents()->
      GetRenderViewHost()->GetView()->IsMouseLocked());
  AutomationJSONReply(this, reply_message).SendSuccess(&dict);
}

void TestingAutomationProvider::IsMouseLockPermissionRequested(
    Browser* browser,
    base::DictionaryValue* args,
    IPC::Message* reply_message) {
  FullscreenExitBubbleType type =
      browser->fullscreen_controller()->GetFullscreenExitBubbleType();
  bool mouse_lock = false;
  fullscreen_bubble::PermissionRequestedByType(type, NULL, &mouse_lock);
  DictionaryValue dict;
  dict.SetBoolean("result", mouse_lock);
  AutomationJSONReply(this, reply_message).SendSuccess(&dict);
}

void TestingAutomationProvider::IsFullscreenPermissionRequested(
    Browser* browser,
    base::DictionaryValue* args,
    IPC::Message* reply_message) {
  FullscreenExitBubbleType type =
      browser->fullscreen_controller()->GetFullscreenExitBubbleType();
  bool fullscreen = false;
  fullscreen_bubble::PermissionRequestedByType(type, &fullscreen, NULL);
  DictionaryValue dict;
  dict.SetBoolean("result", fullscreen);
  AutomationJSONReply(this, reply_message).SendSuccess(&dict);
}

void TestingAutomationProvider::IsFullscreenBubbleDisplayed(Browser* browser,
    base::DictionaryValue* args,
    IPC::Message* reply_message) {
  FullscreenExitBubbleType type =
      browser->fullscreen_controller()->GetFullscreenExitBubbleType();
  DictionaryValue dict;
  dict.SetBoolean("result",
                  type != FEB_TYPE_BROWSER_FULLSCREEN_EXIT_INSTRUCTION);
  AutomationJSONReply(this, reply_message).SendSuccess(&dict);
}

void TestingAutomationProvider::IsFullscreenBubbleDisplayingButtons(
    Browser* browser,
    base::DictionaryValue* args,
    IPC::Message* reply_message) {
  FullscreenExitBubbleType type =
      browser->fullscreen_controller()->GetFullscreenExitBubbleType();
  DictionaryValue dict;
  dict.SetBoolean("result", fullscreen_bubble::ShowButtonsForType(type));
  AutomationJSONReply(this, reply_message).SendSuccess(&dict);
}

void TestingAutomationProvider::AcceptCurrentFullscreenOrMouseLockRequest(
    Browser* browser,
    base::DictionaryValue* args,
    IPC::Message* reply_message) {
  browser->fullscreen_controller()->OnAcceptFullscreenPermission();
  AutomationJSONReply(this, reply_message).SendSuccess(NULL);
}

void TestingAutomationProvider::DenyCurrentFullscreenOrMouseLockRequest(
    Browser* browser,
    base::DictionaryValue* args,
    IPC::Message* reply_message) {
  browser->fullscreen_controller()->OnDenyFullscreenPermission();
  AutomationJSONReply(this, reply_message).SendSuccess(NULL);
}

void TestingAutomationProvider::WaitForTabToBeRestored(
    DictionaryValue* args,
    IPC::Message* reply_message) {
  WebContents* web_contents;
  std::string error;
  if (!GetTabFromJSONArgs(args, &web_contents, &error)) {
    AutomationJSONReply(this, reply_message).SendError(error);
    return;
  }
  NavigationController& controller = web_contents->GetController();
  new NavigationControllerRestoredObserver(this, &controller, reply_message);
}

void TestingAutomationProvider::RefreshPolicies(
    base::DictionaryValue* args,
    IPC::Message* reply_message) {
#if !defined(ENABLE_CONFIGURATION_POLICY)
  AutomationJSONReply(this, reply_message).SendError(
      "Configuration Policy disabled");
#else
  // Some policies (e.g. URLBlacklist) post tasks to other message loops
  // before they start enforcing updated policy values; make sure those tasks
  // have finished after a policy update.
  // Updates of the URLBlacklist are done on IO, after building the blacklist
  // on FILE, which is initiated from IO.
  base::Closure reply =
      base::Bind(SendSuccessReply, AsWeakPtr(), reply_message);
  g_browser_process->policy_service()->RefreshPolicies(
      base::Bind(PostTask, BrowserThread::IO,
          base::Bind(PostTask, BrowserThread::FILE,
              base::Bind(PostTask, BrowserThread::IO,
                  base::Bind(PostTask, BrowserThread::UI, reply)))));
#endif
}

static int AccessArray(const volatile int arr[], const volatile int *index) {
  return arr[*index];
}

void TestingAutomationProvider::SimulateAsanMemoryBug(
    base::DictionaryValue* args, IPC::Message* reply_message) {
  // This array is volatile not to let compiler optimize us out.
  volatile int testarray[3] = {0, 0, 0};

  // Send the reply while we can.
  AutomationJSONReply(this, reply_message).SendSuccess(NULL);

  // Cause Address Sanitizer to abort this process.
  volatile int index = 5;
  AccessArray(testarray, &index);
}

void TestingAutomationProvider::GetIndicesFromTab(
    DictionaryValue* args,
    IPC::Message* reply_message) {
  AutomationJSONReply reply(this, reply_message);
  int id_or_handle = 0;
  bool has_id = args->HasKey("tab_id");
  bool has_handle = args->HasKey("tab_handle");
  if (has_id && has_handle) {
    reply.SendError(
        "Both 'tab_id' and 'tab_handle' were specified. Only one is allowed");
    return;
  } else if (!has_id && !has_handle) {
    reply.SendError("Either 'tab_id' or 'tab_handle' must be specified");
    return;
  }
  if (has_id && !args->GetInteger("tab_id", &id_or_handle)) {
    reply.SendError("'tab_id' is invalid");
    return;
  }
  if (has_handle && (!args->GetInteger("tab_handle", &id_or_handle) ||
                     !tab_tracker_->ContainsHandle(id_or_handle))) {
    reply.SendError("'tab_handle' is invalid");
    return;
  }
  int id = id_or_handle;
  if (has_handle) {
    SessionTabHelper* session_tab_helper =
        SessionTabHelper::FromWebContents(
            tab_tracker_->GetResource(id_or_handle)->GetWebContents());
    id = session_tab_helper->session_id().id();
  }
  chrome::BrowserIterator it;
  int browser_index = 0;
  for (; !it.done(); it.Next(), ++browser_index) {
    Browser* browser = *it;
    for (int tab_index = 0;
         tab_index < browser->tab_strip_model()->count();
         ++tab_index) {
      WebContents* tab =
          browser->tab_strip_model()->GetWebContentsAt(tab_index);
      SessionTabHelper* session_tab_helper =
          SessionTabHelper::FromWebContents(tab);
      if (session_tab_helper->session_id().id() == id) {
        DictionaryValue dict;
        dict.SetInteger("windex", browser_index);
        dict.SetInteger("tab_index", tab_index);
        reply.SendSuccess(&dict);
        return;
      }
    }
  }
  reply.SendError("Could not find tab among current browser windows");
}

void TestingAutomationProvider::NavigateToURL(
    DictionaryValue* args,
    IPC::Message* reply_message) {
  if (SendErrorIfModalDialogActive(this, reply_message))
    return;

  int navigation_count;
  std::string url, error;
  Browser* browser;
  WebContents* web_contents;
  if (!GetBrowserAndTabFromJSONArgs(args, &browser, &web_contents, &error)) {
    AutomationJSONReply(this, reply_message).SendError(error);
    return;
  }
  if (!args->GetString("url", &url)) {
    AutomationJSONReply(this, reply_message)
        .SendError("'url' missing or invalid");
    return;
  }
  if (!args->GetInteger("navigation_count", &navigation_count)) {
    AutomationJSONReply(this, reply_message)
        .SendError("'navigation_count' missing or invalid");
    return;
  }
  if (navigation_count > 0) {
    new NavigationNotificationObserver(
        &web_contents->GetController(), this, reply_message,
        navigation_count, false, true);
  } else {
    AutomationJSONReply(this, reply_message).SendSuccess(NULL);
  }
  OpenURLParams params(
      GURL(url), content::Referrer(), CURRENT_TAB,
      content::PageTransitionFromInt(
          content::PAGE_TRANSITION_TYPED |
          content::PAGE_TRANSITION_FROM_ADDRESS_BAR),
      false);
  browser->OpenURLFromTab(web_contents, params);
}

void TestingAutomationProvider::GetActiveTabIndexJSON(
    DictionaryValue* args,
    IPC::Message* reply_message) {
  AutomationJSONReply reply(this, reply_message);
  Browser* browser;
  std::string error_msg;
  if (!GetBrowserFromJSONArgs(args, &browser, &error_msg)) {
    reply.SendError(error_msg);
    return;
  }
  int tab_index = browser->tab_strip_model()->active_index();
  scoped_ptr<DictionaryValue> return_value(new DictionaryValue);
  return_value->SetInteger("tab_index", tab_index);
  reply.SendSuccess(return_value.get());
}

void TestingAutomationProvider::AppendTabJSON(DictionaryValue* args,
                                              IPC::Message* reply_message) {
  TabAppendedNotificationObserver* observer = NULL;
  int append_tab_response = -1;
  Browser* browser;
  std::string error_msg, url;
  if (!GetBrowserFromJSONArgs(args, &browser, &error_msg)) {
    AutomationJSONReply(this, reply_message).SendError(error_msg);
    return;
  }
  if (!args->GetString("url", &url)) {
    AutomationJSONReply(this, reply_message)
        .SendError("'url' missing or invalid");
    return;
  }
  observer = new TabAppendedNotificationObserver(browser, this, reply_message,
                                                 true);
  WebContents* contents =
      chrome::AddSelectedTabWithURL(browser, GURL(url),
                                    content::PAGE_TRANSITION_TYPED);
  if (contents) {
    append_tab_response = GetIndexForNavigationController(
        &contents->GetController(), browser);
  }

  if (!contents || append_tab_response < 0) {
    if (observer) {
      observer->ReleaseReply();
      delete observer;
    }
    AutomationJSONReply(this, reply_message).SendError("Failed to append tab.");
  }
}

void TestingAutomationProvider::WaitUntilNavigationCompletes(
    DictionaryValue* args,
    IPC::Message* reply_message) {
  if (SendErrorIfModalDialogActive(this, reply_message))
    return;

  std::string error;
  Browser* browser;
  WebContents* web_contents;
  if (!GetBrowserAndTabFromJSONArgs(args, &browser, &web_contents, &error)) {
    AutomationJSONReply(this, reply_message).SendError(error);
    return;
  }
  NavigationNotificationObserver* observer =
      new NavigationNotificationObserver(&web_contents->GetController(), this,
                                         reply_message, 1, true, true);
  if (!web_contents->IsLoading()) {
    observer->ConditionMet(AUTOMATION_MSG_NAVIGATION_SUCCESS);
    return;
  }
}

void TestingAutomationProvider::ExecuteJavascriptJSON(
    DictionaryValue* args,
    IPC::Message* reply_message) {
  if (SendErrorIfModalDialogActive(this, reply_message))
    return;

  string16 frame_xpath, javascript;
  std::string error;
  RenderViewHost* render_view;
  if (!GetRenderViewFromJSONArgs(args, profile(), &render_view, &error)) {
    AutomationJSONReply(this, reply_message).SendError(error);
    return;
  }
  if (!args->GetString("frame_xpath", &frame_xpath)) {
    AutomationJSONReply(this, reply_message)
        .SendError("'frame_xpath' missing or invalid");
    return;
  }
  if (!args->GetString("javascript", &javascript)) {
    AutomationJSONReply(this, reply_message)
        .SendError("'javascript' missing or invalid");
    return;
  }

  new DomOperationMessageSender(this, reply_message, true);
  ExecuteJavascriptInRenderViewFrame(frame_xpath, javascript, reply_message,
                                     render_view);
}

void TestingAutomationProvider::ExecuteJavascriptInRenderView(
    DictionaryValue* args,
    IPC::Message* reply_message) {
  string16 frame_xpath, javascript, extension_id, url_text;
  int render_process_id, render_view_id;
  if (!args->GetString("frame_xpath", &frame_xpath)) {
    AutomationJSONReply(this, reply_message)
        .SendError("'frame_xpath' missing or invalid");
    return;
  }
  if (!args->GetString("javascript", &javascript)) {
    AutomationJSONReply(this, reply_message)
        .SendError("'javascript' missing or invalid");
    return;
  }
  if (!args->GetInteger("view.render_process_id", &render_process_id)) {
    AutomationJSONReply(this, reply_message)
        .SendError("'view.render_process_id' missing or invalid");
    return;
  }
  if (!args->GetInteger("view.render_view_id", &render_view_id)) {
    AutomationJSONReply(this, reply_message)
        .SendError("'view.render_view_id' missing or invalid");
    return;
  }

  RenderViewHost* rvh = RenderViewHost::FromID(render_process_id,
                                               render_view_id);
  if (!rvh) {
    AutomationJSONReply(this, reply_message).SendError(
            "A RenderViewHost object was not found with the given view ID.");
    return;
  }

  new DomOperationMessageSender(this, reply_message, true);
  ExecuteJavascriptInRenderViewFrame(frame_xpath, javascript, reply_message,
                                     rvh);
}

void TestingAutomationProvider::AddDomEventObserver(
    DictionaryValue* args,
    IPC::Message* reply_message) {
  if (SendErrorIfModalDialogActive(this, reply_message))
    return;

  AutomationJSONReply reply(this, reply_message);
  std::string event_name;
  int automation_id;
  bool recurring;
  if (!args->GetString("event_name", &event_name)) {
    reply.SendError("'event_name' missing or invalid");
    return;
  }
  if (!args->GetInteger("automation_id", &automation_id)) {
    reply.SendError("'automation_id' missing or invalid");
    return;
  }
  if (!args->GetBoolean("recurring", &recurring)) {
    reply.SendError("'recurring' missing or invalid");
    return;
  }

  if (!automation_event_queue_.get())
    automation_event_queue_.reset(new AutomationEventQueue);

  int observer_id = automation_event_queue_->AddObserver(
      new DomEventObserver(automation_event_queue_.get(), event_name,
                           automation_id, recurring));
  scoped_ptr<DictionaryValue> return_value(new DictionaryValue);
  return_value->SetInteger("observer_id", observer_id);
  reply.SendSuccess(return_value.get());
}

void TestingAutomationProvider::RemoveEventObserver(
    DictionaryValue* args,
    IPC::Message* reply_message) {
  AutomationJSONReply reply(this, reply_message);
  int observer_id;
  if (!args->GetInteger("observer_id", &observer_id) ||
      !automation_event_queue_.get()) {
    reply.SendError("'observer_id' missing or invalid");
    return;
  }
  if (automation_event_queue_->RemoveObserver(observer_id)) {
    reply.SendSuccess(NULL);
    return;
  }
  reply.SendError("Invalid observer id.");
}

void TestingAutomationProvider::ClearEventQueue(
    DictionaryValue* args,
    IPC::Message* reply_message) {
  automation_event_queue_.reset();
  AutomationJSONReply(this, reply_message).SendSuccess(NULL);
}

void TestingAutomationProvider::GetNextEvent(
    DictionaryValue* args,
    IPC::Message* reply_message) {
  scoped_ptr<AutomationJSONReply> reply(
      new AutomationJSONReply(this, reply_message));
  int observer_id;
  bool blocking;
  if (!args->GetInteger("observer_id", &observer_id)) {
    reply->SendError("'observer_id' missing or invalid");
    return;
  }
  if (!args->GetBoolean("blocking", &blocking)) {
    reply->SendError("'blocking' missing or invalid");
    return;
  }
  if (!automation_event_queue_.get()) {
    reply->SendError(
        "No observers are attached to the queue. Did you create any?");
    return;
  }

  // The reply will be freed once a matching event is added to the queue.
  automation_event_queue_->GetNextEvent(reply.release(), observer_id, blocking);
}

void TestingAutomationProvider::GoForward(
    DictionaryValue* args,
    IPC::Message* reply_message) {
  if (SendErrorIfModalDialogActive(this, reply_message))
    return;

  WebContents* web_contents;
  std::string error;
  if (!GetTabFromJSONArgs(args, &web_contents, &error)) {
    AutomationJSONReply(this, reply_message).SendError(error);
    return;
  }
  NavigationController& controller = web_contents->GetController();
  if (!controller.CanGoForward()) {
    DictionaryValue dict;
    dict.SetBoolean("did_go_forward", false);
    AutomationJSONReply(this, reply_message).SendSuccess(&dict);
    return;
  }
  new NavigationNotificationObserver(&controller, this, reply_message,
                                     1, false, true);
  controller.GoForward();
}

void TestingAutomationProvider::ExecuteBrowserCommandAsyncJSON(
    DictionaryValue* args,
    IPC::Message* reply_message) {
  AutomationJSONReply reply(this, reply_message);
  int command;
  Browser* browser;
  std::string error;
  if (!GetBrowserFromJSONArgs(args, &browser, &error)) {
    reply.SendError(error);
    return;
  }
  if (!args->GetInteger("accelerator", &command)) {
    reply.SendError("'accelerator' missing or invalid.");
    return;
  }
  if (!chrome::SupportsCommand(browser, command)) {
    reply.SendError(base::StringPrintf("Browser does not support command=%d.",
                                       command));
    return;
  }
  if (!chrome::IsCommandEnabled(browser, command)) {
    reply.SendError(base::StringPrintf(
        "Browser command=%d not enabled.", command));
    return;
  }
  chrome::ExecuteCommand(browser, command);
  reply.SendSuccess(NULL);
}

void TestingAutomationProvider::ExecuteBrowserCommandJSON(
    DictionaryValue* args,
    IPC::Message* reply_message) {
  int command;
  Browser* browser;
  std::string error;
  if (!GetBrowserFromJSONArgs(args, &browser, &error)) {
    AutomationJSONReply(this, reply_message).SendError(error);
    return;
  }
  if (!args->GetInteger("accelerator", &command)) {
    AutomationJSONReply(this, reply_message).SendError(
        "'accelerator' missing or invalid.");
    return;
  }
  if (!chrome::SupportsCommand(browser, command)) {
    AutomationJSONReply(this, reply_message).SendError(
        base::StringPrintf("Browser does not support command=%d.", command));
    return;
  }
  if (!chrome::IsCommandEnabled(browser, command)) {
    AutomationJSONReply(this, reply_message).SendError(
        base::StringPrintf("Browser command=%d not enabled.", command));
    return;
  }
  // First check if we can handle the command without using an observer.
  for (size_t i = 0; i < arraysize(kSynchronousCommands); i++) {
    if (command == kSynchronousCommands[i]) {
      chrome::ExecuteCommand(browser, command);
      AutomationJSONReply(this, reply_message).SendSuccess(NULL);
      return;
    }
  }
  // Use an observer if we have one, otherwise fail.
  if (ExecuteBrowserCommandObserver::CreateAndRegisterObserver(
      this, browser, command, reply_message, true)) {
    chrome::ExecuteCommand(browser, command);
    return;
  }
  AutomationJSONReply(this, reply_message).SendError(base::StringPrintf(
      "Unable to register observer for browser command=%d.", command));
}

void TestingAutomationProvider::IsMenuCommandEnabledJSON(
    DictionaryValue* args,
    IPC::Message* reply_message) {
  int command;
  Browser* browser;
  std::string error;
  if (!GetBrowserFromJSONArgs(args, &browser, &error)) {
    AutomationJSONReply(this, reply_message).SendError(error);
    return;
  }
  if (!args->GetInteger("accelerator", &command)) {
    AutomationJSONReply(this, reply_message).SendError(
        "'accelerator' missing or invalid.");
    return;
  }
  DictionaryValue dict;
  dict.SetBoolean("enabled", chrome::IsCommandEnabled(browser, command));
  AutomationJSONReply(this, reply_message).SendSuccess(&dict);
}

void TestingAutomationProvider::GetTabInfo(
    DictionaryValue* args,
    IPC::Message* reply_message) {
  AutomationJSONReply reply(this, reply_message);
  Browser* browser;
  WebContents* tab;
  std::string error;
  if (GetBrowserAndTabFromJSONArgs(args, &browser, &tab, &error)) {
    NavigationEntry* entry = tab->GetController().GetActiveEntry();
    if (!entry) {
      reply.SendError("Unable to get active navigation entry");
      return;
    }
    DictionaryValue dict;
    dict.SetString("title", entry->GetTitleForDisplay(std::string()));
    dict.SetString("url", entry->GetVirtualURL().spec());
    reply.SendSuccess(&dict);
  } else {
    reply.SendError(error);
  }
}

void TestingAutomationProvider::GetTabCountJSON(
    DictionaryValue* args,
    IPC::Message* reply_message) {
  AutomationJSONReply reply(this, reply_message);
  Browser* browser;
  std::string error;
  if (!GetBrowserFromJSONArgs(args, &browser, &error)) {
    reply.SendError(error);
    return;
  }
  DictionaryValue dict;
  dict.SetInteger("tab_count", browser->tab_strip_model()->count());
  reply.SendSuccess(&dict);
}

void TestingAutomationProvider::GoBack(
    DictionaryValue* args,
    IPC::Message* reply_message) {
  if (SendErrorIfModalDialogActive(this, reply_message))
    return;

  WebContents* web_contents;
  std::string error;
  if (!GetTabFromJSONArgs(args, &web_contents, &error)) {
    AutomationJSONReply(this, reply_message).SendError(error);
    return;
  }
  NavigationController& controller = web_contents->GetController();
  if (!controller.CanGoBack()) {
    DictionaryValue dict;
    dict.SetBoolean("did_go_back", false);
    AutomationJSONReply(this, reply_message).SendSuccess(&dict);
    return;
  }
  new NavigationNotificationObserver(&controller, this, reply_message,
                                     1, false, true);
  controller.GoBack();
}

void TestingAutomationProvider::ReloadJSON(
    DictionaryValue* args,
    IPC::Message* reply_message) {
  if (SendErrorIfModalDialogActive(this, reply_message))
    return;

  WebContents* web_contents;
  std::string error;
  if (!GetTabFromJSONArgs(args, &web_contents, &error)) {
    AutomationJSONReply(this, reply_message).SendError(error);
    return;
  }
  NavigationController& controller = web_contents->GetController();
  new NavigationNotificationObserver(&controller, this, reply_message,
                                     1, false, true);
  controller.Reload(false);
}

void TestingAutomationProvider::GetCookiesJSON(
    DictionaryValue* args, IPC::Message* reply_message) {
  automation_util::GetCookiesJSON(this, args, reply_message);
}

void TestingAutomationProvider::DeleteCookieJSON(
    DictionaryValue* args, IPC::Message* reply_message) {
  automation_util::DeleteCookieJSON(this, args, reply_message);
}

void TestingAutomationProvider::SetCookieJSON(
    DictionaryValue* args, IPC::Message* reply_message) {
  automation_util::SetCookieJSON(this, args, reply_message);
}

void TestingAutomationProvider::GetCookiesInBrowserContext(
    DictionaryValue* args,
    IPC::Message* reply_message) {
  AutomationJSONReply reply(this, reply_message);
  WebContents* web_contents;
  std::string value, url_string;
  int windex, value_size;
  if (!args->GetInteger("windex", &windex)) {
    reply.SendError("'windex' missing or invalid.");
    return;
  }
  web_contents = automation_util::GetWebContentsAt(windex, 0);
  if (!web_contents) {
    reply.SendError("'windex' does not refer to a browser window.");
    return;
  }
  if (!args->GetString("url", &url_string)) {
    reply.SendError("'url' missing or invalid.");
    return;
  }
  GURL url(url_string);
  if (!url.is_valid()) {
    reply.SendError("Invalid url.");
    return;
  }
  automation_util::GetCookies(url, web_contents, &value_size, &value);
  if (value_size == -1) {
    reply.SendError(
        base::StringPrintf("Unable to retrieve cookies for url=%s.",
                           url_string.c_str()));
    return;
  }
  DictionaryValue dict;
  dict.SetString("cookies", value);
  reply.SendSuccess(&dict);
}

void TestingAutomationProvider::DeleteCookieInBrowserContext(
    DictionaryValue* args,
    IPC::Message* reply_message) {
  AutomationJSONReply reply(this, reply_message);
  WebContents* web_contents;
  std::string cookie_name, url_string;
  int windex;
  bool success = false;
  if (!args->GetInteger("windex", &windex)) {
    reply.SendError("'windex' missing or invalid.");
    return;
  }
  web_contents = automation_util::GetWebContentsAt(windex, 0);
  if (!web_contents) {
    reply.SendError("'windex' does not refer to a browser window.");
    return;
  }
  if (!args->GetString("cookie_name", &cookie_name)) {
    reply.SendError("'cookie_name' missing or invalid.");
    return;
  }
  if (!args->GetString("url", &url_string)) {
    reply.SendError("'url' missing or invalid.");
    return;
  }
  GURL url(url_string);
  if (!url.is_valid()) {
    reply.SendError("Invalid url.");
    return;
  }
  automation_util::DeleteCookie(url, cookie_name, web_contents, &success);
  if (!success) {
    reply.SendError(
        base::StringPrintf("Failed to delete cookie with name=%s for url=%s.",
                           cookie_name.c_str(), url_string.c_str()));
    return;
  }
  reply.SendSuccess(NULL);
}

void TestingAutomationProvider::SetCookieInBrowserContext(
    DictionaryValue* args,
    IPC::Message* reply_message) {
  AutomationJSONReply reply(this, reply_message);
  WebContents* web_contents;
  std::string value, url_string;
  int windex, response_value = -1;
  if (!args->GetInteger("windex", &windex)) {
    reply.SendError("'windex' missing or invalid.");
    return;
  }
  web_contents = automation_util::GetWebContentsAt(windex, 0);
  if (!web_contents) {
    reply.SendError("'windex' does not refer to a browser window.");
    return;
  }
  if (!args->GetString("value", &value)) {
    reply.SendError("'value' missing or invalid.");
    return;
  }
  if (!args->GetString("url", &url_string)) {
    reply.SendError("'url' missing or invalid.");
    return;
  }
  GURL url(url_string);
  if (!url.is_valid()) {
    reply.SendError("Invalid url.");
    return;
  }
  automation_util::SetCookie(url, value, web_contents, &response_value);
  if (response_value != 1) {
    reply.SendError(base::StringPrintf(
        "Unable set cookie for url=%s.", url_string.c_str()));
    return;
  }
  reply.SendSuccess(NULL);
}

void TestingAutomationProvider::GetTabIds(
    DictionaryValue* args, IPC::Message* reply_message) {
  ListValue* id_list = new ListValue();
  for (chrome::BrowserIterator it; !it.done(); it.Next()) {
    Browser* browser = *it;
    for (int i = 0; i < browser->tab_strip_model()->count(); ++i) {
      int id = SessionTabHelper::FromWebContents(
          browser->tab_strip_model()->GetWebContentsAt(i))->session_id().id();
      id_list->Append(Value::CreateIntegerValue(id));
    }
  }
  DictionaryValue dict;
  dict.Set("ids", id_list);
  AutomationJSONReply(this, reply_message).SendSuccess(&dict);
}

void TestingAutomationProvider::IsTabIdValid(
    DictionaryValue* args, IPC::Message* reply_message) {
  AutomationJSONReply reply(this, reply_message);
  int id;
  if (!args->GetInteger("id", &id)) {
    reply.SendError("'id' missing or invalid");
    return;
  }
  bool is_valid = false;
  for (chrome::BrowserIterator it; !it.done(); it.Next()) {
    Browser* browser = *it;
    for (int i = 0; i < browser->tab_strip_model()->count(); ++i) {
      WebContents* tab = browser->tab_strip_model()->GetWebContentsAt(i);
      SessionTabHelper* session_tab_helper =
          SessionTabHelper::FromWebContents(tab);
      if (session_tab_helper->session_id().id() == id) {
        is_valid = true;
        break;
      }
    }
  }
  DictionaryValue dict;
  dict.SetBoolean("is_valid", is_valid);
  reply.SendSuccess(&dict);
}

void TestingAutomationProvider::CloseTabJSON(
    DictionaryValue* args, IPC::Message* reply_message) {
  Browser* browser;
  WebContents* tab;
  std::string error;
  bool wait_until_closed = false;  // ChromeDriver does not use this.
  args->GetBoolean("wait_until_closed", &wait_until_closed);
  // Close tabs synchronously.
  if (GetBrowserAndTabFromJSONArgs(args, &browser, &tab, &error)) {
    if (wait_until_closed) {
      new TabClosedNotificationObserver(this, wait_until_closed, reply_message,
                                        true);
    }
    chrome::CloseWebContents(browser, tab, false);
    if (!wait_until_closed)
      AutomationJSONReply(this, reply_message).SendSuccess(NULL);
    return;
  }
  // Close other types of views asynchronously.
  RenderViewHost* view;
  if (!GetRenderViewFromJSONArgs(args, profile(), &view, &error)) {
    AutomationJSONReply(this, reply_message).SendError(error);
    return;
  }
  view->ClosePage();
  AutomationJSONReply(this, reply_message).SendSuccess(NULL);
}

void TestingAutomationProvider::SetViewBounds(
    base::DictionaryValue* args,
    IPC::Message* reply_message) {
  AutomationJSONReply reply(this, reply_message);
  int x, y, width, height;
  if (!args->GetInteger("bounds.x", &x) ||
      !args->GetInteger("bounds.y", &y) ||
      !args->GetInteger("bounds.width", &width) ||
      !args->GetInteger("bounds.height", &height)) {
    reply.SendError("Missing or invalid 'bounds'");
    return;
  }
  Browser* browser;
  std::string error;
  if (!GetBrowserFromJSONArgs(args, &browser, &error)) {
    reply.SendError(error);
    return;
  }
  BrowserWindow* browser_window = browser->window();
  if (browser_window->IsMaximized()) {
    browser_window->Restore();
  }
  browser_window->SetBounds(gfx::Rect(x, y, width, height));
  reply.SendSuccess(NULL);
}

void TestingAutomationProvider::MaximizeView(
    base::DictionaryValue* args,
    IPC::Message* reply_message) {
  Browser* browser;
  std::string error;
  if (!GetBrowserFromJSONArgs(args, &browser, &error)) {
    AutomationJSONReply(this, reply_message).SendError(error);
    return;
  }

#if defined(OS_LINUX)
  // Maximization on Linux is asynchronous, so create an observer object to be
  // notified upon maximization completion.
  new WindowMaximizedObserver(this, reply_message);
#endif  // defined(OS_LINUX)

  browser->window()->Maximize();

#if !defined(OS_LINUX)
  // Send success reply right away for OS's with synchronous maximize command.
  AutomationJSONReply(this, reply_message).SendSuccess(NULL);
#endif  // !defined(OS_LINUX)
}

void TestingAutomationProvider::ActivateTabJSON(
    DictionaryValue* args,
    IPC::Message* reply_message) {
  if (SendErrorIfModalDialogActive(this, reply_message))
    return;

  AutomationJSONReply reply(this, reply_message);
  Browser* browser;
  WebContents* web_contents;
  std::string error;
  if (!GetBrowserAndTabFromJSONArgs(args, &browser, &web_contents, &error)) {
    reply.SendError(error);
    return;
  }
  TabStripModel* tab_strip = browser->tab_strip_model();
  tab_strip->ActivateTabAt(tab_strip->GetIndexOfWebContents(web_contents),
                           true);
  reply.SendSuccess(NULL);
}

void TestingAutomationProvider::IsPageActionVisible(
    base::DictionaryValue* args,
    IPC::Message* reply_message) {
  AutomationJSONReply reply(this, reply_message);

  WebContents* tab;
  std::string error;
  if (!GetTabFromJSONArgs(args, &tab, &error)) {
    reply.SendError(error);
    return;
  }
  Browser* browser = automation_util::GetBrowserForTab(tab);
  if (!browser) {
    reply.SendError("Tab does not belong to an open browser");
    return;
  }
  const Extension* extension;
  if (!GetEnabledExtensionFromJSONArgs(
          args, "extension_id", browser->profile(), &extension, &error)) {
    reply.SendError(error);
    return;
  }
  ExtensionAction* page_action =
      ExtensionActionManager::Get(browser->profile())->
      GetPageAction(*extension);
  if (!page_action) {
    reply.SendError("Extension doesn't have any page action");
    return;
  }
  EnsureTabSelected(browser, tab);

  bool is_visible = false;
  LocationBarTesting* loc_bar =
      browser->window()->GetLocationBar()->GetLocationBarForTesting();
  size_t page_action_visible_count =
      static_cast<size_t>(loc_bar->PageActionVisibleCount());
  for (size_t i = 0; i < page_action_visible_count; ++i) {
    if (loc_bar->GetVisiblePageAction(i) == page_action) {
      is_visible = true;
      break;
    }
  }
  DictionaryValue dict;
  dict.SetBoolean("is_visible", is_visible);
  reply.SendSuccess(&dict);
}

void TestingAutomationProvider::CreateNewAutomationProvider(
    DictionaryValue* args,
    IPC::Message* reply_message) {
  AutomationJSONReply reply(this, reply_message);
  std::string channel_id;
  if (!args->GetString("channel_id", &channel_id)) {
    reply.SendError("'channel_id' missing or invalid");
    return;
  }

  AutomationProvider* provider = new TestingAutomationProvider(profile_);
  provider->DisableInitialLoadObservers();
  // TODO(kkania): Remove this when crbug.com/91311 is fixed.
  // Named server channels should ideally be created and closed on the file
  // thread, within the IPC channel code.
  base::ThreadRestrictions::ScopedAllowIO allow_io;
  if (!provider->InitializeChannel(
          automation::kNamedInterfacePrefix + channel_id)) {
    reply.SendError("Failed to initialize channel: " + channel_id);
    return;
  }
  DCHECK(g_browser_process);
  g_browser_process->GetAutomationProviderList()->AddProvider(provider);
  reply.SendSuccess(NULL);
}

void TestingAutomationProvider::WaitForTabCountToBecome(
    int browser_handle,
    int target_tab_count,
    IPC::Message* reply_message) {
  if (!browser_tracker_->ContainsHandle(browser_handle)) {
    AutomationMsg_WaitForTabCountToBecome::WriteReplyParams(reply_message,
                                                            false);
    Send(reply_message);
    return;
  }

  Browser* browser = browser_tracker_->GetResource(browser_handle);

  // The observer will delete itself.
  new TabCountChangeObserver(this, browser, reply_message, target_tab_count);
}

void TestingAutomationProvider::WaitForInfoBarCount(
    int tab_handle,
    size_t target_count,
    IPC::Message* reply_message) {
  if (!tab_tracker_->ContainsHandle(tab_handle)) {
    AutomationMsg_WaitForInfoBarCount::WriteReplyParams(reply_message_, false);
    Send(reply_message_);
    return;
  }

  NavigationController* controller = tab_tracker_->GetResource(tab_handle);
  if (!controller) {
    AutomationMsg_WaitForInfoBarCount::WriteReplyParams(reply_message_, false);
    Send(reply_message_);
    return;
  }

  // The delegate will delete itself.
  new InfoBarCountObserver(this, reply_message,
                           controller->GetWebContents(), target_count);
}

void TestingAutomationProvider::WaitForProcessLauncherThreadToGoIdle(
    IPC::Message* reply_message) {
  new WaitForProcessLauncherThreadToGoIdleObserver(this, reply_message);
}

void TestingAutomationProvider::OnRemoveProvider() {
  if (g_browser_process)
    g_browser_process->GetAutomationProviderList()->RemoveProvider(this);
}

void TestingAutomationProvider::EnsureTabSelected(Browser* browser,
                                                  WebContents* tab) {
  TabStripModel* tab_strip = browser->tab_strip_model();
  if (tab_strip->GetActiveWebContents() != tab)
    tab_strip->ActivateTabAt(tab_strip->GetIndexOfWebContents(tab), true);
}
