Roll src/third_party/skia 2440fcd:4de8c3a
[chromium-blink-merge.git] / content / shell / browser / shell.cc
blobb273931d361dd5ce9265fe85ec405473f9994df8
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/location.h"
10 #include "base/single_thread_task_runner.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 "base/thread_task_runner_handle.h"
16 #include "content/public/browser/devtools_agent_host.h"
17 #include "content/public/browser/navigation_controller.h"
18 #include "content/public/browser/navigation_entry.h"
19 #include "content/public/browser/render_view_host.h"
20 #include "content/public/browser/web_contents.h"
21 #include "content/public/browser/web_contents_observer.h"
22 #include "content/public/common/renderer_preferences.h"
23 #include "content/shell/browser/blink_test_controller.h"
24 #include "content/shell/browser/layout_test/layout_test_bluetooth_chooser_factory.h"
25 #include "content/shell/browser/layout_test/layout_test_devtools_frontend.h"
26 #include "content/shell/browser/layout_test/layout_test_javascript_dialog_manager.h"
27 #include "content/shell/browser/notify_done_forwarder.h"
28 #include "content/shell/browser/shell_browser_main_parts.h"
29 #include "content/shell/browser/shell_content_browser_client.h"
30 #include "content/shell/browser/shell_devtools_frontend.h"
31 #include "content/shell/browser/shell_javascript_dialog_manager.h"
32 #include "content/shell/common/shell_messages.h"
33 #include "content/shell/common/shell_switches.h"
35 namespace content {
37 const int kDefaultTestWindowWidthDip = 800;
38 const int kDefaultTestWindowHeightDip = 600;
40 std::vector<Shell*> Shell::windows_;
41 base::Callback<void(Shell*)> Shell::shell_created_callback_;
43 bool Shell::quit_message_loop_ = true;
45 class Shell::DevToolsWebContentsObserver : public WebContentsObserver {
46 public:
47 DevToolsWebContentsObserver(Shell* shell, WebContents* web_contents)
48 : WebContentsObserver(web_contents),
49 shell_(shell) {
52 // WebContentsObserver
53 void WebContentsDestroyed() override {
54 shell_->OnDevToolsWebContentsDestroyed();
57 private:
58 Shell* shell_;
60 DISALLOW_COPY_AND_ASSIGN(DevToolsWebContentsObserver);
63 Shell::Shell(WebContents* web_contents)
64 : WebContentsObserver(web_contents),
65 devtools_frontend_(NULL),
66 is_fullscreen_(false),
67 window_(NULL),
68 url_edit_view_(NULL),
69 headless_(false) {
70 const base::CommandLine& command_line =
71 *base::CommandLine::ForCurrentProcess();
72 if (command_line.HasSwitch(switches::kRunLayoutTest))
73 headless_ = true;
74 windows_.push_back(this);
76 if (!shell_created_callback_.is_null()) {
77 shell_created_callback_.Run(this);
78 shell_created_callback_.Reset();
82 Shell::~Shell() {
83 PlatformCleanUp();
85 for (size_t i = 0; i < windows_.size(); ++i) {
86 if (windows_[i] == this) {
87 windows_.erase(windows_.begin() + i);
88 break;
92 if (windows_.empty() && quit_message_loop_) {
93 if (headless_)
94 PlatformExit();
95 base::ThreadTaskRunnerHandle::Get()->PostTask(
96 FROM_HERE, 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 (base::CommandLine::ForCurrentProcess()->HasSwitch(
113 switches::kRunLayoutTest)) {
114 web_contents->GetMutableRendererPrefs()->use_custom_colors = false;
115 web_contents->GetRenderViewHost()->SyncRendererPrefs();
118 return shell;
121 void Shell::CloseAllWindows() {
122 base::AutoReset<bool> auto_reset(&quit_message_loop_, false);
123 DevToolsAgentHost::DetachAllClients();
124 std::vector<Shell*> open_windows(windows_);
125 for (size_t i = 0; i < open_windows.size(); ++i)
126 open_windows[i]->Close();
127 base::MessageLoop::current()->RunUntilIdle();
128 PlatformExit();
131 void Shell::SetShellCreatedCallback(
132 base::Callback<void(Shell*)> shell_created_callback) {
133 DCHECK(shell_created_callback_.is_null());
134 shell_created_callback_ = shell_created_callback;
137 Shell* Shell::FromRenderViewHost(RenderViewHost* rvh) {
138 for (size_t i = 0; i < windows_.size(); ++i) {
139 if (windows_[i]->web_contents() &&
140 windows_[i]->web_contents()->GetRenderViewHost() == rvh) {
141 return windows_[i];
144 return NULL;
147 // static
148 void Shell::Initialize() {
149 PlatformInitialize(GetShellDefaultSize());
152 gfx::Size Shell::AdjustWindowSize(const gfx::Size& initial_size) {
153 if (!initial_size.IsEmpty())
154 return initial_size;
155 return GetShellDefaultSize();
158 Shell* Shell::CreateNewWindow(BrowserContext* browser_context,
159 const GURL& url,
160 SiteInstance* site_instance,
161 const gfx::Size& initial_size) {
162 WebContents::CreateParams create_params(browser_context, site_instance);
163 create_params.initial_size = AdjustWindowSize(initial_size);
164 WebContents* web_contents = WebContents::Create(create_params);
165 Shell* shell = CreateShell(web_contents, create_params.initial_size);
166 if (!url.is_empty())
167 shell->LoadURL(url);
168 return shell;
171 void Shell::LoadURL(const GURL& url) {
172 LoadURLForFrame(url, std::string());
175 void Shell::LoadURLForFrame(const GURL& url, const std::string& frame_name) {
176 NavigationController::LoadURLParams params(url);
177 params.transition_type = ui::PageTransitionFromInt(
178 ui::PAGE_TRANSITION_TYPED | ui::PAGE_TRANSITION_FROM_ADDRESS_BAR);
179 params.frame_name = frame_name;
180 web_contents_->GetController().LoadURLWithParams(params);
181 web_contents_->Focus();
184 void Shell::LoadDataWithBaseURL(const GURL& url, const std::string& data,
185 const GURL& base_url) {
186 const GURL data_url = GURL("data:text/html;charset=utf-8," + data);
187 NavigationController::LoadURLParams params(data_url);
188 params.load_type = NavigationController::LOAD_TYPE_DATA;
189 params.base_url_for_data_url = base_url;
190 params.virtual_url_for_data_url = url;
191 params.override_user_agent = NavigationController::UA_OVERRIDE_FALSE;
192 web_contents_->GetController().LoadURLWithParams(params);
193 web_contents_->Focus();
196 void Shell::AddNewContents(WebContents* source,
197 WebContents* new_contents,
198 WindowOpenDisposition disposition,
199 const gfx::Rect& initial_rect,
200 bool user_gesture,
201 bool* was_blocked) {
202 CreateShell(new_contents, AdjustWindowSize(initial_rect.size()));
203 if (base::CommandLine::ForCurrentProcess()->HasSwitch(
204 switches::kRunLayoutTest))
205 NotifyDoneForwarder::CreateForWebContents(new_contents);
208 void Shell::GoBackOrForward(int offset) {
209 web_contents_->GetController().GoToOffset(offset);
210 web_contents_->Focus();
213 void Shell::Reload() {
214 web_contents_->GetController().Reload(false);
215 web_contents_->Focus();
218 void Shell::Stop() {
219 web_contents_->Stop();
220 web_contents_->Focus();
223 void Shell::UpdateNavigationControls(bool to_different_document) {
224 int current_index = web_contents_->GetController().GetCurrentEntryIndex();
225 int max_index = web_contents_->GetController().GetEntryCount() - 1;
227 PlatformEnableUIControl(BACK_BUTTON, current_index > 0);
228 PlatformEnableUIControl(FORWARD_BUTTON, current_index < max_index);
229 PlatformEnableUIControl(STOP_BUTTON,
230 to_different_document && web_contents_->IsLoading());
233 void Shell::ShowDevTools() {
234 InnerShowDevTools();
237 void Shell::ShowDevToolsForElementAt(int x, int y) {
238 InnerShowDevTools();
239 devtools_frontend_->InspectElementAt(x, y);
242 void Shell::CloseDevTools() {
243 if (!devtools_frontend_)
244 return;
245 devtools_observer_.reset();
246 devtools_frontend_->Close();
247 devtools_frontend_ = NULL;
250 gfx::NativeView Shell::GetContentView() {
251 if (!web_contents_)
252 return NULL;
253 return web_contents_->GetNativeView();
256 WebContents* Shell::OpenURLFromTab(WebContents* source,
257 const OpenURLParams& params) {
258 // CURRENT_TAB is the only one we implement for now.
259 if (params.disposition != CURRENT_TAB)
260 return NULL;
261 NavigationController::LoadURLParams load_url_params(params.url);
262 load_url_params.source_site_instance = params.source_site_instance;
263 load_url_params.referrer = params.referrer;
264 load_url_params.frame_tree_node_id = params.frame_tree_node_id;
265 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;
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;
278 source->GetController().LoadURLWithParams(load_url_params);
279 return source;
282 void Shell::LoadingStateChanged(WebContents* source,
283 bool to_different_document) {
284 UpdateNavigationControls(to_different_document);
285 PlatformSetIsLoading(source->IsLoading());
288 void Shell::EnterFullscreenModeForTab(WebContents* web_contents,
289 const GURL& origin) {
290 ToggleFullscreenModeForTab(web_contents, true);
293 void Shell::ExitFullscreenModeForTab(WebContents* web_contents) {
294 ToggleFullscreenModeForTab(web_contents, false);
297 void Shell::ToggleFullscreenModeForTab(WebContents* web_contents,
298 bool enter_fullscreen) {
299 #if defined(OS_ANDROID)
300 PlatformToggleFullscreenModeForTab(web_contents, enter_fullscreen);
301 #endif
302 if (!base::CommandLine::ForCurrentProcess()->HasSwitch(
303 switches::kRunLayoutTest))
304 return;
305 if (is_fullscreen_ != enter_fullscreen) {
306 is_fullscreen_ = enter_fullscreen;
307 web_contents->GetRenderViewHost()->WasResized();
311 bool Shell::IsFullscreenForTabOrPending(const WebContents* web_contents) const {
312 #if defined(OS_ANDROID)
313 return PlatformIsFullscreenForTabOrPending(web_contents);
314 #else
315 return is_fullscreen_;
316 #endif
319 blink::WebDisplayMode Shell::GetDisplayMode(
320 const WebContents* web_contents) const {
321 // TODO : should return blink::WebDisplayModeFullscreen wherever user puts
322 // a browser window into fullscreen (not only in case of renderer-initiated
323 // fullscreen mode): crbug.com/476874.
324 return IsFullscreenForTabOrPending(web_contents) ?
325 blink::WebDisplayModeFullscreen : blink::WebDisplayModeBrowser;
328 void Shell::RequestToLockMouse(WebContents* web_contents,
329 bool user_gesture,
330 bool last_unlocked_by_target) {
331 web_contents->GotResponseToLockMouseRequest(true);
334 void Shell::CloseContents(WebContents* source) {
335 Close();
338 bool Shell::CanOverscrollContent() const {
339 #if defined(USE_AURA)
340 return true;
341 #else
342 return false;
343 #endif
346 void Shell::DidNavigateMainFramePostCommit(WebContents* web_contents) {
347 PlatformSetAddressBarURL(web_contents->GetLastCommittedURL());
350 JavaScriptDialogManager* Shell::GetJavaScriptDialogManager(
351 WebContents* source) {
352 if (!dialog_manager_) {
353 const base::CommandLine& command_line =
354 *base::CommandLine::ForCurrentProcess();
355 dialog_manager_.reset(command_line.HasSwitch(switches::kRunLayoutTest)
356 ? new LayoutTestJavaScriptDialogManager
357 : new ShellJavaScriptDialogManager);
359 return dialog_manager_.get();
362 scoped_ptr<BluetoothChooser> Shell::RunBluetoothChooser(
363 WebContents* web_contents,
364 const BluetoothChooser::EventHandler& event_handler,
365 const GURL& origin) {
366 const base::CommandLine& command_line =
367 *base::CommandLine::ForCurrentProcess();
368 if (command_line.HasSwitch(switches::kRunLayoutTest)) {
369 return BlinkTestController::Get()->RunBluetoothChooser(
370 web_contents, event_handler, origin);
372 return nullptr;
375 bool Shell::AddMessageToConsole(WebContents* source,
376 int32 level,
377 const base::string16& message,
378 int32 line_no,
379 const base::string16& source_id) {
380 return base::CommandLine::ForCurrentProcess()->HasSwitch(
381 switches::kRunLayoutTest);
384 void Shell::RendererUnresponsive(WebContents* source) {
385 if (!base::CommandLine::ForCurrentProcess()->HasSwitch(
386 switches::kRunLayoutTest))
387 return;
388 BlinkTestController::Get()->RendererUnresponsive();
391 void Shell::ActivateContents(WebContents* contents) {
392 contents->GetRenderViewHost()->Focus();
395 void Shell::DeactivateContents(WebContents* contents) {
396 contents->GetRenderViewHost()->Blur();
399 bool Shell::HandleContextMenu(const content::ContextMenuParams& params) {
400 return PlatformHandleContextMenu(params);
403 gfx::Size Shell::GetShellDefaultSize() {
404 static gfx::Size default_shell_size;
405 if (!default_shell_size.IsEmpty())
406 return default_shell_size;
407 base::CommandLine* command_line = base::CommandLine::ForCurrentProcess();
408 if (command_line->HasSwitch(switches::kContentShellHostWindowSize)) {
409 const std::string size_str = command_line->GetSwitchValueASCII(
410 switches::kContentShellHostWindowSize);
411 int width, height;
412 CHECK_EQ(2, sscanf(size_str.c_str(), "%dx%d", &width, &height));
413 default_shell_size = gfx::Size(width, height);
414 } else {
415 default_shell_size = gfx::Size(
416 kDefaultTestWindowWidthDip, kDefaultTestWindowHeightDip);
418 return default_shell_size;
421 void Shell::TitleWasSet(NavigationEntry* entry, bool explicit_set) {
422 if (entry)
423 PlatformSetTitle(entry->GetTitle());
426 void Shell::InnerShowDevTools() {
427 if (!devtools_frontend_) {
428 devtools_frontend_ = ShellDevToolsFrontend::Show(web_contents());
429 devtools_observer_.reset(new DevToolsWebContentsObserver(
430 this, devtools_frontend_->frontend_shell()->web_contents()));
433 devtools_frontend_->Activate();
434 devtools_frontend_->Focus();
437 void Shell::OnDevToolsWebContentsDestroyed() {
438 devtools_observer_.reset();
439 devtools_frontend_ = NULL;
442 } // namespace content