OLD | NEW |
| (Empty) |
1 // Copyright (c) 2012 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/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/notification_details.h" | |
19 #include "content/public/browser/notification_source.h" | |
20 #include "content/public/browser/notification_types.h" | |
21 #include "content/public/browser/render_view_host.h" | |
22 #include "content/public/browser/web_contents.h" | |
23 #include "content/public/browser/web_contents_observer.h" | |
24 #include "content/public/browser/web_contents_view.h" | |
25 #include "content/public/common/renderer_preferences.h" | |
26 #include "content/shell/common/shell_messages.h" | |
27 #include "content/shell/common/shell_switches.h" | |
28 #include "content/shell/notify_done_forwarder.h" | |
29 #include "content/shell/shell_browser_main_parts.h" | |
30 #include "content/shell/shell_content_browser_client.h" | |
31 #include "content/shell/shell_devtools_frontend.h" | |
32 #include "content/shell/shell_javascript_dialog_manager.h" | |
33 #include "content/shell/webkit_test_controller.h" | |
34 | |
35 namespace content { | |
36 | |
37 const int Shell::kDefaultTestWindowWidthDip = 800; | |
38 const int Shell::kDefaultTestWindowHeightDip = 600; | |
39 | |
40 std::vector<Shell*> Shell::windows_; | |
41 base::Callback<void(Shell*)> Shell::shell_created_callback_; | |
42 | |
43 bool Shell::quit_message_loop_ = true; | |
44 | |
45 class Shell::DevToolsWebContentsObserver : public WebContentsObserver { | |
46 public: | |
47 DevToolsWebContentsObserver(Shell* shell, WebContents* web_contents) | |
48 : WebContentsObserver(web_contents), | |
49 shell_(shell) { | |
50 } | |
51 | |
52 // WebContentsObserver | |
53 virtual void WebContentsDestroyed(WebContents* web_contents) OVERRIDE { | |
54 shell_->OnDevToolsWebContentsDestroyed(); | |
55 } | |
56 | |
57 private: | |
58 Shell* shell_; | |
59 | |
60 DISALLOW_COPY_AND_ASSIGN(DevToolsWebContentsObserver); | |
61 }; | |
62 | |
63 Shell::Shell(WebContents* web_contents) | |
64 : devtools_frontend_(NULL), | |
65 is_fullscreen_(false), | |
66 window_(NULL), | |
67 url_edit_view_(NULL), | |
68 #if defined(OS_WIN) && !defined(USE_AURA) | |
69 default_edit_wnd_proc_(0), | |
70 #endif | |
71 headless_(false) { | |
72 const CommandLine& command_line = *CommandLine::ForCurrentProcess(); | |
73 if (command_line.HasSwitch(switches::kDumpRenderTree)) | |
74 headless_ = true; | |
75 registrar_.Add(this, NOTIFICATION_WEB_CONTENTS_TITLE_UPDATED, | |
76 Source<WebContents>(web_contents)); | |
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 | |
85 Shell::~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 | |
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()); | |
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 | |
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(); | |
127 } | |
128 | |
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; | |
133 } | |
134 | |
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]; | |
140 } | |
141 } | |
142 return NULL; | |
143 } | |
144 | |
145 // static | |
146 void Shell::Initialize() { | |
147 PlatformInitialize( | |
148 gfx::Size(kDefaultTestWindowWidthDip, kDefaultTestWindowHeightDip)); | |
149 } | |
150 | |
151 Shell* Shell::CreateNewWindow(BrowserContext* browser_context, | |
152 const GURL& url, | |
153 SiteInstance* site_instance, | |
154 int routing_id, | |
155 const gfx::Size& initial_size) { | |
156 WebContents::CreateParams create_params(browser_context, site_instance); | |
157 create_params.routing_id = routing_id; | |
158 if (!initial_size.IsEmpty()) | |
159 create_params.initial_size = initial_size; | |
160 else | |
161 create_params.initial_size = | |
162 gfx::Size(kDefaultTestWindowWidthDip, kDefaultTestWindowHeightDip); | |
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; | |
168 } | |
169 | |
170 void Shell::LoadURL(const GURL& url) { | |
171 LoadURLForFrame(url, std::string()); | |
172 } | |
173 | |
174 void Shell::LoadURLForFrame(const GURL& url, const std::string& frame_name) { | |
175 NavigationController::LoadURLParams params(url); | |
176 params.transition_type = PageTransitionFromInt( | |
177 PAGE_TRANSITION_TYPED | PAGE_TRANSITION_FROM_ADDRESS_BAR); | |
178 params.frame_name = frame_name; | |
179 web_contents_->GetController().LoadURLWithParams(params); | |
180 web_contents_->GetView()->Focus(); | |
181 } | |
182 | |
183 void Shell::GoBackOrForward(int offset) { | |
184 web_contents_->GetController().GoToOffset(offset); | |
185 web_contents_->GetView()->Focus(); | |
186 } | |
187 | |
188 void Shell::Reload() { | |
189 web_contents_->GetController().Reload(false); | |
190 web_contents_->GetView()->Focus(); | |
191 } | |
192 | |
193 void Shell::Stop() { | |
194 web_contents_->Stop(); | |
195 web_contents_->GetView()->Focus(); | |
196 } | |
197 | |
198 void Shell::UpdateNavigationControls() { | |
199 int current_index = web_contents_->GetController().GetCurrentEntryIndex(); | |
200 int max_index = web_contents_->GetController().GetEntryCount() - 1; | |
201 | |
202 PlatformEnableUIControl(BACK_BUTTON, current_index > 0); | |
203 PlatformEnableUIControl(FORWARD_BUTTON, current_index < max_index); | |
204 PlatformEnableUIControl(STOP_BUTTON, web_contents_->IsLoading()); | |
205 } | |
206 | |
207 void Shell::ShowDevTools() { | |
208 if (devtools_frontend_) { | |
209 devtools_frontend_->Focus(); | |
210 return; | |
211 } | |
212 devtools_frontend_ = ShellDevToolsFrontend::Show(web_contents()); | |
213 devtools_observer_.reset(new DevToolsWebContentsObserver( | |
214 this, devtools_frontend_->frontend_shell()->web_contents())); | |
215 } | |
216 | |
217 void Shell::CloseDevTools() { | |
218 if (!devtools_frontend_) | |
219 return; | |
220 devtools_observer_.reset(); | |
221 devtools_frontend_->Close(); | |
222 devtools_frontend_ = NULL; | |
223 } | |
224 | |
225 gfx::NativeView Shell::GetContentView() { | |
226 if (!web_contents_) | |
227 return NULL; | |
228 return web_contents_->GetView()->GetNativeView(); | |
229 } | |
230 | |
231 WebContents* Shell::OpenURLFromTab(WebContents* source, | |
232 const OpenURLParams& params) { | |
233 // The only one we implement for now. | |
234 DCHECK(params.disposition == CURRENT_TAB); | |
235 NavigationController::LoadURLParams load_url_params(params.url); | |
236 load_url_params.referrer = params.referrer; | |
237 load_url_params.transition_type = params.transition; | |
238 load_url_params.extra_headers = params.extra_headers; | |
239 load_url_params.should_replace_current_entry = | |
240 params.should_replace_current_entry; | |
241 | |
242 if (params.transferred_global_request_id != GlobalRequestID()) { | |
243 load_url_params.is_renderer_initiated = params.is_renderer_initiated; | |
244 load_url_params.transferred_global_request_id = | |
245 params.transferred_global_request_id; | |
246 } else if (params.is_renderer_initiated) { | |
247 load_url_params.is_renderer_initiated = true; | |
248 } | |
249 | |
250 source->GetController().LoadURLWithParams(load_url_params); | |
251 return source; | |
252 } | |
253 | |
254 void Shell::LoadingStateChanged(WebContents* source) { | |
255 UpdateNavigationControls(); | |
256 PlatformSetIsLoading(source->IsLoading()); | |
257 } | |
258 | |
259 void Shell::ToggleFullscreenModeForTab(WebContents* web_contents, | |
260 bool enter_fullscreen) { | |
261 #if defined(OS_ANDROID) | |
262 PlatformToggleFullscreenModeForTab(web_contents, enter_fullscreen); | |
263 #endif | |
264 if (!CommandLine::ForCurrentProcess()->HasSwitch(switches::kDumpRenderTree)) | |
265 return; | |
266 if (is_fullscreen_ != enter_fullscreen) { | |
267 is_fullscreen_ = enter_fullscreen; | |
268 web_contents->GetRenderViewHost()->WasResized(); | |
269 } | |
270 } | |
271 | |
272 bool Shell::IsFullscreenForTabOrPending(const WebContents* web_contents) const { | |
273 #if defined(OS_ANDROID) | |
274 return PlatformIsFullscreenForTabOrPending(web_contents); | |
275 #else | |
276 return is_fullscreen_; | |
277 #endif | |
278 } | |
279 | |
280 void Shell::RequestToLockMouse(WebContents* web_contents, | |
281 bool user_gesture, | |
282 bool last_unlocked_by_target) { | |
283 web_contents->GotResponseToLockMouseRequest(true); | |
284 } | |
285 | |
286 void Shell::CloseContents(WebContents* source) { | |
287 Close(); | |
288 } | |
289 | |
290 bool Shell::CanOverscrollContent() const { | |
291 #if defined(USE_AURA) | |
292 return true; | |
293 #else | |
294 return false; | |
295 #endif | |
296 } | |
297 | |
298 void Shell::WebContentsCreated(WebContents* source_contents, | |
299 int64 source_frame_id, | |
300 const string16& frame_name, | |
301 const GURL& target_url, | |
302 WebContents* new_contents) { | |
303 CreateShell(new_contents, source_contents->GetView()->GetContainerSize()); | |
304 if (CommandLine::ForCurrentProcess()->HasSwitch(switches::kDumpRenderTree)) | |
305 NotifyDoneForwarder::CreateForWebContents(new_contents); | |
306 } | |
307 | |
308 void Shell::DidNavigateMainFramePostCommit(WebContents* web_contents) { | |
309 PlatformSetAddressBarURL(web_contents->GetLastCommittedURL()); | |
310 } | |
311 | |
312 JavaScriptDialogManager* Shell::GetJavaScriptDialogManager() { | |
313 if (!dialog_manager_) | |
314 dialog_manager_.reset(new ShellJavaScriptDialogManager()); | |
315 return dialog_manager_.get(); | |
316 } | |
317 | |
318 bool Shell::AddMessageToConsole(WebContents* source, | |
319 int32 level, | |
320 const string16& message, | |
321 int32 line_no, | |
322 const string16& source_id) { | |
323 return CommandLine::ForCurrentProcess()->HasSwitch(switches::kDumpRenderTree); | |
324 } | |
325 | |
326 void Shell::RendererUnresponsive(WebContents* source) { | |
327 if (!CommandLine::ForCurrentProcess()->HasSwitch(switches::kDumpRenderTree)) | |
328 return; | |
329 WebKitTestController::Get()->RendererUnresponsive(); | |
330 } | |
331 | |
332 void Shell::ActivateContents(WebContents* contents) { | |
333 contents->GetRenderViewHost()->Focus(); | |
334 } | |
335 | |
336 void Shell::DeactivateContents(WebContents* contents) { | |
337 contents->GetRenderViewHost()->Blur(); | |
338 } | |
339 | |
340 void Shell::WorkerCrashed(WebContents* source) { | |
341 if (!CommandLine::ForCurrentProcess()->HasSwitch(switches::kDumpRenderTree)) | |
342 return; | |
343 WebKitTestController::Get()->WorkerCrashed(); | |
344 } | |
345 | |
346 void Shell::Observe(int type, | |
347 const NotificationSource& source, | |
348 const NotificationDetails& details) { | |
349 if (type == NOTIFICATION_WEB_CONTENTS_TITLE_UPDATED) { | |
350 std::pair<NavigationEntry*, bool>* title = | |
351 Details<std::pair<NavigationEntry*, bool> >(details).ptr(); | |
352 | |
353 if (title->first) { | |
354 string16 text = title->first->GetTitle(); | |
355 PlatformSetTitle(text); | |
356 } | |
357 } else { | |
358 NOTREACHED(); | |
359 } | |
360 } | |
361 | |
362 void Shell::OnDevToolsWebContentsDestroyed() { | |
363 devtools_observer_.reset(); | |
364 devtools_frontend_ = NULL; | |
365 } | |
366 | |
367 } // namespace content | |
OLD | NEW |