// Copyright 2023 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "chrome/browser/ui/test/popup_test_base.h"

#include <string>

#include "base/memory/raw_ptr.h"
#include "chrome/browser/ui/browser.h"
#include "chrome/browser/ui/browser_window.h"
#include "chrome/test/base/ui_test_utils.h"
#include "components/embedder_support/switches.h"
#include "components/permissions/permission_request_manager.h"
#include "content/public/test/browser_test_utils.h"
#include "ui/display/display.h"
#include "ui/display/screen.h"
#include "ui/gfx/geometry/rect.h"
#include "ui/gfx/native_ui_types.h"
#include "ui/views/widget/widget.h"
#include "ui/views/widget/widget_observer.h"
#include "url/gurl.h"

namespace {

// A helper to wait for Browser window bounds changes beyond given thresholds.
class BoundsChangeWaiter final : public views::WidgetObserver {
 public:
  BoundsChangeWaiter(Browser* browser, int move_by, int resize_by)
      : widget_(views::Widget::GetWidgetForNativeWindow(
            browser->window()->GetNativeWindow())),
        move_by_(move_by),
        resize_by_(resize_by),
        initial_bounds_(widget_->GetWindowBoundsInScreen()) {}

  BoundsChangeWaiter(const BoundsChangeWaiter&) = delete;
  BoundsChangeWaiter& operator=(const BoundsChangeWaiter&) = delete;
  ~BoundsChangeWaiter() final { widget_->RemoveObserver(this); }

  // views::WidgetObserver:
  void OnWidgetBoundsChanged(views::Widget* widget,
                             const gfx::Rect& rect) final {
    if (BoundsChangeMeetsThreshold(widget_->GetWindowBoundsInScreen())) {
      widget_->RemoveObserver(this);
      run_loop_.Quit();
    }
  }

  // Wait for changes to occur, or return immediately if they already have.
  void Wait() {
    if (!BoundsChangeMeetsThreshold(widget_->GetWindowBoundsInScreen())) {
      widget_->AddObserver(this);
      run_loop_.Run();
    }
  }

 private:
  bool BoundsChangeMeetsThreshold(const gfx::Rect& rect) const {
    return (std::abs(rect.x() - initial_bounds_.x()) >= move_by_ ||
            std::abs(rect.y() - initial_bounds_.y()) >= move_by_) &&
           (std::abs(rect.width() - initial_bounds_.width()) >= resize_by_ ||
            std::abs(rect.height() - initial_bounds_.height()) >= resize_by_);
  }

  const raw_ptr<views::Widget> widget_;
  const int move_by_, resize_by_;
  const gfx::Rect initial_bounds_;
  base::RunLoop run_loop_;
};

}  // namespace

void PopupTestBase::SetUpCommandLine(base::CommandLine* command_line) {
  command_line->AppendSwitch(embedder_support::kDisablePopupBlocking);
}

// static
Browser* PopupTestBase::OpenPopup(Browser* browser,
                                  const std::string& script,
                                  bool user_gesture) {
  return OpenPopup(browser->tab_strip_model()->GetActiveWebContents(), script,
                   user_gesture);
}

// static
Browser* PopupTestBase::OpenPopup(const content::ToRenderFrameHost& adapter,
                                  const std::string& script,
                                  bool user_gesture) {
  if (user_gesture) {
    content::ExecuteScriptAsync(adapter, script);
  } else {
    content::ExecuteScriptAsyncWithoutUserGesture(adapter, script);
  }
  Browser* popup = ui_test_utils::WaitForBrowserToOpen();
  content::WebContents* popup_contents =
      popup->tab_strip_model()->GetActiveWebContents();
  // The popup's bounds are initialized after the synchronous window.open().
  // Ideally, this might wait for browser->renderer window bounds init via:
  // blink::mojom::Widget.UpdateVisualProperties, but it seems sufficient to
  // wait for WebContents to load the URL after the initial about:blank doc,
  // and then for that Document's readyState to be 'complete'. Anecdotally,
  // initial bounds seem settled once outerWidth and outerHeight are non-zero.
  EXPECT_TRUE(WaitForLoadStop(popup_contents));
  EXPECT_TRUE(WaitForRenderFrameReady(popup_contents->GetPrimaryMainFrame()));
  EXPECT_NE("0x0", EvalJs(popup_contents, "outerWidth + 'x' + outerHeight"));
  return popup;
}

// static
void PopupTestBase::WaitForBoundsChange(Browser* browser,
                                        int move_by,
                                        int resize_by) {
  BoundsChangeWaiter(browser, move_by, resize_by).Wait();
}

// static
void PopupTestBase::SetUpWindowManagement(Browser* browser) {
  content::WebContents* web_contents =
      browser->tab_strip_model()->GetActiveWebContents();
  // Request and auto-accept the permission request.
  permissions::PermissionRequestManager* permission_request_manager =
      permissions::PermissionRequestManager::FromWebContents(web_contents);
  permission_request_manager->set_auto_response_for_test(
      permissions::PermissionRequestManager::ACCEPT_ALL);
  content::RenderFrameHost* rfh = web_contents->GetPrimaryMainFrame();
  ASSERT_TRUE(content::WaitForLoadStop(web_contents));
  ASSERT_TRUE(content::WaitForRenderFrameReady(rfh));
  ASSERT_EQ("complete", EvalJs(web_contents, "document.readyState"));
  ASSERT_EQ("visible", EvalJs(web_contents, "document.visibilityState"));
  ASSERT_GT(EvalJs(web_contents,
                   R"JS(getScreenDetails().then(s => {
                          window.screenDetails = s;
                          return s.screens.length; }))JS"),
            0);
  // Do not auto-accept any other permission requests.
  permission_request_manager->set_auto_response_for_test(
      permissions::PermissionRequestManager::NONE);
}

// static
display::Display PopupTestBase::GetDisplayNearestBrowser(
    const Browser* browser) {
  return display::Screen::Get()->GetDisplayNearestWindow(
      browser->window()->GetNativeWindow());
}

// static
void PopupTestBase::WaitForUserActivationExpiry(Browser* browser) {
  const std::string await_activation_expiry_script = R"(
    (async () => {
      while (navigator.userActivation.isActive)
        await new Promise(resolve => setTimeout(resolve, 1000));
      return navigator.userActivation.isActive;
    })();
  )";
  auto* tab = browser->tab_strip_model()->GetActiveWebContents();
  EXPECT_EQ(false, EvalJs(tab, await_activation_expiry_script,
                          content::EXECUTE_SCRIPT_NO_USER_GESTURE));
  EXPECT_FALSE(tab->HasRecentInteraction());
}
