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();
126 base::MessageLoop::current()->RunUntilIdle();
129 void Shell::SetShellCreatedCallback(
130 base::Callback
<void(Shell
*)> shell_created_callback
) {
131 DCHECK(shell_created_callback_
.is_null());
132 shell_created_callback_
= shell_created_callback
;
135 Shell
* Shell::FromRenderViewHost(RenderViewHost
* rvh
) {
136 for (size_t i
= 0; i
< windows_
.size(); ++i
) {
137 if (windows_
[i
]->web_contents() &&
138 windows_
[i
]->web_contents()->GetRenderViewHost() == rvh
) {
146 void Shell::Initialize() {
148 gfx::Size(kDefaultTestWindowWidthDip
, kDefaultTestWindowHeightDip
));
151 gfx::Size
Shell::AdjustWindowSize(const gfx::Size
& initial_size
) {
152 if (!initial_size
.IsEmpty())
154 return gfx::Size(kDefaultTestWindowWidthDip
, kDefaultTestWindowHeightDip
);
157 Shell
* Shell::CreateNewWindow(BrowserContext
* browser_context
,
159 SiteInstance
* site_instance
,
161 const gfx::Size
& initial_size
) {
162 WebContents::CreateParams
create_params(browser_context
, site_instance
);
163 create_params
.routing_id
= routing_id
;
164 create_params
.initial_size
= AdjustWindowSize(initial_size
);
165 WebContents
* web_contents
= WebContents::Create(create_params
);
166 Shell
* shell
= CreateShell(web_contents
, create_params
.initial_size
);
172 void Shell::LoadURL(const GURL
& url
) {
173 LoadURLForFrame(url
, std::string());
176 void Shell::LoadURLForFrame(const GURL
& url
, const std::string
& frame_name
) {
177 NavigationController::LoadURLParams
params(url
);
178 params
.transition_type
= PageTransitionFromInt(
179 PAGE_TRANSITION_TYPED
| PAGE_TRANSITION_FROM_ADDRESS_BAR
);
180 params
.frame_name
= frame_name
;
181 web_contents_
->GetController().LoadURLWithParams(params
);
182 web_contents_
->GetView()->Focus();
185 void Shell::AddNewContents(WebContents
* source
,
186 WebContents
* new_contents
,
187 WindowOpenDisposition disposition
,
188 const gfx::Rect
& initial_pos
,
191 CreateShell(new_contents
, AdjustWindowSize(initial_pos
.size()));
192 if (CommandLine::ForCurrentProcess()->HasSwitch(switches::kDumpRenderTree
))
193 NotifyDoneForwarder::CreateForWebContents(new_contents
);
196 void Shell::GoBackOrForward(int offset
) {
197 web_contents_
->GetController().GoToOffset(offset
);
198 web_contents_
->GetView()->Focus();
201 void Shell::Reload() {
202 web_contents_
->GetController().Reload(false);
203 web_contents_
->GetView()->Focus();
207 web_contents_
->Stop();
208 web_contents_
->GetView()->Focus();
211 void Shell::UpdateNavigationControls() {
212 int current_index
= web_contents_
->GetController().GetCurrentEntryIndex();
213 int max_index
= web_contents_
->GetController().GetEntryCount() - 1;
215 PlatformEnableUIControl(BACK_BUTTON
, current_index
> 0);
216 PlatformEnableUIControl(FORWARD_BUTTON
, current_index
< max_index
);
217 PlatformEnableUIControl(STOP_BUTTON
, web_contents_
->IsLoading());
220 void Shell::ShowDevTools() {
221 if (devtools_frontend_
) {
222 devtools_frontend_
->Focus();
225 devtools_frontend_
= ShellDevToolsFrontend::Show(web_contents());
226 devtools_observer_
.reset(new DevToolsWebContentsObserver(
227 this, devtools_frontend_
->frontend_shell()->web_contents()));
230 void Shell::CloseDevTools() {
231 if (!devtools_frontend_
)
233 devtools_observer_
.reset();
234 devtools_frontend_
->Close();
235 devtools_frontend_
= NULL
;
238 gfx::NativeView
Shell::GetContentView() {
241 return web_contents_
->GetView()->GetNativeView();
244 WebContents
* Shell::OpenURLFromTab(WebContents
* source
,
245 const OpenURLParams
& params
) {
246 // CURRENT_TAB is the only one we implement for now.
247 if (params
.disposition
!= CURRENT_TAB
)
249 NavigationController::LoadURLParams
load_url_params(params
.url
);
250 load_url_params
.referrer
= params
.referrer
;
251 load_url_params
.transition_type
= params
.transition
;
252 load_url_params
.extra_headers
= params
.extra_headers
;
253 load_url_params
.should_replace_current_entry
=
254 params
.should_replace_current_entry
;
256 if (params
.transferred_global_request_id
!= GlobalRequestID()) {
257 load_url_params
.is_renderer_initiated
= params
.is_renderer_initiated
;
258 load_url_params
.transferred_global_request_id
=
259 params
.transferred_global_request_id
;
260 } else if (params
.is_renderer_initiated
) {
261 load_url_params
.is_renderer_initiated
= true;
264 source
->GetController().LoadURLWithParams(load_url_params
);
268 void Shell::LoadingStateChanged(WebContents
* source
) {
269 UpdateNavigationControls();
270 PlatformSetIsLoading(source
->IsLoading());
273 void Shell::ToggleFullscreenModeForTab(WebContents
* web_contents
,
274 bool enter_fullscreen
) {
275 #if defined(OS_ANDROID)
276 PlatformToggleFullscreenModeForTab(web_contents
, enter_fullscreen
);
278 if (!CommandLine::ForCurrentProcess()->HasSwitch(switches::kDumpRenderTree
))
280 if (is_fullscreen_
!= enter_fullscreen
) {
281 is_fullscreen_
= enter_fullscreen
;
282 web_contents
->GetRenderViewHost()->WasResized();
286 bool Shell::IsFullscreenForTabOrPending(const WebContents
* web_contents
) const {
287 #if defined(OS_ANDROID)
288 return PlatformIsFullscreenForTabOrPending(web_contents
);
290 return is_fullscreen_
;
294 void Shell::RequestToLockMouse(WebContents
* web_contents
,
296 bool last_unlocked_by_target
) {
297 web_contents
->GotResponseToLockMouseRequest(true);
300 void Shell::CloseContents(WebContents
* source
) {
304 bool Shell::CanOverscrollContent() const {
305 #if defined(USE_AURA)
312 void Shell::DidNavigateMainFramePostCommit(WebContents
* web_contents
) {
313 PlatformSetAddressBarURL(web_contents
->GetLastCommittedURL());
316 JavaScriptDialogManager
* Shell::GetJavaScriptDialogManager() {
317 if (!dialog_manager_
)
318 dialog_manager_
.reset(new ShellJavaScriptDialogManager());
319 return dialog_manager_
.get();
322 bool Shell::AddMessageToConsole(WebContents
* source
,
324 const string16
& message
,
326 const string16
& source_id
) {
327 return CommandLine::ForCurrentProcess()->HasSwitch(switches::kDumpRenderTree
);
330 void Shell::RendererUnresponsive(WebContents
* source
) {
331 if (!CommandLine::ForCurrentProcess()->HasSwitch(switches::kDumpRenderTree
))
333 WebKitTestController::Get()->RendererUnresponsive();
336 void Shell::ActivateContents(WebContents
* contents
) {
337 contents
->GetRenderViewHost()->Focus();
340 void Shell::DeactivateContents(WebContents
* contents
) {
341 contents
->GetRenderViewHost()->Blur();
344 void Shell::WorkerCrashed(WebContents
* source
) {
345 if (!CommandLine::ForCurrentProcess()->HasSwitch(switches::kDumpRenderTree
))
347 WebKitTestController::Get()->WorkerCrashed();
350 void Shell::TitleWasSet(NavigationEntry
* entry
, bool explicit_set
) {
352 PlatformSetTitle(entry
->GetTitle());
355 void Shell::OnDevToolsWebContentsDestroyed() {
356 devtools_observer_
.reset();
357 devtools_frontend_
= NULL
;
360 } // namespace content