summaryrefslogtreecommitdiffstats
path: root/chromium/chrome/browser/devtools
diff options
context:
space:
mode:
Diffstat (limited to 'chromium/chrome/browser/devtools')
-rw-r--r--chromium/chrome/browser/devtools/BUILD.gn10
-rw-r--r--chromium/chrome/browser/devtools/OWNERS1
-rw-r--r--chromium/chrome/browser/devtools/chrome_devtools_manager_delegate.cc5
-rw-r--r--chromium/chrome/browser/devtools/chrome_devtools_manager_delegate.h1
-rw-r--r--chromium/chrome/browser/devtools/chrome_devtools_session.cc3
-rw-r--r--chromium/chrome/browser/devtools/chrome_devtools_session.h2
-rw-r--r--chromium/chrome/browser/devtools/device/android_device_manager.cc1
-rw-r--r--chromium/chrome/browser/devtools/device/devtools_android_bridge.cc4
-rw-r--r--chromium/chrome/browser/devtools/device/devtools_device_discovery.h1
-rw-r--r--chromium/chrome/browser/devtools/device/port_forwarding_controller.cc20
-rw-r--r--chromium/chrome/browser/devtools/device/tcp_device_provider.cc35
-rw-r--r--chromium/chrome/browser/devtools/device/tcp_device_provider.h8
-rw-r--r--chromium/chrome/browser/devtools/devtools_sanity_browsertest.cc22
-rw-r--r--chromium/chrome/browser/devtools/devtools_ui_bindings.cc146
-rw-r--r--chromium/chrome/browser/devtools/devtools_window.cc25
-rw-r--r--chromium/chrome/browser/devtools/devtools_window.h8
-rw-r--r--chromium/chrome/browser/devtools/frontend/devtools_discovery_page.html28
-rw-r--r--chromium/chrome/browser/devtools/inspector_protocol_config.json5
-rw-r--r--chromium/chrome/browser/devtools/protocol/devtools_protocol_browsertest.cc336
-rw-r--r--chromium/chrome/browser/devtools/protocol/security_handler.cc246
-rw-r--r--chromium/chrome/browser/devtools/protocol/security_handler.h37
-rw-r--r--chromium/chrome/browser/devtools/serialize_host_descriptions.cc6
22 files changed, 852 insertions, 98 deletions
diff --git a/chromium/chrome/browser/devtools/BUILD.gn b/chromium/chrome/browser/devtools/BUILD.gn
index 36b76413f8e..e89c23aab2d 100644
--- a/chromium/chrome/browser/devtools/BUILD.gn
+++ b/chromium/chrome/browser/devtools/BUILD.gn
@@ -26,6 +26,8 @@ if (!is_android) {
"protocol/page.h",
"protocol/protocol.cc",
"protocol/protocol.h",
+ "protocol/security.cc",
+ "protocol/security.h",
"protocol/target.cc",
"protocol/target.h",
]
@@ -198,8 +200,10 @@ static_library("devtools") {
sources += [ "devtools_dock_tile.cc" ]
}
if (!is_android) {
- deps += [ ":protocol_generated_sources",
- "//third_party/inspector_protocol:encoding" ]
+ deps += [
+ ":protocol_generated_sources",
+ "//third_party/inspector_protocol:encoding",
+ ]
sources += [
"protocol/browser_handler.cc",
"protocol/browser_handler.h",
@@ -207,6 +211,8 @@ static_library("devtools") {
"protocol/cast_handler.h",
"protocol/page_handler.cc",
"protocol/page_handler.h",
+ "protocol/security_handler.cc",
+ "protocol/security_handler.h",
"protocol/target_handler.cc",
"protocol/target_handler.h",
]
diff --git a/chromium/chrome/browser/devtools/OWNERS b/chromium/chrome/browser/devtools/OWNERS
index 1329473478e..e1277e85c22 100644
--- a/chromium/chrome/browser/devtools/OWNERS
+++ b/chromium/chrome/browser/devtools/OWNERS
@@ -1,6 +1,7 @@
dgozman@chromium.org
pfeldman@chromium.org
caseq@chromium.org
+yangguo@chromium.org
per-file devtools_embedder_message_dispatcher.*=set noparent
per-file devtools_embedder_message_dispatcher.*=file://ipc/SECURITY_OWNERS
diff --git a/chromium/chrome/browser/devtools/chrome_devtools_manager_delegate.cc b/chromium/chrome/browser/devtools/chrome_devtools_manager_delegate.cc
index d34abfa43f3..3564def60ef 100644
--- a/chromium/chrome/browser/devtools/chrome_devtools_manager_delegate.cc
+++ b/chromium/chrome/browser/devtools/chrome_devtools_manager_delegate.cc
@@ -227,9 +227,8 @@ ChromeDevToolsManagerDelegate::CreateNewTarget(const GURL& url) {
}
std::string ChromeDevToolsManagerDelegate::GetDiscoveryPageHTML() {
- return ui::ResourceBundle::GetSharedInstance()
- .GetRawDataResource(IDR_DEVTOOLS_DISCOVERY_PAGE_HTML)
- .as_string();
+ return ui::ResourceBundle::GetSharedInstance().DecompressDataResource(
+ IDR_DEVTOOLS_DISCOVERY_PAGE_HTML);
}
std::vector<content::BrowserContext*>
diff --git a/chromium/chrome/browser/devtools/chrome_devtools_manager_delegate.h b/chromium/chrome/browser/devtools/chrome_devtools_manager_delegate.h
index 27a2dd29112..0e7bdc0eb74 100644
--- a/chromium/chrome/browser/devtools/chrome_devtools_manager_delegate.h
+++ b/chromium/chrome/browser/devtools/chrome_devtools_manager_delegate.h
@@ -17,6 +17,7 @@
#include "chrome/browser/devtools/protocol/protocol.h"
#include "content/public/browser/devtools_agent_host_observer.h"
#include "content/public/browser/devtools_manager_delegate.h"
+#include "net/base/host_port_pair.h"
class ChromeDevToolsSession;
using RemoteLocations = std::set<net::HostPortPair>;
diff --git a/chromium/chrome/browser/devtools/chrome_devtools_session.cc b/chromium/chrome/browser/devtools/chrome_devtools_session.cc
index 4b75e59539e..846cdec8776 100644
--- a/chromium/chrome/browser/devtools/chrome_devtools_session.cc
+++ b/chromium/chrome/browser/devtools/chrome_devtools_session.cc
@@ -9,6 +9,7 @@
#include "chrome/browser/devtools/protocol/browser_handler.h"
#include "chrome/browser/devtools/protocol/cast_handler.h"
#include "chrome/browser/devtools/protocol/page_handler.h"
+#include "chrome/browser/devtools/protocol/security_handler.h"
#include "chrome/browser/devtools/protocol/target_handler.h"
#include "content/public/browser/devtools_agent_host.h"
#include "content/public/browser/devtools_agent_host_client.h"
@@ -64,6 +65,8 @@ ChromeDevToolsSession::ChromeDevToolsSession(
agent_host->GetType() == content::DevToolsAgentHost::kTypePage) {
page_handler_ = std::make_unique<PageHandler>(agent_host->GetWebContents(),
dispatcher_.get());
+ security_handler_ = std::make_unique<SecurityHandler>(
+ agent_host->GetWebContents(), dispatcher_.get());
if (client->MayAttachToBrowser()) {
cast_handler_ = std::make_unique<CastHandler>(
agent_host->GetWebContents(), dispatcher_.get());
diff --git a/chromium/chrome/browser/devtools/chrome_devtools_session.h b/chromium/chrome/browser/devtools/chrome_devtools_session.h
index 2665df6eb43..4a181761533 100644
--- a/chromium/chrome/browser/devtools/chrome_devtools_session.h
+++ b/chromium/chrome/browser/devtools/chrome_devtools_session.h
@@ -22,6 +22,7 @@ class DevToolsAgentHostClient;
class BrowserHandler;
class CastHandler;
class PageHandler;
+class SecurityHandler;
class TargetHandler;
class WindowManagerHandler;
@@ -61,6 +62,7 @@ class ChromeDevToolsSession : public protocol::FrontendChannel {
std::unique_ptr<BrowserHandler> browser_handler_;
std::unique_ptr<CastHandler> cast_handler_;
std::unique_ptr<PageHandler> page_handler_;
+ std::unique_ptr<SecurityHandler> security_handler_;
std::unique_ptr<TargetHandler> target_handler_;
#if defined(OS_CHROMEOS)
std::unique_ptr<WindowManagerHandler> window_manager_protocl_handler_;
diff --git a/chromium/chrome/browser/devtools/device/android_device_manager.cc b/chromium/chrome/browser/devtools/device/android_device_manager.cc
index a59205407f5..4c4cf0b8584 100644
--- a/chromium/chrome/browser/devtools/device/android_device_manager.cc
+++ b/chromium/chrome/browser/devtools/device/android_device_manager.cc
@@ -18,6 +18,7 @@
#include "base/strings/string_util.h"
#include "base/strings/stringprintf.h"
#include "base/task/post_task.h"
+#include "base/threading/thread.h"
#include "base/threading/thread_task_runner_handle.h"
#include "chrome/browser/devtools/device/usb/usb_device_manager_helper.h"
#include "chrome/browser/devtools/device/usb/usb_device_provider.h"
diff --git a/chromium/chrome/browser/devtools/device/devtools_android_bridge.cc b/chromium/chrome/browser/devtools/device/devtools_android_bridge.cc
index ec895142198..f799123063b 100644
--- a/chromium/chrome/browser/devtools/device/devtools_android_bridge.cc
+++ b/chromium/chrome/browser/devtools/device/devtools_android_bridge.cc
@@ -166,8 +166,8 @@ DevToolsAndroidBridge::DevToolsAndroidBridge(Profile* profile)
base::Bind(&DevToolsAndroidBridge::CreateDeviceProviders,
base::Unretained(this)));
base::Value target_discovery(base::Value::Type::LIST);
- target_discovery.GetList().emplace_back(kChromeDiscoveryURL);
- target_discovery.GetList().emplace_back(kNodeDiscoveryURL);
+ target_discovery.Append(kChromeDiscoveryURL);
+ target_discovery.Append(kNodeDiscoveryURL);
profile->GetPrefs()->SetDefaultPrefValue(prefs::kDevToolsTCPDiscoveryConfig,
std::move(target_discovery));
CreateDeviceProviders();
diff --git a/chromium/chrome/browser/devtools/device/devtools_device_discovery.h b/chromium/chrome/browser/devtools/device/devtools_device_discovery.h
index 7b97e2f90e5..a83ad1f91b4 100644
--- a/chromium/chrome/browser/devtools/device/devtools_device_discovery.h
+++ b/chromium/chrome/browser/devtools/device/devtools_device_discovery.h
@@ -13,6 +13,7 @@
#include "base/macros.h"
#include "base/memory/ref_counted.h"
#include "base/memory/weak_ptr.h"
+#include "base/values.h"
#include "chrome/browser/devtools/device/android_device_manager.h"
#include "content/public/browser/devtools_agent_host.h"
diff --git a/chromium/chrome/browser/devtools/device/port_forwarding_controller.cc b/chromium/chrome/browser/devtools/device/port_forwarding_controller.cc
index 99fe24c6d13..2fbd2e47362 100644
--- a/chromium/chrome/browser/devtools/device/port_forwarding_controller.cc
+++ b/chromium/chrome/browser/devtools/device/port_forwarding_controller.cc
@@ -28,7 +28,7 @@
#include "content/public/browser/browser_task_traits.h"
#include "content/public/browser/browser_thread.h"
#include "content/public/browser/storage_partition.h"
-#include "mojo/public/cpp/bindings/binding.h"
+#include "mojo/public/cpp/bindings/receiver.h"
#include "net/base/address_list.h"
#include "net/base/io_buffer.h"
#include "net/base/net_errors.h"
@@ -153,20 +153,18 @@ class PortForwardingHostResolver : public network::ResolveHostClientBase {
const std::string& host,
int port,
ResolveHostCallback resolve_host_callback)
- : binding_(this),
- resolve_host_callback_(std::move(resolve_host_callback)) {
+ : resolve_host_callback_(std::move(resolve_host_callback)) {
DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
- DCHECK(!binding_);
+ DCHECK(!receiver_.is_bound());
- network::mojom::ResolveHostClientPtr client_ptr;
- binding_.Bind(mojo::MakeRequest(&client_ptr));
- binding_.set_connection_error_handler(
- base::BindOnce(&PortForwardingHostResolver::OnComplete,
- base::Unretained(this), net::ERR_FAILED, base::nullopt));
net::HostPortPair host_port_pair(host, port);
content::BrowserContext::GetDefaultStoragePartition(profile)
->GetNetworkContext()
- ->ResolveHost(host_port_pair, nullptr, std::move(client_ptr));
+ ->ResolveHost(host_port_pair, nullptr,
+ receiver_.BindNewPipeAndPassRemote());
+ receiver_.set_disconnect_handler(
+ base::BindOnce(&PortForwardingHostResolver::OnComplete,
+ base::Unretained(this), net::ERR_FAILED, base::nullopt));
}
private:
@@ -190,7 +188,7 @@ class PortForwardingHostResolver : public network::ResolveHostClientBase {
delete this;
}
- mojo::Binding<network::mojom::ResolveHostClient> binding_;
+ mojo::Receiver<network::mojom::ResolveHostClient> receiver_{this};
ResolveHostCallback resolve_host_callback_;
DISALLOW_COPY_AND_ASSIGN(PortForwardingHostResolver);
diff --git a/chromium/chrome/browser/devtools/device/tcp_device_provider.cc b/chromium/chrome/browser/devtools/device/tcp_device_provider.cc
index 49f340aae90..394538ff6cc 100644
--- a/chromium/chrome/browser/devtools/device/tcp_device_provider.cc
+++ b/chromium/chrome/browser/devtools/device/tcp_device_provider.cc
@@ -18,7 +18,7 @@
#include "chrome/browser/devtools/device/adb/adb_client_socket.h"
#include "chrome/browser/net/system_network_context_manager.h"
#include "content/public/browser/browser_task_traits.h"
-#include "mojo/public/cpp/bindings/binding.h"
+#include "mojo/public/cpp/bindings/receiver.h"
#include "net/base/completion_repeating_callback.h"
#include "net/base/net_errors.h"
#include "net/log/net_log_source.h"
@@ -41,17 +41,16 @@ static void RunSocketCallback(
class ResolveHostAndOpenSocket final : public network::ResolveHostClientBase {
public:
- ResolveHostAndOpenSocket(const net::HostPortPair& address,
- const AdbClientSocket::SocketCallback& callback,
- network::mojom::HostResolverPtr* host_resolver)
- : callback_(callback), binding_(this) {
- network::mojom::ResolveHostClientPtr client_ptr;
- binding_.Bind(mojo::MakeRequest(&client_ptr));
- binding_.set_connection_error_handler(
+ ResolveHostAndOpenSocket(
+ const net::HostPortPair& address,
+ const AdbClientSocket::SocketCallback& callback,
+ mojo::Remote<network::mojom::HostResolver>* host_resolver)
+ : callback_(callback) {
+ (*host_resolver)
+ ->ResolveHost(address, nullptr, receiver_.BindNewPipeAndPassRemote());
+ receiver_.set_disconnect_handler(
base::BindOnce(&ResolveHostAndOpenSocket::OnComplete,
base::Unretained(this), net::ERR_FAILED, base::nullopt));
-
- (*host_resolver)->ResolveHost(address, nullptr, std::move(client_ptr));
}
private:
@@ -77,7 +76,7 @@ class ResolveHostAndOpenSocket final : public network::ResolveHostClientBase {
}
AdbClientSocket::SocketCallback callback_;
- mojo::Binding<network::mojom::ResolveHostClient> binding_;
+ mojo::Receiver<network::mojom::ResolveHostClient> receiver_{this};
};
} // namespace
@@ -157,16 +156,18 @@ TCPDeviceProvider::~TCPDeviceProvider() {
}
void TCPDeviceProvider::InitializeHostResolver() {
- base::PostTask(FROM_HERE, {content::BrowserThread::UI},
- base::BindOnce(&TCPDeviceProvider::InitializeHostResolverOnUI,
- this, mojo::MakeRequest(&host_resolver_)));
- host_resolver_.set_connection_error_handler(base::BindOnce(
+ host_resolver_.reset();
+ base::PostTask(
+ FROM_HERE, {content::BrowserThread::UI},
+ base::BindOnce(&TCPDeviceProvider::InitializeHostResolverOnUI, this,
+ host_resolver_.BindNewPipeAndPassReceiver()));
+ host_resolver_.set_disconnect_handler(base::BindOnce(
&TCPDeviceProvider::InitializeHostResolver, base::Unretained(this)));
}
void TCPDeviceProvider::InitializeHostResolverOnUI(
- network::mojom::HostResolverRequest request) {
+ mojo::PendingReceiver<network::mojom::HostResolver> receiver) {
g_browser_process->system_network_context_manager()
->GetContext()
- ->CreateHostResolver(base::nullopt, std::move(request));
+ ->CreateHostResolver(base::nullopt, std::move(receiver));
}
diff --git a/chromium/chrome/browser/devtools/device/tcp_device_provider.h b/chromium/chrome/browser/devtools/device/tcp_device_provider.h
index 5f1dae62d0b..17dea4f6d02 100644
--- a/chromium/chrome/browser/devtools/device/tcp_device_provider.h
+++ b/chromium/chrome/browser/devtools/device/tcp_device_provider.h
@@ -10,7 +10,10 @@
#include <set>
#include "chrome/browser/devtools/device/android_device_manager.h"
+#include "mojo/public/cpp/bindings/pending_receiver.h"
+#include "mojo/public/cpp/bindings/remote.h"
#include "net/base/host_port_pair.h"
+#include "services/network/public/mojom/host_resolver.mojom.h"
// Instantiate this class only in a test and/or when the DEBUG_DEVTOOLS
// BUILDFLAG is set.
@@ -40,11 +43,12 @@ class TCPDeviceProvider : public AndroidDeviceManager::DeviceProvider {
~TCPDeviceProvider() override;
void InitializeHostResolver();
- void InitializeHostResolverOnUI(network::mojom::HostResolverRequest request);
+ void InitializeHostResolverOnUI(
+ mojo::PendingReceiver<network::mojom::HostResolver> receiver);
HostPortSet targets_;
base::Closure release_callback_;
- network::mojom::HostResolverPtr host_resolver_;
+ mojo::Remote<network::mojom::HostResolver> host_resolver_;
};
#endif // CHROME_BROWSER_DEVTOOLS_DEVICE_TCP_DEVICE_PROVIDER_H_
diff --git a/chromium/chrome/browser/devtools/devtools_sanity_browsertest.cc b/chromium/chrome/browser/devtools/devtools_sanity_browsertest.cc
index ad76170f21e..c290c153251 100644
--- a/chromium/chrome/browser/devtools/devtools_sanity_browsertest.cc
+++ b/chromium/chrome/browser/devtools/devtools_sanity_browsertest.cc
@@ -99,6 +99,7 @@
#include "net/url_request/url_request_context.h"
#include "net/url_request/url_request_context_getter.h"
#include "services/network/public/cpp/features.h"
+#include "services/network/public/cpp/resource_response.h"
#include "third_party/blink/public/platform/web_input_event.h"
#include "ui/compositor/compositor_switches.h"
#include "ui/gl/gl_switches.h"
@@ -762,13 +763,9 @@ IN_PROC_BROWSER_TEST_F(DevToolsBeforeUnloadTest,
// Tests that BeforeUnload event gets called on devtools that are opened
// on another devtools.
-#if defined(OS_CHROMEOS) || defined(OS_LINUX)
// TODO(https://crbug.com/1000654): Re-enable this test.
-#define MAYBE_TestDevToolsOnDevTools DISABLED_TestDevToolsOnDevTools
-#else
-#define MAYBE_TestDevToolsOnDevTools TestDevToolsOnDevTools
-#endif
-IN_PROC_BROWSER_TEST_F(DevToolsBeforeUnloadTest, MAYBE_TestDevToolsOnDevTools) {
+IN_PROC_BROWSER_TEST_F(DevToolsBeforeUnloadTest,
+ DISABLED_TestDevToolsOnDevTools) {
ASSERT_TRUE(spawned_test_server()->Start());
LoadTestPage(kDebuggerTestPage);
@@ -831,9 +828,16 @@ IN_PROC_BROWSER_TEST_F(DevToolsSanityTest, TestShowScriptsTab) {
// Tests that scripts tab is populated with inspected scripts even if it
// hadn't been shown by the moment inspected paged refreshed.
// @see http://crbug.com/26312
-IN_PROC_BROWSER_TEST_F(
- DevToolsSanityTest,
- TestScriptsTabIsPopulatedOnInspectedPageRefresh) {
+// This test is flaky on windows and linux asan. See https://crbug.com/1013003
+#if defined(OS_WIN) || defined(OS_MACOSX)
+#define MAYBE_TestScriptsTabIsPopulatedOnInspectedPageRefresh \
+ DISABLED_TestScriptsTabIsPopulatedOnInspectedPageRefresh
+#else
+#define MAYBE_TestScriptsTabIsPopulatedOnInspectedPageRefresh \
+ TestScriptsTabIsPopulatedOnInspectedPageRefresh
+#endif
+IN_PROC_BROWSER_TEST_F(DevToolsSanityTest,
+ MAYBE_TestScriptsTabIsPopulatedOnInspectedPageRefresh) {
RunTest("testScriptsTabIsPopulatedOnInspectedPageRefresh",
kDebuggerTestPage);
}
diff --git a/chromium/chrome/browser/devtools/devtools_ui_bindings.cc b/chromium/chrome/browser/devtools/devtools_ui_bindings.cc
index 1acc82d6f38..b43e8b7f7fc 100644
--- a/chromium/chrome/browser/devtools/devtools_ui_bindings.cc
+++ b/chromium/chrome/browser/devtools/devtools_ui_bindings.cc
@@ -77,6 +77,7 @@
#include "net/traffic_annotation/network_traffic_annotation.h"
#include "services/network/public/cpp/simple_url_loader.h"
#include "services/network/public/cpp/simple_url_loader_stream_consumer.h"
+#include "services/network/public/mojom/url_response_head.mojom.h"
#include "third_party/blink/public/mojom/renderer_preferences.mojom.h"
#include "third_party/blink/public/public_buildflags.h"
#include "ui/base/page_transition_types.h"
@@ -199,9 +200,17 @@ InfoBarService* DefaultBindingsDelegate::GetInfoBarService() {
}
std::unique_ptr<base::DictionaryValue> BuildObjectForResponse(
- const net::HttpResponseHeaders* rh) {
+ const net::HttpResponseHeaders* rh,
+ bool success) {
auto response = std::make_unique<base::DictionaryValue>();
- response->SetInteger("statusCode", rh ? rh->response_code() : 200);
+ int responseCode = 200;
+ if (rh) {
+ responseCode = rh->response_code();
+ } else if (!success) {
+ // In case of no headers, assume file:// URL and failed to load
+ responseCode = 404;
+ }
+ response->SetInteger("statusCode", responseCode);
auto headers = std::make_unique<base::DictionaryValue>();
size_t iterator = 0;
@@ -312,7 +321,7 @@ std::string SanitizeFrontendQueryParam(
// Convert boolean flags to true.
if (key == "can_dock" || key == "debugFrontend" || key == "experiments" ||
key == "isSharedWorker" || key == "v8only" || key == "remoteFrontend" ||
- key == "nodeFrontend" || key == "hasOtherClients")
+ key == "nodeFrontend" || key == "hasOtherClients" || key == "uiDevTools")
return "true";
// Pass connection endpoints as is.
@@ -372,28 +381,86 @@ GURL SanitizeFrontendURL(const GURL& url,
return result;
}
+constexpr base::TimeDelta kInitialBackoffDelay =
+ base::TimeDelta::FromMilliseconds(250);
+constexpr base::TimeDelta kMaxBackoffDelay = base::TimeDelta::FromSeconds(10);
+
} // namespace
class DevToolsUIBindings::NetworkResourceLoader
: public network::SimpleURLLoaderStreamConsumer {
public:
- NetworkResourceLoader(int stream_id,
- DevToolsUIBindings* bindings,
- std::unique_ptr<network::SimpleURLLoader> loader,
- network::mojom::URLLoaderFactory* url_loader_factory,
- const DispatchCallback& callback)
+ class URLLoaderFactoryHolder {
+ public:
+ network::mojom::URLLoaderFactory* get() {
+ return ptr_.get() ? ptr_.get() : refptr_.get();
+ }
+ void operator=(std::unique_ptr<network::mojom::URLLoaderFactory>&& ptr) {
+ ptr_ = std::move(ptr);
+ }
+ void operator=(scoped_refptr<network::SharedURLLoaderFactory>&& refptr) {
+ refptr_ = std::move(refptr);
+ }
+
+ private:
+ std::unique_ptr<network::mojom::URLLoaderFactory> ptr_;
+ scoped_refptr<network::SharedURLLoaderFactory> refptr_;
+ };
+
+ static void Create(int stream_id,
+ DevToolsUIBindings* bindings,
+ const network::ResourceRequest& resource_request,
+ const net::NetworkTrafficAnnotationTag& traffic_annotation,
+ URLLoaderFactoryHolder url_loader_factory,
+ const DevToolsUIBindings::DispatchCallback& callback,
+ base::TimeDelta retry_delay = base::TimeDelta()) {
+ auto resource_loader =
+ std::make_unique<DevToolsUIBindings::NetworkResourceLoader>(
+ stream_id, bindings, resource_request, traffic_annotation,
+ std::move(url_loader_factory), callback, retry_delay);
+ bindings->loaders_.insert(std::move(resource_loader));
+ }
+
+ NetworkResourceLoader(
+ int stream_id,
+ DevToolsUIBindings* bindings,
+ const network::ResourceRequest& resource_request,
+ const net::NetworkTrafficAnnotationTag& traffic_annotation,
+ URLLoaderFactoryHolder url_loader_factory,
+ const DispatchCallback& callback,
+ base::TimeDelta delay)
: stream_id_(stream_id),
bindings_(bindings),
- loader_(std::move(loader)),
- callback_(callback) {
+ resource_request_(resource_request),
+ traffic_annotation_(traffic_annotation),
+ loader_(network::SimpleURLLoader::Create(
+ std::make_unique<network::ResourceRequest>(resource_request),
+ traffic_annotation)),
+ url_loader_factory_(std::move(url_loader_factory)),
+ callback_(callback),
+ retry_delay_(delay) {
loader_->SetOnResponseStartedCallback(base::BindOnce(
&NetworkResourceLoader::OnResponseStarted, base::Unretained(this)));
- loader_->DownloadAsStream(url_loader_factory, this);
+ timer_.Start(FROM_HERE, delay,
+ base::BindRepeating(&NetworkResourceLoader::DownloadAsStream,
+ base::Unretained(this)));
}
private:
+ void DownloadAsStream() {
+ loader_->DownloadAsStream(url_loader_factory_.get(), this);
+ }
+
+ base::TimeDelta GetNextExponentialBackoffDelay(const base::TimeDelta& delta) {
+ if (delta.is_zero()) {
+ return kInitialBackoffDelay;
+ } else {
+ return delta * 1.3;
+ }
+ }
+
void OnResponseStarted(const GURL& final_url,
- const network::ResourceResponseHead& response_head) {
+ const network::mojom::URLResponseHead& response_head) {
response_headers_ = response_head.headers;
}
@@ -418,9 +485,21 @@ class DevToolsUIBindings::NetworkResourceLoader
}
void OnComplete(bool success) override {
- auto response = BuildObjectForResponse(response_headers_.get());
- callback_.Run(response.get());
-
+ if (!success && loader_->NetError() == net::ERR_INSUFFICIENT_RESOURCES &&
+ retry_delay_ < kMaxBackoffDelay) {
+ const base::TimeDelta delay =
+ GetNextExponentialBackoffDelay(retry_delay_);
+ LOG(WARNING) << "DevToolsUIBindings::NetworkResourceLoader id = "
+ << stream_id_
+ << " failed with insufficient resources, retrying in "
+ << delay << "." << std::endl;
+ NetworkResourceLoader::Create(
+ stream_id_, bindings_, resource_request_, traffic_annotation_,
+ std::move(url_loader_factory_), callback_, delay);
+ } else {
+ auto response = BuildObjectForResponse(response_headers_.get(), success);
+ callback_.Run(response.get());
+ }
bindings_->loaders_.erase(bindings_->loaders_.find(this));
}
@@ -428,9 +507,14 @@ class DevToolsUIBindings::NetworkResourceLoader
const int stream_id_;
DevToolsUIBindings* const bindings_;
+ const network::ResourceRequest resource_request_;
+ const net::NetworkTrafficAnnotationTag traffic_annotation_;
std::unique_ptr<network::SimpleURLLoader> loader_;
+ URLLoaderFactoryHolder url_loader_factory_;
DispatchCallback callback_;
scoped_refptr<net::HttpResponseHeaders> response_headers_;
+ base::OneShotTimer timer_;
+ base::TimeDelta retry_delay_;
DISALLOW_COPY_AND_ASSIGN(NetworkResourceLoader);
};
@@ -738,22 +822,18 @@ void DevToolsUIBindings::LoadNetworkResource(const DispatchCallback& callback,
}
})");
- auto resource_request = std::make_unique<network::ResourceRequest>();
- resource_request->url = gurl;
+ network::ResourceRequest resource_request;
+ resource_request.url = gurl;
// TODO(caseq): this preserves behavior of URLFetcher-based implementation.
// We really need to pass proper first party origin from the front-end.
- resource_request->site_for_cookies = gurl;
- resource_request->headers.AddHeadersFromString(headers);
+ resource_request.site_for_cookies = gurl;
+ resource_request.headers.AddHeadersFromString(headers);
- std::unique_ptr<network::mojom::URLLoaderFactory> file_url_loader_factory;
- scoped_refptr<network::SharedURLLoaderFactory> network_url_loader_factory;
- std::unique_ptr<network::mojom::URLLoaderFactory> webui_url_loader_factory;
- network::mojom::URLLoaderFactory* url_loader_factory;
+ NetworkResourceLoader::URLLoaderFactoryHolder url_loader_factory;
if (gurl.SchemeIsFile()) {
- file_url_loader_factory = content::CreateFileURLLoaderFactory(
+ url_loader_factory = content::CreateFileURLLoaderFactory(
base::FilePath() /* profile_path */,
nullptr /* shared_cors_origin_access_list */);
- url_loader_factory = file_url_loader_factory.get();
} else if (content::HasWebUIScheme(gurl)) {
content::WebContents* target_tab;
#ifndef NDEBUG
@@ -769,10 +849,9 @@ void DevToolsUIBindings::LoadNetworkResource(const DispatchCallback& callback,
if (allow_web_ui_scheme) {
std::vector<std::string> allowed_webui_hosts;
content::RenderFrameHost* frame_host = web_contents()->GetMainFrame();
- webui_url_loader_factory = content::CreateWebUIURLLoader(
+ url_loader_factory = content::CreateWebUIURLLoader(
frame_host, target_tab->GetURL().scheme(),
std::move(allowed_webui_hosts));
- url_loader_factory = webui_url_loader_factory.get();
} else {
base::DictionaryValue response;
response.SetInteger("statusCode", 403);
@@ -782,17 +861,12 @@ void DevToolsUIBindings::LoadNetworkResource(const DispatchCallback& callback,
} else {
auto* partition = content::BrowserContext::GetStoragePartitionForSite(
web_contents_->GetBrowserContext(), gurl);
- network_url_loader_factory =
- partition->GetURLLoaderFactoryForBrowserProcess();
- url_loader_factory = network_url_loader_factory.get();
+ url_loader_factory = partition->GetURLLoaderFactoryForBrowserProcess();
}
- auto simple_url_loader = network::SimpleURLLoader::Create(
- std::move(resource_request), traffic_annotation);
- auto resource_loader = std::make_unique<NetworkResourceLoader>(
- stream_id, this, std::move(simple_url_loader), url_loader_factory,
- callback);
- loaders_.insert(std::move(resource_loader));
+ NetworkResourceLoader::Create(stream_id, this, resource_request,
+ traffic_annotation,
+ std::move(url_loader_factory), callback);
}
void DevToolsUIBindings::OpenInNewTab(const std::string& url) {
diff --git a/chromium/chrome/browser/devtools/devtools_window.cc b/chromium/chrome/browser/devtools/devtools_window.cc
index 14bc702c89f..f0e249161a7 100644
--- a/chromium/chrome/browser/devtools/devtools_window.cc
+++ b/chromium/chrome/browser/devtools/devtools_window.cc
@@ -5,6 +5,7 @@
#include "chrome/browser/devtools/devtools_window.h"
#include <algorithm>
+#include <set>
#include <utility>
#include "base/base64.h"
@@ -21,7 +22,6 @@
#include "chrome/browser/devtools/devtools_eye_dropper.h"
#include "chrome/browser/file_select_helper.h"
#include "chrome/browser/infobars/infobar_service.h"
-#include "chrome/browser/performance_manager/performance_manager_tab_helper.h"
#include "chrome/browser/profiles/profile.h"
#include "chrome/browser/sessions/session_tab_helper.h"
#include "chrome/browser/task_manager/web_contents_tags.h"
@@ -38,6 +38,7 @@
#include "chrome/common/pref_names.h"
#include "chrome/common/url_constants.h"
#include "components/app_modal/javascript_dialog_manager.h"
+#include "components/performance_manager/performance_manager_tab_helper.h"
#include "components/pref_registry/pref_registry_syncable.h"
#include "components/prefs/scoped_user_pref_update.h"
#include "components/sync_preferences/pref_service_syncable.h"
@@ -170,8 +171,8 @@ content::WebContents* DevToolsToolboxDelegate::OpenURLFromTab(
DCHECK(source == web_contents());
if (!params.url.SchemeIs(content::kChromeDevToolsScheme))
return NULL;
- content::NavigationController::LoadURLParams load_url_params(params.url);
- source->GetController().LoadURLWithParams(load_url_params);
+ source->GetController().LoadURLWithParams(
+ content::NavigationController::LoadURLParams(params));
return source;
}
@@ -218,7 +219,7 @@ GURL DecorateFrontendURL(const GURL& base_url) {
std::string url_string(
frontend_url +
((frontend_url.find("?") == std::string::npos) ? "?" : "&") +
- "dockSide=undocked"); // TODO(dgozman): remove this support in M38.
+ "dockSide=undocked"); // TODO(dgozman): remove this support in M38.
base::CommandLine* command_line = base::CommandLine::ForCurrentProcess();
if (command_line->HasSwitch(switches::kEnableDevToolsExperiments))
url_string += "&experiments=true";
@@ -770,6 +771,16 @@ DevToolsWindow::MaybeCreateNavigationThrottle(
return std::make_unique<Throttle>(handle, window);
}
+void DevToolsWindow::UpdateInspectedWebContents(
+ content::WebContents* new_web_contents) {
+ inspected_contents_observer_ =
+ std::make_unique<ObserverWithAccessor>(new_web_contents);
+ bindings_->AttachTo(
+ content::DevToolsAgentHost::GetOrCreateFor(new_web_contents));
+ bindings_->CallClientFunction("DevToolsAPI.reattachMainTarget", nullptr,
+ nullptr, nullptr);
+}
+
void DevToolsWindow::ScheduleShow(const DevToolsToggleAction& action) {
if (life_stage_ == kLoadCompleted) {
Show(action);
@@ -800,7 +811,7 @@ void DevToolsWindow::Show(const DevToolsToggleAction& action) {
&inspected_browser,
&inspected_tab_index);
DCHECK(inspected_browser);
- DCHECK(inspected_tab_index != -1);
+ DCHECK_NE(-1, inspected_tab_index);
RegisterModalDialogManager(inspected_browser);
@@ -821,7 +832,7 @@ void DevToolsWindow::Show(const DevToolsToggleAction& action) {
main_web_contents_->SetInitialFocus();
PrefsTabHelper::CreateForWebContents(main_web_contents_);
- main_web_contents_->GetRenderViewHost()->SyncRendererPrefs();
+ main_web_contents_->SyncRendererPrefs();
DoAction(action);
return;
@@ -1545,7 +1556,7 @@ void DevToolsWindow::CreateDevToolsBrowser() {
browser_->tab_strip_model()->AddWebContents(
std::move(owned_main_web_contents_), -1,
ui::PAGE_TRANSITION_AUTO_TOPLEVEL, TabStripModel::ADD_ACTIVE);
- main_web_contents_->GetRenderViewHost()->SyncRendererPrefs();
+ main_web_contents_->SyncRendererPrefs();
}
BrowserWindow* DevToolsWindow::GetInspectedBrowserWindow() {
diff --git a/chromium/chrome/browser/devtools/devtools_window.h b/chromium/chrome/browser/devtools/devtools_window.h
index b47e506fff9..0a14822e2c4 100644
--- a/chromium/chrome/browser/devtools/devtools_window.h
+++ b/chromium/chrome/browser/devtools/devtools_window.h
@@ -5,6 +5,9 @@
#ifndef CHROME_BROWSER_DEVTOOLS_DEVTOOLS_WINDOW_H_
#define CHROME_BROWSER_DEVTOOLS_DEVTOOLS_WINDOW_H_
+#include <memory>
+#include <string>
+
#include "base/macros.h"
#include "chrome/browser/devtools/devtools_contents_resizing_strategy.h"
#include "chrome/browser/devtools/devtools_toggle_action.h"
@@ -122,6 +125,11 @@ class DevToolsWindow : public DevToolsUIBindings::Delegate,
static std::unique_ptr<content::NavigationThrottle>
MaybeCreateNavigationThrottle(content::NavigationHandle* handle);
+ // Updates the WebContents inspected by the DevToolsWindow by reattaching
+ // the binding to |new_web_contents|. Called when swapping an outer
+ // WebContents with its inner WebContents.
+ void UpdateInspectedWebContents(content::WebContents* new_web_contents);
+
// Sets closure to be called after load is done. If already loaded, calls
// closure immediately.
void SetLoadCompletedCallback(const base::Closure& closure);
diff --git a/chromium/chrome/browser/devtools/frontend/devtools_discovery_page.html b/chromium/chrome/browser/devtools/frontend/devtools_discovery_page.html
index 88291aa4d80..52880365af5 100644
--- a/chromium/chrome/browser/devtools/frontend/devtools_discovery_page.html
+++ b/chromium/chrome/browser/devtools/frontend/devtools_discovery_page.html
@@ -1,5 +1,5 @@
-<html>
-<head>
+<!doctype html>
+<html lang="en">
<title>Inspectable pages</title>
<meta name="referrer" content="no-referrer">
<style>
@@ -102,6 +102,19 @@ function onReady() {
}
}
+function onBlur(event) {
+ const selection = window.getSelection();
+ selection.removeAllRanges();
+ event.stopPropagation();
+ event.preventDefault();
+}
+
+function onFocus(selectElement, event) {
+ selectNodeText(selectElement, event);
+ event.stopPropagation();
+ event.preventDefault();
+}
+
function customFrontendURL(url) {
if (!url || !window.location.hash)
return null;
@@ -164,6 +177,9 @@ function appendItem(item_object) {
var urlValue = document.createElement('div');
urlValue.classList.add("custom-url-value");
urlValue.textContent = customURL;
+ urlValue.tabIndex = 0;
+ urlValue.addEventListener('blur', onBlur);
+ urlValue.addEventListener('focus', event => onFocus(urlValue, event));
urlContainer.appendChild(urlValue);
description.appendChild(urlContainer);
item_element.addEventListener('click', selectNodeText.bind(null, urlValue));
@@ -189,9 +205,11 @@ function selectNodeText(selectElement, event)
</script>
</head>
<body onload='onLoad()'>
- <div id='caption'>Inspectable pages</div>
- <hr>
- <div id='items'>
+ <div role='main'>
+ <div id='caption' role='heading' aria-level='1'>Inspectable pages</div>
+ <hr>
+ <div id='items'>
+ </div>
</div>
</body>
</html>
diff --git a/chromium/chrome/browser/devtools/inspector_protocol_config.json b/chromium/chrome/browser/devtools/inspector_protocol_config.json
index 53897298398..431eaa6b34a 100644
--- a/chromium/chrome/browser/devtools/inspector_protocol_config.json
+++ b/chromium/chrome/browser/devtools/inspector_protocol_config.json
@@ -28,6 +28,11 @@
},
{
"domain": "WindowManager"
+ },
+ {
+ "domain": "Security",
+ "include": [ "enable", "disable" ],
+ "include_events": [ "visibleSecurityStateChanged" ]
}
]
},
diff --git a/chromium/chrome/browser/devtools/protocol/devtools_protocol_browsertest.cc b/chromium/chrome/browser/devtools/protocol/devtools_protocol_browsertest.cc
new file mode 100644
index 00000000000..cebdc256278
--- /dev/null
+++ b/chromium/chrome/browser/devtools/protocol/devtools_protocol_browsertest.cc
@@ -0,0 +1,336 @@
+// 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 <memory>
+#include <string>
+
+#include "base/base64.h"
+#include "base/callback.h"
+#include "base/json/json_reader.h"
+#include "base/json/json_writer.h"
+#include "base/values.h"
+#include "chrome/browser/ui/browser.h"
+#include "chrome/test/base/in_process_browser_test.h"
+#include "chrome/test/base/ui_test_utils.h"
+#include "content/public/browser/devtools_agent_host.h"
+#include "content/public/browser/navigation_entry.h"
+#include "content/public/browser/ssl_status.h"
+#include "content/public/browser/web_contents.h"
+#include "content/public/test/browser_test_utils.h"
+#include "net/dns/mock_host_resolver.h"
+#include "net/ssl/ssl_cipher_suite_names.h"
+#include "net/ssl/ssl_connection_status_flags.h"
+#include "third_party/boringssl/src/include/openssl/ssl.h"
+
+namespace {
+
+const char kIdParam[] = "id";
+const char kMethodParam[] = "method";
+
+} // namespace
+
+class DevToolsProtocolTest : public InProcessBrowserTest,
+ public content::DevToolsAgentHostClient {
+ public:
+ DevToolsProtocolTest() : last_sent_id_(0) {}
+
+ protected:
+ typedef base::RepeatingCallback<bool(const base::Value&)> NotificationMatcher;
+
+ // InProcessBrowserTest interface
+ void TearDownOnMainThread() override { Detach(); }
+
+ // DevToolsAgentHostClient interface
+ void DispatchProtocolMessage(content::DevToolsAgentHost* agent_host,
+ const std::string& message) override {
+ auto parsed_message = base::JSONReader::Read(message);
+ auto id = parsed_message->FindIntPath("id");
+ if (id) {
+ // TODO: implement handling of results from method calls (when needed).
+ } else {
+ std::string* notification = parsed_message->FindStringPath("method");
+ EXPECT_TRUE(notification);
+ notifications_.push_back(*notification);
+ base::Value* params = parsed_message->FindPath("params");
+ notification_params_.push_back(params ? params->Clone() : base::Value());
+ if (waiting_for_notification_ == *notification &&
+ (waiting_for_notification_matcher_.is_null() ||
+ waiting_for_notification_matcher_.Run(
+ notification_params_.back()))) {
+ waiting_for_notification_ = std::string();
+ waiting_for_notification_matcher_ = NotificationMatcher();
+ waiting_for_notification_params_ = notification_params_.back().Clone();
+ std::move(run_loop_quit_closure_).Run();
+ }
+ }
+ }
+
+ void SendCommand(const std::string& method) {
+ base::Value command(base::Value::Type::DICTIONARY);
+ command.SetKey(kIdParam, base::Value(++last_sent_id_));
+ command.SetKey(kMethodParam, base::Value(method));
+ std::string json_command;
+ base::JSONWriter::Write(command, &json_command);
+ agent_host_->DispatchProtocolMessage(this, json_command);
+ }
+
+ void RunLoopUpdatingQuitClosure() {
+ base::RunLoop run_loop;
+ CHECK(!run_loop_quit_closure_);
+ run_loop_quit_closure_ = run_loop.QuitClosure();
+ run_loop.Run();
+ }
+
+ void Attach() {
+ agent_host_ = content::DevToolsAgentHost::GetOrCreateFor(web_contents());
+ agent_host_->AttachClient(this);
+ }
+
+ void Detach() {
+ if (agent_host_) {
+ agent_host_->DetachClient(this);
+ agent_host_ = nullptr;
+ }
+ }
+
+ content::WebContents* web_contents() {
+ return browser()->tab_strip_model()->GetWebContentsAt(0);
+ }
+
+ base::Value WaitForNotification(const std::string& notification) {
+ auto always_match = base::Bind([](const base::Value&) { return true; });
+ return WaitForMatchingNotification(notification, always_match);
+ }
+
+ base::Value WaitForMatchingNotification(const std::string& notification,
+ const NotificationMatcher& matcher) {
+ for (size_t i = 0; i < notifications_.size(); ++i) {
+ if (notifications_[i] == notification &&
+ matcher.Run(notification_params_[i])) {
+ base::Value result = std::move(notification_params_[i]);
+ notifications_.erase(notifications_.begin() + i);
+ notification_params_.erase(notification_params_.begin() + i);
+ return result;
+ }
+ }
+ waiting_for_notification_ = notification;
+ waiting_for_notification_matcher_ = matcher;
+ RunLoopUpdatingQuitClosure();
+ return std::move(waiting_for_notification_params_);
+ }
+
+ private:
+ // DevToolsAgentHostClient interface
+ void AgentHostClosed(content::DevToolsAgentHost* agent_host) override {}
+
+ scoped_refptr<content::DevToolsAgentHost> agent_host_;
+ int last_sent_id_;
+ base::OnceClosure run_loop_quit_closure_;
+ std::vector<std::string> notifications_;
+ std::vector<base::Value> notification_params_;
+ std::string waiting_for_notification_;
+ NotificationMatcher waiting_for_notification_matcher_;
+ base::Value waiting_for_notification_params_;
+};
+
+IN_PROC_BROWSER_TEST_F(DevToolsProtocolTest,
+ VisibleSecurityStateChangedNeutralState) {
+ ui_test_utils::NavigateToURL(browser(), GURL("about:blank"));
+ content::WaitForLoadStop(web_contents());
+
+ Attach();
+ SendCommand("Security.enable");
+ base::Value params =
+ WaitForNotification("Security.visibleSecurityStateChanged");
+
+ std::string* security_state =
+ params.FindStringPath("visibleSecurityState.securityState");
+ ASSERT_TRUE(security_state);
+ ASSERT_EQ(std::string("neutral"), *security_state);
+ ASSERT_FALSE(
+ params.FindPath("visibleSecurityState.certificateSecurityState"));
+ const base::Value* security_state_issue_ids =
+ params.FindListPath("visibleSecurityState.securityStateIssueIds");
+ ASSERT_TRUE(std::find(security_state_issue_ids->GetList().begin(),
+ security_state_issue_ids->GetList().end(),
+ base::Value("scheme-is-not-cryptographic")) !=
+ security_state_issue_ids->GetList().end());
+}
+
+IN_PROC_BROWSER_TEST_F(DevToolsProtocolTest, VisibleSecurityStateSecureState) {
+ net::EmbeddedTestServer https_server(net::EmbeddedTestServer::TYPE_HTTPS);
+ https_server.ServeFilesFromSourceDirectory(GetChromeTestDataDir());
+ ASSERT_TRUE(https_server.Start());
+
+ ui_test_utils::NavigateToURLBlockUntilNavigationsComplete(
+ browser(), https_server.GetURL("/title1.html"), 1);
+ content::NavigationEntry* entry =
+ web_contents()->GetController().GetLastCommittedEntry();
+ ASSERT_TRUE(entry);
+
+ // Extract SSL status data from the navigation entry.
+ scoped_refptr<net::X509Certificate> page_cert = entry->GetSSL().certificate;
+ ASSERT_TRUE(page_cert);
+
+ int ssl_version =
+ net::SSLConnectionStatusToVersion(entry->GetSSL().connection_status);
+ const char* page_protocol;
+ net::SSLVersionToString(&page_protocol, ssl_version);
+
+ const char* page_key_exchange_str;
+ const char* page_cipher;
+ const char* page_mac;
+ bool is_aead;
+ bool is_tls13;
+ uint16_t page_cipher_suite =
+ net::SSLConnectionStatusToCipherSuite(entry->GetSSL().connection_status);
+ net::SSLCipherSuiteToStrings(&page_key_exchange_str, &page_cipher, &page_mac,
+ &is_aead, &is_tls13, page_cipher_suite);
+ std::string page_key_exchange;
+ if (page_key_exchange_str)
+ page_key_exchange = page_key_exchange_str;
+
+ const char* page_key_exchange_group =
+ SSL_get_curve_name(entry->GetSSL().key_exchange_group);
+
+ std::string page_subject_name;
+ std::string page_issuer_name;
+ double page_valid_from = 0.0;
+ double page_valid_to = 0.0;
+ if (entry->GetSSL().certificate) {
+ page_subject_name = entry->GetSSL().certificate->subject().common_name;
+ page_issuer_name = entry->GetSSL().certificate->issuer().common_name;
+ page_valid_from = entry->GetSSL().certificate->valid_start().ToDoubleT();
+ page_valid_to = entry->GetSSL().certificate->valid_expiry().ToDoubleT();
+ }
+
+ bool page_certificate_has_weak_signature =
+ (entry->GetSSL().cert_status & net::CERT_STATUS_WEAK_SIGNATURE_ALGORITHM);
+
+ int status = net::ObsoleteSSLStatus(entry->GetSSL().connection_status,
+ entry->GetSSL().peer_signature_algorithm);
+ bool page_modern_ssl = status == net::OBSOLETE_SSL_NONE;
+ bool page_obsolete_ssl_protocol = status & net::OBSOLETE_SSL_MASK_PROTOCOL;
+ bool page_obsolete_ssl_key_exchange =
+ status & net::OBSOLETE_SSL_MASK_KEY_EXCHANGE;
+ bool page_obsolete_ssl_cipher = status & net::OBSOLETE_SSL_MASK_CIPHER;
+ bool page_obsolete_ssl_signature = status & net::OBSOLETE_SSL_MASK_SIGNATURE;
+
+ Attach();
+ SendCommand("Security.enable");
+ auto has_certificate = [](const base::Value& params) {
+ return params.FindListPath(
+ "visibleSecurityState.certificateSecurityState.certificate") !=
+ nullptr;
+ };
+ base::Value params = WaitForMatchingNotification(
+ "Security.visibleSecurityStateChanged", base::Bind(has_certificate));
+
+ // Verify that the visibleSecurityState payload matches the SSL status data.
+ std::string* security_state =
+ params.FindStringPath("visibleSecurityState.securityState");
+ ASSERT_TRUE(security_state);
+ ASSERT_EQ(std::string("secure"), *security_state);
+
+ base::Value* certificate_security_state =
+ params.FindPath("visibleSecurityState.certificateSecurityState");
+ ASSERT_TRUE(certificate_security_state);
+
+ std::string* protocol =
+ certificate_security_state->FindStringPath("protocol");
+ ASSERT_TRUE(protocol);
+ ASSERT_EQ(*protocol, page_protocol);
+
+ std::string* key_exchange =
+ certificate_security_state->FindStringPath("keyExchange");
+ ASSERT_TRUE(key_exchange);
+ ASSERT_EQ(*key_exchange, page_key_exchange);
+
+ std::string* key_exchange_group =
+ certificate_security_state->FindStringPath("keyExchangeGroup");
+ if (key_exchange_group) {
+ ASSERT_EQ(*key_exchange_group, page_key_exchange_group);
+ }
+
+ std::string* mac = certificate_security_state->FindStringPath("mac");
+ if (mac) {
+ ASSERT_EQ(*mac, page_mac);
+ }
+
+ std::string* cipher = certificate_security_state->FindStringPath("cipher");
+ ASSERT_TRUE(cipher);
+ ASSERT_EQ(*cipher, page_cipher);
+
+ std::string* subject_name =
+ certificate_security_state->FindStringPath("subjectName");
+ ASSERT_TRUE(subject_name);
+ ASSERT_EQ(*subject_name, page_subject_name);
+
+ std::string* issuer = certificate_security_state->FindStringPath("issuer");
+ ASSERT_TRUE(issuer);
+ ASSERT_EQ(*issuer, page_issuer_name);
+
+ auto valid_from = certificate_security_state->FindDoublePath("validFrom");
+ ASSERT_TRUE(valid_from);
+ ASSERT_EQ(*valid_from, page_valid_from);
+
+ auto valid_to = certificate_security_state->FindDoublePath("validTo");
+ ASSERT_TRUE(valid_to);
+ ASSERT_EQ(*valid_to, page_valid_to);
+
+ auto certificate_has_weak_signature =
+ certificate_security_state->FindBoolPath("certifcateHasWeakSignature");
+ ASSERT_TRUE(certificate_has_weak_signature);
+ ASSERT_EQ(*certificate_has_weak_signature,
+ page_certificate_has_weak_signature);
+
+ auto modern_ssl = certificate_security_state->FindBoolPath("modernSSL");
+ ASSERT_TRUE(modern_ssl);
+ ASSERT_EQ(*modern_ssl, page_modern_ssl);
+
+ auto obsolete_ssl_protocol =
+ certificate_security_state->FindBoolPath("obsoleteSslProtocol");
+ ASSERT_TRUE(obsolete_ssl_protocol);
+ ASSERT_EQ(*obsolete_ssl_protocol, page_obsolete_ssl_protocol);
+
+ auto obsolete_ssl_key_exchange =
+ certificate_security_state->FindBoolPath("obsoleteSslKeyExchange");
+ ASSERT_TRUE(obsolete_ssl_key_exchange);
+ ASSERT_EQ(*obsolete_ssl_key_exchange, page_obsolete_ssl_key_exchange);
+
+ auto obsolete_ssl_cipher =
+ certificate_security_state->FindBoolPath("obsoleteSslCipher");
+ ASSERT_TRUE(obsolete_ssl_cipher);
+ ASSERT_EQ(*obsolete_ssl_cipher, page_obsolete_ssl_cipher);
+
+ auto obsolete_ssl_signature =
+ certificate_security_state->FindBoolPath("obsoleteSslSignature");
+ ASSERT_TRUE(obsolete_ssl_signature);
+ ASSERT_EQ(*obsolete_ssl_signature, page_obsolete_ssl_signature);
+
+ const base::Value* certificate_value =
+ certificate_security_state->FindListPath("certificate");
+ std::vector<std::string> der_certs;
+ for (const auto& cert : certificate_value->GetList()) {
+ std::string decoded;
+ ASSERT_TRUE(base::Base64Decode(cert.GetString(), &decoded));
+ der_certs.push_back(decoded);
+ }
+ std::vector<base::StringPiece> cert_string_piece;
+ for (const auto& str : der_certs) {
+ cert_string_piece.push_back(str);
+ }
+
+ // Check that the certificateSecurityState.certificate matches.
+ net::SHA256HashValue page_cert_chain_fingerprint =
+ page_cert->CalculateChainFingerprint256();
+ scoped_refptr<net::X509Certificate> certificate =
+ net::X509Certificate::CreateFromDERCertChain(cert_string_piece);
+ ASSERT_TRUE(certificate);
+ EXPECT_EQ(page_cert_chain_fingerprint,
+ certificate->CalculateChainFingerprint256());
+ const base::Value* security_state_issue_ids =
+ params.FindListPath("visibleSecurityState.securityStateIssueIds");
+ EXPECT_EQ(security_state_issue_ids->GetList().size(), 0u);
+}
diff --git a/chromium/chrome/browser/devtools/protocol/security_handler.cc b/chromium/chrome/browser/devtools/protocol/security_handler.cc
new file mode 100644
index 00000000000..a9db9463a58
--- /dev/null
+++ b/chromium/chrome/browser/devtools/protocol/security_handler.cc
@@ -0,0 +1,246 @@
+// 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/devtools/protocol/security_handler.h"
+
+#include <string>
+#include <vector>
+
+#include "base/base64.h"
+#include "chrome/browser/ssl/security_state_tab_helper.h"
+#include "components/security_state/content/content_utils.h"
+#include "content/public/browser/web_contents.h"
+#include "content/public/common/origin_util.h"
+#include "net/cert/x509_certificate.h"
+#include "net/cert/x509_util.h"
+#include "net/ssl/ssl_cipher_suite_names.h"
+#include "net/ssl/ssl_connection_status_flags.h"
+#include "third_party/boringssl/src/include/openssl/ssl.h"
+
+namespace {
+
+const char kInsecureOriginSecurityStateIssueId[] = "insecure-origin";
+const char kSchemeIsNotCryptographicSecurityStateIssueId[] =
+ "scheme-is-not-cryptographic";
+const char kMalicousContentSecurityStateIssueId[] = "malicious-content";
+const char kDisplayedMixedContentSecurityStateIssueId[] =
+ "displayed-mixed-content";
+const char kContainedMixedFormSecurityStateIssueId[] = "contained-mixed-form";
+const char kRanMixedContentSecurityStateIssueId[] = "ran-mixed-content";
+const char kDisplayedContentWithCertErrorsSecurityStateIssueId[] =
+ "displayed-content-with-cert-errors";
+const char kRanContentWithCertErrorSecurityStateIssueId[] =
+ "ran-content-with-cert-error";
+const char kPkpBypassedSecurityStateIssueId[] = "pkp-bypassed";
+const char kIsErrorPageSecurityStateIssueId[] = "is-error-page";
+const char kInsecureInputEventsSecurityStateIssueId[] = "insecure-input-events";
+
+std::string SecurityLevelToProtocolSecurityState(
+ security_state::SecurityLevel security_level) {
+ switch (security_level) {
+ case security_state::NONE:
+ case security_state::WARNING:
+ return protocol::Security::SecurityStateEnum::Neutral;
+ case security_state::SECURE_WITH_POLICY_INSTALLED_CERT:
+ case security_state::EV_SECURE:
+ case security_state::SECURE:
+ return protocol::Security::SecurityStateEnum::Secure;
+ case security_state::DANGEROUS:
+ return protocol::Security::SecurityStateEnum::Insecure;
+ case security_state::SECURITY_LEVEL_COUNT:
+ NOTREACHED();
+ return protocol::Security::SecurityStateEnum::Neutral;
+ }
+
+ NOTREACHED();
+ return protocol::Security::SecurityStateEnum::Neutral;
+}
+
+std::unique_ptr<protocol::Security::CertificateSecurityState>
+CreateCertificateSecurityState(
+ const security_state::VisibleSecurityState& state) {
+ auto certificate = std::make_unique<protocol::Array<protocol::String>>();
+ if (state.certificate) {
+ certificate->emplace_back();
+ base::Base64Encode(net::x509_util::CryptoBufferAsStringPiece(
+ state.certificate->cert_buffer()),
+ &certificate->back());
+ for (const auto& cert : state.certificate->intermediate_buffers()) {
+ certificate->emplace_back();
+ base::Base64Encode(net::x509_util::CryptoBufferAsStringPiece(cert.get()),
+ &certificate->back());
+ }
+ }
+
+ int ssl_version = net::SSLConnectionStatusToVersion(state.connection_status);
+ const char* protocol;
+ net::SSLVersionToString(&protocol, ssl_version);
+
+ const char* key_exchange_str;
+ const char* cipher;
+ const char* mac;
+ bool is_aead;
+ bool is_tls13;
+ uint16_t cipher_suite =
+ net::SSLConnectionStatusToCipherSuite(state.connection_status);
+ net::SSLCipherSuiteToStrings(&key_exchange_str, &cipher, &mac, &is_aead,
+ &is_tls13, cipher_suite);
+ std::string key_exchange;
+ if (key_exchange_str)
+ key_exchange = key_exchange_str;
+
+ const char* key_exchange_group = SSL_get_curve_name(state.key_exchange_group);
+
+ std::string subject_name;
+ std::string issuer_name;
+ double valid_from = 0.0;
+ double valid_to = 0.0;
+ if (state.certificate) {
+ subject_name = state.certificate->subject().common_name;
+ issuer_name = state.certificate->issuer().common_name;
+ valid_from = state.certificate->valid_start().ToDoubleT();
+ valid_to = state.certificate->valid_expiry().ToDoubleT();
+ }
+
+ bool certificate_has_weak_signature =
+ (state.cert_status & net::CERT_STATUS_WEAK_SIGNATURE_ALGORITHM);
+
+ int status = net::ObsoleteSSLStatus(state.connection_status,
+ state.peer_signature_algorithm);
+ bool modern_ssl = status == net::OBSOLETE_SSL_NONE;
+ bool obsolete_ssl_protocol = status & net::OBSOLETE_SSL_MASK_PROTOCOL;
+ bool obsolete_ssl_key_exchange = status & net::OBSOLETE_SSL_MASK_KEY_EXCHANGE;
+ bool obsolete_ssl_cipher = status & net::OBSOLETE_SSL_MASK_CIPHER;
+ bool obsolete_ssl_signature = status & net::OBSOLETE_SSL_MASK_SIGNATURE;
+
+ auto certificate_security_state =
+ protocol::Security::CertificateSecurityState::Create()
+ .SetProtocol(protocol)
+ .SetKeyExchange(key_exchange)
+ .SetCipher(cipher)
+ .SetCertificate(std::move(certificate))
+ .SetSubjectName(subject_name)
+ .SetIssuer(issuer_name)
+ .SetValidFrom(valid_from)
+ .SetValidTo(valid_to)
+ .SetCertifcateHasWeakSignature(certificate_has_weak_signature)
+ .SetModernSSL(modern_ssl)
+ .SetObsoleteSslProtocol(obsolete_ssl_protocol)
+ .SetObsoleteSslKeyExchange(obsolete_ssl_key_exchange)
+ .SetObsoleteSslCipher(obsolete_ssl_cipher)
+ .SetObsoleteSslSignature(obsolete_ssl_signature)
+ .Build();
+
+ if (key_exchange_group)
+ certificate_security_state->SetKeyExchangeGroup(key_exchange_group);
+ if (mac)
+ certificate_security_state->SetMac(mac);
+
+ return certificate_security_state;
+}
+
+std::unique_ptr<protocol::Security::VisibleSecurityState>
+CreateVisibleSecurityState(const security_state::VisibleSecurityState& state,
+ content::WebContents* web_contents) {
+ SecurityStateTabHelper* helper =
+ SecurityStateTabHelper::FromWebContents(web_contents);
+ DCHECK(helper);
+ std::string security_state =
+ SecurityLevelToProtocolSecurityState(helper->GetSecurityLevel());
+
+ bool scheme_is_cryptographic =
+ security_state::IsSchemeCryptographic(state.url);
+ bool malicious_content = state.malicious_content_status !=
+ security_state::MALICIOUS_CONTENT_STATUS_NONE;
+ bool insecure_input_events =
+ state.insecure_input_events.insecure_field_edited;
+
+ bool secure_origin = scheme_is_cryptographic;
+ if (!scheme_is_cryptographic)
+ secure_origin = content::IsOriginSecure(state.url);
+
+ std::vector<std::string> security_state_issue_ids;
+ if (!secure_origin)
+ security_state_issue_ids.push_back(kInsecureOriginSecurityStateIssueId);
+ if (!scheme_is_cryptographic)
+ security_state_issue_ids.push_back(
+ kSchemeIsNotCryptographicSecurityStateIssueId);
+ if (malicious_content)
+ security_state_issue_ids.push_back(kMalicousContentSecurityStateIssueId);
+ if (state.displayed_mixed_content)
+ security_state_issue_ids.push_back(
+ kDisplayedMixedContentSecurityStateIssueId);
+ if (state.contained_mixed_form)
+ security_state_issue_ids.push_back(kContainedMixedFormSecurityStateIssueId);
+ if (state.ran_mixed_content)
+ security_state_issue_ids.push_back(kRanMixedContentSecurityStateIssueId);
+ if (state.displayed_content_with_cert_errors)
+ security_state_issue_ids.push_back(
+ kDisplayedContentWithCertErrorsSecurityStateIssueId);
+ if (state.ran_content_with_cert_errors)
+ security_state_issue_ids.push_back(
+ kRanContentWithCertErrorSecurityStateIssueId);
+ if (state.pkp_bypassed)
+ security_state_issue_ids.push_back(kPkpBypassedSecurityStateIssueId);
+ if (state.is_error_page)
+ security_state_issue_ids.push_back(kIsErrorPageSecurityStateIssueId);
+ if (insecure_input_events)
+ security_state_issue_ids.push_back(
+ kInsecureInputEventsSecurityStateIssueId);
+
+ auto visible_security_state =
+ protocol::Security::VisibleSecurityState::Create()
+ .SetSecurityState(security_state)
+ .SetSecurityStateIssueIds(
+ std::make_unique<protocol::Array<std::string>>(
+ security_state_issue_ids))
+ .Build();
+
+ if (state.connection_status != 0) {
+ auto certificate_security_state = CreateCertificateSecurityState(state);
+ visible_security_state->SetCertificateSecurityState(
+ std::move(certificate_security_state));
+ }
+ return visible_security_state;
+}
+
+} // namespace
+
+SecurityHandler::SecurityHandler(content::WebContents* web_contents,
+ protocol::UberDispatcher* dispatcher)
+ : content::WebContentsObserver(web_contents) {
+ DCHECK(web_contents);
+ frontend_ =
+ std::make_unique<protocol::Security::Frontend>(dispatcher->channel());
+ protocol::Security::Dispatcher::wire(dispatcher, this);
+}
+
+SecurityHandler::~SecurityHandler() {}
+
+protocol::Response SecurityHandler::Enable() {
+ if (enabled_)
+ return protocol::Response::FallThrough();
+ enabled_ = true;
+ DidChangeVisibleSecurityState();
+ // Do not mark the command as handled. Let it fall through instead, so that
+ // the handler in content gets a chance to process the command.
+ return protocol::Response::FallThrough();
+}
+
+protocol::Response SecurityHandler::Disable() {
+ enabled_ = false;
+ // Do not mark the command as handled. Let it fall through instead, so that
+ // the handler in content gets a chance to process the command.
+ return protocol::Response::FallThrough();
+}
+
+void SecurityHandler::DidChangeVisibleSecurityState() {
+ if (!enabled_)
+ return;
+
+ auto state = security_state::GetVisibleSecurityState(web_contents());
+ auto visible_security_state =
+ CreateVisibleSecurityState(*state.get(), web_contents());
+ frontend_->VisibleSecurityStateChanged(std::move(visible_security_state));
+}
diff --git a/chromium/chrome/browser/devtools/protocol/security_handler.h b/chromium/chrome/browser/devtools/protocol/security_handler.h
new file mode 100644
index 00000000000..e4f3c880dac
--- /dev/null
+++ b/chromium/chrome/browser/devtools/protocol/security_handler.h
@@ -0,0 +1,37 @@
+// 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.
+
+#ifndef CHROME_BROWSER_DEVTOOLS_PROTOCOL_SECURITY_HANDLER_H_
+#define CHROME_BROWSER_DEVTOOLS_PROTOCOL_SECURITY_HANDLER_H_
+
+#include "chrome/browser/devtools/protocol/forward.h"
+#include "chrome/browser/devtools/protocol/security.h"
+#include "content/public/browser/web_contents_observer.h"
+
+namespace content {
+class WebContents;
+} // namespace content
+
+class SecurityHandler : public protocol::Security::Backend,
+ public content::WebContentsObserver {
+ public:
+ SecurityHandler(content::WebContents* web_contents,
+ protocol::UberDispatcher* dispatcher);
+ ~SecurityHandler() override;
+
+ // Security::Backend:
+ protocol::Response Enable() override;
+ protocol::Response Disable() override;
+
+ private:
+ // WebContentsObserver overrides
+ void DidChangeVisibleSecurityState() override;
+
+ bool enabled_ = false;
+ std::unique_ptr<protocol::Security::Frontend> frontend_;
+
+ DISALLOW_COPY_AND_ASSIGN(SecurityHandler);
+};
+
+#endif // CHROME_BROWSER_DEVTOOLS_PROTOCOL_SECURITY_HANDLER_H_
diff --git a/chromium/chrome/browser/devtools/serialize_host_descriptions.cc b/chromium/chrome/browser/devtools/serialize_host_descriptions.cc
index d1bdc912536..054acd9be6b 100644
--- a/chromium/chrome/browser/devtools/serialize_host_descriptions.cc
+++ b/chromium/chrome/browser/devtools/serialize_host_descriptions.cc
@@ -27,8 +27,7 @@ base::DictionaryValue Serialize(
auto child_it = children.find(root);
if (child_it != children.end()) {
for (base::DictionaryValue* child : child_it->second) {
- children_list->base::Value::GetList().push_back(
- Serialize(child_key, child, children));
+ children_list->base::Value::Append(Serialize(child_key, child, children));
}
}
@@ -98,8 +97,7 @@ base::ListValue SerializeHostDescriptions(
base::ListValue list_value;
for (auto* root : roots) {
- list_value.base::Value::GetList().push_back(
- Serialize(child_key, root, children));
+ list_value.base::Value::Append(Serialize(child_key, root, children));
}
return list_value;
}