Refactor management of overview window copy lifetime into a separate class.
[chromium-blink-merge.git] / content / shell / browser / shell.cc
blob8f64cdcf8d43816eabbfe649639d08e8d2157b9a
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"
34 #endif
36 namespace content {
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 {
47 public:
48 DevToolsWebContentsObserver(Shell* shell, WebContents* web_contents)
49 : WebContentsObserver(web_contents),
50 shell_(shell) {
53 // WebContentsObserver
54 virtual void WebContentsDestroyed(WebContents* web_contents) OVERRIDE {
55 shell_->OnDevToolsWebContentsDestroyed();
58 private:
59 Shell* shell_;
61 DISALLOW_COPY_AND_ASSIGN(DevToolsWebContentsObserver);
64 Shell::Shell(WebContents* web_contents)
65 : WebContentsObserver(web_contents),
66 devtools_frontend_(NULL),
67 is_fullscreen_(false),
68 window_(NULL),
69 url_edit_view_(NULL),
70 #if defined(OS_WIN) && !defined(USE_AURA)
71 default_edit_wnd_proc_(0),
72 #endif
73 headless_(false) {
74 const CommandLine& command_line = *CommandLine::ForCurrentProcess();
75 if (command_line.HasSwitch(switches::kDumpRenderTree))
76 headless_ = true;
77 windows_.push_back(this);
79 if (!shell_created_callback_.is_null()) {
80 shell_created_callback_.Run(this);
81 shell_created_callback_.Reset();
85 Shell::~Shell() {
86 PlatformCleanUp();
88 for (size_t i = 0; i < windows_.size(); ++i) {
89 if (windows_[i] == this) {
90 windows_.erase(windows_.begin() + i);
91 break;
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();
117 return shell;
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) {
139 return windows_[i];
142 return NULL;
145 // static
146 void Shell::Initialize() {
147 PlatformInitialize(
148 gfx::Size(kDefaultTestWindowWidthDip, kDefaultTestWindowHeightDip));
151 gfx::Size Shell::AdjustWindowSize(const gfx::Size& initial_size) {
152 if (!initial_size.IsEmpty())
153 return initial_size;
154 return gfx::Size(kDefaultTestWindowWidthDip, kDefaultTestWindowHeightDip);
157 Shell* Shell::CreateNewWindow(BrowserContext* browser_context,
158 const GURL& url,
159 SiteInstance* site_instance,
160 int routing_id,
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);
167 if (!url.is_empty())
168 shell->LoadURL(url);
169 return shell;
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,
189 bool user_gesture,
190 bool* was_blocked) {
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();
206 void Shell::Stop() {
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();
223 return;
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_)
232 return;
233 devtools_observer_.reset();
234 devtools_frontend_->Close();
235 devtools_frontend_ = NULL;
238 gfx::NativeView Shell::GetContentView() {
239 if (!web_contents_)
240 return NULL;
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)
248 return NULL;
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);
265 return source;
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);
277 #endif
278 if (!CommandLine::ForCurrentProcess()->HasSwitch(switches::kDumpRenderTree))
279 return;
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);
289 #else
290 return is_fullscreen_;
291 #endif
294 void Shell::RequestToLockMouse(WebContents* web_contents,
295 bool user_gesture,
296 bool last_unlocked_by_target) {
297 web_contents->GotResponseToLockMouseRequest(true);
300 void Shell::CloseContents(WebContents* source) {
301 Close();
304 bool Shell::CanOverscrollContent() const {
305 #if defined(USE_AURA)
306 return true;
307 #else
308 return false;
309 #endif
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,
323 int32 level,
324 const string16& message,
325 int32 line_no,
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))
332 return;
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))
346 return;
347 WebKitTestController::Get()->WorkerCrashed();
350 void Shell::TitleWasSet(NavigationEntry* entry, bool explicit_set) {
351 if (entry)
352 PlatformSetTitle(entry->GetTitle());
355 void Shell::OnDevToolsWebContentsDestroyed() {
356 devtools_observer_.reset();
357 devtools_frontend_ = NULL;
360 } // namespace content