Introduce the PlatformNotificationContext class.
[chromium-blink-merge.git] / content / shell / browser / shell.cc
blob89ae2a21cd25035df1c2988cce46f53c2c6c9486
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/strings/string_number_conversions.h"
11 #include "base/strings/string_util.h"
12 #include "base/strings/stringprintf.h"
13 #include "base/strings/utf_string_conversions.h"
14 #include "content/public/browser/devtools_agent_host.h"
15 #include "content/public/browser/navigation_controller.h"
16 #include "content/public/browser/navigation_entry.h"
17 #include "content/public/browser/render_view_host.h"
18 #include "content/public/browser/web_contents.h"
19 #include "content/public/browser/web_contents_observer.h"
20 #include "content/public/common/renderer_preferences.h"
21 #include "content/shell/browser/layout_test/layout_test_devtools_frontend.h"
22 #include "content/shell/browser/layout_test/layout_test_javascript_dialog_manager.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 namespace content {
34 const int kDefaultTestWindowWidthDip = 800;
35 const int kDefaultTestWindowHeightDip = 600;
37 std::vector<Shell*> Shell::windows_;
38 base::Callback<void(Shell*)> Shell::shell_created_callback_;
40 bool Shell::quit_message_loop_ = true;
42 class Shell::DevToolsWebContentsObserver : public WebContentsObserver {
43 public:
44 DevToolsWebContentsObserver(Shell* shell, WebContents* web_contents)
45 : WebContentsObserver(web_contents),
46 shell_(shell) {
49 // WebContentsObserver
50 void WebContentsDestroyed() override {
51 shell_->OnDevToolsWebContentsDestroyed();
54 private:
55 Shell* shell_;
57 DISALLOW_COPY_AND_ASSIGN(DevToolsWebContentsObserver);
60 Shell::Shell(WebContents* web_contents)
61 : WebContentsObserver(web_contents),
62 devtools_frontend_(NULL),
63 is_fullscreen_(false),
64 window_(NULL),
65 url_edit_view_(NULL),
66 headless_(false) {
67 const base::CommandLine& command_line =
68 *base::CommandLine::ForCurrentProcess();
69 if (command_line.HasSwitch(switches::kRunLayoutTest))
70 headless_ = true;
71 windows_.push_back(this);
73 if (!shell_created_callback_.is_null()) {
74 shell_created_callback_.Run(this);
75 shell_created_callback_.Reset();
79 Shell::~Shell() {
80 PlatformCleanUp();
82 for (size_t i = 0; i < windows_.size(); ++i) {
83 if (windows_[i] == this) {
84 windows_.erase(windows_.begin() + i);
85 break;
89 if (windows_.empty() && quit_message_loop_) {
90 if (headless_)
91 PlatformExit();
92 base::MessageLoop::current()->PostTask(FROM_HERE,
93 base::MessageLoop::QuitClosure());
97 Shell* Shell::CreateShell(WebContents* web_contents,
98 const gfx::Size& initial_size) {
99 Shell* shell = new Shell(web_contents);
100 shell->PlatformCreateWindow(initial_size.width(), initial_size.height());
102 shell->web_contents_.reset(web_contents);
103 web_contents->SetDelegate(shell);
105 shell->PlatformSetContents();
107 shell->PlatformResizeSubViews();
109 if (base::CommandLine::ForCurrentProcess()->HasSwitch(
110 switches::kRunLayoutTest)) {
111 web_contents->GetMutableRendererPrefs()->use_custom_colors = false;
112 web_contents->GetRenderViewHost()->SyncRendererPrefs();
115 return shell;
118 void Shell::CloseAllWindows() {
119 base::AutoReset<bool> auto_reset(&quit_message_loop_, false);
120 DevToolsAgentHost::DetachAllClients();
121 std::vector<Shell*> open_windows(windows_);
122 for (size_t i = 0; i < open_windows.size(); ++i)
123 open_windows[i]->Close();
124 PlatformExit();
125 base::MessageLoop::current()->RunUntilIdle();
128 void Shell::SetShellCreatedCallback(
129 base::Callback<void(Shell*)> shell_created_callback) {
130 DCHECK(shell_created_callback_.is_null());
131 shell_created_callback_ = shell_created_callback;
134 Shell* Shell::FromRenderViewHost(RenderViewHost* rvh) {
135 for (size_t i = 0; i < windows_.size(); ++i) {
136 if (windows_[i]->web_contents() &&
137 windows_[i]->web_contents()->GetRenderViewHost() == rvh) {
138 return windows_[i];
141 return NULL;
144 // static
145 void Shell::Initialize() {
146 PlatformInitialize(GetShellDefaultSize());
149 gfx::Size Shell::AdjustWindowSize(const gfx::Size& initial_size) {
150 if (!initial_size.IsEmpty())
151 return initial_size;
152 return GetShellDefaultSize();
155 Shell* Shell::CreateNewWindow(BrowserContext* browser_context,
156 const GURL& url,
157 SiteInstance* site_instance,
158 const gfx::Size& initial_size) {
159 WebContents::CreateParams create_params(browser_context, site_instance);
160 create_params.initial_size = AdjustWindowSize(initial_size);
161 WebContents* web_contents = WebContents::Create(create_params);
162 Shell* shell = CreateShell(web_contents, create_params.initial_size);
163 if (!url.is_empty())
164 shell->LoadURL(url);
165 return shell;
168 void Shell::LoadURL(const GURL& url) {
169 LoadURLForFrame(url, std::string());
172 void Shell::LoadURLForFrame(const GURL& url, const std::string& frame_name) {
173 NavigationController::LoadURLParams params(url);
174 params.transition_type = ui::PageTransitionFromInt(
175 ui::PAGE_TRANSITION_TYPED | ui::PAGE_TRANSITION_FROM_ADDRESS_BAR);
176 params.frame_name = frame_name;
177 web_contents_->GetController().LoadURLWithParams(params);
178 web_contents_->Focus();
181 void Shell::LoadDataWithBaseURL(const GURL& url, const std::string& data,
182 const GURL& base_url) {
183 const GURL data_url = GURL("data:text/html;charset=utf-8," + data);
184 NavigationController::LoadURLParams params(data_url);
185 params.load_type = NavigationController::LOAD_TYPE_DATA;
186 params.base_url_for_data_url = base_url;
187 params.virtual_url_for_data_url = url;
188 params.override_user_agent = NavigationController::UA_OVERRIDE_FALSE;
189 web_contents_->GetController().LoadURLWithParams(params);
190 web_contents_->Focus();
193 void Shell::AddNewContents(WebContents* source,
194 WebContents* new_contents,
195 WindowOpenDisposition disposition,
196 const gfx::Rect& initial_rect,
197 bool user_gesture,
198 bool* was_blocked) {
199 CreateShell(new_contents, AdjustWindowSize(initial_rect.size()));
200 if (base::CommandLine::ForCurrentProcess()->HasSwitch(
201 switches::kRunLayoutTest))
202 NotifyDoneForwarder::CreateForWebContents(new_contents);
205 void Shell::GoBackOrForward(int offset) {
206 web_contents_->GetController().GoToOffset(offset);
207 web_contents_->Focus();
210 void Shell::Reload() {
211 web_contents_->GetController().Reload(false);
212 web_contents_->Focus();
215 void Shell::Stop() {
216 web_contents_->Stop();
217 web_contents_->Focus();
220 void Shell::UpdateNavigationControls(bool to_different_document) {
221 int current_index = web_contents_->GetController().GetCurrentEntryIndex();
222 int max_index = web_contents_->GetController().GetEntryCount() - 1;
224 PlatformEnableUIControl(BACK_BUTTON, current_index > 0);
225 PlatformEnableUIControl(FORWARD_BUTTON, current_index < max_index);
226 PlatformEnableUIControl(STOP_BUTTON,
227 to_different_document && web_contents_->IsLoading());
230 void Shell::ShowDevTools() {
231 InnerShowDevTools();
234 void Shell::ShowDevToolsForElementAt(int x, int y) {
235 InnerShowDevTools();
236 devtools_frontend_->InspectElementAt(x, y);
239 void Shell::CloseDevTools() {
240 if (!devtools_frontend_)
241 return;
242 devtools_observer_.reset();
243 devtools_frontend_->Close();
244 devtools_frontend_ = NULL;
247 gfx::NativeView Shell::GetContentView() {
248 if (!web_contents_)
249 return NULL;
250 return web_contents_->GetNativeView();
253 WebContents* Shell::OpenURLFromTab(WebContents* source,
254 const OpenURLParams& params) {
255 // CURRENT_TAB is the only one we implement for now.
256 if (params.disposition != CURRENT_TAB)
257 return NULL;
258 NavigationController::LoadURLParams load_url_params(params.url);
259 load_url_params.source_site_instance = params.source_site_instance;
260 load_url_params.referrer = params.referrer;
261 load_url_params.frame_tree_node_id = params.frame_tree_node_id;
262 load_url_params.transition_type = params.transition;
263 load_url_params.extra_headers = params.extra_headers;
264 load_url_params.should_replace_current_entry =
265 params.should_replace_current_entry;
267 if (params.transferred_global_request_id != GlobalRequestID()) {
268 load_url_params.is_renderer_initiated = params.is_renderer_initiated;
269 load_url_params.transferred_global_request_id =
270 params.transferred_global_request_id;
271 } else if (params.is_renderer_initiated) {
272 load_url_params.is_renderer_initiated = true;
275 source->GetController().LoadURLWithParams(load_url_params);
276 return source;
279 void Shell::LoadingStateChanged(WebContents* source,
280 bool to_different_document) {
281 UpdateNavigationControls(to_different_document);
282 PlatformSetIsLoading(source->IsLoading());
285 void Shell::EnterFullscreenModeForTab(WebContents* web_contents,
286 const GURL& origin) {
287 ToggleFullscreenModeForTab(web_contents, true);
290 void Shell::ExitFullscreenModeForTab(WebContents* web_contents) {
291 ToggleFullscreenModeForTab(web_contents, false);
294 void Shell::ToggleFullscreenModeForTab(WebContents* web_contents,
295 bool enter_fullscreen) {
296 #if defined(OS_ANDROID)
297 PlatformToggleFullscreenModeForTab(web_contents, enter_fullscreen);
298 #endif
299 if (!base::CommandLine::ForCurrentProcess()->HasSwitch(
300 switches::kRunLayoutTest))
301 return;
302 if (is_fullscreen_ != enter_fullscreen) {
303 is_fullscreen_ = enter_fullscreen;
304 web_contents->GetRenderViewHost()->WasResized();
308 bool Shell::IsFullscreenForTabOrPending(const WebContents* web_contents) const {
309 #if defined(OS_ANDROID)
310 return PlatformIsFullscreenForTabOrPending(web_contents);
311 #else
312 return is_fullscreen_;
313 #endif
316 void Shell::RequestToLockMouse(WebContents* web_contents,
317 bool user_gesture,
318 bool last_unlocked_by_target) {
319 web_contents->GotResponseToLockMouseRequest(true);
322 void Shell::CloseContents(WebContents* source) {
323 Close();
326 bool Shell::CanOverscrollContent() const {
327 #if defined(USE_AURA)
328 return true;
329 #else
330 return false;
331 #endif
334 void Shell::DidNavigateMainFramePostCommit(WebContents* web_contents) {
335 PlatformSetAddressBarURL(web_contents->GetLastCommittedURL());
338 JavaScriptDialogManager* Shell::GetJavaScriptDialogManager(
339 WebContents* source) {
340 if (!dialog_manager_) {
341 const base::CommandLine& command_line =
342 *base::CommandLine::ForCurrentProcess();
343 dialog_manager_.reset(command_line.HasSwitch(switches::kRunLayoutTest)
344 ? new LayoutTestJavaScriptDialogManager
345 : new ShellJavaScriptDialogManager);
347 return dialog_manager_.get();
350 bool Shell::AddMessageToConsole(WebContents* source,
351 int32 level,
352 const base::string16& message,
353 int32 line_no,
354 const base::string16& source_id) {
355 return base::CommandLine::ForCurrentProcess()->HasSwitch(
356 switches::kRunLayoutTest);
359 void Shell::RendererUnresponsive(WebContents* source) {
360 if (!base::CommandLine::ForCurrentProcess()->HasSwitch(
361 switches::kRunLayoutTest))
362 return;
363 WebKitTestController::Get()->RendererUnresponsive();
366 void Shell::ActivateContents(WebContents* contents) {
367 contents->GetRenderViewHost()->Focus();
370 void Shell::DeactivateContents(WebContents* contents) {
371 contents->GetRenderViewHost()->Blur();
374 void Shell::WorkerCrashed(WebContents* source) {
375 if (!base::CommandLine::ForCurrentProcess()->HasSwitch(
376 switches::kRunLayoutTest))
377 return;
378 WebKitTestController::Get()->WorkerCrashed();
381 bool Shell::HandleContextMenu(const content::ContextMenuParams& params) {
382 return PlatformHandleContextMenu(params);
385 void Shell::WebContentsFocused(WebContents* contents) {
386 #if defined(TOOLKIT_VIEWS)
387 PlatformWebContentsFocused(contents);
388 #endif
391 gfx::Size Shell::GetShellDefaultSize() {
392 static gfx::Size default_shell_size;
393 if (!default_shell_size.IsEmpty())
394 return default_shell_size;
395 base::CommandLine* command_line = base::CommandLine::ForCurrentProcess();
396 if (command_line->HasSwitch(switches::kContentShellHostWindowSize)) {
397 const std::string size_str = command_line->GetSwitchValueASCII(
398 switches::kContentShellHostWindowSize);
399 int width, height;
400 CHECK_EQ(2, sscanf(size_str.c_str(), "%dx%d", &width, &height));
401 default_shell_size = gfx::Size(width, height);
402 } else {
403 default_shell_size = gfx::Size(
404 kDefaultTestWindowWidthDip, kDefaultTestWindowHeightDip);
406 return default_shell_size;
409 void Shell::TitleWasSet(NavigationEntry* entry, bool explicit_set) {
410 if (entry)
411 PlatformSetTitle(entry->GetTitle());
414 void Shell::InnerShowDevTools() {
415 if (!devtools_frontend_) {
416 devtools_frontend_ = ShellDevToolsFrontend::Show(web_contents());
417 devtools_observer_.reset(new DevToolsWebContentsObserver(
418 this, devtools_frontend_->frontend_shell()->web_contents()));
421 devtools_frontend_->Activate();
422 devtools_frontend_->Focus();
425 void Shell::OnDevToolsWebContentsDestroyed() {
426 devtools_observer_.reset();
427 devtools_frontend_ = NULL;
430 } // namespace content