[lens overlay] Suppress the page action on the NTP

Also adds interactive tests for focused location bar state.

Bug: 344654856
Change-Id: I4001341075abf053738825bbfb347fa33a2ce96f
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/5594613
Commit-Queue: Thomas Lukaszewicz <tluk@chromium.org>
Reviewed-by: Peter Boström <pbos@chromium.org>
Code-Coverage: findit-for-me@appspot.gserviceaccount.com <findit-for-me@appspot.gserviceaccount.com>
Reviewed-by: Eshwar Stalin <estalin@chromium.org>
Cr-Commit-Position: refs/heads/main@{#1310205}
diff --git a/chrome/browser/ui/browser_element_identifiers.cc b/chrome/browser/ui/browser_element_identifiers.cc
index cfa94e3..18482c3 100644
--- a/chrome/browser/ui/browser_element_identifiers.cc
+++ b/chrome/browser/ui/browser_element_identifiers.cc
@@ -34,6 +34,7 @@
 DEFINE_ELEMENT_IDENTIFIER_VALUE(kInactiveTabSettingElementId);
 DEFINE_ELEMENT_IDENTIFIER_VALUE(kInstallPwaElementId);
 DEFINE_ELEMENT_IDENTIFIER_VALUE(kIntentChipElementId);
+DEFINE_ELEMENT_IDENTIFIER_VALUE(kLensOverlayPageActionIconElementId);
 DEFINE_ELEMENT_IDENTIFIER_VALUE(kLensPermissionDialogCancelButtonElementId);
 DEFINE_ELEMENT_IDENTIFIER_VALUE(kLensPermissionDialogOkButtonElementId);
 DEFINE_ELEMENT_IDENTIFIER_VALUE(kLensSearchBubbleElementId);
diff --git a/chrome/browser/ui/browser_element_identifiers.h b/chrome/browser/ui/browser_element_identifiers.h
index 3b21c41..6c69dbd 100644
--- a/chrome/browser/ui/browser_element_identifiers.h
+++ b/chrome/browser/ui/browser_element_identifiers.h
@@ -43,6 +43,7 @@
 DECLARE_ELEMENT_IDENTIFIER_VALUE(kInactiveTabSettingElementId);
 DECLARE_ELEMENT_IDENTIFIER_VALUE(kInstallPwaElementId);
 DECLARE_ELEMENT_IDENTIFIER_VALUE(kIntentChipElementId);
+DECLARE_ELEMENT_IDENTIFIER_VALUE(kLensOverlayPageActionIconElementId);
 DECLARE_ELEMENT_IDENTIFIER_VALUE(kLensPermissionDialogCancelButtonElementId);
 DECLARE_ELEMENT_IDENTIFIER_VALUE(kLensPermissionDialogOkButtonElementId);
 DECLARE_ELEMENT_IDENTIFIER_VALUE(kLensSearchBubbleElementId);
diff --git a/chrome/browser/ui/views/location_bar/lens_overlay_page_action_icon_view.cc b/chrome/browser/ui/views/location_bar/lens_overlay_page_action_icon_view.cc
index 8c6a6c0b..cd4bf1d4 100644
--- a/chrome/browser/ui/views/location_bar/lens_overlay_page_action_icon_view.cc
+++ b/chrome/browser/ui/views/location_bar/lens_overlay_page_action_icon_view.cc
@@ -4,15 +4,46 @@
 
 #include "chrome/browser/ui/views/location_bar/lens_overlay_page_action_icon_view.h"
 
+#include "chrome/browser/search/search.h"
+#include "chrome/browser/ui/browser_element_identifiers.h"
 #include "chrome/browser/ui/color/chrome_color_id.h"
 #include "chrome/browser/ui/lens/lens_overlay_controller.h"
 #include "chrome/browser/ui/views/frame/browser_view.h"
 #include "chrome/browser/ui/views/location_bar/location_bar_view.h"
 #include "chrome/browser/ui/views/omnibox/omnibox_view_views.h"
+#include "chrome/browser/ui/webui/new_tab_page/new_tab_page_ui.h"
+#include "chrome/browser/ui/webui/new_tab_page_third_party/new_tab_page_third_party_ui.h"
+#include "chrome/browser/ui/webui/ntp/new_tab_ui.h"
 #include "chrome/browser/user_education/user_education_service.h"
 #include "components/lens/lens_features.h"
 #include "components/vector_icons/vector_icons.h"
+#include "content/public/browser/navigation_controller.h"
+#include "content/public/browser/navigation_entry.h"
 #include "ui/base/metadata/metadata_impl_macros.h"
+#include "ui/views/view_class_properties.h"
+
+namespace {
+
+// TODO(tluk): Similar bespoke checks are used throughout the codebase, this
+// approach is taken from BookmarkTabHelper. This should be factored out as a
+// common util and other callsites converted to use this.
+bool IsNewTabPage(content::WebContents* const web_contents) {
+  // Use the committed entry (or the visible entry, if the committed entry is
+  // the initial NavigationEntry) so the bookmarks bar disappears at the same
+  // time the page does.
+  CHECK(web_contents);
+  content::NavigationEntry* entry =
+      web_contents->GetController().GetLastCommittedEntry();
+  if (entry->IsInitialEntry()) {
+    entry = web_contents->GetController().GetVisibleEntry();
+  }
+  const GURL& url = entry->GetURL();
+  return NewTabUI::IsNewTab(url) || NewTabPageUI::IsNewTabPageOrigin(url) ||
+         NewTabPageThirdPartyUI::IsNewTabPageOrigin(url) ||
+         search::NavEntryIsInstantNTP(web_contents, entry);
+}
+
+}  // namespace
 
 LensOverlayPageActionIconView::LensOverlayPageActionIconView(
     Browser* browser,
@@ -28,6 +59,8 @@
   image_container_view()->SetFlipCanvasOnPaintForRTLUI(false);
   SetUpForInOutAnimation();
 
+  SetProperty(views::kElementIdentifierKey,
+              kLensOverlayPageActionIconElementId);
   SetLabel(l10n_util::GetStringUTF16(IDS_CONTENT_CONTEXT_LENS_OVERLAY));
   SetUseTonalColorsWhenExpanded(true);
   SetPaintLabelOverSolidBackground(true);
@@ -45,9 +78,15 @@
           focus_manager->GetFocusedView());
     }
   }
+
+  // The overlay is unavailable on the NTP as it is unlikely to be useful to
+  // users on the page, it would also appear immediately when a new tab or
+  // window is created due to focus immediatey jumping into the location bar.
+  auto* web_Contents = GetWebContents();
   const bool lens_overlay_available =
-      GetWebContents() &&
-      LensOverlayController::GetController(GetWebContents()) != nullptr;
+      web_Contents &&
+      LensOverlayController::GetController(web_Contents) != nullptr &&
+      !IsNewTabPage(web_Contents);
   SetVisible(location_bar_has_focus && lens_overlay_available);
   ResetSlideAnimation(true);
 
@@ -56,6 +95,10 @@
   // the last call to IconLabelBubbleView::UpdateBackground() seems to think
   // that the label isn't showing / shouldn't paint over a solid background.
   UpdateBackground();
+
+  if (update_callback_for_testing_) {
+    std::move(update_callback_for_testing_).Run();
+  }
 }
 
 void LensOverlayPageActionIconView::OnExecuting(
diff --git a/chrome/browser/ui/views/location_bar/lens_overlay_page_action_icon_view.h b/chrome/browser/ui/views/location_bar/lens_overlay_page_action_icon_view.h
index 4a4a60f0..962400b 100644
--- a/chrome/browser/ui/views/location_bar/lens_overlay_page_action_icon_view.h
+++ b/chrome/browser/ui/views/location_bar/lens_overlay_page_action_icon_view.h
@@ -5,6 +5,7 @@
 #ifndef CHROME_BROWSER_UI_VIEWS_LOCATION_BAR_LENS_OVERLAY_PAGE_ACTION_ICON_VIEW_H_
 #define CHROME_BROWSER_UI_VIEWS_LOCATION_BAR_LENS_OVERLAY_PAGE_ACTION_ICON_VIEW_H_
 
+#include "base/functional/callback_forward.h"
 #include "base/memory/raw_ptr.h"
 #include "chrome/browser/ui/views/page_action/page_action_icon_view.h"
 #include "ui/base/metadata/metadata_header_macros.h"
@@ -24,6 +25,10 @@
       const LensOverlayPageActionIconView&) = delete;
   ~LensOverlayPageActionIconView() override;
 
+  void set_update_callback_for_testing(base::OnceClosure update_callback) {
+    update_callback_for_testing_ = std::move(update_callback);
+  }
+
  protected:
   // PageActionIconView:
   void UpdateImpl() override;
@@ -35,6 +40,7 @@
 
  private:
   raw_ptr<Browser> browser_;
+  base::OnceClosure update_callback_for_testing_;
 };
 
 #endif  // CHROME_BROWSER_UI_VIEWS_LOCATION_BAR_LENS_OVERLAY_PAGE_ACTION_ICON_VIEW_H_
diff --git a/chrome/browser/ui/views/location_bar/lens_overlay_page_action_icon_view_interactive_uitest.cc b/chrome/browser/ui/views/location_bar/lens_overlay_page_action_icon_view_interactive_uitest.cc
new file mode 100644
index 0000000..a3394fe
--- /dev/null
+++ b/chrome/browser/ui/views/location_bar/lens_overlay_page_action_icon_view_interactive_uitest.cc
@@ -0,0 +1,94 @@
+// Copyright 2024 The Chromium Authors
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+// #include "build/build_config.h"
+#include "chrome/browser/ui/browser_element_identifiers.h"
+#include "chrome/browser/ui/views/frame/browser_view.h"
+#include "chrome/browser/ui/views/location_bar/lens_overlay_page_action_icon_view.h"
+#include "chrome/browser/ui/views/location_bar/location_bar_view.h"
+#include "chrome/browser/ui/views/toolbar/toolbar_view.h"
+#include "chrome/common/webui_url_constants.h"
+#include "chrome/test/base/in_process_browser_test.h"
+#include "chrome/test/base/ui_test_utils.h"
+#include "components/lens/lens_features.h"
+#include "content/public/test/browser_test.h"
+#include "ui/views/interaction/element_tracker_views.h"
+#include "url/url_constants.h"
+
+namespace {
+
+class LensOverlayPageActionIconViewTest : public InProcessBrowserTest {
+ public:
+  LensOverlayPageActionIconViewTest() {
+    scoped_feature_list_.InitWithFeatures({lens::features::kLensOverlay}, {});
+  }
+  LensOverlayPageActionIconViewTest(const LensOverlayPageActionIconViewTest&) =
+      delete;
+  LensOverlayPageActionIconViewTest& operator=(
+      const LensOverlayPageActionIconViewTest&) = delete;
+  ~LensOverlayPageActionIconViewTest() override = default;
+
+  LensOverlayPageActionIconView* lens_overlay_icon_view() {
+    views::View* const icon_view =
+        views::ElementTrackerViews::GetInstance()->GetFirstMatchingView(
+            kLensOverlayPageActionIconElementId,
+            browser()->window()->GetElementContext());
+    return icon_view
+               ? views::AsViewClass<LensOverlayPageActionIconView>(icon_view)
+               : nullptr;
+  }
+
+  LocationBarView* location_bar() {
+    BrowserView* browser_view =
+        BrowserView::GetBrowserViewForBrowser(browser());
+    return views::AsViewClass<LocationBarView>(
+        browser_view->toolbar()->location_bar());
+  }
+
+ private:
+  base::test::ScopedFeatureList scoped_feature_list_;
+};
+
+IN_PROC_BROWSER_TEST_F(LensOverlayPageActionIconViewTest,
+                       ShowsWhenLocationBarFocused) {
+  // Navigate to a non-NTP page.
+  ASSERT_TRUE(
+      ui_test_utils::NavigateToURL(browser(), GURL(url::kAboutBlankURL)));
+
+  LensOverlayPageActionIconView* icon_view = lens_overlay_icon_view();
+  views::FocusManager* focus_manager = icon_view->GetFocusManager();
+  focus_manager->ClearFocus();
+  EXPECT_FALSE(focus_manager->GetFocusedView());
+  EXPECT_FALSE(icon_view->GetVisible());
+
+  // Focus in the location bar should show the icon.
+  base::RunLoop run_loop;
+  icon_view->set_update_callback_for_testing(run_loop.QuitClosure());
+  location_bar()->FocusLocation(false);
+  EXPECT_TRUE(focus_manager->GetFocusedView());
+  run_loop.Run();
+  EXPECT_TRUE(icon_view->GetVisible());
+}
+
+IN_PROC_BROWSER_TEST_F(LensOverlayPageActionIconViewTest, DoesNotShowOnNTP) {
+  // Navigate to the NTP.
+  ASSERT_TRUE(ui_test_utils::NavigateToURL(
+      browser(), GURL(chrome::kChromeUINewTabPageURL)));
+
+  LensOverlayPageActionIconView* icon_view = lens_overlay_icon_view();
+  views::FocusManager* focus_manager = icon_view->GetFocusManager();
+  focus_manager->ClearFocus();
+  EXPECT_FALSE(focus_manager->GetFocusedView());
+  EXPECT_FALSE(icon_view->GetVisible());
+
+  // The icon should remain hidden despite focus in the location bar.
+  base::RunLoop run_loop;
+  icon_view->set_update_callback_for_testing(run_loop.QuitClosure());
+  location_bar()->FocusLocation(false);
+  EXPECT_TRUE(focus_manager->GetFocusedView());
+  run_loop.Run();
+  EXPECT_FALSE(icon_view->GetVisible());
+}
+
+}  // namespace
diff --git a/chrome/test/BUILD.gn b/chrome/test/BUILD.gn
index 8a87688c..35851a6 100644
--- a/chrome/test/BUILD.gn
+++ b/chrome/test/BUILD.gn
@@ -11436,6 +11436,7 @@
         "../browser/ui/views/fullscreen_control/fullscreen_control_view_interactive_uitest.cc",
         "../browser/ui/views/keyboard_access_interactive_uitest.cc",
         "../browser/ui/views/location_bar/cookie_controls/cookie_controls_interactive_uitest.cc",
+        "../browser/ui/views/location_bar/lens_overlay_page_action_icon_view_interactive_uitest.cc",
         "../browser/ui/views/location_bar/location_icon_view_interactive_uitest.cc",
         "../browser/ui/views/location_bar/read_anything_icon_view_interactive_uitest.cc",
         "../browser/ui/views/location_bar/selected_keyword_view_interactive_uitest.cc",