Commit 318912a6 authored by Esmael El-Moslimany's avatar Esmael El-Moslimany Committed by Commit Bot

Local NTP: create chrome://new-tab-page placeholder page

The launch of WebUI NTP depends on an effort that has begun that
will allow WebUI pages to use <iframe>'s. The embedded <iframe>
content will be site-isolated from the embedder if the embedder is a
WebUI page. The parts of the page that depend on this are the
OneGoogleBar, doodle, voice search and promo.

I plan to work on tasks that do not depend on embedding isolated
content.

 - Create placeholder WebUI page
 - Create parts of the page
   * search box
   * shortcuts and most-visited sites
   * customization
   * search suggestion chips (if still relevant after zero-suggest)
 - Flag that uses chrome://new-tab-page in place of
   chrome-search://local-ntp/local-ntp.html

Bug: 997229
Change-Id: I333588a379193d9fe6c542eaed589ff2e6cb4f52
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/1769054
Commit-Queue: Esmael Elmoslimany <aee@chromium.org>
Reviewed-by: default avatarDaniel Cheng <dcheng@chromium.org>
Reviewed-by: default avatarLei Zhang <thestig@chromium.org>
Reviewed-by: default avatarDan Beam <dbeam@chromium.org>
Reviewed-by: default avatarSteven Bennetts <stevenjb@chromium.org>
Cr-Commit-Position: refs/heads/master@{#716428}
parent d290d1cb
......@@ -1565,6 +1565,7 @@ group("extra_resources") {
"//chrome/browser/resources:dev_ui_paks",
"//chrome/browser/resources:downloads_resources",
"//chrome/browser/resources:local_ntp_resources",
"//chrome/browser/resources:new_tab_page_resources",
"//chrome/browser/resources:settings_resources",
]
}
......
......@@ -413,6 +413,7 @@ source_set("chrome_content_browser_overlay_manifest") {
"//chrome/browser/ui/webui/downloads:mojo_bindings",
"//chrome/browser/ui/webui/feed_internals:mojo_bindings",
"//chrome/browser/ui/webui/interventions_internals:mojo_bindings",
"//chrome/browser/ui/webui/new_tab_page:mojo_bindings",
"//chrome/browser/ui/webui/omnibox:mojo_bindings",
"//chrome/browser/ui/webui/reset_password:mojo_bindings",
"//chrome/browser/ui/webui/snippets_internals:mojo_bindings",
......
......@@ -13,6 +13,7 @@
#include "chrome/browser/ui/webui/downloads/downloads.mojom.h"
#include "chrome/browser/ui/webui/feed_internals/feed_internals.mojom.h"
#include "chrome/browser/ui/webui/interventions_internals/interventions_internals.mojom.h"
#include "chrome/browser/ui/webui/new_tab_page/new_tab_page.mojom.h"
#include "chrome/browser/ui/webui/omnibox/omnibox.mojom.h"
#include "chrome/browser/ui/webui/reset_password/reset_password.mojom.h"
#include "chrome/browser/ui/webui/snippets_internals/snippets_internals.mojom.h"
......@@ -156,6 +157,7 @@ const service_manager::Manifest& GetChromeContentBrowserOverlayManifest() {
// for for now.
downloads::mojom::PageHandlerFactory,
feed_internals::mojom::PageHandler,
new_tab_page::mojom::PageHandlerFactory,
#if defined(OS_ANDROID)
explore_sites_internals::mojom::PageHandler,
#else
......
......@@ -28,6 +28,7 @@ if (closure_compile) {
"local_state:closure_compile",
"management:closure_compile",
"media_router:closure_compile",
"new_tab_page:closure_compile",
"ntp4:closure_compile",
"omnibox:closure_compile",
"pdf:closure_compile",
......@@ -178,6 +179,32 @@ if (!is_android) {
output_dir = "$root_gen_dir/chrome"
}
grit("new_tab_page_resources") {
source = "new_tab_page/new_tab_page_resources.grd"
deps = [
"//chrome/browser/resources/new_tab_page:polymer3_elements",
"//chrome/browser/ui/webui/new_tab_page:mojo_bindings_js",
]
# The .grd contains references to generated files.
source_is_generated = true
grit_flags = [
"-E",
"root_gen_dir=" + rebase_path(root_gen_dir, root_build_dir),
]
defines = chrome_grit_defines
outputs = [
"grit/new_tab_page_resources.h",
"grit/new_tab_page_resources_map.cc",
"grit/new_tab_page_resources_map.h",
"new_tab_page_resources.pak",
]
output_dir = "$root_gen_dir/chrome"
}
grit("settings_resources") {
if (optimize_webui) {
source = "settings/settings_resources_vulcanized.grd"
......
# Copyright 2019 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.
import("//third_party/closure_compiler/compile_js.gni")
import("//tools/polymer/polymer.gni")
js_type_check("closure_compile") {
is_polymer3 = true
deps = [
":browser_proxy",
":manager",
]
}
js_library("browser_proxy") {
deps = [
"//chrome/browser/ui/webui/new_tab_page:mojo_bindings_js_library_for_compile",
"//third_party/polymer/v3_0/components-chromium/polymer:polymer_bundled",
"//ui/webui/resources/js:cr.m",
]
externs_list = [ "externs.js" ]
}
js_library("manager") {
deps = [
":browser_proxy",
"//third_party/polymer/v3_0/components-chromium/polymer:polymer_bundled",
"//ui/webui/resources/js:assert.m",
]
}
polymer_modulizer("manager") {
js_file = "manager.js"
html_file = "manager.html"
html_type = "v3-ready"
}
group("polymer3_elements") {
deps = [
":manager_module",
]
}
// Copyright 2019 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.
import 'chrome://resources/mojo/mojo/public/js/mojo_bindings_lite.js';
import './new_tab_page.mojom-lite.js';
import {addSingletonGetter} from 'chrome://resources/js/cr.m.js';
export class BrowserProxy {
constructor() {
/** @type {newTabPage.mojom.PageCallbackRouter} */
this.callbackRouter = new newTabPage.mojom.PageCallbackRouter();
/** @type {newTabPage.mojom.PageHandlerRemote} */
this.handler = new newTabPage.mojom.PageHandlerRemote();
const factory = newTabPage.mojom.PageHandlerFactory.getRemote();
factory.createPageHandler(
this.callbackRouter.$.bindNewPipeAndPassRemote(),
this.handler.$.bindNewPipeAndPassReceiver());
}
}
addSingletonGetter(BrowserProxy);
// Copyright 2019 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.
/**
* @fileoverview Externs for objects sent from C++ to JS for
* chrome://new-tab-page.
* @externs
*/
// eslint-disable-next-line no-var
var newTabPage = {};
// Copyright 2019 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.
import {assert} from 'chrome://resources/js/assert.m.js';
import {html, PolymerElement} from 'chrome://resources/polymer/v3_0/polymer/polymer_bundled.min.js';
import {BrowserProxy} from './browser_proxy.js';
class ManagerUI extends PolymerElement {
static get is() {
return 'manager-ui';
}
static get template() {
return html`{__html_template__}`;
}
constructor() {
super();
const browserProxy = BrowserProxy.getInstance();
/** @private {newTabPage.mojom.PageCallbackRouter} */
this.mojoEventTarget_ = browserProxy.callbackRouter;
/** @private {newTabPage.mojom.PageHandlerInterface} */
this.mojoHandler_ = browserProxy.handler;
}
}
customElements.define(ManagerUI.is, ManagerUI);
<!doctype html>
<html dir="$i18n{textdirection}" lang="$i18n{language}">
<head>
<meta charset="utf-8">
<title>$i18n{title}</title>
<style>
html,
body {
height: 100%;
overflow: hidden;
}
body {
margin: 0;
}
</style>
</head>
<body>
<manager-ui></manager-ui>
<script type="module" src="manager.js"></script>
</body>
</html>
\ No newline at end of file
<?xml version="1.0" encoding="UTF-8"?>
<grit latest_public_release="0" current_release="1" output_all_resource_defines="false">
<outputs>
<output filename="grit/new_tab_page_resources.h" type="rc_header">
<emit emit_type='prepend'></emit>
</output>
<output filename="grit/new_tab_page_resources_map.cc"
type="resource_file_map_source" />
<output filename="grit/new_tab_page_resources_map.h"
type="resource_map_header" />
<output filename="new_tab_page_resources.pak" type="data_package" />
</outputs>
<release seq="1">
<includes>
<include name="IDR_NEW_TAB_PAGE_MOJO_LITE_JS"
file="${root_gen_dir}/chrome/browser/ui/webui/new_tab_page/new_tab_page.mojom-lite.js"
use_base_dir="false" type="BINDATA" compress="gzip" />
<include name="IDR_NEW_TAB_PAGE_MANAGER_JS"
file="${root_gen_dir}/chrome/browser/resources/new_tab_page/manager.js"
use_base_dir="false" type="BINDATA" compress="gzip" />
</includes>
<structures>
<structure name="IDR_NEW_TAB_PAGE_NEW_TAB_PAGE_HTML"
file="new_tab_page.html" type="chrome_html" compress="gzip" />
<structure name="IDR_NEW_TAB_PAGE_BROWSER_PROXY_JS"
file="browser_proxy.js" type="chrome_html" compress="gzip" />
</structures>
</release>
</grit>
......@@ -401,6 +401,7 @@ jumbo_static_library("ui") {
"//chrome/browser/ui/webui/bluetooth_internals",
"//chrome/browser/ui/webui/downloads:mojo_bindings",
"//chrome/browser/ui/webui/interventions_internals:mojo_bindings",
"//chrome/browser/ui/webui/new_tab_page:mojo_bindings",
"//chrome/browser/ui/webui/omnibox:mojo_bindings",
"//chrome/browser/ui/webui/usb_internals:mojo_bindings",
"//chrome/common",
......@@ -1253,6 +1254,10 @@ jumbo_static_library("ui") {
"webui/media_router/media_router_internals_webui_message_handler.cc",
"webui/media_router/media_router_internals_webui_message_handler.h",
"webui/media_router/web_contents_display_observer.h",
"webui/new_tab_page/new_tab_page_handler.cc",
"webui/new_tab_page/new_tab_page_handler.h",
"webui/new_tab_page/new_tab_page_ui.cc",
"webui/new_tab_page/new_tab_page_ui.h",
"webui/ntp/app_icon_webui_handler.cc",
"webui/ntp/app_icon_webui_handler.h",
"webui/ntp/app_launcher_handler.cc",
......
......@@ -13,6 +13,7 @@
#include "chrome/browser/ui/bookmarks/bookmark_tab_helper_observer.h"
#include "chrome/browser/ui/bookmarks/bookmark_utils.h"
#include "chrome/browser/ui/sad_tab.h"
#include "chrome/browser/ui/webui/new_tab_page/new_tab_page_ui.h"
#include "chrome/browser/ui/webui/ntp/new_tab_ui.h"
#include "components/bookmarks/browser/bookmark_model.h"
#include "components/bookmarks/common/bookmark_pref_names.h"
......@@ -33,7 +34,10 @@ bool IsNTP(content::WebContents* web_contents) {
web_contents->GetController().GetLastCommittedEntry();
if (!entry)
entry = web_contents->GetController().GetVisibleEntry();
return (entry && NewTabUI::IsNewTab(entry->GetURL())) ||
if (!entry)
return false;
const GURL& url = entry->GetURL();
return NewTabUI::IsNewTab(url) || NewTabPageUI::IsNewTabPageOrigin(url) ||
search::NavEntryIsInstantNTP(web_contents, entry);
}
......
......@@ -134,6 +134,7 @@
#include "chrome/browser/ui/webui/history_ui.h"
#include "chrome/browser/ui/webui/inspect_ui.h"
#include "chrome/browser/ui/webui/management_ui.h"
#include "chrome/browser/ui/webui/new_tab_page/new_tab_page_ui.h"
#include "chrome/browser/ui/webui/ntp/new_tab_ui.h"
#include "chrome/browser/ui/webui/page_not_available_for_guest/page_not_available_for_guest_ui.h"
#include "chrome/browser/ui/webui/sync_file_system_internals/sync_file_system_internals_ui.h"
......@@ -440,6 +441,8 @@ WebUIFactoryFunction GetWebUIFactoryFunction(WebUI* web_ui,
return &NewWebUI<IdentityInternalsUI>;
if (url.host_piece() == chrome::kChromeUINewTabHost)
return &NewWebUI<NewTabUI>;
if (url.host_piece() == chrome::kChromeUINewTabPageHost)
return &NewWebUI<NewTabPageUI>;
// Settings are implemented with native UI elements on Android.
if (url.host_piece() == chrome::kChromeUISettingsHost)
return &NewWebUI<settings::SettingsUI>;
......
# Copyright 2019 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.
import("//mojo/public/tools/bindings/mojom.gni")
mojom("mojo_bindings") {
sources = [
"new_tab_page.mojom",
]
}
aee@chromium.org
dbeam@chromium.org
mahmadi@chromium.org
per-file *.mojom=set noparent
per-file *.mojom=file://ipc/SECURITY_OWNERS
# COMPONENT: UI>Browser>NewTabPage
// Copyright 2019 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.
module new_tab_page.mojom;
// Used by the WebUI page to bootstrap bidirectional communication.
interface PageHandlerFactory {
// The WebUI page's |BrowserProxy| singleton calls this method when the page
// is first initialized.
CreatePageHandler(pending_remote<Page> page,
pending_receiver<PageHandler> handler);
};
// Browser-side handler for requests from WebUI page.
interface PageHandler {
};
// WebUI-side handler for requests from the browser.
interface Page {
};
// Copyright 2019 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/webui/new_tab_page/new_tab_page_handler.h"
NewTabPageHandler::NewTabPageHandler(
mojo::PendingReceiver<new_tab_page::mojom::PageHandler>
pending_page_handler,
mojo::PendingRemote<new_tab_page::mojom::Page> pending_page)
: page_{std::move(pending_page)},
receiver_{this, std::move(pending_page_handler)} {}
NewTabPageHandler::~NewTabPageHandler() = default;
// Copyright (c) 2019 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_WEBUI_NEW_TAB_PAGE_NEW_TAB_PAGE_HANDLER_H_
#define CHROME_BROWSER_UI_WEBUI_NEW_TAB_PAGE_NEW_TAB_PAGE_HANDLER_H_
#include "base/macros.h"
#include "chrome/browser/ui/webui/new_tab_page/new_tab_page.mojom.h"
#include "content/public/browser/web_contents_observer.h"
#include "mojo/public/cpp/bindings/pending_receiver.h"
#include "mojo/public/cpp/bindings/pending_remote.h"
#include "mojo/public/cpp/bindings/receiver.h"
#include "mojo/public/cpp/bindings/remote.h"
class NewTabPageHandler : public content::WebContentsObserver,
public new_tab_page::mojom::PageHandler {
public:
NewTabPageHandler(
mojo::PendingReceiver<new_tab_page::mojom::PageHandler>
pending_page_handler,
mojo::PendingRemote<new_tab_page::mojom::Page> pending_page);
~NewTabPageHandler() override;
private:
mojo::Remote<new_tab_page::mojom::Page> page_;
mojo::Receiver<new_tab_page::mojom::PageHandler> receiver_;
DISALLOW_COPY_AND_ASSIGN(NewTabPageHandler);
};
#endif // CHROME_BROWSER_UI_WEBUI_NEW_TAB_PAGE_NEW_TAB_PAGE_HANDLER_H_
// Copyright 2019 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/webui/new_tab_page/new_tab_page_ui.h"
#include "chrome/browser/profiles/profile.h"
#include "chrome/browser/ui/webui/localized_string.h"
#include "chrome/browser/ui/webui/managed_ui_handler.h"
#include "chrome/browser/ui/webui/new_tab_page/new_tab_page_handler.h"
#include "chrome/common/url_constants.h"
#include "chrome/grit/new_tab_page_resources.h"
#include "chrome/grit/new_tab_page_resources_map.h"
#include "components/strings/grit/components_strings.h"
#include "content/public/browser/url_data_source.h"
#include "content/public/browser/web_ui_data_source.h"
using content::BrowserContext;
using content::WebContents;
namespace {
content::WebUIDataSource* CreateNewTabPageUiHtmlSource() {
content::WebUIDataSource* source =
content::WebUIDataSource::Create(chrome::kChromeUINewTabPageHost);
static constexpr LocalizedString kStrings[] = {
{"title", IDS_NEW_TAB_TITLE},
};
AddLocalizedStringsBulk(source, kStrings, base::size(kStrings));
source->AddResourcePath("new_tab_page.mojom-lite.js",
IDR_NEW_TAB_PAGE_MOJO_LITE_JS);
std::string generated_path =
"@out_folder@/gen/chrome/browser/resources/new_tab_page/";
for (size_t i = 0; i < kNewTabPageResourcesSize; ++i) {
base::StringPiece path = kNewTabPageResources[i].name;
if (path.rfind(generated_path, 0) == 0) {
path = path.substr(generated_path.length());
}
source->AddResourcePath(path, kNewTabPageResources[i].value);
}
source->SetDefaultResource(IDR_NEW_TAB_PAGE_NEW_TAB_PAGE_HTML);
source->UseStringsJs();
return source;
}
} // namespace
NewTabPageUI::NewTabPageUI(content::WebUI* web_ui)
: ui::MojoWebUIController(web_ui, true), page_factory_receiver_(this) {
Profile* profile = Profile::FromWebUI(web_ui);
content::WebUIDataSource* source = CreateNewTabPageUiHtmlSource();
ManagedUIHandler::Initialize(web_ui, source);
content::WebUIDataSource::Add(profile, source);
AddHandlerToRegistry(base::BindRepeating(
&NewTabPageUI::BindPageHandlerFactory, base::Unretained(this)));
}
NewTabPageUI::~NewTabPageUI() = default;
void NewTabPageUI::BindPageHandlerFactory(
mojo::PendingReceiver<new_tab_page::mojom::PageHandlerFactory>
pending_receiver) {
if (page_factory_receiver_.is_bound()) {
page_factory_receiver_.reset();
}
page_factory_receiver_.Bind(std::move(pending_receiver));
}
void NewTabPageUI::CreatePageHandler(
mojo::PendingRemote<new_tab_page::mojom::Page> pending_page,
mojo::PendingReceiver<new_tab_page::mojom::PageHandler>
pending_page_handler) {
DCHECK(pending_page.is_valid());
page_handler_ = std::make_unique<NewTabPageHandler>(
std::move(pending_page_handler), std::move(pending_page));
}
// static
bool NewTabPageUI::IsNewTabPageOrigin(const GURL& url) {
return url.GetOrigin() == GURL(chrome::kChromeUINewTabPageURL).GetOrigin();
}
// Copyright (c) 2019 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_WEBUI_NEW_TAB_PAGE_NEW_TAB_PAGE_UI_H_
#define CHROME_BROWSER_UI_WEBUI_NEW_TAB_PAGE_NEW_TAB_PAGE_UI_H_
#include "base/macros.h"
#include "chrome/browser/ui/webui/new_tab_page/new_tab_page.mojom.h"
#include "mojo/public/cpp/bindings/pending_receiver.h"
#include "mojo/public/cpp/bindings/pending_remote.h"
#include "mojo/public/cpp/bindings/receiver.h"
#include "ui/webui/mojo_web_ui_controller.h"
namespace content {
class WebUI;
}
class GURL;
class NewTabPageHandler;
class NewTabPageUI : public ui::MojoWebUIController,
public new_tab_page::mojom::PageHandlerFactory {
public:
explicit NewTabPageUI(content::WebUI* web_ui);
~NewTabPageUI() override;
static bool IsNewTabPageOrigin(const GURL& url);
private:
void BindPageHandlerFactory(
mojo::PendingReceiver<new_tab_page::mojom::PageHandlerFactory>
pending_receiver);
// new_tab_page::mojom::PageHandlerFactory:
void CreatePageHandler(
mojo::PendingRemote<new_tab_page::mojom::Page> pending_page,
mojo::PendingReceiver<new_tab_page::mojom::PageHandler>
pending_page_handler) override;
std::unique_ptr<NewTabPageHandler> page_handler_;
mojo::Receiver<new_tab_page::mojom::PageHandlerFactory>
page_factory_receiver_;
DISALLOW_COPY_AND_ASSIGN(NewTabPageUI);
};
#endif // CHROME_BROWSER_UI_WEBUI_NEW_TAB_PAGE_NEW_TAB_PAGE_UI_H_
......@@ -137,6 +137,7 @@ template("chrome_extra_paks") {
"$root_gen_dir/chrome/dev_ui_resources.pak",
"$root_gen_dir/chrome/downloads_resources.pak",
"$root_gen_dir/chrome/local_ntp_resources.pak",
"$root_gen_dir/chrome/new_tab_page_resources.pak",
"$root_gen_dir/chrome/settings_resources.pak",
"$root_gen_dir/content/browser/devtools/devtools_resources.pak",
"$root_gen_dir/headless/headless_lib_resources.pak",
......@@ -147,6 +148,7 @@ template("chrome_extra_paks") {
"//chrome/browser/resources:dev_ui_paks",
"//chrome/browser/resources:downloads_resources",
"//chrome/browser/resources:local_ntp_resources",
"//chrome/browser/resources:new_tab_page_resources",
"//chrome/browser/resources:settings_resources",
"//content/browser/devtools:devtools_resources",
"//headless:resources",
......
......@@ -103,6 +103,8 @@ const char kChromeUINetInternalsHost[] = "net-internals";
const char kChromeUINetInternalsURL[] = "chrome://net-internals/";
const char kChromeUINewTabHost[] = "newtab";
const char kChromeUINewTabIconHost[] = "ntpicon";
const char kChromeUINewTabPageHost[] = "new-tab-page";
const char kChromeUINewTabPageURL[] = "chrome://new-tab-page";
const char kChromeUINewTabURL[] = "chrome://newtab/";
const char kChromeUINotificationsInternalsHost[] = "notifications-internals";
const char kChromeUIOmniboxHost[] = "omnibox";
......@@ -569,6 +571,7 @@ const char* const kChromeHostURLs[] = {
kChromeUIDownloadsHost,
kChromeUIHelpHost,
kChromeUIInspectHost,
kChromeUINewTabPageHost,
kChromeUISettingsHost,
kChromeUISystemInfoHost,
#endif
......
......@@ -109,6 +109,8 @@ extern const char kChromeUINetInternalsHost[];
extern const char kChromeUINetInternalsURL[];
extern const char kChromeUINewTabHost[];
extern const char kChromeUINewTabIconHost[];
extern const char kChromeUINewTabPageHost[];
extern const char kChromeUINewTabPageURL[];
extern const char kChromeUINewTabURL[];
extern const char kChromeUINotificationsInternalsHost[];
extern const char kChromeUIOfflineInternalsHost[];
......
......@@ -136,20 +136,24 @@
"structures": [12260],
},
"chrome/browser/resources/extensions/extensions_resources_vulcanized.grd": {
"includes": [12340],
"includes": [12290],
},
"chrome/browser/resources/extensions/extensions_resources.grd": {
"includes": [12350],
"structures": [12400],
"includes": [12300],
"structures": [12350],
},
"chrome/browser/resources/invalidations_resources.grd": {
"includes": [12440],
"includes": [12390],
},
"chrome/browser/resources/local_ntp/local_ntp_resources.grd": {
"includes": [12480],
"includes": [12430],
},
"chrome/browser/resources/net_internals/net_internals_resources.grd": {
"includes": [12540],
"includes": [12490],
},
"chrome/browser/resources/new_tab_page/new_tab_page_resources.grd": {
"includes": [12500],
"structures": [12510],
},
"chrome/browser/resources/print_preview/print_preview_resources_vulcanized.grd": {
"includes": [12550],
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment