blob: 2ff20b9f8ba5ad3d21992b82d28160455b46617a [file] [log] [blame]
// Copyright 2014 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "content/web_test/browser/web_test_devtools_bindings.h"
#include "base/memory/raw_ptr.h"
#include <memory>
#include "base/command_line.h"
#include "base/functional/callback_helpers.h"
#include "base/path_service.h"
#include "base/strings/string_util.h"
#include "base/strings/utf_string_conversions.h"
#include "build/build_config.h"
#include "content/public/browser/render_frame_host.h"
#include "content/public/browser/web_contents.h"
#include "content/shell/browser/shell.h"
#if !BUILDFLAG(IS_ANDROID) && !BUILDFLAG(IS_IOS)
#include "content/shell/common/shell_switches.h"
#endif
#include "content/web_test/browser/web_test_control_host.h"
#include "content/web_test/common/web_test_switches.h"
#include "net/base/filename_util.h"
namespace {
const char kDevToolsFrontendOrigin[] = "debug-frontend.test";
const char kOriginToReplace[] = "127.0.0.1";
GURL GetInspectedPageURL(const GURL& test_url) {
std::string spec = test_url.spec();
std::string test_query_param = "&inspected_test=";
std::string test_script_url =
spec.substr(spec.find(test_query_param) + test_query_param.length());
std::string inspected_page_url = test_script_url.replace(
test_script_url.find("/devtools/"), std::string::npos,
"/devtools/resources/inspected-page.html");
return GURL(inspected_page_url);
}
} // namespace
namespace content {
class WebTestDevToolsBindings::SecondaryObserver : public WebContentsObserver {
public:
explicit SecondaryObserver(WebTestDevToolsBindings* bindings)
: WebContentsObserver(bindings->inspected_contents()),
bindings_(bindings) {}
SecondaryObserver(const SecondaryObserver&) = delete;
SecondaryObserver& operator=(const SecondaryObserver&) = delete;
// WebContentsObserver implementation.
void PrimaryMainDocumentElementAvailable() override {
if (bindings_)
bindings_->NavigateDevToolsFrontend();
bindings_ = nullptr;
}
private:
raw_ptr<WebTestDevToolsBindings> bindings_;
};
// static.
GURL WebTestDevToolsBindings::MapTestURLIfNeeded(const GURL& test_url,
bool* is_devtools_test) {
std::string test_url_string = test_url.spec();
*is_devtools_test = test_url_string.find("/devtools/") != std::string::npos;
if (!*is_devtools_test)
return test_url;
base::FilePath dir_exe;
if (!base::PathService::Get(base::DIR_EXE, &dir_exe)) {
NOTREACHED();
return GURL();
}
#if BUILDFLAG(IS_MAC)
// On Mac, the executable is in
// out/Release/Content Shell.app/Contents/MacOS/Content Shell.
// We need to go up 3 directories to get to out/Release.
dir_exe = dir_exe.AppendASCII("../../..");
#endif
base::FilePath dev_tools_path;
bool is_debug_dev_tools = base::CommandLine::ForCurrentProcess()->HasSwitch(
switches::kDebugDevTools);
// The test runner hosts DevTools resources at this path.
// To reduce timeouts, we need to load DevTools resources from the same
// origin as the `test_url_string`.
CHECK_NE(test_url_string.find("127.0.0.1:8000"), std::string::npos);
std::string url_string = "http://" + std::string(kDevToolsFrontendOrigin) +
":8000/inspector-sources/";
url_string += "integration_test_runner.html?experiments=true";
if (is_debug_dev_tools)
url_string += "&debugFrontend=true";
std::string devtools_test_url = test_url_string;
devtools_test_url.replace(test_url_string.find(kOriginToReplace),
std::strlen(kOriginToReplace),
kDevToolsFrontendOrigin);
url_string += "&test=" + devtools_test_url;
url_string += "&inspected_test=" + test_url_string;
#if !BUILDFLAG(IS_ANDROID) && !BUILDFLAG(IS_IOS)
if (base::CommandLine::ForCurrentProcess()->HasSwitch(
switches::kContentShellDevToolsTabTarget)) {
url_string += "&targetType=tab";
}
#endif
return GURL(url_string);
}
void WebTestDevToolsBindings::NavigateDevToolsFrontend() {
NavigationController::LoadURLParams params(frontend_url_);
params.transition_type = ui::PageTransitionFromInt(
ui::PAGE_TRANSITION_TYPED | ui::PAGE_TRANSITION_FROM_ADDRESS_BAR);
web_contents()->GetController().LoadURLWithParams(params);
}
void WebTestDevToolsBindings::Attach() {}
WebTestDevToolsBindings::WebTestDevToolsBindings(
WebContents* devtools_contents,
WebContents* inspected_contents,
const GURL& frontend_url)
: ShellDevToolsBindings(devtools_contents, inspected_contents, nullptr),
frontend_url_(frontend_url) {
secondary_observer_ = std::make_unique<SecondaryObserver>(this);
NavigationController::LoadURLParams params(GetInspectedPageURL(frontend_url));
params.transition_type = ui::PageTransitionFromInt(
ui::PAGE_TRANSITION_TYPED | ui::PAGE_TRANSITION_FROM_ADDRESS_BAR);
inspected_contents->GetController().LoadURLWithParams(params);
}
WebTestDevToolsBindings::~WebTestDevToolsBindings() {}
void WebTestDevToolsBindings::PrimaryMainDocumentElementAvailable() {
ShellDevToolsBindings::Attach();
}
} // namespace content