Chrome · Google Lens › Lensoverlay
CVE-2026-106217
Authorization Error in Google Lens (Lensoverlay)
Overview
Medium
Severity
—
CVSS
No
Exploited ITW
Fixed
Fix Status
Changed Functions
| Function | Change | Notes |
|---|---|---|
GetLensSuggestInputschrome/browser/ui/lens/lens_composebox_controller.cc |
modified | |
ifchrome/browser/ui/lens/lens_overlay_controller.cc |
modified | |
lens_search_controller_chrome/browser/ui/lens/lens_search_contextualization_controller.cc |
modified | |
ifchrome/browser/ui/lens/lens_search_contextualization_controller.cc |
modified |
Files Changed
chrome/browser/ui/lens/lens_search_controller.hchrome/browser/ui/lens/lens_search_contextualization_controller.ccchrome/browser/ui/lens/lens_composebox_controller_browsertest.ccchrome/browser/ui/lens/lens_search_controller.ccchrome/browser/ui/lens/lens_overlay_controller.ccchrome/browser/ui/lens/lens_search_contextualization_controller.hchrome/browser/ui/lens/lens_composebox_controller.cc
Patch
From c13c2eeeba9fb7d7442efd85f0e8d5cf805d6e2d Mon Sep 17 00:00:00 2001 From: Jason Hu <[email protected]> Date: Mon, 14 Sep 2026 15:17:22 -0700 Subject: [PATCH] [lensoverlay] Prevent cross-origin leaks during contextualization In flows where the Lens side panel is open without a frozen overlay (e.g., side-panel-only text queries, or after navigating to a live page with the overlay hidden), cross-origin navigations could allow context or session tokens from the initial page to leak into subsequent queries or in-flight extractions. This CL prevents cross-origin context leaks by: 1. Setting session_origin_ on LensSearchController and guarding contextualization access via IsCurrentTabSameOrigin(). 2. Canceling in-flight extraction in LensSearchContextualizationController on PrimaryPageChanged via a dedicated in_flight_weak_ptr_factory_. 3. Sanitizing suggest inputs and query message payloads in LensComposeboxController and blocking overlay reshow / context updates in LensOverlayController when the tab has navigated cross-origin. Bug: 501770489 Change-Id: I4e3745783f128a897629bb419198d39b59d6a2c4 Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/8403211 Reviewed-by: Juan Mojica <[email protected]> Commit-Queue: Jason Hu <[email protected]> Cr-Commit-Position: refs/heads/main@{#1697593} --- diff --git a/chrome/browser/ui/lens/lens_composebox_controller.cc b/chrome/browser/ui/lens/lens_composebox_controller.cc index 4cf389e..88003456 100644 --- a/chrome/browser/ui/lens/lens_composebox_controller.cc +++ b/chrome/browser/ui/lens/lens_composebox_controller.cc @@ -146,6 +146,10 @@ return; } + if (!lens_search_controller_->IsCurrentTabSameOrigin()) { + return; + } + // Ignore if contextualization is not active. if (!lens_search_controller_->lens_search_contextualization_controller() ->IsActive()) { @@ -270,6 +274,9 @@ lens::proto::LensOverlaySuggestInputs LensComposeboxController::GetLensSuggestInputs() const { + if (!lens_search_controller_->IsCurrentTabSameOrigin()) { + return lens::proto::LensOverlaySuggestInputs(); + } if (!lens::features::GetAimSuggestionsEnabled()) { return lens::proto::LensOverlaySuggestInputs(); } @@ -329,13 +336,15 @@ lens_image_query_data->set_search_session_id( query_controller->search_session_id()); + const bool is_same_origin = lens_search_controller_->IsCurrentTabSameOrigin(); const auto& primary_content_type = - contextualization_controller->primary_content_type(); + is_same_origin ? contextualization_controller->primary_content_type() + : lens::MimeType::kUnknown; const auto media_type = overlay_controller->HasRegionSelection() ? lens::LensOverlayRequestId::MEDIA_TYPE_DEFAULT_IMAGE : MimeTypeToMediaType(primary_content_type, - /*has_viewport_screenshot=*/true); + /*has_viewport_screenshot=*/is_same_origin); lens_image_query_data->mutable_request_id()->CopyFrom( *query_controller->GetNextRequestId(lens::RequestIdUpdateMode::kSearchUrl, media_type)); @@ -346,7 +355,7 @@ std::optional<lens::LensOverlayVisualSearchInteractionData> visual_search_interaction_data = query_controller->GetVisualSearchInteractionData(); - if (visual_search_interaction_data && + if (is_same_origin && visual_search_interaction_data && overlay_controller->HasRegionSelection()) { lens_image_query_data->mutable_visual_search_interaction_data()->CopyFrom( visual_search_interaction_data.value()); diff --git a/chrome/browser/ui/lens/lens_overlay_controller.cc b/chrome/browser/ui/lens/lens_overlay_controller.cc index 60e3b79..ce44f4e 100644 --- a/chrome/browser/ui/lens/lens_overlay_controller.cc +++ b/chrome/browser/ui/lens/lens_overlay_controller.cc @@ -906,6 +906,9 @@ GetLensSessionMetricsLogger()->OnSearchboxFocused(); if (state() == State::kHidden) { + if (!lens_search_controller_->IsCurrentTabSameOrigin()) { + return; + } // If the live page is showing and the searchbox becomes focused, showing // intent to issue a new query, upload the new page content for // contextualization. @@ -1136,6 +1139,11 @@ if (page_context_start_time.has_value()) { lens::RecordTimeToGetPageContext(base::TimeTicks::Now() - invocation_time_); } + if (!lens_search_controller_->IsCurrentTabSameOrigin()) { + page_contents.clear(); + primary_content_type = lens::MimeType::kUnknown; + page_count = std::nullopt; + } initialization_data->page_contents_ = page_contents; initialization_data->primary_content_type_ = primary_content_type; initialization_data->pdf_page_count_ = page_count; @@ -1912,6 +1920,9 @@ } void LensOverlayController::ReshowOverlay() { + if (!lens_search_controller_->IsCurrentTabSameOrigin()) { + return; + } OverlayBaseController::ReshowOverlay(); use_aim_for_visual_search_ = true; @@ -2109,6 +2120,9 @@ } void LensOverlayController::NotifyPageContentUpdated() { + if (!lens_search_controller_->IsCurrentTabSameOrigin()) { + return; + } auto page_content_type = lens::StringMimeTypeToMojoPageContentType( tab_->GetContents()->GetContentsMimeType()); if (page_) { @@ -2235,6 +2249,9 @@ } void LensOverlayController::ReshowOverlayPart2() { + if (!lens_search_controller_->IsCurrentTabSameOrigin()) { + return; + } ReshowScreenshot(GetContextualizationController()->viewport_screenshot(), base::BindOnce(&LensOverlayController::ReshowOverlayPart3, weak_factory_.GetWeakPtr())); diff --git a/chrome/browser/ui/lens/lens_search_contextualization_controller.cc b/chrome/browser/ui/lens/lens_search_contextualization_controller.cc index 5b1da1e..4f539de8 100644 --- a/chrome/browser/ui/lens/lens_search_contextualization_controller.cc +++ b/chrome/browser/ui/lens/lens_search_contextualization_controller.cc @@ -143,10 +143,38 @@ LensSearchContextualizationController::LensSearchContextualizationController( LensSearchController* lens_search_controller) - : lens_search_controller_(lens_search_controller) {} + : content::WebContentsObserver( + lens_search_controller->GetTabInterface() + ? lens_search_controller->GetTabInterface()->GetContents() + : nullptr), + lens_search_controller_(lens_search_controller) {} LensSearchContextualizationController:: ~LensSearchContextualizationController() = default; +void LensSearchContextualizationController::CancelInFlightContextualization() { + in_flight_weak_ptr_factory_.InvalidateWeakPtrs(); + is_page_context_eligible_ = false; + page_contents_.clear(); + primary_content_type_ = lens::MimeType::kUnknown; + viewport_screenshot_.reset(); + last_retrieved_most_visible_page_ = std::nullopt; + pdf_partial_page_text_retrieved_callback_.Reset(); + pdf_pages_text_.clear(); + page_context_eligibility_callback_.Reset(); + pending_context_eligibility_params_.reset(); + if (state_ == State::kInitializing) { + state_ = State::kOff; + } + if (on_page_context_updated_callback_) { + std::move(on_page_context_updated_callback_).Run(); + } +} + +void LensSearchContextualizationController::PrimaryPageChanged( + content::Page& page) { + CancelInFlightContextualization(); +} + void LensSearchContextualizationController::StartContextualization( lens::LensOverlayInvocationSource invocation_source, OnPageContextUpdatedCallback callback) { @@ -157,14 +185,16 @@ // needed. StartScreenshotFlow(base::BindOnce( &LensSearchContextualizationController::OnScreenshotTakenForContextual, - weak_ptr_factory_.GetWeakPtr(), std::move(callback))); + in_flight_weak_ptr_factory_.GetWeakPtr(), std::move(callback))); } void LensSearchContextualizationController::GetPageContextualization( PageContentRetrievedCallback callback) { - // If the contextual searchbox is disabled, exit early. + // If the contextual searchbox is disabled or tab is not same origin, exit + // early. if (!lens::IsLensOverlayContextualSearchboxEnabled( - lens_search_controller_->GetProfile())) { + lens_search_controller_->GetProfile()) || + !lens_search_controller_->IsCurrentTabSameOrigin()) { std::move(callback).Run(/*page_contents=*/{}, lens::MimeType::kUnknown, std::nullopt); return; @@ -209,6 +239,10 @@ // controller finishes initializing. return; } + if (!lens_search_controller_->IsCurrentTabSameOrigin()) { + std::move(callback).Run(); + return; + } if (state_ == State::kOff) { // TODO(crbug.com/418825720): The viewport screenshot should be only be set // in this controller in the future. @@ -230,7 +264,7 @@ on_page_context_updated_callback_ = std::move(callback); GetPageContextualization(base::BindOnce( &LensSearchContextualizationController::UpdatePageContextualization, - weak_ptr_factory_.GetWeakPtr())); + in_flight_weak_ptr_factory_.GetWeakPtr())); } #if BUILDFLAG(ENABLE_PDF) @@ -258,24 +292,16 @@ /*page_index=*/0, base::BindOnce( &LensSearchContextualizationController::GetPartialPdfTextCallback, - weak_ptr_factory_.GetWeakPtr(), /*page_index=*/0, page_count, + in_flight_weak_ptr_factory_.GetWeakPtr(), /*page_index=*/0, + page_count, /*total_characters_retrieved=*/0)); } #endif // BUILDFLAG(ENABLE_PDF) void LensSearchContextualizationController::ResetState() { on_page_context_updated_callback_.Reset(); - is_page_context_eligible_ = false; + CancelInFlightContextualization(); ocr_dom_similarity_recorded_in_session_ = false; - page_contents_.clear(); - primary_content_type_ = lens::MimeType::kUnknown; - viewport_screenshot_.reset(); - last_retrieved_most_visible_page_ = std::nullopt; - pdf_partial_page_text_retrieved_callback_.Reset(); - pdf_pages_text_.clear(); - // Reset the page context eligibility API state. - page_context_eligibility_callback_.Reset(); - pending_context_eligibility_params_.reset(); weak_ptr_factory_.InvalidateWeakPtrs(); state_ = State::kOff; } @@ -319,7 +345,7 @@ *render_frame_host, /*node_id=*/std::nullopt, base::BindOnce( &LensSearchContextualizationController::RecordInnerTextSize, - weak_ptr_factory_.GetWeakPtr())); + in_flight_weak_ptr_factory_.GetWeakPtr())); } // Try and record the OCR DOM similarity since the page content is now @@ -376,8 +402,12 @@ std::vector<lens::PageContent> page_contents, lens::MimeType primary_content_type, std::optional<uint32_t> page_count) { - // Exit early if the controller is off. - if (state_ == State::kOff) { + // Exit early if the controller is off or the tab is not same origin. + if (state_ == State::kOff || + !lens_search_controller_->IsCurrentTabSameOrigin()) { + if (on_page_context_updated_callback_) { + std::move(on_page_context_updated_callback_).Run(); + } return; } @@ -407,8 +437,8 @@ // Begin the process of grabbing a screenshot. CaptureScreenshot(base::BindOnce( &LensSearchContextualizationController::UpdatePageContextualizationPart2, - weak_ptr_factory_.GetWeakPtr(), page_contents, primary_content_type, - page_count)); + in_flight_weak_ptr_factory_.GetWeakPtr(), page_contents, + primary_content_type, page_count)); } void LensSearchContextualizationController::UpdatePageContextualizationPart2( @@ -430,8 +460,8 @@ if (pdf_helper) { pdf_helper->GetMostVisiblePageIndex(base::BindOnce( &LensSearchContextualizationController::UpdatePageContext, - weak_ptr_factory_.GetWeakPtr(), page_contents, primary_content_type, - page_count, bitmap)); + in_flight_weak_ptr_factory_.GetWeakPtr(), page_contents, + primary_content_type, page_count, bitmap)); return; } #endif // BUILDFLAG(ENABLE_PDF) @@ -449,7 +479,11 @@ // It's possible the Lens session could have been closed while updating the // page context. Return early and do not run the callback as it should have // been cleared. - if (state_ == State::kOff) { + if (state_ == State::kOff || + !lens_search_controller_->IsCurrentTabSameOrigin()) { + if (on_page_context_updated_callback_) { + std::move(on_page_context_updated_callback_).Run(); + } return; } @@ -551,7 +585,7 @@ page_count.value_or(0), base::BindOnce(&LensSearchContextualizationController:: OnPdfPartialPageTextRetrieved, - weak_ptr_factory_.GetWeakPtr())); + in_flight_weak_ptr_factory_.GetWeakPtr())); } #endif @@ -583,8 +617,8 @@ *render_frame_host, /*node_id=*/std::nullopt, base::BindOnce( &LensSearchContextualizationController::OnInnerTextReceived, - weak_ptr_factory_.GetWeakPtr(), page_contents, render_frame_host, - std::move(callback))); + in_flight_weak_ptr_factory_.GetWeakPtr(), page_contents, + render_frame_host, std::move(callback))); } void LensSearchContextualizationController::OnInnerTextReceived( @@ -592,6 +626,12 @@ content::RenderFrameHost* render_frame_host, PageContentRetrievedCallback callback, std::unique_ptr<content_extraction::InnerTextResult> result) { + if (!lens_search_controller_->IsCurrentTabSameOrigin()) { + std::move(callback).Run(/*page_contents=*/{}, lens::MimeType::kUnknown, + std::nullopt); + return; + } + const bool was_successful = result && result->inner_text.size() <= lens::features::GetLensOverlayFileUploadLimitBytes(); @@ -633,7 +673,7 @@ std::move(ai_page_content_options), base::BindOnce(&LensSearchContextualizationController:: OnAnnotatedPageContentReceived, - weak_ptr_factory_.GetWeakPtr(), page_contents, + in_flight_weak_ptr_factory_.GetWeakPtr(), page_contents, std::move(callback))); } @@ -641,6 +681,12 @@ std::vector<lens::PageContent> page_contents, PageContentRetrievedCallback callback, optimization_guide::AIPageContentResultOrError result) { + if (!lens_search_controller_->IsCurrentTabSameOrigin()) { + std::move(callback).Run(/*page_contents=*/{}, lens::MimeType::kUnknown, + std::nullopt); + return; + } + // The tab URL is used to check if the page is context eligible. const auto& tab_url = lens_search_controller_->GetTabInterface() ->GetContents() @@ -659,17 +705,18 @@ tab_url, std::move(frame_metadata_structs), base::BindOnce(&LensSearchContextualizationController:: OnPageContextEligibilityFetched, - weak_ptr_factory_.GetWeakPtr(), std::move(page_contents), - std::move(callback), std::move(result.value()))); + in_flight_weak_ptr_factory_.GetWeakPtr(), + std::move(page_contents), std::move(callback), + std::move(result.value()))); return; } - IsPageContextEligible( - tab_url, {}, - base::BindOnce(&LensSearchContextualizationController:: - OnPageContextEligibilityFetched, - weak_ptr_factory_.GetWeakPtr(), std::move(page_contents), - std::move(callback), std::nullopt)); + IsPageContextEligible(tab_url, {}, + base::BindOnce(&LensSearchContextualizationController:: + OnPageContextEligibilityFetched, + in_flight_weak_ptr_factory_.GetWeakPtr(), + std::move(page_contents), + std::move(callback), std::nullopt)); } void LensSearchContextualizationController::OnPageContextEligibilityFetched( @@ -677,6 +724,12 @@ PageContentRetrievedCallback callback, std::optional<optimization_guide::AIPageContentResult> result, bool is_page_context_eligible) { + if (!lens_search_controller_->IsCurrentTabSameOrigin()) { + std::move(callback).Run(/*page_contents=*/{}, lens::MimeType::kUnknown, + std::nullopt); + return; + } + ... (file diff truncated)
Loading diff…
Regression Test / PoC
shipped with the fix
diff --git a/chrome/browser/ui/lens/lens_composebox_controller_browsertest.cc b/chrome/browser/ui/lens/lens_composebox_controller_browsertest.cc
index dc83fdba..3091ad22 100644
--- a/chrome/browser/ui/lens/lens_composebox_controller_browsertest.cc
+++ b/chrome/browser/ui/lens/lens_composebox_controller_browsertest.cc
@@ -39,6 +39,7 @@
#include "content/public/test/browser_test.h"
#include "content/public/test/browser_test_utils.h"
#include "content/public/test/test_navigation_observer.h"
+#include "net/dns/mock_host_resolver.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "third_party/lens_server_proto/aim_communication.pb.h"
#include "ui/base/unowned_user_data/user_data_factory.h"
@@ -197,6 +198,7 @@
void SetUpOnMainThread() override {
InProcessBrowserTest::SetUpOnMainThread();
+ host_resolver()->AddRule("*", "127.0.0.1");
embedded_test_server()->StartAcceptingConnections();
// Permits sharing the page screenshot by default.
@@ -1396,3 +1398,213 @@
// Simulate focus. This should not crash.
GetLensComposeboxController()->OnFocusChanged(true);
}
+
+IN_PROC_BROWSER_TEST_F(LensComposeboxControllerBrowserTest,
+ LensButtonClickDoesNotReshowOnDifferentOrigin) {
+ const GURL initial_url =
+ embedded_test_server()->GetURL("a.com", "/select.html");
+ ASSERT_TRUE(ui_test_utils::NavigateToURL(browser(), initial_url));
+
+ auto* controller = GetLensSearchController();
+ ASSERT_TRUE(controller->IsOff());
+
+ // Issue a text search request to open the side panel without the overlay.
+ controller->IssueTextSearchRequest(
+ lens::LensOverlayInvocationSource::kContentAreaContextMenuText, "query",
+ {}, AutocompleteMatchType::Type::SEARCH_WHAT_YOU_TYPED,
+ /*is_zero_prefix_suggestion=*/false,
+ /*suppress_contextualization=*/true);
+
+ // Wait for side panel to be visible.
+ ASSERT_TRUE(
+ base::test::RunUntil([&]() { return IsResultsSidePanelShowing(); }));
+
+ // Wait for the composebox handler to be set.
+ ASSERT_TRUE(base::test::RunUntil([&]() {
+ return GetLensComposeboxController()->composebox_handler_for_testing() !=
+ nullptr;
+ }));
+
+ auto* overlay_controller = GetLensOverlayController();
+ EXPECT_FALSE(overlay_controller->IsOverlayActive());
+
+ // Navigate the main tab to a different origin.
+ const GURL different_origin_url =
+ embedded_test_server()->GetURL("b.com", "/title1.html");
+ ASSERT_TRUE(ui_test_utils::NavigateToURL(browser(), different_origin_url));
+
+ // Trigger Lens button click from composebox handler.
+ GetLensComposeboxController()
+ ->composebox_handler_for_testing()
+ ->HandleLensButtonClick();
+
+ // The overlay must not open on the different origin.
+ EXPECT_FALSE(overlay_controller->IsOverlayActive());
+ EXPECT_NE(overlay_controller->state(), State::kOverlay);
+}
+
+IN_PROC_BROWSER_TEST_F(LensComposeboxControllerBrowserTest,
+ FocusChangedDoesNotContextualizeOnDifferentOrigin) {
+ const GURL initial_url =
+ embedded_test_server()->GetURL("a.com", "/select.html");
+ ASSERT_TRUE(ui_test_utils::NavigateToURL(browser(), initial_url));
+
+ auto* controller = GetLensSearchController();
+ ASSERT_TRUE(controller->IsOff());
+
+ // Issue a text search request to open the side panel without the overlay.
+ controller->IssueTextSearchRequest(
+ lens::LensOverlayInvocationSource::kContentAreaContextMenuText, "query",
+ {}, AutocompleteMatchType::Type::SEARCH_WHAT_YOU_TYPED,
+ /*is_zero_prefix_suggestion=*/false,
+ /*suppress_contextualization=*/true);
+
+ // Wait for side panel to be visible.
+ ASSERT_TRUE(
+ base::test::RunUntil([&]() { return IsResultsSidePanelShowing(); }));
+
+ // Wait for the composebox handler to be set.
+ ASSERT_TRUE(base::test::RunUntil([&]() {
+ return GetLensComposeboxController()->composebox_handler_for_testing() !=
+ nullptr;
+ }));
+
+ auto* fake_query_controller =
+ static_cast<lens::TestLensOverlayQueryController*>(
+ controller->lens_overlay_query_controller());
+ ASSERT_TRUE(base::test::RunUntil([&]() {
+ return fake_query_controller->num_full_image_requests_sent() == 1 &&
+ fake_query_controller->num_page_content_update_requests_sent() == 1;
+ }));
+
+ const int initial_updates =
+ fake_query_controller->num_page_content_update_requests_sent();
+
+ auto* composebox_controller = GetLensComposeboxController();
+ auto* test_composebox_controller =
+ static_cast<TestLensComposeboxController*>(composebox_controller);
+ ASSERT_TRUE(test_composebox_controller);
+ MockSearchboxPage& mock_searchbox_page =
+ test_composebox_controller->mock_searchbox_page();
+ EXPECT_CALL(mock_searchbox_page, SetThumbnail(testing::_, testing::_))
+ .Times(0);
+
+ // Navigate the main tab to a different origin.
+ const GURL different_origin_url =
+ embedded_test_server()->GetURL("b.com", "/title1.html");
+ ASSERT_TRUE(ui_test_utils::NavigateToURL(browser(), different_origin_url));
+
+ // Trigger FocusChanged from composebox handler.
+ GetLensComposeboxController()->composebox_handler_for_testing()->FocusChanged(
+ true);
+
+ // Verify that no new page content update was sent for the different origin.
+ EXPECT_EQ(fake_query_controller->num_page_content_update_requests_sent(),
+ initial_updates);
+}
+
+IN_PROC_BROWSER_TEST_F(LensComposeboxControllerBrowserTest,
+ OpenLensOverlayInCurrentSessionRequiresPermission) {
+ WaitForPaint();
+
+ auto* controller = GetLensSearchController();
+ ASSERT_TRUE(controller->IsOff());
+
+ // Issue a text search request to open the side panel without the overlay.
+ controller->IssueTextSearchRequest(
+ lens::LensOverlayInvocationSource::kContentAreaContextMenuText, "query",
+ {}, AutocompleteMatchType::Type::SEARCH_WHAT_YOU_TYPED,
+ /*is_zero_prefix_suggestion=*/false,
+ /*suppress_contextualization=*/true);
+
+ // Wait for side panel to be visible.
+ ASSERT_TRUE(
+ base::test::RunUntil([&]() { return IsResultsSidePanelShowing(); }));
+
+ // Wait for the composebox handler to be set.
+ ASSERT_TRUE(base::test::RunUntil([&]() {
+ return GetLensComposeboxController()->composebox_handler_for_testing() !=
+ nullptr;
+ }));
+
+ auto* overlay_controller = GetLensOverlayController();
+ EXPECT_FALSE(overlay_controller->IsOverlayActive());
+
+ // Revoke screenshot and content permissions.
+ PrefService* prefs = browser()->GetProfile()->GetPrefs();
+ prefs->SetBoolean(lens::prefs::kLensSharingPageScreenshotEnabled, false);
+ prefs->SetBoolean(lens::prefs::kLensSharingPageContentEnabled, false);
+
+ // Attempt to open overlay in current session without permission.
+ controller->OpenLensOverlayInCurrentSession();
+
+ // Overlay should not open because eligibility checks require permission.
+ EXPECT_FALSE(overlay_controller->IsOverlayActive());
+ EXPECT_NE(overlay_controller->state(), State::kOverlay);
+}
+
+IN_PROC_BROWSER_TEST_F(LensComposeboxControllerBrowserTest,
+ SuggestInputsAndSubmitQueryClearedOnDifferentOrigin) {
+ const GURL initial_url =
+ embedded_test_server()->GetURL("a.com", "/select.html");
+ ASSERT_TRUE(ui_test_utils::NavigateToURL(browser(), initial_url));
+
+ auto* controller = GetLensSearchController();
+ ASSERT_TRUE(controller->IsOff());
+
+ // Issue a text search request to open the side panel without the overlay.
+ controller->IssueTextSearchRequest(
+ lens::LensOverlayInvocationSource::kContentAreaContextMenuText, "query",
+ {}, AutocompleteMatchType::Type::SEARCH_WHAT_YOU_TYPED,
+ /*is_zero_prefix_suggestion=*/false,
+ /*suppress_contextualization=*/true);
+
+ ASSERT_TRUE(
+ base::test::RunUntil([&]() { return IsResultsSidePanelShowing(); }));
+
+ ASSERT_TRUE(base::test::RunUntil([&]() {
+ return GetLensComposeboxController()->composebox_handler_for_testing() !=
+ nullptr;
+ }));
+
+ EXPECT_TRUE(controller->IsCurrentTabSameOrigin());
+
+ // Navigate to different origin.
+ const GURL different_origin_url =
+ embedded_test_server()->GetURL("b.com", "/title1.html");
+ ASSERT_TRUE(ui_test_utils::NavigateToURL(browser(), different_origin_url));
+
+ EXPECT_FALSE(controller->IsCurrentTabSameOrigin());
+
+ // Suggest inputs should be empty on different origin.
+ auto suggest_inputs = GetLensComposeboxController()->GetLensSuggestInputs();
+ EXPECT_TRUE(
+ suggest_inputs.encoded_visual_search_interaction_log_data().empty());
+ EXPECT_TRUE(suggest_inputs.search_session_id().empty());
+
+ // Mock a handshake call so the composebox controller can send query messages.
+ lens::AimToClientMessage aim_to_client_message;
+ aim_to_client_message.mutable_handshake_response()->add_capabilities(
+ lens::FeatureCapability::DEFAULT);
+ MockAimToClientMessage(aim_to_client_message);
+
+ // SubmitQuery message should not include visual search interaction data or
+ // valid visual input type for the different origin.
+ GetLensComposeboxController()->composebox_handler_for_testing()->SubmitQuery(
+ "new query", /*mouse_button=*/0, /*alt_key=*/false, /*ctrl_key=*/false,
+ /*meta_key=*/false, /*shift_key=*/false, /*is_voice_search=*/false);
+
+ auto* test_side_panel_coordinator = GetLensSidePanelCoordinator();
+ ASSERT_TRUE(test_side_panel_coordinator);
+ ASSERT_TRUE(test_side_panel_coordinator->last_sent_client_message_to_aim_
+ .has_submit_query());
+ const auto& submit_query =
+ test_side_panel_coordinator->last_sent_client_message_to_aim_
+ .submit_query();
+ ASSERT_EQ(submit_query.payload().lens_image_query_data_size(), 1);
+ const auto& image_query_data =
+ submit_query.payload().lens_image_query_data(0);
+ EXPECT_FALSE(image_query_data.has_visual_search_interaction_data());
+ EXPECT_EQ(image_query_data.visual_input_type(),
+ lens::LensOverlayVisualInputType::VISUAL_INPUT_TYPE_UNKNOWN);
+}
Loading diff…
Original Bug Report
The reporter's bug is still restricted on the tracker. Chrome de-restricts security bugs ~30–90 days after the fix ships; a later run will backfill it here.
References
On This Page