blob: 69fe055fd90a790ef8d459727041a60e9105a77a [file] [log] [blame]
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00001// Copyright (c) 2013 The Chromium Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5#include "content/browser/devtools/renderer_overrides_handler.h"
6
7#include <string>
8
Torne (Richard Coles)c2e0dbd2013-05-09 18:35:53 +01009#include "base/base64.h"
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +000010#include "base/bind.h"
11#include "base/bind_helpers.h"
12#include "base/files/file_path.h"
Torne (Richard Coles)868fa2f2013-06-11 10:57:03 +010013#include "base/strings/string16.h"
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +000014#include "base/values.h"
15#include "content/browser/child_process_security_policy_impl.h"
16#include "content/browser/devtools/devtools_protocol_constants.h"
Ben Murdochca12bfa2013-07-23 11:17:05 +010017#include "content/browser/devtools/devtools_tracing_handler.h"
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +000018#include "content/browser/renderer_host/render_view_host_delegate.h"
Ben Murdochbb1529c2013-08-08 10:24:53 +010019#include "content/public/browser/browser_thread.h"
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +000020#include "content/public/browser/devtools_agent_host.h"
21#include "content/public/browser/javascript_dialog_manager.h"
22#include "content/public/browser/navigation_controller.h"
23#include "content/public/browser/render_process_host.h"
24#include "content/public/browser/render_view_host.h"
Torne (Richard Coles)c2e0dbd2013-05-09 18:35:53 +010025#include "content/public/browser/render_widget_host_view.h"
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +000026#include "content/public/browser/web_contents.h"
27#include "content/public/browser/web_contents_delegate.h"
28#include "content/public/common/page_transition_types.h"
29#include "content/public/common/referrer.h"
Torne (Richard Coles)c2e0dbd2013-05-09 18:35:53 +010030#include "ui/snapshot/snapshot.h"
Ben Murdoch7dbb3d52013-07-17 14:55:54 +010031#include "url/gurl.h"
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +000032
33namespace content {
34
35RendererOverridesHandler::RendererOverridesHandler(DevToolsAgentHost* agent)
Ben Murdochbb1529c2013-08-08 10:24:53 +010036 : agent_(agent),
37 weak_factory_(this) {
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +000038 RegisterCommandHandler(
39 devtools::DOM::setFileInputFiles::kName,
40 base::Bind(
41 &RendererOverridesHandler::GrantPermissionsForSetFileInputFiles,
42 base::Unretained(this)));
43 RegisterCommandHandler(
44 devtools::Page::handleJavaScriptDialog::kName,
45 base::Bind(
46 &RendererOverridesHandler::PageHandleJavaScriptDialog,
47 base::Unretained(this)));
48 RegisterCommandHandler(
49 devtools::Page::navigate::kName,
50 base::Bind(
51 &RendererOverridesHandler::PageNavigate,
52 base::Unretained(this)));
Torne (Richard Coles)c2e0dbd2013-05-09 18:35:53 +010053 RegisterCommandHandler(
54 devtools::Page::captureScreenshot::kName,
55 base::Bind(
56 &RendererOverridesHandler::PageCaptureScreenshot,
57 base::Unretained(this)));
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +000058}
59
60RendererOverridesHandler::~RendererOverridesHandler() {}
61
Ben Murdochbb1529c2013-08-08 10:24:53 +010062scoped_refptr<DevToolsProtocol::Response>
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +000063RendererOverridesHandler::GrantPermissionsForSetFileInputFiles(
Ben Murdochbb1529c2013-08-08 10:24:53 +010064 scoped_refptr<DevToolsProtocol::Command> command) {
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +000065 base::DictionaryValue* params = command->params();
66 base::ListValue* file_list = NULL;
67 const char* param =
68 devtools::DOM::setFileInputFiles::kParamFiles;
Torne (Richard Coles)c2e0dbd2013-05-09 18:35:53 +010069 if (!params || !params->GetList(param, &file_list))
70 return command->InvalidParamResponse(param);
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +000071 RenderViewHost* host = agent_->GetRenderViewHost();
72 if (!host)
Ben Murdochbb1529c2013-08-08 10:24:53 +010073 return NULL;
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +000074
75 for (size_t i = 0; i < file_list->GetSize(); ++i) {
76 base::FilePath::StringType file;
Torne (Richard Coles)c2e0dbd2013-05-09 18:35:53 +010077 if (!file_list->GetString(i, &file))
78 return command->InvalidParamResponse(param);
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +000079 ChildProcessSecurityPolicyImpl::GetInstance()->GrantReadFile(
80 host->GetProcess()->GetID(), base::FilePath(file));
81 }
Ben Murdochbb1529c2013-08-08 10:24:53 +010082 return NULL;
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +000083}
84
Ben Murdochbb1529c2013-08-08 10:24:53 +010085scoped_refptr<DevToolsProtocol::Response>
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +000086RendererOverridesHandler::PageHandleJavaScriptDialog(
Ben Murdochbb1529c2013-08-08 10:24:53 +010087 scoped_refptr<DevToolsProtocol::Command> command) {
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +000088 base::DictionaryValue* params = command->params();
89 const char* paramAccept =
90 devtools::Page::handleJavaScriptDialog::kParamAccept;
91 bool accept;
Torne (Richard Coles)c2e0dbd2013-05-09 18:35:53 +010092 if (!params || !params->GetBoolean(paramAccept, &accept))
93 return command->InvalidParamResponse(paramAccept);
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +000094 string16 prompt_override;
95 string16* prompt_override_ptr = &prompt_override;
96 if (!params || !params->GetString(
97 devtools::Page::handleJavaScriptDialog::kParamPromptText,
98 prompt_override_ptr)) {
99 prompt_override_ptr = NULL;
100 }
101
102 RenderViewHost* host = agent_->GetRenderViewHost();
103 if (host) {
104 WebContents* web_contents = host->GetDelegate()->GetAsWebContents();
105 if (web_contents) {
106 JavaScriptDialogManager* manager =
107 web_contents->GetDelegate()->GetJavaScriptDialogManager();
108 if (manager && manager->HandleJavaScriptDialog(
109 web_contents, accept, prompt_override_ptr)) {
Ben Murdochbb1529c2013-08-08 10:24:53 +0100110 return NULL;
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000111 }
112 }
113 }
Torne (Richard Coles)c2e0dbd2013-05-09 18:35:53 +0100114 return command->InternalErrorResponse("No JavaScript dialog to handle");
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000115}
116
Ben Murdochbb1529c2013-08-08 10:24:53 +0100117scoped_refptr<DevToolsProtocol::Response>
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000118RendererOverridesHandler::PageNavigate(
Ben Murdochbb1529c2013-08-08 10:24:53 +0100119 scoped_refptr<DevToolsProtocol::Command> command) {
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000120 base::DictionaryValue* params = command->params();
121 std::string url;
122 const char* param = devtools::Page::navigate::kParamUrl;
Torne (Richard Coles)c2e0dbd2013-05-09 18:35:53 +0100123 if (!params || !params->GetString(param, &url))
124 return command->InvalidParamResponse(param);
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000125 GURL gurl(url);
126 if (!gurl.is_valid()) {
Torne (Richard Coles)c2e0dbd2013-05-09 18:35:53 +0100127 return command->InternalErrorResponse("Cannot navigate to invalid URL");
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000128 }
129 RenderViewHost* host = agent_->GetRenderViewHost();
130 if (host) {
131 WebContents* web_contents = host->GetDelegate()->GetAsWebContents();
132 if (web_contents) {
Torne (Richard Coles)c2e0dbd2013-05-09 18:35:53 +0100133 web_contents->GetController()
134 .LoadURL(gurl, Referrer(), PAGE_TRANSITION_TYPED, std::string());
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000135 return command->SuccessResponse(new base::DictionaryValue());
136 }
137 }
Torne (Richard Coles)c2e0dbd2013-05-09 18:35:53 +0100138 return command->InternalErrorResponse("No WebContents to navigate");
139}
140
Ben Murdochbb1529c2013-08-08 10:24:53 +0100141scoped_refptr<DevToolsProtocol::Response>
Torne (Richard Coles)c2e0dbd2013-05-09 18:35:53 +0100142RendererOverridesHandler::PageCaptureScreenshot(
Ben Murdochbb1529c2013-08-08 10:24:53 +0100143 scoped_refptr<DevToolsProtocol::Command> command) {
144 // Emulate async processing.
145 BrowserThread::PostTask(
146 BrowserThread::UI, FROM_HERE,
147 base::Bind(&RendererOverridesHandler::CaptureScreenshot,
148 weak_factory_.GetWeakPtr(),
149 command));
Torne (Richard Coles)c2e0dbd2013-05-09 18:35:53 +0100150
Ben Murdochbb1529c2013-08-08 10:24:53 +0100151 return command->AsyncResponsePromise();
Torne (Richard Coles)c2e0dbd2013-05-09 18:35:53 +0100152}
153
Ben Murdochbb1529c2013-08-08 10:24:53 +0100154void RendererOverridesHandler::CaptureScreenshot(
155 scoped_refptr<DevToolsProtocol::Command> command) {
156
Torne (Richard Coles)c2e0dbd2013-05-09 18:35:53 +0100157 RenderViewHost* host = agent_->GetRenderViewHost();
158 gfx::Rect view_bounds = host->GetView()->GetViewBounds();
159 gfx::Rect snapshot_bounds(view_bounds.size());
160 gfx::Size snapshot_size = snapshot_bounds.size();
Torne (Richard Coles)c2e0dbd2013-05-09 18:35:53 +0100161
Ben Murdochbb1529c2013-08-08 10:24:53 +0100162 std::vector<unsigned char> png;
163 if (ui::GrabViewSnapshot(host->GetView()->GetNativeView(),
164 &png,
165 snapshot_bounds)) {
166 std::string base_64_data;
167 bool success = base::Base64Encode(
168 base::StringPiece(reinterpret_cast<char*>(&*png.begin()), png.size()),
169 &base_64_data);
170 if (success) {
171 base::DictionaryValue* result = new base::DictionaryValue();
172 result->SetString(
173 devtools::Page::captureScreenshot::kResponseData, base_64_data);
174 scoped_refptr<DevToolsProtocol::Response> response =
175 command->SuccessResponse(result);
176 SendRawMessage(response->Serialize());
177 return;
178 }
179 }
180 SendRawMessage(command->
181 InternalErrorResponse("Unable to capture a screenshot")->Serialize());
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000182}
183
184} // namespace content