// 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 "extensions/browser/api/app_window/app_window_api.h"

#include <memory>
#include <utility>

#include "base/command_line.h"
#include "base/stl_util.h"
#include "base/strings/string_number_conversions.h"
#include "base/strings/string_util.h"
#include "base/time/time.h"
#include "base/values.h"
#include "build/build_config.h"
#include "content/public/browser/notification_registrar.h"
#include "content/public/browser/notification_types.h"
#include "content/public/browser/render_frame_host.h"
#include "content/public/browser/render_process_host.h"
#include "content/public/browser/web_contents.h"
#include "content/public/common/url_constants.h"
#include "extensions/browser/app_window/app_window.h"
#include "extensions/browser/app_window/app_window_client.h"
#include "extensions/browser/app_window/app_window_contents.h"
#include "extensions/browser/app_window/app_window_registry.h"
#include "extensions/browser/app_window/native_app_window.h"
#include "extensions/browser/extensions_browser_client.h"
#include "extensions/common/api/app_runtime.h"
#include "extensions/common/api/app_window.h"
#include "extensions/common/features/simple_feature.h"
#include "extensions/common/image_util.h"
#include "extensions/common/manifest.h"
#include "extensions/common/permissions/permissions_data.h"
#include "extensions/common/switches.h"
#include "third_party/skia/include/core/SkColor.h"
#include "ui/base/ui_base_types.h"
#include "ui/gfx/geometry/rect.h"
#include "url/gurl.h"

namespace app_window = extensions::api::app_window;
namespace Create = app_window::Create;

namespace extensions {

namespace app_window_constants {
constexpr char kInvalidWindowId[] =
    "The window id can not be more than 256 characters long.";
constexpr char kInvalidColorSpecification[] =
    "The color specification could not be parsed.";
constexpr char kColorWithFrameNone[] =
    "Windows with no frame cannot have a color.";
constexpr char kInactiveColorWithoutColor[] =
    "frame.inactiveColor must be used with frame.color.";
constexpr char kConflictingBoundsOptions[] =
    "The $1 property cannot be specified for both inner and outer bounds.";
constexpr char kAlwaysOnTopPermission[] =
    "The \"app.window.alwaysOnTop\" permission is required.";
constexpr char kInvalidUrlParameter[] =
    "The URL used for window creation must be local for security reasons.";
constexpr char kAlphaEnabledWrongChannel[] =
    "The alphaEnabled option requires dev channel or newer.";
constexpr char kAlphaEnabledMissingPermission[] =
    "The alphaEnabled option requires app.window.alpha permission.";
constexpr char kAlphaEnabledNeedsFrameNone[] =
    "The alphaEnabled option can only be used with \"frame: 'none'\".";
constexpr char kImeWindowMissingPermission[] =
    "Extensions require the \"app.window.ime\" permission to create windows.";
constexpr char kImeOptionIsNotSupported[] =
    "The \"ime\" option is not supported for platform app.";
#if !defined(OS_CHROMEOS)
constexpr char kImeWindowUnsupportedPlatform[] =
    "The \"ime\" option can only be used on ChromeOS.";
#else
constexpr char kImeWindowMustBeImeWindow[] =
    "IME extensions must create an IME window ( with \"ime: true\" and "
    "\"frame: 'none'\"). Panels are no longer supported for IME extensions.";
#endif
constexpr char kShowInShelfWindowKeyNotSet[] =
    "The \"showInShelf\" option requires the \"id\" option to be set.";
constexpr char kLockScreenActionRequiresLockScreenContext[] =
    "The lockScreenAction option requires lock screen app context.";
constexpr char kLockScreenActionRequiresLockScreenPermission[] =
    "The lockScreenAction option requires lockScreen permission.";
constexpr char kAppWindowCreationFailed[] = "Failed to create the app window.";
constexpr char kPrematureWindowClose[] =
    "App window is closed before ready to commit first navigation.";
}  // namespace app_window_constants

const char kNoneFrameOption[] = "none";

namespace {

// If the same property is specified for the inner and outer bounds, raise an
// error.
bool CheckBoundsConflict(const std::unique_ptr<int>& inner_property,
                         const std::unique_ptr<int>& outer_property,
                         const std::string& property_name,
                         std::string* error) {
  if (inner_property.get() && outer_property.get()) {
    std::vector<std::string> subst;
    subst.push_back(property_name);
    *error = base::ReplaceStringPlaceholders(
        app_window_constants::kConflictingBoundsOptions, subst, NULL);
    return false;
  }

  return true;
}

// Copy over the bounds specification properties from the API to the
// AppWindow::CreateParams.
void CopyBoundsSpec(const app_window::BoundsSpecification* input_spec,
                    AppWindow::BoundsSpecification* create_spec) {
  if (!input_spec)
    return;

  if (input_spec->left.get())
    create_spec->bounds.set_x(*input_spec->left);
  if (input_spec->top.get())
    create_spec->bounds.set_y(*input_spec->top);
  if (input_spec->width.get())
    create_spec->bounds.set_width(*input_spec->width);
  if (input_spec->height.get())
    create_spec->bounds.set_height(*input_spec->height);
  if (input_spec->min_width.get())
    create_spec->minimum_size.set_width(*input_spec->min_width);
  if (input_spec->min_height.get())
    create_spec->minimum_size.set_height(*input_spec->min_height);
  if (input_spec->max_width.get())
    create_spec->maximum_size.set_width(*input_spec->max_width);
  if (input_spec->max_height.get())
    create_spec->maximum_size.set_height(*input_spec->max_height);
}

}  // namespace

AppWindowCreateFunction::AppWindowCreateFunction() {}

ExtensionFunction::ResponseAction AppWindowCreateFunction::Run() {
  // Don't create app window if the system is shutting down.
  if (ExtensionsBrowserClient::Get()->IsShuttingDown())
    return RespondNow(Error(kUnknownErrorDoNotUse));

  std::unique_ptr<Create::Params> params(Create::Params::Create(*args_));
  EXTENSION_FUNCTION_VALIDATE(params.get());

  GURL url = extension()->GetResourceURL(params->url);
  // Allow absolute URLs for component apps, otherwise prepend the extension
  // path.
  // TODO(devlin): Investigate if this is still used. If not, kill it dead!
  GURL absolute = GURL(params->url);
  if (absolute.has_scheme()) {
    if (extension()->location() == Manifest::COMPONENT) {
      url = absolute;
    } else {
      // Show error when url passed isn't local.
      return RespondNow(Error(app_window_constants::kInvalidUrlParameter));
    }
  }

  // TODO(jeremya): figure out a way to pass the opening WebContents through to
  // AppWindow::Create so we can set the opener at create time rather than
  // with a hack in AppWindowCustomBindings::GetView().
  AppWindow::CreateParams create_params;
  app_window::CreateWindowOptions* options = params->options.get();
  if (options) {
    if (options->id.get()) {
      // TODO(mek): use URL if no id specified?
      // Limit length of id to 256 characters.
      if (options->id->length() > 256)
        return RespondNow(Error(app_window_constants::kInvalidWindowId));

      create_params.window_key = *options->id;

      if (options->singleton && *options->singleton == false) {
        WriteToConsole(
          content::CONSOLE_MESSAGE_LEVEL_WARNING,
          "The 'singleton' option in chrome.apps.window.create() is deprecated!"
          " Change your code to no longer rely on this.");
      }

      if (!options->singleton || *options->singleton) {
        AppWindow* existing_window =
            AppWindowRegistry::Get(browser_context())
                ->GetAppWindowForAppAndKey(extension_id(),
                                           create_params.window_key);
        if (existing_window) {
          content::RenderFrameHost* existing_frame =
              existing_window->web_contents()->GetMainFrame();
          int frame_id = MSG_ROUTING_NONE;
          if (render_frame_host()->GetProcess()->GetID() ==
              existing_frame->GetProcess()->GetID()) {
            frame_id = existing_frame->GetRoutingID();
          }

          if (!options->hidden.get() || !*options->hidden) {
            if (options->focused.get() && !*options->focused)
              existing_window->Show(AppWindow::SHOW_INACTIVE);
            else
              existing_window->Show(AppWindow::SHOW_ACTIVE);
          }

          std::unique_ptr<base::DictionaryValue> result(
              new base::DictionaryValue);
          result->SetInteger("frameId", frame_id);
          existing_window->GetSerializedState(result.get());
          result->SetBoolean("existingWindow", true);
          return RespondNow(OneArgument(std::move(result)));
        }
      }
    }

    std::string error;
    if (!GetBoundsSpec(*options, &create_params, &error))
      return RespondNow(Error(error));

    if (options->type == app_window::WINDOW_TYPE_PANEL) {
      WriteToConsole(content::CONSOLE_MESSAGE_LEVEL_WARNING,
                     "Panels are no longer supported.");
    }

    if (!GetFrameOptions(*options, &create_params, &error))
      return RespondNow(Error(error));

    if (extension()->GetType() == Manifest::TYPE_EXTENSION) {
      // Whitelisted IME extensions are allowed to use this API to create IME
      // specific windows to show accented characters or suggestions.
      if (!extension()->permissions_data()->HasAPIPermission(
              APIPermission::kImeWindowEnabled)) {
        return RespondNow(
            Error(app_window_constants::kImeWindowMissingPermission));
      }

#if !defined(OS_CHROMEOS)
      // IME window is only supported on ChromeOS.
      return RespondNow(
          Error(app_window_constants::kImeWindowUnsupportedPlatform));
#else
      // IME extensions must create ime window (with "ime: true" and
      // "frame: none").
      if (options->ime.get() && *options->ime.get() &&
          create_params.frame == AppWindow::FRAME_NONE) {
        create_params.is_ime_window = true;
      } else {
        return RespondNow(
            Error(app_window_constants::kImeWindowMustBeImeWindow));
      }
#endif  // OS_CHROMEOS
    } else {
      if (options->ime.get()) {
        return RespondNow(
            Error(app_window_constants::kImeOptionIsNotSupported));
      }
    }

    if (options->alpha_enabled.get()) {
      const char* const kWhitelist[] = {
#if defined(OS_CHROMEOS)
        "B58B99751225318C7EB8CF4688B5434661083E07",  // http://crbug.com/410550
        "06BE211D5F014BAB34BC22D9DDA09C63A81D828E",  // http://crbug.com/425539
        "F94EE6AB36D6C6588670B2B01EB65212D9C64E33",
        "B9EF10DDFEA11EF77873CC5009809E5037FC4C7A",  // http://crbug.com/435380
#endif
        "0F42756099D914A026DADFA182871C015735DD95",  // http://crbug.com/323773
        "2D22CDB6583FD0A13758AEBE8B15E45208B4E9A7",
        "E7E2461CE072DF036CF9592740196159E2D7C089",  // http://crbug.com/356200
        "A74A4D44C7CFCD8844830E6140C8D763E12DD8F3",
        "312745D9BF916161191143F6490085EEA0434997",
        "53041A2FA309EECED01FFC751E7399186E860B2C",
        "A07A5B743CD82A1C2579DB77D353C98A23201EEF",  // http://crbug.com/413748
        "F16F23C83C5F6DAD9B65A120448B34056DD80691",
        "0F585FB1D0FDFBEBCE1FEB5E9DFFB6DA476B8C9B"
      };
      if (AppWindowClient::Get()->IsCurrentChannelOlderThanDev() &&
          !SimpleFeature::IsIdInArray(extension_id(), kWhitelist,
                                      base::size(kWhitelist))) {
        return RespondNow(
            Error(app_window_constants::kAlphaEnabledWrongChannel));
      }
      if (!extension()->permissions_data()->HasAPIPermission(
              APIPermission::kAlphaEnabled)) {
        return RespondNow(
            Error(app_window_constants::kAlphaEnabledMissingPermission));
      }
      if (create_params.frame != AppWindow::FRAME_NONE) {
        return RespondNow(
            Error(app_window_constants::kAlphaEnabledNeedsFrameNone));
      }
#if defined(USE_AURA)
      create_params.alpha_enabled = *options->alpha_enabled;
#else
      // Transparency is only supported on Aura.
      // Fallback to creating an opaque window (by ignoring alphaEnabled).
#endif
    }

    if (options->hidden.get())
      create_params.hidden = *options->hidden;

    if (options->resizable.get())
      create_params.resizable = *options->resizable;

    if (options->always_on_top.get()) {
      create_params.always_on_top = *options->always_on_top;

      if (create_params.always_on_top &&
          !extension()->permissions_data()->HasAPIPermission(
              APIPermission::kAlwaysOnTopWindows)) {
        return RespondNow(Error(app_window_constants::kAlwaysOnTopPermission));
      }
    }

    if (options->focused.get())
      create_params.focused = *options->focused;

    if (options->visible_on_all_workspaces.get()) {
      create_params.visible_on_all_workspaces =
          *options->visible_on_all_workspaces;
    }

    if (options->show_in_shelf.get()) {
      create_params.show_in_shelf = *options->show_in_shelf.get();

      if (create_params.show_in_shelf && create_params.window_key.empty()) {
        return RespondNow(
            Error(app_window_constants::kShowInShelfWindowKeyNotSet));
      }
    }

    if (options->icon.get()) {
      // First, check if the window icon URL is a valid global URL.
      create_params.window_icon_url = GURL(*options->icon.get());

      // If the URL is not global, check for a valid extension local URL.
      if (!create_params.window_icon_url.is_valid()) {
        create_params.window_icon_url =
            extension()->GetResourceURL(*options->icon.get());
      }
    }

    switch (options->state) {
      case app_window::STATE_NONE:
      case app_window::STATE_NORMAL:
        break;
      case app_window::STATE_FULLSCREEN:
        create_params.state = ui::SHOW_STATE_FULLSCREEN;
        break;
      case app_window::STATE_MAXIMIZED:
        create_params.state = ui::SHOW_STATE_MAXIMIZED;
        break;
      case app_window::STATE_MINIMIZED:
        create_params.state = ui::SHOW_STATE_MINIMIZED;
        break;
    }
  }

  api::app_runtime::ActionType action_type = api::app_runtime::ACTION_TYPE_NONE;
  if (options &&
      options->lock_screen_action != api::app_runtime::ACTION_TYPE_NONE) {
    if (source_context_type() != Feature::LOCK_SCREEN_EXTENSION_CONTEXT) {
      return RespondNow(Error(
          app_window_constants::kLockScreenActionRequiresLockScreenContext));
    }

    if (!extension()->permissions_data()->HasAPIPermission(
            APIPermission::kLockScreen)) {
      return RespondNow(Error(
          app_window_constants::kLockScreenActionRequiresLockScreenPermission));
    }

    action_type = options->lock_screen_action;
    create_params.show_on_lock_screen = true;
  }

  create_params.creator_process_id =
      render_frame_host()->GetProcess()->GetID();

  AppWindow* app_window = nullptr;
  if (action_type == api::app_runtime::ACTION_TYPE_NONE) {
    app_window =
        AppWindowClient::Get()->CreateAppWindow(browser_context(), extension());
  } else {
    app_window = AppWindowClient::Get()->CreateAppWindowForLockScreenAction(
        browser_context(), extension(), action_type);
  }

  // App window client might refuse to create an app window, e.g. when the app
  // attempts to create a lock screen action handler window when the action was
  // not requested.
  if (!app_window)
    return RespondNow(Error(app_window_constants::kAppWindowCreationFailed));

  app_window->Init(url, new AppWindowContentsImpl(app_window),
                   render_frame_host(), create_params);

  if (ExtensionsBrowserClient::Get()->IsRunningInForcedAppMode() &&
      !app_window->is_ime_window()) {
    app_window->ForcedFullscreen();
  }

  content::RenderFrameHost* created_frame =
      app_window->web_contents()->GetMainFrame();
  int frame_id = MSG_ROUTING_NONE;
  if (create_params.creator_process_id == created_frame->GetProcess()->GetID())
    frame_id = created_frame->GetRoutingID();

  std::unique_ptr<base::DictionaryValue> result(new base::DictionaryValue);
  result->SetInteger("frameId", frame_id);
  result->SetString("id", app_window->window_key());
  app_window->GetSerializedState(result.get());
  ResponseValue result_arg = OneArgument(std::move(result));

  if (AppWindowRegistry::Get(browser_context())
          ->HadDevToolsAttached(app_window->web_contents())) {
    AppWindowClient::Get()->OpenDevToolsWindow(
        app_window->web_contents(),
        base::Bind(&AppWindowCreateFunction::Respond, this,
                   base::Passed(&result_arg)));
    // OpenDevToolsWindow might have already responded.
    return did_respond() ? AlreadyResponded() : RespondLater();
  }

  // Delay sending the response until the newly created window has been told to
  // navigate, and blink has been correctly initialized in the renderer.
  // SetOnFirstCommitOrWindowClosedCallback() will respond asynchronously.
  app_window->SetOnFirstCommitOrWindowClosedCallback(base::Bind(
      &AppWindowCreateFunction::OnAppWindowReadyToCommitFirstNavigationOrClosed,
      this, base::Passed(&result_arg)));
  return RespondLater();
}

void AppWindowCreateFunction::OnAppWindowReadyToCommitFirstNavigationOrClosed(
    ResponseValue result_arg,
    bool ready_to_commit) {
  DCHECK(!did_respond());

  if (!ready_to_commit) {
    Respond(Error(app_window_constants::kPrematureWindowClose));
    return;
  }

  Respond(std::move(result_arg));
}

bool AppWindowCreateFunction::GetBoundsSpec(
    const app_window::CreateWindowOptions& options,
    AppWindow::CreateParams* params,
    std::string* error) {
  DCHECK(params);
  DCHECK(error);

  if (options.inner_bounds.get() || options.outer_bounds.get()) {
    // Parse the inner and outer bounds specifications. If developers use the
    // new API, the deprecated fields will be ignored - do not attempt to merge
    // them.

    const app_window::BoundsSpecification* inner_bounds =
        options.inner_bounds.get();
    const app_window::BoundsSpecification* outer_bounds =
        options.outer_bounds.get();
    if (inner_bounds && outer_bounds) {
      if (!CheckBoundsConflict(
               inner_bounds->left, outer_bounds->left, "left", error)) {
        return false;
      }
      if (!CheckBoundsConflict(
               inner_bounds->top, outer_bounds->top, "top", error)) {
        return false;
      }
      if (!CheckBoundsConflict(
               inner_bounds->width, outer_bounds->width, "width", error)) {
        return false;
      }
      if (!CheckBoundsConflict(
               inner_bounds->height, outer_bounds->height, "height", error)) {
        return false;
      }
      if (!CheckBoundsConflict(inner_bounds->min_width,
                               outer_bounds->min_width,
                               "minWidth",
                               error)) {
        return false;
      }
      if (!CheckBoundsConflict(inner_bounds->min_height,
                               outer_bounds->min_height,
                               "minHeight",
                               error)) {
        return false;
      }
      if (!CheckBoundsConflict(inner_bounds->max_width,
                               outer_bounds->max_width,
                               "maxWidth",
                               error)) {
        return false;
      }
      if (!CheckBoundsConflict(inner_bounds->max_height,
                               outer_bounds->max_height,
                               "maxHeight",
                               error)) {
        return false;
      }
    }

    CopyBoundsSpec(inner_bounds, &(params->content_spec));
    CopyBoundsSpec(outer_bounds, &(params->window_spec));
  } else {
    // Parse deprecated fields.
    // Due to a bug in NativeAppWindow::GetFrameInsets() on Windows and ChromeOS
    // the bounds set the position of the window and the size of the content.
    // This will be preserved as apps may be relying on this behavior.

    if (options.default_width.get())
      params->content_spec.bounds.set_width(*options.default_width);
    if (options.default_height.get())
      params->content_spec.bounds.set_height(*options.default_height);
    if (options.default_left.get())
      params->window_spec.bounds.set_x(*options.default_left);
    if (options.default_top.get())
      params->window_spec.bounds.set_y(*options.default_top);

    if (options.width.get())
      params->content_spec.bounds.set_width(*options.width);
    if (options.height.get())
      params->content_spec.bounds.set_height(*options.height);
    if (options.left.get())
      params->window_spec.bounds.set_x(*options.left);
    if (options.top.get())
      params->window_spec.bounds.set_y(*options.top);

    if (options.bounds.get()) {
      app_window::ContentBounds* bounds = options.bounds.get();
      if (bounds->width.get())
        params->content_spec.bounds.set_width(*bounds->width);
      if (bounds->height.get())
        params->content_spec.bounds.set_height(*bounds->height);
      if (bounds->left.get())
        params->window_spec.bounds.set_x(*bounds->left);
      if (bounds->top.get())
        params->window_spec.bounds.set_y(*bounds->top);
    }

    gfx::Size& minimum_size = params->content_spec.minimum_size;
    if (options.min_width.get())
      minimum_size.set_width(*options.min_width);
    if (options.min_height.get())
      minimum_size.set_height(*options.min_height);
    gfx::Size& maximum_size = params->content_spec.maximum_size;
    if (options.max_width.get())
      maximum_size.set_width(*options.max_width);
    if (options.max_height.get())
      maximum_size.set_height(*options.max_height);
  }

  return true;
}

AppWindow::Frame AppWindowCreateFunction::GetFrameFromString(
    const std::string& frame_string) {
  if (frame_string == kNoneFrameOption)
    return AppWindow::FRAME_NONE;

  return AppWindow::FRAME_CHROME;
}

bool AppWindowCreateFunction::GetFrameOptions(
    const app_window::CreateWindowOptions& options,
    AppWindow::CreateParams* create_params,
    std::string* error) {
  if (!options.frame)
    return true;

  DCHECK(options.frame->as_string || options.frame->as_frame_options);
  if (options.frame->as_string) {
    create_params->frame = GetFrameFromString(*options.frame->as_string);
    return true;
  }

  if (options.frame->as_frame_options->type)
    create_params->frame =
        GetFrameFromString(*options.frame->as_frame_options->type);

  if (options.frame->as_frame_options->color.get()) {
    if (create_params->frame != AppWindow::FRAME_CHROME) {
      *error = app_window_constants::kColorWithFrameNone;
      return false;
    }

    if (!image_util::ParseHexColorString(
            *options.frame->as_frame_options->color,
            &create_params->active_frame_color)) {
      *error = app_window_constants::kInvalidColorSpecification;
      return false;
    }

    create_params->has_frame_color = true;
    create_params->inactive_frame_color = create_params->active_frame_color;

    if (options.frame->as_frame_options->inactive_color.get()) {
      if (!image_util::ParseHexColorString(
              *options.frame->as_frame_options->inactive_color,
              &create_params->inactive_frame_color)) {
        *error = app_window_constants::kInvalidColorSpecification;
        return false;
      }
    }

    return true;
  }

  if (options.frame->as_frame_options->inactive_color.get()) {
    *error = app_window_constants::kInactiveColorWithoutColor;
    return false;
  }

  return true;
}

}  // namespace extensions
