Add a custom tab bar to use for desktop PWAs.
Bug: 853593
Change-Id: I4618ca91c53a18ed7a56cb8dce0416d25318ab41
Reviewed-on: https://chromium-review.googlesource.com/c/1328084
Commit-Queue: Jay Harris <harrisjay@chromium.org>
Reviewed-by: Peter Kasting <pkasting@chromium.org>
Reviewed-by: Matt Giuca <mgiuca@chromium.org>
Cr-Commit-Position: refs/heads/master@{#613322}
diff --git a/chrome/browser/ui/BUILD.gn b/chrome/browser/ui/BUILD.gn
index e427c04..902f935b 100644
--- a/chrome/browser/ui/BUILD.gn
+++ b/chrome/browser/ui/BUILD.gn
@@ -2536,6 +2536,8 @@
"views/load_complete_listener.h",
"views/location_bar/content_setting_image_view.cc",
"views/location_bar/content_setting_image_view.h",
+ "views/location_bar/custom_tab_bar_view.cc",
+ "views/location_bar/custom_tab_bar_view.h",
"views/location_bar/find_bar_icon.cc",
"views/location_bar/find_bar_icon.h",
"views/location_bar/icon_label_bubble_view.cc",
diff --git a/chrome/browser/ui/browser.cc b/chrome/browser/ui/browser.cc
index 6e0ce319..5033fa2 100644
--- a/chrome/browser/ui/browser.cc
+++ b/chrome/browser/ui/browser.cc
@@ -669,9 +669,9 @@
// |contents| can be NULL because GetWindowTitleForCurrentTab is called by the
// window during the window's creation (before tabs have been added).
if (contents) {
- title = hosted_app_controller_ ? hosted_app_controller_->GetTitle()
- : contents->GetTitle();
- FormatTitleForDisplay(&title);
+ title = FormatTitleForDisplay(hosted_app_controller_
+ ? hosted_app_controller_->GetTitle()
+ : contents->GetTitle());
}
// If there is no title, leave it empty for apps.
@@ -700,14 +700,16 @@
}
// static
-void Browser::FormatTitleForDisplay(base::string16* title) {
+base::string16 Browser::FormatTitleForDisplay(base::string16 title) {
size_t current_index = 0;
size_t match_index;
- while ((match_index = title->find(L'\n', current_index)) !=
+ while ((match_index = title.find(L'\n', current_index)) !=
base::string16::npos) {
- title->replace(match_index, 1, base::string16());
+ title.replace(match_index, 1, base::string16());
current_index = match_index;
}
+
+ return title;
}
///////////////////////////////////////////////////////////////////////////////
diff --git a/chrome/browser/ui/browser.h b/chrome/browser/ui/browser.h
index c5dc61d..9769a792 100644
--- a/chrome/browser/ui/browser.h
+++ b/chrome/browser/ui/browser.h
@@ -336,7 +336,7 @@
content::WebContents* contents) const;
// Prepares a title string for display (removes embedded newlines, etc).
- static void FormatTitleForDisplay(base::string16* title);
+ static base::string16 FormatTitleForDisplay(base::string16 title);
// OnBeforeUnload handling //////////////////////////////////////////////////
diff --git a/chrome/browser/ui/bubble_anchor_util.h b/chrome/browser/ui/bubble_anchor_util.h
index 9a21594..ac2162a 100644
--- a/chrome/browser/ui/bubble_anchor_util.h
+++ b/chrome/browser/ui/bubble_anchor_util.h
@@ -21,6 +21,7 @@
enum Anchor {
kLocationBar,
kAppMenuButton,
+ kCustomTabBar,
};
// Offset from the window edge to show bubbles when there is no location bar.
diff --git a/chrome/browser/ui/extensions/hosted_app_browsertest.cc b/chrome/browser/ui/extensions/hosted_app_browsertest.cc
index a86076b..8a73739 100644
--- a/chrome/browser/ui/extensions/hosted_app_browsertest.cc
+++ b/chrome/browser/ui/extensions/hosted_app_browsertest.cc
@@ -316,7 +316,7 @@
// kDesktopPWAWindowing flag.
class HostedAppTest
: public extensions::ExtensionBrowserTest,
- public ::testing::WithParamInterface<std::tuple<AppType, bool>> {
+ public ::testing::WithParamInterface<std::tuple<AppType, bool, bool>> {
public:
HostedAppTest()
: app_browser_(nullptr),
@@ -328,8 +328,9 @@
https_server_.AddDefaultHandlers(base::FilePath(kDocRoot));
bool desktop_pwa_flag;
+ bool use_custom_tab_flag;
- std::tie(app_type_, desktop_pwa_flag) = GetParam();
+ std::tie(app_type_, desktop_pwa_flag, use_custom_tab_flag) = GetParam();
std::vector<base::Feature> enabled_features;
std::vector<base::Feature> disabled_features = {
predictors::kSpeculativePreconnectFeature};
@@ -342,6 +343,9 @@
#endif
}
+ auto& features = use_custom_tab_flag ? enabled_features : disabled_features;
+ features.push_back(features::kDesktopPWAsCustomTabUI);
+
scoped_feature_list_.InitWithFeatures(enabled_features, disabled_features);
extensions::ExtensionBrowserTest::SetUp();
}
@@ -918,9 +922,12 @@
app_browser->GetWindowTitleForCurrentTab(false));
}
+using HostedAppCustomTabBarOnlyTest = HostedAppTest;
+
// Ensure that hosted app windows display the app title instead of the page
// title when off scope.
-IN_PROC_BROWSER_TEST_P(HostedAppTest, OffScopeUrlsDisplayAppTitle) {
+IN_PROC_BROWSER_TEST_P(HostedAppCustomTabBarOnlyTest,
+ OffScopeUrlsDisplayAppTitle) {
ASSERT_TRUE(https_server()->Start());
GURL url = GetSecureAppURL();
@@ -949,7 +956,8 @@
// Ensure that hosted app windows display the app title instead of the page
// title when using http.
-IN_PROC_BROWSER_TEST_P(HostedAppTest, InScopeHttpUrlsDisplayAppTitle) {
+IN_PROC_BROWSER_TEST_P(HostedAppCustomTabBarOnlyTest,
+ InScopeHttpUrlsDisplayAppTitle) {
ASSERT_TRUE(embedded_test_server()->Start());
GURL url = embedded_test_server()->GetURL("app.site.com", "/simple.html");
WebApplicationInfo web_app_info;
@@ -2712,30 +2720,44 @@
INSTANTIATE_TEST_CASE_P(/* no prefix */,
HostedAppTest,
- ::testing::Combine(kAppTypeValues, ::testing::Bool()));
+ ::testing::Combine(kAppTypeValues,
+ ::testing::Bool(),
+ ::testing::Bool()));
+
INSTANTIATE_TEST_CASE_P(/* no prefix */,
- HostedAppPWAOnlyTest,
- ::testing::Values(std::tuple<AppType, bool>{
- AppType::BOOKMARK_APP, true}));
+ HostedAppCustomTabBarOnlyTest,
+ ::testing::Combine(kAppTypeValues,
+ ::testing::Bool(),
+ ::testing::Values(true)));
+INSTANTIATE_TEST_CASE_P(
+ /* no prefix */,
+ HostedAppPWAOnlyTest,
+ ::testing::Combine(::testing::Values(AppType::BOOKMARK_APP),
+ ::testing::Values(true),
+ ::testing::Bool()));
INSTANTIATE_TEST_CASE_P(
/* no prefix */,
BookmarkAppOnlyTest,
::testing::Combine(::testing::Values(AppType::BOOKMARK_APP),
+ ::testing::Bool(),
::testing::Bool()));
INSTANTIATE_TEST_CASE_P(
/* no prefix */,
HostedAppProcessModelTest,
::testing::Combine(::testing::Values(AppType::HOSTED_APP),
+ ::testing::Bool(),
::testing::Bool()));
INSTANTIATE_TEST_CASE_P(
/* no prefix */,
HostedAppIsolatedOriginTest,
::testing::Combine(::testing::Values(AppType::HOSTED_APP),
+ ::testing::Bool(),
::testing::Bool()));
INSTANTIATE_TEST_CASE_P(
/* no prefix */,
HostedAppSitePerProcessTest,
::testing::Combine(::testing::Values(AppType::HOSTED_APP),
+ ::testing::Bool(),
::testing::Bool()));
diff --git a/chrome/browser/ui/omnibox/omnibox_theme.cc b/chrome/browser/ui/omnibox/omnibox_theme.cc
index eb042c7..ce80ecc1 100644
--- a/chrome/browser/ui/omnibox/omnibox_theme.cc
+++ b/chrome/browser/ui/omnibox/omnibox_theme.cc
@@ -129,6 +129,24 @@
return gfx::kPlaceholderColor;
}
+SkColor GetOmniboxSecurityChipColor(
+ OmniboxTint tint,
+ security_state::SecurityLevel security_level) {
+ if (security_level == security_state::SECURE_WITH_POLICY_INSTALLED_CERT) {
+ return GetOmniboxColor(OmniboxPart::LOCATION_BAR_TEXT_DIMMED, tint);
+ }
+
+ OmniboxPartState state = OmniboxPartState::CHIP_DEFAULT;
+ if (security_level == security_state::EV_SECURE ||
+ security_level == security_state::SECURE) {
+ state = OmniboxPartState::CHIP_SECURE;
+ } else if (security_level == security_state::DANGEROUS) {
+ state = OmniboxPartState::CHIP_DANGEROUS;
+ }
+
+ return GetOmniboxColor(OmniboxPart::LOCATION_BAR_SECURITY_CHIP, tint, state);
+}
+
float GetOmniboxStateAlpha(OmniboxPartState state) {
switch (state) {
case OmniboxPartState::NORMAL:
diff --git a/chrome/browser/ui/omnibox/omnibox_theme.h b/chrome/browser/ui/omnibox/omnibox_theme.h
index 001bd45e..5c8625b 100644
--- a/chrome/browser/ui/omnibox/omnibox_theme.h
+++ b/chrome/browser/ui/omnibox/omnibox_theme.h
@@ -5,6 +5,7 @@
#ifndef CHROME_BROWSER_UI_OMNIBOX_OMNIBOX_THEME_H_
#define CHROME_BROWSER_UI_OMNIBOX_OMNIBOX_THEME_H_
+#include "components/security_state/core/security_state.h"
#include "third_party/skia/include/core/SkColor.h"
// A part of the omnibox (location bar, location bar decoration, or dropdown).
@@ -53,6 +54,11 @@
OmniboxTint tint,
OmniboxPartState state = OmniboxPartState::NORMAL);
+// Returns the color of the security chip given |tint| and |security_level|.
+SkColor GetOmniboxSecurityChipColor(
+ OmniboxTint tint,
+ security_state::SecurityLevel security_level);
+
float GetOmniboxStateAlpha(OmniboxPartState state);
#endif // CHROME_BROWSER_UI_OMNIBOX_OMNIBOX_THEME_H_
diff --git a/chrome/browser/ui/views/bubble_anchor_util_views.cc b/chrome/browser/ui/views/bubble_anchor_util_views.cc
index 192f311a..edd18e5 100644
--- a/chrome/browser/ui/views/bubble_anchor_util_views.cc
+++ b/chrome/browser/ui/views/bubble_anchor_util_views.cc
@@ -24,8 +24,13 @@
return {browser_view->GetLocationBarView(),
browser_view->GetLocationBarView()->location_icon_view(),
views::BubbleBorder::TOP_LEFT};
- // Fall back to menu button if no location bar present.
+ if (anchor == kCustomTabBar && browser_view->toolbar()->custom_tab_bar())
+ return {browser_view->toolbar()->custom_tab_bar(),
+ browser_view->toolbar()->custom_tab_bar()->location_icon_view(),
+ views::BubbleBorder::TOP_LEFT};
+
+ // Fall back to menu button.
views::Button* app_menu_button =
browser_view->toolbar_button_provider()->GetAppMenuButton();
if (app_menu_button && app_menu_button->IsDrawn())
diff --git a/chrome/browser/ui/views/location_bar/custom_tab_bar_view.cc b/chrome/browser/ui/views/location_bar/custom_tab_bar_view.cc
new file mode 100644
index 0000000..d5461da
--- /dev/null
+++ b/chrome/browser/ui/views/location_bar/custom_tab_bar_view.cc
@@ -0,0 +1,157 @@
+// Copyright 2018 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/custom_tab_bar_view.h"
+
+#include "base/strings/utf_string_conversions.h"
+#include "chrome/browser/ui/layout_constants.h"
+#include "chrome/browser/ui/omnibox/omnibox_theme.h"
+#include "chrome/browser/ui/page_info/page_info_dialog.h"
+#include "chrome/browser/ui/views/chrome_typography.h"
+#include "components/url_formatter/url_formatter.h"
+#include "content/public/browser/navigation_entry.h"
+#include "ui/gfx/color_palette.h"
+#include "ui/gfx/paint_vector_icon.h"
+#include "ui/views/background.h"
+#include "ui/views/border.h"
+#include "ui/views/layout/box_layout.h"
+#include "ui/views/style/typography.h"
+#include "ui/views/style/typography_provider.h"
+
+// Container view for laying out and rendering the title/origin of the current
+// page.
+class CustomTabBarTitleOriginView : public views::View {
+ public:
+ CustomTabBarTitleOriginView() {
+ title_label_ = new views::Label(
+ base::string16(), views::style::TextContext::CONTEXT_DIALOG_TITLE);
+ location_label_ = new views::Label(base::string16());
+
+ constexpr SkColor text_color = gfx::kGoogleGrey900;
+ title_label_->SetEnabledColor(text_color);
+ location_label_->SetEnabledColor(text_color);
+
+ AddChildView(title_label_);
+ AddChildView(location_label_);
+
+ auto layout = std::make_unique<views::BoxLayout>(
+ views::BoxLayout::Orientation::kVertical, gfx::Insets(), 0);
+ layout->set_cross_axis_alignment(
+ views::BoxLayout::CrossAxisAlignment::CROSS_AXIS_ALIGNMENT_START);
+ SetLayoutManager(std::move(layout));
+ }
+
+ void Update(base::string16 title, base::string16 location) {
+ title_label_->SetText(title);
+ location_label_->SetText(location);
+ }
+
+ private:
+ views::Label* title_label_;
+ views::Label* location_label_;
+};
+
+// static
+const char CustomTabBarView::kViewClassName[] = "CustomTabBarView";
+
+CustomTabBarView::CustomTabBarView(Browser* browser,
+ LocationBarView::Delegate* delegate)
+ : TabStripModelObserver(), delegate_(delegate) {
+ constexpr SkColor background_color = SK_ColorWHITE;
+ SetBackground(views::CreateSolidBackground(background_color));
+ browser->tab_strip_model()->AddObserver(this);
+
+ const gfx::FontList& font_list = views::style::GetFont(
+ CONTEXT_OMNIBOX_PRIMARY, views::style::STYLE_PRIMARY);
+ location_icon_view_ = new LocationIconView(font_list, this);
+ AddChildView(location_icon_view_);
+
+ title_origin_view_ = new CustomTabBarTitleOriginView();
+ AddChildView(title_origin_view_);
+
+ int padding = GetLayoutConstant(LayoutConstant::LOCATION_BAR_ELEMENT_PADDING);
+ // The location icon already has some padding, so we subtract it from the
+ // padding we're going to apply.
+ int location_icon_padding =
+ GetLayoutInsets(LayoutInset::LOCATION_BAR_ICON_INTERIOR_PADDING).left();
+ gfx::Insets insets(padding, padding - location_icon_padding, padding,
+ padding);
+
+ auto layout = std::make_unique<views::BoxLayout>(
+ views::BoxLayout::Orientation::kHorizontal, insets, 0);
+ layout->set_cross_axis_alignment(
+ views::BoxLayout::CrossAxisAlignment::CROSS_AXIS_ALIGNMENT_CENTER);
+
+ SetLayoutManager(std::move(layout));
+
+ constexpr SkColor border_color = gfx::kGoogleGrey400;
+ // Create a bottom border.
+ SetBorder(views::CreateSolidSidedBorder(0, 0, 1, 0, border_color));
+}
+
+CustomTabBarView::~CustomTabBarView() {}
+
+void CustomTabBarView::TabChangedAt(content::WebContents* contents,
+ int index,
+ TabChangeType change_type) {
+ if (!contents)
+ return;
+
+ content::NavigationEntry* entry = contents->GetController().GetVisibleEntry();
+ base::string16 title, location;
+ if (entry) {
+ title = Browser::FormatTitleForDisplay(entry->GetTitleForDisplay());
+ location = url_formatter::FormatUrl(
+ entry->GetVirtualURL(), url_formatter::kFormatUrlOmitDefaults,
+ net::UnescapeRule::NORMAL, nullptr, nullptr, nullptr);
+ }
+
+ title_origin_view_->Update(title, location);
+ location_icon_view_->Update(/*suppress animations = */ false);
+
+ last_title_ = title;
+ last_location_ = location;
+
+ Layout();
+}
+
+content::WebContents* CustomTabBarView::GetWebContents() {
+ return delegate_->GetWebContents();
+}
+
+bool CustomTabBarView::IsEditingOrEmpty() {
+ return false;
+}
+
+void CustomTabBarView::OnLocationIconPressed(const ui::MouseEvent& event) {}
+
+void CustomTabBarView::OnLocationIconDragged(const ui::MouseEvent& event) {}
+
+bool CustomTabBarView::ShowPageInfoDialog() {
+ return ::ShowPageInfoDialog(GetWebContents(),
+ bubble_anchor_util::Anchor::kCustomTabBar);
+}
+
+SkColor CustomTabBarView::GetSecurityChipColor(
+ security_state::SecurityLevel security_level) const {
+ // TODO(harrisjay): Use app theme color to determine OmniboxTint.
+ return GetOmniboxSecurityChipColor(OmniboxTint::LIGHT, security_level);
+}
+
+gfx::ImageSkia CustomTabBarView::GetLocationIcon(
+ LocationIconView::Delegate::IconFetchedCallback on_icon_fetched) const {
+ return gfx::CreateVectorIcon(
+ delegate_->GetLocationBarModel()->GetVectorIcon(),
+ GetLayoutConstant(LOCATION_BAR_ICON_SIZE),
+ GetSecurityChipColor(GetLocationBarModel()->GetSecurityLevel(false)));
+}
+
+SkColor CustomTabBarView::GetLocationIconInkDropColor() const {
+ return GetNativeTheme()->GetSystemColor(
+ ui::NativeTheme::kColorId_TextfieldDefaultColor);
+}
+
+const LocationBarModel* CustomTabBarView::GetLocationBarModel() const {
+ return delegate_->GetLocationBarModel();
+}
diff --git a/chrome/browser/ui/views/location_bar/custom_tab_bar_view.h b/chrome/browser/ui/views/location_bar/custom_tab_bar_view.h
new file mode 100644
index 0000000..29f58297
--- /dev/null
+++ b/chrome/browser/ui/views/location_bar/custom_tab_bar_view.h
@@ -0,0 +1,63 @@
+// Copyright 2018 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.
+
+#ifndef CHROME_BROWSER_UI_VIEWS_LOCATION_BAR_CUSTOM_TAB_BAR_VIEW_H_
+#define CHROME_BROWSER_UI_VIEWS_LOCATION_BAR_CUSTOM_TAB_BAR_VIEW_H_
+
+#include "base/macros.h"
+#include "chrome/browser/ui/browser.h"
+#include "chrome/browser/ui/views/location_bar/location_bar_view.h"
+#include "chrome/browser/ui/views/location_bar/location_icon_view.h"
+
+class CustomTabBarTitleOriginView;
+
+// A CustomTabBarView displays a read only title and origin for the current page
+// and a security status icon. This is visible if the hosted app window is
+// displaying a page over HTTP or if the current page is outside of the app
+// scope.
+class CustomTabBarView : public views::View,
+ public TabStripModelObserver,
+ public LocationIconView::Delegate {
+ public:
+ static const char kViewClassName[];
+
+ CustomTabBarView(Browser* browser, LocationBarView::Delegate* delegate);
+ ~CustomTabBarView() override;
+
+ LocationIconView* location_icon_view() { return location_icon_view_; }
+
+ // TabstripModelObserver:
+ void TabChangedAt(content::WebContents* contents,
+ int index,
+ TabChangeType change_type) override;
+
+ // LocationIconView::Delegate:
+ content::WebContents* GetWebContents() override;
+ bool IsEditingOrEmpty() override;
+ void OnLocationIconPressed(const ui::MouseEvent& event) override;
+ void OnLocationIconDragged(const ui::MouseEvent& event) override;
+ SkColor GetSecurityChipColor(
+ security_state::SecurityLevel security_level) const override;
+ bool ShowPageInfoDialog() override;
+ const LocationBarModel* GetLocationBarModel() const override;
+ gfx::ImageSkia GetLocationIcon(LocationIconView::Delegate::IconFetchedCallback
+ on_icon_fetched) const override;
+ SkColor GetLocationIconInkDropColor() const override;
+
+ // Methods for testing.
+ base::string16 title_for_testing() const { return last_title_; }
+ base::string16 location_for_testing() const { return last_location_; }
+
+ private:
+ base::string16 last_title_;
+ base::string16 last_location_;
+
+ LocationBarView::Delegate* delegate_ = nullptr;
+ LocationIconView* location_icon_view_ = nullptr;
+ CustomTabBarTitleOriginView* title_origin_view_ = nullptr;
+
+ DISALLOW_COPY_AND_ASSIGN(CustomTabBarView);
+};
+
+#endif // CHROME_BROWSER_UI_VIEWS_LOCATION_BAR_CUSTOM_TAB_BAR_VIEW_H_
diff --git a/chrome/browser/ui/views/location_bar/custom_tab_bar_view_browsertest.cc b/chrome/browser/ui/views/location_bar/custom_tab_bar_view_browsertest.cc
new file mode 100644
index 0000000..51e61fe
--- /dev/null
+++ b/chrome/browser/ui/views/location_bar/custom_tab_bar_view_browsertest.cc
@@ -0,0 +1,349 @@
+// Copyright 2018 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 "base/scoped_observer.h"
+#include "chrome/browser/extensions/extension_browsertest.h"
+#include "chrome/browser/ssl/cert_verifier_browser_test.h"
+#include "chrome/browser/ui/browser_finder.h"
+#include "chrome/browser/ui/views/frame/browser_view.h"
+#include "chrome/browser/ui/views/toolbar/toolbar_view.h"
+#include "chrome/common/chrome_features.h"
+#include "chrome/common/chrome_switches.h"
+#include "chrome/common/web_application_info.h"
+#include "chrome/test/base/in_process_browser_test.h"
+#include "chrome/test/base/ui_test_utils.h"
+#include "content/public/browser/navigation_entry.h"
+#include "content/public/browser/notification_service.h"
+#include "content/public/test/browser_test_utils.h"
+#include "content/public/test/test_navigation_observer.h"
+#include "net/dns/mock_host_resolver.h"
+
+const base::FilePath::CharType kDocRoot[] =
+ FILE_PATH_LITERAL("chrome/test/data");
+
+namespace {
+
+// Waits until the title of any tab in the browser for |contents| has the title
+// |target_title|.
+class TestTitleObserver : public TabStripModelObserver {
+ public:
+ // Create a new TitleObserver for the browser of |contents|, waiting for
+ // |target_title|.
+ TestTitleObserver(content::WebContents* contents, base::string16 target_title)
+ : contents_(contents),
+ target_title_(target_title),
+ tab_strip_model_observer_(this) {
+ browser_ = chrome::FindBrowserWithWebContents(contents_);
+ tab_strip_model_observer_.Add(browser_->tab_strip_model());
+ }
+
+ // Run a loop, blocking until a tab has the title |target_title|.
+ void Wait() {
+ if (seen_target_title_)
+ return;
+
+ awaiter_.Run();
+ }
+
+ // TabstripModelObserver:
+ void TabChangedAt(content::WebContents* contents,
+ int index,
+ TabChangeType change_type) override {
+ content::NavigationEntry* entry =
+ contents->GetController().GetVisibleEntry();
+ base::string16 title = entry ? entry->GetTitle() : base::string16();
+
+ if (title != target_title_)
+ return;
+
+ seen_target_title_ = true;
+ awaiter_.Quit();
+ }
+
+ private:
+ bool seen_target_title_ = false;
+
+ content::WebContents* contents_;
+ Browser* browser_;
+ base::string16 target_title_;
+ base::RunLoop awaiter_;
+ ScopedObserver<TabStripModel, TestTitleObserver> tab_strip_model_observer_;
+};
+
+// Opens a new popup window from |web_contents| on |target_url| and returns
+// the Browser it opened in.
+Browser* OpenPopup(content::WebContents* web_contents, const GURL& target_url) {
+ content::TestNavigationObserver nav_observer(target_url);
+ nav_observer.StartWatchingNewWebContents();
+
+ std::string script = "window.open('" + target_url.spec() +
+ "', 'popup', 'width=400 height=400');";
+ EXPECT_TRUE(content::ExecuteScript(web_contents, script));
+ nav_observer.Wait();
+
+ return chrome::FindLastActive();
+}
+
+// Navigates to |target_url| and waits for navigation to complete.
+void NavigateAndWait(content::WebContents* web_contents,
+ const GURL& target_url) {
+ content::TestNavigationObserver nav_observer(web_contents);
+
+ std::string script = "window.location = '" + target_url.spec() + "';";
+ EXPECT_TRUE(content::ExecuteScript(web_contents, script));
+ nav_observer.Wait();
+}
+
+// Navigates |web_contents| to |location|, waits for navigation to complete
+// and then sets document.title to be |title| and waits for the change
+// to propogate.
+void SetTitleAndLocation(content::WebContents* web_contents,
+ const base::string16 title,
+ const GURL& location) {
+ NavigateAndWait(web_contents, location);
+
+ TestTitleObserver title_observer(web_contents, title);
+
+ std::string script = "document.title = '" + base::UTF16ToASCII(title) + "';";
+ EXPECT_TRUE(content::ExecuteScript(web_contents, script));
+
+ title_observer.Wait();
+}
+
+} // namespace
+
+class CustomTabBarViewBrowserTest : public extensions::ExtensionBrowserTest {
+ public:
+ CustomTabBarViewBrowserTest()
+ : https_server_(net::EmbeddedTestServer::TYPE_HTTPS) {}
+ ~CustomTabBarViewBrowserTest() override {}
+
+ protected:
+ void SetUpInProcessBrowserTestFixture() override {
+ extensions::ExtensionBrowserTest::SetUpInProcessBrowserTestFixture();
+ cert_verifier_.SetUpInProcessBrowserTestFixture();
+ }
+
+ void TearDownInProcessBrowserTestFixture() override {
+ extensions::ExtensionBrowserTest::TearDownInProcessBrowserTestFixture();
+ cert_verifier_.TearDownInProcessBrowserTestFixture();
+ }
+
+ void SetUpCommandLine(base::CommandLine* command_line) override {
+ extensions::ExtensionBrowserTest::SetUpCommandLine(command_line);
+ // Browser will both run and display insecure content.
+ command_line->AppendSwitch(switches::kAllowRunningInsecureContent);
+ cert_verifier_.SetUpCommandLine(command_line);
+ }
+
+ void SetUpOnMainThread() override {
+ scoped_feature_list_.InitWithFeatures(
+ {features::kDesktopPWAsStayInWindow, features::kDesktopPWAWindowing,
+ features::kDesktopPWAsCustomTabUI},
+ {});
+ https_server_.AddDefaultHandlers(base::FilePath(kDocRoot));
+
+ // Everything should be redirected to the http server.
+ host_resolver()->AddRule("*", "127.0.0.1");
+ // All SSL cert checks should be valid.
+ cert_verifier_.mock_cert_verifier()->set_default_result(net::OK);
+
+ browser_view_ = BrowserView::GetBrowserViewForBrowser(browser());
+
+ location_bar_ = browser_view_->GetLocationBarView();
+ custom_tab_bar_ = browser_view_->toolbar()->custom_tab_bar();
+ }
+
+ void InstallPWA(const GURL& app_url) {
+ WebApplicationInfo web_app_info;
+ web_app_info.app_url = app_url;
+ web_app_info.scope = app_url.GetWithoutFilename();
+ web_app_info.open_as_window = true;
+
+ auto* app = InstallBookmarkApp(web_app_info);
+
+ ui_test_utils::UrlLoadObserver url_observer(
+ app_url, content::NotificationService::AllSources());
+ app_browser_ = LaunchAppBrowser(app);
+ url_observer.Wait();
+
+ DCHECK(app_browser_);
+ DCHECK(app_browser_ != browser());
+ }
+
+ Browser* app_browser_;
+ BrowserView* browser_view_;
+ LocationBarView* location_bar_;
+ CustomTabBarView* custom_tab_bar_;
+
+ net::EmbeddedTestServer* https_server() { return &https_server_; }
+
+ private:
+ base::test::ScopedFeatureList scoped_feature_list_;
+ net::EmbeddedTestServer https_server_;
+ // Similar to net::MockCertVerifier, but also updates the CertVerifier
+ // used by the NetworkService. This is needed for when tests run with
+ // the NetworkService enabled.
+ ChromeMockCertVerifier cert_verifier_;
+
+ DISALLOW_COPY_AND_ASSIGN(CustomTabBarViewBrowserTest);
+};
+
+// Check the custom tab bar is not instantiated for a tabbed browser window.
+IN_PROC_BROWSER_TEST_F(CustomTabBarViewBrowserTest,
+ IsNotCreatedInTabbedBrowser) {
+ EXPECT_TRUE(browser_view_->IsBrowserTypeNormal());
+ EXPECT_FALSE(custom_tab_bar_);
+}
+
+// Check the custom tab bar is not instantiated for a popup window.
+IN_PROC_BROWSER_TEST_F(CustomTabBarViewBrowserTest, IsNotCreatedInPopup) {
+ Browser* popup = OpenPopup(browser_view_->GetActiveWebContents(),
+ GURL("http://example.com"));
+ EXPECT_TRUE(popup);
+
+ BrowserView* popup_view = BrowserView::GetBrowserViewForBrowser(popup);
+
+ // The popup should be in a new window.
+ EXPECT_NE(browser_view_, popup_view);
+
+ // Popups are not the normal browser view.
+ EXPECT_FALSE(popup_view->IsBrowserTypeNormal());
+ // Popups should not have a custom tab bar view.
+ EXPECT_FALSE(popup_view->toolbar()->custom_tab_bar());
+}
+
+// Check the custom tab will be used for a Desktop PWA.
+IN_PROC_BROWSER_TEST_F(CustomTabBarViewBrowserTest, IsUsedForDesktopPWA) {
+ ASSERT_TRUE(https_server()->Start());
+ ASSERT_TRUE(embedded_test_server()->Start());
+
+ const GURL& url = https_server()->GetURL("app.com", "/ssl/google.html");
+ InstallPWA(url);
+
+ EXPECT_TRUE(app_browser_);
+
+ BrowserView* app_view = BrowserView::GetBrowserViewForBrowser(app_browser_);
+ EXPECT_NE(app_view, browser_view_);
+
+ EXPECT_FALSE(app_view->IsBrowserTypeNormal());
+
+ // Custom tab bar should be created.
+ EXPECT_TRUE(app_view->toolbar()->custom_tab_bar());
+}
+
+// The custom tab bar should update with the title and location of the current
+// page.
+IN_PROC_BROWSER_TEST_F(CustomTabBarViewBrowserTest, TitleAndLocationUpdate) {
+ ASSERT_TRUE(https_server()->Start());
+
+ const GURL& app_url = https_server()->GetURL("app.com", "/ssl/google.html");
+ const GURL& navigate_to =
+ https_server()->GetURL("app.com", "/ssl/blank_page.html");
+
+ InstallPWA(app_url);
+
+ EXPECT_TRUE(app_browser_);
+
+ BrowserView* app_view = BrowserView::GetBrowserViewForBrowser(app_browser_);
+ EXPECT_NE(app_view, browser_view_);
+
+ SetTitleAndLocation(app_view->GetActiveWebContents(),
+ base::ASCIIToUTF16("FooBar"), navigate_to);
+
+ EXPECT_EQ(base::ASCIIToUTF16(navigate_to.spec()),
+ app_view->toolbar()->custom_tab_bar()->location_for_testing());
+ EXPECT_EQ(base::ASCIIToUTF16("FooBar"),
+ app_view->toolbar()->custom_tab_bar()->title_for_testing());
+}
+
+// If the page doesn't specify a title, we should use the origin.
+IN_PROC_BROWSER_TEST_F(CustomTabBarViewBrowserTest,
+ UsesLocationInsteadOfEmptyTitles) {
+ ASSERT_TRUE(https_server()->Start());
+
+ const GURL& app_url = https_server()->GetURL("app.com", "/ssl/google.html");
+ InstallPWA(app_url);
+
+ EXPECT_TRUE(app_browser_);
+
+ BrowserView* app_view = BrowserView::GetBrowserViewForBrowser(app_browser_);
+ EXPECT_NE(app_view, browser_view_);
+
+ // Empty title should use location.
+ SetTitleAndLocation(app_view->GetActiveWebContents(), base::string16(),
+ GURL("http://example.test/"));
+ EXPECT_EQ(base::ASCIIToUTF16("example.test"),
+ app_view->toolbar()->custom_tab_bar()->location_for_testing());
+ EXPECT_EQ(base::ASCIIToUTF16("example.test"),
+ app_view->toolbar()->custom_tab_bar()->title_for_testing());
+}
+
+IN_PROC_BROWSER_TEST_F(CustomTabBarViewBrowserTest, URLsWithEmojiArePunyCoded) {
+ ASSERT_TRUE(https_server()->Start());
+
+ const GURL& app_url = https_server()->GetURL("app.com", "/ssl/google.html");
+ const GURL& navigate_to = GURL("https://🔒.example/ssl/blank_page.html");
+
+ InstallPWA(app_url);
+
+ EXPECT_TRUE(app_browser_);
+
+ BrowserView* app_view = BrowserView::GetBrowserViewForBrowser(app_browser_);
+ EXPECT_NE(app_view, browser_view_);
+
+ SetTitleAndLocation(app_view->GetActiveWebContents(),
+ base::ASCIIToUTF16("FooBar"), navigate_to);
+
+ EXPECT_EQ(base::UTF8ToUTF16("https://xn--lv8h.example/ssl/blank_page.html"),
+ app_view->toolbar()->custom_tab_bar()->location_for_testing());
+ EXPECT_EQ(base::ASCIIToUTF16("FooBar"),
+ app_view->toolbar()->custom_tab_bar()->title_for_testing());
+}
+
+IN_PROC_BROWSER_TEST_F(CustomTabBarViewBrowserTest,
+ URLsWithNonASCIICharactersDisplayNormally) {
+ ASSERT_TRUE(https_server()->Start());
+
+ const GURL& app_url = https_server()->GetURL("app.com", "/ssl/google.html");
+ const GURL& navigate_to = GURL("https://ΐ.example/ssl/blank_page.html");
+
+ InstallPWA(app_url);
+
+ EXPECT_TRUE(app_browser_);
+
+ BrowserView* app_view = BrowserView::GetBrowserViewForBrowser(app_browser_);
+ EXPECT_NE(app_view, browser_view_);
+
+ SetTitleAndLocation(app_view->GetActiveWebContents(),
+ base::ASCIIToUTF16("FooBar"), navigate_to);
+
+ EXPECT_EQ(base::UTF8ToUTF16("https://ΐ.example/ssl/blank_page.html"),
+ app_view->toolbar()->custom_tab_bar()->location_for_testing());
+ EXPECT_EQ(base::ASCIIToUTF16("FooBar"),
+ app_view->toolbar()->custom_tab_bar()->title_for_testing());
+}
+
+IN_PROC_BROWSER_TEST_F(CustomTabBarViewBrowserTest,
+ BannedCharactersAreURLEncoded) {
+ ASSERT_TRUE(https_server()->Start());
+
+ const GURL& app_url = https_server()->GetURL("app.com", "/ssl/google.html");
+ const GURL& navigate_to = GURL("https://ΐ.example/🔒/blank_page.html");
+
+ InstallPWA(app_url);
+
+ EXPECT_TRUE(app_browser_);
+
+ BrowserView* app_view = BrowserView::GetBrowserViewForBrowser(app_browser_);
+ EXPECT_NE(app_view, browser_view_);
+
+ SetTitleAndLocation(app_view->GetActiveWebContents(),
+ base::ASCIIToUTF16("FooBar"), navigate_to);
+
+ EXPECT_EQ(base::UTF8ToUTF16("https://ΐ.example/%F0%9F%94%92/blank_page.html"),
+ app_view->toolbar()->custom_tab_bar()->location_for_testing());
+ EXPECT_EQ(base::ASCIIToUTF16("FooBar"),
+ app_view->toolbar()->custom_tab_bar()->title_for_testing());
+}
diff --git a/chrome/browser/ui/views/location_bar/location_bar_view.cc b/chrome/browser/ui/views/location_bar/location_bar_view.cc
index 34e4b11..b930b27 100644
--- a/chrome/browser/ui/views/location_bar/location_bar_view.cc
+++ b/chrome/browser/ui/views/location_bar/location_bar_view.cc
@@ -1186,20 +1186,7 @@
SkColor LocationBarView::GetSecurityChipColor(
security_state::SecurityLevel security_level) const {
- // Only used in ChromeOS.
- if (security_level == security_state::SECURE_WITH_POLICY_INSTALLED_CERT)
- return GetColor(OmniboxPart::LOCATION_BAR_TEXT_DIMMED);
-
- OmniboxPartState state = OmniboxPartState::CHIP_DEFAULT;
- if (security_level == security_state::EV_SECURE ||
- security_level == security_state::SECURE) {
- state = OmniboxPartState::CHIP_SECURE;
- } else if (security_level == security_state::DANGEROUS) {
- state = OmniboxPartState::CHIP_DANGEROUS;
- }
-
- return GetOmniboxColor(OmniboxPart::LOCATION_BAR_SECURITY_CHIP, tint(),
- state);
+ return GetOmniboxSecurityChipColor(tint(), security_level);
}
bool LocationBarView::ShowPageInfoDialog() {
diff --git a/chrome/browser/ui/views/tabs/tab.cc b/chrome/browser/ui/views/tabs/tab.cc
index 73e7ebe..37bc104 100644
--- a/chrome/browser/ui/views/tabs/tab.cc
+++ b/chrome/browser/ui/views/tabs/tab.cc
@@ -709,7 +709,7 @@
? l10n_util::GetStringUTF16(IDS_TAB_LOADING_TITLE)
: CoreTabHelper::GetDefaultTitle();
} else {
- Browser::FormatTitleForDisplay(&title);
+ title = Browser::FormatTitleForDisplay(title);
}
title_->SetText(title);
diff --git a/chrome/browser/ui/views/toolbar/toolbar_view.cc b/chrome/browser/ui/views/toolbar/toolbar_view.cc
index 999a6eb1..ac59fa1 100644
--- a/chrome/browser/ui/views/toolbar/toolbar_view.cc
+++ b/chrome/browser/ui/views/toolbar/toolbar_view.cc
@@ -46,6 +46,7 @@
#include "chrome/browser/ui/views/translate/translate_bubble_view.h"
#include "chrome/browser/ui/views/translate/translate_icon_view.h"
#include "chrome/browser/upgrade_detector/upgrade_detector.h"
+#include "chrome/common/chrome_features.h"
#include "chrome/common/pref_names.h"
#include "chrome/grit/chromium_strings.h"
#include "chrome/grit/generated_resources.h"
@@ -102,6 +103,18 @@
return ui::MaterialDesignController::touch_ui() ? 0 : 8;
}
+// Gets the display mode for a given browser.
+ToolbarView::DisplayMode GetDisplayMode(Browser* browser) {
+ if (browser->SupportsWindowFeature(Browser::FEATURE_TABSTRIP))
+ return ToolbarView::DisplayMode::NORMAL;
+
+ if (browser->hosted_app_controller() &&
+ base::FeatureList::IsEnabled(features::kDesktopPWAsCustomTabUI))
+ return ToolbarView::DisplayMode::CUSTOM_TAB;
+
+ return ToolbarView::DisplayMode::LOCATION;
+}
+
} // namespace
// static
@@ -114,9 +127,7 @@
: browser_(browser),
browser_view_(browser_view),
app_menu_icon_controller_(browser->profile(), this),
- display_mode_(browser->SupportsWindowFeature(Browser::FEATURE_TABSTRIP)
- ? DISPLAYMODE_NORMAL
- : DISPLAYMODE_LOCATION) {
+ display_mode_(GetDisplayMode(browser)) {
set_id(VIEW_ID_TOOLBAR);
chrome::AddCommandObserver(browser_, IDC_BACK, this);
@@ -144,13 +155,19 @@
void ToolbarView::Init() {
location_bar_ = new LocationBarView(browser_, browser_->profile(),
browser_->command_controller(), this,
- !is_display_mode_normal());
+ display_mode_ != DisplayMode::NORMAL);
// Make sure the toolbar shows by default.
size_animation_.Reset(1);
- if (!is_display_mode_normal()) {
+ if (display_mode_ != DisplayMode::NORMAL) {
AddChildView(location_bar_);
location_bar_->Init();
+
+ if (display_mode_ == DisplayMode::CUSTOM_TAB) {
+ custom_tab_bar_ = new CustomTabBarView(browser_, this);
+ AddChildView(custom_tab_bar_);
+ }
+
initialized_ = true;
return;
}
@@ -290,7 +307,11 @@
void ToolbarView::SetToolbarVisibility(bool visible) {
SetVisible(visible);
- location_bar_->SetVisible(visible);
+ views::View* bar = display_mode_ == DisplayMode::CUSTOM_TAB
+ ? static_cast<views::View*>(custom_tab_bar_)
+ : static_cast<views::View*>(location_bar_);
+
+ bar->SetVisible(visible);
}
void ToolbarView::UpdateToolbarVisibility(bool visible, bool animate) {
@@ -498,7 +519,14 @@
if (!initialized_)
return;
- if (!is_display_mode_normal()) {
+ if (display_mode_ == DisplayMode::CUSTOM_TAB) {
+ custom_tab_bar_->SetBounds(0, 0, width(),
+ custom_tab_bar_->GetPreferredSize().height());
+ location_bar_->SetVisible(false);
+ return;
+ }
+
+ if (display_mode_ == DisplayMode::LOCATION) {
location_bar_->SetBounds(0, 0, width(),
location_bar_->GetPreferredSize().height());
return;
@@ -626,7 +654,7 @@
}
void ToolbarView::OnPaintBackground(gfx::Canvas* canvas) {
- if (!is_display_mode_normal())
+ if (display_mode_ != DisplayMode::NORMAL)
return;
const ui::ThemeProvider* tp = GetThemeProvider();
@@ -655,7 +683,7 @@
}
void ToolbarView::OnThemeChanged() {
- if (is_display_mode_normal())
+ if (display_mode_ == DisplayMode::NORMAL)
LoadImages();
}
@@ -695,7 +723,7 @@
// ui::MaterialDesignControllerObserver:
void ToolbarView::OnTouchUiChanged() {
- if (is_display_mode_normal()) {
+ if (display_mode_ == DisplayMode::NORMAL) {
LoadImages();
PreferredSizeChanged();
}
@@ -770,8 +798,12 @@
gfx::Size ToolbarView::GetSizeInternal(
gfx::Size (View::*get_size)() const) const {
- gfx::Size size((location_bar_->*get_size)());
- if (is_display_mode_normal()) {
+ View* view = display_mode_ == DisplayMode::CUSTOM_TAB
+ ? static_cast<View*>(custom_tab_bar_)
+ : static_cast<View*>(location_bar_);
+
+ gfx::Size size = (view->*get_size)();
+ if (display_mode_ == DisplayMode::NORMAL) {
const int element_padding = GetLayoutConstant(TOOLBAR_ELEMENT_PADDING);
const int browser_actions_width =
(browser_actions_->*get_size)().width();
@@ -793,7 +825,7 @@
}
gfx::Size ToolbarView::SizeForContentSize(gfx::Size size) const {
- if (is_display_mode_normal()) {
+ if (display_mode_ == DisplayMode::NORMAL) {
// The size of the toolbar is computed using the size of the location bar
// and constant padding values.
int content_height = std::max(back_->GetPreferredSize().height(),
@@ -810,7 +842,7 @@
}
void ToolbarView::LoadImages() {
- DCHECK(is_display_mode_normal());
+ DCHECK_EQ(display_mode_, DisplayMode::NORMAL);
const ui::ThemeProvider* tp = GetThemeProvider();
diff --git a/chrome/browser/ui/views/toolbar/toolbar_view.h b/chrome/browser/ui/views/toolbar/toolbar_view.h
index 23b8a08..2e2f7aa 100644
--- a/chrome/browser/ui/views/toolbar/toolbar_view.h
+++ b/chrome/browser/ui/views/toolbar/toolbar_view.h
@@ -16,6 +16,7 @@
#include "chrome/browser/ui/toolbar/back_forward_menu_model.h"
#include "chrome/browser/ui/views/frame/browser_root_view.h"
#include "chrome/browser/ui/views/frame/toolbar_button_provider.h"
+#include "chrome/browser/ui/views/location_bar/custom_tab_bar_view.h"
#include "chrome/browser/ui/views/location_bar/location_bar_view.h"
#include "chrome/browser/ui/views/profiles/avatar_toolbar_button.h"
#include "chrome/browser/ui/views/toolbar/browser_actions_container.h"
@@ -68,6 +69,15 @@
public BrowserRootView::DropTarget,
public ui::MaterialDesignControllerObserver {
public:
+ // Types of display mode this toolbar can have.
+ enum class DisplayMode {
+ NORMAL, // Normal toolbar with buttons, etc.
+ LOCATION, // Slimline toolbar showing only compact location
+ // bar, used for popups.
+ CUSTOM_TAB // Custom tab bar, used in PWAs when a location
+ // needs to be displayed.
+ };
+
// The view class name.
static const char kViewClassName[];
@@ -122,6 +132,7 @@
ToolbarButton* back_button() const { return back_; }
ReloadButton* reload_button() const { return reload_; }
LocationBarView* location_bar() const { return location_bar_; }
+ CustomTabBarView* custom_tab_bar() { return custom_tab_bar_; }
media_router::CastToolbarButton* cast_button() const { return cast_; }
AvatarToolbarButton* avatar_button() const { return avatar_; }
BrowserAppMenuButton* app_menu_button() const { return app_menu_button_; }
@@ -175,10 +186,6 @@
bool AcceleratorPressed(const ui::Accelerator& acc) override;
void ChildPreferredSizeChanged(views::View* child) override;
- bool is_display_mode_normal() const {
- return display_mode_ == DISPLAYMODE_NORMAL;
- }
-
protected:
// AccessiblePaneView:
bool SetPaneFocusAndFocusDefault() override;
@@ -186,19 +193,12 @@
// ui::MaterialDesignControllerObserver:
void OnTouchUiChanged() override;
- // This controls Toolbar and LocationBar visibility.
- // If we don't both, tab navigation from the app menu breaks
+ // This controls Toolbar, LocationBar and CustomTabBar visibility.
+ // If we don't set all three, tab navigation from the app menu breaks
// on Chrome OS.
void SetToolbarVisibility(bool visible);
private:
- // Types of display mode this toolbar can have.
- enum DisplayMode {
- DISPLAYMODE_NORMAL, // Normal toolbar with buttons, etc.
- DISPLAYMODE_LOCATION // Slimline toolbar showing only compact location
- // bar, used for popups.
- };
-
// AnimationDelegate:
void AnimationEnded(const gfx::Animation* animation) override;
void AnimationProgressed(const gfx::Animation* animation) override;
@@ -251,6 +251,7 @@
ToolbarButton* forward_ = nullptr;
ReloadButton* reload_ = nullptr;
HomeButton* home_ = nullptr;
+ CustomTabBarView* custom_tab_bar_ = nullptr;
LocationBarView* location_bar_ = nullptr;
BrowserActionsContainer* browser_actions_ = nullptr;
media_router::CastToolbarButton* cast_ = nullptr;
diff --git a/chrome/common/chrome_features.cc b/chrome/common/chrome_features.cc
index 48dc4bd..d1584b3 100644
--- a/chrome/common/chrome_features.cc
+++ b/chrome/common/chrome_features.cc
@@ -212,7 +212,7 @@
// Determines whether out of scope pages in the hosted app will use the
// custom tab UI.
const base::Feature kDesktopPWAsCustomTabUI{"DesktopPWAsCustomTabUI",
- base::FEATURE_ENABLED_BY_DEFAULT};
+ base::FEATURE_DISABLED_BY_DEFAULT};
// Determines whether in scope requests are always opened in the same window.
const base::Feature kDesktopPWAsStayInWindow{"DesktopPWAsStayInWindow",
diff --git a/chrome/test/BUILD.gn b/chrome/test/BUILD.gn
index ab57261..f638d7a 100644
--- a/chrome/test/BUILD.gn
+++ b/chrome/test/BUILD.gn
@@ -1533,6 +1533,7 @@
"../browser/ui/views/hung_renderer_view_browsertest.cc",
"../browser/ui/views/importer/import_lock_dialog_view_browsertest.cc",
"../browser/ui/views/location_bar/content_setting_bubble_dialog_browsertest.cc",
+ "../browser/ui/views/location_bar/custom_tab_bar_view_browsertest.cc",
"../browser/ui/views/location_bar/location_bar_view_browsertest.cc",
"../browser/ui/views/location_bar/location_icon_view_browsertest.cc",
"../browser/ui/views/location_bar/zoom_bubble_view_browsertest.cc",