// Copyright (c) 2012 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/extensions/api/developer_private/developer_private_api.h"

#include "apps/app_load_service.h"
#include "apps/app_restore_service.h"
#include "apps/saved_files_service.h"
#include "apps/shell_window.h"
#include "apps/shell_window_registry.h"
#include "base/base64.h"
#include "base/command_line.h"
#include "base/file_util.h"
#include "base/files/file_enumerator.h"
#include "base/i18n/file_util_icu.h"
#include "base/strings/string_number_conversions.h"
#include "base/strings/utf_string_conversions.h"
#include "base/values.h"
#include "chrome/browser/chrome_notification_types.h"
#include "chrome/browser/devtools/devtools_window.h"
#include "chrome/browser/extensions/api/developer_private/developer_private_api_factory.h"
#include "chrome/browser/extensions/api/developer_private/entry_picker.h"
#include "chrome/browser/extensions/api/extension_action/extension_action_api.h"
#include "chrome/browser/extensions/devtools_util.h"
#include "chrome/browser/extensions/extension_disabled_ui.h"
#include "chrome/browser/extensions/extension_error_reporter.h"
#include "chrome/browser/extensions/extension_service.h"
#include "chrome/browser/extensions/extension_system.h"
#include "chrome/browser/extensions/extension_util.h"
#include "chrome/browser/extensions/management_policy.h"
#include "chrome/browser/extensions/unpacked_installer.h"
#include "chrome/browser/extensions/updater/extension_updater.h"
#include "chrome/browser/platform_util.h"
#include "chrome/browser/profiles/profile.h"
#include "chrome/browser/sync_file_system/drive_backend_v1/drive_file_sync_service.h"
#include "chrome/browser/sync_file_system/syncable_file_system_util.h"
#include "chrome/browser/ui/chrome_select_file_policy.h"
#include "chrome/browser/ui/webui/extensions/extension_icon_source.h"
#include "chrome/common/extensions/api/developer_private.h"
#include "chrome/common/extensions/background_info.h"
#include "chrome/common/extensions/incognito_handler.h"
#include "chrome/common/extensions/manifest_handlers/app_launch_info.h"
#include "chrome/common/extensions/manifest_handlers/icons_handler.h"
#include "chrome/common/extensions/manifest_handlers/offline_enabled_info.h"
#include "chrome/common/extensions/manifest_url_handler.h"
#include "chrome/common/url_constants.h"
#include "content/public/browser/browser_thread.h"
#include "content/public/browser/notification_service.h"
#include "content/public/browser/render_process_host.h"
#include "content/public/browser/render_view_host.h"
#include "content/public/browser/site_instance.h"
#include "content/public/browser/storage_partition.h"
#include "content/public/browser/web_contents.h"
#include "extensions/browser/view_type_utils.h"
#include "extensions/common/constants.h"
#include "extensions/common/extension_resource.h"
#include "extensions/common/install_warning.h"
#include "extensions/common/switches.h"
#include "grit/chromium_strings.h"
#include "grit/generated_resources.h"
#include "grit/theme_resources.h"
#include "net/base/net_util.h"
#include "ui/base/l10n/l10n_util.h"
#include "ui/base/resource/resource_bundle.h"
#include "ui/base/webui/web_ui_util.h"
#include "webkit/browser/fileapi/file_system_context.h"
#include "webkit/browser/fileapi/file_system_operation.h"
#include "webkit/browser/fileapi/file_system_operation_runner.h"
#include "webkit/common/blob/shareable_file_reference.h"

using apps::ShellWindow;
using apps::ShellWindowRegistry;
using content::RenderViewHost;

namespace extensions {

namespace developer_private = api::developer_private;

namespace {

const base::FilePath::CharType kUnpackedAppsFolder[]
    = FILE_PATH_LITERAL("apps_target");

ExtensionUpdater* GetExtensionUpdater(Profile* profile) {
    return profile->GetExtensionService()->updater();
}

GURL GetImageURLFromData(std::string contents) {
  std::string contents_base64;
  if (!base::Base64Encode(contents, &contents_base64))
    return GURL();

  // TODO(dvh): make use of chrome::kDataScheme. Filed as crbug/297301.
  const char kDataURLPrefix[] = "data:image;base64,";
  return GURL(kDataURLPrefix + contents_base64);
}

GURL GetDefaultImageURL(developer_private::ItemType type) {
  int icon_resource_id;
  switch (type) {
    case developer::ITEM_TYPE_LEGACY_PACKAGED_APP:
    case developer::ITEM_TYPE_HOSTED_APP:
    case developer::ITEM_TYPE_PACKAGED_APP:
      icon_resource_id = IDR_APP_DEFAULT_ICON;
      break;
    default:
      icon_resource_id = IDR_EXTENSION_DEFAULT_ICON;
      break;
  }

  return GetImageURLFromData(
      ResourceBundle::GetSharedInstance().GetRawDataResourceForScale(
          icon_resource_id, ui::SCALE_FACTOR_100P).as_string());
}

// TODO(dvh): This code should be refactored and moved to
// extensions::ImageLoader. Also a resize should be performed to avoid
// potential huge URLs: crbug/297298.
GURL ToDataURL(const base::FilePath& path, developer_private::ItemType type) {
  std::string contents;
  if (path.empty() || !base::ReadFileToString(path, &contents))
    return GetDefaultImageURL(type);

  return GetImageURLFromData(contents);
}

std::vector<base::FilePath> ListFolder(const base::FilePath path) {
  base::FileEnumerator files(path, false,
      base::FileEnumerator::DIRECTORIES | base::FileEnumerator::FILES);
  std::vector<base::FilePath> paths;

  for (base::FilePath current_path = files.Next(); !current_path.empty();
       current_path = files.Next()) {
    paths.push_back(current_path);
  }
  return paths;
}

bool ValidateFolderName(const base::FilePath::StringType& name) {
  base::FilePath::StringType name_sanitized(name);
  file_util::ReplaceIllegalCharactersInPath(&name_sanitized, '_');
  return name == name_sanitized;
}

const Extension* GetExtensionByPath(const ExtensionSet* extensions,
                                    const base::FilePath& path) {
  base::FilePath extension_path = base::MakeAbsoluteFilePath(path);
  for (ExtensionSet::const_iterator iter = extensions->begin();
       iter != extensions->end(); ++iter) {
    if ((*iter)->path() == extension_path)
      return iter->get();
  }
  return NULL;
}

std::string GetExtensionID(const RenderViewHost* render_view_host) {
  if (!render_view_host->GetSiteInstance())
    return std::string();

  return render_view_host->GetSiteInstance()->GetSiteURL().host();
}

}  // namespace

namespace AllowFileAccess = api::developer_private::AllowFileAccess;
namespace AllowIncognito = api::developer_private::AllowIncognito;
namespace ChoosePath = api::developer_private::ChoosePath;
namespace Enable = api::developer_private::Enable;
namespace GetItemsInfo = api::developer_private::GetItemsInfo;
namespace Inspect = api::developer_private::Inspect;
namespace PackDirectory = api::developer_private::PackDirectory;
namespace Reload = api::developer_private::Reload;

DeveloperPrivateAPI* DeveloperPrivateAPI::Get(Profile* profile) {
  return DeveloperPrivateAPIFactory::GetForProfile(profile);
}

DeveloperPrivateAPI::DeveloperPrivateAPI(Profile* profile) : profile_(profile) {
  RegisterNotifications();
}

DeveloperPrivateEventRouter::DeveloperPrivateEventRouter(Profile* profile)
: profile_(profile) {
  int types[] = {
    chrome::NOTIFICATION_EXTENSION_INSTALLED,
    chrome::NOTIFICATION_EXTENSION_UNINSTALLED,
    chrome::NOTIFICATION_EXTENSION_LOADED,
    chrome::NOTIFICATION_EXTENSION_UNLOADED,
    chrome::NOTIFICATION_EXTENSION_VIEW_REGISTERED,
    chrome::NOTIFICATION_EXTENSION_VIEW_UNREGISTERED
  };

  CHECK(registrar_.IsEmpty());
  for (size_t i = 0; i < arraysize(types); ++i) {
    registrar_.Add(this,
                   types[i],
                   content::Source<Profile>(profile_));
  }
}


DeveloperPrivateEventRouter::~DeveloperPrivateEventRouter() {}

void DeveloperPrivateEventRouter::Observe(
    int type,
    const content::NotificationSource& source,
    const content::NotificationDetails& details) {
  const char* event_name = NULL;
  Profile* profile = content::Source<Profile>(source).ptr();
  CHECK(profile);
  CHECK(profile_->IsSameProfile(profile));
  developer::EventData event_data;
  const Extension* extension = NULL;

  switch (type) {
    case chrome::NOTIFICATION_EXTENSION_INSTALLED:
      event_data.event_type = developer::EVENT_TYPE_INSTALLED;
      extension =
          content::Details<const InstalledExtensionInfo>(details)->extension;
      break;
    case chrome::NOTIFICATION_EXTENSION_UNINSTALLED:
      event_data.event_type = developer::EVENT_TYPE_UNINSTALLED;
      extension = content::Details<const Extension>(details).ptr();
      break;
    case chrome::NOTIFICATION_EXTENSION_LOADED:
      event_data.event_type = developer::EVENT_TYPE_LOADED;
      extension = content::Details<const Extension>(details).ptr();
      break;
    case chrome::NOTIFICATION_EXTENSION_UNLOADED:
      event_data.event_type = developer::EVENT_TYPE_UNLOADED;
      extension =
          content::Details<const UnloadedExtensionInfo>(details)->extension;
      break;
    case chrome::NOTIFICATION_EXTENSION_VIEW_UNREGISTERED:
      event_data.event_type = developer::EVENT_TYPE_VIEW_UNREGISTERED;
      event_data.item_id = GetExtensionID(
          content::Details<const RenderViewHost>(details).ptr());
      break;
    case chrome::NOTIFICATION_EXTENSION_VIEW_REGISTERED:
      event_data.event_type = developer::EVENT_TYPE_VIEW_REGISTERED;
      event_data.item_id = GetExtensionID(
          content::Details<const RenderViewHost>(details).ptr());
      break;
    default:
      NOTREACHED();
      return;
  }

  if (extension)
    event_data.item_id = extension->id();

  scoped_ptr<ListValue> args(new ListValue());
  args->Append(event_data.ToValue().release());

  event_name = developer_private::OnItemStateChanged::kEventName;
  scoped_ptr<Event> event(new Event(event_name, args.Pass()));
  ExtensionSystem::Get(profile)->event_router()->BroadcastEvent(event.Pass());
}

void DeveloperPrivateAPI::SetLastUnpackedDirectory(const base::FilePath& path) {
  last_unpacked_directory_ = path;
}

void DeveloperPrivateAPI::RegisterNotifications() {
  ExtensionSystem::Get(profile_)->event_router()->RegisterObserver(
      this, developer_private::OnItemStateChanged::kEventName);
}

DeveloperPrivateAPI::~DeveloperPrivateAPI() {}

void DeveloperPrivateAPI::Shutdown() {}

void DeveloperPrivateAPI::OnListenerAdded(
    const EventListenerInfo& details) {
  if (!developer_private_event_router_)
    developer_private_event_router_.reset(
        new DeveloperPrivateEventRouter(profile_));
}

void DeveloperPrivateAPI::OnListenerRemoved(
    const EventListenerInfo& details) {
  if (!ExtensionSystem::Get(profile_)->event_router()->HasEventListener(
          developer_private::OnItemStateChanged::kEventName))
    developer_private_event_router_.reset(NULL);
}

namespace api {

bool DeveloperPrivateAutoUpdateFunction::RunImpl() {
  ExtensionUpdater* updater = GetExtensionUpdater(GetProfile());
  if (updater)
    updater->CheckNow(ExtensionUpdater::CheckParams());
  SetResult(new base::FundamentalValue(true));
  return true;
}

DeveloperPrivateAutoUpdateFunction::~DeveloperPrivateAutoUpdateFunction() {}

scoped_ptr<developer::ItemInfo>
  DeveloperPrivateGetItemsInfoFunction::CreateItemInfo(
      const Extension& item,
      bool item_is_enabled) {
  scoped_ptr<developer::ItemInfo> info(new developer::ItemInfo());

  ExtensionSystem* system = ExtensionSystem::Get(GetProfile());
  ExtensionService* service = GetProfile()->GetExtensionService();

  info->id = item.id();
  info->name = item.name();
  info->enabled = service->IsExtensionEnabled(info->id);
  info->offline_enabled = OfflineEnabledInfo::IsOfflineEnabled(&item);
  info->version = item.VersionString();
  info->description = item.description();

  if (item.is_app()) {
    if (item.is_legacy_packaged_app())
      info->type = developer::ITEM_TYPE_LEGACY_PACKAGED_APP;
    else if (item.is_hosted_app())
      info->type = developer::ITEM_TYPE_HOSTED_APP;
    else if (item.is_platform_app())
      info->type = developer::ITEM_TYPE_PACKAGED_APP;
    else
      NOTREACHED();
  } else if (item.is_theme()) {
    info->type = developer::ITEM_TYPE_THEME;
  } else if (item.is_extension()) {
    info->type = developer::ITEM_TYPE_EXTENSION;
  } else {
    NOTREACHED();
  }

  if (Manifest::IsUnpackedLocation(item.location())) {
    info->path.reset(
        new std::string(UTF16ToUTF8(item.path().LossyDisplayName())));
    for (std::vector<extensions::InstallWarning>::const_iterator it =
             item.install_warnings().begin();
         it != item.install_warnings().end(); ++it) {
      developer::InstallWarning* warning = new developer::InstallWarning();
      warning->message = it->message;
      info->install_warnings.push_back(make_linked_ptr(warning));
    }
  }

  info->incognito_enabled =
      extension_util::IsIncognitoEnabled(item.id(),service);
  info->wants_file_access = item.wants_file_access();
  info->allow_file_access = extension_util::AllowFileAccess(&item, service);
  info->allow_reload = Manifest::IsUnpackedLocation(item.location());
  info->is_unpacked = Manifest::IsUnpackedLocation(item.location());
  info->terminated = service->terminated_extensions()->Contains(item.id());
  info->allow_incognito = item.can_be_incognito_enabled();

  info->homepage_url.reset(new std::string(
      ManifestURL::GetHomepageURL(&item).spec()));
  if (!ManifestURL::GetOptionsPage(&item).is_empty()) {
    info->options_url.reset(
        new std::string(ManifestURL::GetOptionsPage(&item).spec()));
  }

  if (!ManifestURL::GetUpdateURL(&item).is_empty()) {
    info->update_url.reset(
        new std::string(ManifestURL::GetUpdateURL(&item).spec()));
  }

  if (item.is_app()) {
    info->app_launch_url.reset(new std::string(
        extensions::AppLaunchInfo::GetFullLaunchURL(&item).spec()));
  }

  info->may_disable = system->management_policy()->
      UserMayModifySettings(&item, NULL);
  info->is_app = item.is_app();
  info->views = GetInspectablePagesForExtension(&item, item_is_enabled);

  return info.Pass();
}

void DeveloperPrivateGetItemsInfoFunction::GetIconsOnFileThread(
    ItemInfoList item_list,
    const std::map<std::string, ExtensionResource> idToIcon) {
  for (ItemInfoList::iterator iter = item_list.begin();
       iter != item_list.end(); ++iter) {
    developer_private::ItemInfo* info = iter->get();
    std::map<std::string, ExtensionResource>::const_iterator resource_ptr
        = idToIcon.find(info->id);
    if (resource_ptr != idToIcon.end()) {
      info->icon_url =
          ToDataURL(resource_ptr->second.GetFilePath(), info->type).spec();
    }
  }

  results_ = developer::GetItemsInfo::Results::Create(item_list);
  content::BrowserThread::PostTask(content::BrowserThread::UI, FROM_HERE,
      base::Bind(&DeveloperPrivateGetItemsInfoFunction::SendResponse,
                 this,
                 true));
}

void DeveloperPrivateGetItemsInfoFunction::
    GetInspectablePagesForExtensionProcess(
        const Extension* extension,
        const std::set<content::RenderViewHost*>& views,
        ItemInspectViewList* result) {
  bool has_generated_background_page =
      BackgroundInfo::HasGeneratedBackgroundPage(extension);
  for (std::set<content::RenderViewHost*>::const_iterator iter = views.begin();
       iter != views.end(); ++iter) {
    content::RenderViewHost* host = *iter;
    content::WebContents* web_contents =
        content::WebContents::FromRenderViewHost(host);
    ViewType host_type = GetViewType(web_contents);
    if (VIEW_TYPE_EXTENSION_POPUP == host_type ||
        VIEW_TYPE_EXTENSION_DIALOG == host_type)
      continue;

    content::RenderProcessHost* process = host->GetProcess();
    bool is_background_page =
        (web_contents->GetURL() == BackgroundInfo::GetBackgroundURL(extension));
    result->push_back(constructInspectView(
        web_contents->GetURL(),
        process->GetID(),
        host->GetRoutingID(),
        process->GetBrowserContext()->IsOffTheRecord(),
        is_background_page && has_generated_background_page));
  }
}

void DeveloperPrivateGetItemsInfoFunction::
    GetShellWindowPagesForExtensionProfile(
        const Extension* extension,
        ItemInspectViewList* result) {
  ShellWindowRegistry* registry = ShellWindowRegistry::Get(GetProfile());
  if (!registry) return;

  const ShellWindowRegistry::ShellWindowList windows =
      registry->GetShellWindowsForApp(extension->id());

  bool has_generated_background_page =
      BackgroundInfo::HasGeneratedBackgroundPage(extension);
  for (ShellWindowRegistry::const_iterator it = windows.begin();
       it != windows.end(); ++it) {
    content::WebContents* web_contents = (*it)->web_contents();
    RenderViewHost* host = web_contents->GetRenderViewHost();
    content::RenderProcessHost* process = host->GetProcess();
    bool is_background_page =
        (web_contents->GetURL() == BackgroundInfo::GetBackgroundURL(extension));
    result->push_back(constructInspectView(
        web_contents->GetURL(),
        process->GetID(),
        host->GetRoutingID(),
        process->GetBrowserContext()->IsOffTheRecord(),
        is_background_page && has_generated_background_page));
  }
}

linked_ptr<developer::ItemInspectView> DeveloperPrivateGetItemsInfoFunction::
    constructInspectView(
        const GURL& url,
        int render_process_id,
        int render_view_id,
        bool incognito,
        bool generated_background_page) {
  linked_ptr<developer::ItemInspectView> view(new developer::ItemInspectView());

  if (url.scheme() == kExtensionScheme) {
    // No leading slash.
    view->path = url.path().substr(1);
  } else {
    // For live pages, use the full URL.
    view->path = url.spec();
  }

  view->render_process_id = render_process_id;
  view->render_view_id = render_view_id;
  view->incognito = incognito;
  view->generated_background_page = generated_background_page;
  return view;
}

ItemInspectViewList DeveloperPrivateGetItemsInfoFunction::
    GetInspectablePagesForExtension(
        const Extension* extension,
        bool extension_is_enabled) {

  ItemInspectViewList result;
  // Get the extension process's active views.
  ExtensionProcessManager* process_manager =
      ExtensionSystem::Get(GetProfile())->process_manager();
  GetInspectablePagesForExtensionProcess(
      extension,
      process_manager->GetRenderViewHostsForExtension(extension->id()),
      &result);

  // Get shell window views
  GetShellWindowPagesForExtensionProfile(extension, &result);

  // Include a link to start the lazy background page, if applicable.
  if (BackgroundInfo::HasLazyBackgroundPage(extension) &&
      extension_is_enabled &&
      !process_manager->GetBackgroundHostForExtension(extension->id())) {
    result.push_back(constructInspectView(
        BackgroundInfo::GetBackgroundURL(extension),
        -1,
        -1,
        false,
        BackgroundInfo::HasGeneratedBackgroundPage(extension)));
  }

  ExtensionService* service = GetProfile()->GetExtensionService();
  // Repeat for the incognito process, if applicable. Don't try to get
  // shell windows for incognito process.
  if (service->profile()->HasOffTheRecordProfile() &&
      IncognitoInfo::IsSplitMode(extension)) {
    process_manager = ExtensionSystem::Get(
        service->profile()->GetOffTheRecordProfile())->process_manager();
    GetInspectablePagesForExtensionProcess(
        extension,
        process_manager->GetRenderViewHostsForExtension(extension->id()),
        &result);

    if (BackgroundInfo::HasLazyBackgroundPage(extension) &&
        extension_is_enabled &&
        !process_manager->GetBackgroundHostForExtension(extension->id())) {
    result.push_back(constructInspectView(
        BackgroundInfo::GetBackgroundURL(extension),
        -1,
        -1,
        false,
        BackgroundInfo::HasGeneratedBackgroundPage(extension)));
    }
  }

  return result;
}

bool DeveloperPrivateGetItemsInfoFunction::RunImpl() {
  scoped_ptr<developer::GetItemsInfo::Params> params(
      developer::GetItemsInfo::Params::Create(*args_));
  EXTENSION_FUNCTION_VALIDATE(params.get() != NULL);

  bool include_disabled = params->include_disabled;
  bool include_terminated = params->include_terminated;

  ExtensionSet items;

  ExtensionService* service = GetProfile()->GetExtensionService();

  items.InsertAll(*service->extensions());

  if (include_disabled) {
    items.InsertAll(*service->disabled_extensions());
  }

  if (include_terminated) {
    items.InsertAll(*service->terminated_extensions());
  }

  std::map<std::string, ExtensionResource> id_to_icon;
  ItemInfoList item_list;

  for (ExtensionSet::const_iterator iter = items.begin();
       iter != items.end(); ++iter) {
    const Extension& item = *iter->get();

    ExtensionResource item_resource =
        IconsInfo::GetIconResource(&item,
                                   extension_misc::EXTENSION_ICON_MEDIUM,
                                   ExtensionIconSet::MATCH_BIGGER);
    id_to_icon[item.id()] = item_resource;

    // Don't show component extensions and invisible apps.
    if (item.ShouldNotBeVisible())
      continue;

    item_list.push_back(make_linked_ptr<developer::ItemInfo>(
        CreateItemInfo(
            item, service->IsExtensionEnabled(item.id())).release()));
  }

  content::BrowserThread::PostTask(content::BrowserThread::FILE, FROM_HERE,
      base::Bind(&DeveloperPrivateGetItemsInfoFunction::GetIconsOnFileThread,
                 this,
                 item_list,
                 id_to_icon));

  return true;
}

DeveloperPrivateGetItemsInfoFunction::~DeveloperPrivateGetItemsInfoFunction() {}

bool DeveloperPrivateAllowFileAccessFunction::RunImpl() {
  scoped_ptr<AllowFileAccess::Params> params(
      AllowFileAccess::Params::Create(*args_));
  EXTENSION_FUNCTION_VALIDATE(params.get());

  EXTENSION_FUNCTION_VALIDATE(user_gesture_);

  ExtensionSystem* system = ExtensionSystem::Get(GetProfile());
  ManagementPolicy* management_policy = system->management_policy();
  ExtensionService* service = GetProfile()->GetExtensionService();
  const Extension* extension = service->GetInstalledExtension(params->item_id);
  bool result = true;

  if (!extension) {
    result = false;
  } else if (!management_policy->UserMayModifySettings(extension, NULL)) {
    LOG(ERROR) << "Attempt to change allow file access of an extension that "
               << "non-usermanagable was made. Extension id : "
               << extension->id();
    result = false;
  } else {
    extension_util::SetAllowFileAccess(extension, service, params->allow);
    result = true;
  }

  return result;
}

DeveloperPrivateAllowFileAccessFunction::
    ~DeveloperPrivateAllowFileAccessFunction() {}

bool DeveloperPrivateAllowIncognitoFunction::RunImpl() {
  scoped_ptr<AllowIncognito::Params> params(
      AllowIncognito::Params::Create(*args_));
  EXTENSION_FUNCTION_VALIDATE(params.get());

  ExtensionService* service = GetProfile()->GetExtensionService();
  const Extension* extension = service->GetInstalledExtension(params->item_id);
  bool result = true;

  if (!extension)
    result = false;
  else
    extension_util::SetIsIncognitoEnabled(
        extension->id(),service, params->allow);

  return result;
}

DeveloperPrivateAllowIncognitoFunction::
    ~DeveloperPrivateAllowIncognitoFunction() {}


bool DeveloperPrivateReloadFunction::RunImpl() {
  scoped_ptr<Reload::Params> params(Reload::Params::Create(*args_));
  EXTENSION_FUNCTION_VALIDATE(params.get());

  ExtensionService* service = GetProfile()->GetExtensionService();
  CHECK(!params->item_id.empty());
  service->ReloadExtension(params->item_id);
  return true;
}

bool DeveloperPrivateShowPermissionsDialogFunction::RunImpl() {
  EXTENSION_FUNCTION_VALIDATE(args_->GetString(0, &extension_id_));
  ExtensionService* service = GetProfile()->GetExtensionService();
  CHECK(!extension_id_.empty());
  ShellWindowRegistry* registry = ShellWindowRegistry::Get(GetProfile());
  DCHECK(registry);
  ShellWindow* shell_window = registry->GetShellWindowForRenderViewHost(
      render_view_host());
  prompt_.reset(new ExtensionInstallPrompt(shell_window->web_contents()));
  const Extension* extension = service->GetInstalledExtension(extension_id_);

  if (!extension)
    return false;

  // Released by InstallUIAbort or InstallUIProceed.
  AddRef();
  std::vector<base::FilePath> retained_file_paths;
  if (extension->HasAPIPermission(extensions::APIPermission::kFileSystem)) {
    std::vector<apps::SavedFileEntry> retained_file_entries =
        apps::SavedFilesService::Get(GetProfile())
            ->GetAllFileEntries(extension_id_);
    for (size_t i = 0; i < retained_file_entries.size(); i++) {
      retained_file_paths.push_back(retained_file_entries[i].path);
    }
  }
  prompt_->ReviewPermissions(this, extension, retained_file_paths);
  return true;
}

DeveloperPrivateReloadFunction::~DeveloperPrivateReloadFunction() {}

// This is called when the user clicks "Revoke File Access."
void DeveloperPrivateShowPermissionsDialogFunction::InstallUIProceed() {
  apps::SavedFilesService::Get(GetProfile())
      ->ClearQueue(GetProfile()->GetExtensionService()->GetExtensionById(
            extension_id_, true));
  if (apps::AppRestoreService::Get(GetProfile())
          ->IsAppRestorable(extension_id_))
    apps::AppLoadService::Get(GetProfile())->RestartApplication(extension_id_);
  SendResponse(true);
  Release();
}

void DeveloperPrivateShowPermissionsDialogFunction::InstallUIAbort(
    bool user_initiated) {
  SendResponse(true);
  Release();
}

DeveloperPrivateShowPermissionsDialogFunction::
    DeveloperPrivateShowPermissionsDialogFunction() {}

DeveloperPrivateShowPermissionsDialogFunction::
    ~DeveloperPrivateShowPermissionsDialogFunction() {}

DeveloperPrivateEnableFunction::DeveloperPrivateEnableFunction() {}

bool DeveloperPrivateEnableFunction::RunImpl() {
  scoped_ptr<Enable::Params> params(Enable::Params::Create(*args_));
  EXTENSION_FUNCTION_VALIDATE(params.get());

  std::string extension_id = params->item_id;

  ExtensionSystem* system = ExtensionSystem::Get(GetProfile());
  ManagementPolicy* management_policy = system->management_policy();
  ExtensionService* service = GetProfile()->GetExtensionService();

  const Extension* extension = service->GetInstalledExtension(extension_id);
  if (!extension ||
      !management_policy->UserMayModifySettings(extension, NULL)) {
    LOG(ERROR) << "Attempt to enable an extension that is non-usermanagable "
               "was made. Extension id: " << extension_id.c_str();
    return false;
  }

  if (params->enable) {
    ExtensionPrefs* prefs = service->extension_prefs();
    if (prefs->DidExtensionEscalatePermissions(extension_id)) {
      ShellWindowRegistry* registry = ShellWindowRegistry::Get(GetProfile());
      CHECK(registry);
      ShellWindow* shell_window = registry->GetShellWindowForRenderViewHost(
          render_view_host());
      if (!shell_window) {
        return false;
      }

      ShowExtensionDisabledDialog(
          service, shell_window->web_contents(), extension);
    } else if ((prefs->GetDisableReasons(extension_id) &
                  Extension::DISABLE_UNSUPPORTED_REQUIREMENT) &&
               !requirements_checker_.get()) {
      // Recheck the requirements.
      scoped_refptr<const Extension> extension =
          service->GetExtensionById(extension_id,
                                     true );// include_disabled
      requirements_checker_.reset(new RequirementsChecker);
      // Released by OnRequirementsChecked.
      AddRef();
      requirements_checker_->Check(
          extension,
          base::Bind(&DeveloperPrivateEnableFunction::OnRequirementsChecked,
                     this, extension_id));
    } else {
      service->EnableExtension(extension_id);

      // Make sure any browser action contained within it is not hidden.
      ExtensionActionAPI::SetBrowserActionVisibility(
          prefs, extension->id(), true);
    }
  } else {
    service->DisableExtension(extension_id, Extension::DISABLE_USER_ACTION);
  }
  return true;
}

void DeveloperPrivateEnableFunction::OnRequirementsChecked(
    std::string extension_id,
    std::vector<std::string> requirements_errors) {
  if (requirements_errors.empty()) {
    ExtensionService* service = GetProfile()->GetExtensionService();
    service->EnableExtension(extension_id);
  } else {
    ExtensionErrorReporter::GetInstance()->ReportError(
        UTF8ToUTF16(JoinString(requirements_errors, ' ')),
        true /* be noisy */);
  }
  Release();
}

DeveloperPrivateEnableFunction::~DeveloperPrivateEnableFunction() {}

bool DeveloperPrivateInspectFunction::RunImpl() {
  scoped_ptr<developer::Inspect::Params> params(
      developer::Inspect::Params::Create(*args_));
  EXTENSION_FUNCTION_VALIDATE(params.get() != NULL);
  const developer::InspectOptions& options = params->options;

  int render_process_id;
  base::StringToInt(options.render_process_id, &render_process_id);

  if (render_process_id == -1) {
    // This is a lazy background page. Identify if it is a normal
    // or incognito background page.
    ExtensionService* service = GetProfile()->GetExtensionService();
    if (options.incognito)
      service = ExtensionSystem::Get(
          service->profile()->GetOffTheRecordProfile())->extension_service();
    const Extension* extension = service->extensions()->GetByID(
        options.extension_id);
    DCHECK(extension);
    // Wakes up the background page and  opens the inspect window.
    devtools_util::InspectBackgroundPage(extension, GetProfile());
    return false;
  }

  int render_view_id;
  base::StringToInt(options.render_view_id, &render_view_id);
  content::RenderViewHost* host = content::RenderViewHost::FromID(
      render_process_id, render_view_id);

  if (!host) {
    // This can happen if the host has gone away since the page was displayed.
    return false;
  }

  DevToolsWindow::OpenDevToolsWindow(host);
  return true;
}

DeveloperPrivateInspectFunction::~DeveloperPrivateInspectFunction() {}

bool DeveloperPrivateLoadUnpackedFunction::RunImpl() {
  string16 select_title =
      l10n_util::GetStringUTF16(IDS_EXTENSION_LOAD_FROM_DIRECTORY);

  // Balanced in FileSelected / FileSelectionCanceled.
  AddRef();
  bool result = ShowPicker(
      ui::SelectFileDialog::SELECT_FOLDER,
      DeveloperPrivateAPI::Get(GetProfile())->GetLastUnpackedDirectory(),
      select_title,
      ui::SelectFileDialog::FileTypeInfo(),
      0);
  return result;
}

void DeveloperPrivateLoadUnpackedFunction::FileSelected(
    const base::FilePath& path) {
  ExtensionService* service = GetProfile()->GetExtensionService();
  UnpackedInstaller::Create(service)->Load(path);
  DeveloperPrivateAPI::Get(GetProfile())->SetLastUnpackedDirectory(path);
  SendResponse(true);
  Release();
}

void DeveloperPrivateLoadUnpackedFunction::FileSelectionCanceled() {
  SendResponse(false);
  Release();
}

bool DeveloperPrivateChooseEntryFunction::ShowPicker(
    ui::SelectFileDialog::Type picker_type,
    const base::FilePath& last_directory,
    const string16& select_title,
    const ui::SelectFileDialog::FileTypeInfo& info,
    int file_type_index) {
  ShellWindowRegistry* registry = ShellWindowRegistry::Get(GetProfile());
  DCHECK(registry);
  ShellWindow* shell_window = registry->GetShellWindowForRenderViewHost(
      render_view_host());
  if (!shell_window) {
    return false;
  }

  // The entry picker will hold a reference to this function instance,
  // and subsequent sending of the function response) until the user has
  // selected a file or cancelled the picker. At that point, the picker will
  // delete itself.
  new EntryPicker(this, shell_window->web_contents(), picker_type,
  last_directory, select_title, info, file_type_index);
  return true;
}

bool DeveloperPrivateChooseEntryFunction::RunImpl() { return false; }

DeveloperPrivateChooseEntryFunction::~DeveloperPrivateChooseEntryFunction() {}

void DeveloperPrivatePackDirectoryFunction::OnPackSuccess(
    const base::FilePath& crx_file,
    const base::FilePath& pem_file) {
  developer::PackDirectoryResponse response;
  response.message =
      UTF16ToUTF8(PackExtensionJob::StandardSuccessMessage(crx_file, pem_file));
  response.status = developer::PACK_STATUS_SUCCESS;
  results_ = developer::PackDirectory::Results::Create(response);
  SendResponse(true);
  Release();
}

void DeveloperPrivatePackDirectoryFunction::OnPackFailure(
    const std::string& error,
    ExtensionCreator::ErrorType error_type) {
  developer::PackDirectoryResponse response;
  response.message = error;
  if (error_type == ExtensionCreator::kCRXExists) {
    response.item_path = item_path_str_;
    response.pem_path = key_path_str_;
    response.override_flags = ExtensionCreator::kOverwriteCRX;
    response.status = developer::PACK_STATUS_WARNING;
  } else {
    response.status = developer::PACK_STATUS_ERROR;
  }
  results_ = developer::PackDirectory::Results::Create(response);
  SendResponse(true);
  Release();
}

bool DeveloperPrivatePackDirectoryFunction::RunImpl() {
  scoped_ptr<PackDirectory::Params> params(
      PackDirectory::Params::Create(*args_));
  EXTENSION_FUNCTION_VALIDATE(params.get());

  int flags = params->flags;
  item_path_str_ = params->path;
  key_path_str_ = params->private_key_path;

  base::FilePath root_directory =
      base::FilePath::FromUTF8Unsafe(item_path_str_);

  base::FilePath key_file = base::FilePath::FromUTF8Unsafe(key_path_str_);

  developer::PackDirectoryResponse response;
  if (root_directory.empty()) {
    if (item_path_str_.empty())
      response.message = l10n_util::GetStringUTF8(
          IDS_EXTENSION_PACK_DIALOG_ERROR_ROOT_REQUIRED);
    else
      response.message = l10n_util::GetStringUTF8(
          IDS_EXTENSION_PACK_DIALOG_ERROR_ROOT_INVALID);

    response.status = developer::PACK_STATUS_ERROR;
    results_ = developer::PackDirectory::Results::Create(response);
    SendResponse(true);
    return true;
  }

  if (!key_path_str_.empty() && key_file.empty()) {
    response.message = l10n_util::GetStringUTF8(
        IDS_EXTENSION_PACK_DIALOG_ERROR_KEY_INVALID);
    response.status = developer::PACK_STATUS_ERROR;
    results_ = developer::PackDirectory::Results::Create(response);
    SendResponse(true);
    return true;
  }

  // Balanced in OnPackSuccess / OnPackFailure.
  AddRef();

  pack_job_ = new PackExtensionJob(this, root_directory, key_file, flags);
  pack_job_->Start();
  return true;
}

DeveloperPrivatePackDirectoryFunction::DeveloperPrivatePackDirectoryFunction()
{}

DeveloperPrivatePackDirectoryFunction::~DeveloperPrivatePackDirectoryFunction()
{}

DeveloperPrivateLoadUnpackedFunction::~DeveloperPrivateLoadUnpackedFunction() {}

bool DeveloperPrivateExportSyncfsFolderToLocalfsFunction::RunImpl() {
  // TODO(grv) : add unittests.
  base::FilePath::StringType project_name;
  EXTENSION_FUNCTION_VALIDATE(args_->GetString(0, &project_name));
  if (!ValidateFolderName(project_name)) {
    DLOG(INFO) << "Invalid project_name : [" << project_name << "]";
    return false;
  }

  context_ = content::BrowserContext::GetStoragePartition(
      GetProfile(), render_view_host()->GetSiteInstance())
                 ->GetFileSystemContext();

  base::FilePath project_path(GetProfile()->GetPath());
  project_path = project_path.Append(kUnpackedAppsFolder);
  project_path = project_path.Append(project_name);

  content::BrowserThread::PostTask(content::BrowserThread::FILE, FROM_HERE,
      base::Bind(&DeveloperPrivateExportSyncfsFolderToLocalfsFunction::
                     ClearPrexistingDirectoryContent,
                 this,
                 project_path));

  return true;
}

void DeveloperPrivateExportSyncfsFolderToLocalfsFunction::
    ClearPrexistingDirectoryContent(const base::FilePath& project_path) {

  // Clear the project directory before copying new files.
  base::DeleteFile(project_path, true/*recursive*/);

  pendingCopyOperationsCount_ = 1;

  content::BrowserThread::PostTask(content::BrowserThread::IO, FROM_HERE,
      base::Bind(&DeveloperPrivateExportSyncfsFolderToLocalfsFunction::
                 ReadSyncFileSystemDirectory,
                 this, project_path, project_path.BaseName()));
}

void DeveloperPrivateExportSyncfsFolderToLocalfsFunction::
    ReadSyncFileSystemDirectory(const base::FilePath& project_path,
                                const base::FilePath& destination_path) {
  std::string origin_url(
      Extension::GetBaseURLFromExtensionId(extension_id()).spec());
  fileapi::FileSystemURL url(sync_file_system::CreateSyncableFileSystemURL(
      GURL(origin_url),
      destination_path));

  context_->operation_runner()->ReadDirectory(
      url, base::Bind(&DeveloperPrivateExportSyncfsFolderToLocalfsFunction::
                      ReadSyncFileSystemDirectoryCb,
                      this, project_path, destination_path));
}

void DeveloperPrivateExportSyncfsFolderToLocalfsFunction::
    ReadSyncFileSystemDirectoryCb(
    const base::FilePath& project_path,
    const base::FilePath& destination_path,
    base::PlatformFileError status,
    const fileapi::FileSystemOperation::FileEntryList& file_list,
    bool has_more) {

  if (status != base::PLATFORM_FILE_OK) {
    DLOG(ERROR) << "Error in copying files from sync filesystem.";
    return;
  }

  // We add 1 to the pending copy operations for both files and directories. We
  // release the directory copy operation once all the files under the directory
  // are added for copying. We do that to ensure that pendingCopyOperationsCount
  // does not become zero before all copy operations are finished.
  // In case the directory happens to be executing the last copy operation it
  // will call SendResponse to send the response to the API. The pending copy
  // operations of files are released by the CopyFile function.
  pendingCopyOperationsCount_ += file_list.size();

  for (size_t i = 0; i < file_list.size(); ++i) {
    if (file_list[i].is_directory) {
      ReadSyncFileSystemDirectory(project_path.Append(file_list[i].name),
                                  destination_path.Append(file_list[i].name));
      continue;
    }

    std::string origin_url(
        Extension::GetBaseURLFromExtensionId(extension_id()).spec());
    fileapi::FileSystemURL url(sync_file_system::CreateSyncableFileSystemURL(
        GURL(origin_url),
        destination_path.Append(file_list[i].name)));
    base::FilePath target_path = project_path;
    target_path = target_path.Append(file_list[i].name);

    context_->operation_runner()->CreateSnapshotFile(
        url,
        base::Bind(
            &DeveloperPrivateExportSyncfsFolderToLocalfsFunction::
                SnapshotFileCallback,
            this,
            target_path));

  }

  // Directory copy operation released here.
  pendingCopyOperationsCount_--;

  if (!pendingCopyOperationsCount_) {
    content::BrowserThread::PostTask(content::BrowserThread::UI, FROM_HERE,
        base::Bind(&DeveloperPrivateExportSyncfsFolderToLocalfsFunction::
                       SendResponse,
                   this,
                   success_));
  }
}

void DeveloperPrivateExportSyncfsFolderToLocalfsFunction::SnapshotFileCallback(
    const base::FilePath& target_path,
    base::PlatformFileError result,
    const base::PlatformFileInfo& file_info,
    const base::FilePath& src_path,
    const scoped_refptr<webkit_blob::ShareableFileReference>& file_ref) {
  if (result != base::PLATFORM_FILE_OK) {
    SetError("Error in copying files from sync filesystem.");
    success_ = false;
    return;
  }

  content::BrowserThread::PostTask(content::BrowserThread::FILE, FROM_HERE,
      base::Bind(&DeveloperPrivateExportSyncfsFolderToLocalfsFunction::CopyFile,
                 this,
                 src_path,
                 target_path));
}

void DeveloperPrivateExportSyncfsFolderToLocalfsFunction::CopyFile(
    const base::FilePath& src_path,
    const base::FilePath& target_path) {
  if (!file_util::CreateDirectory(target_path.DirName())) {
    SetError("Error in copying files from sync filesystem.");
    success_ = false;
  }

  if (success_)
    base::CopyFile(src_path, target_path);

  CHECK(pendingCopyOperationsCount_ > 0);
  pendingCopyOperationsCount_--;

  if (!pendingCopyOperationsCount_) {
    content::BrowserThread::PostTask(content::BrowserThread::UI, FROM_HERE,
        base::Bind(&DeveloperPrivateExportSyncfsFolderToLocalfsFunction::
                       SendResponse,
                   this,
                   success_));
  }
}

DeveloperPrivateExportSyncfsFolderToLocalfsFunction::
    DeveloperPrivateExportSyncfsFolderToLocalfsFunction()
    : pendingCopyOperationsCount_(0), success_(true) {}

DeveloperPrivateExportSyncfsFolderToLocalfsFunction::
    ~DeveloperPrivateExportSyncfsFolderToLocalfsFunction() {}

bool DeveloperPrivateLoadProjectFunction::RunImpl() {
  // TODO(grv) : add unit tests.
  base::FilePath::StringType project_name;
  EXTENSION_FUNCTION_VALIDATE(args_->GetString(0, &project_name));
  if (!ValidateFolderName(project_name)) {
    DLOG(INFO) << "Invalid project_name : [" << project_name << "]";
    return false;
  }

  base::FilePath path(GetProfile()->GetPath());
  path = path.Append(kUnpackedAppsFolder);
  // TODO(grv) : Sanitize / check project_name.
  path = path.Append(project_name);
  ExtensionService* service = GetProfile()->GetExtensionService();
  UnpackedInstaller::Create(service)->Load(path);

  const ExtensionSet* extensions = service->extensions();
  // Released by GetUnpackedExtension.
  AddRef();
  content::BrowserThread::PostTask(content::BrowserThread::FILE, FROM_HERE,
      base::Bind(&DeveloperPrivateLoadProjectFunction::GetUnpackedExtension,
                 this, path, extensions));
  return true;
}

void DeveloperPrivateLoadProjectFunction::GetUnpackedExtension(
    const base::FilePath& path,
    const ExtensionSet* extensions) {
  const Extension* extension = GetExtensionByPath(extensions, path);
  bool success = true;
  if (extension) {
    SetResult(new base::StringValue(extension->id()));
  } else {
    SetError("unable to load the project");
    success = false;
  }
  content::BrowserThread::PostTask(content::BrowserThread::UI, FROM_HERE,
      base::Bind(&DeveloperPrivateLoadProjectFunction::SendResponse,
                 this,
                 success));
  Release();
}

DeveloperPrivateLoadProjectFunction::DeveloperPrivateLoadProjectFunction() {}

DeveloperPrivateLoadProjectFunction::~DeveloperPrivateLoadProjectFunction() {}

bool DeveloperPrivateChoosePathFunction::RunImpl() {

  scoped_ptr<developer::ChoosePath::Params> params(
      developer::ChoosePath::Params::Create(*args_));
  EXTENSION_FUNCTION_VALIDATE(params.get() != NULL);

  ui::SelectFileDialog::Type type = ui::SelectFileDialog::SELECT_FOLDER;
  ui::SelectFileDialog::FileTypeInfo info;
  if (params->select_type == developer::SELECT_TYPE_FILE) {
    type = ui::SelectFileDialog::SELECT_OPEN_FILE;
  }
  string16 select_title;

  int file_type_index = 0;
  if (params->file_type == developer::FILE_TYPE_LOAD)
    select_title = l10n_util::GetStringUTF16(IDS_EXTENSION_LOAD_FROM_DIRECTORY);
  else if (params->file_type== developer::FILE_TYPE_PEM) {
    select_title = l10n_util::GetStringUTF16(
        IDS_EXTENSION_PACK_DIALOG_SELECT_KEY);
    info.extensions.push_back(std::vector<base::FilePath::StringType>());
    info.extensions.front().push_back(FILE_PATH_LITERAL("pem"));
    info.extension_description_overrides.push_back(
        l10n_util::GetStringUTF16(
            IDS_EXTENSION_PACK_DIALOG_KEY_FILE_TYPE_DESCRIPTION));
    info.include_all_files = true;
    file_type_index = 1;
  } else {
    NOTREACHED();
  }

  // Balanced by FileSelected / FileSelectionCanceled.
  AddRef();
  bool result = ShowPicker(
      type,
      DeveloperPrivateAPI::Get(GetProfile())->GetLastUnpackedDirectory(),
      select_title,
      info,
      file_type_index);
  return result;
}

void DeveloperPrivateChoosePathFunction::FileSelected(
    const base::FilePath& path) {
  SetResult(new base::StringValue(UTF16ToUTF8(path.LossyDisplayName())));
  SendResponse(true);
  Release();
}

void DeveloperPrivateChoosePathFunction::FileSelectionCanceled() {
  SendResponse(false);
  Release();
}

DeveloperPrivateChoosePathFunction::~DeveloperPrivateChoosePathFunction() {}

bool DeveloperPrivateGetStringsFunction::RunImpl() {
  base::DictionaryValue* dict = new base::DictionaryValue();
  SetResult(dict);

  webui::SetFontAndTextDirection(dict);

  #define   SET_STRING(id, idr) \
    dict->SetString(id, l10n_util::GetStringUTF16(idr))
  SET_STRING("extensionSettings", IDS_MANAGE_EXTENSIONS_SETTING_WINDOWS_TITLE);

  SET_STRING("appsDevtoolSearch", IDS_APPS_DEVTOOL_SEARCH);
  SET_STRING("appsDevtoolApps", IDS_APPS_DEVTOOL_APPS_INSTALLED);
  SET_STRING("appsDevtoolExtensions", IDS_APPS_DEVTOOL_EXTENSIONS_INSTALLED);
  SET_STRING("appsDevtoolNoExtensions", IDS_EXTENSIONS_NONE_INSTALLED);
  SET_STRING("appsDevtoolUnpacked", IDS_APPS_DEVTOOL_UNPACKED_INSTALLED);
  SET_STRING("appsDevtoolInstalled", IDS_APPS_DEVTOOL_INSTALLED);
  SET_STRING("appsDevtoolNoPackedApps", IDS_APPS_DEVTOOL_NO_PACKED_APPS);
  SET_STRING("appsDevtoolNoUnpackedApps", IDS_APPS_DEVTOOL_NO_UNPACKED_APPS);
  SET_STRING("appsDevtoolNoPackedExtensions",
      IDS_APPS_DEVTOOL_NO_PACKED_EXTENSIONS);
  SET_STRING("appsDevtoolNoUnpackedExtensions",
      IDS_APPS_DEVTOOL_NO_UNPACKED_EXTENSIONS);
  SET_STRING("appsDevtoolUpdating", IDS_APPS_DEVTOOL_UPDATING);
  SET_STRING("extensionSettingsGetMoreExtensions", IDS_GET_MORE_EXTENSIONS);
  SET_STRING("extensionSettingsExtensionId", IDS_EXTENSIONS_ID);
  SET_STRING("extensionSettingsExtensionPath", IDS_EXTENSIONS_PATH);
  SET_STRING("extensionSettingsInspectViews", IDS_EXTENSIONS_INSPECT_VIEWS);
  SET_STRING("extensionSettingsInstallWarnings",
             IDS_EXTENSIONS_INSTALL_WARNINGS);
  SET_STRING("viewIncognito", IDS_EXTENSIONS_VIEW_INCOGNITO);
  SET_STRING("viewInactive", IDS_EXTENSIONS_VIEW_INACTIVE);
  SET_STRING("backgroundPage", IDS_EXTENSIONS_BACKGROUND_PAGE);
  SET_STRING("extensionSettingsEnable", IDS_EXTENSIONS_ENABLE);
  SET_STRING("extensionSettingsEnabled", IDS_EXTENSIONS_ENABLED);
  SET_STRING("extensionSettingsRemove", IDS_EXTENSIONS_REMOVE);
  SET_STRING("extensionSettingsEnableIncognito",
             IDS_EXTENSIONS_ENABLE_INCOGNITO);
  SET_STRING("extensionSettingsAllowFileAccess",
             IDS_EXTENSIONS_ALLOW_FILE_ACCESS);
  SET_STRING("extensionSettingsReloadTerminated",
             IDS_EXTENSIONS_RELOAD_TERMINATED);
  SET_STRING("extensionSettingsReloadUnpacked",
             IDS_APPS_DEV_TOOLS_RELOAD_UNPACKED);
  SET_STRING("extensionSettingsLaunch", IDS_EXTENSIONS_LAUNCH);
  SET_STRING("extensionSettingsOptions", IDS_EXTENSIONS_OPTIONS_LINK);
  SET_STRING("extensionSettingsPermissions", IDS_EXTENSIONS_PERMISSIONS_LINK);
  SET_STRING("extensionSettingsVisitWebsite", IDS_EXTENSIONS_VISIT_WEBSITE);
  SET_STRING("extensionSettingsVisitWebStore", IDS_EXTENSIONS_VISIT_WEBSTORE);
  SET_STRING("extensionSettingsPolicyControlled",
             IDS_EXTENSIONS_POLICY_CONTROLLED);
  SET_STRING("extensionSettingsManagedMode",
             IDS_EXTENSIONS_LOCKED_MANAGED_USER);
  SET_STRING("extensionSettingsShowButton", IDS_EXTENSIONS_SHOW_BUTTON);
  SET_STRING("appsDevtoolLoadUnpackedButton",
             IDS_APPS_DEVTOOL_LOAD_UNPACKED_BUTTON);
  SET_STRING("appsDevtoolPackButton", IDS_APPS_DEVTOOL_PACK_BUTTON);
  SET_STRING("extensionSettingsCommandsLink",
             IDS_EXTENSIONS_COMMANDS_CONFIGURE);
  SET_STRING("appsDevtoolUpdateButton", IDS_APPS_DEVTOOL_UPDATE_BUTTON);
  SET_STRING("extensionSettingsWarningsTitle", IDS_EXTENSION_WARNINGS_TITLE);
  SET_STRING("extensionSettingsShowDetails", IDS_EXTENSIONS_SHOW_DETAILS);
  SET_STRING("extensionSettingsHideDetails", IDS_EXTENSIONS_HIDE_DETAILS);
  SET_STRING("extensionUninstall", IDS_EXTENSIONS_UNINSTALL);
  SET_STRING("extensionsPermissionsHeading",
             IDS_EXTENSIONS_PERMISSIONS_HEADING);
  SET_STRING("extensionsPermissionsClose", IDS_EXTENSIONS_PERMISSIONS_CLOSE);
  SET_STRING("extensionDisabled", IDS_EXTENSIONS_DISABLED);
  SET_STRING("extensionSettingsShowLogsButton", IDS_EXTENSIONS_SHOW_LOGS);
  SET_STRING("extensionSettingsMoreDetailsButton", IDS_EXTENSIONS_MORE_DETAILS);
  SET_STRING("extensionSettingsVersion", IDS_EXTENSIONS_VERSION);
  SET_STRING("extensionSettingsDelete", IDS_EXTENSIONS_ADT_DELETE);
  SET_STRING("extensionSettingsPack", IDS_EXTENSIONS_PACK);

// Pack Extension strings
  SET_STRING("packExtensionOverlay", IDS_EXTENSION_PACK_DIALOG_TITLE);
  SET_STRING("packExtensionHeading", IDS_EXTENSION_ADT_PACK_DIALOG_HEADING);
  SET_STRING("packButton", IDS_EXTENSION_ADT_PACK_BUTTON);
  SET_STRING("ok", IDS_OK);
  SET_STRING("cancel", IDS_CANCEL);
  SET_STRING("packExtensionRootDir",
     IDS_EXTENSION_PACK_DIALOG_ROOT_DIRECTORY_LABEL);
  SET_STRING("packExtensionPrivateKey",
     IDS_EXTENSION_PACK_DIALOG_PRIVATE_KEY_LABEL);
  SET_STRING("packExtensionBrowseButton", IDS_EXTENSION_PACK_DIALOG_BROWSE);
  SET_STRING("packExtensionProceedAnyway", IDS_EXTENSION_PROCEED_ANYWAY);
  SET_STRING("packExtensionWarningTitle", IDS_EXTENSION_PACK_WARNING_TITLE);
  SET_STRING("packExtensionErrorTitle", IDS_EXTENSION_PACK_ERROR_TITLE);
  SET_STRING("packAppOverlay", IDS_EXTENSION_PACK_APP_DIALOG_TITLE);
  SET_STRING("packAppHeading", IDS_EXTENSION_ADT_PACK_APP_DIALOG_HEADING);

// Delete confirmation dialog.
  SET_STRING("deleteConfirmationDeleteButton",
      IDS_APPS_DEVTOOL_DELETE_CONFIRMATION_BUTTON);
  SET_STRING("deleteConfirmationTitle",
      IDS_APPS_DEVTOOL_DELETE_CONFIRMATION_TITLE);
  SET_STRING("deleteConfirmationMessageApp",
      IDS_APPS_DEVTOOL_DELETE_CONFIRMATION_MESSAGE_APP);
  SET_STRING("deleteConfirmationMessageExtension",
      IDS_APPS_DEVTOOL_DELETE_CONFIRMATION_MESSAGE_EXTENSION);

// Dialog when profile is managed.
  SET_STRING("managedProfileDialogCloseButton",
      IDS_APPS_DEVTOOL_MANAGED_PROFILE_DIALOG_CLOSE_BUTTON);
  SET_STRING("managedProfileDialogTitle",
      IDS_APPS_DEVTOOL_MANAGED_PROFILE_DIALOG_TITLE);
  SET_STRING("managedProfileDialogDescription",
      IDS_APPS_DEVTOOL_MANAGED_PROFILE_DIALOG_DESCRIPTION);

  #undef   SET_STRING
  return true;
}

DeveloperPrivateGetStringsFunction::~DeveloperPrivateGetStringsFunction() {}

bool DeveloperPrivateIsProfileManagedFunction::RunImpl() {
  SetResult(new base::FundamentalValue(GetProfile()->IsManaged()));
  return true;
}

DeveloperPrivateIsProfileManagedFunction::
    ~DeveloperPrivateIsProfileManagedFunction() {
}

} // namespace api

} // namespace extensions
