Mojo: Add WebUI JS module support
This adds a new _webui_js sub-target for any mojom target that explicitly sets webui_module_path in GN. This allows mojom JS modules to work well with WebUI resource URLs, which are typically either a chrome://resources/ URL for shared resources, or a relative path-only URL for resources exclusive to a single WebUI page. Bug: 1004256 Change-Id: I5b8be3f69733239f81b313f882d3185183b72a99 Tbr: dcheng@chromium.org Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2459393 Commit-Queue: Ken Rockot <rockot@google.com> Reviewed-by: Daniel Cheng <dcheng@chromium.org> Reviewed-by: dpapad <dpapad@chromium.org> Reviewed-by: Lei Zhang <thestig@chromium.org> Reviewed-by: Avi Drissman <avi@chromium.org> Reviewed-by: Bo <boliu@chromium.org> Cr-Commit-Position: refs/heads/master@{#817225}
This commit is contained in:
android_webview
content
mojo/public
js
tools
bindings
mojom
third_party/closure_compiler
tools/gritsettings
url/mojom
@ -934,6 +934,7 @@ grit("generate_mojo_resources") {
|
||||
]
|
||||
deps = [
|
||||
"//mojo/public/js:bindings_lite",
|
||||
"//mojo/public/js:bindings_module",
|
||||
"//mojo/public/mojom/base:base_js",
|
||||
]
|
||||
}
|
||||
|
@ -93,44 +93,12 @@ const std::map<int, std::string> CreateContentResourceIdToAliasMap() {
|
||||
"mojo/mojo/public/mojom/base/unguessable_token.mojom-lite.js"},
|
||||
{IDR_URL_MOJO_HTML, "mojo/url/mojom/url.mojom.html"},
|
||||
{IDR_URL_MOJO_JS, "mojo/url/mojom/url.mojom-lite.js"},
|
||||
{IDR_URL_MOJOM_WEBUI_JS, "mojo/url/mojom/url.mojom-webui.js"},
|
||||
{IDR_VULKAN_INFO_MOJO_JS, "gpu/ipc/common/vulkan_info.mojom-lite.js"},
|
||||
{IDR_VULKAN_TYPES_MOJO_JS, "gpu/ipc/common/vulkan_types.mojom-lite.js"},
|
||||
};
|
||||
}
|
||||
|
||||
const std::map<int, std::string> CreateMojoResourceIdToAliasMap() {
|
||||
return std::map<int, std::string> {
|
||||
{IDR_MOJO_MOJO_BINDINGS_LITE_HTML,
|
||||
"mojo/mojo/public/js/mojo_bindings_lite.html"},
|
||||
{IDR_MOJO_MOJO_BINDINGS_LITE_JS,
|
||||
"mojo/mojo/public/js/mojo_bindings_lite.js"},
|
||||
{IDR_MOJO_BIG_BUFFER_MOJOM_HTML,
|
||||
"mojo/mojo/public/mojom/base/big_buffer.mojom.html"},
|
||||
{IDR_MOJO_BIG_BUFFER_MOJOM_LITE_JS,
|
||||
"mojo/mojo/public/mojom/base/big_buffer.mojom-lite.js"},
|
||||
{IDR_MOJO_FILE_MOJOM_HTML,
|
||||
"mojo/mojo/public/mojom/base/file.mojom.html"},
|
||||
{IDR_MOJO_FILE_MOJOM_LITE_JS,
|
||||
"mojo/mojo/public/mojom/base/file.mojom-lite.js"},
|
||||
{IDR_MOJO_STRING16_MOJOM_HTML,
|
||||
"mojo/mojo/public/mojom/base/string16.mojom.html"},
|
||||
{IDR_MOJO_STRING16_MOJOM_LITE_JS,
|
||||
"mojo/mojo/public/mojom/base/string16.mojom-lite.js"},
|
||||
{IDR_MOJO_TEXT_DIRECTION_MOJOM_HTML,
|
||||
"mojo/mojo/public/mojom/base/text_direction.mojom.html"},
|
||||
{IDR_MOJO_TEXT_DIRECTION_MOJOM_LITE_JS,
|
||||
"mojo/mojo/public/mojom/base/text_direction.mojom-lite.js"},
|
||||
#if defined(OS_WIN) || defined(OS_MAC) || defined(OS_LINUX) || \
|
||||
defined(OS_CHROMEOS) || defined(OS_ANDROID)
|
||||
{IDR_MOJO_TIME_MOJOM_HTML,
|
||||
"mojo/mojo/public/mojom/base/time.mojom.html"},
|
||||
{IDR_MOJO_TIME_MOJOM_LITE_JS,
|
||||
"mojo/mojo/public/mojom/base/time.mojom-lite.js"},
|
||||
#endif // defined(OS_WIN) || defined(OS_MAC) || defined(OS_LINUX) ||
|
||||
// defined(OS_CHROMEOS) || defined(OS_ANDROID)
|
||||
};
|
||||
}
|
||||
|
||||
const std::map<int, std::string> CreateSkiaResourceIdToAliasMap() {
|
||||
return std::map<int, std::string>{
|
||||
{IDR_SKIA_BITMAP_MOJOM_LITE_JS,
|
||||
@ -248,6 +216,14 @@ void AddAliasedResourcesToMap(
|
||||
}
|
||||
}
|
||||
|
||||
// Adds |resources| to |resources_map| using the path given by resource_path in
|
||||
// each GRD entry.
|
||||
void AddGritResourcesToMap(base::span<const GritResourceMap> resources,
|
||||
ResourcesMap* resources_map) {
|
||||
for (const GritResourceMap& entry : resources)
|
||||
AddResource(entry.name, entry.value, resources_map);
|
||||
}
|
||||
|
||||
const ResourcesMap* CreateResourcesMap() {
|
||||
ResourcesMap* result = new ResourcesMap();
|
||||
AddResourcesToMap(result);
|
||||
@ -256,9 +232,9 @@ const ResourcesMap* CreateResourcesMap() {
|
||||
AddAliasedResourcesToMap(CreateContentResourceIdToAliasMap(),
|
||||
kMediaInternalsResources,
|
||||
kMediaInternalsResourcesSize, result);
|
||||
AddAliasedResourcesToMap(CreateMojoResourceIdToAliasMap(),
|
||||
kMojoBindingsResources, kMojoBindingsResourcesSize,
|
||||
result);
|
||||
AddGritResourcesToMap(
|
||||
base::make_span(kMojoBindingsResources, kMojoBindingsResourcesSize),
|
||||
result);
|
||||
AddAliasedResourcesToMap(CreateSkiaResourceIdToAliasMap(), kSkiaResources,
|
||||
kSkiaResourcesSize, result);
|
||||
#if defined(OS_CHROMEOS)
|
||||
|
@ -8,11 +8,9 @@
|
||||
#include "base/bind.h"
|
||||
#include "base/callback.h"
|
||||
#include "base/containers/flat_map.h"
|
||||
#include "base/files/file_path.h"
|
||||
#include "base/files/file_util.h"
|
||||
#include "base/containers/span.h"
|
||||
#include "base/macros.h"
|
||||
#include "base/memory/ref_counted_memory.h"
|
||||
#include "base/path_service.h"
|
||||
#include "base/run_loop.h"
|
||||
#include "base/strings/string_util.h"
|
||||
#include "base/threading/thread_restrictions.h"
|
||||
@ -29,8 +27,6 @@
|
||||
#include "content/public/browser/web_ui_data_source.h"
|
||||
#include "content/public/common/bindings_policy.h"
|
||||
#include "content/public/common/content_client.h"
|
||||
#include "content/public/common/content_paths.h"
|
||||
#include "content/public/common/content_switches.h"
|
||||
#include "content/public/common/referrer.h"
|
||||
#include "content/public/common/url_constants.h"
|
||||
#include "content/public/common/url_utils.h"
|
||||
@ -41,7 +37,10 @@
|
||||
#include "content/public/test/test_navigation_observer.h"
|
||||
#include "content/public/test/test_utils.h"
|
||||
#include "content/shell/browser/shell.h"
|
||||
#include "content/test/data/web_ui_test_mojo_bindings.mojom.h"
|
||||
#include "content/test/data/web_ui_test.test-mojom.h"
|
||||
#include "content/test/data/web_ui_test_types.test-mojom.h"
|
||||
#include "content/test/grit/web_ui_mojo_test_resources.h"
|
||||
#include "content/test/grit/web_ui_mojo_test_resources_map.h"
|
||||
#include "mojo/public/cpp/bindings/binder_map.h"
|
||||
#include "mojo/public/cpp/bindings/pending_receiver.h"
|
||||
#include "mojo/public/cpp/bindings/receiver.h"
|
||||
@ -49,87 +48,58 @@
|
||||
namespace content {
|
||||
namespace {
|
||||
|
||||
bool g_got_message = false;
|
||||
const char kMojoWebUiHost[] = "mojo-web-ui";
|
||||
const char kDummyWebUiHost[] = "dummy-web-ui";
|
||||
|
||||
base::FilePath GetFilePathForJSResource(const std::string& path) {
|
||||
base::ScopedAllowBlockingForTesting allow_blocking;
|
||||
|
||||
std::string binding_path = "gen/" + path;
|
||||
#if defined(OS_WIN)
|
||||
base::ReplaceChars(binding_path, "//", "\\", &binding_path);
|
||||
#endif
|
||||
base::FilePath exe_dir;
|
||||
base::PathService::Get(base::DIR_EXE, &exe_dir);
|
||||
return exe_dir.AppendASCII(binding_path);
|
||||
}
|
||||
|
||||
// The bindings for the page are generated from a .mojom file. This code looks
|
||||
// up the generated file from disk and returns it.
|
||||
void GetResource(const std::string& id,
|
||||
WebUIDataSource::GotDataCallback callback) {
|
||||
base::ScopedAllowBlockingForTesting allow_blocking;
|
||||
|
||||
std::string contents;
|
||||
if (base::EndsWith(id, ".mojom-lite.js", base::CompareCase::SENSITIVE)) {
|
||||
CHECK(base::ReadFileToString(GetFilePathForJSResource(id), &contents))
|
||||
<< id;
|
||||
} else {
|
||||
base::FilePath path;
|
||||
CHECK(base::PathService::Get(content::DIR_TEST_DATA, &path));
|
||||
path = path.AppendASCII(id.substr(0, id.find("?")));
|
||||
CHECK(base::ReadFileToString(path, &contents)) << path.value();
|
||||
}
|
||||
|
||||
base::RefCountedString* ref_contents = new base::RefCountedString;
|
||||
ref_contents->data() = contents;
|
||||
std::move(callback).Run(ref_contents);
|
||||
}
|
||||
|
||||
class BrowserTargetImpl : public mojom::BrowserTarget {
|
||||
class WebUIMojoTestCacheImpl : public mojom::WebUIMojoTestCache {
|
||||
public:
|
||||
BrowserTargetImpl(base::RunLoop* run_loop,
|
||||
mojo::PendingReceiver<mojom::BrowserTarget> receiver)
|
||||
: run_loop_(run_loop), receiver_(this, std::move(receiver)) {}
|
||||
explicit WebUIMojoTestCacheImpl(
|
||||
mojo::PendingReceiver<mojom::WebUIMojoTestCache> receiver)
|
||||
: receiver_(this, std::move(receiver)) {}
|
||||
|
||||
~BrowserTargetImpl() override {}
|
||||
~WebUIMojoTestCacheImpl() override = default;
|
||||
|
||||
// mojom::BrowserTarget overrides:
|
||||
void Start(StartCallback closure) override { std::move(closure).Run(); }
|
||||
void Stop() override {
|
||||
g_got_message = true;
|
||||
run_loop_->Quit();
|
||||
// mojom::WebUIMojoTestCache overrides:
|
||||
void Put(const GURL& url, const std::string& contents) override {
|
||||
cache_[url] = contents;
|
||||
}
|
||||
|
||||
protected:
|
||||
base::RunLoop* const run_loop_;
|
||||
void GetAll(GetAllCallback callback) override {
|
||||
std::vector<mojom::CacheItemPtr> items;
|
||||
for (const auto& entry : cache_)
|
||||
items.push_back(mojom::CacheItem::New(entry.first, entry.second));
|
||||
std::move(callback).Run(std::move(items));
|
||||
}
|
||||
|
||||
private:
|
||||
mojo::Receiver<mojom::BrowserTarget> receiver_;
|
||||
DISALLOW_COPY_AND_ASSIGN(BrowserTargetImpl);
|
||||
mojo::Receiver<mojom::WebUIMojoTestCache> receiver_;
|
||||
std::map<GURL, std::string> cache_;
|
||||
};
|
||||
|
||||
// WebUIController that sets up mojo bindings.
|
||||
class TestWebUIController : public WebUIController {
|
||||
public:
|
||||
TestWebUIController(WebUI* web_ui,
|
||||
base::RunLoop* run_loop,
|
||||
int bindings = BINDINGS_POLICY_MOJO_WEB_UI)
|
||||
: WebUIController(web_ui), run_loop_(run_loop) {
|
||||
explicit TestWebUIController(WebUI* web_ui,
|
||||
int bindings = BINDINGS_POLICY_MOJO_WEB_UI)
|
||||
: WebUIController(web_ui) {
|
||||
const base::span<const GritResourceMap> kMojoWebUiResources =
|
||||
base::make_span(kWebUiMojoTestResources, kWebUiMojoTestResourcesSize);
|
||||
|
||||
web_ui->SetBindings(bindings);
|
||||
{
|
||||
WebUIDataSource* data_source = WebUIDataSource::Create("mojo-web-ui");
|
||||
WebUIDataSource* data_source = WebUIDataSource::Create(kMojoWebUiHost);
|
||||
data_source->OverrideContentSecurityPolicy(
|
||||
network::mojom::CSPDirectiveName::ScriptSrc,
|
||||
"script-src chrome://resources 'self' 'unsafe-eval';");
|
||||
data_source->DisableTrustedTypesCSP();
|
||||
data_source->SetRequestFilter(
|
||||
base::BindRepeating([](const std::string& path) { return true; }),
|
||||
base::BindRepeating(&GetResource));
|
||||
for (const GritResourceMap& resource : kMojoWebUiResources)
|
||||
data_source->AddResourcePath(resource.name, resource.value);
|
||||
data_source->AddResourcePath("", IDR_WEB_UI_MOJO_HTML);
|
||||
WebUIDataSource::Add(web_ui->GetWebContents()->GetBrowserContext(),
|
||||
data_source);
|
||||
}
|
||||
{
|
||||
WebUIDataSource* data_source = WebUIDataSource::Create("dummy-web-ui");
|
||||
WebUIDataSource* data_source = WebUIDataSource::Create(kDummyWebUiHost);
|
||||
data_source->SetRequestFilter(
|
||||
base::BindRepeating([](const std::string& path) { return true; }),
|
||||
base::BindRepeating([](const std::string& id,
|
||||
@ -142,40 +112,34 @@ class TestWebUIController : public WebUIController {
|
||||
}
|
||||
|
||||
protected:
|
||||
base::RunLoop* const run_loop_;
|
||||
std::unique_ptr<BrowserTargetImpl> browser_target_;
|
||||
std::unique_ptr<WebUIMojoTestCacheImpl> cache_;
|
||||
|
||||
private:
|
||||
DISALLOW_COPY_AND_ASSIGN(TestWebUIController);
|
||||
};
|
||||
|
||||
// TestWebUIController that additionally creates the ping test BrowserTarget
|
||||
// implementation at the right time.
|
||||
class PingTestWebUIController : public TestWebUIController {
|
||||
// TestWebUIController that can bind a WebUIMojoTestCache interface when
|
||||
// requested by the page.
|
||||
class CacheTestWebUIController : public TestWebUIController {
|
||||
public:
|
||||
PingTestWebUIController(WebUI* web_ui, base::RunLoop* run_loop)
|
||||
: TestWebUIController(web_ui, run_loop) {}
|
||||
explicit CacheTestWebUIController(WebUI* web_ui)
|
||||
: TestWebUIController(web_ui) {}
|
||||
~CacheTestWebUIController() override = default;
|
||||
|
||||
~PingTestWebUIController() override {}
|
||||
|
||||
void CreateHandler(mojo::PendingReceiver<mojom::BrowserTarget> receiver) {
|
||||
browser_target_ =
|
||||
std::make_unique<BrowserTargetImpl>(run_loop_, std::move(receiver));
|
||||
void CreateHandler(
|
||||
mojo::PendingReceiver<mojom::WebUIMojoTestCache> receiver) {
|
||||
cache_ = std::make_unique<WebUIMojoTestCacheImpl>(std::move(receiver));
|
||||
}
|
||||
|
||||
private:
|
||||
DISALLOW_COPY_AND_ASSIGN(PingTestWebUIController);
|
||||
};
|
||||
|
||||
// WebUIControllerFactory that creates TestWebUIController.
|
||||
class TestWebUIControllerFactory : public WebUIControllerFactory {
|
||||
public:
|
||||
TestWebUIControllerFactory()
|
||||
: run_loop_(nullptr),
|
||||
registered_controllers_(
|
||||
{{"ping", base::BindRepeating(
|
||||
&TestWebUIControllerFactory::CreatePingController,
|
||||
base::Unretained(this))},
|
||||
: registered_controllers_(
|
||||
{{"cache", base::BindRepeating(
|
||||
&TestWebUIControllerFactory::CreateCacheController,
|
||||
base::Unretained(this))},
|
||||
{"hybrid", base::BindRepeating(
|
||||
&TestWebUIControllerFactory::CreateHybridController,
|
||||
base::Unretained(this))},
|
||||
@ -184,8 +148,6 @@ class TestWebUIControllerFactory : public WebUIControllerFactory {
|
||||
&TestWebUIControllerFactory::CreateWebUIController,
|
||||
base::Unretained(this))}}) {}
|
||||
|
||||
void set_run_loop(base::RunLoop* run_loop) { run_loop_ = run_loop; }
|
||||
|
||||
std::unique_ptr<WebUIController> CreateWebUIControllerForURL(
|
||||
WebUI* web_ui,
|
||||
const GURL& url) override {
|
||||
@ -196,7 +158,7 @@ class TestWebUIControllerFactory : public WebUIControllerFactory {
|
||||
if (it != registered_controllers_.end())
|
||||
return it->second.Run(web_ui);
|
||||
|
||||
return std::make_unique<TestWebUIController>(web_ui, run_loop_);
|
||||
return std::make_unique<TestWebUIController>(web_ui);
|
||||
}
|
||||
|
||||
WebUI::TypeID GetWebUIType(BrowserContext* browser_context,
|
||||
@ -219,22 +181,20 @@ class TestWebUIControllerFactory : public WebUIControllerFactory {
|
||||
void set_web_ui_enabled(bool enabled) { web_ui_enabled_ = enabled; }
|
||||
|
||||
private:
|
||||
std::unique_ptr<WebUIController> CreatePingController(WebUI* web_ui) {
|
||||
return std::make_unique<PingTestWebUIController>(web_ui, run_loop_);
|
||||
std::unique_ptr<WebUIController> CreateCacheController(WebUI* web_ui) {
|
||||
return std::make_unique<CacheTestWebUIController>(web_ui);
|
||||
}
|
||||
|
||||
std::unique_ptr<WebUIController> CreateHybridController(WebUI* web_ui) {
|
||||
return std::make_unique<TestWebUIController>(
|
||||
web_ui, run_loop_,
|
||||
BINDINGS_POLICY_WEB_UI | BINDINGS_POLICY_MOJO_WEB_UI);
|
||||
web_ui, BINDINGS_POLICY_WEB_UI | BINDINGS_POLICY_MOJO_WEB_UI);
|
||||
}
|
||||
|
||||
std::unique_ptr<WebUIController> CreateWebUIController(WebUI* web_ui) {
|
||||
return std::make_unique<TestWebUIController>(web_ui, run_loop_,
|
||||
return std::make_unique<TestWebUIController>(web_ui,
|
||||
BINDINGS_POLICY_WEB_UI);
|
||||
}
|
||||
|
||||
base::RunLoop* run_loop_;
|
||||
bool web_ui_enabled_ = true;
|
||||
const base::flat_map<
|
||||
std::string,
|
||||
@ -256,14 +216,15 @@ class TestWebUIContentBrowserClient : public ContentBrowserClient {
|
||||
void RegisterBrowserInterfaceBindersForFrame(
|
||||
RenderFrameHost* render_frame_host,
|
||||
mojo::BinderMapWithContext<content::RenderFrameHost*>* map) override {
|
||||
map->Add<mojom::BrowserTarget>(
|
||||
base::BindRepeating(&TestWebUIContentBrowserClient::BindBrowserTarget,
|
||||
base::Unretained(this)));
|
||||
map->Add<mojom::WebUIMojoTestCache>(base::BindRepeating(
|
||||
&TestWebUIContentBrowserClient::BindTestCache, base::Unretained(this)));
|
||||
}
|
||||
void BindBrowserTarget(content::RenderFrameHost* render_frame_host,
|
||||
mojo::PendingReceiver<mojom::BrowserTarget> receiver) {
|
||||
void BindTestCache(
|
||||
content::RenderFrameHost* render_frame_host,
|
||||
mojo::PendingReceiver<mojom::WebUIMojoTestCache> receiver) {
|
||||
auto* contents = WebContents::FromRenderFrameHost(render_frame_host);
|
||||
static_cast<PingTestWebUIController*>(contents->GetWebUI()->GetController())
|
||||
static_cast<CacheTestWebUIController*>(
|
||||
contents->GetWebUI()->GetController())
|
||||
->CreateHandler(std::move(receiver));
|
||||
}
|
||||
};
|
||||
@ -283,8 +244,9 @@ class WebUIMojoTest : public ContentBrowserTest {
|
||||
void NavigateWithNewWebUI(const std::string& path) {
|
||||
// Load a dummy WebUI URL first so that a new WebUI is set up when we load
|
||||
// the URL we're actually interested in.
|
||||
EXPECT_TRUE(NavigateToURL(shell(), GetWebUIURL("dummy-web-ui")));
|
||||
EXPECT_TRUE(NavigateToURL(shell(), GetWebUIURL("mojo-web-ui/" + path)));
|
||||
EXPECT_TRUE(NavigateToURL(shell(), GetWebUIURL(kDummyWebUiHost)));
|
||||
EXPECT_TRUE(NavigateToURL(
|
||||
shell(), GetWebUIURL(kMojoWebUiHost + std::string("/") + path)));
|
||||
}
|
||||
|
||||
// Run |script| and return a boolean result.
|
||||
@ -314,78 +276,50 @@ class WebUIMojoTest : public ContentBrowserTest {
|
||||
DISALLOW_COPY_AND_ASSIGN(WebUIMojoTest);
|
||||
};
|
||||
|
||||
bool IsGeneratedResourceAvailable(const std::string& resource_path) {
|
||||
// Currently there is no way to have a generated file included in the isolate
|
||||
// files. If the bindings file doesn't exist assume we're on such a bot and
|
||||
// pass.
|
||||
// TODO(sky): remove this conditional when isolates support copying from gen.
|
||||
base::ScopedAllowBlockingForTesting allow_blocking;
|
||||
const base::FilePath test_file_path(GetFilePathForJSResource(resource_path));
|
||||
if (base::PathExists(test_file_path))
|
||||
return true;
|
||||
LOG(WARNING) << " mojom binding file doesn't exist, assuming on isolate";
|
||||
return false;
|
||||
}
|
||||
// Loads a WebUI page that contains Mojo JS bindings and verifies a message
|
||||
// round-trip between the page and the browser.
|
||||
IN_PROC_BROWSER_TEST_F(WebUIMojoTest, EndToEndCommunication) {
|
||||
GURL kTestUrl(GetWebUIURL(std::string(kMojoWebUiHost) + "/?cache"));
|
||||
const std::string kTestScript = "runTest();";
|
||||
bool passed = false;
|
||||
EXPECT_TRUE(NavigateToURL(shell(), kTestUrl));
|
||||
EXPECT_TRUE(ExecuteScriptAndExtractBool(shell()->web_contents(), kTestScript,
|
||||
&passed));
|
||||
EXPECT_TRUE(passed);
|
||||
|
||||
// Loads a webui page that contains mojo bindings and verifies a message makes
|
||||
// it from the browser to the page and back.
|
||||
IN_PROC_BROWSER_TEST_F(WebUIMojoTest, EndToEndPing) {
|
||||
if (!IsGeneratedResourceAvailable(
|
||||
"content/test/data/web_ui_test_mojo_bindings.mojom-lite.js"))
|
||||
return;
|
||||
GURL test_url(GetWebUIURL("mojo-web-ui/web_ui_mojo.html?ping"));
|
||||
// Check that a second shell works correctly.
|
||||
passed = false;
|
||||
Shell* other_shell = CreateBrowser();
|
||||
EXPECT_TRUE(NavigateToURL(other_shell, kTestUrl));
|
||||
EXPECT_TRUE(ExecuteScriptAndExtractBool(other_shell->web_contents(),
|
||||
kTestScript, &passed));
|
||||
EXPECT_TRUE(passed);
|
||||
|
||||
{
|
||||
g_got_message = false;
|
||||
base::RunLoop run_loop;
|
||||
factory()->set_run_loop(&run_loop);
|
||||
EXPECT_TRUE(NavigateToURL(shell(), test_url));
|
||||
// RunLoop is quit when message received from page.
|
||||
run_loop.Run();
|
||||
EXPECT_TRUE(g_got_message);
|
||||
}
|
||||
// We expect two independent chrome://foo tabs/shells to use a separate
|
||||
// process.
|
||||
EXPECT_NE(shell()->web_contents()->GetMainFrame()->GetProcess(),
|
||||
other_shell->web_contents()->GetMainFrame()->GetProcess());
|
||||
|
||||
{
|
||||
// Check that a second shell works correctly.
|
||||
Shell* other_shell = CreateBrowser();
|
||||
g_got_message = false;
|
||||
base::RunLoop other_run_loop;
|
||||
factory()->set_run_loop(&other_run_loop);
|
||||
EXPECT_TRUE(NavigateToURL(other_shell, test_url));
|
||||
// RunLoop is quit when message received from page.
|
||||
other_run_loop.Run();
|
||||
EXPECT_TRUE(g_got_message);
|
||||
// Close the second shell and wait until its process exits.
|
||||
RenderProcessHostWatcher process_watcher(
|
||||
other_shell->web_contents()->GetMainFrame()->GetProcess(),
|
||||
RenderProcessHostWatcher::WATCH_FOR_PROCESS_EXIT);
|
||||
other_shell->Close();
|
||||
process_watcher.Wait();
|
||||
|
||||
// We expect two independent chrome://foo tabs/shells to use a separate
|
||||
// process.
|
||||
EXPECT_NE(shell()->web_contents()->GetMainFrame()->GetProcess(),
|
||||
other_shell->web_contents()->GetMainFrame()->GetProcess());
|
||||
// Check that a third shell works correctly, even if we force it to share a
|
||||
// process with the first shell, by forcing an artificially low process
|
||||
// limit.
|
||||
RenderProcessHost::SetMaxRendererProcessCount(1);
|
||||
|
||||
// Close the second shell and wait until its process exits.
|
||||
RenderProcessHostWatcher process_watcher(
|
||||
other_shell->web_contents()->GetMainFrame()->GetProcess(),
|
||||
RenderProcessHostWatcher::WATCH_FOR_PROCESS_EXIT);
|
||||
other_shell->Close();
|
||||
process_watcher.Wait();
|
||||
}
|
||||
|
||||
{
|
||||
// Check that a third shell works correctly, even if we force it to share a
|
||||
// process with the first shell, by forcing an artificially low process
|
||||
// limit.
|
||||
RenderProcessHost::SetMaxRendererProcessCount(1);
|
||||
|
||||
Shell* other_shell = CreateBrowser();
|
||||
g_got_message = false;
|
||||
base::RunLoop other_run_loop;
|
||||
factory()->set_run_loop(&other_run_loop);
|
||||
EXPECT_TRUE(NavigateToURL(other_shell, test_url));
|
||||
// RunLoop is quit when message received from page.
|
||||
other_run_loop.Run();
|
||||
EXPECT_TRUE(g_got_message);
|
||||
EXPECT_EQ(shell()->web_contents()->GetMainFrame()->GetProcess(),
|
||||
other_shell->web_contents()->GetMainFrame()->GetProcess());
|
||||
}
|
||||
other_shell = CreateBrowser();
|
||||
passed = false;
|
||||
EXPECT_TRUE(NavigateToURL(other_shell, kTestUrl));
|
||||
EXPECT_EQ(shell()->web_contents()->GetMainFrame()->GetProcess(),
|
||||
other_shell->web_contents()->GetMainFrame()->GetProcess());
|
||||
EXPECT_TRUE(ExecuteScriptAndExtractBool(other_shell->web_contents(),
|
||||
kTestScript, &passed));
|
||||
EXPECT_TRUE(passed);
|
||||
}
|
||||
|
||||
// Disabled due to flakiness: crbug.com/860385.
|
||||
@ -445,8 +379,8 @@ IN_PROC_BROWSER_TEST_F(WebUIMojoTest, MAYBE_ChromeSendAvailable) {
|
||||
}
|
||||
|
||||
IN_PROC_BROWSER_TEST_F(WebUIMojoTest, ChromeSendAvailable_AfterCrash) {
|
||||
GURL test_url(
|
||||
GetWebUIURL("mojo-web-ui/web_ui_mojo_native.html?webui_bindings"));
|
||||
GURL test_url(GetWebUIURL(std::string(kMojoWebUiHost) +
|
||||
"/web_ui_mojo_native.html?webui_bindings"));
|
||||
|
||||
// Navigate with normal WebUI bindings and ensure chrome.send is available.
|
||||
EXPECT_TRUE(NavigateToURL(shell(), test_url));
|
||||
|
@ -35,6 +35,7 @@ Other resources that belong in this file:
|
||||
<include name="IDR_UNGUESSABLE_TOKEN_MOJO_JS" file="${root_gen_dir}/mojo/public/mojom/base/unguessable_token.mojom-lite.js" use_base_dir="false" type="BINDATA" />
|
||||
<include name="IDR_URL_MOJO_HTML" file="${root_gen_dir}/url/mojom/url.mojom.html" use_base_dir="false" type="BINDATA" />
|
||||
<include name="IDR_URL_MOJO_JS" file="${root_gen_dir}/url/mojom/url.mojom-lite.js" use_base_dir="false" type="BINDATA" />
|
||||
<include name="IDR_URL_MOJOM_WEBUI_JS" file="${root_gen_dir}/mojom-webui/url/mojom/url.mojom-webui.js" use_base_dir="false" type="BINDATA" />
|
||||
<include name="IDR_VULKAN_INFO_MOJO_JS" file="${root_gen_dir}/gpu/ipc/common/vulkan_info.mojom-lite.js" use_base_dir="false" type="BINDATA" />
|
||||
<include name="IDR_VULKAN_TYPES_MOJO_JS" file="${root_gen_dir}/gpu/ipc/common/vulkan_types.mojom-lite.js" use_base_dir="false" type="BINDATA" />
|
||||
</includes>
|
||||
|
@ -408,6 +408,7 @@ repack("pak") {
|
||||
"$root_gen_dir/content/content_resources.pak",
|
||||
"$root_gen_dir/content/dev_ui_content_resources.pak",
|
||||
"$root_gen_dir/content/shell/shell_resources.pak",
|
||||
"$root_gen_dir/content/test/web_ui_mojo_test_resources.pak",
|
||||
"$root_gen_dir/mojo/public/js/mojo_bindings_resources.pak",
|
||||
"$root_gen_dir/net/net_resources.pak",
|
||||
"$root_gen_dir/third_party/blink/public/resources/blink_resources.pak",
|
||||
@ -428,6 +429,7 @@ repack("pak") {
|
||||
"//content/browser/resources/media:media_internals_resources",
|
||||
"//content/browser/tracing:resources",
|
||||
"//content/browser/webrtc/resources",
|
||||
"//content/test:web_ui_mojo_test_resources",
|
||||
"//mojo/public/js:resources",
|
||||
"//net:net_resources",
|
||||
"//third_party/blink/public:devtools_inspector_resources",
|
||||
|
@ -18,6 +18,9 @@ import("//net/features.gni")
|
||||
import("//ppapi/buildflags/buildflags.gni")
|
||||
import("//testing/test.gni")
|
||||
import("//third_party/blink/public/public_features.gni")
|
||||
import("//third_party/closure_compiler/closure_args.gni")
|
||||
import("//third_party/closure_compiler/compile_js.gni")
|
||||
import("//tools/grit/grit_rule.gni")
|
||||
import("//tools/v8_context_snapshot/v8_context_snapshot.gni")
|
||||
import("//v8/gni/v8.gni")
|
||||
|
||||
@ -778,7 +781,26 @@ mojom("content_test_mojo_bindings") {
|
||||
}
|
||||
|
||||
mojom("web_ui_test_mojo_bindings") {
|
||||
sources = [ "data/web_ui_test_mojo_bindings.mojom" ]
|
||||
testonly = true
|
||||
sources = [
|
||||
"data/web_ui_test.test-mojom",
|
||||
"data/web_ui_test_types.test-mojom",
|
||||
]
|
||||
public_deps = [ "//url/mojom:url_mojom_gurl" ]
|
||||
webui_module_path = "/content/test/data"
|
||||
}
|
||||
|
||||
js_library("web_ui_mojo_test_js") {
|
||||
sources = [ "data/web_ui_mojo_test.js" ]
|
||||
deps = [ ":web_ui_test_mojo_bindings_webui_js" ]
|
||||
}
|
||||
|
||||
# NOTE: Building this target serves as a compile test for type-checking of
|
||||
# WebUI JS that consumes generated Mojom JS bindings.
|
||||
js_type_check("web_ui_mojo_test_js_type_check") {
|
||||
uses_js_modules = true
|
||||
deps = [ ":web_ui_mojo_test_js" ]
|
||||
closure_flags = mojom_js_args
|
||||
}
|
||||
|
||||
mojom("mojo_web_test_bindings") {
|
||||
@ -1181,6 +1203,7 @@ test("content_browsertests") {
|
||||
]
|
||||
|
||||
public_deps = [
|
||||
":web_ui_mojo_test_resources",
|
||||
"//content:content_resources",
|
||||
"//content:dev_ui_content_resources",
|
||||
]
|
||||
@ -1190,6 +1213,7 @@ test("content_browsertests") {
|
||||
":content_test_mojo_bindings",
|
||||
":test_interfaces",
|
||||
":test_support",
|
||||
":web_ui_mojo_test_js_type_check",
|
||||
":web_ui_test_mojo_bindings",
|
||||
"//base/test:test_support",
|
||||
"//build:chromecast_buildflags",
|
||||
@ -1305,7 +1329,6 @@ test("content_browsertests") {
|
||||
data = []
|
||||
|
||||
data_deps = [
|
||||
":web_ui_test_mojo_bindings_js_data_deps",
|
||||
"//content/shell:pak",
|
||||
"//testing/buildbot/filters:content_browsertests_filters",
|
||||
"//third_party/mesa_headers",
|
||||
@ -1621,6 +1644,22 @@ test("content_browsertests") {
|
||||
}
|
||||
}
|
||||
|
||||
grit("web_ui_mojo_test_resources") {
|
||||
source = "web_ui_mojo_test_resources.grd"
|
||||
|
||||
outputs = [
|
||||
"grit/web_ui_mojo_test_resources.h",
|
||||
"grit/web_ui_mojo_test_resources_map.cc",
|
||||
"grit/web_ui_mojo_test_resources_map.h",
|
||||
"web_ui_mojo_test_resources.pak",
|
||||
]
|
||||
grit_flags = [
|
||||
"-E",
|
||||
"root_gen_dir=" + rebase_path(root_gen_dir, root_build_dir),
|
||||
]
|
||||
deps = [ ":web_ui_test_mojo_bindings_webui_js" ]
|
||||
}
|
||||
|
||||
static_library("run_all_unittests") {
|
||||
testonly = true
|
||||
sources = [ "run_all_unittests.cc" ]
|
||||
|
@ -1,10 +0,0 @@
|
||||
<html>
|
||||
<head>
|
||||
<script src="chrome://resources/mojo/mojo/public/js/mojo_bindings_lite.js"></script>
|
||||
<script src="content/test/data/web_ui_test_mojo_bindings.mojom-lite.js"></script>
|
||||
<script src="web_ui_mojo.js"></script>
|
||||
</head>
|
||||
<body>
|
||||
x
|
||||
</body>
|
||||
</html>
|
@ -1,10 +0,0 @@
|
||||
// Copyright 2014 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.
|
||||
|
||||
(async () => {
|
||||
const browserTarget = content.mojom.BrowserTarget.getRemote();
|
||||
|
||||
await browserTarget.start();
|
||||
browserTarget.stop();
|
||||
})();
|
8
content/test/data/web_ui_mojo_test.html
Normal file
8
content/test/data/web_ui_mojo_test.html
Normal file
@ -0,0 +1,8 @@
|
||||
<html>
|
||||
<head>
|
||||
<script src="web_ui_mojo_test.js" type="module"></script>
|
||||
</head>
|
||||
<body>
|
||||
x
|
||||
</body>
|
||||
</html>
|
46
content/test/data/web_ui_mojo_test.js
Normal file
46
content/test/data/web_ui_mojo_test.js
Normal file
@ -0,0 +1,46 @@
|
||||
// Copyright 2020 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 {WebUIMojoTestCache} from './content/test/data/web_ui_test.test-mojom-webui.js';
|
||||
|
||||
/** @type {{send: function(*)}} */
|
||||
Window.prototype.domAutomationController;
|
||||
|
||||
const TEST_DATA = [
|
||||
{ url: 'https://google.com/', contents: 'i am in fact feeling lucky' },
|
||||
{ url: 'https://youtube.com/', contents: 'probably cat videos?' },
|
||||
{ url: 'https://example.com/', contents: 'internets wow' },
|
||||
];
|
||||
|
||||
async function doTest() {
|
||||
const cache = WebUIMojoTestCache.getRemote();
|
||||
for (const entry of TEST_DATA) {
|
||||
cache.put({ url: entry.url }, entry.contents);
|
||||
}
|
||||
|
||||
const {items} = await cache.getAll();
|
||||
if (items.length != TEST_DATA.length) {
|
||||
return false;
|
||||
}
|
||||
|
||||
const entries = {};
|
||||
for (const item of items) {
|
||||
entries[item.url.url] = item.contents;
|
||||
}
|
||||
|
||||
for (const entry of TEST_DATA) {
|
||||
if (!(entry.url in entries)) {
|
||||
return false;
|
||||
}
|
||||
if (entries[entry.url] != entry.contents) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
window.runTest = async function() {
|
||||
window.domAutomationController.send(await doTest());
|
||||
}
|
13
content/test/data/web_ui_test.test-mojom
Normal file
13
content/test/data/web_ui_test.test-mojom
Normal file
@ -0,0 +1,13 @@
|
||||
// Copyright 2020 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 content.mojom;
|
||||
|
||||
import "content/test/data/web_ui_test_types.test-mojom";
|
||||
import "url/mojom/url.mojom";
|
||||
|
||||
interface WebUIMojoTestCache {
|
||||
Put(url.mojom.Url url, string contents);
|
||||
GetAll() => (array<CacheItem> items);
|
||||
};
|
@ -1,10 +0,0 @@
|
||||
// Copyright 2014 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 content.mojom;
|
||||
|
||||
interface BrowserTarget {
|
||||
Start() => ();
|
||||
Stop();
|
||||
};
|
16
content/test/data/web_ui_test_types.test-mojom
Normal file
16
content/test/data/web_ui_test_types.test-mojom
Normal file
@ -0,0 +1,16 @@
|
||||
// Copyright 2020 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 content.mojom;
|
||||
|
||||
import "url/mojom/url.mojom";
|
||||
|
||||
// This struct is imported by web_ui_test.test-mojom and is used to provide
|
||||
// test coverage of non-shared WebUI mojom JS modules importing other
|
||||
// non-shared WebUI mojom JS modules.
|
||||
struct CacheItem {
|
||||
url.mojom.Url url;
|
||||
string contents;
|
||||
};
|
||||
|
25
content/test/web_ui_mojo_test_resources.grd
Normal file
25
content/test/web_ui_mojo_test_resources.grd
Normal file
@ -0,0 +1,25 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!--
|
||||
This file specifies resources for content_browsertests.
|
||||
-->
|
||||
<grit latest_public_release="0" current_release="1" output_all_resource_defines="false">
|
||||
<outputs>
|
||||
<output filename="grit/web_ui_mojo_test_resources.h" type="rc_header">
|
||||
<emit emit_type='prepend'></emit>
|
||||
</output>
|
||||
<output filename="grit/web_ui_mojo_test_resources_map.cc" type="resource_file_map_source" />
|
||||
<output filename="grit/web_ui_mojo_test_resources_map.h" type="resource_map_header" />
|
||||
<output filename="web_ui_mojo_test_resources.pak" type="data_package" />
|
||||
</outputs>
|
||||
<translations />
|
||||
<release seq="1">
|
||||
<includes>
|
||||
<include name="IDR_WEB_UI_MOJO_HTML" file="data/web_ui_mojo_test.html" type="BINDATA" />
|
||||
<include name="IDR_WEB_UI_MOJO_JS" file="data/web_ui_mojo_test.js" type="BINDATA" resource_path="web_ui_mojo_test.js" />
|
||||
<include name="IDR_WEB_UI_MOJO_NATIVE_HTML" file="data/web_ui_mojo_native.html" type="BINDATA" resource_path="web_ui_mojo_native.html" />
|
||||
<include name="IDR_WEB_UI_MOJO_NATIVE_JS" file="data/web_ui_mojo_native.js" type="BINDATA" resource_path="web_ui_mojo_native.js" />
|
||||
<include name="IDR_WEB_UI_TEST_MOJOM_JS" file="${root_gen_dir}/mojom-webui/content/test/data/web_ui_test.test-mojom-webui.js" use_base_dir="false" type="BINDATA" resource_path="content/test/data/web_ui_test.test-mojom-webui.js" />
|
||||
<include name="IDR_WEB_UI_TEST_TYPES_MOJOM_JS" file="${root_gen_dir}/mojom-webui/content/test/data/web_ui_test_types.test-mojom-webui.js" use_base_dir="false" type="BINDATA" resource_path="content/test/data/web_ui_test_types.test-mojom-webui.js" />
|
||||
</includes>
|
||||
</release>
|
||||
</grit>
|
@ -103,7 +103,7 @@ concatenate_files("bindings_uncompiled_module") {
|
||||
"interface_support.js",
|
||||
"bindings_uncompiled_module_export.js.part",
|
||||
]
|
||||
output = "bindings_uncompiled.m.js"
|
||||
output = "bindings_uncompiled.js"
|
||||
deps = [ "//mojo/public/interfaces/bindings:bindings_js_library" ]
|
||||
}
|
||||
|
||||
@ -128,13 +128,13 @@ if (enable_mojom_closure_compile || enable_js_type_check) {
|
||||
"$target_gen_dir/mojo_bindings_lite.js",
|
||||
"bindings_module_export.js.part",
|
||||
]
|
||||
output = "bindings_compiled.m.js"
|
||||
output = "bindings_compiled.js"
|
||||
deps = [ ":bindings_lite" ]
|
||||
}
|
||||
|
||||
copy("bindings_module") {
|
||||
sources = [ "$target_gen_dir/bindings_compiled.m.js" ]
|
||||
outputs = [ "$target_gen_dir/bindings.m.js" ]
|
||||
sources = [ "$target_gen_dir/bindings_compiled.js" ]
|
||||
outputs = [ "$target_gen_dir/bindings.js" ]
|
||||
deps = [ ":bindings_compiled_module" ]
|
||||
}
|
||||
} else {
|
||||
@ -158,19 +158,19 @@ if (enable_mojom_closure_compile || enable_js_type_check) {
|
||||
}
|
||||
|
||||
copy("bindings_module") {
|
||||
sources = [ "$target_gen_dir/bindings_uncompiled.m.js" ]
|
||||
outputs = [ "$target_gen_dir/bindings.m.js" ]
|
||||
sources = [ "$target_gen_dir/bindings_uncompiled.js" ]
|
||||
outputs = [ "$target_gen_dir/bindings.js" ]
|
||||
deps = [ ":bindings_uncompiled_module" ]
|
||||
}
|
||||
}
|
||||
|
||||
# This is the library target used in the dependency tree of any JS libraries
|
||||
# or binaries compiling against mojom JS bindings. This library is functionally
|
||||
# equivalent to the bindings.m.js generated by the ":bindings_module" target and
|
||||
# equivalent to the bindings.js generated by the ":bindings_module" target and
|
||||
# used at runtime by all consumers, except that this module includes all type
|
||||
# annotations and is suitable for Closure compilation and type checking.
|
||||
js_library("bindings_uncompiled.m") {
|
||||
sources = [ "$target_gen_dir/bindings_uncompiled.m.js" ]
|
||||
js_library("bindings_uncompiled") {
|
||||
sources = [ "$target_gen_dir/bindings_uncompiled.js" ]
|
||||
extra_deps = [ ":bindings_uncompiled_module" ]
|
||||
}
|
||||
|
||||
@ -192,6 +192,7 @@ grit("resources") {
|
||||
deps = [
|
||||
":bindings",
|
||||
":bindings_lite",
|
||||
":bindings_module",
|
||||
"//mojo/public/mojom/base:base_js",
|
||||
]
|
||||
}
|
||||
|
@ -7,7 +7,7 @@
|
||||
<output filename="grit/mojo_bindings_resources_map.h"
|
||||
type="resource_map_header" />
|
||||
<output filename="grit/mojo_bindings_resources_map.cc"
|
||||
type="resource_map_source" />
|
||||
type="resource_file_map_source" />
|
||||
<output filename="mojo_bindings_resources.pak" type="data_package" />
|
||||
</outputs>
|
||||
<translations />
|
||||
@ -18,55 +18,73 @@
|
||||
<include name="IDR_MOJO_MOJO_BINDINGS_JS"
|
||||
file="${root_gen_dir}/mojo/public/js/mojo_bindings.js"
|
||||
use_base_dir="false"
|
||||
resource_path="mojo/mojo/public/js/mojo_bindings.js"
|
||||
type="BINDATA" />
|
||||
</if>
|
||||
<include name="IDR_MOJO_BINDINGS_JS"
|
||||
file="${root_gen_dir}/mojo/public/js/bindings.js"
|
||||
use_base_dir="false"
|
||||
resource_path="mojo/mojo/public/js/bindings.js"
|
||||
type="BINDATA" />
|
||||
<include name="IDR_MOJO_MOJO_BINDINGS_LITE_HTML"
|
||||
file="mojo_bindings_lite.html"
|
||||
resource_path="mojo/mojo/public/js/mojo_bindings_lite.html"
|
||||
type="BINDATA" />
|
||||
<include name="IDR_MOJO_MOJO_BINDINGS_LITE_JS"
|
||||
file="${root_gen_dir}/mojo/public/js/mojo_bindings_lite.js"
|
||||
use_base_dir="false"
|
||||
resource_path="mojo/mojo/public/js/mojo_bindings_lite.js"
|
||||
type="BINDATA" />
|
||||
<include name="IDR_MOJO_BIG_BUFFER_MOJOM_HTML"
|
||||
file="${root_gen_dir}/mojo/public/mojom/base/big_buffer.mojom.html"
|
||||
use_base_dir="false"
|
||||
resource_path="mojo/mojo/public/mojom/base/big_buffer.mojom.html"
|
||||
type="BINDATA" />
|
||||
<include name="IDR_MOJO_BIG_BUFFER_MOJOM_LITE_JS"
|
||||
file="${root_gen_dir}/mojo/public/mojom/base/big_buffer.mojom-lite.js"
|
||||
use_base_dir="false"
|
||||
resource_path="mojo/mojo/public/mojom/base/big_buffer.mojom-lite.js"
|
||||
type="BINDATA" />
|
||||
<include name="IDR_MOJO_FILE_MOJOM_HTML"
|
||||
file="${root_gen_dir}/mojo/public/mojom/base/file.mojom.html"
|
||||
use_base_dir="false"
|
||||
resource_path="mojo/mojo/public/mojom/base/file.mojom.html"
|
||||
type="BINDATA" />
|
||||
<include name="IDR_MOJO_FILE_MOJOM_LITE_JS"
|
||||
file="${root_gen_dir}/mojo/public/mojom/base/file.mojom-lite.js"
|
||||
use_base_dir="false"
|
||||
resource_path="mojo/mojo/public/mojom/base/file.mojom-lite.js"
|
||||
type="BINDATA" />
|
||||
<include name="IDR_MOJO_STRING16_MOJOM_HTML"
|
||||
file="${root_gen_dir}/mojo/public/mojom/base/string16.mojom.html"
|
||||
use_base_dir="false"
|
||||
resource_path="mojo/mojo/public/mojom/base/string16.mojom.html"
|
||||
type="BINDATA" />
|
||||
<include name="IDR_MOJO_STRING16_MOJOM_LITE_JS"
|
||||
file="${root_gen_dir}/mojo/public/mojom/base/string16.mojom-lite.js"
|
||||
use_base_dir="false"
|
||||
resource_path="mojo/mojo/public/mojom/base/string16.mojom-lite.js"
|
||||
type="BINDATA" />
|
||||
<include name="IDR_MOJO_TEXT_DIRECTION_MOJOM_HTML"
|
||||
file="${root_gen_dir}/mojo/public/mojom/base/text_direction.mojom.html"
|
||||
use_base_dir="false"
|
||||
resource_path="mojo/mojo/public/mojom/base/text_direction.mojom.html"
|
||||
type="BINDATA" />
|
||||
<include name="IDR_MOJO_TEXT_DIRECTION_MOJOM_LITE_JS"
|
||||
file="${root_gen_dir}/mojo/public/mojom/base/text_direction.mojom-lite.js"
|
||||
use_base_dir="false"
|
||||
resource_path="mojo/mojo/public/mojom/base/text_direction.mojom-lite.js"
|
||||
type="BINDATA" />
|
||||
<if expr="is_win or is_macosx or is_linux or is_android">
|
||||
<include name="IDR_MOJO_TIME_MOJOM_HTML"
|
||||
file="${root_gen_dir}/mojo/public/mojom/base/time.mojom.html"
|
||||
use_base_dir="false"
|
||||
resource_path="mojo/mojo/public/mojom/base/time.mojom.html"
|
||||
type="BINDATA"
|
||||
compress="gzip" />
|
||||
<include name="IDR_MOJO_TIME_MOJOM_LITE_JS"
|
||||
file="${root_gen_dir}/mojo/public/mojom/base/time.mojom-lite.js"
|
||||
resource_path="mojo/mojo/public/mojom/base/time.mojom-lite.js"
|
||||
use_base_dir="false"
|
||||
type="BINDATA"
|
||||
compress="gzip" />
|
||||
|
@ -1,7 +1,11 @@
|
||||
{# For bindings internals, generated code is concatenated into a larger module
|
||||
# at build time, so we avoid a superfluous file header here. #}
|
||||
{%- if not for_bindings_internals -%}
|
||||
// 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.
|
||||
'use strict';
|
||||
{%- endif %}
|
||||
|
||||
{% if generate_closure_exports -%}
|
||||
goog.require('mojo.internal');
|
||||
|
@ -40,6 +40,7 @@ mojo.internal.Struct(
|
||||
|
||||
{% if generate_closure_exports -%}
|
||||
goog.provide('{{module.namespace}}.{{struct.name}}');
|
||||
{%- endif %}
|
||||
|
||||
/** @record */
|
||||
{{module.namespace}}.{{struct.name}} = class {
|
||||
@ -51,4 +52,3 @@ goog.provide('{{module.namespace}}.{{struct.name}}');
|
||||
}
|
||||
};
|
||||
|
||||
{%- endif %}
|
||||
|
@ -203,6 +203,16 @@ _primitive_kind_to_fuzz_type = {
|
||||
}
|
||||
|
||||
|
||||
_SHARED_MODULE_PREFIX = 'chrome://resources/mojo'
|
||||
|
||||
|
||||
def _GetWebUiModulePath(module):
|
||||
path = module.metadata.get('webui_module_path')
|
||||
if path is None:
|
||||
return None
|
||||
return path.strip('/')
|
||||
|
||||
|
||||
def JavaScriptPayloadSize(packed):
|
||||
packed_fields = packed.packed_fields
|
||||
if not packed_fields:
|
||||
@ -265,24 +275,40 @@ class JavaScriptStylizer(generator.Stylizer):
|
||||
|
||||
|
||||
class Generator(generator.Generator):
|
||||
def _GetParameters(self, for_compile=False):
|
||||
def _GetParameters(self, for_compile=False, for_webui_module=False):
|
||||
return {
|
||||
"bindings_library_path": self._GetBindingsLibraryPath(),
|
||||
"enums": self.module.enums,
|
||||
"for_bindings_internals": self.disallow_native_types,
|
||||
"html_imports": self._GenerateHtmlImports(),
|
||||
"imports": self.module.imports,
|
||||
"interfaces": self.module.interfaces,
|
||||
"js_module_imports": self._GetJsModuleImports(),
|
||||
"kinds": self.module.kinds,
|
||||
"module": self.module,
|
||||
"mojom_filename": os.path.basename(self.module.path),
|
||||
"mojom_namespace": self.module.mojom_namespace,
|
||||
"structs": self.module.structs + self._GetStructsFromMethods(),
|
||||
"unions": self.module.unions,
|
||||
"generate_fuzzing": self.generate_fuzzing,
|
||||
"generate_closure_exports": for_compile,
|
||||
"generate_struct_deserializers": self.js_generate_struct_deserializers,
|
||||
"bindings_library_path":
|
||||
self._GetBindingsLibraryPath(for_webui_module=for_webui_module),
|
||||
"enums":
|
||||
self.module.enums,
|
||||
"for_bindings_internals":
|
||||
self.disallow_native_types,
|
||||
"html_imports":
|
||||
self._GenerateHtmlImports(),
|
||||
"imports":
|
||||
self.module.imports,
|
||||
"interfaces":
|
||||
self.module.interfaces,
|
||||
"js_module_imports":
|
||||
self._GetJsModuleImports(for_webui_module=for_webui_module),
|
||||
"kinds":
|
||||
self.module.kinds,
|
||||
"module":
|
||||
self.module,
|
||||
"mojom_filename":
|
||||
os.path.basename(self.module.path),
|
||||
"mojom_namespace":
|
||||
self.module.mojom_namespace,
|
||||
"structs":
|
||||
self.module.structs + self._GetStructsFromMethods(),
|
||||
"unions":
|
||||
self.module.unions,
|
||||
"generate_fuzzing":
|
||||
self.generate_fuzzing,
|
||||
"generate_closure_exports":
|
||||
for_compile,
|
||||
"generate_struct_deserializers":
|
||||
self.js_generate_struct_deserializers,
|
||||
}
|
||||
|
||||
@staticmethod
|
||||
@ -386,6 +412,10 @@ class Generator(generator.Generator):
|
||||
def _GenerateJsModule(self):
|
||||
return self._GetParameters()
|
||||
|
||||
@UseJinja("lite/mojom.m.js.tmpl")
|
||||
def _GenerateWebUiModule(self):
|
||||
return self._GetParameters(for_webui_module=True)
|
||||
|
||||
def GenerateFiles(self, args):
|
||||
if self.variant:
|
||||
raise Exception("Variants not supported in JavaScript bindings.")
|
||||
@ -409,6 +439,9 @@ class Generator(generator.Generator):
|
||||
"%s-lite-for-compile.js" % self.module.path)
|
||||
self.WriteWithComment(self._GenerateJsModule(),
|
||||
"%s.m.js" % self.module.path)
|
||||
if _GetWebUiModulePath(self.module) is not None:
|
||||
self.WriteWithComment(self._GenerateWebUiModule(),
|
||||
"mojom-webui/%s-webui.js" % self.module.path)
|
||||
|
||||
def _GetRelativePath(self, path):
|
||||
relpath = urllib_request.pathname2url(
|
||||
@ -417,8 +450,10 @@ class Generator(generator.Generator):
|
||||
return relpath
|
||||
return './' + relpath
|
||||
|
||||
def _GetBindingsLibraryPath(self):
|
||||
return self._GetRelativePath('mojo/public/js/bindings.m.js')
|
||||
def _GetBindingsLibraryPath(self, for_webui_module=False):
|
||||
if for_webui_module:
|
||||
return "chrome://resources/mojo/mojo/public/js/bindings.js"
|
||||
return self._GetRelativePath('mojo/public/js/bindings.js')
|
||||
|
||||
def _SetUniqueNameForImports(self):
|
||||
used_names = set()
|
||||
@ -951,13 +986,39 @@ class Generator(generator.Generator):
|
||||
os.path.relpath(full_import.path, os.path.dirname(self.module.path)))
|
||||
return result
|
||||
|
||||
def _GetJsModuleImports(self):
|
||||
def _GetJsModuleImports(self, for_webui_module=False):
|
||||
this_module_path = _GetWebUiModulePath(self.module)
|
||||
if this_module_path:
|
||||
this_module_is_shared = this_module_path.startswith(_SHARED_MODULE_PREFIX)
|
||||
imports = dict()
|
||||
for spec, kind in self.module.imported_kinds.items():
|
||||
path = self._GetRelativePath(kind.module.path) + '.m.js'
|
||||
if path not in imports:
|
||||
imports[path] = []
|
||||
imports[path].append(kind)
|
||||
if for_webui_module:
|
||||
base_path = _GetWebUiModulePath(kind.module)
|
||||
assert base_path is not None
|
||||
import_path = '{}/{}-webui.js'.format(
|
||||
base_path, os.path.basename(kind.module.path))
|
||||
import_module_is_shared = import_path.startswith(_SHARED_MODULE_PREFIX)
|
||||
if import_module_is_shared == this_module_is_shared:
|
||||
# Either we're a non-shared resource importing another non-shared
|
||||
# resource, or we're a shared resource importing another shared
|
||||
# resource. In both cases, we assume a relative import path will
|
||||
# suffice.
|
||||
import_path = os.path.relpath(
|
||||
import_path.lstrip(_SHARED_MODULE_PREFIX),
|
||||
this_module_path.lstrip(_SHARED_MODULE_PREFIX))
|
||||
if (not import_path.startswith('.')
|
||||
and not import_path.startswith('/')):
|
||||
import_path = './' + import_path
|
||||
else:
|
||||
assert import_module_is_shared, \
|
||||
'Shared WebUI module "{}" cannot depend on non-shared WebUI ' \
|
||||
'module "{}"'.format(self.module.path, kind.module.path)
|
||||
else:
|
||||
import_path = self._GetRelativePath(kind.module.path) + '.m.js'
|
||||
|
||||
if import_path not in imports:
|
||||
imports[import_path] = []
|
||||
imports[import_path].append(kind)
|
||||
return imports
|
||||
|
||||
def _GetStructsFromMethods(self):
|
||||
|
@ -291,6 +291,21 @@ if (enable_scrambled_message_ids) {
|
||||
# List of extra C++ templates that are used to generate additional source
|
||||
# and/or header files. The templates should end with extension ".tmpl".
|
||||
#
|
||||
# webui_module_path (optional)
|
||||
# The path or URL at which modules generated by this target will be
|
||||
# accessible to WebUI pages. This may either be an absolute path or
|
||||
# a full URL path starting with "chrome://resources/mojo".
|
||||
#
|
||||
# If an absolute path, a WebUI page may only import these modules if
|
||||
# they are manually packaged and mapped independently by that page's
|
||||
# WebUIDataSource. The mapped path must match the path given here.
|
||||
#
|
||||
# If this is is instead a URL string starting with
|
||||
# "chrome://resources/mojo", the generated resources must be added to
|
||||
# content_resources.grd and registered with
|
||||
# content::SharedResourcesDataSource with a corresponding path, at which
|
||||
# point they will be made available to all WebUI pages at the given URL.
|
||||
#
|
||||
# The following parameters are used to support the component build. They are
|
||||
# needed so that bindings which are linked with a component can use the same
|
||||
# export settings for classes. The first three are for the chromium variant, and
|
||||
@ -656,6 +671,13 @@ template("mojom") {
|
||||
enabled_feature,
|
||||
]
|
||||
}
|
||||
|
||||
if (defined(invoker.webui_module_path)) {
|
||||
args += [
|
||||
"--add-module-metadata",
|
||||
"webui_module_path=${invoker.webui_module_path}",
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -1556,6 +1578,10 @@ template("mojom") {
|
||||
"$root_gen_dir/$base_path.html",
|
||||
"$root_gen_dir/$base_path-lite-for-compile.js",
|
||||
]
|
||||
|
||||
if (defined(invoker.webui_module_path)) {
|
||||
outputs += [ "$root_gen_dir/mojom-webui/$base_path-webui.js" ]
|
||||
}
|
||||
}
|
||||
|
||||
response_file_contents = filelist
|
||||
@ -1689,7 +1715,7 @@ template("mojom") {
|
||||
invoker.disallow_native_types) {
|
||||
deps = []
|
||||
} else {
|
||||
deps = [ "//mojo/public/js:bindings_uncompiled.m" ]
|
||||
deps = [ "//mojo/public/js:bindings_uncompiled" ]
|
||||
}
|
||||
foreach(d, all_deps) {
|
||||
full_name = get_label_info(d, "label_no_toolchain")
|
||||
@ -1700,6 +1726,36 @@ template("mojom") {
|
||||
group(js_modules_target_name) {
|
||||
}
|
||||
}
|
||||
|
||||
if (defined(invoker.webui_module_path)) {
|
||||
webui_js_target_name = "${target_name}_webui_js"
|
||||
if (sources_list != []) {
|
||||
js_library(webui_js_target_name) {
|
||||
extra_public_deps = [ ":$generator_js_target_name" ]
|
||||
sources = []
|
||||
foreach(base_path, output_file_base_paths) {
|
||||
sources += [ "$root_gen_dir/mojom-webui/${base_path}-webui.js" ]
|
||||
}
|
||||
externs_list = [
|
||||
"${externs_path}/mojo_core.js",
|
||||
"${externs_path}/pending.js",
|
||||
]
|
||||
if (defined(invoker.disallow_native_types) &&
|
||||
invoker.disallow_native_types) {
|
||||
deps = []
|
||||
} else {
|
||||
deps = [ "//mojo/public/js:bindings_uncompiled" ]
|
||||
}
|
||||
foreach(d, all_deps) {
|
||||
full_name = get_label_info(d, "label_no_toolchain")
|
||||
deps += [ "${full_name}_webui_js" ]
|
||||
}
|
||||
}
|
||||
} else {
|
||||
group(webui_js_target_name) {
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if ((generate_fuzzing || !defined(invoker.cpp_only) || !invoker.cpp_only) &&
|
||||
use_typescript_for_target) {
|
||||
|
@ -1362,6 +1362,7 @@ class Module(object):
|
||||
self.attributes = attributes
|
||||
self.imports = []
|
||||
self.imported_kinds = {}
|
||||
self.metadata = {}
|
||||
|
||||
def __repr__(self):
|
||||
# Gives us a decent __repr__ for modules.
|
||||
|
@ -98,7 +98,7 @@ def _GetModuleFilename(mojom_filename):
|
||||
|
||||
|
||||
def _EnsureInputLoaded(mojom_abspath, module_path, abs_paths, asts,
|
||||
dependencies, loaded_modules):
|
||||
dependencies, loaded_modules, module_metadata):
|
||||
"""Recursively ensures that a module and its dependencies are loaded.
|
||||
|
||||
Args:
|
||||
@ -111,10 +111,8 @@ def _EnsureInputLoaded(mojom_abspath, module_path, abs_paths, asts,
|
||||
by absolute file path.
|
||||
loaded_modules: A mapping of all modules loaded so far, including non-input
|
||||
modules that were pulled in as transitive dependencies of the inputs.
|
||||
import_set: The working set of mojom imports processed so far in this
|
||||
call stack. Used to detect circular dependencies.
|
||||
import_stack: An ordered list of imports processed so far in this call
|
||||
stack. Used to report circular dependencies.
|
||||
module_metadata: Metadata to be attached to every module loaded by this
|
||||
helper.
|
||||
|
||||
Returns:
|
||||
None
|
||||
@ -129,7 +127,7 @@ def _EnsureInputLoaded(mojom_abspath, module_path, abs_paths, asts,
|
||||
for dep_abspath, dep_path in dependencies[mojom_abspath]:
|
||||
if dep_abspath not in loaded_modules:
|
||||
_EnsureInputLoaded(dep_abspath, dep_path, abs_paths, asts, dependencies,
|
||||
loaded_modules)
|
||||
loaded_modules, module_metadata)
|
||||
|
||||
imports = {}
|
||||
for imp in asts[mojom_abspath].import_list:
|
||||
@ -137,6 +135,7 @@ def _EnsureInputLoaded(mojom_abspath, module_path, abs_paths, asts,
|
||||
imports[path] = loaded_modules[abs_paths[path]]
|
||||
loaded_modules[mojom_abspath] = translate.OrderedModule(
|
||||
asts[mojom_abspath], module_path, imports)
|
||||
loaded_modules[mojom_abspath].metadata = dict(module_metadata)
|
||||
|
||||
|
||||
def _CollectAllowedImportsFromBuildMetadata(build_metadata_filename):
|
||||
@ -161,6 +160,7 @@ def _ParseMojoms(mojom_files,
|
||||
input_root_paths,
|
||||
output_root_path,
|
||||
enabled_features,
|
||||
module_metadata,
|
||||
allowed_imports=None):
|
||||
"""Parses a set of mojom files and produces serialized module outputs.
|
||||
|
||||
@ -176,6 +176,8 @@ def _ParseMojoms(mojom_files,
|
||||
modules for any transitive dependencies not listed in mojom_files.
|
||||
enabled_features: A list of enabled feature names, controlling which AST
|
||||
nodes are filtered by [EnableIf] attributes.
|
||||
module_metadata: A list of 2-tuples representing metadata key-value pairs to
|
||||
attach to each compiled module output.
|
||||
|
||||
Returns:
|
||||
None.
|
||||
@ -236,7 +238,7 @@ def _ParseMojoms(mojom_files,
|
||||
num_existing_modules_loaded = len(loaded_modules)
|
||||
for mojom_abspath, mojom_path in mojom_files_to_parse.items():
|
||||
_EnsureInputLoaded(mojom_abspath, mojom_path, abs_paths, loaded_mojom_asts,
|
||||
input_dependencies, loaded_modules)
|
||||
input_dependencies, loaded_modules, module_metadata)
|
||||
assert (num_existing_modules_loaded +
|
||||
len(mojom_files_to_parse) == len(loaded_modules))
|
||||
|
||||
@ -333,6 +335,16 @@ already present in the provided output root.""")
|
||||
'build-time dependency checking for mojom imports, where each build '
|
||||
'metadata file corresponds to a build target in the dependency graph of '
|
||||
'a typical build system.')
|
||||
arg_parser.add_argument(
|
||||
'--add-module-metadata',
|
||||
dest='module_metadata',
|
||||
default=[],
|
||||
action='append',
|
||||
metavar='KEY=VALUE',
|
||||
help='Adds a metadata key-value pair to the output module. This can be '
|
||||
'used by build toolchains to augment parsed mojom modules with product-'
|
||||
'specific metadata for later extraction and use by custom bindings '
|
||||
'generators.')
|
||||
|
||||
args, _ = arg_parser.parse_known_args(command_line)
|
||||
if args.mojom_file_list:
|
||||
@ -353,8 +365,9 @@ already present in the provided output root.""")
|
||||
else:
|
||||
allowed_imports = None
|
||||
|
||||
module_metadata = map(lambda kvp: tuple(kvp.split('=')), args.module_metadata)
|
||||
_ParseMojoms(mojom_files, input_roots, output_root, args.enabled_features,
|
||||
allowed_imports)
|
||||
module_metadata, allowed_imports)
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
|
16
third_party/closure_compiler/closure_args.gni
vendored
16
third_party/closure_compiler/closure_args.gni
vendored
@ -57,6 +57,22 @@ js_modules_args = [
|
||||
"chrome_pass=false",
|
||||
]
|
||||
|
||||
mojom_js_args = [
|
||||
"js_module_root=gen/mojo/public/js/",
|
||||
"js_module_root=gen/mojom-webui/",
|
||||
|
||||
# Mojom WebUI JS modules load bindings.js which may be compiled and stripped
|
||||
# of type annotations. Rewrite these references to the uncompiled equivalent
|
||||
# for compilation and type-checking.
|
||||
"browser_resolver_prefix_replacements=\"chrome://resources/mojo/mojo/public/js/bindings.js=/bindings_uncompiled.js\"",
|
||||
|
||||
# Shared Mojom WebUI JS modules are by convention exposed through URLs like
|
||||
# chrome://resources/mojo/<path-to-module>. At build time these will be given
|
||||
# as gen/<path-to-module> for compilation, so we can rewrite them as absolute
|
||||
# paths.
|
||||
"browser_resolver_prefix_replacements=\"chrome://resources/mojo/=/\"",
|
||||
]
|
||||
|
||||
polymer3_args = js_modules_args + [
|
||||
"browser_resolver_prefix_replacements=\"../polymer/polymer_bundled.min.js=../polymer/polymer_bundled.js\"",
|
||||
"browser_resolver_prefix_replacements=\"chrome://resources/polymer/v3_0/polymer/polymer_bundled.min.js=../../third_party/polymer/v3_0/components-chromium/polymer/polymer_bundled.js\"",
|
||||
|
@ -484,6 +484,9 @@
|
||||
"content/shell/shell_resources.grd": {
|
||||
"includes": [2940],
|
||||
},
|
||||
"content/test/web_ui_mojo_test_resources.grd": {
|
||||
"includes": [2950],
|
||||
},
|
||||
|
||||
# This file is generated during the build.
|
||||
"<(SHARED_INTERMEDIATE_DIR)/content/browser/tracing/tracing_resources.grd": {
|
||||
|
@ -40,6 +40,8 @@ mojom("url_mojom_gurl") {
|
||||
traits_public_deps = [ "//url" ]
|
||||
},
|
||||
]
|
||||
|
||||
webui_module_path = "chrome://resources/mojo/url/mojom"
|
||||
}
|
||||
|
||||
mojom("url_mojom_origin") {
|
||||
|
Reference in New Issue
Block a user