[ntp] OneGoogleBar AsyncBarParts integration
Bug: 373569279
Change-Id: I9274845246e99d2b26b2a4e71381f49ec2e6ac73
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/6177840
Commit-Queue: Roman Arora <romanarora@chromium.org>
Reviewed-by: Riley Tatum <rtatum@google.com>
Cr-Commit-Position: refs/heads/main@{#1407391}
diff --git a/chrome/browser/new_tab_page/one_google_bar/one_google_bar_loader_impl.cc b/chrome/browser/new_tab_page/one_google_bar/one_google_bar_loader_impl.cc
index 635ef8d..c7217a50 100644
--- a/chrome/browser/new_tab_page/one_google_bar/one_google_bar_loader_impl.cc
+++ b/chrome/browser/new_tab_page/one_google_bar/one_google_bar_loader_impl.cc
@@ -18,6 +18,7 @@
#include "chrome/common/chrome_content_client.h"
#include "chrome/common/webui_url_constants.h"
#include "components/google/core/common/google_util.h"
+#include "components/search/ntp_features.h"
#include "components/signin/public/identity_manager/tribool.h"
#include "components/variations/net/variations_http_headers.h"
#include "google_apis/gaia/gaia_id.h"
@@ -94,7 +95,8 @@
} // namespace safe_html
-std::optional<OneGoogleBarData> JsonToOGBData(const base::Value& value) {
+std::optional<OneGoogleBarData> JsonToOGBData(const base::Value& value,
+ bool expect_async_bar_parts) {
if (!value.is_dict()) {
DVLOG(1) << "Parse error: top-level dictionary not found";
return std::nullopt;
@@ -113,16 +115,19 @@
language_code = *maybe_language;
}
- const base::Value::Dict* one_google_bar = update->FindDict("ogb");
+ OneGoogleBarData result;
+ result.language_code = language_code;
+
+ const base::Value::Dict* one_google_bar =
+ update->FindDict(expect_async_bar_parts ? "ogb_parts" : "ogb");
if (!one_google_bar) {
DVLOG(1) << "Parse error: no ogb";
return std::nullopt;
}
- OneGoogleBarData result;
- result.language_code = language_code;
-
- if (!safe_html::GetHtml(*one_google_bar, "html", &result.bar_html)) {
+ if (!safe_html::GetHtml(*one_google_bar,
+ expect_async_bar_parts ? "right_html" : "html",
+ &result.bar_html)) {
DVLOG(1) << "Parse error: no html";
return std::nullopt;
}
@@ -284,8 +289,9 @@
bool account_consistency_mirror_required)
: url_loader_factory_(url_loader_factory),
application_locale_(application_locale),
- account_consistency_mirror_required_(
- account_consistency_mirror_required) {}
+ account_consistency_mirror_required_(account_consistency_mirror_required),
+ async_bar_parts_(base::FeatureList::IsEnabled(
+ ntp_features::kNtpOneGoogleBarAsyncBarParts)) {}
OneGoogleBarLoaderImpl::~OneGoogleBarLoaderImpl() = default;
@@ -337,6 +343,9 @@
if (additional_query_params_.find("&async=") == std::string::npos) {
query += "&async=fixed:0";
}
+ if (async_bar_parts_) {
+ query += "&expflags=OgbModule__use_async_bar_parts:true";
+ }
if (query.at(0) == '&') {
query = query.substr(1);
}
@@ -380,7 +389,8 @@
return;
}
- std::optional<OneGoogleBarData> data = JsonToOGBData(*result);
+ std::optional<OneGoogleBarData> data =
+ JsonToOGBData(*result, async_bar_parts_);
Respond(data.has_value() ? Status::OK : Status::FATAL_ERROR, data);
}
diff --git a/chrome/browser/new_tab_page/one_google_bar/one_google_bar_loader_impl.h b/chrome/browser/new_tab_page/one_google_bar/one_google_bar_loader_impl.h
index 06aeb257..39fd6f24 100644
--- a/chrome/browser/new_tab_page/one_google_bar/one_google_bar_loader_impl.h
+++ b/chrome/browser/new_tab_page/one_google_bar/one_google_bar_loader_impl.h
@@ -54,6 +54,7 @@
scoped_refptr<network::SharedURLLoaderFactory> url_loader_factory_;
const std::string application_locale_;
const bool account_consistency_mirror_required_;
+ const bool async_bar_parts_;
std::vector<OneGoogleCallback> callbacks_;
std::unique_ptr<AuthenticatedURLLoader> pending_request_;
diff --git a/chrome/browser/new_tab_page/one_google_bar/one_google_bar_loader_impl_unittest.cc b/chrome/browser/new_tab_page/one_google_bar/one_google_bar_loader_impl_unittest.cc
index e5f2efe..0eaf0be1 100644
--- a/chrome/browser/new_tab_page/one_google_bar/one_google_bar_loader_impl_unittest.cc
+++ b/chrome/browser/new_tab_page/one_google_bar/one_google_bar_loader_impl_unittest.cc
@@ -12,11 +12,13 @@
#include "base/strings/stringprintf.h"
#include "base/test/bind.h"
#include "base/test/mock_callback.h"
+#include "base/test/scoped_feature_list.h"
#include "base/test/test_simple_task_runner.h"
#include "base/time/time.h"
#include "build/build_config.h"
#include "build/chromeos_buildflags.h"
#include "chrome/browser/new_tab_page/one_google_bar/one_google_bar_data.h"
+#include "components/search/ntp_features.h"
#include "components/signin/core/browser/signin_header_helper.h"
#include "components/variations/scoped_variations_ids_provider.h"
#include "content/public/test/browser_task_environment.h"
@@ -50,6 +52,11 @@
"page_hooks": {}
}}})json";
+const char kMinimalBarPartsValidResponse[] = R"json({"update": { "ogb_parts": {
+ "right_html": { "private_do_not_access_or_else_safe_html_wrapped_value": "" },
+ "page_hooks": {}
+}}})json";
+
// Returns the value of the "enable_account_consistency" parameter in the
// "X-ChromeConnected" header. The header is expected to be in the format:
// param1=value1,param2=value2,[...],paramN=valueN
@@ -97,6 +104,10 @@
}
#endif
+ InitOneGoogleBarLoader();
+ }
+
+ void InitOneGoogleBarLoader() {
one_google_bar_loader_ = std::make_unique<OneGoogleBarLoaderImpl>(
test_shared_loader_factory_, kApplicationLocale,
account_consistency_mirror_required_);
@@ -198,6 +209,26 @@
EXPECT_TRUE(data.has_value());
}
+TEST_F(OneGoogleBarLoaderImplTest, BarPartsRequestReturns) {
+ base::test::ScopedFeatureList features;
+ features.InitWithFeatures(
+ /*enabled_features=*/{ntp_features::kNtpOneGoogleBarAsyncBarParts},
+ /*disabled_features=*/{});
+ InitOneGoogleBarLoader();
+ SetUpResponseWithData(kMinimalBarPartsValidResponse);
+
+ base::MockCallback<OneGoogleBarLoader::OneGoogleCallback> callback;
+ one_google_bar_loader()->Load(callback.Get());
+
+ std::optional<OneGoogleBarData> data;
+ base::RunLoop loop;
+ EXPECT_CALL(callback, Run(OneGoogleBarLoader::Status::OK, _))
+ .WillOnce(DoAll(SaveArg<1>(&data), Quit(&loop)));
+ loop.Run();
+
+ EXPECT_TRUE(data.has_value());
+}
+
TEST_F(OneGoogleBarLoaderImplTest, HandlesResponsePreamble) {
// The reponse may contain a ")]}'" prefix. The loader should ignore that
// during parsing.
diff --git a/chrome/browser/resources/new_tab_page/untrusted/one_google_bar.html b/chrome/browser/resources/new_tab_page/untrusted/one_google_bar.html
index 3a59760..38213ad2 100644
--- a/chrome/browser/resources/new_tab_page/untrusted/one_google_bar.html
+++ b/chrome/browser/resources/new_tab_page/untrusted/one_google_bar.html
@@ -23,6 +23,7 @@
$i18nRaw{inHeadStyle}
</style>
+ <script>$i18nRaw{varsHeadScript}</script>
<script>$i18nRaw{inHeadScript}</script>
</head>
<body>
diff --git a/chrome/browser/resources/new_tab_page/untrusted/one_google_bar.ts b/chrome/browser/resources/new_tab_page/untrusted/one_google_bar.ts
index 9c1eea5..3a34f07 100644
--- a/chrome/browser/resources/new_tab_page/untrusted/one_google_bar.ts
+++ b/chrome/browser/resources/new_tab_page/untrusted/one_google_bar.ts
@@ -4,6 +4,8 @@
type MessageType = 'overlaysUpdated'|'click'|'loaded';
+declare let abp: boolean;
+
/**
* The following |messageType|'s are sent to the parent frame:
* - loaded: sent on initial load.
@@ -26,10 +28,14 @@
setForegroundStyle(style: number): void;
}
+interface AsyncBar {
+ setDarkMode(matches: boolean): void;
+}
+
const oneGoogleBarApi = (() => {
type IndexableApi = Record<string, Function>;
interface Gbar {
- gbar?: {a: Record<string, () => IndexableApi>};
+ gbar?: {a: Record<string, () => IndexableApi>, P: () => void};
}
async function callApi(
@@ -42,6 +48,17 @@
return api[fnName]!.apply(api, args);
}
+ async function callAsyncBarApi(
+ fnName: string, ...args: any[]): Promise<unknown> {
+ const {gbar} = window as Window & Gbar;
+ if (!gbar) {
+ return;
+ }
+
+ const barApi = new (gbar.P as any)();
+ return barApi[fnName]!.apply(barApi, args);
+ }
+
interface Definition {
name: string;
apiName: string;
@@ -67,14 +84,25 @@
return topLevelApi;
}, {} as {bar: Bar});
+ const asyncBar: AsyncBar =
+ [['setDarkMode', 'pp']].reduce((bar: any, [name, fnName]) => {
+ bar[name!] = callAsyncBarApi.bind(null, fnName!);
+ return bar;
+ }, {} as Bar);
+
async function updateDarkMode(): Promise<void> {
- await api.bar.setDarkMode(
- window.matchMedia('(prefers-color-scheme: dark)').matches);
- // |setDarkMode(toggle)| updates the background color and foreground style.
- // The background color should always be 'transparent'.
- api.bar.setBackgroundColor('transparent');
- // The foreground style is set based on NTP theme and not dark mode.
- api.bar.setForegroundStyle(foregroundLight ? 1 : 0);
+ if (abp) {
+ await asyncBar.setDarkMode(
+ window.matchMedia('(prefers-color-scheme: dark)').matches);
+ } else {
+ await api.bar.setDarkMode(
+ window.matchMedia('(prefers-color-scheme: dark)').matches);
+ // |setDarkMode(toggle)| updates the background color and foreground
+ // style. The background color should always be 'transparent'.
+ api.bar.setBackgroundColor('transparent');
+ // The foreground style is set based on NTP theme and not dark mode.
+ api.bar.setForegroundStyle(foregroundLight ? 1 : 0);
+ }
}
let foregroundLight: boolean = false;
@@ -85,7 +113,9 @@
* the background.
*/
setForegroundLight: (enabled: boolean) => {
- if (foregroundLight !== enabled) {
+ if (abp) {
+ asyncBar.setDarkMode(enabled);
+ } else if (foregroundLight !== enabled) {
foregroundLight = enabled;
api.bar.setForegroundStyle(foregroundLight ? 1 : 0);
}
diff --git a/chrome/browser/ui/webui/new_tab_page/untrusted_source.cc b/chrome/browser/ui/webui/new_tab_page/untrusted_source.cc
index c0bf46ec..2f5b125 100644
--- a/chrome/browser/ui/webui/new_tab_page/untrusted_source.cc
+++ b/chrome/browser/ui/webui/new_tab_page/untrusted_source.cc
@@ -248,6 +248,11 @@
ui::TemplateReplacements replacements;
replacements["textdirection"] = base::i18n::IsRTL() ? "rtl" : "ltr";
replacements["barHtml"] = data->bar_html;
+ replacements["varsHeadScript"] = base::StringPrintf(
+ "let abp = %s;", base::FeatureList::IsEnabled(
+ ntp_features::kNtpOneGoogleBarAsyncBarParts)
+ ? "true"
+ : "false");
replacements["inHeadScript"] = data->in_head_script;
replacements["inHeadStyle"] = data->in_head_style;
replacements["afterBarScript"] = data->after_bar_script;
diff --git a/components/search/ntp_features.cc b/components/search/ntp_features.cc
index 56cf126..10c9a41 100644
--- a/components/search/ntp_features.cc
+++ b/components/search/ntp_features.cc
@@ -283,6 +283,11 @@
"NtpMicrosoftAuthenticationModule",
base::FEATURE_DISABLED_BY_DEFAULT);
+// If enabled, the OGB loader will request for the async bar parts payload type.
+BASE_FEATURE(kNtpOneGoogleBarAsyncBarParts,
+ "NtpOneGoogleBarAsyncBarParts",
+ base::FEATURE_DISABLED_BY_DEFAULT);
+
const char kNtpModuleIgnoredCriteriaThreshold[] =
"NtpModuleIgnoredCriteriaThreshold";
const char kNtpModuleIgnoredHaTSDelayTimeParam[] =
diff --git a/components/search/ntp_features.h b/components/search/ntp_features.h
index 187fcc0..b11017e 100644
--- a/components/search/ntp_features.h
+++ b/components/search/ntp_features.h
@@ -25,8 +25,6 @@
BASE_DECLARE_FEATURE(kCustomizeChromeWallpaperSearch);
BASE_DECLARE_FEATURE(kCustomizeChromeWallpaperSearchButton);
BASE_DECLARE_FEATURE(kCustomizeChromeWallpaperSearchInspirationCard);
-BASE_DECLARE_FEATURE(kIframeOneGoogleBar);
-BASE_DECLARE_FEATURE(kOneGoogleBarModalOverlays);
BASE_DECLARE_FEATURE(kRealboxCr23Theming);
BASE_DECLARE_FEATURE(kRealboxMatchOmniboxTheme);
BASE_DECLARE_FEATURE(kRealboxMatchSearchboxTheme);
@@ -77,6 +75,7 @@
BASE_DECLARE_FEATURE(kNtpWallpaperSearchButtonAnimationShownThreshold);
BASE_DECLARE_FEATURE(kNtpMobilePromo);
BASE_DECLARE_FEATURE(kNtpMicrosoftAuthenticationModule);
+BASE_DECLARE_FEATURE(kNtpOneGoogleBarAsyncBarParts);
// Parameter for controlling the luminosity difference for NTP elements on light
// backgrounds.