Add ICU message format support
[chromium-blink-merge.git] / content / shell / browser / shell.cc
bloba78bb4ab9a8ddc5b25fd4bea7c5f682782fdbc0c
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_devtools_frontend.h"
25 #include "content/shell/browser/layout_test/layout_test_javascript_dialog_manager.h"
26 #include "content/shell/browser/notify_done_forwarder.h"
27 #include "content/shell/browser/shell_browser_main_parts.h"
28 #include "content/shell/browser/shell_content_browser_client.h"
29 #include "content/shell/browser/shell_devtools_frontend.h"
30 #include "content/shell/browser/shell_javascript_dialog_manager.h"
31 #include "content/shell/common/shell_messages.h"
32 #include "content/shell/common/shell_switches.h"
34 namespace content {
36 const int kDefaultTestWindowWidthDip = 800;
37 const int kDefaultTestWindowHeightDip = 600;
39 std::vector<Shell*> Shell::windows_;
40 base::Callback<void(Shell*)> Shell::shell_created_callback_;
42 bool Shell::quit_message_loop_ = true;
44 class Shell::DevToolsWebContentsObserver : public WebContentsObserver {
45 public:
46 DevToolsWebContentsObserver(Shell* shell, WebContents* web_contents)
47 : WebContentsObserver(web_contents),
48 shell_(shell) {
51 // WebContentsObserver
52 void WebContentsDestroyed() override {
53 shell_->OnDevToolsWebContentsDestroyed();
56 private:
57 Shell* shell_;
59 DISALLOW_COPY_AND_ASSIGN(DevToolsWebContentsObserver);
62 Shell::Shell(WebContents* web_contents)
63 : WebContentsObserver(web_contents),
64 devtools_frontend_(NULL),
65 is_fullscreen_(false),
66 window_(NULL),
67 url_edit_view_(NULL),
68 headless_(false) {
69 const base::CommandLine& command_line =
70 *base::CommandLine::ForCurrentProcess();
71 if (command_line.HasSwitch(switches::kRunLayoutTest))
72 headless_ = true;
73 windows_.push_back(this);
75 if (!shell_created_callback_.is_null()) {
76 shell_created_callback_.Run(this);
77 shell_created_callback_.Reset();
81 Shell::~Shell() {
82 PlatformCleanUp();
84 for (size_t i = 0; i < windows_.size(); ++i) {
85 if (windows_[i] == this) {
86 windows_.erase(windows_.begin() + i);
87 break;
91 if (windows_.empty() && quit_message_loop_) {
92 if (headless_)
93 PlatformExit();
94 base::ThreadTaskRunnerHandle::Get()->PostTask(
95 FROM_HERE, base::MessageLoop::QuitClosure());
99 Shell* Shell::CreateShell(WebContents* web_contents,
100 const gfx::Size& initial_size) {
101 Shell* shell = new Shell(web_contents);
102 shell->PlatformCreateWindow(initial_size.width(), initial_size.height());
104 shell->web_contents_.reset(web_contents);
105 web_contents->SetDelegate(shell);
107 shell->PlatformSetContents();
109 shell->PlatformResizeSubViews();
111 if (base::CommandLine::ForCurrentProcess()->HasSwitch(
112 switches::kRunLayoutTest)) {
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 DevToolsAgentHost::DetachAllClients();
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();
127 PlatformExit();
130 void Shell::SetShellCreatedCallback(
131 base::Callback<void(Shell*)> shell_created_callback) {
132 DCHECK(shell_created_callback_.is_null());
133 shell_created_callback_ = shell_created_callback;
136 Shell* 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];
143 return NULL;
146 // static
147 void Shell::Initialize() {
148 PlatformInitialize(GetShellDefaultSize());
151 gfx::Size Shell::AdjustWindowSize(const gfx::Size& initial_size) {
152 if (!initial_size.IsEmpty())
153 return initial_size;
154 return GetShellDefaultSize();
157 Shell* Shell::CreateNewWindow(BrowserContext* browser_context,
158 const GURL& url,
159 SiteInstance* site_instance,
160 const gfx::Size& initial_size) {
161 WebContents::CreateParams create_params(browser_context, site_instance);
162 create_params.initial_size = AdjustWindowSize(initial_size);
163 WebContents* web_contents = WebContents::Create(create_params);
164 Shell* shell = CreateShell(web_contents, create_params.initial_size);
165 if (!url.is_empty())
166 shell->LoadURL(url);
167 return shell;
170 void Shell::LoadURL(const GURL& url) {
171 LoadURLForFrame(url, std::string());
174 void Shell::LoadURLForFrame(const GURL& url, const std::string& frame_name) {
175 NavigationController::LoadURLParams params(url);
176 params.transition_type = ui::PageTransitionFromInt(
177 ui::PAGE_TRANSITION_TYPED | ui::PAGE_TRANSITION_FROM_ADDRESS_BAR);
178 params.frame_name = frame_name;
179 web_contents_->GetController().LoadURLWithParams(params);
180 web_contents_->Focus();
183 void Shell::LoadDataWithBaseURL(const GURL& url, const std::string& data,
184 const GURL& base_url) {
185 const GURL data_url = GURL("data:text/html;charset=utf-8," + data);
186 NavigationController::LoadURLParams params(data_url);
187 params.load_type = NavigationController::LOAD_TYPE_DATA;
188 params.base_url_for_data_url = base_url;
189 params.virtual_url_for_data_url = url;
190 params.override_user_agent = NavigationController::UA_OVERRIDE_FALSE;
191 web_contents_->GetController().LoadURLWithParams(params);
192 web_contents_->Focus();
195 void Shell::AddNewContents(WebContents* source,
196 WebContents* new_contents,
197 WindowOpenDisposition disposition,
198 const gfx::Rect& initial_rect,
199 bool user_gesture,
200 bool* was_blocked) {
201 CreateShell(new_contents, AdjustWindowSize(initial_rect.size()));
202 if (base::CommandLine::ForCurrentProcess()->HasSwitch(
203 switches::kRunLayoutTest))
204 NotifyDoneForwarder::CreateForWebContents(new_contents);
207 void Shell::GoBackOrForward(int offset) {
208 web_contents_->GetController().GoToOffset(offset);
209 web_contents_->Focus();
212 void Shell::Reload() {
213 web_contents_->GetController().Reload(false);
214 web_contents_->Focus();
217 void Shell::Stop() {
218 web_contents_->Stop();
219 web_contents_->Focus();
222 void Shell::UpdateNavigationControls(bool to_different_document) {
223 int current_index = web_contents_->GetController().GetCurrentEntryIndex();
224 int max_index = web_contents_->GetController().GetEntryCount() - 1;
226 PlatformEnableUIControl(BACK_BUTTON, current_index > 0);
227 PlatformEnableUIControl(FORWARD_BUTTON, current_index < max_index);
228 PlatformEnableUIControl(STOP_BUTTON,
229 to_different_document && web_contents_->IsLoading());
232 void Shell::ShowDevTools() {
233 InnerShowDevTools();
236 void Shell::ShowDevToolsForElementAt(int x, int y) {
237 InnerShowDevTools();
238 devtools_frontend_->InspectElementAt(x, y);
241 void Shell::CloseDevTools() {
242 if (!devtools_frontend_)
243 return;
244 devtools_observer_.reset();
245 devtools_frontend_->Close();
246 devtools_frontend_ = NULL;
249 gfx::NativeView Shell::GetContentView() {
250 if (!web_contents_)
251 return NULL;
252 return web_contents_->GetNativeView();
255 WebContents* Shell::OpenURLFromTab(WebContents* source,
256 const OpenURLParams& params) {
257 // CURRENT_TAB is the only one we implement for now.
258 if (params.disposition != CURRENT_TAB)
259 return NULL;
260 NavigationController::LoadURLParams load_url_params(params.url);
261 load_url_params.source_site_instance = params.source_site_instance;
262 load_url_params.referrer = params.referrer;
263 load_url_params.frame_tree_node_id = params.frame_tree_node_id;
264 load_url_params.transition_type = params.transition;
265 load_url_params.extra_headers = params.extra_headers;
266 load_url_params.should_replace_current_entry =
267 params.should_replace_current_entry;
269 if (params.transferred_global_request_id != GlobalRequestID()) {
270 load_url_params.is_renderer_initiated = params.is_renderer_initiated;
271 load_url_params.transferred_global_request_id =
272 params.transferred_global_request_id;
273 } else if (params.is_renderer_initiated) {
274 load_url_params.is_renderer_initiated = true;
277 source->GetController().LoadURLWithParams(load_url_params);
278 return source;
281 void Shell::LoadingStateChanged(WebContents* source,
282 bool to_different_document) {
283 UpdateNavigationControls(to_different_document);
284 PlatformSetIsLoading(source->IsLoading());
287 void Shell::EnterFullscreenModeForTab(WebContents* web_contents,
288 const GURL& origin) {
289 ToggleFullscreenModeForTab(web_contents, true);
292 void Shell::ExitFullscreenModeForTab(WebContents* web_contents) {
293 ToggleFullscreenModeForTab(web_contents, false);
296 void Shell::ToggleFullscreenModeForTab(WebContents* web_contents,
297 bool enter_fullscreen) {
298 #if defined(OS_ANDROID)
299 PlatformToggleFullscreenModeForTab(web_contents, enter_fullscreen);
300 #endif
301 if (!base::CommandLine::ForCurrentProcess()->HasSwitch(
302 switches::kRunLayoutTest))
303 return;
304 if (is_fullscreen_ != enter_fullscreen) {
305 is_fullscreen_ = enter_fullscreen;
306 web_contents->GetRenderViewHost()->WasResized();
310 bool Shell::IsFullscreenForTabOrPending(const WebContents* web_contents) const {
311 #if defined(OS_ANDROID)
312 return PlatformIsFullscreenForTabOrPending(web_contents);
313 #else
314 return is_fullscreen_;
315 #endif
318 blink::WebDisplayMode Shell::GetDisplayMode(
319 const WebContents* web_contents) const {
320 // TODO : should return blink::WebDisplayModeFullscreen wherever user puts
321 // a browser window into fullscreen (not only in case of renderer-initiated
322 // fullscreen mode): crbug.com/476874.
323 return IsFullscreenForTabOrPending(web_contents) ?
324 blink::WebDisplayModeFullscreen : blink::WebDisplayModeBrowser;
327 void Shell::RequestToLockMouse(WebContents* web_contents,
328 bool user_gesture,
329 bool last_unlocked_by_target) {
330 web_contents->GotResponseToLockMouseRequest(true);
333 void Shell::CloseContents(WebContents* source) {
334 Close();
337 bool Shell::CanOverscrollContent() const {
338 #if defined(USE_AURA)
339 return true;
340 #else
341 return false;
342 #endif
345 void Shell::DidNavigateMainFramePostCommit(WebContents* web_contents) {
346 PlatformSetAddressBarURL(web_contents->GetLastCommittedURL());
349 JavaScriptDialogManager* Shell::GetJavaScriptDialogManager(
350 WebContents* source) {
351 if (!dialog_manager_) {
352 const base::CommandLine& command_line =
353 *base::CommandLine::ForCurrentProcess();
354 dialog_manager_.reset(command_line.HasSwitch(switches::kRunLayoutTest)
355 ? new LayoutTestJavaScriptDialogManager
356 : new ShellJavaScriptDialogManager);
358 return dialog_manager_.get();
361 bool Shell::AddMessageToConsole(WebContents* source,
362 int32 level,
363 const base::string16& message,
364 int32 line_no,
365 const base::string16& source_id) {
366 return base::CommandLine::ForCurrentProcess()->HasSwitch(
367 switches::kRunLayoutTest);
370 void Shell::RendererUnresponsive(WebContents* source) {
371 if (!base::CommandLine::ForCurrentProcess()->HasSwitch(
372 switches::kRunLayoutTest))
373 return;
374 BlinkTestController::Get()->RendererUnresponsive();
377 void Shell::ActivateContents(WebContents* contents) {
378 contents->GetRenderViewHost()->Focus();
381 void Shell::DeactivateContents(WebContents* contents) {
382 contents->GetRenderViewHost()->Blur();
385 bool Shell::HandleContextMenu(const content::ContextMenuParams& params) {
386 return PlatformHandleContextMenu(params);
389 gfx::Size Shell::GetShellDefaultSize() {
390 static gfx::Size default_shell_size;
391 if (!default_shell_size.IsEmpty())
392 return default_shell_size;
393 base::CommandLine* command_line = base::CommandLine::ForCurrentProcess();
394 if (command_line->HasSwitch(switches::kContentShellHostWindowSize)) {
395 const std::string size_str = command_line->GetSwitchValueASCII(
396 switches::kContentShellHostWindowSize);
397 int width, height;
398 CHECK_EQ(2, sscanf(size_str.c_str(), "%dx%d", &width, &height));
399 default_shell_size = gfx::Size(width, height);
400 } else {
401 default_shell_size = gfx::Size(
402 kDefaultTestWindowWidthDip, kDefaultTestWindowHeightDip);
404 return default_shell_size;
407 void Shell::TitleWasSet(NavigationEntry* entry, bool explicit_set) {
408 if (entry)
409 PlatformSetTitle(entry->GetTitle());
412 void Shell::InnerShowDevTools() {
413 if (!devtools_frontend_) {
414 devtools_frontend_ = ShellDevToolsFrontend::Show(web_contents());
415 devtools_observer_.reset(new DevToolsWebContentsObserver(
416 this, devtools_frontend_->frontend_shell()->web_contents()));
419 devtools_frontend_->Activate();
420 devtools_frontend_->Focus();
423 void Shell::OnDevToolsWebContentsDestroyed() {
424 devtools_observer_.reset();
425 devtools_frontend_ = NULL;
428 } // namespace content