Skip to content

Commit

Permalink
[Webcompat report dialog] Hidden "Send" button if reported URL is too…
Browse files Browse the repository at this point in the history
… long (#27063)

[Webcompat report dialog] Hidden "Send" button if reported URL is too long
(brave/brave-browser#42902)
---------

Signed-off-by: Vadym Struts <[email protected]>
  • Loading branch information
vadimstruts authored Jan 10, 2025
1 parent 53b345a commit c1a3e10
Show file tree
Hide file tree
Showing 5 changed files with 174 additions and 24 deletions.
139 changes: 122 additions & 17 deletions browser/ui/webui/webcompat_reporter/webcompat_reporter_ui.cc
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@
#include "brave/browser/ui/webui/webcompat_reporter/webcompat_reporter_ui.h"

#include <memory>
#include <optional>
#include <string>
#include <utility>
#include <vector>

Expand All @@ -15,7 +17,9 @@
#include "base/strings/string_util.h"
#include "base/task/sequenced_task_runner.h"
#include "base/task/thread_pool.h"
#include "base/values.h"
#include "brave/browser/brave_browser_process.h"
#include "brave/browser/ui/brave_browser_window.h"
#include "brave/browser/ui/webui/brave_webui_source.h"
#include "brave/browser/ui/webui/webcompat_reporter/webcompat_reporter_dialog.h"
#include "brave/browser/webcompat_reporter/webcompat_reporter_service_factory.h"
Expand All @@ -31,16 +35,20 @@
#include "brave/components/webcompat_reporter/resources/grit/webcompat_reporter_generated_map.h"
#include "chrome/browser/ui/browser.h"
#include "chrome/browser/ui/browser_finder.h"
#include "chrome/browser/ui/browser_list.h"
#include "components/grit/brave_components_resources.h"
#include "components/language/core/browser/pref_names.h"
#include "components/prefs/pref_service.h"
#include "content/public/browser/browser_thread.h"
#include "content/public/browser/render_frame_host.h"
#include "content/public/browser/render_widget_host_view.h"
#include "content/public/browser/web_contents.h"
#include "content/public/browser/web_ui_data_source.h"
#include "services/network/public/cpp/shared_url_loader_factory.h"
#include "ui/compositor/compositor.h"
#include "ui/gfx/codec/png_codec.h"
#include "url/gurl.h"
#include "ui/gfx/geometry/rect.h"
#include "ui/gfx/geometry/size.h"

#if BUILDFLAG(ENABLE_BRAVE_VPN)
#include "brave/browser/brave_vpn/brave_vpn_service_factory.h"
Expand All @@ -53,6 +61,58 @@ namespace {

constexpr char kUISourceHistogramName[] = "Brave.Webcompat.UISource";
constexpr int kMaxScreenshotPixelCount = 1280 * 720;
constexpr char kGetViewPortSizeParamName[] = "height";
constexpr char kOnViewPortSizeChangedEventName[] = "onViewPortSizeChanged";

content::WebContents* GetActiveWebContents() {
const auto* browser = BrowserList::GetInstance()->GetLastActive();
if (!browser) {
return nullptr;
}
return browser->tab_strip_model()->GetActiveWebContents();
}

const std::optional<gfx::Rect> GetContainerBounds(content::WebUI* web_ui) {
if (!web_ui) {
auto* web_contents = GetActiveWebContents();
return web_contents ? std::make_optional(web_contents->GetContainerBounds())
: std::nullopt;
}

return web_ui->GetWebContents()->GetContainerBounds();
}

views::Widget* GetBrowserWidget() {
const auto* browser = BrowserList::GetInstance()->GetLastActive();
if (!browser) {
return nullptr;
}

auto* widget = views::Widget::GetWidgetForNativeWindow(
browser->window()->GetNativeWindow());
if (!widget) {
return nullptr;
}

return widget->GetPrimaryWindowWidget();
}

const std::optional<int> GetDlgMaxHeight(content::WebUI* web_ui,
const views::Widget* browser_widget) {
DCHECK(browser_widget);
if (!browser_widget) {
return std::nullopt;
}
const auto modal_dlg_bounds = GetContainerBounds(web_ui);
if (!modal_dlg_bounds) {
return std::nullopt;
}

const auto browser_wnd_bounds =
browser_widget->client_view()->GetBoundsInScreen();

return browser_wnd_bounds.bottom() - modal_dlg_bounds->y();
}

} // namespace

Expand All @@ -65,16 +125,6 @@ WebcompatReporterDOMHandler::WebcompatReporterDOMHandler(Profile* profile)
DCHECK_CURRENTLY_ON(content::BrowserThread::UI);

InitAdditionalParameters(profile);

auto* browser = chrome::FindLastActiveWithProfile(profile);
if (!browser) {
return;
}
auto* web_contents = browser->tab_strip_model()->GetActiveWebContents();
if (!web_contents) {
return;
}
render_widget_host_view_ = web_contents->GetTopLevelRenderWidgetHostView();
}

void WebcompatReporterDOMHandler::InitAdditionalParameters(Profile* profile) {
Expand All @@ -97,6 +147,18 @@ void WebcompatReporterDOMHandler::InitAdditionalParameters(Profile* profile) {

WebcompatReporterDOMHandler::~WebcompatReporterDOMHandler() = default;

base::WeakPtr<WebcompatReporterDOMHandler>
WebcompatReporterDOMHandler::AsWeekPtr() {
return weak_ptr_factory_.GetWeakPtr();
}

void WebcompatReporterDOMHandler::OnWindowResize(const int& height) {
AllowJavascript();
base::Value::Dict event_data;
event_data.Set(kGetViewPortSizeParamName, height);
FireWebUIListener(kOnViewPortSizeChangedEventName, event_data);
}

void WebcompatReporterDOMHandler::RegisterMessages() {
web_ui()->RegisterMessageCallback(
"webcompat_reporter.submitReport",
Expand All @@ -115,16 +177,22 @@ void WebcompatReporterDOMHandler::RegisterMessages() {
"webcompat_reporter.clearScreenshot",
base::BindRepeating(&WebcompatReporterDOMHandler::HandleClearScreenshot,
base::Unretained(this)));
web_ui()->RegisterMessageCallback(
"webcompat_reporter.init",
base::BindRepeating(&WebcompatReporterDOMHandler::HandleInit,
base::Unretained(this)));
}

void WebcompatReporterDOMHandler::HandleCaptureScreenshot(
const base::Value::List& args) {
CHECK(render_widget_host_view_);
auto* render_widget_host_view =
web_ui()->GetWebContents()->GetTopLevelRenderWidgetHostView();
CHECK(render_widget_host_view);
CHECK_EQ(args.size(), 1u);

AllowJavascript();

auto output_size = render_widget_host_view_->GetVisibleViewportSize();
auto output_size = render_widget_host_view->GetVisibleViewportSize();
auto original_area = output_size.GetArea();

if (original_area > kMaxScreenshotPixelCount) {
Expand All @@ -134,7 +202,7 @@ void WebcompatReporterDOMHandler::HandleCaptureScreenshot(
output_size = gfx::ScaleToRoundedSize(output_size, output_scale);
}

render_widget_host_view_->CopyFromSurface(
render_widget_host_view->CopyFromSurface(
{}, output_size,
base::BindOnce(
[](base::WeakPtr<WebcompatReporterDOMHandler> handler,
Expand Down Expand Up @@ -192,6 +260,22 @@ void WebcompatReporterDOMHandler::HandleGetCapturedScreenshot(
ResolveJavascriptCallback(args[0], screenshot_b64);
}

void WebcompatReporterDOMHandler::HandleInit(const base::Value::List& args) {
CHECK_EQ(args.size(), 1u);

AllowJavascript();

const auto max_height = GetDlgMaxHeight(nullptr, GetBrowserWidget());
if (!max_height) {
RejectJavascriptCallback(args[0], {});
return;
}

base::Value::Dict event_data;
event_data.Set(kGetViewPortSizeParamName, *max_height);
ResolveJavascriptCallback(args[0], event_data);
}

void WebcompatReporterDOMHandler::HandleClearScreenshot(
const base::Value::List& args) {
pending_report_->screenshot_png = std::nullopt;
Expand Down Expand Up @@ -248,12 +332,33 @@ WebcompatReporterUI::WebcompatReporterUI(content::WebUI* web_ui)
CreateAndAddWebUIDataSource(
web_ui, kWebcompatReporterHost, kWebcompatReporterGenerated,
kWebcompatReporterGeneratedSize, IDR_WEBCOMPAT_REPORTER_HTML);
Profile* profile = Profile::FromWebUI(web_ui);
auto* profile = Profile::FromWebUI(web_ui);

auto webcompat_reporter_handler =
std::make_unique<WebcompatReporterDOMHandler>(profile);

web_ui->AddMessageHandler(
std::make_unique<WebcompatReporterDOMHandler>(profile));
webcompat_reporter_handler_ = webcompat_reporter_handler->AsWeekPtr();

web_ui->AddMessageHandler(std::move(webcompat_reporter_handler));

if (auto* widget = GetBrowserWidget()) {
observed_windows_.AddObservation(widget);
}
}

WebcompatReporterUI::~WebcompatReporterUI() = default;

void WebcompatReporterUI::OnWidgetBoundsChanged(views::Widget* widget,
const gfx::Rect& new_bounds) {
DCHECK(widget);
DCHECK(webcompat_reporter_handler_);
if (!webcompat_reporter_handler_ || !widget) {
return;
}

if (const auto max_height = GetDlgMaxHeight(web_ui(), widget)) {
webcompat_reporter_handler_->OnWindowResize(*max_height);
}
}

} // namespace webcompat_reporter
27 changes: 22 additions & 5 deletions browser/ui/webui/webcompat_reporter/webcompat_reporter_ui.h
Original file line number Diff line number Diff line change
Expand Up @@ -6,11 +6,12 @@
#ifndef BRAVE_BROWSER_UI_WEBUI_WEBCOMPAT_REPORTER_WEBCOMPAT_REPORTER_UI_H_
#define BRAVE_BROWSER_UI_WEBUI_WEBCOMPAT_REPORTER_WEBCOMPAT_REPORTER_UI_H_

#include <memory>
#include <string>
#include <optional>
#include <vector>

#include "base/memory/raw_ptr.h"
#include "base/memory/weak_ptr.h"
#include "base/scoped_multi_source_observation.h"
#include "base/task/sequenced_task_runner.h"
#include "brave/components/constants/webui_url_constants.h"
#include "brave/components/webcompat_reporter/common/webcompat_reporter.mojom-forward.h"
Expand All @@ -19,11 +20,14 @@
#include "content/public/browser/web_ui_message_handler.h"
#include "content/public/browser/webui_config.h"
#include "content/public/common/url_constants.h"
#include "ui/gfx/geometry/rect.h"
#include "ui/views/widget/widget.h"
#include "ui/views/widget/widget_observer.h"

namespace content {
class RenderWidgetHostView;
class WebUI;
}
} // namespace content

namespace webcompat_reporter {

Expand All @@ -45,6 +49,9 @@ class WebcompatReporterDOMHandler : public content::WebUIMessageHandler {
delete;
~WebcompatReporterDOMHandler() override;

void OnWindowResize(const int& height);
base::WeakPtr<WebcompatReporterDOMHandler> AsWeekPtr();

// WebUIMessageHandler implementation.
void RegisterMessages() override;

Expand All @@ -61,23 +68,33 @@ class WebcompatReporterDOMHandler : public content::WebUIMessageHandler {
void HandleClearScreenshot(const base::Value::List& args);

void HandleSubmitReport(const base::Value::List& args);
void HandleInit(const base::Value::List& args);

raw_ptr<WebcompatReporterService> reporter_service_ = nullptr;
raw_ptr<PrefService> pref_service_ = nullptr;
raw_ptr<content::RenderWidgetHostView> render_widget_host_view_;
scoped_refptr<base::SequencedTaskRunner> ui_task_runner_;

mojom::ReportInfoPtr pending_report_;

base::WeakPtrFactory<WebcompatReporterDOMHandler> weak_ptr_factory_{this};
};

class WebcompatReporterUI : public ConstrainedWebDialogUI {
class WebcompatReporterUI : public ConstrainedWebDialogUI,
public views::WidgetObserver {
public:
explicit WebcompatReporterUI(content::WebUI* web_ui);
WebcompatReporterUI(const WebcompatReporterUI&) = delete;
WebcompatReporterUI& operator=(const WebcompatReporterUI&) = delete;
~WebcompatReporterUI() override;

// views::WidgetObserver
void OnWidgetBoundsChanged(views::Widget* widget,
const gfx::Rect& new_bounds) override;

private:
base::WeakPtr<WebcompatReporterDOMHandler> webcompat_reporter_handler_;
base::ScopedMultiSourceObservation<views::Widget, views::WidgetObserver>
observed_windows_{this};
};

} // namespace webcompat_reporter
Expand Down
15 changes: 14 additions & 1 deletion components/webcompat_reporter/ui/browser_proxy.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,10 @@
// This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0. If a copy of the MPL was not distributed with this file,
// You can obtain one at https://mozilla.org/MPL/2.0/.
import { sendWithPromise } from 'chrome://resources/js/cr.js';
import {
addWebUiListener,
sendWithPromise
} from 'chrome://resources/js/cr.js';

export function submitReport(reportDetails: { [key: string]: any }) {
chrome.send('webcompat_reporter.submitReport', [
Expand All @@ -29,3 +32,13 @@ export function clearScreenshot() {
export function getCapturedScreenshot(): Promise<string> {
return sendWithPromise('webcompat_reporter.getCapturedScreenshot')
}

export interface ViewPortSizeChangedObject {
height: number
}

export function setViewPortChangeListener(
calback: (data: ViewPortSizeChangedObject) => void) {
sendWithPromise('webcompat_reporter.init').then(calback)
addWebUiListener('onViewPortSizeChanged', calback)
}
2 changes: 2 additions & 0 deletions components/webcompat_reporter/ui/webcompat_reporter.html
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,8 @@
<style>
#root {
height: 100%;
overflow-x: hidden;
overflow-y: auto;
}
body {
margin: 0;
Expand Down
15 changes: 14 additions & 1 deletion components/webcompat_reporter/ui/webcompat_reporter.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,11 @@ import App from './containers/App'
// Utils
import store from './store'
import * as webcompatReporterActions from './actions/webcompatreporter_actions'
import { getDialogArgs } from './browser_proxy'
import {
getDialogArgs,
setViewPortChangeListener,
ViewPortSizeChangedObject,
} from './browser_proxy'

let actions: any

Expand All @@ -43,9 +47,18 @@ function loadDialogArgs () {
getActions().setDialogArgs(dialogArgs)
}

function onViewPortSizeChanged(data: ViewPortSizeChangedObject) {
const root = document.getElementById('root')
if (root) {
root.style.maxHeight = `${data.height}px`
}
}

function initialize () {
loadDialogArgs()

setViewPortChangeListener(onViewPortSizeChanged)

new Promise(resolve => chrome.braveTheme.getBraveThemeType(resolve))
.then((themeType: chrome.braveTheme.ThemeType) => {
render(
Expand Down

0 comments on commit c1a3e10

Please sign in to comment.