diff options
author | pfeldman@chromium.org <pfeldman@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2014-04-29 14:09:25 +0000 |
---|---|---|
committer | pfeldman@chromium.org <pfeldman@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2014-04-29 14:09:25 +0000 |
commit | 5ef358a82330132e3417774a04af15e4a27ff1b9 (patch) | |
tree | 91f4da8fd12e14a5de64378eeaf687ca83543731 /chrome | |
parent | 7f9a60e9685326279e540039d44a9f560d85835e (diff) | |
download | chromium_src-5ef358a82330132e3417774a04af15e4a27ff1b9.zip chromium_src-5ef358a82330132e3417774a04af15e4a27ff1b9.tar.gz chromium_src-5ef358a82330132e3417774a04af15e4a27ff1b9.tar.bz2 |
DevTools: extract DevToolsWindowBase, leave docking, unload and factory logic in DevToolsWindow.
R=dgozman@chromium.org, vsevik@chromium.org
TBR=jam for chrome/chrome.gyp
Review URL: https://codereview.chromium.org/253823005
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@266873 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'chrome')
-rw-r--r-- | chrome/browser/devtools/devtools_sanity_browsertest.cc | 8 | ||||
-rw-r--r-- | chrome/browser/devtools/devtools_window.cc | 766 | ||||
-rw-r--r-- | chrome/browser/devtools/devtools_window.h | 136 | ||||
-rw-r--r-- | chrome/browser/devtools/devtools_window_base.cc | 685 | ||||
-rw-r--r-- | chrome/browser/devtools/devtools_window_base.h | 161 | ||||
-rw-r--r-- | chrome/chrome.gyp | 3 |
6 files changed, 956 insertions, 803 deletions
diff --git a/chrome/browser/devtools/devtools_sanity_browsertest.cc b/chrome/browser/devtools/devtools_sanity_browsertest.cc index e3fab99..8b8c48b 100644 --- a/chrome/browser/devtools/devtools_sanity_browsertest.cc +++ b/chrome/browser/devtools/devtools_sanity_browsertest.cc @@ -89,14 +89,14 @@ void RunTestFunction(DevToolsWindow* window, const char* test_name) { // files have been loaded) and has runTest method. ASSERT_TRUE( content::ExecuteScriptAndExtractString( - window->GetRenderViewHost(), + window->web_contents()->GetRenderViewHost(), "window.domAutomationController.send(" " '' + (window.uiTests && (typeof uiTests.runTest)));", &result)); ASSERT_EQ("function", result) << "DevTools front-end is broken."; ASSERT_TRUE(content::ExecuteScriptAndExtractString( - window->GetRenderViewHost(), + window->web_contents()->GetRenderViewHost(), base::StringPrintf("uiTests.runTest('%s')", test_name), &result)); EXPECT_EQ("[OK]", result); @@ -539,7 +539,7 @@ class WorkerDevToolsSanityTest : public InProcessBrowserTest { worker_data->worker_process_id, worker_data->worker_route_id)); window_ = DevToolsWindow::OpenDevToolsWindowForWorker(profile, agent_host); - RenderViewHost* client_rvh = window_->GetRenderViewHost(); + RenderViewHost* client_rvh = window_->web_contents()->GetRenderViewHost(); WebContents* client_contents = WebContents::FromRenderViewHost(client_rvh); content::WaitForLoadStop(client_contents); } @@ -871,7 +871,7 @@ IN_PROC_BROWSER_TEST_F(DevToolsSanityTest, TestPageWithNoJavaScript) { std::string result; ASSERT_TRUE( content::ExecuteScriptAndExtractString( - window_->GetRenderViewHost(), + window_->web_contents()->GetRenderViewHost(), "window.domAutomationController.send(" " '' + (window.uiTests && (typeof uiTests.runTest)));", &result)); diff --git a/chrome/browser/devtools/devtools_window.cc b/chrome/browser/devtools/devtools_window.cc index 8b12c80..7b1c46d 100644 --- a/chrome/browser/devtools/devtools_window.cc +++ b/chrome/browser/devtools/devtools_window.cc @@ -6,32 +6,16 @@ #include <algorithm> -#include "base/command_line.h" #include "base/json/json_reader.h" -#include "base/json/json_writer.h" -#include "base/lazy_instance.h" #include "base/metrics/histogram.h" #include "base/prefs/scoped_user_pref_update.h" -#include "base/strings/string_number_conversions.h" -#include "base/strings/string_util.h" -#include "base/strings/utf_string_conversions.h" #include "base/time/time.h" #include "base/values.h" -#include "chrome/browser/browser_process.h" -#include "chrome/browser/chrome_notification_types.h" #include "chrome/browser/chrome_page_zoom.h" -#include "chrome/browser/extensions/api/debugger/debugger_api.h" -#include "chrome/browser/extensions/chrome_extension_web_contents_observer.h" -#include "chrome/browser/extensions/extension_service.h" #include "chrome/browser/file_select_helper.h" -#include "chrome/browser/infobars/confirm_infobar_delegate.h" -#include "chrome/browser/infobars/infobar_service.h" #include "chrome/browser/prefs/pref_service_syncable.h" #include "chrome/browser/profiles/profile.h" #include "chrome/browser/sessions/session_tab_helper.h" -#include "chrome/browser/themes/theme_properties.h" -#include "chrome/browser/themes/theme_service.h" -#include "chrome/browser/themes/theme_service_factory.h" #include "chrome/browser/ui/browser.h" #include "chrome/browser/ui/browser_dialogs.h" #include "chrome/browser/ui/browser_iterator.h" @@ -42,19 +26,14 @@ #include "chrome/browser/ui/tabs/tab_strip_model.h" #include "chrome/browser/ui/webui/devtools_ui.h" #include "chrome/common/chrome_switches.h" -#include "chrome/common/extensions/manifest_url_handler.h" #include "chrome/common/pref_names.h" #include "chrome/common/render_messages.h" #include "chrome/common/url_constants.h" -#include "components/infobars/core/infobar.h" #include "components/user_prefs/pref_registry_syncable.h" #include "content/public/browser/browser_thread.h" -#include "content/public/browser/child_process_security_policy.h" #include "content/public/browser/devtools_agent_host.h" #include "content/public/browser/devtools_client_host.h" #include "content/public/browser/devtools_manager.h" -#include "content/public/browser/favicon_status.h" -#include "content/public/browser/load_notification_details.h" #include "content/public/browser/native_web_keyboard_event.h" #include "content/public/browser/navigation_controller.h" #include "content/public/browser/navigation_entry.h" @@ -66,111 +45,32 @@ #include "content/public/browser/web_contents.h" #include "content/public/browser/web_contents_observer.h" #include "content/public/browser/web_contents_view.h" -#include "content/public/common/bindings_policy.h" #include "content/public/common/content_client.h" #include "content/public/common/page_transition_types.h" -#include "content/public/common/renderer_preferences.h" #include "content/public/common/url_constants.h" #include "content/public/test/test_utils.h" -#include "extensions/browser/extension_system.h" -#include "extensions/common/extension_set.h" -#include "grit/generated_resources.h" #include "third_party/WebKit/public/web/WebInputEvent.h" -#include "ui/base/l10n/l10n_util.h" #include "ui/events/keycodes/keyboard_codes.h" using base::DictionaryValue; using blink::WebInputEvent; using content::BrowserThread; using content::DevToolsAgentHost; - - -// DevToolsConfirmInfoBarDelegate --------------------------------------------- - -class DevToolsConfirmInfoBarDelegate : public ConfirmInfoBarDelegate { - public: - // If |infobar_service| is NULL, runs |callback| with a single argument with - // value "false". Otherwise, creates a dev tools confirm infobar and delegate - // and adds the infobar to |infobar_service|. - static void Create(InfoBarService* infobar_service, - const DevToolsWindow::InfoBarCallback& callback, - const base::string16& message); - - private: - DevToolsConfirmInfoBarDelegate( - const DevToolsWindow::InfoBarCallback& callback, - const base::string16& message); - virtual ~DevToolsConfirmInfoBarDelegate(); - - virtual base::string16 GetMessageText() const OVERRIDE; - virtual base::string16 GetButtonLabel(InfoBarButton button) const OVERRIDE; - virtual bool Accept() OVERRIDE; - virtual bool Cancel() OVERRIDE; - - DevToolsWindow::InfoBarCallback callback_; - const base::string16 message_; - - DISALLOW_COPY_AND_ASSIGN(DevToolsConfirmInfoBarDelegate); -}; - -void DevToolsConfirmInfoBarDelegate::Create( - InfoBarService* infobar_service, - const DevToolsWindow::InfoBarCallback& callback, - const base::string16& message) { - if (!infobar_service) { - callback.Run(false); - return; - } - - infobar_service->AddInfoBar(ConfirmInfoBarDelegate::CreateInfoBar( - scoped_ptr<ConfirmInfoBarDelegate>( - new DevToolsConfirmInfoBarDelegate(callback, message)))); -} - -DevToolsConfirmInfoBarDelegate::DevToolsConfirmInfoBarDelegate( - const DevToolsWindow::InfoBarCallback& callback, - const base::string16& message) - : ConfirmInfoBarDelegate(), - callback_(callback), - message_(message) { -} - -DevToolsConfirmInfoBarDelegate::~DevToolsConfirmInfoBarDelegate() { - if (!callback_.is_null()) - callback_.Run(false); -} - -base::string16 DevToolsConfirmInfoBarDelegate::GetMessageText() const { - return message_; -} - -base::string16 DevToolsConfirmInfoBarDelegate::GetButtonLabel( - InfoBarButton button) const { - return l10n_util::GetStringUTF16((button == BUTTON_OK) ? - IDS_DEV_TOOLS_CONFIRM_ALLOW_BUTTON : IDS_DEV_TOOLS_CONFIRM_DENY_BUTTON); -} - -bool DevToolsConfirmInfoBarDelegate::Accept() { - callback_.Run(true); - callback_.Reset(); - return true; -} - -bool DevToolsConfirmInfoBarDelegate::Cancel() { - callback_.Run(false); - callback_.Reset(); - return true; -} - -// DevToolsEventForwarder ----------------------------------------------------- +using content::WebContents; namespace { +typedef std::vector<DevToolsWindow*> DevToolsWindows; +base::LazyInstance<DevToolsWindows>::Leaky g_instances = + LAZY_INSTANCE_INITIALIZER; + static const char kKeyUpEventName[] = "keyup"; static const char kKeyDownEventName[] = "keydown"; } // namespace +// DevToolsEventForwarder ----------------------------------------------------- + class DevToolsEventForwarder { public: explicit DevToolsEventForwarder(DevToolsWindow* window) @@ -285,10 +185,10 @@ int DevToolsEventForwarder::VirtualKeyCodeWithoutLocation(int key_code) class DevToolsWindow::InspectedWebContentsObserver : public content::WebContentsObserver { public: - explicit InspectedWebContentsObserver(content::WebContents* web_contents); + explicit InspectedWebContentsObserver(WebContents* web_contents); virtual ~InspectedWebContentsObserver(); - content::WebContents* web_contents() { + WebContents* web_contents() { return WebContentsObserver::web_contents(); } @@ -297,94 +197,18 @@ class DevToolsWindow::InspectedWebContentsObserver }; DevToolsWindow::InspectedWebContentsObserver::InspectedWebContentsObserver( - content::WebContents* web_contents) + WebContents* web_contents) : WebContentsObserver(web_contents) { } DevToolsWindow::InspectedWebContentsObserver::~InspectedWebContentsObserver() { } - -// DevToolsWindow::FrontendWebContentsObserver -------------------------------- - -class DevToolsWindow::FrontendWebContentsObserver - : public content::WebContentsObserver { - public: - explicit FrontendWebContentsObserver(DevToolsWindow* window); - virtual ~FrontendWebContentsObserver(); - - private: - // contents::WebContentsObserver: - virtual void AboutToNavigateRenderView( - content::RenderViewHost* render_view_host) OVERRIDE; - virtual void DocumentOnLoadCompletedInMainFrame(int32 page_id) OVERRIDE; - virtual void WebContentsDestroyed(content::WebContents*) OVERRIDE; - - DevToolsWindow* devtools_window_; - DISALLOW_COPY_AND_ASSIGN(FrontendWebContentsObserver); -}; - -DevToolsWindow::FrontendWebContentsObserver::FrontendWebContentsObserver( - DevToolsWindow* devtools_window) - : WebContentsObserver(devtools_window->web_contents()), - devtools_window_(devtools_window) { -} - -void DevToolsWindow::FrontendWebContentsObserver::WebContentsDestroyed( - content::WebContents* contents) { - delete devtools_window_; -} - -DevToolsWindow::FrontendWebContentsObserver::~FrontendWebContentsObserver() { -} - -void DevToolsWindow::FrontendWebContentsObserver::AboutToNavigateRenderView( - content::RenderViewHost* render_view_host) { - content::DevToolsClientHost::SetupDevToolsFrontendClient(render_view_host); -} - -void DevToolsWindow::FrontendWebContentsObserver:: - DocumentOnLoadCompletedInMainFrame(int32 page_id) { - devtools_window_->DocumentOnLoadCompletedInMainFrame(); -} - // DevToolsWindow ------------------------------------------------------------- -namespace { - -typedef std::vector<DevToolsWindow*> DevToolsWindows; -base::LazyInstance<DevToolsWindows>::Leaky g_instances = - LAZY_INSTANCE_INITIALIZER; - -static const char kFrontendHostId[] = "id"; -static const char kFrontendHostMethod[] = "method"; -static const char kFrontendHostParams[] = "params"; - -std::string SkColorToRGBAString(SkColor color) { - // We avoid StringPrintf because it will use locale specific formatters for - // the double (e.g. ',' instead of '.' in German). - return "rgba(" + base::IntToString(SkColorGetR(color)) + "," + - base::IntToString(SkColorGetG(color)) + "," + - base::IntToString(SkColorGetB(color)) + "," + - base::DoubleToString(SkColorGetA(color) / 255.0) + ")"; -} - -base::DictionaryValue* CreateFileSystemValue( - DevToolsFileHelper::FileSystem file_system) { - base::DictionaryValue* file_system_value = new base::DictionaryValue(); - file_system_value->SetString("fileSystemName", file_system.file_system_name); - file_system_value->SetString("rootURL", file_system.root_url); - file_system_value->SetString("fileSystemPath", file_system.file_system_path); - return file_system_value; -} - -} // namespace - const char DevToolsWindow::kDevToolsApp[] = "DevToolsApp"; DevToolsWindow::~DevToolsWindow() { - content::DevToolsManager::GetInstance()->ClientHostClosing( - frontend_host_.get()); UpdateBrowserToolbar(); DevToolsWindows* instances = g_instances.Pointer(); @@ -392,14 +216,6 @@ DevToolsWindow::~DevToolsWindow() { std::find(instances->begin(), instances->end(), this)); DCHECK(it != instances->end()); instances->erase(it); - - for (IndexingJobsMap::const_iterator jobs_it(indexing_jobs_.begin()); - jobs_it != indexing_jobs_.end(); ++jobs_it) { - jobs_it->second->Stop(); - } - indexing_jobs_.clear(); - if (device_listener_enabled_) - EnableRemoteDeviceCounter(false); } // static @@ -444,7 +260,7 @@ void DevToolsWindow::RegisterProfilePrefs( // static DevToolsWindow* DevToolsWindow::GetDockedInstanceForInspectedTab( - content::WebContents* inspected_web_contents) { + WebContents* inspected_web_contents) { DevToolsWindow* window = GetInstanceForInspectedRenderViewHost( inspected_web_contents->GetRenderViewHost()); if (!window) @@ -469,7 +285,7 @@ DevToolsWindow* DevToolsWindow::GetInstanceForInspectedRenderViewHost( // static DevToolsWindow* DevToolsWindow::GetInstanceForInspectedWebContents( - content::WebContents* inspected_web_contents) { + WebContents* inspected_web_contents) { if (!inspected_web_contents) return NULL; return GetInstanceForInspectedRenderViewHost( @@ -490,7 +306,7 @@ DevToolsWindow* DevToolsWindow::OpenDevToolsWindowForWorker( window = DevToolsWindow::CreateDevToolsWindowForWorker(profile); // Will disconnect the current client host if there is one. content::DevToolsManager::GetInstance()->RegisterDevToolsClientHostFor( - worker_agent, window->frontend_host_.get()); + worker_agent, window->frontend_host()); } window->ScheduleShow(DevToolsToggleAction::Show()); return window; @@ -561,7 +377,7 @@ void DevToolsWindow::OpenExternalFrontend( window = Create(profile, DevToolsUI::GetProxyURL(frontend_url), NULL, false, true, false); content::DevToolsManager::GetInstance()->RegisterDevToolsClientHostFor( - agent_host, window->frontend_host_.get()); + agent_host, window->frontend_host()); } window->ScheduleShow(DevToolsToggleAction::Show()); } @@ -583,7 +399,7 @@ DevToolsWindow* DevToolsWindow::ToggleDevToolsWindow( base::UserMetricsAction("DevTools_InspectRenderer")); window = Create(profile, GURL(), inspected_rvh, false, false, true); manager->RegisterDevToolsClientHostFor(agent.get(), - window->frontend_host_.get()); + window->frontend_host()); do_open = true; } @@ -616,18 +432,6 @@ void DevToolsWindow::InspectElement(content::RenderViewHost* inspected_rvh, window->inspect_element_start_time_ = start_time; } -void DevToolsWindow::InspectedContentsClosing() { - intercepted_page_beforeunload_ = false; - // This will prevent any activity after frontend is loaded. - action_on_load_ = DevToolsToggleAction::NoOp(); - ignore_set_is_docked_ = true; - web_contents_->GetRenderViewHost()->ClosePage(); -} - -content::RenderViewHost* DevToolsWindow::GetRenderViewHost() { - return web_contents_->GetRenderViewHost(); -} - const DevToolsContentsResizingStrategy& DevToolsWindow::GetContentsResizingStrategy() const { return contents_resizing_strategy_; @@ -670,21 +474,21 @@ void DevToolsWindow::Show(const DevToolsToggleAction& action) { // Tell inspected browser to update splitter and switch to inspected panel. BrowserWindow* inspected_window = inspected_browser->window(); - web_contents_->SetDelegate(this); + web_contents()->SetDelegate(this); TabStripModel* tab_strip_model = inspected_browser->tab_strip_model(); tab_strip_model->ActivateTabAt(inspected_tab_index, true); inspected_window->UpdateDevTools(); - web_contents_->GetView()->SetInitialFocus(); + web_contents()->GetView()->SetInitialFocus(); inspected_window->Show(); // On Aura, focusing once is not enough. Do it again. // Note that focusing only here but not before isn't enough either. We just // need to focus twice. - web_contents_->GetView()->SetInitialFocus(); + web_contents()->GetView()->SetInitialFocus(); - PrefsTabHelper::CreateForWebContents(web_contents_); - GetRenderViewHost()->SyncRendererPrefs(); + PrefsTabHelper::CreateForWebContents(web_contents()); + web_contents()->GetRenderViewHost()->SyncRendererPrefs(); DoAction(action); return; @@ -700,14 +504,14 @@ void DevToolsWindow::Show(const DevToolsToggleAction& action) { if (should_show_window) { browser_->window()->Show(); - web_contents_->GetView()->SetInitialFocus(); + web_contents()->GetView()->SetInitialFocus(); } DoAction(action); } // static -bool DevToolsWindow::HandleBeforeUnload(content::WebContents* frontend_contents, +bool DevToolsWindow::HandleBeforeUnload(WebContents* frontend_contents, bool proceed, bool* proceed_to_fire_unload) { DevToolsWindow* window = AsDevToolsWindow( frontend_contents->GetRenderViewHost()); @@ -721,7 +525,7 @@ bool DevToolsWindow::HandleBeforeUnload(content::WebContents* frontend_contents, } // static -bool DevToolsWindow::InterceptPageBeforeUnload(content::WebContents* contents) { +bool DevToolsWindow::InterceptPageBeforeUnload(WebContents* contents) { DevToolsWindow* window = DevToolsWindow::GetInstanceForInspectedRenderViewHost( contents->GetRenderViewHost()); @@ -743,7 +547,7 @@ bool DevToolsWindow::InterceptPageBeforeUnload(content::WebContents* contents) { // static bool DevToolsWindow::NeedsToInterceptBeforeUnload( - content::WebContents* contents) { + WebContents* contents) { DevToolsWindow* window = DevToolsWindow::GetInstanceForInspectedRenderViewHost( contents->GetRenderViewHost()); @@ -759,7 +563,7 @@ bool DevToolsWindow::HasFiredBeforeUnloadEventForDevToolsBrowser( // beforeunload. if (browser->tab_strip_model()->empty()) return true; - content::WebContents* contents = + WebContents* contents = browser->tab_strip_model()->GetWebContentsAt(0); DevToolsWindow* window = AsDevToolsWindow(contents->GetRenderViewHost()); if (!window) @@ -768,7 +572,7 @@ bool DevToolsWindow::HasFiredBeforeUnloadEventForDevToolsBrowser( } // static -void DevToolsWindow::OnPageCloseCanceled(content::WebContents* contents) { +void DevToolsWindow::OnPageCloseCanceled(WebContents* contents) { DevToolsWindow *window = DevToolsWindow::GetInstanceForInspectedRenderViewHost( contents->GetRenderViewHost()); @@ -783,59 +587,29 @@ DevToolsWindow::DevToolsWindow(Profile* profile, const GURL& url, content::RenderViewHost* inspected_rvh, bool can_dock) - : profile_(profile), + : DevToolsWindowBase( + WebContents::Create(WebContents::CreateParams(profile)), url), browser_(NULL), is_docked_(true), can_dock_(can_dock), - device_listener_enabled_(false), // This initialization allows external front-end to work without changes. // We don't wait for docking call, but instead immediately show undocked. // Passing "dockSide=undocked" parameter ensures proper UI. load_state_(can_dock ? kNotLoaded : kIsDockedSet), action_on_load_(DevToolsToggleAction::NoOp()), ignore_set_is_docked_(false), - intercepted_page_beforeunload_(false), - weak_factory_(this) { - web_contents_ = - content::WebContents::Create(content::WebContents::CreateParams(profile)); - frontend_contents_observer_.reset(new FrontendWebContentsObserver(this)); - web_contents_->GetMutableRendererPrefs()->can_accept_load_drops = false; + intercepted_page_beforeunload_(false) { // Set up delegate, so we get fully-functional window immediately. // It will not appear in UI though until |load_state_ == kLoadCompleted|. - web_contents_->SetDelegate(this); - - web_contents_->GetController().LoadURL(url, content::Referrer(), - content::PAGE_TRANSITION_AUTO_TOPLEVEL, std::string()); - - frontend_host_.reset(content::DevToolsClientHost::CreateDevToolsFrontendHost( - web_contents_, this)); - file_helper_.reset(new DevToolsFileHelper(web_contents_, profile)); - file_system_indexer_ = new DevToolsFileSystemIndexer(); - extensions::ChromeExtensionWebContentsObserver::CreateForWebContents( - web_contents_); + web_contents()->SetDelegate(this); g_instances.Get().push_back(this); - // Wipe out page icon so that the default application icon is used. - content::NavigationEntry* entry = - web_contents_->GetController().GetActiveEntry(); - entry->GetFavicon().image = gfx::Image(); - entry->GetFavicon().valid = true; - - // Register on-load actions. - registrar_.Add( - this, chrome::NOTIFICATION_BROWSER_THEME_CHANGED, - content::Source<ThemeService>( - ThemeServiceFactory::GetForProfile(profile_))); - // There is no inspected_rvh in case of shared workers. if (inspected_rvh) inspected_contents_observer_.reset(new InspectedWebContentsObserver( content::WebContents::FromRenderViewHost(inspected_rvh))); - - embedder_message_dispatcher_.reset( - DevToolsEmbedderMessageDispatcher::createForDevToolsFrontend(this)); event_forwarder_.reset(new DevToolsEventForwarder(this)); } @@ -851,7 +625,7 @@ DevToolsWindow* DevToolsWindow::Create( // Check for a place to dock. Browser* browser = NULL; int tab; - content::WebContents* inspected_web_contents = + WebContents* inspected_web_contents = content::WebContents::FromRenderViewHost(inspected_rvh); if (!FindInspectedBrowserAndTabIndex(inspected_web_contents, &browser, &tab) || @@ -875,31 +649,22 @@ GURL DevToolsWindow::GetDevToolsURL(Profile* profile, bool shared_worker_frontend, bool external_frontend, bool can_dock) { + // Compatibility errors are encoded with data urls, pass them + // through with no decoration. if (base_url.SchemeIs("data")) return base_url; std::string frontend_url( base_url.is_empty() ? chrome::kChromeUIDevToolsURL : base_url.spec()); - ThemeService* tp = ThemeServiceFactory::GetForProfile(profile); - DCHECK(tp); std::string url_string( frontend_url + - ((frontend_url.find("?") == std::string::npos) ? "?" : "&") + - "dockSide=undocked" + // TODO(dgozman): remove this support in M38. - "&toolbarColor=" + - SkColorToRGBAString(tp->GetColor(ThemeProperties::COLOR_TOOLBAR)) + - "&textColor=" + - SkColorToRGBAString(tp->GetColor(ThemeProperties::COLOR_BOOKMARK_TEXT))); + ((frontend_url.find("?") == std::string::npos) ? "?" : "&")); if (shared_worker_frontend) url_string += "&isSharedWorker=true"; if (external_frontend) url_string += "&remoteFrontend=true"; if (can_dock) url_string += "&can_dock=true"; - if (CommandLine::ForCurrentProcess()->HasSwitch( - switches::kEnableDevToolsExperiments)) - url_string += "&experiments=true"; - url_string += "&updateAppcache"; return GURL(url_string); } @@ -910,7 +675,7 @@ DevToolsWindow* DevToolsWindow::FindDevToolsWindow( content::DevToolsManager* manager = content::DevToolsManager::GetInstance(); for (DevToolsWindows::iterator it(instances->begin()); it != instances->end(); ++it) { - if (manager->GetDevToolsAgentHostFor((*it)->frontend_host_.get()) == + if (manager->GetDevToolsAgentHostFor((*it)->frontend_host()) == agent_host) return *it; } @@ -925,50 +690,60 @@ DevToolsWindow* DevToolsWindow::AsDevToolsWindow( DevToolsWindows* instances = g_instances.Pointer(); for (DevToolsWindows::iterator it(instances->begin()); it != instances->end(); ++it) { - if ((*it)->web_contents_->GetRenderViewHost() == window_rvh) + if ((*it)->web_contents()->GetRenderViewHost() == window_rvh) return *it; } return NULL; } -void DevToolsWindow::Observe(int type, - const content::NotificationSource& source, - const content::NotificationDetails& details) { - DCHECK_EQ(chrome::NOTIFICATION_BROWSER_THEME_CHANGED, type); - UpdateTheme(); +void DevToolsWindow::InspectedContentsClosing() { + intercepted_page_beforeunload_ = false; + // This will prevent any activity after frontend is loaded. + action_on_load_ = DevToolsToggleAction::NoOp(); + ignore_set_is_docked_ = true; + DevToolsWindowBase::InspectedContentsClosing(); } -content::WebContents* DevToolsWindow::OpenURLFromTab( - content::WebContents* source, +WebContents* DevToolsWindow::OpenURLFromTab( + WebContents* source, const content::OpenURLParams& params) { - DCHECK(source == web_contents_); + DCHECK(source == web_contents()); if (!params.url.SchemeIs(content::kChromeDevToolsScheme)) { - content::WebContents* inspected_web_contents = GetInspectedWebContents(); + WebContents* inspected_web_contents = GetInspectedWebContents(); return inspected_web_contents ? inspected_web_contents->OpenURL(params) : NULL; } content::DevToolsManager* manager = content::DevToolsManager::GetInstance(); scoped_refptr<DevToolsAgentHost> agent_host( - manager->GetDevToolsAgentHostFor(frontend_host_.get())); + manager->GetDevToolsAgentHostFor(frontend_host())); if (!agent_host.get()) return NULL; - manager->ClientHostClosing(frontend_host_.get()); + manager->ClientHostClosing(frontend_host()); manager->RegisterDevToolsClientHostFor(agent_host.get(), - frontend_host_.get()); + frontend_host()); content::NavigationController::LoadURLParams load_url_params(params.url); - web_contents_->GetController().LoadURLWithParams(load_url_params); - return web_contents_; + web_contents()->GetController().LoadURLWithParams(load_url_params); + return web_contents(); +} + +void DevToolsWindow::ActivateContents(WebContents* contents) { + if (is_docked_) { + WebContents* inspected_tab = GetInspectedWebContents(); + inspected_tab->GetDelegate()->ActivateContents(inspected_tab); + } else { + browser_->window()->Activate(); + } } -void DevToolsWindow::AddNewContents(content::WebContents* source, - content::WebContents* new_contents, +void DevToolsWindow::AddNewContents(WebContents* source, + WebContents* new_contents, WindowOpenDisposition disposition, const gfx::Rect& initial_pos, bool user_gesture, bool* was_blocked) { - content::WebContents* inspected_web_contents = GetInspectedWebContents(); + WebContents* inspected_web_contents = GetInspectedWebContents(); if (inspected_web_contents) { inspected_web_contents->GetDelegate()->AddNewContents( source, new_contents, disposition, initial_pos, user_gesture, @@ -976,7 +751,7 @@ void DevToolsWindow::AddNewContents(content::WebContents* source, } } -void DevToolsWindow::CloseContents(content::WebContents* source) { +void DevToolsWindow::CloseContents(WebContents* source) { CHECK(is_docked_); // This will prevent any activity after frontend is loaded. action_on_load_ = DevToolsToggleAction::NoOp(); @@ -985,10 +760,10 @@ void DevToolsWindow::CloseContents(content::WebContents* source) { BrowserWindow* inspected_window = GetInspectedBrowserWindow(); if (inspected_window) inspected_window->UpdateDevTools(); - // In case of docked web_contents_, we own it so delete here. + // In case of docked web_contents(), we own it so delete here. // Embedding DevTools window will be deleted as a result of // WebContentsDestroyed callback. - delete web_contents_; + delete web_contents(); } void DevToolsWindow::ContentsZoomChange(bool zoom_in) { @@ -997,19 +772,19 @@ void DevToolsWindow::ContentsZoomChange(bool zoom_in) { zoom_in ? content::PAGE_ZOOM_IN : content::PAGE_ZOOM_OUT); } -void DevToolsWindow::BeforeUnloadFired(content::WebContents* tab, +void DevToolsWindow::BeforeUnloadFired(WebContents* tab, bool proceed, bool* proceed_to_fire_unload) { if (!intercepted_page_beforeunload_) { // Docked devtools window closed directly. if (proceed) { content::DevToolsManager::GetInstance()->ClientHostClosing( - frontend_host_.get()); + frontend_host()); } *proceed_to_fire_unload = proceed; } else { // Inspected page is attempting to close. - content::WebContents* inspected_web_contents = GetInspectedWebContents(); + WebContents* inspected_web_contents = GetInspectedWebContents(); if (proceed) { inspected_web_contents->DispatchBeforeUnload(false); } else { @@ -1023,7 +798,7 @@ void DevToolsWindow::BeforeUnloadFired(content::WebContents* tab, } bool DevToolsWindow::PreHandleKeyboardEvent( - content::WebContents* source, + WebContents* source, const content::NativeWebKeyboardEvent& event, bool* is_keyboard_shortcut) { if (is_docked_) { @@ -1037,7 +812,7 @@ bool DevToolsWindow::PreHandleKeyboardEvent( } void DevToolsWindow::HandleKeyboardEvent( - content::WebContents* source, + WebContents* source, const content::NativeWebKeyboardEvent& event) { if (is_docked_) { if (event.windowsKeyCode == 0x08) { @@ -1051,25 +826,25 @@ void DevToolsWindow::HandleKeyboardEvent( } content::JavaScriptDialogManager* DevToolsWindow::GetJavaScriptDialogManager() { - content::WebContents* inspected_web_contents = GetInspectedWebContents(); + WebContents* inspected_web_contents = GetInspectedWebContents(); return (inspected_web_contents && inspected_web_contents->GetDelegate()) ? inspected_web_contents->GetDelegate()->GetJavaScriptDialogManager() : content::WebContentsDelegate::GetJavaScriptDialogManager(); } content::ColorChooser* DevToolsWindow::OpenColorChooser( - content::WebContents* web_contents, + WebContents* web_contents, SkColor initial_color, const std::vector<content::ColorSuggestion>& suggestions) { return chrome::ShowColorChooser(web_contents, initial_color); } -void DevToolsWindow::RunFileChooser(content::WebContents* web_contents, +void DevToolsWindow::RunFileChooser(WebContents* web_contents, const content::FileChooserParams& params) { FileSelectHelper::RunFileChooser(web_contents, params); } -void DevToolsWindow::WebContentsFocused(content::WebContents* contents) { +void DevToolsWindow::WebContentsFocused(WebContents* contents) { Browser* inspected_browser = NULL; int inspected_tab_index = -1; if (is_docked_ && FindInspectedBrowserAndTabIndex(GetInspectedWebContents(), @@ -1079,7 +854,7 @@ void DevToolsWindow::WebContentsFocused(content::WebContents* contents) { } bool DevToolsWindow::PreHandleGestureEvent( - content::WebContents* source, + WebContents* source, const blink::WebGestureEvent& event) { // Disable pinch zooming. return event.type == blink::WebGestureEvent::GesturePinchBegin || @@ -1087,57 +862,19 @@ bool DevToolsWindow::PreHandleGestureEvent( event.type == blink::WebGestureEvent::GesturePinchEnd; } -void DevToolsWindow::DispatchOnEmbedder(const std::string& message) { - std::string method; - base::ListValue empty_params; - base::ListValue* params = &empty_params; - - base::DictionaryValue* dict = NULL; - scoped_ptr<base::Value> parsed_message(base::JSONReader::Read(message)); - if (!parsed_message || - !parsed_message->GetAsDictionary(&dict) || - !dict->GetString(kFrontendHostMethod, &method) || - (dict->HasKey(kFrontendHostParams) && - !dict->GetList(kFrontendHostParams, ¶ms))) { - LOG(ERROR) << "Invalid message was sent to embedder: " << message; - return; - } - - int id = 0; - dict->GetInteger(kFrontendHostId, &id); - - std::string error; - embedder_message_dispatcher_->Dispatch(method, params, &error); - if (id) { - scoped_ptr<base::Value> id_value(base::Value::CreateIntegerValue(id)); - scoped_ptr<base::Value> error_value(base::Value::CreateStringValue(error)); - CallClientFunction("InspectorFrontendAPI.embedderMessageAck", - id_value.get(), error_value.get(), NULL); - } -} - void DevToolsWindow::ActivateWindow() { if (is_docked_ && GetInspectedBrowserWindow()) - web_contents_->GetView()->Focus(); + web_contents()->GetView()->Focus(); else if (!is_docked_ && !browser_->window()->IsActive()) browser_->window()->Activate(); } -void DevToolsWindow::ActivateContents(content::WebContents* contents) { - if (is_docked_) { - content::WebContents* inspected_tab = this->GetInspectedWebContents(); - inspected_tab->GetDelegate()->ActivateContents(inspected_tab); - } else { - browser_->window()->Activate(); - } -} - void DevToolsWindow::CloseWindow() { DCHECK(is_docked_); // This will prevent any activity after frontend is loaded. action_on_load_ = DevToolsToggleAction::NoOp(); ignore_set_is_docked_ = true; - web_contents_->DispatchBeforeUnload(false); + web_contents()->DispatchBeforeUnload(false); } void DevToolsWindow::SetContentsInsets( @@ -1222,7 +959,7 @@ void DevToolsWindow::SetIsDocked(bool dock_requested) { // the browser object's close and delete. Remove observer first. TabStripModel* tab_strip_model = browser_->tab_strip_model(); tab_strip_model->DetachWebContentsAt( - tab_strip_model->GetIndexOfWebContents(web_contents_)); + tab_strip_model->GetIndexOfWebContents(web_contents())); browser_ = NULL; } else if (!dock_requested && was_docked) { // Update inspected window to hide split and reset it. @@ -1238,7 +975,7 @@ void DevToolsWindow::OpenInNewTab(const std::string& url) { content::OpenURLParams params( GURL(url), content::Referrer(), NEW_FOREGROUND_TAB, content::PAGE_TRANSITION_LINK, false); - content::WebContents* inspected_web_contents = GetInspectedWebContents(); + WebContents* inspected_web_contents = GetInspectedWebContents(); if (inspected_web_contents) { inspected_web_contents->OpenURL(params); } else { @@ -1264,264 +1001,14 @@ void DevToolsWindow::OpenInNewTab(const std::string& url) { } } -void DevToolsWindow::SaveToFile(const std::string& url, - const std::string& content, - bool save_as) { - file_helper_->Save(url, content, save_as, - base::Bind(&DevToolsWindow::FileSavedAs, - weak_factory_.GetWeakPtr(), url), - base::Bind(&DevToolsWindow::CanceledFileSaveAs, - weak_factory_.GetWeakPtr(), url)); -} - -void DevToolsWindow::AppendToFile(const std::string& url, - const std::string& content) { - file_helper_->Append(url, content, - base::Bind(&DevToolsWindow::AppendedTo, - weak_factory_.GetWeakPtr(), url)); -} - -void DevToolsWindow::RequestFileSystems() { - CHECK(web_contents_->GetURL().SchemeIs(content::kChromeDevToolsScheme)); - file_helper_->RequestFileSystems(base::Bind( - &DevToolsWindow::FileSystemsLoaded, weak_factory_.GetWeakPtr())); -} - -void DevToolsWindow::AddFileSystem() { - CHECK(web_contents_->GetURL().SchemeIs(content::kChromeDevToolsScheme)); - file_helper_->AddFileSystem( - base::Bind(&DevToolsWindow::FileSystemAdded, weak_factory_.GetWeakPtr()), - base::Bind(&DevToolsWindow::ShowDevToolsConfirmInfoBar, - weak_factory_.GetWeakPtr())); -} - -void DevToolsWindow::RemoveFileSystem(const std::string& file_system_path) { - CHECK(web_contents_->GetURL().SchemeIs(content::kChromeDevToolsScheme)); - file_helper_->RemoveFileSystem(file_system_path); - base::StringValue file_system_path_value(file_system_path); - CallClientFunction("InspectorFrontendAPI.fileSystemRemoved", - &file_system_path_value, NULL, NULL); -} - -void DevToolsWindow::UpgradeDraggedFileSystemPermissions( - const std::string& file_system_url) { - CHECK(web_contents_->GetURL().SchemeIs(content::kChromeDevToolsScheme)); - file_helper_->UpgradeDraggedFileSystemPermissions( - file_system_url, - base::Bind(&DevToolsWindow::FileSystemAdded, weak_factory_.GetWeakPtr()), - base::Bind(&DevToolsWindow::ShowDevToolsConfirmInfoBar, - weak_factory_.GetWeakPtr())); -} - -void DevToolsWindow::IndexPath(int request_id, - const std::string& file_system_path) { - DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); - CHECK(web_contents_->GetURL().SchemeIs(content::kChromeDevToolsScheme)); - if (!file_helper_->IsFileSystemAdded(file_system_path)) { - IndexingDone(request_id, file_system_path); - return; - } - indexing_jobs_[request_id] = - scoped_refptr<DevToolsFileSystemIndexer::FileSystemIndexingJob>( - file_system_indexer_->IndexPath( - file_system_path, - Bind(&DevToolsWindow::IndexingTotalWorkCalculated, - weak_factory_.GetWeakPtr(), - request_id, - file_system_path), - Bind(&DevToolsWindow::IndexingWorked, - weak_factory_.GetWeakPtr(), - request_id, - file_system_path), - Bind(&DevToolsWindow::IndexingDone, - weak_factory_.GetWeakPtr(), - request_id, - file_system_path))); -} - -void DevToolsWindow::StopIndexing(int request_id) { - DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); - IndexingJobsMap::iterator it = indexing_jobs_.find(request_id); - if (it == indexing_jobs_.end()) - return; - it->second->Stop(); - indexing_jobs_.erase(it); -} - -void DevToolsWindow::SearchInPath(int request_id, - const std::string& file_system_path, - const std::string& query) { - DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); - CHECK(web_contents_->GetURL().SchemeIs(content::kChromeDevToolsScheme)); - if (!file_helper_->IsFileSystemAdded(file_system_path)) { - SearchCompleted(request_id, file_system_path, std::vector<std::string>()); - return; - } - file_system_indexer_->SearchInPath(file_system_path, - query, - Bind(&DevToolsWindow::SearchCompleted, - weak_factory_.GetWeakPtr(), - request_id, - file_system_path)); -} - -void DevToolsWindow::ZoomIn() { - chrome_page_zoom::Zoom(web_contents(), content::PAGE_ZOOM_IN); -} - -void DevToolsWindow::ZoomOut() { - chrome_page_zoom::Zoom(web_contents(), content::PAGE_ZOOM_OUT); -} - -void DevToolsWindow::ResetZoom() { - chrome_page_zoom::Zoom(web_contents(), content::PAGE_ZOOM_RESET); -} - -void DevToolsWindow::OpenUrlOnRemoteDeviceAndInspect( - const std::string& browser_id, - const std::string& url) { - if (remote_targets_handler_) - remote_targets_handler_->OpenAndInspect(browser_id, url, profile_); -} - -void DevToolsWindow::StartRemoteDevicesListener() { - remote_targets_handler_ = DevToolsRemoteTargetsUIHandler::CreateForAdb( - base::Bind(&DevToolsWindow::PopulateRemoteDevices, - base::Unretained(this)), - profile_); -} - -void DevToolsWindow::StopRemoteDevicesListener() { - remote_targets_handler_.reset(); -} - -void DevToolsWindow::EnableRemoteDeviceCounter(bool enable) { - DevToolsAndroidBridge* adb_bridge = - DevToolsAndroidBridge::Factory::GetForProfile(profile_); - if (!adb_bridge) - return; - - DCHECK(device_listener_enabled_ != enable); - device_listener_enabled_ = enable; - if (enable) - adb_bridge->AddDeviceCountListener(this); - else - adb_bridge->RemoveDeviceCountListener(this); -} - -void DevToolsWindow::DeviceCountChanged(int count) { - base::FundamentalValue value(count); - CallClientFunction( - "InspectorFrontendAPI.setRemoteDeviceCount", &value, NULL, NULL); -} - -void DevToolsWindow::PopulateRemoteDevices( - const std::string& source, - scoped_ptr<base::ListValue> targets) { - CallClientFunction( - "InspectorFrontendAPI.populateRemoteDevices", targets.get(), NULL, NULL); -} - -void DevToolsWindow::FileSavedAs(const std::string& url) { - base::StringValue url_value(url); - CallClientFunction("InspectorFrontendAPI.savedURL", &url_value, NULL, NULL); -} - -void DevToolsWindow::CanceledFileSaveAs(const std::string& url) { - base::StringValue url_value(url); - CallClientFunction("InspectorFrontendAPI.canceledSaveURL", - &url_value, NULL, NULL); -} - -void DevToolsWindow::AppendedTo(const std::string& url) { - base::StringValue url_value(url); - CallClientFunction("InspectorFrontendAPI.appendedToURL", &url_value, NULL, - NULL); -} - -void DevToolsWindow::FileSystemsLoaded( - const std::vector<DevToolsFileHelper::FileSystem>& file_systems) { - base::ListValue file_systems_value; - for (size_t i = 0; i < file_systems.size(); ++i) - file_systems_value.Append(CreateFileSystemValue(file_systems[i])); - CallClientFunction("InspectorFrontendAPI.fileSystemsLoaded", - &file_systems_value, NULL, NULL); -} - -void DevToolsWindow::FileSystemAdded( - const DevToolsFileHelper::FileSystem& file_system) { - scoped_ptr<base::StringValue> error_string_value( - new base::StringValue(std::string())); - scoped_ptr<base::DictionaryValue> file_system_value; - if (!file_system.file_system_path.empty()) - file_system_value.reset(CreateFileSystemValue(file_system)); - CallClientFunction("InspectorFrontendAPI.fileSystemAdded", - error_string_value.get(), file_system_value.get(), NULL); -} - -void DevToolsWindow::IndexingTotalWorkCalculated( - int request_id, - const std::string& file_system_path, - int total_work) { - DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); - base::FundamentalValue request_id_value(request_id); - base::StringValue file_system_path_value(file_system_path); - base::FundamentalValue total_work_value(total_work); - CallClientFunction("InspectorFrontendAPI.indexingTotalWorkCalculated", - &request_id_value, &file_system_path_value, - &total_work_value); -} - -void DevToolsWindow::IndexingWorked(int request_id, - const std::string& file_system_path, - int worked) { - DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); - base::FundamentalValue request_id_value(request_id); - base::StringValue file_system_path_value(file_system_path); - base::FundamentalValue worked_value(worked); - CallClientFunction("InspectorFrontendAPI.indexingWorked", &request_id_value, - &file_system_path_value, &worked_value); -} - -void DevToolsWindow::IndexingDone(int request_id, - const std::string& file_system_path) { - indexing_jobs_.erase(request_id); - DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); - base::FundamentalValue request_id_value(request_id); - base::StringValue file_system_path_value(file_system_path); - CallClientFunction("InspectorFrontendAPI.indexingDone", &request_id_value, - &file_system_path_value, NULL); -} - -void DevToolsWindow::SearchCompleted( - int request_id, - const std::string& file_system_path, - const std::vector<std::string>& file_paths) { - DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); - base::ListValue file_paths_value; - for (std::vector<std::string>::const_iterator it(file_paths.begin()); - it != file_paths.end(); ++it) { - file_paths_value.AppendString(*it); - } - base::FundamentalValue request_id_value(request_id); - base::StringValue file_system_path_value(file_system_path); - CallClientFunction("InspectorFrontendAPI.searchCompleted", &request_id_value, - &file_system_path_value, &file_paths_value); -} - -void DevToolsWindow::ShowDevToolsConfirmInfoBar( - const base::string16& message, - const InfoBarCallback& callback) { - DevToolsConfirmInfoBarDelegate::Create( - is_docked_ ? - InfoBarService::FromWebContents(GetInspectedWebContents()) : - InfoBarService::FromWebContents(web_contents_), - callback, message); +void DevToolsWindow::SetWhitelistedShortcuts( + const std::string& message) { + event_forwarder_->SetWhitelistedShortcuts(message); } void DevToolsWindow::CreateDevToolsBrowser() { std::string wp_key = GetDevToolsWindowPlacementPrefKey(); - PrefService* prefs = profile_->GetPrefs(); + PrefService* prefs = profile()->GetPrefs(); const base::DictionaryValue* wp_pref = prefs->GetDictionary(wp_key.c_str()); if (!wp_pref || wp_pref->empty()) { DictionaryPrefUpdate update(prefs, wp_key.c_str()); @@ -1535,18 +1022,18 @@ void DevToolsWindow::CreateDevToolsBrowser() { } browser_ = new Browser(Browser::CreateParams::CreateForDevTools( - profile_, + profile(), chrome::GetHostDesktopTypeForNativeView( - web_contents_->GetView()->GetNativeView()))); + web_contents()->GetView()->GetNativeView()))); browser_->tab_strip_model()->AddWebContents( - web_contents_, -1, content::PAGE_TRANSITION_AUTO_TOPLEVEL, + web_contents(), -1, content::PAGE_TRANSITION_AUTO_TOPLEVEL, TabStripModel::ADD_ACTIVE); - GetRenderViewHost()->SyncRendererPrefs(); + web_contents()->GetRenderViewHost()->SyncRendererPrefs(); } // static bool DevToolsWindow::FindInspectedBrowserAndTabIndex( - content::WebContents* inspected_web_contents, Browser** browser, int* tab) { + WebContents* inspected_web_contents, Browser** browser, int* tab) { if (!inspected_web_contents) return false; @@ -1606,20 +1093,8 @@ void DevToolsWindow::DoAction(const DevToolsToggleAction& action) { } } -void DevToolsWindow::UpdateTheme() { - ThemeService* tp = ThemeServiceFactory::GetForProfile(profile_); - DCHECK(tp); - - std::string command("InspectorFrontendAPI.setToolbarColors(\"" + - SkColorToRGBAString(tp->GetColor(ThemeProperties::COLOR_TOOLBAR)) + - "\", \"" + - SkColorToRGBAString(tp->GetColor(ThemeProperties::COLOR_BOOKMARK_TEXT)) + - "\")"); - web_contents_->GetMainFrame()->ExecuteJavaScript(base::ASCIIToUTF16(command)); -} - void DevToolsWindow::AddDevToolsExtensionsToClient() { - content::WebContents* inspected_web_contents = GetInspectedWebContents(); + WebContents* inspected_web_contents = GetInspectedWebContents(); if (inspected_web_contents) { SessionTabHelper* session_tab_helper = SessionTabHelper::FromWebContents(inspected_web_contents); @@ -1628,56 +1103,7 @@ void DevToolsWindow::AddDevToolsExtensionsToClient() { CallClientFunction("WebInspector.setInspectedTabId", &tabId, NULL, NULL); } } - - Profile* profile = - Profile::FromBrowserContext(web_contents_->GetBrowserContext()); - const ExtensionService* extension_service = extensions::ExtensionSystem::Get( - profile->GetOriginalProfile())->extension_service(); - if (!extension_service) - return; - const extensions::ExtensionSet* extensions = extension_service->extensions(); - - base::ListValue results; - for (extensions::ExtensionSet::const_iterator extension(extensions->begin()); - extension != extensions->end(); ++extension) { - if (extensions::ManifestURL::GetDevToolsPage(extension->get()).is_empty()) - continue; - base::DictionaryValue* extension_info = new base::DictionaryValue(); - extension_info->Set( - "startPage", - new base::StringValue( - extensions::ManifestURL::GetDevToolsPage(extension->get()).spec())); - extension_info->Set("name", new base::StringValue((*extension)->name())); - extension_info->Set( - "exposeExperimentalAPIs", - new base::FundamentalValue((*extension)->HasAPIPermission( - extensions::APIPermission::kExperimental))); - results.Append(extension_info); - } - CallClientFunction("WebInspector.addExtensions", &results, NULL, NULL); -} - -void DevToolsWindow::CallClientFunction(const std::string& function_name, - const base::Value* arg1, - const base::Value* arg2, - const base::Value* arg3) { - std::string params; - if (arg1) { - std::string json; - base::JSONWriter::Write(arg1, &json); - params.append(json); - if (arg2) { - base::JSONWriter::Write(arg2, &json); - params.append(", " + json); - if (arg3) { - base::JSONWriter::Write(arg3, &json); - params.append(", " + json); - } - } - } - base::string16 javascript = - base::UTF8ToUTF16(function_name + "(" + params + ");"); - web_contents_->GetMainFrame()->ExecuteJavaScript(javascript); + DevToolsWindowBase::AddDevToolsExtensionsToClient(); } void DevToolsWindow::UpdateBrowserToolbar() { @@ -1686,12 +1112,13 @@ void DevToolsWindow::UpdateBrowserToolbar() { inspected_window->UpdateToolbar(NULL); } -content::WebContents* DevToolsWindow::GetInspectedWebContents() { +WebContents* DevToolsWindow::GetInspectedWebContents() { return inspected_contents_observer_ ? inspected_contents_observer_->web_contents() : NULL; } void DevToolsWindow::DocumentOnLoadCompletedInMainFrame() { + DevToolsWindowBase::DocumentOnLoadCompletedInMainFrame(); // We could be in kLoadCompleted state already if frontend reloads itself. if (load_state_ != kLoadCompleted) { // Load is completed when both kIsDockedSet and kOnLoadFired happened. @@ -1705,8 +1132,6 @@ void DevToolsWindow::DocumentOnLoadCompletedInMainFrame() { void DevToolsWindow::LoadCompleted() { Show(action_on_load_); action_on_load_ = DevToolsToggleAction::NoOp(); - UpdateTheme(); - AddDevToolsExtensionsToClient(); if (!load_completed_callback_.is_null()) { load_completed_callback_.Run(); load_completed_callback_ = base::Closure(); @@ -1722,11 +1147,6 @@ void DevToolsWindow::SetLoadCompletedCallback(const base::Closure& closure) { load_completed_callback_ = closure; } -void DevToolsWindow::SetWhitelistedShortcuts( - const std::string& message) { - event_forwarder_->SetWhitelistedShortcuts(message); -} - bool DevToolsWindow::ForwardKeyboardEvent( const content::NativeWebKeyboardEvent& event) { return event_forwarder_->ForwardEvent(event); diff --git a/chrome/browser/devtools/devtools_window.h b/chrome/browser/devtools/devtools_window.h index a7c7153..79972f4 100644 --- a/chrome/browser/devtools/devtools_window.h +++ b/chrome/browser/devtools/devtools_window.h @@ -5,62 +5,29 @@ #ifndef CHROME_BROWSER_DEVTOOLS_DEVTOOLS_WINDOW_H_ #define CHROME_BROWSER_DEVTOOLS_DEVTOOLS_WINDOW_H_ -#include <string> -#include <vector> - -#include "base/basictypes.h" -#include "base/memory/scoped_ptr.h" -#include "base/memory/weak_ptr.h" -#include "base/strings/string16.h" -#include "chrome/browser/devtools/device/devtools_android_bridge.h" #include "chrome/browser/devtools/devtools_contents_resizing_strategy.h" -#include "chrome/browser/devtools/devtools_embedder_message_dispatcher.h" -#include "chrome/browser/devtools/devtools_file_helper.h" -#include "chrome/browser/devtools/devtools_file_system_indexer.h" -#include "chrome/browser/devtools/devtools_targets_ui.h" #include "chrome/browser/devtools/devtools_toggle_action.h" -#include "content/public/browser/devtools_client_host.h" -#include "content/public/browser/devtools_frontend_host_delegate.h" -#include "content/public/browser/notification_observer.h" -#include "content/public/browser/notification_registrar.h" +#include "chrome/browser/devtools/devtools_window_base.h" #include "content/public/browser/web_contents_delegate.h" -#include "ui/gfx/size.h" class Browser; class BrowserWindow; class DevToolsControllerTest; class DevToolsEventForwarder; -class Profile; - -namespace base { -class Value; -} namespace content { class DevToolsAgentHost; -class DevToolsClientHost; -struct FileChooserParams; struct NativeWebKeyboardEvent; class RenderViewHost; -class WebContents; -} - -namespace IPC { -class Message; } namespace user_prefs { class PrefRegistrySyncable; } -class DevToolsWindow : private content::NotificationObserver, - private content::WebContentsDelegate, - private content::DevToolsFrontendHostDelegate, - private DevToolsEmbedderMessageDispatcher::Delegate, - private DevToolsAndroidBridge::DeviceCountListener { +class DevToolsWindow : public DevToolsWindowBase, + public content::WebContentsDelegate { public: - typedef base::Callback<void(bool)> InfoBarCallback; - static const char kDevToolsApp[]; virtual ~DevToolsWindow(); @@ -122,14 +89,8 @@ class DevToolsWindow : private content::NotificationObserver, static void InspectElement( content::RenderViewHost* inspected_rvh, int x, int y); - // content::DevToolsFrontendHostDelegate: - virtual void InspectedContentsClosing() OVERRIDE; - - content::WebContents* web_contents() { return web_contents_; } Browser* browser() { return browser_; } // For tests. - content::RenderViewHost* GetRenderViewHost(); - // Inspected WebContents is placed over DevTools WebContents in docked mode. // The following method returns the resizing strategy of inspected // WebContents relative to DevTools WebContents. @@ -267,15 +228,14 @@ class DevToolsWindow : private content::NotificationObserver, bool force_open, const DevToolsToggleAction& action); - // content::NotificationObserver: - virtual void Observe(int type, - const content::NotificationSource& source, - const content::NotificationDetails& details) OVERRIDE; + // content::DevToolsFrontendHostDelegate override: + virtual void InspectedContentsClosing() OVERRIDE; // content::WebContentsDelegate: virtual content::WebContents* OpenURLFromTab( content::WebContents* source, const content::OpenURLParams& params) OVERRIDE; + virtual void ActivateContents(content::WebContents* contents) OVERRIDE; virtual void AddNewContents(content::WebContents* source, content::WebContents* new_contents, WindowOpenDisposition disposition, @@ -308,12 +268,8 @@ class DevToolsWindow : private content::NotificationObserver, content::WebContents* source, const blink::WebGestureEvent& event) OVERRIDE; - // content::DevToolsFrontendHostDelegate override: - virtual void DispatchOnEmbedder(const std::string& message) OVERRIDE; - // DevToolsEmbedderMessageDispatcher::Delegate overrides: virtual void ActivateWindow() OVERRIDE; - virtual void ActivateContents(content::WebContents* contents) OVERRIDE; virtual void CloseWindow() OVERRIDE; virtual void SetContentsInsets( int left, int top, int right, int bottom) OVERRIDE; @@ -323,58 +279,11 @@ class DevToolsWindow : private content::NotificationObserver, virtual void MoveWindow(int x, int y) OVERRIDE; virtual void SetIsDocked(bool is_docked) OVERRIDE; virtual void OpenInNewTab(const std::string& url) OVERRIDE; - virtual void SaveToFile(const std::string& url, - const std::string& content, - bool save_as) OVERRIDE; - virtual void AppendToFile(const std::string& url, - const std::string& content) OVERRIDE; - virtual void RequestFileSystems() OVERRIDE; - virtual void AddFileSystem() OVERRIDE; - virtual void RemoveFileSystem(const std::string& file_system_path) OVERRIDE; - virtual void UpgradeDraggedFileSystemPermissions( - const std::string& file_system_url) OVERRIDE; - virtual void IndexPath(int request_id, - const std::string& file_system_path) OVERRIDE; - virtual void StopIndexing(int request_id) OVERRIDE; - virtual void SearchInPath(int request_id, - const std::string& file_system_path, - const std::string& query) OVERRIDE; virtual void SetWhitelistedShortcuts(const std::string& message) OVERRIDE; - virtual void ZoomIn() OVERRIDE; - virtual void ZoomOut() OVERRIDE; - virtual void ResetZoom() OVERRIDE; - virtual void OpenUrlOnRemoteDeviceAndInspect(const std::string& browser_id, - const std::string& url) OVERRIDE; - virtual void StartRemoteDevicesListener() OVERRIDE; - virtual void StopRemoteDevicesListener() OVERRIDE; - virtual void EnableRemoteDeviceCounter(bool enable) OVERRIDE; - - // DevToolsAndroidBridge::DeviceCountListener override: - virtual void DeviceCountChanged(int count) OVERRIDE; - - // Forwards discovered devices to frontend. - virtual void PopulateRemoteDevices(const std::string& source, - scoped_ptr<base::ListValue> targets); - - // DevToolsFileHelper callbacks. - void FileSavedAs(const std::string& url); - void CanceledFileSaveAs(const std::string& url); - void AppendedTo(const std::string& url); - void FileSystemsLoaded( - const std::vector<DevToolsFileHelper::FileSystem>& file_systems); - void FileSystemAdded(const DevToolsFileHelper::FileSystem& file_system); - void IndexingTotalWorkCalculated(int request_id, - const std::string& file_system_path, - int total_work); - void IndexingWorked(int request_id, - const std::string& file_system_path, - int worked); - void IndexingDone(int request_id, const std::string& file_system_path); - void SearchCompleted(int request_id, - const std::string& file_system_path, - const std::vector<std::string>& file_paths); - void ShowDevToolsConfirmInfoBar(const base::string16& message, - const InfoBarCallback& callback); + + // DevToolsWindowBase overrides + virtual void AddDevToolsExtensionsToClient() OVERRIDE; + virtual void DocumentOnLoadCompletedInMainFrame() OVERRIDE; void CreateDevToolsBrowser(); BrowserWindow* GetInspectedBrowserWindow(); @@ -383,49 +292,24 @@ class DevToolsWindow : private content::NotificationObserver, void DoAction(const DevToolsToggleAction& action); void LoadCompleted(); void SetIsDockedAndShowImmediatelyForTest(bool is_docked); - void UpdateTheme(); - void AddDevToolsExtensionsToClient(); - void CallClientFunction(const std::string& function_name, - const base::Value* arg1, - const base::Value* arg2, - const base::Value* arg3); void UpdateBrowserToolbar(); content::WebContents* GetInspectedWebContents(); - void DocumentOnLoadCompletedInMainFrame(); class InspectedWebContentsObserver; scoped_ptr<InspectedWebContentsObserver> inspected_contents_observer_; - class FrontendWebContentsObserver; - friend class FrontendWebContentsObserver; - scoped_ptr<FrontendWebContentsObserver> frontend_contents_observer_; - Profile* profile_; - content::WebContents* web_contents_; Browser* browser_; bool is_docked_; const bool can_dock_; - bool device_listener_enabled_; LoadState load_state_; DevToolsToggleAction action_on_load_; bool ignore_set_is_docked_; - content::NotificationRegistrar registrar_; - scoped_ptr<content::DevToolsClientHost> frontend_host_; - scoped_ptr<DevToolsFileHelper> file_helper_; - scoped_refptr<DevToolsFileSystemIndexer> file_system_indexer_; - typedef std::map< - int, - scoped_refptr<DevToolsFileSystemIndexer::FileSystemIndexingJob> > - IndexingJobsMap; - IndexingJobsMap indexing_jobs_; DevToolsContentsResizingStrategy contents_resizing_strategy_; // True if we're in the process of handling a beforeunload event originating // from the inspected webcontents, see InterceptPageBeforeUnload for details. bool intercepted_page_beforeunload_; base::Closure load_completed_callback_; - scoped_ptr<DevToolsRemoteTargetsUIHandler> remote_targets_handler_; - scoped_ptr<DevToolsEmbedderMessageDispatcher> embedder_message_dispatcher_; - base::WeakPtrFactory<DevToolsWindow> weak_factory_; base::TimeTicks inspect_element_start_time_; scoped_ptr<DevToolsEventForwarder> event_forwarder_; diff --git a/chrome/browser/devtools/devtools_window_base.cc b/chrome/browser/devtools/devtools_window_base.cc new file mode 100644 index 0000000..a239820 --- /dev/null +++ b/chrome/browser/devtools/devtools_window_base.cc @@ -0,0 +1,685 @@ +// Copyright (c) 2014 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "chrome/browser/devtools/devtools_window.h" + +#include <algorithm> + +#include "base/command_line.h" +#include "base/json/json_reader.h" +#include "base/json/json_writer.h" +#include "base/strings/string_number_conversions.h" +#include "base/strings/string_util.h" +#include "base/strings/utf_string_conversions.h" +#include "base/values.h" +#include "chrome/browser/chrome_notification_types.h" +#include "chrome/browser/chrome_page_zoom.h" +#include "chrome/browser/extensions/chrome_extension_web_contents_observer.h" +#include "chrome/browser/extensions/extension_service.h" +#include "chrome/browser/infobars/confirm_infobar_delegate.h" +#include "chrome/browser/infobars/infobar_service.h" +#include "chrome/browser/profiles/profile.h" +#include "chrome/browser/themes/theme_properties.h" +#include "chrome/browser/themes/theme_service.h" +#include "chrome/browser/themes/theme_service_factory.h" +#include "chrome/browser/ui/browser.h" +#include "chrome/browser/ui/browser_iterator.h" +#include "chrome/browser/ui/browser_list.h" +#include "chrome/browser/ui/browser_window.h" +#include "chrome/browser/ui/tabs/tab_strip_model.h" +#include "chrome/common/chrome_switches.h" +#include "chrome/common/extensions/manifest_url_handler.h" +#include "chrome/common/url_constants.h" +#include "components/infobars/core/infobar.h" +#include "content/public/browser/devtools_client_host.h" +#include "content/public/browser/devtools_manager.h" +#include "content/public/browser/favicon_status.h" +#include "content/public/browser/navigation_controller.h" +#include "content/public/browser/navigation_entry.h" +#include "content/public/browser/notification_source.h" +#include "content/public/browser/render_frame_host.h" +#include "content/public/browser/render_view_host.h" +#include "content/public/browser/user_metrics.h" +#include "content/public/browser/web_contents.h" +#include "content/public/browser/web_contents_observer.h" +#include "content/public/browser/web_contents_view.h" +#include "content/public/common/page_transition_types.h" +#include "content/public/common/renderer_preferences.h" +#include "content/public/common/url_constants.h" +#include "extensions/browser/extension_system.h" +#include "extensions/common/extension_set.h" +#include "grit/generated_resources.h" +#include "ui/base/l10n/l10n_util.h" + +using base::DictionaryValue; +using content::BrowserThread; + +namespace { + +// DevToolsConfirmInfoBarDelegate --------------------------------------------- + +typedef base::Callback<void(bool)> InfoBarCallback; + +class DevToolsConfirmInfoBarDelegate : public ConfirmInfoBarDelegate { + public: + // If |infobar_service| is NULL, runs |callback| with a single argument with + // value "false". Otherwise, creates a dev tools confirm infobar and delegate + // and adds the infobar to |infobar_service|. + static void Create(InfoBarService* infobar_service, + const InfoBarCallback& callback, + const base::string16& message); + + private: + DevToolsConfirmInfoBarDelegate( + const InfoBarCallback& callback, + const base::string16& message); + virtual ~DevToolsConfirmInfoBarDelegate(); + + virtual base::string16 GetMessageText() const OVERRIDE; + virtual base::string16 GetButtonLabel(InfoBarButton button) const OVERRIDE; + virtual bool Accept() OVERRIDE; + virtual bool Cancel() OVERRIDE; + + InfoBarCallback callback_; + const base::string16 message_; + + DISALLOW_COPY_AND_ASSIGN(DevToolsConfirmInfoBarDelegate); +}; + +void DevToolsConfirmInfoBarDelegate::Create( + InfoBarService* infobar_service, + const InfoBarCallback& callback, + const base::string16& message) { + if (!infobar_service) { + callback.Run(false); + return; + } + + infobar_service->AddInfoBar(ConfirmInfoBarDelegate::CreateInfoBar( + scoped_ptr<ConfirmInfoBarDelegate>( + new DevToolsConfirmInfoBarDelegate(callback, message)))); +} + +DevToolsConfirmInfoBarDelegate::DevToolsConfirmInfoBarDelegate( + const InfoBarCallback& callback, + const base::string16& message) + : ConfirmInfoBarDelegate(), + callback_(callback), + message_(message) { +} + +DevToolsConfirmInfoBarDelegate::~DevToolsConfirmInfoBarDelegate() { + if (!callback_.is_null()) + callback_.Run(false); +} + +base::string16 DevToolsConfirmInfoBarDelegate::GetMessageText() const { + return message_; +} + +base::string16 DevToolsConfirmInfoBarDelegate::GetButtonLabel( + InfoBarButton button) const { + return l10n_util::GetStringUTF16((button == BUTTON_OK) ? + IDS_DEV_TOOLS_CONFIRM_ALLOW_BUTTON : IDS_DEV_TOOLS_CONFIRM_DENY_BUTTON); +} + +bool DevToolsConfirmInfoBarDelegate::Accept() { + callback_.Run(true); + callback_.Reset(); + return true; +} + +bool DevToolsConfirmInfoBarDelegate::Cancel() { + callback_.Run(false); + callback_.Reset(); + return true; +} + +static const char kFrontendHostId[] = "id"; +static const char kFrontendHostMethod[] = "method"; +static const char kFrontendHostParams[] = "params"; + +std::string SkColorToRGBAString(SkColor color) { + // We avoid StringPrintf because it will use locale specific formatters for + // the double (e.g. ',' instead of '.' in German). + return "rgba(" + base::IntToString(SkColorGetR(color)) + "," + + base::IntToString(SkColorGetG(color)) + "," + + base::IntToString(SkColorGetB(color)) + "," + + base::DoubleToString(SkColorGetA(color) / 255.0) + ")"; +} + +base::DictionaryValue* CreateFileSystemValue( + DevToolsFileHelper::FileSystem file_system) { + base::DictionaryValue* file_system_value = new base::DictionaryValue(); + file_system_value->SetString("fileSystemName", file_system.file_system_name); + file_system_value->SetString("rootURL", file_system.root_url); + file_system_value->SetString("fileSystemPath", file_system.file_system_path); + return file_system_value; +} + +Browser* FindBrowser(content::WebContents* web_contents) { + for (chrome::BrowserIterator it; !it.done(); it.Next()) { + int tab_index = it->tab_strip_model()->GetIndexOfWebContents( + web_contents); + if (tab_index != TabStripModel::kNoTab) + return *it; + } + return NULL; +} + +} // namespace + +// DevToolsWindowBase::FrontendWebContentsObserver ---------------------------- + +class DevToolsWindowBase::FrontendWebContentsObserver + : public content::WebContentsObserver { + public: + explicit FrontendWebContentsObserver(DevToolsWindowBase* window); + virtual ~FrontendWebContentsObserver(); + + private: + // contents::WebContentsObserver: + virtual void AboutToNavigateRenderView( + content::RenderViewHost* render_view_host) OVERRIDE; + virtual void DocumentOnLoadCompletedInMainFrame(int32 page_id) OVERRIDE; + virtual void WebContentsDestroyed(content::WebContents*) OVERRIDE; + + DevToolsWindowBase* devtools_window_; + DISALLOW_COPY_AND_ASSIGN(FrontendWebContentsObserver); +}; + +DevToolsWindowBase::FrontendWebContentsObserver::FrontendWebContentsObserver( + DevToolsWindowBase* devtools_window) + : WebContentsObserver(devtools_window->web_contents()), + devtools_window_(devtools_window) { +} + +void DevToolsWindowBase::FrontendWebContentsObserver::WebContentsDestroyed( + content::WebContents* contents) { + delete devtools_window_; +} + +DevToolsWindowBase::FrontendWebContentsObserver:: + ~FrontendWebContentsObserver() { +} + +void DevToolsWindowBase::FrontendWebContentsObserver::AboutToNavigateRenderView( + content::RenderViewHost* render_view_host) { + content::DevToolsClientHost::SetupDevToolsFrontendClient(render_view_host); +} + +void DevToolsWindowBase::FrontendWebContentsObserver:: + DocumentOnLoadCompletedInMainFrame(int32 page_id) { + devtools_window_->DocumentOnLoadCompletedInMainFrame(); +} + +// DevToolsWindowBase --------------------------------------------------------- + +DevToolsWindowBase::~DevToolsWindowBase() { + content::DevToolsManager::GetInstance()->ClientHostClosing( + frontend_host_.get()); + + for (IndexingJobsMap::const_iterator jobs_it(indexing_jobs_.begin()); + jobs_it != indexing_jobs_.end(); ++jobs_it) { + jobs_it->second->Stop(); + } + indexing_jobs_.clear(); + if (device_listener_enabled_) + EnableRemoteDeviceCounter(false); +} + +void DevToolsWindowBase::InspectedContentsClosing() { + web_contents_->GetRenderViewHost()->ClosePage(); +} + +DevToolsWindowBase::DevToolsWindowBase(content::WebContents* web_contents, + const GURL& url) + : profile_(Profile::FromBrowserContext(web_contents->GetBrowserContext())), + web_contents_(web_contents), + device_listener_enabled_(false), + weak_factory_(this) { + frontend_contents_observer_.reset(new FrontendWebContentsObserver(this)); + web_contents_->GetMutableRendererPrefs()->can_accept_load_drops = false; + + web_contents_->GetController().LoadURL( + ApplyThemeToURL(url), content::Referrer(), + content::PAGE_TRANSITION_AUTO_TOPLEVEL, std::string()); + + frontend_host_.reset(content::DevToolsClientHost::CreateDevToolsFrontendHost( + web_contents_, this)); + file_helper_.reset(new DevToolsFileHelper(web_contents_, profile_)); + file_system_indexer_ = new DevToolsFileSystemIndexer(); + extensions::ChromeExtensionWebContentsObserver::CreateForWebContents( + web_contents_); + + // Wipe out page icon so that the default application icon is used. + content::NavigationEntry* entry = + web_contents_->GetController().GetActiveEntry(); + entry->GetFavicon().image = gfx::Image(); + entry->GetFavicon().valid = true; + + // Register on-load actions. + registrar_.Add( + this, chrome::NOTIFICATION_BROWSER_THEME_CHANGED, + content::Source<ThemeService>( + ThemeServiceFactory::GetForProfile(profile_))); + + embedder_message_dispatcher_.reset( + DevToolsEmbedderMessageDispatcher::createForDevToolsFrontend(this)); +} + +GURL DevToolsWindowBase::ApplyThemeToURL(const GURL& base_url) { + std::string frontend_url = base_url.spec(); + ThemeService* tp = ThemeServiceFactory::GetForProfile(profile_); + DCHECK(tp); + std::string url_string( + frontend_url + + ((frontend_url.find("?") == std::string::npos) ? "?" : "&") + + "dockSide=undocked" + // TODO(dgozman): remove this support in M38. + "&toolbarColor=" + + SkColorToRGBAString(tp->GetColor(ThemeProperties::COLOR_TOOLBAR)) + + "&textColor=" + + SkColorToRGBAString(tp->GetColor(ThemeProperties::COLOR_BOOKMARK_TEXT))); + if (CommandLine::ForCurrentProcess()->HasSwitch( + switches::kEnableDevToolsExperiments)) + url_string += "&experiments=true"; + return GURL(url_string); +} + +void DevToolsWindowBase::Observe(int type, + const content::NotificationSource& source, + const content::NotificationDetails& details) { + DCHECK_EQ(chrome::NOTIFICATION_BROWSER_THEME_CHANGED, type); + UpdateTheme(); +} + +void DevToolsWindowBase::DispatchOnEmbedder(const std::string& message) { + std::string method; + base::ListValue empty_params; + base::ListValue* params = &empty_params; + + base::DictionaryValue* dict = NULL; + scoped_ptr<base::Value> parsed_message(base::JSONReader::Read(message)); + if (!parsed_message || + !parsed_message->GetAsDictionary(&dict) || + !dict->GetString(kFrontendHostMethod, &method) || + (dict->HasKey(kFrontendHostParams) && + !dict->GetList(kFrontendHostParams, ¶ms))) { + LOG(ERROR) << "Invalid message was sent to embedder: " << message; + return; + } + + int id = 0; + dict->GetInteger(kFrontendHostId, &id); + + std::string error; + embedder_message_dispatcher_->Dispatch(method, params, &error); + if (id) { + scoped_ptr<base::Value> id_value(base::Value::CreateIntegerValue(id)); + scoped_ptr<base::Value> error_value(base::Value::CreateStringValue(error)); + CallClientFunction("InspectorFrontendAPI.embedderMessageAck", + id_value.get(), error_value.get(), NULL); + } +} + +void DevToolsWindowBase::ActivateWindow() { + web_contents_->GetDelegate()->ActivateContents(web_contents_); + web_contents_->GetView()->Focus(); +} + +void DevToolsWindowBase::CloseWindow() { +} + +void DevToolsWindowBase::SetContentsInsets( + int top, int left, int bottom, int right) { +} + +void DevToolsWindowBase::SetContentsResizingStrategy( + const gfx::Insets& insets, const gfx::Size& min_size) { +} + +void DevToolsWindowBase::MoveWindow(int x, int y) { +} + +void DevToolsWindowBase::SetIsDocked(bool dock_requested) { +} + +void DevToolsWindowBase::InspectElementCompleted() { +} + +void DevToolsWindowBase::OpenInNewTab(const std::string& url) { + content::OpenURLParams params( + GURL(url), content::Referrer(), NEW_FOREGROUND_TAB, + content::PAGE_TRANSITION_LINK, false); + Browser* browser = FindBrowser(web_contents_); + browser->OpenURL(params); +} + +void DevToolsWindowBase::SaveToFile(const std::string& url, + const std::string& content, + bool save_as) { + file_helper_->Save(url, content, save_as, + base::Bind(&DevToolsWindowBase::FileSavedAs, + weak_factory_.GetWeakPtr(), url), + base::Bind(&DevToolsWindowBase::CanceledFileSaveAs, + weak_factory_.GetWeakPtr(), url)); +} + +void DevToolsWindowBase::AppendToFile(const std::string& url, + const std::string& content) { + file_helper_->Append(url, content, + base::Bind(&DevToolsWindowBase::AppendedTo, + weak_factory_.GetWeakPtr(), url)); +} + +void DevToolsWindowBase::RequestFileSystems() { + CHECK(web_contents_->GetURL().SchemeIs(content::kChromeDevToolsScheme)); + file_helper_->RequestFileSystems(base::Bind( + &DevToolsWindowBase::FileSystemsLoaded, weak_factory_.GetWeakPtr())); +} + +void DevToolsWindowBase::AddFileSystem() { + CHECK(web_contents_->GetURL().SchemeIs(content::kChromeDevToolsScheme)); + file_helper_->AddFileSystem( + base::Bind(&DevToolsWindowBase::FileSystemAdded, + weak_factory_.GetWeakPtr()), + base::Bind(&DevToolsWindowBase::ShowDevToolsConfirmInfoBar, + weak_factory_.GetWeakPtr())); +} + +void DevToolsWindowBase::RemoveFileSystem( + const std::string& file_system_path) { + CHECK(web_contents_->GetURL().SchemeIs(content::kChromeDevToolsScheme)); + file_helper_->RemoveFileSystem(file_system_path); + base::StringValue file_system_path_value(file_system_path); + CallClientFunction("InspectorFrontendAPI.fileSystemRemoved", + &file_system_path_value, NULL, NULL); +} + +void DevToolsWindowBase::UpgradeDraggedFileSystemPermissions( + const std::string& file_system_url) { + CHECK(web_contents_->GetURL().SchemeIs(content::kChromeDevToolsScheme)); + file_helper_->UpgradeDraggedFileSystemPermissions( + file_system_url, + base::Bind(&DevToolsWindowBase::FileSystemAdded, + weak_factory_.GetWeakPtr()), + base::Bind(&DevToolsWindowBase::ShowDevToolsConfirmInfoBar, + weak_factory_.GetWeakPtr())); +} + +void DevToolsWindowBase::IndexPath(int request_id, + const std::string& file_system_path) { + DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); + CHECK(web_contents_->GetURL().SchemeIs(content::kChromeDevToolsScheme)); + if (!file_helper_->IsFileSystemAdded(file_system_path)) { + IndexingDone(request_id, file_system_path); + return; + } + indexing_jobs_[request_id] = + scoped_refptr<DevToolsFileSystemIndexer::FileSystemIndexingJob>( + file_system_indexer_->IndexPath( + file_system_path, + Bind(&DevToolsWindowBase::IndexingTotalWorkCalculated, + weak_factory_.GetWeakPtr(), + request_id, + file_system_path), + Bind(&DevToolsWindowBase::IndexingWorked, + weak_factory_.GetWeakPtr(), + request_id, + file_system_path), + Bind(&DevToolsWindowBase::IndexingDone, + weak_factory_.GetWeakPtr(), + request_id, + file_system_path))); +} + +void DevToolsWindowBase::StopIndexing(int request_id) { + DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); + IndexingJobsMap::iterator it = indexing_jobs_.find(request_id); + if (it == indexing_jobs_.end()) + return; + it->second->Stop(); + indexing_jobs_.erase(it); +} + +void DevToolsWindowBase::SearchInPath(int request_id, + const std::string& file_system_path, + const std::string& query) { + DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); + CHECK(web_contents_->GetURL().SchemeIs(content::kChromeDevToolsScheme)); + if (!file_helper_->IsFileSystemAdded(file_system_path)) { + SearchCompleted(request_id, file_system_path, std::vector<std::string>()); + return; + } + file_system_indexer_->SearchInPath(file_system_path, + query, + Bind(&DevToolsWindowBase::SearchCompleted, + weak_factory_.GetWeakPtr(), + request_id, + file_system_path)); +} + +void DevToolsWindowBase::SetWhitelistedShortcuts( + const std::string& message) { +} + +void DevToolsWindowBase::ZoomIn() { + chrome_page_zoom::Zoom(web_contents(), content::PAGE_ZOOM_IN); +} + +void DevToolsWindowBase::ZoomOut() { + chrome_page_zoom::Zoom(web_contents(), content::PAGE_ZOOM_OUT); +} + +void DevToolsWindowBase::ResetZoom() { + chrome_page_zoom::Zoom(web_contents(), content::PAGE_ZOOM_RESET); +} + +void DevToolsWindowBase::OpenUrlOnRemoteDeviceAndInspect( + const std::string& browser_id, + const std::string& url) { + if (remote_targets_handler_) + remote_targets_handler_->OpenAndInspect(browser_id, url, profile_); +} + +void DevToolsWindowBase::StartRemoteDevicesListener() { + remote_targets_handler_ = DevToolsRemoteTargetsUIHandler::CreateForAdb( + base::Bind(&DevToolsWindowBase::PopulateRemoteDevices, + base::Unretained(this)), + profile_); +} + +void DevToolsWindowBase::StopRemoteDevicesListener() { + remote_targets_handler_.reset(); +} + +void DevToolsWindowBase::EnableRemoteDeviceCounter(bool enable) { + DevToolsAndroidBridge* adb_bridge = + DevToolsAndroidBridge::Factory::GetForProfile(profile_); + if (!adb_bridge) + return; + + DCHECK(device_listener_enabled_ != enable); + device_listener_enabled_ = enable; + if (enable) + adb_bridge->AddDeviceCountListener(this); + else + adb_bridge->RemoveDeviceCountListener(this); +} + +void DevToolsWindowBase::DeviceCountChanged(int count) { + base::FundamentalValue value(count); + CallClientFunction( + "InspectorFrontendAPI.setRemoteDeviceCount", &value, NULL, NULL); +} + +void DevToolsWindowBase::PopulateRemoteDevices( + const std::string& source, + scoped_ptr<base::ListValue> targets) { + CallClientFunction( + "InspectorFrontendAPI.populateRemoteDevices", targets.get(), NULL, NULL); +} + +void DevToolsWindowBase::FileSavedAs(const std::string& url) { + base::StringValue url_value(url); + CallClientFunction("InspectorFrontendAPI.savedURL", &url_value, NULL, NULL); +} + +void DevToolsWindowBase::CanceledFileSaveAs(const std::string& url) { + base::StringValue url_value(url); + CallClientFunction("InspectorFrontendAPI.canceledSaveURL", + &url_value, NULL, NULL); +} + +void DevToolsWindowBase::AppendedTo(const std::string& url) { + base::StringValue url_value(url); + CallClientFunction("InspectorFrontendAPI.appendedToURL", &url_value, NULL, + NULL); +} + +void DevToolsWindowBase::FileSystemsLoaded( + const std::vector<DevToolsFileHelper::FileSystem>& file_systems) { + base::ListValue file_systems_value; + for (size_t i = 0; i < file_systems.size(); ++i) + file_systems_value.Append(CreateFileSystemValue(file_systems[i])); + CallClientFunction("InspectorFrontendAPI.fileSystemsLoaded", + &file_systems_value, NULL, NULL); +} + +void DevToolsWindowBase::FileSystemAdded( + const DevToolsFileHelper::FileSystem& file_system) { + scoped_ptr<base::StringValue> error_string_value( + new base::StringValue(std::string())); + scoped_ptr<base::DictionaryValue> file_system_value; + if (!file_system.file_system_path.empty()) + file_system_value.reset(CreateFileSystemValue(file_system)); + CallClientFunction("InspectorFrontendAPI.fileSystemAdded", + error_string_value.get(), file_system_value.get(), NULL); +} + +void DevToolsWindowBase::IndexingTotalWorkCalculated( + int request_id, + const std::string& file_system_path, + int total_work) { + DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); + base::FundamentalValue request_id_value(request_id); + base::StringValue file_system_path_value(file_system_path); + base::FundamentalValue total_work_value(total_work); + CallClientFunction("InspectorFrontendAPI.indexingTotalWorkCalculated", + &request_id_value, &file_system_path_value, + &total_work_value); +} + +void DevToolsWindowBase::IndexingWorked(int request_id, + const std::string& file_system_path, + int worked) { + DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); + base::FundamentalValue request_id_value(request_id); + base::StringValue file_system_path_value(file_system_path); + base::FundamentalValue worked_value(worked); + CallClientFunction("InspectorFrontendAPI.indexingWorked", &request_id_value, + &file_system_path_value, &worked_value); +} + +void DevToolsWindowBase::IndexingDone(int request_id, + const std::string& file_system_path) { + indexing_jobs_.erase(request_id); + DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); + base::FundamentalValue request_id_value(request_id); + base::StringValue file_system_path_value(file_system_path); + CallClientFunction("InspectorFrontendAPI.indexingDone", &request_id_value, + &file_system_path_value, NULL); +} + +void DevToolsWindowBase::SearchCompleted( + int request_id, + const std::string& file_system_path, + const std::vector<std::string>& file_paths) { + DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); + base::ListValue file_paths_value; + for (std::vector<std::string>::const_iterator it(file_paths.begin()); + it != file_paths.end(); ++it) { + file_paths_value.AppendString(*it); + } + base::FundamentalValue request_id_value(request_id); + base::StringValue file_system_path_value(file_system_path); + CallClientFunction("InspectorFrontendAPI.searchCompleted", &request_id_value, + &file_system_path_value, &file_paths_value); +} + +void DevToolsWindowBase::ShowDevToolsConfirmInfoBar( + const base::string16& message, + const InfoBarCallback& callback) { + DevToolsConfirmInfoBarDelegate::Create( + InfoBarService::FromWebContents(web_contents_), + callback, message); +} + +void DevToolsWindowBase::UpdateTheme() { + ThemeService* tp = ThemeServiceFactory::GetForProfile(profile_); + DCHECK(tp); + + std::string command("InspectorFrontendAPI.setToolbarColors(\"" + + SkColorToRGBAString(tp->GetColor(ThemeProperties::COLOR_TOOLBAR)) + + "\", \"" + + SkColorToRGBAString(tp->GetColor(ThemeProperties::COLOR_BOOKMARK_TEXT)) + + "\")"); + web_contents_->GetMainFrame()->ExecuteJavaScript(base::ASCIIToUTF16(command)); +} + +void DevToolsWindowBase::AddDevToolsExtensionsToClient() { + const ExtensionService* extension_service = extensions::ExtensionSystem::Get( + profile_->GetOriginalProfile())->extension_service(); + if (!extension_service) + return; + const extensions::ExtensionSet* extensions = extension_service->extensions(); + + base::ListValue results; + for (extensions::ExtensionSet::const_iterator extension(extensions->begin()); + extension != extensions->end(); ++extension) { + if (extensions::ManifestURL::GetDevToolsPage(extension->get()).is_empty()) + continue; + base::DictionaryValue* extension_info = new base::DictionaryValue(); + extension_info->Set( + "startPage", + new base::StringValue( + extensions::ManifestURL::GetDevToolsPage( + extension->get()).spec())); + extension_info->Set("name", new base::StringValue((*extension)->name())); + extension_info->Set( + "exposeExperimentalAPIs", + new base::FundamentalValue((*extension)->HasAPIPermission( + extensions::APIPermission::kExperimental))); + results.Append(extension_info); + } + CallClientFunction("WebInspector.addExtensions", &results, NULL, NULL); +} + +void DevToolsWindowBase::CallClientFunction(const std::string& function_name, + const base::Value* arg1, + const base::Value* arg2, + const base::Value* arg3) { + std::string params; + if (arg1) { + std::string json; + base::JSONWriter::Write(arg1, &json); + params.append(json); + if (arg2) { + base::JSONWriter::Write(arg2, &json); + params.append(", " + json); + if (arg3) { + base::JSONWriter::Write(arg3, &json); + params.append(", " + json); + } + } + } + base::string16 javascript = + base::UTF8ToUTF16(function_name + "(" + params + ");"); + web_contents_->GetMainFrame()->ExecuteJavaScript(javascript); +} + +void DevToolsWindowBase::DocumentOnLoadCompletedInMainFrame() { + UpdateTheme(); + AddDevToolsExtensionsToClient(); +} diff --git a/chrome/browser/devtools/devtools_window_base.h b/chrome/browser/devtools/devtools_window_base.h new file mode 100644 index 0000000..e5f544e --- /dev/null +++ b/chrome/browser/devtools/devtools_window_base.h @@ -0,0 +1,161 @@ +// Copyright (c) 2014 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef CHROME_BROWSER_DEVTOOLS_DEVTOOLS_WINDOW_BASE_H_ +#define CHROME_BROWSER_DEVTOOLS_DEVTOOLS_WINDOW_BASE_H_ + +#include <string> +#include <vector> + +#include "base/basictypes.h" +#include "base/memory/scoped_ptr.h" +#include "base/memory/weak_ptr.h" +#include "base/strings/string16.h" +#include "chrome/browser/devtools/device/devtools_android_bridge.h" +#include "chrome/browser/devtools/devtools_embedder_message_dispatcher.h" +#include "chrome/browser/devtools/devtools_file_helper.h" +#include "chrome/browser/devtools/devtools_file_system_indexer.h" +#include "chrome/browser/devtools/devtools_targets_ui.h" +#include "content/public/browser/devtools_client_host.h" +#include "content/public/browser/devtools_frontend_host_delegate.h" +#include "content/public/browser/notification_observer.h" +#include "content/public/browser/notification_registrar.h" +#include "ui/gfx/size.h" + +class Profile; + +namespace content { +class DevToolsClientHost; +struct FileChooserParams; +class WebContents; +} + +// Base implementation of DevTools bindings around front-end. +class DevToolsWindowBase : public content::NotificationObserver, + public content::DevToolsFrontendHostDelegate, + public DevToolsEmbedderMessageDispatcher::Delegate, + public DevToolsAndroidBridge::DeviceCountListener { + public: + virtual ~DevToolsWindowBase(); + + content::WebContents* web_contents() { return web_contents_; } + + // content::NotificationObserver: + virtual void Observe(int type, + const content::NotificationSource& source, + const content::NotificationDetails& details) OVERRIDE; + + // content::DevToolsFrontendHostDelegate override: + virtual void InspectedContentsClosing() OVERRIDE; + virtual void DispatchOnEmbedder(const std::string& message) OVERRIDE; + + // DevToolsEmbedderMessageDispatcher::Delegate overrides: + virtual void ActivateWindow() OVERRIDE; + virtual void CloseWindow() OVERRIDE; + virtual void SetContentsInsets( + int left, int top, int right, int bottom) OVERRIDE; + virtual void SetContentsResizingStrategy( + const gfx::Insets& insets, const gfx::Size& min_size) OVERRIDE; + virtual void InspectElementCompleted() OVERRIDE; + virtual void MoveWindow(int x, int y) OVERRIDE; + virtual void SetIsDocked(bool is_docked) OVERRIDE; + virtual void OpenInNewTab(const std::string& url) OVERRIDE; + virtual void SaveToFile(const std::string& url, + const std::string& content, + bool save_as) OVERRIDE; + virtual void AppendToFile(const std::string& url, + const std::string& content) OVERRIDE; + virtual void RequestFileSystems() OVERRIDE; + virtual void AddFileSystem() OVERRIDE; + virtual void RemoveFileSystem(const std::string& file_system_path) OVERRIDE; + virtual void UpgradeDraggedFileSystemPermissions( + const std::string& file_system_url) OVERRIDE; + virtual void IndexPath(int request_id, + const std::string& file_system_path) OVERRIDE; + virtual void StopIndexing(int request_id) OVERRIDE; + virtual void SearchInPath(int request_id, + const std::string& file_system_path, + const std::string& query) OVERRIDE; + virtual void SetWhitelistedShortcuts(const std::string& message) OVERRIDE; + virtual void ZoomIn() OVERRIDE; + virtual void ZoomOut() OVERRIDE; + virtual void ResetZoom() OVERRIDE; + virtual void OpenUrlOnRemoteDeviceAndInspect(const std::string& browser_id, + const std::string& url) OVERRIDE; + virtual void StartRemoteDevicesListener() OVERRIDE; + virtual void StopRemoteDevicesListener() OVERRIDE; + virtual void EnableRemoteDeviceCounter(bool enable) OVERRIDE; + + // DevToolsAndroidBridge::DeviceCountListener override: + virtual void DeviceCountChanged(int count) OVERRIDE; + + // Forwards discovered devices to frontend. + virtual void PopulateRemoteDevices(const std::string& source, + scoped_ptr<base::ListValue> targets); + + protected: + DevToolsWindowBase(content::WebContents* web_contents, + const GURL& frontend_url); + + virtual void AddDevToolsExtensionsToClient(); + virtual void DocumentOnLoadCompletedInMainFrame(); + void CallClientFunction(const std::string& function_name, + const base::Value* arg1, + const base::Value* arg2, + const base::Value* arg3); + Profile* profile() { return profile_; } + content::DevToolsClientHost* frontend_host() { return frontend_host_.get(); } + + private: + typedef base::Callback<void(bool)> InfoBarCallback; + + // DevToolsFileHelper callbacks. + void FileSavedAs(const std::string& url); + void CanceledFileSaveAs(const std::string& url); + void AppendedTo(const std::string& url); + void FileSystemsLoaded( + const std::vector<DevToolsFileHelper::FileSystem>& file_systems); + void FileSystemAdded(const DevToolsFileHelper::FileSystem& file_system); + void IndexingTotalWorkCalculated(int request_id, + const std::string& file_system_path, + int total_work); + void IndexingWorked(int request_id, + const std::string& file_system_path, + int worked); + void IndexingDone(int request_id, const std::string& file_system_path); + void SearchCompleted(int request_id, + const std::string& file_system_path, + const std::vector<std::string>& file_paths); + void ShowDevToolsConfirmInfoBar(const base::string16& message, + const InfoBarCallback& callback); + + // Theme and extensions support. + GURL ApplyThemeToURL(const GURL& base_url); + void UpdateTheme(); + + class FrontendWebContentsObserver; + friend class FrontendWebContentsObserver; + scoped_ptr<FrontendWebContentsObserver> frontend_contents_observer_; + + Profile* profile_; + content::WebContents* web_contents_; + bool device_listener_enabled_; + content::NotificationRegistrar registrar_; + scoped_ptr<content::DevToolsClientHost> frontend_host_; + scoped_ptr<DevToolsFileHelper> file_helper_; + scoped_refptr<DevToolsFileSystemIndexer> file_system_indexer_; + typedef std::map< + int, + scoped_refptr<DevToolsFileSystemIndexer::FileSystemIndexingJob> > + IndexingJobsMap; + IndexingJobsMap indexing_jobs_; + + scoped_ptr<DevToolsRemoteTargetsUIHandler> remote_targets_handler_; + scoped_ptr<DevToolsEmbedderMessageDispatcher> embedder_message_dispatcher_; + base::WeakPtrFactory<DevToolsWindowBase> weak_factory_; + + DISALLOW_COPY_AND_ASSIGN(DevToolsWindowBase); +}; + +#endif // CHROME_BROWSER_DEVTOOLS_DEVTOOLS_WINDOW_BASE_H_ diff --git a/chrome/chrome.gyp b/chrome/chrome.gyp index a09103e..23e691f 100644 --- a/chrome/chrome.gyp +++ b/chrome/chrome.gyp @@ -186,6 +186,8 @@ 'browser/devtools/devtools_toggle_action.h', 'browser/devtools/devtools_window.cc', 'browser/devtools/devtools_window.h', + 'browser/devtools/devtools_window_base.cc', + 'browser/devtools/devtools_window_base.h', 'browser/devtools/remote_debugging_server.cc', 'browser/devtools/remote_debugging_server.h', ], @@ -200,6 +202,7 @@ 'browser/devtools/devtools_file_system_indexer.cc', 'browser/devtools/devtools_target_impl.cc', 'browser/devtools/devtools_window.cc', + 'browser/devtools/devtools_window_base.cc', 'browser/devtools/remote_debugging_server.cc', ], }], |