1 // Copyright 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.
5 #include "content/shell/browser/shell.h"
7 #include "base/auto_reset.h"
8 #include "base/command_line.h"
9 #include "base/message_loop/message_loop.h"
10 #include "base/path_service.h"
11 #include "base/strings/string_number_conversions.h"
12 #include "base/strings/string_util.h"
13 #include "base/strings/stringprintf.h"
14 #include "base/strings/utf_string_conversions.h"
15 #include "content/public/browser/devtools_manager.h"
16 #include "content/public/browser/navigation_controller.h"
17 #include "content/public/browser/navigation_entry.h"
18 #include "content/public/browser/render_view_host.h"
19 #include "content/public/browser/web_contents.h"
20 #include "content/public/browser/web_contents_observer.h"
21 #include "content/public/browser/web_contents_view.h"
22 #include "content/public/common/renderer_preferences.h"
23 #include "content/shell/browser/notify_done_forwarder.h"
24 #include "content/shell/browser/shell_browser_main_parts.h"
25 #include "content/shell/browser/shell_content_browser_client.h"
26 #include "content/shell/browser/shell_devtools_frontend.h"
27 #include "content/shell/browser/shell_javascript_dialog_manager.h"
28 #include "content/shell/browser/webkit_test_controller.h"
29 #include "content/shell/common/shell_messages.h"
30 #include "content/shell/common/shell_switches.h"
32 #if defined(USE_AURA) && !defined(TOOLKIT_VIEWS)
33 #include "content/shell/browser/shell_aura.h"
38 const int Shell::kDefaultTestWindowWidthDip
= 800;
39 const int Shell::kDefaultTestWindowHeightDip
= 600;
41 std::vector
<Shell
*> Shell::windows_
;
42 base::Callback
<void(Shell
*)> Shell::shell_created_callback_
;
44 bool Shell::quit_message_loop_
= true;
46 class Shell::DevToolsWebContentsObserver
: public WebContentsObserver
{
48 DevToolsWebContentsObserver(Shell
* shell
, WebContents
* web_contents
)
49 : WebContentsObserver(web_contents
),
53 // WebContentsObserver
54 virtual void WebContentsDestroyed(WebContents
* web_contents
) OVERRIDE
{
55 shell_
->OnDevToolsWebContentsDestroyed();
61 DISALLOW_COPY_AND_ASSIGN(DevToolsWebContentsObserver
);
64 Shell::Shell(WebContents
* web_contents
)
65 : WebContentsObserver(web_contents
),
66 devtools_frontend_(NULL
),
67 is_fullscreen_(false),
70 #if defined(OS_WIN) && !defined(USE_AURA)
71 default_edit_wnd_proc_(0),
74 const CommandLine
& command_line
= *CommandLine::ForCurrentProcess();
75 if (command_line
.HasSwitch(switches::kDumpRenderTree
))
77 windows_
.push_back(this);
79 if (!shell_created_callback_
.is_null()) {
80 shell_created_callback_
.Run(this);
81 shell_created_callback_
.Reset();
88 for (size_t i
= 0; i
< windows_
.size(); ++i
) {
89 if (windows_
[i
] == this) {
90 windows_
.erase(windows_
.begin() + i
);
95 if (windows_
.empty() && quit_message_loop_
)
96 base::MessageLoop::current()->PostTask(FROM_HERE
,
97 base::MessageLoop::QuitClosure());
100 Shell
* Shell::CreateShell(WebContents
* web_contents
,
101 const gfx::Size
& initial_size
) {
102 Shell
* shell
= new Shell(web_contents
);
103 shell
->PlatformCreateWindow(initial_size
.width(), initial_size
.height());
105 shell
->web_contents_
.reset(web_contents
);
106 web_contents
->SetDelegate(shell
);
108 shell
->PlatformSetContents();
110 shell
->PlatformResizeSubViews();
112 if (CommandLine::ForCurrentProcess()->HasSwitch(switches::kDumpRenderTree
)) {
113 web_contents
->GetMutableRendererPrefs()->use_custom_colors
= false;
114 web_contents
->GetRenderViewHost()->SyncRendererPrefs();
120 void Shell::CloseAllWindows() {
121 base::AutoReset
<bool> auto_reset(&quit_message_loop_
, false);
122 DevToolsManager::GetInstance()->CloseAllClientHosts();
123 std::vector
<Shell
*> open_windows(windows_
);
124 for (size_t i
= 0; i
< open_windows
.size(); ++i
)
125 open_windows
[i
]->Close();
127 base::MessageLoop::current()->RunUntilIdle();
130 void Shell::SetShellCreatedCallback(
131 base::Callback
<void(Shell
*)> shell_created_callback
) {
132 DCHECK(shell_created_callback_
.is_null());
133 shell_created_callback_
= shell_created_callback
;
136 Shell
* Shell::FromRenderViewHost(RenderViewHost
* rvh
) {
137 for (size_t i
= 0; i
< windows_
.size(); ++i
) {
138 if (windows_
[i
]->web_contents() &&
139 windows_
[i
]->web_contents()->GetRenderViewHost() == rvh
) {
147 void Shell::Initialize() {
149 gfx::Size(kDefaultTestWindowWidthDip
, kDefaultTestWindowHeightDip
));
152 gfx::Size
Shell::AdjustWindowSize(const gfx::Size
& initial_size
) {
153 if (!initial_size
.IsEmpty())
155 return gfx::Size(kDefaultTestWindowWidthDip
, kDefaultTestWindowHeightDip
);
158 Shell
* Shell::CreateNewWindow(BrowserContext
* browser_context
,
160 SiteInstance
* site_instance
,
162 const gfx::Size
& initial_size
) {
163 WebContents::CreateParams
create_params(browser_context
, site_instance
);
164 create_params
.routing_id
= routing_id
;
165 create_params
.initial_size
= AdjustWindowSize(initial_size
);
166 WebContents
* web_contents
= WebContents::Create(create_params
);
167 Shell
* shell
= CreateShell(web_contents
, create_params
.initial_size
);
173 void Shell::LoadURL(const GURL
& url
) {
174 LoadURLForFrame(url
, std::string());
177 void Shell::LoadURLForFrame(const GURL
& url
, const std::string
& frame_name
) {
178 NavigationController::LoadURLParams
params(url
);
179 params
.transition_type
= PageTransitionFromInt(
180 PAGE_TRANSITION_TYPED
| PAGE_TRANSITION_FROM_ADDRESS_BAR
);
181 params
.frame_name
= frame_name
;
182 web_contents_
->GetController().LoadURLWithParams(params
);
183 web_contents_
->GetView()->Focus();
186 void Shell::AddNewContents(WebContents
* source
,
187 WebContents
* new_contents
,
188 WindowOpenDisposition disposition
,
189 const gfx::Rect
& initial_pos
,
192 CreateShell(new_contents
, AdjustWindowSize(initial_pos
.size()));
193 if (CommandLine::ForCurrentProcess()->HasSwitch(switches::kDumpRenderTree
))
194 NotifyDoneForwarder::CreateForWebContents(new_contents
);
197 void Shell::GoBackOrForward(int offset
) {
198 web_contents_
->GetController().GoToOffset(offset
);
199 web_contents_
->GetView()->Focus();
202 void Shell::Reload() {
203 web_contents_
->GetController().Reload(false);
204 web_contents_
->GetView()->Focus();
208 web_contents_
->Stop();
209 web_contents_
->GetView()->Focus();
212 void Shell::UpdateNavigationControls() {
213 int current_index
= web_contents_
->GetController().GetCurrentEntryIndex();
214 int max_index
= web_contents_
->GetController().GetEntryCount() - 1;
216 PlatformEnableUIControl(BACK_BUTTON
, current_index
> 0);
217 PlatformEnableUIControl(FORWARD_BUTTON
, current_index
< max_index
);
218 PlatformEnableUIControl(STOP_BUTTON
, web_contents_
->IsLoading());
221 void Shell::ShowDevTools() {
222 if (devtools_frontend_
) {
223 devtools_frontend_
->Focus();
226 devtools_frontend_
= ShellDevToolsFrontend::Show(web_contents());
227 devtools_observer_
.reset(new DevToolsWebContentsObserver(
228 this, devtools_frontend_
->frontend_shell()->web_contents()));
231 void Shell::CloseDevTools() {
232 if (!devtools_frontend_
)
234 devtools_observer_
.reset();
235 devtools_frontend_
->Close();
236 devtools_frontend_
= NULL
;
239 gfx::NativeView
Shell::GetContentView() {
242 return web_contents_
->GetView()->GetNativeView();
245 WebContents
* Shell::OpenURLFromTab(WebContents
* source
,
246 const OpenURLParams
& params
) {
247 // CURRENT_TAB is the only one we implement for now.
248 if (params
.disposition
!= CURRENT_TAB
)
250 NavigationController::LoadURLParams
load_url_params(params
.url
);
251 load_url_params
.referrer
= params
.referrer
;
252 load_url_params
.frame_tree_node_id
= params
.frame_tree_node_id
;
253 load_url_params
.transition_type
= params
.transition
;
254 load_url_params
.extra_headers
= params
.extra_headers
;
255 load_url_params
.should_replace_current_entry
=
256 params
.should_replace_current_entry
;
258 if (params
.transferred_global_request_id
!= GlobalRequestID()) {
259 load_url_params
.is_renderer_initiated
= params
.is_renderer_initiated
;
260 load_url_params
.transferred_global_request_id
=
261 params
.transferred_global_request_id
;
262 } else if (params
.is_renderer_initiated
) {
263 load_url_params
.is_renderer_initiated
= true;
266 source
->GetController().LoadURLWithParams(load_url_params
);
270 void Shell::LoadingStateChanged(WebContents
* source
) {
271 UpdateNavigationControls();
272 PlatformSetIsLoading(source
->IsLoading());
275 void Shell::ToggleFullscreenModeForTab(WebContents
* web_contents
,
276 bool enter_fullscreen
) {
277 #if defined(OS_ANDROID)
278 PlatformToggleFullscreenModeForTab(web_contents
, enter_fullscreen
);
280 if (!CommandLine::ForCurrentProcess()->HasSwitch(switches::kDumpRenderTree
))
282 if (is_fullscreen_
!= enter_fullscreen
) {
283 is_fullscreen_
= enter_fullscreen
;
284 web_contents
->GetRenderViewHost()->WasResized();
288 bool Shell::IsFullscreenForTabOrPending(const WebContents
* web_contents
) const {
289 #if defined(OS_ANDROID)
290 return PlatformIsFullscreenForTabOrPending(web_contents
);
292 return is_fullscreen_
;
296 void Shell::RequestToLockMouse(WebContents
* web_contents
,
298 bool last_unlocked_by_target
) {
299 web_contents
->GotResponseToLockMouseRequest(true);
302 void Shell::CloseContents(WebContents
* source
) {
306 bool Shell::CanOverscrollContent() const {
307 #if defined(USE_AURA)
314 void Shell::DidNavigateMainFramePostCommit(WebContents
* web_contents
) {
315 PlatformSetAddressBarURL(web_contents
->GetLastCommittedURL());
318 JavaScriptDialogManager
* Shell::GetJavaScriptDialogManager() {
319 if (!dialog_manager_
)
320 dialog_manager_
.reset(new ShellJavaScriptDialogManager());
321 return dialog_manager_
.get();
324 bool Shell::AddMessageToConsole(WebContents
* source
,
326 const base::string16
& message
,
328 const base::string16
& source_id
) {
329 return CommandLine::ForCurrentProcess()->HasSwitch(switches::kDumpRenderTree
);
332 void Shell::RendererUnresponsive(WebContents
* source
) {
333 if (!CommandLine::ForCurrentProcess()->HasSwitch(switches::kDumpRenderTree
))
335 WebKitTestController::Get()->RendererUnresponsive();
338 void Shell::ActivateContents(WebContents
* contents
) {
339 contents
->GetRenderViewHost()->Focus();
342 void Shell::DeactivateContents(WebContents
* contents
) {
343 contents
->GetRenderViewHost()->Blur();
346 void Shell::WorkerCrashed(WebContents
* source
) {
347 if (!CommandLine::ForCurrentProcess()->HasSwitch(switches::kDumpRenderTree
))
349 WebKitTestController::Get()->WorkerCrashed();
352 void Shell::TitleWasSet(NavigationEntry
* entry
, bool explicit_set
) {
354 PlatformSetTitle(entry
->GetTitle());
357 void Shell::OnDevToolsWebContentsDestroyed() {
358 devtools_observer_
.reset();
359 devtools_frontend_
= NULL
;
362 } // namespace content