Commit 1df0bf47 authored by Andrey Kosyakov's avatar Andrey Kosyakov Committed by Commit Bot

DevTools extensions: validate devtools_page URLs

This ensures that the devtools_page URL has correct scheme and host,
both when loading the manifest and when pushing data to DevTools front-end.

Bug: 1059577
Change-Id: I69a7ccdccfae31781ead371a85d23df36f108665
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2118894
Commit-Queue: Andrey Kosyakov <caseq@chromium.org>
Reviewed-by: default avatarDevlin <rdevlin.cronin@chromium.org>
Cr-Commit-Position: refs/heads/master@{#753369}
parent 419be001
...@@ -1420,8 +1420,14 @@ void DevToolsUIBindings::AddDevToolsExtensionsToClient() { ...@@ -1420,8 +1420,14 @@ void DevToolsUIBindings::AddDevToolsExtensionsToClient() {
for (const scoped_refptr<const extensions::Extension>& extension : for (const scoped_refptr<const extensions::Extension>& extension :
registry->enabled_extensions()) { registry->enabled_extensions()) {
if (extensions::chrome_manifest_urls::GetDevToolsPage(extension.get()) if (extensions::chrome_manifest_urls::GetDevToolsPage(extension.get())
.is_empty()) .is_empty()) {
continue; continue;
}
GURL url =
extensions::chrome_manifest_urls::GetDevToolsPage(extension.get());
const bool is_extension_url = url.SchemeIs(extensions::kExtensionScheme) &&
url.host_piece() == extension->id();
CHECK(is_extension_url || url.SchemeIsHTTPOrHTTPS());
// Each devtools extension will need to be able to run in the devtools // Each devtools extension will need to be able to run in the devtools
// process. Grant the devtools process the ability to request URLs from the // process. Grant the devtools process the ability to request URLs from the
...@@ -1432,10 +1438,7 @@ void DevToolsUIBindings::AddDevToolsExtensionsToClient() { ...@@ -1432,10 +1438,7 @@ void DevToolsUIBindings::AddDevToolsExtensionsToClient() {
std::unique_ptr<base::DictionaryValue> extension_info( std::unique_ptr<base::DictionaryValue> extension_info(
new base::DictionaryValue()); new base::DictionaryValue());
extension_info->SetString( extension_info->SetString("startPage", url.spec());
"startPage",
extensions::chrome_manifest_urls::GetDevToolsPage(extension.get())
.spec());
extension_info->SetString("name", extension->name()); extension_info->SetString("name", extension->name());
extension_info->SetBoolean("exposeExperimentalAPIs", extension_info->SetBoolean("exposeExperimentalAPIs",
extension->permissions_data()->HasAPIPermission( extension->permissions_data()->HasAPIPermission(
......
...@@ -15,6 +15,7 @@ ...@@ -15,6 +15,7 @@
#include "build/build_config.h" #include "build/build_config.h"
#include "chrome/common/chrome_constants.h" #include "chrome/common/chrome_constants.h"
#include "chrome/common/url_constants.h" #include "chrome/common/url_constants.h"
#include "extensions/common/constants.h"
#include "extensions/common/error_utils.h" #include "extensions/common/error_utils.h"
#include "extensions/common/file_util.h" #include "extensions/common/file_util.h"
#include "extensions/common/manifest.h" #include "extensions/common/manifest.h"
...@@ -76,7 +77,15 @@ bool DevToolsPageHandler::Parse(Extension* extension, base::string16* error) { ...@@ -76,7 +77,15 @@ bool DevToolsPageHandler::Parse(Extension* extension, base::string16* error) {
*error = base::ASCIIToUTF16(errors::kInvalidDevToolsPage); *error = base::ASCIIToUTF16(errors::kInvalidDevToolsPage);
return false; return false;
} }
manifest_url->url_ = extension->GetResourceURL(devtools_str); GURL url = extension->GetResourceURL(devtools_str);
const bool is_extension_url =
url.SchemeIs(kExtensionScheme) && url.host_piece() == extension->id();
// TODO(caseq): using http(s) is unsupported and will be disabled in m83.
if (!is_extension_url && !url.SchemeIsHTTPOrHTTPS()) {
*error = base::ASCIIToUTF16(errors::kInvalidDevToolsPage);
return false;
}
manifest_url->url_ = std::move(url);
extension->SetManifestData(keys::kDevToolsPage, std::move(manifest_url)); extension->SetManifestData(keys::kDevToolsPage, std::move(manifest_url));
PermissionsParser::AddAPIPermission(extension, APIPermission::kDevtools); PermissionsParser::AddAPIPermission(extension, APIPermission::kDevtools);
return true; return true;
......
...@@ -72,7 +72,8 @@ extension pages as panels and sidebars to the DevTools window using the ...@@ -72,7 +72,8 @@ extension pages as panels and sidebars to the DevTools window using the
<p class="note">The <code>devtools_page</code> field must point to an HTML page. <p class="note">The <code>devtools_page</code> field must point to an HTML page.
This differs from the <code>background</code> field, used for specifying a background page, This differs from the <code>background</code> field, used for specifying a background page,
which lets you specify JavaScript files directly.</p> which lets you specify JavaScript files directly. The DevTools page must be
local to your extension, so it is best to specify it using a relative URL.</p>
<p>The <code>chrome.devtools.*</code> API modules are available only to the pages <p>The <code>chrome.devtools.*</code> API modules are available only to the pages
loaded within the DevTools window. Content scripts and other extension pages do not loaded within the DevTools window. Content scripts and other extension pages do not
......
...@@ -16,7 +16,17 @@ TEST_F(DevToolsPageManifestTest, DevToolsExtensions) { ...@@ -16,7 +16,17 @@ TEST_F(DevToolsPageManifestTest, DevToolsExtensions) {
LoadAndExpectError("devtools_extension_url_invalid_type.json", LoadAndExpectError("devtools_extension_url_invalid_type.json",
extensions::manifest_errors::kInvalidDevToolsPage); extensions::manifest_errors::kInvalidDevToolsPage);
LoadAndExpectError("devtools_extension_invalid_page_url.json",
extensions::manifest_errors::kInvalidDevToolsPage);
// TODO(caseq): the implementation should be changed to produce failure
// with the manifest below.
scoped_refptr<extensions::Extension> extension; scoped_refptr<extensions::Extension> extension;
extension = LoadAndExpectSuccess("devtools_extension_page_url_https.json");
EXPECT_EQ("https://bad.example.com/dont_ever_do_this.html",
extensions::chrome_manifest_urls::GetDevToolsPage(extension.get())
.spec());
extension = LoadAndExpectSuccess("devtools_extension.json"); extension = LoadAndExpectSuccess("devtools_extension.json");
EXPECT_EQ(extension->url().spec() + "devtools.html", EXPECT_EQ(extension->url().spec() + "devtools.html",
extensions::chrome_manifest_urls::GetDevToolsPage(extension.get()) extensions::chrome_manifest_urls::GetDevToolsPage(extension.get())
......
{
"name": "test",
"manifest_version": 2,
"version": "1",
"devtools_page": "data:text/html,hello"
}
{
"name": "test",
"manifest_version": 2,
"version": "1",
"devtools_page": "https://bad.example.com/dont_ever_do_this.html"
}
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