blob: 89ae2a21cd25035df1c2988cce46f53c2c6c9486 [file] [log] [blame]
[email protected]de7d61ff2013-08-20 11:30:411// Copyright 2013 The Chromium Authors. All rights reserved.
[email protected]9fbd3f862011-09-20 23:31:342// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
[email protected]de7d61ff2013-08-20 11:30:415#include "content/shell/browser/shell.h"
[email protected]9fbd3f862011-09-20 23:31:346
[email protected]11a65b692012-03-30 11:29:167#include "base/auto_reset.h"
[email protected]efb5f572012-01-29 10:57:338#include "base/command_line.h"
[email protected]aaf68892013-07-18 00:11:309#include "base/message_loop/message_loop.h"
[email protected]21aa99682013-06-11 07:17:0110#include "base/strings/string_number_conversions.h"
11#include "base/strings/string_util.h"
12#include "base/strings/stringprintf.h"
[email protected]74ebfb12013-06-07 20:48:0013#include "base/strings/utf_string_conversions.h"
[email protected]b50452f2014-08-18 12:31:4414#include "content/public/browser/devtools_agent_host.h"
[email protected]0b659b32012-03-26 21:29:3215#include "content/public/browser/navigation_controller.h"
[email protected]b7c504c2013-05-07 14:42:1216#include "content/public/browser/navigation_entry.h"
[email protected]0b659b32012-03-26 21:29:3217#include "content/public/browser/render_view_host.h"
18#include "content/public/browser/web_contents.h"
[email protected]7fff43e2013-05-21 20:21:1019#include "content/public/browser/web_contents_observer.h"
[email protected]1596efb2013-01-17 22:13:0120#include "content/public/common/renderer_preferences.h"
mkwst30d20d52014-10-09 13:33:1421#include "content/shell/browser/layout_test/layout_test_devtools_frontend.h"
mkwst6efe7f2e62014-10-08 15:09:0122#include "content/shell/browser/layout_test/layout_test_javascript_dialog_manager.h"
[email protected]de7d61ff2013-08-20 11:30:4123#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"
[email protected]b7c504c2013-05-07 14:42:1229#include "content/shell/common/shell_messages.h"
30#include "content/shell/common/shell_switches.h"
[email protected]9fbd3f862011-09-20 23:31:3431
[email protected]9fbd3f862011-09-20 23:31:3432namespace content {
33
pdrcab84ee2015-03-13 21:47:0434const int kDefaultTestWindowWidthDip = 800;
35const int kDefaultTestWindowHeightDip = 600;
[email protected]1e57cab2013-05-28 04:26:1136
[email protected]e99ca5112011-09-26 17:22:5437std::vector<Shell*> Shell::windows_;
[email protected]9e00e6352012-07-30 17:05:1838base::Callback<void(Shell*)> Shell::shell_created_callback_;
[email protected]9fbd3f862011-09-20 23:31:3439
[email protected]11a65b692012-03-30 11:29:1640bool Shell::quit_message_loop_ = true;
41
[email protected]7fff43e2013-05-21 20:21:1042class Shell::DevToolsWebContentsObserver : public WebContentsObserver {
43 public:
44 DevToolsWebContentsObserver(Shell* shell, WebContents* web_contents)
45 : WebContentsObserver(web_contents),
46 shell_(shell) {
47 }
48
49 // WebContentsObserver
dchenge933b3e2014-10-21 11:44:0950 void WebContentsDestroyed() override {
[email protected]7fff43e2013-05-21 20:21:1051 shell_->OnDevToolsWebContentsDestroyed();
52 }
53
54 private:
55 Shell* shell_;
56
57 DISALLOW_COPY_AND_ASSIGN(DevToolsWebContentsObserver);
58};
59
[email protected]0b659b32012-03-26 21:29:3260Shell::Shell(WebContents* web_contents)
[email protected]1ef02d242013-10-07 16:18:5361 : WebContentsObserver(web_contents),
62 devtools_frontend_(NULL),
[email protected]001841c92012-12-11 17:00:1363 is_fullscreen_(false),
[email protected]99c014c2012-11-27 12:03:4264 window_(NULL),
[email protected]86b36e672012-12-21 00:09:5165 url_edit_view_(NULL),
[email protected]86b36e672012-12-21 00:09:5166 headless_(false) {
avi83883c82014-12-23 00:08:4967 const base::CommandLine& command_line =
68 *base::CommandLine::ForCurrentProcess();
paulmeyerbcc6ad22015-02-11 21:51:5969 if (command_line.HasSwitch(switches::kRunLayoutTest))
[email protected]86b36e672012-12-21 00:09:5170 headless_ = true;
[email protected]9e00e6352012-07-30 17:05:1871 windows_.push_back(this);
72
73 if (!shell_created_callback_.is_null()) {
74 shell_created_callback_.Run(this);
75 shell_created_callback_.Reset();
76 }
[email protected]9fbd3f862011-09-20 23:31:3477}
78
79Shell::~Shell() {
80 PlatformCleanUp();
[email protected]e99ca5112011-09-26 17:22:5481
82 for (size_t i = 0; i < windows_.size(); ++i) {
83 if (windows_[i] == this) {
84 windows_.erase(windows_.begin() + i);
85 break;
86 }
87 }
[email protected]11a65b692012-03-30 11:29:1688
[email protected]b53adf452014-02-07 12:55:0889 if (windows_.empty() && quit_message_loop_) {
90 if (headless_)
91 PlatformExit();
[email protected]dd32b1272013-05-04 14:17:1192 base::MessageLoop::current()->PostTask(FROM_HERE,
93 base::MessageLoop::QuitClosure());
[email protected]b53adf452014-02-07 12:55:0894 }
[email protected]9fbd3f862011-09-20 23:31:3495}
96
[email protected]c0d036d2013-05-07 12:50:5097Shell* Shell::CreateShell(WebContents* web_contents,
98 const gfx::Size& initial_size) {
[email protected]0b659b32012-03-26 21:29:3299 Shell* shell = new Shell(web_contents);
[email protected]c0d036d2013-05-07 12:50:50100 shell->PlatformCreateWindow(initial_size.width(), initial_size.height());
[email protected]3fd84032012-01-12 18:20:17101
[email protected]0b659b32012-03-26 21:29:32102 shell->web_contents_.reset(web_contents);
103 web_contents->SetDelegate(shell);
[email protected]3fd84032012-01-12 18:20:17104
[email protected]5cba3bf2012-01-14 02:40:35105 shell->PlatformSetContents();
[email protected]3fd84032012-01-12 18:20:17106
107 shell->PlatformResizeSubViews();
[email protected]1596efb2013-01-17 22:13:01108
avi83883c82014-12-23 00:08:49109 if (base::CommandLine::ForCurrentProcess()->HasSwitch(
paulmeyerbcc6ad22015-02-11 21:51:59110 switches::kRunLayoutTest)) {
[email protected]1596efb2013-01-17 22:13:01111 web_contents->GetMutableRendererPrefs()->use_custom_colors = false;
112 web_contents->GetRenderViewHost()->SyncRendererPrefs();
113 }
114
[email protected]3fd84032012-01-12 18:20:17115 return shell;
116}
117
[email protected]11a65b692012-03-30 11:29:16118void Shell::CloseAllWindows() {
[email protected]997ec9f2012-11-21 04:44:14119 base::AutoReset<bool> auto_reset(&quit_message_loop_, false);
[email protected]b50452f2014-08-18 12:31:44120 DevToolsAgentHost::DetachAllClients();
[email protected]11a65b692012-03-30 11:29:16121 std::vector<Shell*> open_windows(windows_);
122 for (size_t i = 0; i < open_windows.size(); ++i)
123 open_windows[i]->Close();
[email protected]4249a422013-11-27 19:04:04124 PlatformExit();
[email protected]dd32b1272013-05-04 14:17:11125 base::MessageLoop::current()->RunUntilIdle();
[email protected]11a65b692012-03-30 11:29:16126}
127
[email protected]9e00e6352012-07-30 17:05:18128void Shell::SetShellCreatedCallback(
129 base::Callback<void(Shell*)> shell_created_callback) {
130 DCHECK(shell_created_callback_.is_null());
131 shell_created_callback_ = shell_created_callback;
132}
133
[email protected]74830f02012-01-30 22:27:04134Shell* Shell::FromRenderViewHost(RenderViewHost* rvh) {
135 for (size_t i = 0; i < windows_.size(); ++i) {
[email protected]0b659b32012-03-26 21:29:32136 if (windows_[i]->web_contents() &&
137 windows_[i]->web_contents()->GetRenderViewHost() == rvh) {
[email protected]74830f02012-01-30 22:27:04138 return windows_[i];
139 }
140 }
141 return NULL;
142}
143
[email protected]6153b272013-01-25 22:29:23144// static
145void Shell::Initialize() {
pdrcab84ee2015-03-13 21:47:04146 PlatformInitialize(GetShellDefaultSize());
[email protected]6153b272013-01-25 22:29:23147}
148
[email protected]a2904092013-10-15 04:53:59149gfx::Size Shell::AdjustWindowSize(const gfx::Size& initial_size) {
150 if (!initial_size.IsEmpty())
151 return initial_size;
pdrcab84ee2015-03-13 21:47:04152 return GetShellDefaultSize();
[email protected]a2904092013-10-15 04:53:59153}
154
[email protected]bdcf9152012-07-19 17:43:21155Shell* Shell::CreateNewWindow(BrowserContext* browser_context,
[email protected]e99ca5112011-09-26 17:22:54156 const GURL& url,
157 SiteInstance* site_instance,
[email protected]cdb806722013-01-10 14:18:23158 const gfx::Size& initial_size) {
[email protected]54944cde2012-12-09 09:24:59159 WebContents::CreateParams create_params(browser_context, site_instance);
[email protected]a2904092013-10-15 04:53:59160 create_params.initial_size = AdjustWindowSize(initial_size);
[email protected]54944cde2012-12-09 09:24:59161 WebContents* web_contents = WebContents::Create(create_params);
[email protected]c0d036d2013-05-07 12:50:50162 Shell* shell = CreateShell(web_contents, create_params.initial_size);
[email protected]e99ca5112011-09-26 17:22:54163 if (!url.is_empty())
164 shell->LoadURL(url);
[email protected]9fbd3f862011-09-20 23:31:34165 return shell;
166}
167
168void Shell::LoadURL(const GURL& url) {
[email protected]d2494ff2013-02-20 08:22:37169 LoadURLForFrame(url, std::string());
170}
171
172void Shell::LoadURLForFrame(const GURL& url, const std::string& frame_name) {
173 NavigationController::LoadURLParams params(url);
Sylvain Defresnec6ccc77d2014-09-19 10:19:35174 params.transition_type = ui::PageTransitionFromInt(
175 ui::PAGE_TRANSITION_TYPED | ui::PAGE_TRANSITION_FROM_ADDRESS_BAR);
[email protected]d2494ff2013-02-20 08:22:37176 params.frame_name = frame_name;
177 web_contents_->GetController().LoadURLWithParams(params);
[email protected]fc2b46b2014-05-03 16:33:45178 web_contents_->Focus();
[email protected]9fbd3f862011-09-20 23:31:34179}
180
[email protected]76bdecb2014-04-16 17:58:08181void 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);
[email protected]fc2b46b2014-05-03 16:33:45190 web_contents_->Focus();
[email protected]76bdecb2014-04-16 17:58:08191}
192
[email protected]a2904092013-10-15 04:53:59193void Shell::AddNewContents(WebContents* source,
194 WebContents* new_contents,
195 WindowOpenDisposition disposition,
bokan107a47f2015-02-03 23:23:39196 const gfx::Rect& initial_rect,
[email protected]a2904092013-10-15 04:53:59197 bool user_gesture,
198 bool* was_blocked) {
bokan107a47f2015-02-03 23:23:39199 CreateShell(new_contents, AdjustWindowSize(initial_rect.size()));
avi83883c82014-12-23 00:08:49200 if (base::CommandLine::ForCurrentProcess()->HasSwitch(
paulmeyerbcc6ad22015-02-11 21:51:59201 switches::kRunLayoutTest))
[email protected]a2904092013-10-15 04:53:59202 NotifyDoneForwarder::CreateForWebContents(new_contents);
203}
204
[email protected]9fbd3f862011-09-20 23:31:34205void Shell::GoBackOrForward(int offset) {
[email protected]0b659b32012-03-26 21:29:32206 web_contents_->GetController().GoToOffset(offset);
[email protected]fc2b46b2014-05-03 16:33:45207 web_contents_->Focus();
[email protected]9fbd3f862011-09-20 23:31:34208}
209
210void Shell::Reload() {
[email protected]0b659b32012-03-26 21:29:32211 web_contents_->GetController().Reload(false);
[email protected]fc2b46b2014-05-03 16:33:45212 web_contents_->Focus();
[email protected]9fbd3f862011-09-20 23:31:34213}
214
215void Shell::Stop() {
[email protected]0b659b32012-03-26 21:29:32216 web_contents_->Stop();
[email protected]fc2b46b2014-05-03 16:33:45217 web_contents_->Focus();
[email protected]9fbd3f862011-09-20 23:31:34218}
219
[email protected]e3b10d12014-03-28 16:06:09220void Shell::UpdateNavigationControls(bool to_different_document) {
[email protected]0b659b32012-03-26 21:29:32221 int current_index = web_contents_->GetController().GetCurrentEntryIndex();
222 int max_index = web_contents_->GetController().GetEntryCount() - 1;
[email protected]9fbd3f862011-09-20 23:31:34223
224 PlatformEnableUIControl(BACK_BUTTON, current_index > 0);
225 PlatformEnableUIControl(FORWARD_BUTTON, current_index < max_index);
[email protected]e3b10d12014-03-28 16:06:09226 PlatformEnableUIControl(STOP_BUTTON,
227 to_different_document && web_contents_->IsLoading());
[email protected]9fbd3f862011-09-20 23:31:34228}
229
[email protected]7c17b6992012-08-09 16:16:30230void Shell::ShowDevTools() {
pfeldman552756452015-02-03 17:33:06231 InnerShowDevTools();
[email protected]3142e5d2014-02-07 00:54:46232}
233
234void Shell::ShowDevToolsForElementAt(int x, int y) {
pfeldman552756452015-02-03 17:33:06235 InnerShowDevTools();
[email protected]2317fcd2014-02-10 14:36:48236 devtools_frontend_->InspectElementAt(x, y);
[email protected]7c17b6992012-08-09 16:16:30237}
238
[email protected]001841c92012-12-11 17:00:13239void Shell::CloseDevTools() {
[email protected]0773e0c2013-01-25 15:57:57240 if (!devtools_frontend_)
[email protected]001841c92012-12-11 17:00:13241 return;
[email protected]7fff43e2013-05-21 20:21:10242 devtools_observer_.reset();
[email protected]0773e0c2013-01-25 15:57:57243 devtools_frontend_->Close();
244 devtools_frontend_ = NULL;
[email protected]001841c92012-12-11 17:00:13245}
246
[email protected]9fbd3f862011-09-20 23:31:34247gfx::NativeView Shell::GetContentView() {
[email protected]59383c782013-04-17 16:43:27248 if (!web_contents_)
[email protected]9fbd3f862011-09-20 23:31:34249 return NULL;
[email protected]fc2b46b2014-05-03 16:33:45250 return web_contents_->GetNativeView();
[email protected]9fbd3f862011-09-20 23:31:34251}
252
[email protected]9e00e6352012-07-30 17:05:18253WebContents* Shell::OpenURLFromTab(WebContents* source,
254 const OpenURLParams& params) {
[email protected]7cf38302013-08-29 12:23:46255 // CURRENT_TAB is the only one we implement for now.
256 if (params.disposition != CURRENT_TAB)
257 return NULL;
[email protected]fbaccee2013-08-12 23:24:02258 NavigationController::LoadURLParams load_url_params(params.url);
lfg9ef7d2d2014-12-15 22:32:30259 load_url_params.source_site_instance = params.source_site_instance;
[email protected]fbaccee2013-08-12 23:24:02260 load_url_params.referrer = params.referrer;
[email protected]c80297782013-11-21 07:10:16261 load_url_params.frame_tree_node_id = params.frame_tree_node_id;
[email protected]fbaccee2013-08-12 23:24:02262 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;
266
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;
273 }
274
275 source->GetController().LoadURLWithParams(load_url_params);
[email protected]9e00e6352012-07-30 17:05:18276 return source;
277}
278
[email protected]e3b10d12014-03-28 16:06:09279void Shell::LoadingStateChanged(WebContents* source,
280 bool to_different_document) {
281 UpdateNavigationControls(to_different_document);
[email protected]15aea412012-01-19 03:18:50282 PlatformSetIsLoading(source->IsLoading());
[email protected]e99ca5112011-09-26 17:22:54283}
284
mlamouri7a78d6fd2015-01-17 13:23:53285void Shell::EnterFullscreenModeForTab(WebContents* web_contents,
286 const GURL& origin) {
287 ToggleFullscreenModeForTab(web_contents, true);
288}
289
290void Shell::ExitFullscreenModeForTab(WebContents* web_contents) {
291 ToggleFullscreenModeForTab(web_contents, false);
292}
293
[email protected]99c014c2012-11-27 12:03:42294void Shell::ToggleFullscreenModeForTab(WebContents* web_contents,
295 bool enter_fullscreen) {
296#if defined(OS_ANDROID)
297 PlatformToggleFullscreenModeForTab(web_contents, enter_fullscreen);
298#endif
avi83883c82014-12-23 00:08:49299 if (!base::CommandLine::ForCurrentProcess()->HasSwitch(
paulmeyerbcc6ad22015-02-11 21:51:59300 switches::kRunLayoutTest))
[email protected]99c014c2012-11-27 12:03:42301 return;
302 if (is_fullscreen_ != enter_fullscreen) {
303 is_fullscreen_ = enter_fullscreen;
304 web_contents->GetRenderViewHost()->WasResized();
305 }
306}
307
308bool 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
314}
315
[email protected]f78439002012-11-28 14:45:59316void Shell::RequestToLockMouse(WebContents* web_contents,
317 bool user_gesture,
318 bool last_unlocked_by_target) {
319 web_contents->GotResponseToLockMouseRequest(true);
320}
321
[email protected]9e00e6352012-07-30 17:05:18322void Shell::CloseContents(WebContents* source) {
323 Close();
324}
325
[email protected]067310262012-11-22 14:30:41326bool Shell::CanOverscrollContent() const {
327#if defined(USE_AURA)
328 return true;
329#else
330 return false;
331#endif
332}
333
[email protected]3bbacc5b2012-04-17 17:46:15334void Shell::DidNavigateMainFramePostCommit(WebContents* web_contents) {
[email protected]4e3c7522013-08-13 11:53:18335 PlatformSetAddressBarURL(web_contents->GetLastCommittedURL());
[email protected]e99ca5112011-09-26 17:22:54336}
337
mathiash72a5e462014-11-19 08:18:50338JavaScriptDialogManager* Shell::GetJavaScriptDialogManager(
339 WebContents* source) {
mkwst6efe7f2e62014-10-08 15:09:01340 if (!dialog_manager_) {
avi83883c82014-12-23 00:08:49341 const base::CommandLine& command_line =
342 *base::CommandLine::ForCurrentProcess();
paulmeyerbcc6ad22015-02-11 21:51:59343 dialog_manager_.reset(command_line.HasSwitch(switches::kRunLayoutTest)
mkwst6efe7f2e62014-10-08 15:09:01344 ? new LayoutTestJavaScriptDialogManager
345 : new ShellJavaScriptDialogManager);
346 }
[email protected]71a88bb2013-02-01 22:05:15347 return dialog_manager_.get();
[email protected]f2210022012-03-29 00:36:08348}
349
[email protected]c272c5b2012-06-06 09:01:06350bool Shell::AddMessageToConsole(WebContents* source,
351 int32 level,
[email protected]fcf75d42013-12-03 20:11:26352 const base::string16& message,
[email protected]c272c5b2012-06-06 09:01:06353 int32 line_no,
[email protected]fcf75d42013-12-03 20:11:26354 const base::string16& source_id) {
avi83883c82014-12-23 00:08:49355 return base::CommandLine::ForCurrentProcess()->HasSwitch(
paulmeyerbcc6ad22015-02-11 21:51:59356 switches::kRunLayoutTest);
[email protected]efb5f572012-01-29 10:57:33357}
358
[email protected]5bf68f22012-08-31 07:38:10359void Shell::RendererUnresponsive(WebContents* source) {
avi83883c82014-12-23 00:08:49360 if (!base::CommandLine::ForCurrentProcess()->HasSwitch(
paulmeyerbcc6ad22015-02-11 21:51:59361 switches::kRunLayoutTest))
[email protected]5bf68f22012-08-31 07:38:10362 return;
363 WebKitTestController::Get()->RendererUnresponsive();
364}
365
[email protected]233567d2013-02-27 20:22:02366void Shell::ActivateContents(WebContents* contents) {
367 contents->GetRenderViewHost()->Focus();
368}
369
370void Shell::DeactivateContents(WebContents* contents) {
371 contents->GetRenderViewHost()->Blur();
372}
373
[email protected]3eeacfa62013-07-23 09:23:15374void Shell::WorkerCrashed(WebContents* source) {
avi83883c82014-12-23 00:08:49375 if (!base::CommandLine::ForCurrentProcess()->HasSwitch(
paulmeyerbcc6ad22015-02-11 21:51:59376 switches::kRunLayoutTest))
[email protected]3eeacfa62013-07-23 09:23:15377 return;
378 WebKitTestController::Get()->WorkerCrashed();
379}
380
[email protected]3142e5d2014-02-07 00:54:46381bool Shell::HandleContextMenu(const content::ContextMenuParams& params) {
382 return PlatformHandleContextMenu(params);
383}
384
[email protected]d0bb9952014-02-10 20:58:26385void Shell::WebContentsFocused(WebContents* contents) {
386#if defined(TOOLKIT_VIEWS)
387 PlatformWebContentsFocused(contents);
388#endif
389}
390
pdrcab84ee2015-03-13 21:47:04391gfx::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);
405 }
406 return default_shell_size;
407}
408
[email protected]1ef02d242013-10-07 16:18:53409void Shell::TitleWasSet(NavigationEntry* entry, bool explicit_set) {
410 if (entry)
411 PlatformSetTitle(entry->GetTitle());
[email protected]aecc085b2012-06-01 18:15:53412}
413
pfeldman552756452015-02-03 17:33:06414void Shell::InnerShowDevTools() {
[email protected]fee9eca02014-02-14 19:24:40415 if (!devtools_frontend_) {
pfeldman552756452015-02-03 17:33:06416 devtools_frontend_ = ShellDevToolsFrontend::Show(web_contents());
[email protected]fee9eca02014-02-14 19:24:40417 devtools_observer_.reset(new DevToolsWebContentsObserver(
418 this, devtools_frontend_->frontend_shell()->web_contents()));
419 }
420
421 devtools_frontend_->Activate();
422 devtools_frontend_->Focus();
423}
424
[email protected]7fff43e2013-05-21 20:21:10425void Shell::OnDevToolsWebContentsDestroyed() {
426 devtools_observer_.reset();
427 devtools_frontend_ = NULL;
428}
429
[email protected]9fbd3f862011-09-20 23:31:34430} // namespace content