// Copyright 2014 The Chromium Authors
// 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 <memory>
#include <string>
#include <utility>
#include <vector>

#include "base/functional/bind.h"
#include "base/strings/string_util.h"
#include "base/strings/utf_string_conversions.h"
#include "base/task/task_runner.h"
#include "base/values.h"
#include "build/build_config.h"
#include "build/chromeos_buildflags.h"
#include "components/user_prefs/user_prefs.h"
#include "components/web_modal/web_contents_modal_dialog_manager.h"
#include "content/public/browser/browser_context.h"
#include "content/public/browser/color_chooser.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/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/process_manager.h"
#include "extensions/browser/suggest_permission_util.h"
#include "extensions/browser/view_type_utils.h"
#include "extensions/common/extension.h"
#include "extensions/common/manifest_handlers/icons_handler.h"
#include "extensions/common/mojom/view_type.mojom.h"
#include "extensions/common/permissions/permissions_data.h"
#include "third_party/blink/public/common/mediastream/media_stream_request.h"
#include "third_party/blink/public/mojom/page/draggable_region.mojom.h"
#include "third_party/skia/include/core/SkBitmap.h"
#include "third_party/skia/include/core/SkRegion.h"
#include "ui/base/mojom/window_show_state.mojom.h"
#include "ui/display/display.h"
#include "ui/display/screen.h"
#include "ui/events/keycodes/keyboard_codes.h"
#include "ui/gfx/geometry/rounded_corners_f.h"
#include "ui/gfx/geometry/size.h"

#if !BUILDFLAG(IS_MAC)
#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::DictValue* bounds_properties) {
  DCHECK(bounds_properties);
  if (value != SizeConstraints::kUnboundedSize)
    bounds_properties->Set(name, value);
  else
    bounds_properties->Set(name, base::Value());
}

void SetBoundsProperties(const gfx::Rect& bounds,
                         const gfx::Size& min_size,
                         const gfx::Size& max_size,
                         const std::string& bounds_name,
                         base::DictValue* window_properties) {
  DCHECK(window_properties);
  base::DictValue bounds_properties;

  bounds_properties.Set("left", bounds.x());
  bounds_properties.Set("top", bounds.y());
  bounds_properties.Set("width", bounds.width());
  bounds_properties.Set("height", bounds.height());

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

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

// Combines the constraints of the content and window, and returns constraints
// for the window. `is_minimum_size_constraint` is true when combining the
// minimum_size constraints for the window.
gfx::Size GetCombinedWindowConstraints(const gfx::Size& window_constraints,
                                       const gfx::Size& content_constraints,
                                       const gfx::Insets& frame_insets,
                                       const gfx::RoundedCornersF& window_radii,
                                       bool is_minimum_size_constraint) {
  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());
  }

  // To prevent the rounded corners of the window from overlapping, the rounded
  // window should have a minimum size equal to `rounded_window_minimum_size`.
  // Adjust the combined constraint (minimum size or maximum size of the window)
  // to enforce the minimum size of the window to at least be equal to
  // `rounded_window_minimum_size`, and if a maximum size is set, it should be
  // greater than or equal to `rounded_window_minimum_size`.
  const gfx::Size rounded_window_minimum_size =
      SizeConstraints::GetMinimumSizeSupportingRoundedCorners(window_radii);
  const bool override_width_constraint =
      is_minimum_size_constraint || combined_constraints.width() > 0;
  const bool override_height_constraint =
      is_minimum_size_constraint || combined_constraints.height() > 0;

  if (override_width_constraint) {
    combined_constraints.set_width(std::max(rounded_window_minimum_size.width(),
                                            combined_constraints.width()));
  }

  if (override_height_constraint) {
    combined_constraints.set_height(std::max(
        rounded_window_minimum_size.height(), combined_constraints.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() = default;

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::mojom::WindowShowState::kDefault),
      hidden(false),
      resizable(true),
      focused(true),
      always_on_top(false),
      visible_on_all_workspaces(false),
      show_in_shelf(false) {}

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

AppWindow::CreateParams::~CreateParams() = default;

gfx::Rect AppWindow::CreateParams::GetInitialWindowBounds(
    const gfx::Insets& frame_insets,
    const gfx::RoundedCornersF& window_radii) 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,
          window_radii, /*is_minimum_size_constraint=*/true),
      GetCombinedWindowConstraints(
          window_spec.maximum_size, content_spec.maximum_size, frame_insets,
          window_radii, /*is_minimum_size_constraint=*/false));
  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 gfx::RoundedCornersF& window_radii) const {
  return GetCombinedWindowConstraints(
      window_spec.minimum_size, content_spec.minimum_size, frame_insets,
      window_radii, /*is_minimum_size_constraint=*/true);
}

gfx::Size AppWindow::CreateParams::GetWindowMaximumSize(
    const gfx::Insets& frame_insets,
    const gfx::RoundedCornersF& window_radii) const {
  return GetCombinedWindowConstraints(
      window_spec.maximum_size, content_spec.maximum_size, frame_insets,
      window_radii, /*is_minimum_size_constraint=*/false);
}

// AppWindow

AppWindow::AppWindow(BrowserContext* context,
                     std::unique_ptr<AppDelegate> app_delegate,
                     const Extension* extension)
    : browser_context_(context),
      extension_id_(extension->id()),
      session_id_(SessionID::NewUnique()),
      app_delegate_(std::move(app_delegate)) {
  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,
                     std::unique_ptr<AppWindowContents> app_window_contents,
                     content::RenderFrameHost* creator_frame,
                     const CreateParams& params) {
  // Initialize the render interface and web contents
  app_window_contents_ = std::move(app_window_contents);
  app_window_contents_->Initialize(browser_context(), creator_frame, url);

  initial_url_ = url;

  content::WebContentsObserver::Observe(web_contents());
  SetViewType(web_contents(), mojom::ViewType::kAppWindow);
  app_delegate_->InitWebContents(web_contents());

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

  WebContentsModalDialogManager::CreateForWebContents(web_contents());

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

  // Initialize the window
  CreateParams new_params = LoadDefaults(params);
  window_type_ = new_params.window_type;
  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::mojom::WindowShowState::kFullscreen &&
      !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_in_shelf_ = params.show_in_shelf;

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

  helper_ = std::make_unique<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 {
    // These states may cause the window to show, so they are ignored if the
    // window is initially hidden.
    if (new_params.state == ui::mojom::WindowShowState::kFullscreen) {
      Fullscreen();
    } else if (new_params.state == ui::mojom::WindowShowState::kMaximized) {
      Maximize();
    } else if (new_params.state == ui::mojom::WindowShowState::kMinimized) {
      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::BindOnce(
      &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 url::Origin& security_origin,
    blink::mojom::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,
    base::OnceCallback<void(content::NavigationHandle&)>
        navigation_handle_callback) {
  DCHECK_EQ(web_contents(), source);
  return helper_->OpenURLFromTab(params, std::move(navigation_handle_callback));
}

content::WebContents* AppWindow::AddNewContents(
    WebContents* source,
    std::unique_ptr<WebContents> new_contents,
    const GURL& target_url,
    WindowOpenDisposition disposition,
    const blink::mojom::WindowFeatures& window_features,
    bool user_gesture,
    bool* was_blocked) {
  DCHECK(new_contents->GetBrowserContext() == browser_context_);
  app_delegate_->AddNewContents(browser_context_, std::move(new_contents),
                                target_url, disposition, window_features,
                                user_gesture);
  return nullptr;
}

content::KeyboardEventProcessingResult AppWindow::PreHandleKeyboardEvent(
    content::WebContents* source,
    const input::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(
          mojom::APIPermissionID::kOverrideEscFullscreen)) {
    Restore();
    return content::KeyboardEventProcessingResult::HANDLED;
  }

  return content::KeyboardEventProcessingResult::NOT_HANDLED;
}

bool AppWindow::HandleKeyboardEvent(
    WebContents* source,
    const input::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::RequestPointerLock(WebContents* web_contents,
                                   bool user_gesture,
                                   bool last_unlocked_by_target) {
  DCHECK_EQ(AppWindow::web_contents(), web_contents);
  helper_->RequestPointerLock();
}

content::PictureInPictureResult AppWindow::EnterPictureInPicture(
    content::WebContents* web_contents) {
  return app_delegate_->EnterPictureInPicture(web_contents);
}

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

bool AppWindow::ShouldShowStaleContentOnEviction(content::WebContents* source) {
#if BUILDFLAG(IS_CHROMEOS)
  return true;
#else
  return false;
#endif  // BUILDFLAG(IS_CHROMEOS)
}

void AppWindow::RenderFrameCreated(content::RenderFrameHost* frame_host) {
  app_delegate_->RenderFrameCreated(frame_host);
}

void AppWindow::AddOnDidFinishFirstNavigationCallback(
    DidFinishFirstNavigationCallback callback) {
  on_did_finish_first_navigation_callbacks_.push_back(std::move(callback));
}

void AppWindow::OnDidFinishFirstNavigation() {
  did_finish_first_navigation_ = true;
  std::vector<DidFinishFirstNavigationCallback> callbacks;
  std::swap(callbacks, on_did_finish_first_navigation_callbacks_);
  for (auto&& callback : callbacks)
    std::move(callback).Run(true /* did_finish */);
}

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

  // Run pending |on_did_finish_first_navigation_callback_| so that
  // AppWindowCreateFunction can respond with an error properly.
  std::vector<DidFinishFirstNavigationCallback> callbacks;
  std::swap(callbacks, on_did_finish_first_navigation_callbacks_);
  // No "OnClosed" event on window creation error.
  const bool send_onclosed = callbacks.empty();
  for (auto&& callback : callbacks)
    std::move(callback).Run(false /* did_finish */);

  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 BUILDFLAG(IS_MAC)
  // 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 BUILDFLAG(IS_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;
}

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

  // 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.
  std::u16string 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, u"\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/41357416.
  if (!window_ready_)
    return;

  StartAppIconDownload();
}

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

void AppWindow::DraggableRegionsChanged(
    const std::vector<blink::mojom::DraggableRegionPtr>& regions,
    content::WebContents* contents) {
  CHECK_EQ(contents, web_contents())
      << "Received DraggableRegionsChanged() notification for unexpected web "
         "contents";

  native_app_window_->DraggableRegionsChanged(regions);

  if (on_update_draggable_regions_callback_for_testing_) {
    std::move(on_update_draggable_regions_callback_for_testing_).Run();
  }
}

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 !BUILDFLAG(IS_MAC)
    // 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/40300937
    if (type != FULLSCREEN_TYPE_FORCED) {
      PrefService* prefs = user_prefs::UserPrefs::Get(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_->SetZOrderLevel(always_on_top
                                           ? ui::ZOrderLevel::kFloatingWindow
                                           : ui::ZOrderLevel::kNormal);
  }

  OnNativeWindowChanged();
}

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

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

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

  properties->Set("fullscreen", native_app_window_->IsFullscreenOrPending());
  properties->Set("minimized", native_app_window_->IsMinimized());
  properties->Set("maximized", native_app_window_->IsMaximized());
  properties->Set("alwaysOnTop", IsAlwaysOnTop());
  properties->Set("hasFrameColor", native_app_window_->HasFrameColor());
  properties->Set(
      "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->Set("activeFrameColor",
                  static_cast<int>(native_app_window_->ActiveFrameColor() &
                                   transparent_white));
  properties->Set("inactiveFrameColor",
                  static_cast<int>(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::RoundedCornersF window_radii = native_app_window_->GetWindowRadii();
  gfx::Rect window_bounds = native_app_window_->GetBounds();
  gfx::Size window_min_size = SizeConstraints::AddWindowToConstraints(
      content_min_size, frame_insets, window_radii);
  gfx::Size window_max_size = SizeConstraints::AddWindowToConstraints(
      content_max_size, frame_insets, window_radii);
  SetBoundsProperties(window_bounds, window_min_size, window_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();
  const gfx::Size preferred_size(app_delegate_->PreferredIconSize(),
                                 app_delegate_->PreferredIconSize());
  web_contents()->DownloadImage(
      app_icon_url_,
      true,  // is a favicon
      preferred_size,
      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 BUILDFLAG(IS_WIN)
  display::Screen* screen = display::Screen::Get();
  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_->GetZOrderLevel() == ui::ZOrderLevel::kFloatingWindow;
  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_->SetZOrderLevel(ui::ZOrderLevel::kNormal);
  } else if (!is_on_top && !fullscreen && !intersects_taskbar) {
    // When exiting fullscreen and moving away from the taskbar, reinstate
    // always-on-top.
    native_app_window_->SetZOrderLevel(ui::ZOrderLevel::kFloatingWindow);
  }
}

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;
}

void AppWindow::RunFileChooser(
    content::RenderFrameHost* render_frame_host,
    scoped_refptr<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::RenderFrameHost* requesting_frame,
    const blink::mojom::FullscreenOptions& options) {
  ToggleFullscreenModeForTab(WebContents::FromRenderFrameHost(requesting_frame),
                             true);
}

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

void AppWindow::AppWindowReady() {
  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(
          mojom::APIPermissionID::kFullscreen, extension,
          source->GetPrimaryMainFrame())) {
    return;
  }

  SetFullscreen(FULLSCREEN_TYPE_HTML_API, enter_fullscreen);
}

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

blink::mojom::DisplayMode AppWindow::GetDisplayMode(
    const content::WebContents* source) {
  return IsFullscreen() ? blink::mojom::DisplayMode::kFullscreen
                        : blink::mojom::DisplayMode::kStandalone;
}

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

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(
    content::WebContents* web_contents) {
  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::Get()->GetDisplayMatching(bounds).work_area();
  ui::mojom::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::mojom::WindowShowState cached_state =
        ui::mojom::WindowShowState::kDefault;
    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::Get();
      display::Display display = screen->GetDisplayMatching(cached_bounds);
      gfx::Rect current_screen_bounds = display.work_area();
      SizeConstraints constraints(
          params.GetWindowMinimumSize(gfx::Insets(), gfx::RoundedCornersF()),
          params.GetWindowMaximumSize(gfx::Insets(), gfx::RoundedCornersF()));
      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<blink::mojom::DraggableRegionPtr>& regions) {
  SkRegion* sk_region = new SkRegion;
  for (const auto& region : regions) {
    sk_region->op(
        SkIRect::MakeLTRB(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
