blob: 7f18192f4f79c86fe76a5cc8f83fac8f4ea5fd60 [file] [log] [blame]
// 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.
#include "content/shell/browser/layout_test/layout_test_devtools_bindings.h"
#include "base/command_line.h"
#include "base/json/json_reader.h"
#include "base/json/json_writer.h"
#include "base/path_service.h"
#include "base/strings/string_util.h"
#include "base/strings/stringprintf.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/layout_test/blink_test_controller.h"
#include "content/shell/browser/shell.h"
#include "content/shell/common/layout_test/layout_test_switches.h"
#include "net/base/filename_util.h"
namespace content {
// static.
GURL LayoutTestDevToolsBindings::GetDevToolsPathAsURL(
const std::string& frontend_url) {
if (!frontend_url.empty())
return GURL(frontend_url);
base::FilePath dir_exe;
if (!PathService::Get(base::DIR_EXE, &dir_exe)) {
NOTREACHED();
return GURL();
}
#if defined(OS_MACOSX)
// 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);
if (base::CommandLine::ForCurrentProcess()->HasSwitch(
switches::kCustomDevToolsFrontend)) {
dev_tools_path = base::CommandLine::ForCurrentProcess()->GetSwitchValuePath(
switches::kCustomDevToolsFrontend);
} else {
std::string folder = is_debug_dev_tools ? "debug/" : "";
dev_tools_path = dir_exe.AppendASCII("resources/inspector/" + folder);
}
GURL result =
net::FilePathToFileURL(dev_tools_path.AppendASCII("inspector.html"));
std::string url_string =
base::StringPrintf("%s?experiments=true", result.spec().c_str());
if (is_debug_dev_tools)
url_string += "&debugFrontend=true";
return GURL(url_string);
}
// static.
GURL LayoutTestDevToolsBindings::MapTestURLIfNeeded(const GURL& test_url,
bool* is_devtools_js_test) {
std::string spec = test_url.spec();
bool is_js_test =
base::EndsWith(spec, ".js", base::CompareCase::INSENSITIVE_ASCII);
*is_devtools_js_test =
spec.find("/devtools/") != std::string::npos && is_js_test;
bool is_unit_test = spec.find("/inspector-unit/") != std::string::npos;
if (!*is_devtools_js_test && !is_unit_test)
return test_url;
return MapJSTestURL(test_url, is_unit_test ? "unit_test_runner.html"
: "integration_test_runner.html");
}
// static.
GURL LayoutTestDevToolsBindings::MapJSTestURL(
const GURL& test_url,
const std::string& entry_filename) {
std::string url_string = GetDevToolsPathAsURL(std::string()).spec();
std::string inspector_file_name = "inspector.html";
size_t start_position = url_string.find(inspector_file_name);
url_string.replace(start_position, inspector_file_name.length(),
entry_filename);
url_string += "&test=" + test_url.spec();
return GURL(url_string);
}
// static
LayoutTestDevToolsBindings* LayoutTestDevToolsBindings::LoadDevTools(
WebContents* devtools_contents_,
WebContents* inspected_contents_,
const std::string& settings,
const std::string& frontend_url) {
LayoutTestDevToolsBindings* bindings =
new LayoutTestDevToolsBindings(devtools_contents_, inspected_contents_);
bindings->SetPreferences(settings);
GURL devtools_url =
LayoutTestDevToolsBindings::GetDevToolsPathAsURL(frontend_url);
NavigationController::LoadURLParams params(devtools_url);
params.transition_type = ui::PageTransitionFromInt(
ui::PAGE_TRANSITION_TYPED | ui::PAGE_TRANSITION_FROM_ADDRESS_BAR);
bindings->web_contents()->GetController().LoadURLWithParams(params);
bindings->web_contents()->Focus();
return bindings;
}
// static.
GURL LayoutTestDevToolsBindings::GetInspectedPageURL(const GURL& test_url) {
std::string spec = test_url.spec();
std::string test_query_param = "&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);
}
void LayoutTestDevToolsBindings::EvaluateInFrontend(int call_id,
const std::string& script) {
if (!ready_for_test_) {
pending_evaluations_.push_back(std::make_pair(call_id, script));
return;
}
std::string encoded_script;
base::JSONWriter::Write(base::Value(script), &encoded_script);
std::string source =
base::StringPrintf("DevToolsAPI.evaluateForTestInFrontend(%d, %s);",
call_id, encoded_script.c_str());
web_contents()->GetMainFrame()->ExecuteJavaScriptForTests(
base::UTF8ToUTF16(source));
}
LayoutTestDevToolsBindings::LayoutTestDevToolsBindings(
WebContents* devtools_contents,
WebContents* inspected_contents)
: ShellDevToolsBindings(devtools_contents, inspected_contents, nullptr),
ready_for_test_(false) {}
LayoutTestDevToolsBindings::~LayoutTestDevToolsBindings() {}
void LayoutTestDevToolsBindings::HandleMessageFromDevToolsFrontend(
const std::string& message) {
std::string method;
base::DictionaryValue* dict = nullptr;
std::unique_ptr<base::Value> parsed_message = base::JSONReader::Read(message);
if (parsed_message && parsed_message->GetAsDictionary(&dict) &&
dict->GetString("method", &method) && method == "readyForTest") {
ready_for_test_ = true;
for (const auto& pair : pending_evaluations_)
EvaluateInFrontend(pair.first, pair.second);
pending_evaluations_.clear();
return;
}
ShellDevToolsBindings::HandleMessageFromDevToolsFrontend(message);
}
void LayoutTestDevToolsBindings::RenderProcessGone(
base::TerminationStatus status) {
BlinkTestController::Get()->DevToolsProcessCrashed();
}
void LayoutTestDevToolsBindings::RenderFrameCreated(
RenderFrameHost* render_frame_host) {
BlinkTestController::Get()->HandleNewRenderFrameHost(render_frame_host);
}
} // namespace content