shell.cc revision a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7
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. 4 5#include "content/shell/browser/shell.h" 6 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" 31 32#if defined(USE_AURA) && !defined(TOOLKIT_VIEWS) 33#include "content/shell/browser/shell_aura.h" 34#endif 35 36namespace content { 37 38const int Shell::kDefaultTestWindowWidthDip = 800; 39const int Shell::kDefaultTestWindowHeightDip = 600; 40 41std::vector<Shell*> Shell::windows_; 42base::Callback<void(Shell*)> Shell::shell_created_callback_; 43 44bool Shell::quit_message_loop_ = true; 45 46class Shell::DevToolsWebContentsObserver : public WebContentsObserver { 47 public: 48 DevToolsWebContentsObserver(Shell* shell, WebContents* web_contents) 49 : WebContentsObserver(web_contents), 50 shell_(shell) { 51 } 52 53 // WebContentsObserver 54 virtual void WebContentsDestroyed(WebContents* web_contents) OVERRIDE { 55 shell_->OnDevToolsWebContentsDestroyed(); 56 } 57 58 private: 59 Shell* shell_; 60 61 DISALLOW_COPY_AND_ASSIGN(DevToolsWebContentsObserver); 62}; 63 64Shell::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); 78 79 if (!shell_created_callback_.is_null()) { 80 shell_created_callback_.Run(this); 81 shell_created_callback_.Reset(); 82 } 83} 84 85Shell::~Shell() { 86 PlatformCleanUp(); 87 88 for (size_t i = 0; i < windows_.size(); ++i) { 89 if (windows_[i] == this) { 90 windows_.erase(windows_.begin() + i); 91 break; 92 } 93 } 94 95 if (windows_.empty() && quit_message_loop_) 96 base::MessageLoop::current()->PostTask(FROM_HERE, 97 base::MessageLoop::QuitClosure()); 98} 99 100Shell* 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()); 104 105 shell->web_contents_.reset(web_contents); 106 web_contents->SetDelegate(shell); 107 108 shell->PlatformSetContents(); 109 110 shell->PlatformResizeSubViews(); 111 112 if (CommandLine::ForCurrentProcess()->HasSwitch(switches::kDumpRenderTree)) { 113 web_contents->GetMutableRendererPrefs()->use_custom_colors = false; 114 web_contents->GetRenderViewHost()->SyncRendererPrefs(); 115 } 116 117 return shell; 118} 119 120void 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 PlatformExit(); 127 base::MessageLoop::current()->RunUntilIdle(); 128} 129 130void Shell::SetShellCreatedCallback( 131 base::Callback<void(Shell*)> shell_created_callback) { 132 DCHECK(shell_created_callback_.is_null()); 133 shell_created_callback_ = shell_created_callback; 134} 135 136Shell* 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) { 140 return windows_[i]; 141 } 142 } 143 return NULL; 144} 145 146// static 147void Shell::Initialize() { 148 PlatformInitialize( 149 gfx::Size(kDefaultTestWindowWidthDip, kDefaultTestWindowHeightDip)); 150} 151 152gfx::Size Shell::AdjustWindowSize(const gfx::Size& initial_size) { 153 if (!initial_size.IsEmpty()) 154 return initial_size; 155 return gfx::Size(kDefaultTestWindowWidthDip, kDefaultTestWindowHeightDip); 156} 157 158Shell* Shell::CreateNewWindow(BrowserContext* browser_context, 159 const GURL& url, 160 SiteInstance* site_instance, 161 int routing_id, 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); 168 if (!url.is_empty()) 169 shell->LoadURL(url); 170 return shell; 171} 172 173void Shell::LoadURL(const GURL& url) { 174 LoadURLForFrame(url, std::string()); 175} 176 177void 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(); 184} 185 186void Shell::AddNewContents(WebContents* source, 187 WebContents* new_contents, 188 WindowOpenDisposition disposition, 189 const gfx::Rect& initial_pos, 190 bool user_gesture, 191 bool* was_blocked) { 192 CreateShell(new_contents, AdjustWindowSize(initial_pos.size())); 193 if (CommandLine::ForCurrentProcess()->HasSwitch(switches::kDumpRenderTree)) 194 NotifyDoneForwarder::CreateForWebContents(new_contents); 195} 196 197void Shell::GoBackOrForward(int offset) { 198 web_contents_->GetController().GoToOffset(offset); 199 web_contents_->GetView()->Focus(); 200} 201 202void Shell::Reload() { 203 web_contents_->GetController().Reload(false); 204 web_contents_->GetView()->Focus(); 205} 206 207void Shell::Stop() { 208 web_contents_->Stop(); 209 web_contents_->GetView()->Focus(); 210} 211 212void Shell::UpdateNavigationControls() { 213 int current_index = web_contents_->GetController().GetCurrentEntryIndex(); 214 int max_index = web_contents_->GetController().GetEntryCount() - 1; 215 216 PlatformEnableUIControl(BACK_BUTTON, current_index > 0); 217 PlatformEnableUIControl(FORWARD_BUTTON, current_index < max_index); 218 PlatformEnableUIControl(STOP_BUTTON, web_contents_->IsLoading()); 219} 220 221void Shell::ShowDevTools() { 222 if (devtools_frontend_) { 223 devtools_frontend_->Focus(); 224 return; 225 } 226 devtools_frontend_ = ShellDevToolsFrontend::Show(web_contents()); 227 devtools_observer_.reset(new DevToolsWebContentsObserver( 228 this, devtools_frontend_->frontend_shell()->web_contents())); 229} 230 231void Shell::CloseDevTools() { 232 if (!devtools_frontend_) 233 return; 234 devtools_observer_.reset(); 235 devtools_frontend_->Close(); 236 devtools_frontend_ = NULL; 237} 238 239gfx::NativeView Shell::GetContentView() { 240 if (!web_contents_) 241 return NULL; 242 return web_contents_->GetView()->GetNativeView(); 243} 244 245WebContents* 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) 249 return NULL; 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; 257 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; 264 } 265 266 source->GetController().LoadURLWithParams(load_url_params); 267 return source; 268} 269 270void Shell::LoadingStateChanged(WebContents* source) { 271 UpdateNavigationControls(); 272 PlatformSetIsLoading(source->IsLoading()); 273} 274 275void Shell::ToggleFullscreenModeForTab(WebContents* web_contents, 276 bool enter_fullscreen) { 277#if defined(OS_ANDROID) 278 PlatformToggleFullscreenModeForTab(web_contents, enter_fullscreen); 279#endif 280 if (!CommandLine::ForCurrentProcess()->HasSwitch(switches::kDumpRenderTree)) 281 return; 282 if (is_fullscreen_ != enter_fullscreen) { 283 is_fullscreen_ = enter_fullscreen; 284 web_contents->GetRenderViewHost()->WasResized(); 285 } 286} 287 288bool Shell::IsFullscreenForTabOrPending(const WebContents* web_contents) const { 289#if defined(OS_ANDROID) 290 return PlatformIsFullscreenForTabOrPending(web_contents); 291#else 292 return is_fullscreen_; 293#endif 294} 295 296void Shell::RequestToLockMouse(WebContents* web_contents, 297 bool user_gesture, 298 bool last_unlocked_by_target) { 299 web_contents->GotResponseToLockMouseRequest(true); 300} 301 302void Shell::CloseContents(WebContents* source) { 303 Close(); 304} 305 306bool Shell::CanOverscrollContent() const { 307#if defined(USE_AURA) 308 return true; 309#else 310 return false; 311#endif 312} 313 314void Shell::DidNavigateMainFramePostCommit(WebContents* web_contents) { 315 PlatformSetAddressBarURL(web_contents->GetLastCommittedURL()); 316} 317 318JavaScriptDialogManager* Shell::GetJavaScriptDialogManager() { 319 if (!dialog_manager_) 320 dialog_manager_.reset(new ShellJavaScriptDialogManager()); 321 return dialog_manager_.get(); 322} 323 324bool Shell::AddMessageToConsole(WebContents* source, 325 int32 level, 326 const base::string16& message, 327 int32 line_no, 328 const base::string16& source_id) { 329 return CommandLine::ForCurrentProcess()->HasSwitch(switches::kDumpRenderTree); 330} 331 332void Shell::RendererUnresponsive(WebContents* source) { 333 if (!CommandLine::ForCurrentProcess()->HasSwitch(switches::kDumpRenderTree)) 334 return; 335 WebKitTestController::Get()->RendererUnresponsive(); 336} 337 338void Shell::ActivateContents(WebContents* contents) { 339 contents->GetRenderViewHost()->Focus(); 340} 341 342void Shell::DeactivateContents(WebContents* contents) { 343 contents->GetRenderViewHost()->Blur(); 344} 345 346void Shell::WorkerCrashed(WebContents* source) { 347 if (!CommandLine::ForCurrentProcess()->HasSwitch(switches::kDumpRenderTree)) 348 return; 349 WebKitTestController::Get()->WorkerCrashed(); 350} 351 352void Shell::TitleWasSet(NavigationEntry* entry, bool explicit_set) { 353 if (entry) 354 PlatformSetTitle(entry->GetTitle()); 355} 356 357void Shell::OnDevToolsWebContentsDestroyed() { 358 devtools_observer_.reset(); 359 devtools_frontend_ = NULL; 360} 361 362} // namespace content 363