blob: 69fe055fd90a790ef8d459727041a60e9105a77a [file] [log] [blame]
// Copyright (c) 2013 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/browser/devtools/renderer_overrides_handler.h"
#include <string>
#include "base/base64.h"
#include "base/bind.h"
#include "base/bind_helpers.h"
#include "base/files/file_path.h"
#include "base/strings/string16.h"
#include "base/values.h"
#include "content/browser/child_process_security_policy_impl.h"
#include "content/browser/devtools/devtools_protocol_constants.h"
#include "content/browser/devtools/devtools_tracing_handler.h"
#include "content/browser/renderer_host/render_view_host_delegate.h"
#include "content/public/browser/browser_thread.h"
#include "content/public/browser/devtools_agent_host.h"
#include "content/public/browser/javascript_dialog_manager.h"
#include "content/public/browser/navigation_controller.h"
#include "content/public/browser/render_process_host.h"
#include "content/public/browser/render_view_host.h"
#include "content/public/browser/render_widget_host_view.h"
#include "content/public/browser/web_contents.h"
#include "content/public/browser/web_contents_delegate.h"
#include "content/public/common/page_transition_types.h"
#include "content/public/common/referrer.h"
#include "ui/snapshot/snapshot.h"
#include "url/gurl.h"
namespace content {
RendererOverridesHandler::RendererOverridesHandler(DevToolsAgentHost* agent)
: agent_(agent),
weak_factory_(this) {
RegisterCommandHandler(
devtools::DOM::setFileInputFiles::kName,
base::Bind(
&RendererOverridesHandler::GrantPermissionsForSetFileInputFiles,
base::Unretained(this)));
RegisterCommandHandler(
devtools::Page::handleJavaScriptDialog::kName,
base::Bind(
&RendererOverridesHandler::PageHandleJavaScriptDialog,
base::Unretained(this)));
RegisterCommandHandler(
devtools::Page::navigate::kName,
base::Bind(
&RendererOverridesHandler::PageNavigate,
base::Unretained(this)));
RegisterCommandHandler(
devtools::Page::captureScreenshot::kName,
base::Bind(
&RendererOverridesHandler::PageCaptureScreenshot,
base::Unretained(this)));
}
RendererOverridesHandler::~RendererOverridesHandler() {}
scoped_refptr<DevToolsProtocol::Response>
RendererOverridesHandler::GrantPermissionsForSetFileInputFiles(
scoped_refptr<DevToolsProtocol::Command> command) {
base::DictionaryValue* params = command->params();
base::ListValue* file_list = NULL;
const char* param =
devtools::DOM::setFileInputFiles::kParamFiles;
if (!params || !params->GetList(param, &file_list))
return command->InvalidParamResponse(param);
RenderViewHost* host = agent_->GetRenderViewHost();
if (!host)
return NULL;
for (size_t i = 0; i < file_list->GetSize(); ++i) {
base::FilePath::StringType file;
if (!file_list->GetString(i, &file))
return command->InvalidParamResponse(param);
ChildProcessSecurityPolicyImpl::GetInstance()->GrantReadFile(
host->GetProcess()->GetID(), base::FilePath(file));
}
return NULL;
}
scoped_refptr<DevToolsProtocol::Response>
RendererOverridesHandler::PageHandleJavaScriptDialog(
scoped_refptr<DevToolsProtocol::Command> command) {
base::DictionaryValue* params = command->params();
const char* paramAccept =
devtools::Page::handleJavaScriptDialog::kParamAccept;
bool accept;
if (!params || !params->GetBoolean(paramAccept, &accept))
return command->InvalidParamResponse(paramAccept);
string16 prompt_override;
string16* prompt_override_ptr = &prompt_override;
if (!params || !params->GetString(
devtools::Page::handleJavaScriptDialog::kParamPromptText,
prompt_override_ptr)) {
prompt_override_ptr = NULL;
}
RenderViewHost* host = agent_->GetRenderViewHost();
if (host) {
WebContents* web_contents = host->GetDelegate()->GetAsWebContents();
if (web_contents) {
JavaScriptDialogManager* manager =
web_contents->GetDelegate()->GetJavaScriptDialogManager();
if (manager && manager->HandleJavaScriptDialog(
web_contents, accept, prompt_override_ptr)) {
return NULL;
}
}
}
return command->InternalErrorResponse("No JavaScript dialog to handle");
}
scoped_refptr<DevToolsProtocol::Response>
RendererOverridesHandler::PageNavigate(
scoped_refptr<DevToolsProtocol::Command> command) {
base::DictionaryValue* params = command->params();
std::string url;
const char* param = devtools::Page::navigate::kParamUrl;
if (!params || !params->GetString(param, &url))
return command->InvalidParamResponse(param);
GURL gurl(url);
if (!gurl.is_valid()) {
return command->InternalErrorResponse("Cannot navigate to invalid URL");
}
RenderViewHost* host = agent_->GetRenderViewHost();
if (host) {
WebContents* web_contents = host->GetDelegate()->GetAsWebContents();
if (web_contents) {
web_contents->GetController()
.LoadURL(gurl, Referrer(), PAGE_TRANSITION_TYPED, std::string());
return command->SuccessResponse(new base::DictionaryValue());
}
}
return command->InternalErrorResponse("No WebContents to navigate");
}
scoped_refptr<DevToolsProtocol::Response>
RendererOverridesHandler::PageCaptureScreenshot(
scoped_refptr<DevToolsProtocol::Command> command) {
// Emulate async processing.
BrowserThread::PostTask(
BrowserThread::UI, FROM_HERE,
base::Bind(&RendererOverridesHandler::CaptureScreenshot,
weak_factory_.GetWeakPtr(),
command));
return command->AsyncResponsePromise();
}
void RendererOverridesHandler::CaptureScreenshot(
scoped_refptr<DevToolsProtocol::Command> command) {
RenderViewHost* host = agent_->GetRenderViewHost();
gfx::Rect view_bounds = host->GetView()->GetViewBounds();
gfx::Rect snapshot_bounds(view_bounds.size());
gfx::Size snapshot_size = snapshot_bounds.size();
std::vector<unsigned char> png;
if (ui::GrabViewSnapshot(host->GetView()->GetNativeView(),
&png,
snapshot_bounds)) {
std::string base_64_data;
bool success = base::Base64Encode(
base::StringPiece(reinterpret_cast<char*>(&*png.begin()), png.size()),
&base_64_data);
if (success) {
base::DictionaryValue* result = new base::DictionaryValue();
result->SetString(
devtools::Page::captureScreenshot::kResponseData, base_64_data);
scoped_refptr<DevToolsProtocol::Response> response =
command->SuccessResponse(result);
SendRawMessage(response->Serialize());
return;
}
}
SendRawMessage(command->
InternalErrorResponse("Unable to capture a screenshot")->Serialize());
}
} // namespace content