blob: b10943df253c6d47eaa4cc733ac14c25e32fff26 [file] [log] [blame]
[email protected]de7d61ff2013-08-20 11:30:411// Copyright 2013 The Chromium Authors. All rights reserved.
[email protected]9fbd3f862011-09-20 23:31:342// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
[email protected]de7d61ff2013-08-20 11:30:415#include "content/shell/browser/shell.h"
[email protected]9fbd3f862011-09-20 23:31:346
[email protected]11a65b692012-03-30 11:29:167#include "base/auto_reset.h"
[email protected]efb5f572012-01-29 10:57:338#include "base/command_line.h"
[email protected]aaf68892013-07-18 00:11:309#include "base/message_loop/message_loop.h"
[email protected]9fbd3f862011-09-20 23:31:3410#include "base/path_service.h"
[email protected]21aa99682013-06-11 07:17:0111#include "base/strings/string_number_conversions.h"
12#include "base/strings/string_util.h"
13#include "base/strings/stringprintf.h"
[email protected]74ebfb12013-06-07 20:48:0014#include "base/strings/utf_string_conversions.h"
[email protected]b50452f2014-08-18 12:31:4415#include "content/public/browser/devtools_agent_host.h"
[email protected]0b659b32012-03-26 21:29:3216#include "content/public/browser/navigation_controller.h"
[email protected]b7c504c2013-05-07 14:42:1217#include "content/public/browser/navigation_entry.h"
[email protected]0b659b32012-03-26 21:29:3218#include "content/public/browser/render_view_host.h"
19#include "content/public/browser/web_contents.h"
[email protected]7fff43e2013-05-21 20:21:1020#include "content/public/browser/web_contents_observer.h"
[email protected]1596efb2013-01-17 22:13:0121#include "content/public/common/renderer_preferences.h"
[email protected]de7d61ff2013-08-20 11:30:4122#include "content/shell/browser/notify_done_forwarder.h"
23#include "content/shell/browser/shell_browser_main_parts.h"
24#include "content/shell/browser/shell_content_browser_client.h"
25#include "content/shell/browser/shell_devtools_frontend.h"
26#include "content/shell/browser/shell_javascript_dialog_manager.h"
27#include "content/shell/browser/webkit_test_controller.h"
[email protected]b7c504c2013-05-07 14:42:1228#include "content/shell/common/shell_messages.h"
29#include "content/shell/common/shell_switches.h"
[email protected]9fbd3f862011-09-20 23:31:3430
[email protected]9fbd3f862011-09-20 23:31:3431namespace content {
32
[email protected]1e57cab2013-05-28 04:26:1133const int Shell::kDefaultTestWindowWidthDip = 800;
34const int Shell::kDefaultTestWindowHeightDip = 600;
35
[email protected]e99ca5112011-09-26 17:22:5436std::vector<Shell*> Shell::windows_;
[email protected]9e00e6352012-07-30 17:05:1837base::Callback<void(Shell*)> Shell::shell_created_callback_;
[email protected]9fbd3f862011-09-20 23:31:3438
[email protected]11a65b692012-03-30 11:29:1639bool Shell::quit_message_loop_ = true;
40
[email protected]7fff43e2013-05-21 20:21:1041class Shell::DevToolsWebContentsObserver : public WebContentsObserver {
42 public:
43 DevToolsWebContentsObserver(Shell* shell, WebContents* web_contents)
44 : WebContentsObserver(web_contents),
45 shell_(shell) {
46 }
47
48 // WebContentsObserver
[email protected]12a46832014-05-09 13:35:5849 virtual void WebContentsDestroyed() OVERRIDE {
[email protected]7fff43e2013-05-21 20:21:1050 shell_->OnDevToolsWebContentsDestroyed();
51 }
52
53 private:
54 Shell* shell_;
55
56 DISALLOW_COPY_AND_ASSIGN(DevToolsWebContentsObserver);
57};
58
[email protected]0b659b32012-03-26 21:29:3259Shell::Shell(WebContents* web_contents)
[email protected]1ef02d242013-10-07 16:18:5360 : WebContentsObserver(web_contents),
61 devtools_frontend_(NULL),
[email protected]001841c92012-12-11 17:00:1362 is_fullscreen_(false),
[email protected]99c014c2012-11-27 12:03:4263 window_(NULL),
[email protected]86b36e672012-12-21 00:09:5164 url_edit_view_(NULL),
[email protected]86b36e672012-12-21 00:09:5165 headless_(false) {
66 const CommandLine& command_line = *CommandLine::ForCurrentProcess();
[email protected]28cc78e2013-06-13 09:05:4667 if (command_line.HasSwitch(switches::kDumpRenderTree))
[email protected]86b36e672012-12-21 00:09:5168 headless_ = true;
[email protected]9e00e6352012-07-30 17:05:1869 windows_.push_back(this);
70
71 if (!shell_created_callback_.is_null()) {
72 shell_created_callback_.Run(this);
73 shell_created_callback_.Reset();
74 }
[email protected]9fbd3f862011-09-20 23:31:3475}
76
77Shell::~Shell() {
78 PlatformCleanUp();
[email protected]e99ca5112011-09-26 17:22:5479
80 for (size_t i = 0; i < windows_.size(); ++i) {
81 if (windows_[i] == this) {
82 windows_.erase(windows_.begin() + i);
83 break;
84 }
85 }
[email protected]11a65b692012-03-30 11:29:1686
[email protected]b53adf452014-02-07 12:55:0887 if (windows_.empty() && quit_message_loop_) {
88 if (headless_)
89 PlatformExit();
[email protected]dd32b1272013-05-04 14:17:1190 base::MessageLoop::current()->PostTask(FROM_HERE,
91 base::MessageLoop::QuitClosure());
[email protected]b53adf452014-02-07 12:55:0892 }
[email protected]9fbd3f862011-09-20 23:31:3493}
94
[email protected]c0d036d2013-05-07 12:50:5095Shell* Shell::CreateShell(WebContents* web_contents,
96 const gfx::Size& initial_size) {
[email protected]0b659b32012-03-26 21:29:3297 Shell* shell = new Shell(web_contents);
[email protected]c0d036d2013-05-07 12:50:5098 shell->PlatformCreateWindow(initial_size.width(), initial_size.height());
[email protected]3fd84032012-01-12 18:20:1799
[email protected]0b659b32012-03-26 21:29:32100 shell->web_contents_.reset(web_contents);
101 web_contents->SetDelegate(shell);
[email protected]3fd84032012-01-12 18:20:17102
[email protected]5cba3bf2012-01-14 02:40:35103 shell->PlatformSetContents();
[email protected]3fd84032012-01-12 18:20:17104
105 shell->PlatformResizeSubViews();
[email protected]1596efb2013-01-17 22:13:01106
107 if (CommandLine::ForCurrentProcess()->HasSwitch(switches::kDumpRenderTree)) {
108 web_contents->GetMutableRendererPrefs()->use_custom_colors = false;
109 web_contents->GetRenderViewHost()->SyncRendererPrefs();
110 }
111
[email protected]3fd84032012-01-12 18:20:17112 return shell;
113}
114
[email protected]11a65b692012-03-30 11:29:16115void Shell::CloseAllWindows() {
[email protected]997ec9f2012-11-21 04:44:14116 base::AutoReset<bool> auto_reset(&quit_message_loop_, false);
[email protected]b50452f2014-08-18 12:31:44117 DevToolsAgentHost::DetachAllClients();
[email protected]11a65b692012-03-30 11:29:16118 std::vector<Shell*> open_windows(windows_);
119 for (size_t i = 0; i < open_windows.size(); ++i)
120 open_windows[i]->Close();
[email protected]4249a422013-11-27 19:04:04121 PlatformExit();
[email protected]dd32b1272013-05-04 14:17:11122 base::MessageLoop::current()->RunUntilIdle();
[email protected]11a65b692012-03-30 11:29:16123}
124
[email protected]9e00e6352012-07-30 17:05:18125void Shell::SetShellCreatedCallback(
126 base::Callback<void(Shell*)> shell_created_callback) {
127 DCHECK(shell_created_callback_.is_null());
128 shell_created_callback_ = shell_created_callback;
129}
130
[email protected]74830f02012-01-30 22:27:04131Shell* Shell::FromRenderViewHost(RenderViewHost* rvh) {
132 for (size_t i = 0; i < windows_.size(); ++i) {
[email protected]0b659b32012-03-26 21:29:32133 if (windows_[i]->web_contents() &&
134 windows_[i]->web_contents()->GetRenderViewHost() == rvh) {
[email protected]74830f02012-01-30 22:27:04135 return windows_[i];
136 }
137 }
138 return NULL;
139}
140
[email protected]6153b272013-01-25 22:29:23141// static
142void Shell::Initialize() {
[email protected]1e57cab2013-05-28 04:26:11143 PlatformInitialize(
144 gfx::Size(kDefaultTestWindowWidthDip, kDefaultTestWindowHeightDip));
[email protected]6153b272013-01-25 22:29:23145}
146
[email protected]a2904092013-10-15 04:53:59147gfx::Size Shell::AdjustWindowSize(const gfx::Size& initial_size) {
148 if (!initial_size.IsEmpty())
149 return initial_size;
150 return gfx::Size(kDefaultTestWindowWidthDip, kDefaultTestWindowHeightDip);
151}
152
[email protected]bdcf9152012-07-19 17:43:21153Shell* Shell::CreateNewWindow(BrowserContext* browser_context,
[email protected]e99ca5112011-09-26 17:22:54154 const GURL& url,
155 SiteInstance* site_instance,
156 int routing_id,
[email protected]cdb806722013-01-10 14:18:23157 const gfx::Size& initial_size) {
[email protected]54944cde2012-12-09 09:24:59158 WebContents::CreateParams create_params(browser_context, site_instance);
159 create_params.routing_id = routing_id;
[email protected]a2904092013-10-15 04:53:59160 create_params.initial_size = AdjustWindowSize(initial_size);
[email protected]54944cde2012-12-09 09:24:59161 WebContents* web_contents = WebContents::Create(create_params);
[email protected]c0d036d2013-05-07 12:50:50162 Shell* shell = CreateShell(web_contents, create_params.initial_size);
[email protected]e99ca5112011-09-26 17:22:54163 if (!url.is_empty())
164 shell->LoadURL(url);
[email protected]9fbd3f862011-09-20 23:31:34165 return shell;
166}
167
168void Shell::LoadURL(const GURL& url) {
[email protected]d2494ff2013-02-20 08:22:37169 LoadURLForFrame(url, std::string());
170}
171
172void Shell::LoadURLForFrame(const GURL& url, const std::string& frame_name) {
173 NavigationController::LoadURLParams params(url);
174 params.transition_type = PageTransitionFromInt(
175 PAGE_TRANSITION_TYPED | PAGE_TRANSITION_FROM_ADDRESS_BAR);
176 params.frame_name = frame_name;
177 web_contents_->GetController().LoadURLWithParams(params);
[email protected]fc2b46b2014-05-03 16:33:45178 web_contents_->Focus();
[email protected]9fbd3f862011-09-20 23:31:34179}
180
[email protected]76bdecb2014-04-16 17:58:08181void Shell::LoadDataWithBaseURL(const GURL& url, const std::string& data,
182 const GURL& base_url) {
183 const GURL data_url = GURL("data:text/html;charset=utf-8," + data);
184 NavigationController::LoadURLParams params(data_url);
185 params.load_type = NavigationController::LOAD_TYPE_DATA;
186 params.base_url_for_data_url = base_url;
187 params.virtual_url_for_data_url = url;
188 params.override_user_agent = NavigationController::UA_OVERRIDE_FALSE;
189 web_contents_->GetController().LoadURLWithParams(params);
[email protected]fc2b46b2014-05-03 16:33:45190 web_contents_->Focus();
[email protected]76bdecb2014-04-16 17:58:08191}
192
[email protected]a2904092013-10-15 04:53:59193void Shell::AddNewContents(WebContents* source,
194 WebContents* new_contents,
195 WindowOpenDisposition disposition,
196 const gfx::Rect& initial_pos,
197 bool user_gesture,
198 bool* was_blocked) {
199 CreateShell(new_contents, AdjustWindowSize(initial_pos.size()));
200 if (CommandLine::ForCurrentProcess()->HasSwitch(switches::kDumpRenderTree))
201 NotifyDoneForwarder::CreateForWebContents(new_contents);
202}
203
[email protected]9fbd3f862011-09-20 23:31:34204void Shell::GoBackOrForward(int offset) {
[email protected]0b659b32012-03-26 21:29:32205 web_contents_->GetController().GoToOffset(offset);
[email protected]fc2b46b2014-05-03 16:33:45206 web_contents_->Focus();
[email protected]9fbd3f862011-09-20 23:31:34207}
208
209void Shell::Reload() {
[email protected]0b659b32012-03-26 21:29:32210 web_contents_->GetController().Reload(false);
[email protected]fc2b46b2014-05-03 16:33:45211 web_contents_->Focus();
[email protected]9fbd3f862011-09-20 23:31:34212}
213
214void Shell::Stop() {
[email protected]0b659b32012-03-26 21:29:32215 web_contents_->Stop();
[email protected]fc2b46b2014-05-03 16:33:45216 web_contents_->Focus();
[email protected]9fbd3f862011-09-20 23:31:34217}
218
[email protected]e3b10d12014-03-28 16:06:09219void Shell::UpdateNavigationControls(bool to_different_document) {
[email protected]0b659b32012-03-26 21:29:32220 int current_index = web_contents_->GetController().GetCurrentEntryIndex();
221 int max_index = web_contents_->GetController().GetEntryCount() - 1;
[email protected]9fbd3f862011-09-20 23:31:34222
223 PlatformEnableUIControl(BACK_BUTTON, current_index > 0);
224 PlatformEnableUIControl(FORWARD_BUTTON, current_index < max_index);
[email protected]e3b10d12014-03-28 16:06:09225 PlatformEnableUIControl(STOP_BUTTON,
226 to_different_document && web_contents_->IsLoading());
[email protected]9fbd3f862011-09-20 23:31:34227}
228
[email protected]7c17b6992012-08-09 16:16:30229void Shell::ShowDevTools() {
[email protected]06c253012014-04-16 18:35:33230 InnerShowDevTools("", "");
[email protected]3142e5d2014-02-07 00:54:46231}
232
233void Shell::ShowDevToolsForElementAt(int x, int y) {
[email protected]06c253012014-04-16 18:35:33234 InnerShowDevTools("", "");
[email protected]2317fcd2014-02-10 14:36:48235 devtools_frontend_->InspectElementAt(x, y);
[email protected]7c17b6992012-08-09 16:16:30236}
237
[email protected]06c253012014-04-16 18:35:33238void Shell::ShowDevToolsForTest(const std::string& settings,
239 const std::string& frontend_url) {
240 InnerShowDevTools(settings, frontend_url);
[email protected]fee9eca02014-02-14 19:24:40241}
242
[email protected]001841c92012-12-11 17:00:13243void Shell::CloseDevTools() {
[email protected]0773e0c2013-01-25 15:57:57244 if (!devtools_frontend_)
[email protected]001841c92012-12-11 17:00:13245 return;
[email protected]7fff43e2013-05-21 20:21:10246 devtools_observer_.reset();
[email protected]0773e0c2013-01-25 15:57:57247 devtools_frontend_->Close();
248 devtools_frontend_ = NULL;
[email protected]001841c92012-12-11 17:00:13249}
250
[email protected]9fbd3f862011-09-20 23:31:34251gfx::NativeView Shell::GetContentView() {
[email protected]59383c782013-04-17 16:43:27252 if (!web_contents_)
[email protected]9fbd3f862011-09-20 23:31:34253 return NULL;
[email protected]fc2b46b2014-05-03 16:33:45254 return web_contents_->GetNativeView();
[email protected]9fbd3f862011-09-20 23:31:34255}
256
[email protected]9e00e6352012-07-30 17:05:18257WebContents* Shell::OpenURLFromTab(WebContents* source,
258 const OpenURLParams& params) {
[email protected]7cf38302013-08-29 12:23:46259 // CURRENT_TAB is the only one we implement for now.
260 if (params.disposition != CURRENT_TAB)
261 return NULL;
[email protected]fbaccee2013-08-12 23:24:02262 NavigationController::LoadURLParams load_url_params(params.url);
263 load_url_params.referrer = params.referrer;
[email protected]c80297782013-11-21 07:10:16264 load_url_params.frame_tree_node_id = params.frame_tree_node_id;
[email protected]fbaccee2013-08-12 23:24:02265 load_url_params.transition_type = params.transition;
266 load_url_params.extra_headers = params.extra_headers;
267 load_url_params.should_replace_current_entry =
268 params.should_replace_current_entry;
269
270 if (params.transferred_global_request_id != GlobalRequestID()) {
271 load_url_params.is_renderer_initiated = params.is_renderer_initiated;
272 load_url_params.transferred_global_request_id =
273 params.transferred_global_request_id;
274 } else if (params.is_renderer_initiated) {
275 load_url_params.is_renderer_initiated = true;
276 }
277
278 source->GetController().LoadURLWithParams(load_url_params);
[email protected]9e00e6352012-07-30 17:05:18279 return source;
280}
281
[email protected]e3b10d12014-03-28 16:06:09282void Shell::LoadingStateChanged(WebContents* source,
283 bool to_different_document) {
284 UpdateNavigationControls(to_different_document);
[email protected]15aea412012-01-19 03:18:50285 PlatformSetIsLoading(source->IsLoading());
[email protected]e99ca5112011-09-26 17:22:54286}
287
[email protected]99c014c2012-11-27 12:03:42288void Shell::ToggleFullscreenModeForTab(WebContents* web_contents,
289 bool enter_fullscreen) {
290#if defined(OS_ANDROID)
291 PlatformToggleFullscreenModeForTab(web_contents, enter_fullscreen);
292#endif
293 if (!CommandLine::ForCurrentProcess()->HasSwitch(switches::kDumpRenderTree))
294 return;
295 if (is_fullscreen_ != enter_fullscreen) {
296 is_fullscreen_ = enter_fullscreen;
297 web_contents->GetRenderViewHost()->WasResized();
298 }
299}
300
301bool Shell::IsFullscreenForTabOrPending(const WebContents* web_contents) const {
302#if defined(OS_ANDROID)
303 return PlatformIsFullscreenForTabOrPending(web_contents);
304#else
305 return is_fullscreen_;
306#endif
307}
308
[email protected]f78439002012-11-28 14:45:59309void Shell::RequestToLockMouse(WebContents* web_contents,
310 bool user_gesture,
311 bool last_unlocked_by_target) {
312 web_contents->GotResponseToLockMouseRequest(true);
313}
314
[email protected]9e00e6352012-07-30 17:05:18315void Shell::CloseContents(WebContents* source) {
316 Close();
317}
318
[email protected]067310262012-11-22 14:30:41319bool Shell::CanOverscrollContent() const {
320#if defined(USE_AURA)
321 return true;
322#else
323 return false;
324#endif
325}
326
[email protected]3bbacc5b2012-04-17 17:46:15327void Shell::DidNavigateMainFramePostCommit(WebContents* web_contents) {
[email protected]4e3c7522013-08-13 11:53:18328 PlatformSetAddressBarURL(web_contents->GetLastCommittedURL());
[email protected]e99ca5112011-09-26 17:22:54329}
330
[email protected]71a88bb2013-02-01 22:05:15331JavaScriptDialogManager* Shell::GetJavaScriptDialogManager() {
[email protected]59383c782013-04-17 16:43:27332 if (!dialog_manager_)
[email protected]71a88bb2013-02-01 22:05:15333 dialog_manager_.reset(new ShellJavaScriptDialogManager());
334 return dialog_manager_.get();
[email protected]f2210022012-03-29 00:36:08335}
336
[email protected]c272c5b2012-06-06 09:01:06337bool Shell::AddMessageToConsole(WebContents* source,
338 int32 level,
[email protected]fcf75d42013-12-03 20:11:26339 const base::string16& message,
[email protected]c272c5b2012-06-06 09:01:06340 int32 line_no,
[email protected]fcf75d42013-12-03 20:11:26341 const base::string16& source_id) {
[email protected]55a5cd12013-01-28 15:24:23342 return CommandLine::ForCurrentProcess()->HasSwitch(switches::kDumpRenderTree);
[email protected]efb5f572012-01-29 10:57:33343}
344
[email protected]5bf68f22012-08-31 07:38:10345void Shell::RendererUnresponsive(WebContents* source) {
346 if (!CommandLine::ForCurrentProcess()->HasSwitch(switches::kDumpRenderTree))
347 return;
348 WebKitTestController::Get()->RendererUnresponsive();
349}
350
[email protected]233567d2013-02-27 20:22:02351void Shell::ActivateContents(WebContents* contents) {
352 contents->GetRenderViewHost()->Focus();
353}
354
355void Shell::DeactivateContents(WebContents* contents) {
356 contents->GetRenderViewHost()->Blur();
357}
358
[email protected]3eeacfa62013-07-23 09:23:15359void Shell::WorkerCrashed(WebContents* source) {
360 if (!CommandLine::ForCurrentProcess()->HasSwitch(switches::kDumpRenderTree))
361 return;
362 WebKitTestController::Get()->WorkerCrashed();
363}
364
[email protected]3142e5d2014-02-07 00:54:46365bool Shell::HandleContextMenu(const content::ContextMenuParams& params) {
366 return PlatformHandleContextMenu(params);
367}
368
[email protected]d0bb9952014-02-10 20:58:26369void Shell::WebContentsFocused(WebContents* contents) {
370#if defined(TOOLKIT_VIEWS)
371 PlatformWebContentsFocused(contents);
372#endif
373}
374
[email protected]1ef02d242013-10-07 16:18:53375void Shell::TitleWasSet(NavigationEntry* entry, bool explicit_set) {
376 if (entry)
377 PlatformSetTitle(entry->GetTitle());
[email protected]aecc085b2012-06-01 18:15:53378}
379
[email protected]06c253012014-04-16 18:35:33380void Shell::InnerShowDevTools(const std::string& settings,
381 const std::string& frontend_url) {
[email protected]fee9eca02014-02-14 19:24:40382 if (!devtools_frontend_) {
[email protected]06c253012014-04-16 18:35:33383 devtools_frontend_ = ShellDevToolsFrontend::Show(
384 web_contents(), settings, frontend_url);
[email protected]fee9eca02014-02-14 19:24:40385 devtools_observer_.reset(new DevToolsWebContentsObserver(
386 this, devtools_frontend_->frontend_shell()->web_contents()));
387 }
388
389 devtools_frontend_->Activate();
390 devtools_frontend_->Focus();
391}
392
[email protected]7fff43e2013-05-21 20:21:10393void Shell::OnDevToolsWebContentsDestroyed() {
394 devtools_observer_.reset();
395 devtools_frontend_ = NULL;
396}
397
[email protected]9fbd3f862011-09-20 23:31:34398} // namespace content