blob: 46ac65888a1f7869e26b8c01fbe141b90b0ac73a [file] [log] [blame]
// 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 "chrome/browser/ui/views/location_bar/location_bar_bubble_delegate_view.h"
#include "build/build_config.h"
#include "chrome/browser/chrome_notification_types.h"
#include "chrome/browser/ui/browser.h"
#include "chrome/browser/ui/browser_finder.h"
#include "chrome/browser/ui/exclusive_access/fullscreen_controller.h"
#include "chrome/browser/ui/layout_constants.h"
#include "chrome/grit/generated_resources.h"
#include "content/public/browser/notification_source.h"
#include "content/public/browser/render_view_host.h"
#include "ui/base/l10n/l10n_util.h"
#include "ui/gfx/geometry/rect.h"
#include "ui/views/accessibility/view_accessibility.h"
LocationBarBubbleDelegateView::WebContentMouseHandler::WebContentMouseHandler(
LocationBarBubbleDelegateView* bubble,
content::WebContents* web_contents)
: bubble_(bubble), web_contents_(web_contents) {
DCHECK(bubble_);
DCHECK(web_contents_);
event_monitor_ = views::EventMonitor::CreateWindowMonitor(
this, web_contents_->GetTopLevelNativeWindow(),
{ui::ET_MOUSE_PRESSED, ui::ET_KEY_PRESSED, ui::ET_TOUCH_PRESSED});
}
LocationBarBubbleDelegateView::WebContentMouseHandler::
~WebContentMouseHandler() = default;
void LocationBarBubbleDelegateView::WebContentMouseHandler::OnEvent(
const ui::Event& event) {
if (event.IsKeyEvent() && event.AsKeyEvent()->key_code() != ui::VKEY_ESCAPE &&
!web_contents_->IsFocusedElementEditable()) {
return;
}
bubble_->CloseBubble();
}
LocationBarBubbleDelegateView::LocationBarBubbleDelegateView(
views::View* anchor_view,
const gfx::Point& anchor_point,
content::WebContents* web_contents)
: BubbleDialogDelegateView(anchor_view,
anchor_view ? views::BubbleBorder::TOP_RIGHT
: views::BubbleBorder::NONE),
WebContentsObserver(web_contents) {
// Add observer to close the bubble if the fullscreen state changes.
if (web_contents) {
Browser* browser = chrome::FindBrowserWithWebContents(web_contents);
registrar_.Add(
this, chrome::NOTIFICATION_FULLSCREEN_CHANGED,
content::Source<FullscreenController>(
browser->exclusive_access_manager()->fullscreen_controller()));
}
if (!anchor_view)
SetAnchorRect(gfx::Rect(anchor_point, gfx::Size()));
}
LocationBarBubbleDelegateView::~LocationBarBubbleDelegateView() = default;
void LocationBarBubbleDelegateView::ShowForReason(DisplayReason reason,
bool allow_refocus_alert) {
if (reason == USER_GESTURE) {
GetWidget()->Show();
} else {
GetWidget()->ShowInactive();
if (allow_refocus_alert) {
// Since this widget is inactive (but shown), accessibility tools won't
// alert the user to its presence. Accessibility tools such as screen
// readers work by tracking system focus. Give users of these tools a hint
// description and alert them to the presence of this widget.
GetWidget()->GetRootView()->GetViewAccessibility().OverrideDescription(
l10n_util::GetStringUTF8(IDS_SHOW_BUBBLE_INACTIVE_DESCRIPTION));
}
}
if (GetAccessibleWindowRole() == ax::mojom::Role::kAlert ||
GetAccessibleWindowRole() == ax::mojom::Role::kAlertDialog) {
GetWidget()->GetRootView()->NotifyAccessibilityEvent(
ax::mojom::Event::kAlert, true);
}
}
void LocationBarBubbleDelegateView::Observe(
int type,
const content::NotificationSource& source,
const content::NotificationDetails& details) {
DCHECK_EQ(chrome::NOTIFICATION_FULLSCREEN_CHANGED, type);
GetWidget()->SetVisibilityAnimationTransition(views::Widget::ANIMATE_NONE);
CloseBubble();
}
void LocationBarBubbleDelegateView::OnVisibilityChanged(
content::Visibility visibility) {
if (visibility == content::Visibility::HIDDEN)
CloseBubble();
}
void LocationBarBubbleDelegateView::WebContentsDestroyed() {
CloseBubble();
}
gfx::Rect LocationBarBubbleDelegateView::GetAnchorBoundsInScreen() const {
gfx::Rect bounds = GetBoundsInScreen();
bounds.Inset(gfx::Insets(
GetLayoutConstant(LOCATION_BAR_BUBBLE_ANCHOR_VERTICAL_INSET), 0));
return bounds;
}
void LocationBarBubbleDelegateView::AdjustForFullscreen(
const gfx::Rect& screen_bounds) {
if (GetAnchorView())
return;
const int kBubblePaddingFromScreenEdge = 20;
int horizontal_offset = width() / 2 + kBubblePaddingFromScreenEdge;
const int x_pos = base::i18n::IsRTL()
? (screen_bounds.x() + horizontal_offset)
: (screen_bounds.right() - horizontal_offset);
SetAnchorRect(gfx::Rect(x_pos, screen_bounds.y(), 0, 0));
}
void LocationBarBubbleDelegateView::CloseBubble() {
GetWidget()->Close();
}