// Copyright 2014 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/app_window/app_window.h"

#include <stddef.h>

#include <algorithm>
#include <string>
#include <utility>
#include <vector>

#include "base/bind.h"
#include "base/metrics/histogram_macros.h"
#include "base/strings/string_util.h"
#include "base/strings/utf_string_conversions.h"
#include "base/task_runner.h"
#include "base/threading/thread_task_runner_handle.h"
#include "base/values.h"
#include "build/build_config.h"
#include "components/web_modal/web_contents_modal_dialog_manager.h"
#include "content/public/browser/browser_context.h"
#include "content/public/browser/file_select_listener.h"
#include "content/public/browser/invalidate_type.h"
#include "content/public/browser/keyboard_event_processing_result.h"
#include "content/public/browser/navigation_entry.h"
#include "content/public/browser/render_view_host.h"
#include "content/public/browser/render_widget_host.h"
#include "content/public/browser/resource_dispatcher_host.h"
#include "content/public/browser/web_contents.h"
#include "extensions/browser/app_window/app_delegate.h"
#include "extensions/browser/app_window/app_web_contents_helper.h"
#include "extensions/browser/app_window/app_window_client.h"
#include "extensions/browser/app_window/app_window_geometry_cache.h"
#include "extensions/browser/app_window/app_window_registry.h"
#include "extensions/browser/app_window/native_app_window.h"
#include "extensions/browser/app_window/size_constraints.h"
#include "extensions/browser/extension_registry.h"
#include "extensions/browser/extension_system.h"
#include "extensions/browser/extension_web_contents_observer.h"
#include "extensions/browser/extensions_browser_client.h"
#include "extensions/browser/notification_types.h"
#include "extensions/browser/process_manager.h"
#include "extensions/browser/suggest_permission_util.h"
#include "extensions/browser/view_type_utils.h"
#include "extensions/common/draggable_region.h"
#include "extensions/common/extension.h"
#include "extensions/common/extension_messages.h"
#include "extensions/common/manifest_handlers/icons_handler.h"
#include "extensions/common/permissions/permissions_data.h"
#include "ipc/ipc_message_macros.h"
#include "third_party/blink/public/common/mediastream/media_stream_request.h"
#include "third_party/skia/include/core/SkBitmap.h"
#include "third_party/skia/include/core/SkRegion.h"
#include "ui/display/display.h"
#include "ui/display/screen.h"
#include "ui/events/keycodes/keyboard_codes.h"

#if !defined(OS_MACOSX)
#include "components/prefs/pref_service.h"
#include "extensions/browser/pref_names.h"
#endif

using blink::mojom::ConsoleMessageLevel;
using content::BrowserContext;
using content::WebContents;
using web_modal::WebContentsModalDialogHost;
using web_modal::WebContentsModalDialogManager;

namespace extensions {

namespace {

const int kDefaultWidth = 512;
const int kDefaultHeight = 384;

void SetConstraintProperty(const std::string& name,
                           int value,
                           base::DictionaryValue* bounds_properties) {
  if (value != SizeConstraints::kUnboundedSize)
    bounds_properties->SetInteger(name, value);
  else
    bounds_properties->Set(name, std::make_unique<base::Value>());
}

void SetBoundsProperties(const gfx::Rect& bounds,
                         const gfx::Size& min_size,
                         const gfx::Size& max_size,
                         const std::string& bounds_name,
                         base::DictionaryValue* window_properties) {
  std::unique_ptr<base::DictionaryValue> bounds_properties(
      new base::DictionaryValue());

  bounds_properties->SetInteger("left", bounds.x());
  bounds_properties->SetInteger("top", bounds.y());
  bounds_properties->SetInteger("width", bounds.width());
  bounds_properties->SetInteger("height", bounds.height());

  SetConstraintProperty("minWidth", min_size.width(), bounds_properties.get());
  SetConstraintProperty(
      "minHeight", min_size.height(), bounds_properties.get());
  SetConstraintProperty("maxWidth", max_size.width(), bounds_properties.get());
  SetConstraintProperty(
      "maxHeight", max_size.height(), bounds_properties.get());

  window_properties->Set(bounds_name, std::move(bounds_properties));
}

// Combines the constraints of the content and window, and returns constraints
// for the window.
gfx::Size GetCombinedWindowConstraints(const gfx::Size& window_constraints,
                                       const gfx::Size& content_constraints,
                                       const gfx::Insets& frame_insets) {
  gfx::Size combined_constraints(window_constraints);
  if (content_constraints.width() > 0) {
    combined_constraints.set_width(
        content_constraints.width() + frame_insets.width());
  }
  if (content_constraints.height() > 0) {
    combined_constraints.set_height(
        content_constraints.height() + frame_insets.height());
  }
  return combined_constraints;
}

// Combines the constraints of the content and window, and returns constraints
// for the content.
gfx::Size GetCombinedContentConstraints(const gfx::Size& window_constraints,
                                        const gfx::Size& content_constraints,
                                        const gfx::Insets& frame_insets) {
  gfx::Size combined_constraints(content_constraints);
  if (window_constraints.width() > 0) {
    combined_constraints.set_width(
        std::max(0, window_constraints.width() - frame_insets.width()));
  }
  if (window_constraints.height() > 0) {
    combined_constraints.set_height(
        std::max(0, window_constraints.height() - frame_insets.height()));
  }
  return combined_constraints;
}

}  // namespace

// AppWindow::BoundsSpecification

const int AppWindow::BoundsSpecification::kUnspecifiedPosition = INT_MIN;

AppWindow::BoundsSpecification::BoundsSpecification()
    : bounds(kUnspecifiedPosition, kUnspecifiedPosition, 0, 0) {}

AppWindow::BoundsSpecification::~BoundsSpecification() {}

void AppWindow::BoundsSpecification::ResetBounds() {
  bounds.SetRect(kUnspecifiedPosition, kUnspecifiedPosition, 0, 0);
}

// AppWindow::CreateParams

AppWindow::CreateParams::CreateParams()
    : window_type(AppWindow::WINDOW_TYPE_DEFAULT),
      frame(AppWindow::FRAME_CHROME),
      has_frame_color(false),
      active_frame_color(SK_ColorBLACK),
      inactive_frame_color(SK_ColorBLACK),
      alpha_enabled(false),
      is_ime_window(false),
      creator_process_id(0),
      state(ui::SHOW_STATE_DEFAULT),
      hidden(false),
      resizable(true),
      focused(true),
      always_on_top(false),
      visible_on_all_workspaces(false),
      show_on_lock_screen(false),
      show_in_shelf(false) {}

AppWindow::CreateParams::CreateParams(const CreateParams& other) = default;

AppWindow::CreateParams::~CreateParams() {}

gfx::Rect AppWindow::CreateParams::GetInitialWindowBounds(
    const gfx::Insets& frame_insets) const {
  // Combine into a single window bounds.
  gfx::Rect combined_bounds(window_spec.bounds);
  if (content_spec.bounds.x() != BoundsSpecification::kUnspecifiedPosition)
    combined_bounds.set_x(content_spec.bounds.x() - frame_insets.left());
  if (content_spec.bounds.y() != BoundsSpecification::kUnspecifiedPosition)
    combined_bounds.set_y(content_spec.bounds.y() - frame_insets.top());
  if (content_spec.bounds.width() > 0) {
    combined_bounds.set_width(
        content_spec.bounds.width() + frame_insets.width());
  }
  if (content_spec.bounds.height() > 0) {
    combined_bounds.set_height(
        content_spec.bounds.height() + frame_insets.height());
  }

  // Constrain the bounds.
  SizeConstraints constraints(
      GetCombinedWindowConstraints(
          window_spec.minimum_size, content_spec.minimum_size, frame_insets),
      GetCombinedWindowConstraints(
          window_spec.maximum_size, content_spec.maximum_size, frame_insets));
  combined_bounds.set_size(constraints.ClampSize(combined_bounds.size()));

  return combined_bounds;
}

gfx::Size AppWindow::CreateParams::GetContentMinimumSize(
    const gfx::Insets& frame_insets) const {
  return GetCombinedContentConstraints(window_spec.minimum_size,
                                       content_spec.minimum_size,
                                       frame_insets);
}

gfx::Size AppWindow::CreateParams::GetContentMaximumSize(
    const gfx::Insets& frame_insets) const {
  return GetCombinedContentConstraints(window_spec.maximum_size,
                                       content_spec.maximum_size,
                                       frame_insets);
}

gfx::Size AppWindow::CreateParams::GetWindowMinimumSize(
    const gfx::Insets& frame_insets) const {
  return GetCombinedWindowConstraints(window_spec.minimum_size,
                                      content_spec.minimum_size,
                                      frame_insets);
}

gfx::Size AppWindow::CreateParams::GetWindowMaximumSize(
    const gfx::Insets& frame_insets) const {
  return GetCombinedWindowConstraints(window_spec.maximum_size,
                                      content_spec.maximum_size,
                                      frame_insets);
}

// AppWindow

AppWindow::AppWindow(BrowserContext* context,
                     AppDelegate* app_delegate,
                     const Extension* extension)
    : browser_context_(context),
      extension_id_(extension->id()),
      session_id_(SessionID::NewUnique()),
      app_delegate_(app_delegate),
      image_loader_ptr_factory_(this) {
  ExtensionsBrowserClient* client = ExtensionsBrowserClient::Get();
  CHECK(!client->IsGuestSession(context) || context->IsOffTheRecord())
      << "Only off the record window may be opened in the guest mode.";
}

void AppWindow::Init(const GURL& url,
                     AppWindowContents* app_window_contents,
                     content::RenderFrameHost* creator_frame,
                     const CreateParams& params) {
  // Initialize the render interface and web contents
  app_window_contents_.reset(app_window_contents);
  app_window_contents_->Initialize(browser_context(), creator_frame, url);

  initial_url_ = url;

  content::WebContentsObserver::Observe(web_contents());
  SetViewType(web_contents(), VIEW_TYPE_APP_WINDOW);
  app_delegate_->InitWebContents(web_contents());

  ExtensionWebContentsObserver::GetForWebContents(web_contents())->
      dispatcher()->set_delegate(this);

  WebContentsModalDialogManager::CreateForWebContents(web_contents());

  web_contents()->SetDelegate(this);
  WebContentsModalDialogManager::FromWebContents(web_contents())
      ->SetDelegate(this);

  // Initialize the window
  CreateParams new_params = LoadDefaults(params);
  window_type_ = new_params.window_type;
  UMA_HISTOGRAM_ENUMERATION("Apps.Window.Type", new_params.window_type,
                            WINDOW_TYPE_COUNT);

  window_key_ = new_params.window_key;

  // Windows cannot be always-on-top in fullscreen mode for security reasons.
  cached_always_on_top_ = new_params.always_on_top;
  if (new_params.state == ui::SHOW_STATE_FULLSCREEN &&
      !ExtensionsBrowserClient::Get()->IsScreensaverInDemoMode(
          extension_id())) {
    new_params.always_on_top = false;
  }

  requested_alpha_enabled_ = new_params.alpha_enabled;
  is_ime_window_ = params.is_ime_window;
  show_on_lock_screen_ = params.show_on_lock_screen;
  show_in_shelf_ = params.show_in_shelf;

  AppWindowClient* app_window_client = AppWindowClient::Get();
  native_app_window_.reset(
      app_window_client->CreateNativeAppWindow(this, &new_params));

  helper_.reset(new AppWebContentsHelper(
      browser_context_, extension_id_, web_contents(), app_delegate_.get()));

  native_app_window_->UpdateWindowIcon();

  if (params.window_icon_url.is_valid())
    SetAppIconUrl(params.window_icon_url);

  AppWindowRegistry::Get(browser_context_)->AddAppWindow(this);

  if (new_params.hidden) {
    // Although the window starts hidden by default, calling Hide() here
    // notifies observers of the window being hidden.
    Hide();
  } else {
    Show(SHOW_INACTIVE);

    // These states may cause the window to show, so they are ignored if the
    // window is initially hidden.
    if (new_params.state == ui::SHOW_STATE_FULLSCREEN)
      Fullscreen();
    else if (new_params.state == ui::SHOW_STATE_MAXIMIZED)
      Maximize();
    else if (new_params.state == ui::SHOW_STATE_MINIMIZED)
      Minimize();

    Show(new_params.focused ? SHOW_ACTIVE : SHOW_INACTIVE);
  }

  OnNativeWindowChanged();

  ExtensionRegistry::Get(browser_context_)->AddObserver(this);

  // Close when the browser process is exiting.
  app_delegate_->SetTerminatingCallback(
      base::Bind(&NativeAppWindow::Close,
                 base::Unretained(native_app_window_.get())));

  app_window_contents_->LoadContents(new_params.creator_process_id);
}

AppWindow::~AppWindow() {
  ExtensionRegistry::Get(browser_context_)->RemoveObserver(this);
}

void AppWindow::RequestMediaAccessPermission(
    content::WebContents* web_contents,
    const content::MediaStreamRequest& request,
    content::MediaResponseCallback callback) {
  DCHECK_EQ(AppWindow::web_contents(), web_contents);
  helper_->RequestMediaAccessPermission(request, std::move(callback));
}

bool AppWindow::CheckMediaAccessPermission(
    content::RenderFrameHost* render_frame_host,
    const GURL& security_origin,
    blink::MediaStreamType type) {
  DCHECK_EQ(web_contents(),
            content::WebContents::FromRenderFrameHost(render_frame_host)
                ->GetOutermostWebContents());
  return helper_->CheckMediaAccessPermission(render_frame_host, security_origin,
                                             type);
}

WebContents* AppWindow::OpenURLFromTab(WebContents* source,
                                       const content::OpenURLParams& params) {
  DCHECK_EQ(web_contents(), source);
  return helper_->OpenURLFromTab(params);
}

void AppWindow::AddNewContents(WebContents* source,
                               std::unique_ptr<WebContents> new_contents,
                               WindowOpenDisposition disposition,
                               const gfx::Rect& initial_rect,
                               bool user_gesture,
                               bool* was_blocked) {
  DCHECK(new_contents->GetBrowserContext() == browser_context_);
  app_delegate_->AddNewContents(browser_context_, std::move(new_contents),
                                disposition, initial_rect, user_gesture);
}

content::KeyboardEventProcessingResult AppWindow::PreHandleKeyboardEvent(
    content::WebContents* source,
    const content::NativeWebKeyboardEvent& event) {
  const Extension* extension = GetExtension();
  if (!extension)
    return content::KeyboardEventProcessingResult::NOT_HANDLED;

  // Here, we can handle a key event before the content gets it. When we are
  // fullscreen and it is not forced, we want to allow the user to leave
  // when ESC is pressed.
  // However, if the application has the "overrideEscFullscreen" permission, we
  // should let it override that behavior.
  // ::HandleKeyboardEvent() will only be called if the KeyEvent's default
  // action is not prevented.
  // Thus, we should handle the KeyEvent here only if the permission is not set.
  if (event.windows_key_code == ui::VKEY_ESCAPE && IsFullscreen() &&
      !IsForcedFullscreen() &&
      !extension->permissions_data()->HasAPIPermission(
          APIPermission::kOverrideEscFullscreen)) {
    Restore();
    return content::KeyboardEventProcessingResult::HANDLED;
  }

  return content::KeyboardEventProcessingResult::NOT_HANDLED;
}

bool AppWindow::HandleKeyboardEvent(
    WebContents* source,
    const content::NativeWebKeyboardEvent& event) {
  // If the window is currently fullscreen and not forced, ESC should leave
  // fullscreen.  If this code is being called for ESC, that means that the
  // KeyEvent's default behavior was not prevented by the content.
  if (event.windows_key_code == ui::VKEY_ESCAPE && IsFullscreen() &&
      !IsForcedFullscreen()) {
    Restore();
    return true;
  }

  return native_app_window_->HandleKeyboardEvent(event);
}

void AppWindow::RequestToLockMouse(WebContents* web_contents,
                                   bool user_gesture,
                                   bool last_unlocked_by_target) {
  DCHECK_EQ(AppWindow::web_contents(), web_contents);
  helper_->RequestToLockMouse();
}

bool AppWindow::PreHandleGestureEvent(WebContents* source,
                                      const blink::WebGestureEvent& event) {
  return AppWebContentsHelper::ShouldSuppressGestureEvent(event);
}

std::unique_ptr<content::BluetoothChooser> AppWindow::RunBluetoothChooser(
    content::RenderFrameHost* frame,
    const content::BluetoothChooser::EventHandler& event_handler) {
  return ExtensionsBrowserClient::Get()->CreateBluetoothChooser(frame,
                                                                event_handler);
}

bool AppWindow::TakeFocus(WebContents* source, bool reverse) {
  return app_delegate_->TakeFocus(source, reverse);
}

gfx::Size AppWindow::EnterPictureInPicture(content::WebContents* web_contents,
                                           const viz::SurfaceId& surface_id,
                                           const gfx::Size& natural_size) {
  return app_delegate_->EnterPictureInPicture(web_contents, surface_id,
                                              natural_size);
}

void AppWindow::ExitPictureInPicture() {
  app_delegate_->ExitPictureInPicture();
}

bool AppWindow::OnMessageReceived(const IPC::Message& message,
                                  content::RenderFrameHost* render_frame_host) {
  bool handled = true;
  IPC_BEGIN_MESSAGE_MAP(AppWindow, message)
    IPC_MESSAGE_HANDLER(ExtensionHostMsg_AppWindowReady, OnAppWindowReady)
    IPC_MESSAGE_UNHANDLED(handled = false)
  IPC_END_MESSAGE_MAP()
  return handled;
}

void AppWindow::RenderViewCreated(content::RenderViewHost* render_view_host) {
  app_delegate_->RenderViewCreated(render_view_host);
}

void AppWindow::SetOnFirstCommitOrWindowClosedCallback(
    FirstCommitOrWindowClosedCallback callback) {
  DCHECK(on_first_commit_or_window_closed_callback_.is_null());
  on_first_commit_or_window_closed_callback_ = std::move(callback);
}

void AppWindow::OnReadyToCommitFirstNavigation() {
  // Execute renderer-side setup now that there is a renderer process assigned
  // to the navigation. We must wait until this point in time in the navigation.
  if (on_first_commit_or_window_closed_callback_.is_null())
    return;
  // It is important that the callback executes after the calls to
  // WebContentsObserver::ReadyToCommitNavigation have been processed. The
  // CommitNavigation IPC that will properly set up the renderer will only be
  // sent after these, and it must be sent before the callback gets to run,
  // hence the use of PostTask.
  base::ThreadTaskRunnerHandle::Get()->PostTask(
      FROM_HERE,
      base::BindOnce(std::move(on_first_commit_or_window_closed_callback_),
                     true /* ready_to_commit */));
}

void AppWindow::OnNativeClose() {
  AppWindowRegistry::Get(browser_context_)->RemoveAppWindow(this);

  // Dispatch "OnClosed" event by default.
  bool send_onclosed = true;

  // Run pending |on_first_commit_or_window_closed_callback_| so that
  // AppWindowCreateFunction can respond with an error properly.
  if (!on_first_commit_or_window_closed_callback_.is_null()) {
    std::move(on_first_commit_or_window_closed_callback_)
        .Run(false /* ready_to_commit */);

    send_onclosed = false;  // No "OnClosed" event on window creation error.
  }

  if (app_window_contents_) {
    WebContentsModalDialogManager* modal_dialog_manager =
        WebContentsModalDialogManager::FromWebContents(web_contents());
    if (modal_dialog_manager)  // May be null in unit tests.
      modal_dialog_manager->SetDelegate(nullptr);
    app_window_contents_->NativeWindowClosed(send_onclosed);
  }

  delete this;
}

void AppWindow::OnNativeWindowChanged() {
  // This may be called during Init before |native_app_window_| is set.
  if (!native_app_window_)
    return;

#if defined(OS_MACOSX)
  // On Mac the user can change the window's fullscreen state. If that has
  // happened, update AppWindow's internal state.
  if (native_app_window_->IsFullscreen()) {
    if (!IsFullscreen())
      fullscreen_types_ = FULLSCREEN_TYPE_OS;
  } else {
    fullscreen_types_ = FULLSCREEN_TYPE_NONE;
  }

  RestoreAlwaysOnTop();  // Same as in SetNativeWindowFullscreen.
#endif

  SaveWindowPosition();

#if defined(OS_WIN)
  if (cached_always_on_top_ && !IsFullscreen() &&
      !native_app_window_->IsMaximized() &&
      !native_app_window_->IsMinimized()) {
    UpdateNativeAlwaysOnTop();
  }
#endif

  if (app_window_contents_)
    app_window_contents_->NativeWindowChanged(native_app_window_.get());
}

void AppWindow::OnNativeWindowActivated() {
  AppWindowRegistry::Get(browser_context_)->AppWindowActivated(this);
}

content::WebContents* AppWindow::web_contents() const {
  if (app_window_contents_)
    return app_window_contents_->GetWebContents();
  return nullptr;
}

const Extension* AppWindow::GetExtension() const {
  return ExtensionRegistry::Get(browser_context_)
      ->enabled_extensions()
      .GetByID(extension_id_);
}

NativeAppWindow* AppWindow::GetBaseWindow() { return native_app_window_.get(); }

gfx::NativeWindow AppWindow::GetNativeWindow() {
  return GetBaseWindow()->GetNativeWindow();
}

gfx::Rect AppWindow::GetClientBounds() const {
  gfx::Rect bounds = native_app_window_->GetBounds();
  bounds.Inset(native_app_window_->GetFrameInsets());
  return bounds;
}

base::string16 AppWindow::GetTitle() const {
  const Extension* extension = GetExtension();
  if (!extension)
    return base::string16();

  // WebContents::GetTitle() will return the page's URL if there's no <title>
  // specified. However, we'd prefer to show the name of the extension in that
  // case, so we directly inspect the NavigationEntry's title.
  base::string16 title;
  content::NavigationEntry* entry = web_contents() ?
      web_contents()->GetController().GetLastCommittedEntry() : nullptr;
  if (!entry || entry->GetTitle().empty()) {
    title = base::UTF8ToUTF16(extension->name());
  } else {
    title = web_contents()->GetTitle();
  }
  base::RemoveChars(title, base::ASCIIToUTF16("\n"), &title);
  return title;
}

void AppWindow::SetAppIconUrl(const GURL& url) {
  app_icon_url_ = url;

  // Don't start custom app icon loading in the case window is not ready yet.
  // see crbug.com/788531.
  if (!window_ready_)
    return;

  StartAppIconDownload();
}

void AppWindow::UpdateShape(std::unique_ptr<ShapeRects> rects) {
  native_app_window_->UpdateShape(std::move(rects));
}

void AppWindow::UpdateDraggableRegions(
    const std::vector<DraggableRegion>& regions) {
  native_app_window_->UpdateDraggableRegions(regions);
}

void AppWindow::UpdateAppIcon(const gfx::Image& image) {
  if (image.IsEmpty())
    return;
  custom_app_icon_ = image;
  native_app_window_->UpdateWindowIcon();
}

void AppWindow::SetFullscreen(FullscreenType type, bool enable) {
  DCHECK_NE(FULLSCREEN_TYPE_NONE, type);

  if (enable) {
#if !defined(OS_MACOSX)
    // Do not enter fullscreen mode if disallowed by pref.
    // TODO(bartfab): Add a test once it becomes possible to simulate a user
    // gesture. http://crbug.com/174178
    if (type != FULLSCREEN_TYPE_FORCED) {
      PrefService* prefs =
          ExtensionsBrowserClient::Get()->GetPrefServiceForContext(
              browser_context());
      if (!prefs->GetBoolean(pref_names::kAppFullscreenAllowed))
        return;
    }
#endif
    fullscreen_types_ |= type;
  } else {
    fullscreen_types_ &= ~type;
  }
  SetNativeWindowFullscreen();
}

bool AppWindow::IsFullscreen() const {
  return fullscreen_types_ != FULLSCREEN_TYPE_NONE;
}

bool AppWindow::IsForcedFullscreen() const {
  return (fullscreen_types_ & FULLSCREEN_TYPE_FORCED) != 0;
}

bool AppWindow::IsHtmlApiFullscreen() const {
  return (fullscreen_types_ & FULLSCREEN_TYPE_HTML_API) != 0;
}

bool AppWindow::IsOsFullscreen() const {
  return (fullscreen_types_ & FULLSCREEN_TYPE_OS) != 0;
}

void AppWindow::Fullscreen() {
  SetFullscreen(FULLSCREEN_TYPE_WINDOW_API, true);
}

void AppWindow::Maximize() { GetBaseWindow()->Maximize(); }

void AppWindow::Minimize() { GetBaseWindow()->Minimize(); }

void AppWindow::Restore() {
  if (IsFullscreen()) {
    fullscreen_types_ = FULLSCREEN_TYPE_NONE;
    SetNativeWindowFullscreen();
  } else {
    GetBaseWindow()->Restore();
  }
}

void AppWindow::OSFullscreen() {
  SetFullscreen(FULLSCREEN_TYPE_OS, true);
}

void AppWindow::ForcedFullscreen() {
  SetFullscreen(FULLSCREEN_TYPE_FORCED, true);
}

void AppWindow::SetContentSizeConstraints(const gfx::Size& min_size,
                                          const gfx::Size& max_size) {
  SizeConstraints constraints(min_size, max_size);
  native_app_window_->SetContentSizeConstraints(constraints.GetMinimumSize(),
                                                constraints.GetMaximumSize());

  gfx::Rect bounds = GetClientBounds();
  gfx::Size constrained_size = constraints.ClampSize(bounds.size());
  if (bounds.size() != constrained_size) {
    bounds.set_size(constrained_size);
    bounds.Inset(-native_app_window_->GetFrameInsets());
    native_app_window_->SetBounds(bounds);
  }
  OnNativeWindowChanged();
}

void AppWindow::Show(ShowType show_type) {
  app_delegate_->OnShow();
  bool was_hidden = is_hidden_ || !has_been_shown_;
  is_hidden_ = false;

  switch (show_type) {
    case SHOW_ACTIVE:
      GetBaseWindow()->Show();
      break;
    case SHOW_INACTIVE:
      GetBaseWindow()->ShowInactive();
      break;
  }
  AppWindowRegistry::Get(browser_context_)->AppWindowShown(this, was_hidden);
  has_been_shown_ = true;
}

void AppWindow::Hide() {
  is_hidden_ = true;
  GetBaseWindow()->Hide();
  AppWindowRegistry::Get(browser_context_)->AppWindowHidden(this);
  app_delegate_->OnHide();
}

void AppWindow::SetAlwaysOnTop(bool always_on_top) {
  if (cached_always_on_top_ == always_on_top)
    return;

  cached_always_on_top_ = always_on_top;

  // As a security measure, do not allow fullscreen windows or windows that
  // overlap the taskbar to be on top. The property will be applied when the
  // window exits fullscreen and moves away from the taskbar.
  if ((!IsFullscreen() ||
       ExtensionsBrowserClient::Get()->IsScreensaverInDemoMode(
           extension_id())) &&
      !IntersectsWithTaskbar()) {
    native_app_window_->SetAlwaysOnTop(always_on_top);
  }

  OnNativeWindowChanged();
}

bool AppWindow::IsAlwaysOnTop() const { return cached_always_on_top_; }

void AppWindow::RestoreAlwaysOnTop() {
  if (cached_always_on_top_)
    UpdateNativeAlwaysOnTop();
}

void AppWindow::GetSerializedState(base::DictionaryValue* properties) const {
  DCHECK(properties);

  properties->SetBoolean("fullscreen",
                         native_app_window_->IsFullscreenOrPending());
  properties->SetBoolean("minimized", native_app_window_->IsMinimized());
  properties->SetBoolean("maximized", native_app_window_->IsMaximized());
  properties->SetBoolean("alwaysOnTop", IsAlwaysOnTop());
  properties->SetBoolean("hasFrameColor", native_app_window_->HasFrameColor());
  properties->SetBoolean(
      "alphaEnabled",
      requested_alpha_enabled_ && native_app_window_->CanHaveAlphaEnabled());

  // These properties are undocumented and are to enable testing. Alpha is
  // removed to
  // make the values easier to check.
  SkColor transparent_white = ~SK_ColorBLACK;
  properties->SetInteger(
      "activeFrameColor",
      native_app_window_->ActiveFrameColor() & transparent_white);
  properties->SetInteger(
      "inactiveFrameColor",
      native_app_window_->InactiveFrameColor() & transparent_white);

  gfx::Rect content_bounds = GetClientBounds();
  gfx::Size content_min_size = native_app_window_->GetContentMinimumSize();
  gfx::Size content_max_size = native_app_window_->GetContentMaximumSize();
  SetBoundsProperties(content_bounds,
                      content_min_size,
                      content_max_size,
                      "innerBounds",
                      properties);

  gfx::Insets frame_insets = native_app_window_->GetFrameInsets();
  gfx::Rect frame_bounds = native_app_window_->GetBounds();
  gfx::Size frame_min_size = SizeConstraints::AddFrameToConstraints(
      content_min_size, frame_insets);
  gfx::Size frame_max_size = SizeConstraints::AddFrameToConstraints(
      content_max_size, frame_insets);
  SetBoundsProperties(frame_bounds,
                      frame_min_size,
                      frame_max_size,
                      "outerBounds",
                      properties);
}

//------------------------------------------------------------------------------
// Private methods
void AppWindow::StartAppIconDownload() {
  DCHECK(app_icon_url_.is_valid());

  // Avoid using any previous icons that were being downloaded.
  image_loader_ptr_factory_.InvalidateWeakPtrs();
  web_contents()->DownloadImage(
      app_icon_url_,
      true,   // is a favicon
      0,      // no maximum size
      false,  // normal cache policy
      base::BindOnce(&AppWindow::DidDownloadFavicon,
                     image_loader_ptr_factory_.GetWeakPtr()));
}

void AppWindow::DidDownloadFavicon(
    int id,
    int http_status_code,
    const GURL& image_url,
    const std::vector<SkBitmap>& bitmaps,
    const std::vector<gfx::Size>& original_bitmap_sizes) {
  if (image_url != app_icon_url_ || bitmaps.empty())
    return;

  // Bitmaps are ordered largest to smallest. Choose the smallest bitmap
  // whose height >= the preferred size.
  int largest_index = 0;
  for (size_t i = 1; i < bitmaps.size(); ++i) {
    if (bitmaps[i].height() < app_delegate_->PreferredIconSize())
      break;
    largest_index = i;
  }
  const SkBitmap& largest = bitmaps[largest_index];
  UpdateAppIcon(gfx::Image::CreateFrom1xBitmap(largest));
}

void AppWindow::SetNativeWindowFullscreen() {
  native_app_window_->SetFullscreen(fullscreen_types_);

  RestoreAlwaysOnTop();
}

bool AppWindow::IntersectsWithTaskbar() const {
#if defined(OS_WIN)
  display::Screen* screen = display::Screen::GetScreen();
  gfx::Rect window_bounds = native_app_window_->GetRestoredBounds();
  std::vector<display::Display> displays = screen->GetAllDisplays();

  for (std::vector<display::Display>::const_iterator it = displays.begin();
       it != displays.end(); ++it) {
    gfx::Rect taskbar_bounds = it->bounds();
    taskbar_bounds.Subtract(it->work_area());
    if (taskbar_bounds.IsEmpty())
      continue;

    if (window_bounds.Intersects(taskbar_bounds))
      return true;
  }
#endif

  return false;
}

void AppWindow::UpdateNativeAlwaysOnTop() {
  DCHECK(cached_always_on_top_);
  bool is_on_top = native_app_window_->IsAlwaysOnTop();
  bool fullscreen = IsFullscreen();
  bool intersects_taskbar = IntersectsWithTaskbar();

  if (is_on_top && (fullscreen || intersects_taskbar)) {
    // When entering fullscreen or overlapping the taskbar, ensure windows are
    // not always-on-top.
    native_app_window_->SetAlwaysOnTop(false);
  } else if (!is_on_top && !fullscreen && !intersects_taskbar) {
    // When exiting fullscreen and moving away from the taskbar, reinstate
    // always-on-top.
    native_app_window_->SetAlwaysOnTop(true);
  }
}

void AppWindow::ActivateContents(WebContents* contents) {
  native_app_window_->Activate();
}

void AppWindow::CloseContents(WebContents* contents) {
  native_app_window_->Close();
}

bool AppWindow::ShouldSuppressDialogs(WebContents* source) {
  return true;
}

content::ColorChooser* AppWindow::OpenColorChooser(
    WebContents* web_contents,
    SkColor initial_color,
    const std::vector<blink::mojom::ColorSuggestionPtr>& suggestions) {
  return app_delegate_->ShowColorChooser(web_contents, initial_color);
}

void AppWindow::RunFileChooser(
    content::RenderFrameHost* render_frame_host,
    std::unique_ptr<content::FileSelectListener> listener,
    const blink::mojom::FileChooserParams& params) {
  app_delegate_->RunFileChooser(render_frame_host, std::move(listener), params);
}

void AppWindow::SetContentsBounds(WebContents* source,
                                  const gfx::Rect& bounds) {
  native_app_window_->SetBounds(bounds);
}

void AppWindow::NavigationStateChanged(content::WebContents* source,
                                       content::InvalidateTypes changed_flags) {
  if (changed_flags & content::INVALIDATE_TYPE_TITLE)
    native_app_window_->UpdateWindowTitle();
  else if (changed_flags & content::INVALIDATE_TYPE_TAB)
    native_app_window_->UpdateWindowIcon();
}

void AppWindow::EnterFullscreenModeForTab(
    content::WebContents* source,
    const GURL& origin,
    const blink::WebFullscreenOptions& options) {
  ToggleFullscreenModeForTab(source, true);
}

void AppWindow::ExitFullscreenModeForTab(content::WebContents* source) {
  ToggleFullscreenModeForTab(source, false);
}

void AppWindow::OnAppWindowReady() {
  window_ready_ = true;

  if (app_icon_url_.is_valid())
    StartAppIconDownload();
}

void AppWindow::ToggleFullscreenModeForTab(content::WebContents* source,
                                           bool enter_fullscreen) {
  const Extension* extension = GetExtension();
  if (!extension)
    return;

  if (!IsExtensionWithPermissionOrSuggestInConsole(
          APIPermission::kFullscreen, extension, source->GetMainFrame())) {
    return;
  }

  SetFullscreen(FULLSCREEN_TYPE_HTML_API, enter_fullscreen);
}

bool AppWindow::IsFullscreenForTabOrPending(const content::WebContents* source)
    const {
  return IsHtmlApiFullscreen();
}

blink::WebDisplayMode AppWindow::GetDisplayMode(
    const content::WebContents* source) const {
  return IsFullscreen() ? blink::kWebDisplayModeFullscreen
                        : blink::kWebDisplayModeStandalone;
}

WindowController* AppWindow::GetExtensionWindowController() const {
  return app_window_contents_->GetWindowController();
}

content::WebContents* AppWindow::GetAssociatedWebContents() const {
  return web_contents();
}

void AppWindow::OnExtensionUnloaded(BrowserContext* browser_context,
                                    const Extension* extension,
                                    UnloadedExtensionReason reason) {
  if (extension_id_ == extension->id())
    native_app_window_->Close();
}

void AppWindow::SetWebContentsBlocked(content::WebContents* web_contents,
                                      bool blocked) {
  app_delegate_->SetWebContentsBlocked(web_contents, blocked);
}

bool AppWindow::IsWebContentsVisible(content::WebContents* web_contents) {
  return app_delegate_->IsWebContentsVisible(web_contents);
}

WebContentsModalDialogHost* AppWindow::GetWebContentsModalDialogHost() {
  return native_app_window_.get();
}

void AppWindow::SaveWindowPosition() {
  DCHECK(native_app_window_);
  if (window_key_.empty())
    return;

  AppWindowGeometryCache* cache =
      AppWindowGeometryCache::Get(browser_context());

  gfx::Rect bounds = native_app_window_->GetRestoredBounds();
  gfx::Rect screen_bounds =
      display::Screen::GetScreen()->GetDisplayMatching(bounds).work_area();
  ui::WindowShowState window_state = native_app_window_->GetRestoredState();
  cache->SaveGeometry(
      extension_id(), window_key_, bounds, screen_bounds, window_state);
}

void AppWindow::AdjustBoundsToBeVisibleOnScreen(
    const gfx::Rect& cached_bounds,
    const gfx::Rect& cached_screen_bounds,
    const gfx::Rect& current_screen_bounds,
    const gfx::Size& minimum_size,
    gfx::Rect* bounds) const {
  *bounds = cached_bounds;

  // Reposition and resize the bounds if the cached_screen_bounds is different
  // from the current screen bounds and the current screen bounds doesn't
  // completely contain the bounds.
  if (cached_screen_bounds != current_screen_bounds &&
      !current_screen_bounds.Contains(cached_bounds)) {
    bounds->set_width(
        std::max(minimum_size.width(),
                 std::min(bounds->width(), current_screen_bounds.width())));
    bounds->set_height(
        std::max(minimum_size.height(),
                 std::min(bounds->height(), current_screen_bounds.height())));
    bounds->set_x(
        std::max(current_screen_bounds.x(),
                 std::min(bounds->x(),
                          current_screen_bounds.right() - bounds->width())));
    bounds->set_y(
        std::max(current_screen_bounds.y(),
                 std::min(bounds->y(),
                          current_screen_bounds.bottom() - bounds->height())));
  }
}

AppWindow::CreateParams AppWindow::LoadDefaults(CreateParams params)
    const {
  // Ensure width and height are specified.
  if (params.content_spec.bounds.width() == 0 &&
      params.window_spec.bounds.width() == 0) {
    params.content_spec.bounds.set_width(kDefaultWidth);
  }
  if (params.content_spec.bounds.height() == 0 &&
      params.window_spec.bounds.height() == 0) {
    params.content_spec.bounds.set_height(kDefaultHeight);
  }

  // If left and top are left undefined, the native app window will center
  // the window on the main screen in a platform-defined manner.

  // Load cached state if it exists.
  if (!params.window_key.empty()) {
    AppWindowGeometryCache* cache =
        AppWindowGeometryCache::Get(browser_context());

    gfx::Rect cached_bounds;
    gfx::Rect cached_screen_bounds;
    ui::WindowShowState cached_state = ui::SHOW_STATE_DEFAULT;
    if (cache->GetGeometry(extension_id(),
                           params.window_key,
                           &cached_bounds,
                           &cached_screen_bounds,
                           &cached_state)) {
      // App window has cached screen bounds, make sure it fits on screen in
      // case the screen resolution changed.
      display::Screen* screen = display::Screen::GetScreen();
      display::Display display = screen->GetDisplayMatching(cached_bounds);
      gfx::Rect current_screen_bounds = display.work_area();
      SizeConstraints constraints(params.GetWindowMinimumSize(gfx::Insets()),
                                  params.GetWindowMaximumSize(gfx::Insets()));
      AdjustBoundsToBeVisibleOnScreen(cached_bounds,
                                      cached_screen_bounds,
                                      current_screen_bounds,
                                      constraints.GetMinimumSize(),
                                      &params.window_spec.bounds);
      params.state = cached_state;

      // Since we are restoring a cached state, reset the content bounds spec to
      // ensure it is not used.
      params.content_spec.ResetBounds();
    }
  }

  return params;
}

// static
SkRegion* AppWindow::RawDraggableRegionsToSkRegion(
    const std::vector<DraggableRegion>& regions) {
  SkRegion* sk_region = new SkRegion;
  for (auto iter = regions.cbegin(); iter != regions.cend(); ++iter) {
    const DraggableRegion& region = *iter;
    sk_region->op(
        region.bounds.x(),
        region.bounds.y(),
        region.bounds.right(),
        region.bounds.bottom(),
        region.draggable ? SkRegion::kUnion_Op : SkRegion::kDifference_Op);
  }
  return sk_region;
}

}  // namespace extensions
