Skip to content

Commit

Permalink
Add a basic Compose webui bubble
Browse files Browse the repository at this point in the history
This is likely to change over time as we get more advanced
animation and positioning, but this provides an acceptable
initial experience.

Bug: b:305019677
Change-Id: Ideff0ca5ba6ba2f92e4946f109fc976e11b4f411
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/4953087
Reviewed-by: Scott Violet <sky@chromium.org>
Reviewed-by: Anthony Cui <cuianthony@chromium.org>
Commit-Queue: Justin DeWitt <dewittj@chromium.org>
Cr-Commit-Position: refs/heads/main@{#1212409}
  • Loading branch information
mrdewitt authored and Chromium LUCI CQ committed Oct 19, 2023
1 parent de482b1 commit a5e6ac1
Show file tree
Hide file tree
Showing 19 changed files with 204 additions and 253 deletions.
20 changes: 17 additions & 3 deletions chrome/browser/compose/chrome_compose_client.cc
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@

#include "base/functional/bind.h"
#include "base/strings/utf_string_conversions.h"
#include "base/task/bind_post_task.h"
#include "base/task/thread_pool.h"
#include "chrome/browser/compose/compose_enabling.h"
#include "chrome/browser/optimization_guide/optimization_guide_keyed_service.h"
Expand All @@ -27,11 +28,19 @@
#include "components/optimization_guide/core/optimization_guide_features.h"
#include "components/optimization_guide/core/optimization_guide_util.h"
#include "components/strings/grit/components_strings.h"
#include "content/public/browser/browser_thread.h"
#include "content/public/browser/web_contents_user_data.h"
#include "mojo/public/cpp/bindings/callback_helpers.h"
#include "ui/base/l10n/l10n_util.h"
#include "ui/gfx/geometry/rect_conversions.h"
#include "ui/gfx/geometry/rect_f.h"

namespace {

const char kComposeURL[] = "chrome://compose/";

} // namespace

ChromeComposeClient::ChromeComposeClient(content::WebContents* web_contents)
: content::WebContentsUserData<ChromeComposeClient>(*web_contents),
manager_(this) {
Expand All @@ -57,7 +66,7 @@ void ChromeComposeClient::BindComposeDialog(
mojo::PendingRemote<compose::mojom::ComposeDialog> dialog) {
url::Origin origin =
GetWebContents().GetPrimaryMainFrame()->GetLastCommittedOrigin();
if (origin == url::Origin::Create(GURL("chrome://compose"))) {
if (origin == url::Origin::Create(GURL(kComposeURL))) {
debug_session_ =
std::make_unique<ComposeSession>(&GetWebContents(), GetModelExecutor());
debug_session_->Bind(std::move(handler), std::move(dialog));
Expand All @@ -76,8 +85,13 @@ void ChromeComposeClient::ShowComposeDialog(
ComposeDialogCallback callback) {
SaveFieldAndCreateComposeStateIfEmpty(trigger_field.global_id());
if (!skip_show_dialog_for_test_) {
const gfx::RectF element_bounds = trigger_field.bounds;
chrome::ShowComposeDialog(GetWebContents(), element_bounds);
// The bounds given by autofill are relative to the top level frame. Here we
// offset by the WebContents container to make up for that.
gfx::RectF bounds_in_screen = trigger_field.bounds;
bounds_in_screen.Offset(
GetWebContents().GetContainerBounds().OffsetFromOrigin());
compose_dialog_controller_ =
chrome::ShowComposeDialog(GetWebContents(), bounds_in_screen);
}
}

Expand Down
2 changes: 2 additions & 0 deletions chrome/browser/compose/chrome_compose_client.h
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
#include "chrome/common/compose/compose.mojom.h"
#include "components/autofill/core/common/unique_ids.h"
#include "components/compose/core/browser/compose_client.h"
#include "components/compose/core/browser/compose_dialog_controller.h"
#include "components/compose/core/browser/compose_manager.h"
#include "components/compose/core/browser/compose_manager_impl.h"
#include "components/optimization_guide/core/optimization_guide_decision.h"
Expand Down Expand Up @@ -77,6 +78,7 @@ class ChromeComposeClient

compose::ComposeManagerImpl manager_;

std::unique_ptr<compose::ComposeDialogController> compose_dialog_controller_;
// A handle to optimization guide for information about URLs that have
// recently been navigated to.
raw_ptr<optimization_guide::OptimizationGuideDecider> opt_guide_;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3298,7 +3298,7 @@ void RenderViewContextMenu::ExecuteCommand(int id, int event_flags) {
// Extraction API is available.
compose_manager->OpenComposeFromContextMenu(
frame_token, autofill::FieldRendererId(*params_.field_renderer_id),
gfx::RectF(params_.x, params_.y, 50, 50));
gfx::Point(params_.x, params_.y));
}
break;
}
Expand Down
1 change: 1 addition & 0 deletions chrome/browser/resources/compose/compose.html
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
html, body {
cursor: default;
margin: 0;
min-width: 448px;
overflow: hidden;
}

Expand Down
11 changes: 9 additions & 2 deletions chrome/browser/ui/BUILD.gn
Original file line number Diff line number Diff line change
Expand Up @@ -4933,8 +4933,6 @@ static_library("ui") {
"views/commerce/price_tracking_view.h",
"views/commerce/shopping_collection_iph_view.cc",
"views/commerce/shopping_collection_iph_view.h",
"views/compose/compose_dialog_controller.cc",
"views/compose/compose_dialog_controller.h",
"views/compose/compose_dialog_view.cc",
"views/compose/compose_dialog_view.h",
"views/confirm_bubble_views.cc",
Expand Down Expand Up @@ -6181,6 +6179,15 @@ static_library("ui") {
"//chrome/browser/screen_ai:screen_ai_service_router_factory",
]
}

if (enable_compose) {
sources += [
"views/compose/chrome_compose_dialog_controller.cc",
"views/compose/chrome_compose_dialog_controller.h",
]

deps += [ "//components/compose/core/browser" ]
}
}

if (enable_lens_desktop_google_branded_features) {
Expand Down
11 changes: 9 additions & 2 deletions chrome/browser/ui/browser_dialogs.h
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,12 @@ namespace views {
class Widget;
} // namespace views

#if BUILDFLAG(ENABLE_COMPOSE)
namespace compose {
class ComposeDialogController;
} // namespace compose
#endif

namespace chrome {

// Shows or hides the Task Manager. |browser| can be NULL when called from Ash.
Expand Down Expand Up @@ -132,8 +138,9 @@ std::unique_ptr<ui::DialogModel> CreateWindowNamePromptDialogModelForTesting(
Browser* browser);

#if BUILDFLAG(ENABLE_COMPOSE)
void ShowComposeDialog(content::WebContents& web_contents,
const gfx::RectF& element_bounds);
std::unique_ptr<compose::ComposeDialogController> ShowComposeDialog(
content::WebContents& web_contents,
const gfx::RectF& element_bounds_in_screen);
#endif

} // namespace chrome
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,85 @@
// 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/views/compose/chrome_compose_dialog_controller.h"

#include "chrome/browser/profiles/profile.h"
#include "chrome/browser/ui/browser_dialogs.h"
#include "chrome/browser/ui/browser_finder.h"
#include "chrome/browser/ui/views/bubble/webui_bubble_dialog_view.h"
#include "chrome/browser/ui/views/frame/browser_view.h"
#include "ui/views/bubble/bubble_border.h"
#include "ui/views/bubble/bubble_dialog_delegate_view.h"

// Default size from Figma spec. The size of the view will follow the requested
// size of the WebUI, once these are connected.
namespace {

const char kComposeURL[] = "chrome://compose/";

}

namespace chrome {

std::unique_ptr<compose::ComposeDialogController> ShowComposeDialog(
content::WebContents& web_contents,
const gfx::RectF& element_bounds_in_screen) {
auto controller =
std::make_unique<ChromeComposeDialogController>(&web_contents);
controller->ShowComposeDialog(nullptr, element_bounds_in_screen);
return controller;
}

} // namespace chrome

ChromeComposeDialogController::~ChromeComposeDialogController() = default;

// TOOD(b/301371110): This function should accept an argument indicating whether
// it was called from the context menu. If so, open by popping in. Otherwise,
// open with an expanding animation.
void ChromeComposeDialogController::ShowComposeDialog(
views::View* anchor_view,
const gfx::RectF& element_bounds_in_screen) {
if (!web_contents_) {
return;
}

Profile* profile =
Profile::FromBrowserContext(web_contents_->GetBrowserContext());
bubble_wrapper_ = std::make_unique<BubbleContentsWrapperT<ComposeUI>>(
GURL(kComposeURL), profile, IDS_COMPOSE_TITLE);
bubble_wrapper_->ReloadWebContents();

// This WebUI needs to know the calling BrowserContents so that the compose
// request/result can be properly associated with the triggering form.
bubble_wrapper_->GetWebUIController()->set_triggering_web_contents(
web_contents_.get());

auto bubble_view = std::make_unique<WebUIBubbleDialogView>(
anchor_view, bubble_wrapper_.get(),
gfx::ToRoundedRect(element_bounds_in_screen));

// Allows the bubble bounds to escape the browser window.
bubble_view->set_has_parent(false);

auto weak_ptr = bubble_view->GetWeakPtr();
views::BubbleDialogDelegateView::CreateBubble(std::move(bubble_view));

weak_ptr->ShowUI();
}

BubbleContentsWrapperT<ComposeUI>*
ChromeComposeDialogController::GetBubbleWrapper() const {
return bubble_wrapper_.get();
}

// TODO(b/300939629): Flesh out implementation and cover other closing paths.
void ChromeComposeDialogController::Close() {
bubble_wrapper_->CloseUI();
bubble_wrapper_.reset();
}

ChromeComposeDialogController::ChromeComposeDialogController(
content::WebContents* web_contents)
: web_contents_(web_contents->GetWeakPtr()) {}
47 changes: 47 additions & 0 deletions chrome/browser/ui/views/compose/chrome_compose_dialog_controller.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
// 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.

#ifndef CHROME_BROWSER_UI_VIEWS_COMPOSE_CHROME_COMPOSE_DIALOG_CONTROLLER_H_
#define CHROME_BROWSER_UI_VIEWS_COMPOSE_CHROME_COMPOSE_DIALOG_CONTROLLER_H_

#include "base/memory/weak_ptr.h"
#include "chrome/browser/ui/views/bubble/bubble_contents_wrapper.h"
#include "chrome/browser/ui/views/compose/compose_dialog_view.h"
#include "chrome/browser/ui/webui/compose/compose_ui.h"
#include "components/compose/core/browser/compose_dialog_controller.h"
#include "components/strings/grit/components_strings.h"
#include "content/public/browser/web_contents.h"
#include "content/public/browser/web_contents_user_data.h"

namespace gfx {
class RectF;
}

// Controls how Compose dialogs are shown and hidden, and animations related to
// both actions.
class ChromeComposeDialogController : public compose::ComposeDialogController {
public:
explicit ChromeComposeDialogController(content::WebContents* contents);
~ChromeComposeDialogController() override;

// Create and show the dialog view.
void ShowComposeDialog(views::View* anchor_view,
const gfx::RectF& element_bounds_in_screen);

// Returns the currently shown compose dialog. Returns nullptr if the dialog
// is not currently shown.
BubbleContentsWrapperT<ComposeUI>* GetBubbleWrapper() const;

void Close() override;

private:
friend class ChromeComposeDialogControllerTest;

std::unique_ptr<BubbleContentsWrapperT<ComposeUI>> bubble_wrapper_;
base::WeakPtr<content::WebContents> web_contents_;

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

#endif // CHROME_BROWSER_UI_VIEWS_COMPOSE_CHROME_COMPOSE_DIALOG_CONTROLLER_H_
94 changes: 0 additions & 94 deletions chrome/browser/ui/views/compose/compose_dialog_controller.cc

This file was deleted.

0 comments on commit a5e6ac1

Please sign in to comment.