From 70019150e9f7f53074cacb335de0d238bbc37380 Mon Sep 17 00:00:00 2001 From: "pfeldman@chromium.org" Date: Wed, 19 Dec 2012 11:44:19 +0000 Subject: DevTools: rename debugger/ to devtools/, move DevTools files into content/renderer/devtools. Review URL: https://codereview.chromium.org/11630004 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@173903 0039d316-1c4b-4281-b951-d872f2087c98 --- android_webview/android_webview.gyp | 2 +- .../automation/testing_automation_provider.cc | 2 +- chrome/browser/browser_process_impl.cc | 2 +- chrome/browser/debugger/OWNERS | 3 - .../debugger/browser_list_tabcontents_provider.cc | 96 --- .../debugger/browser_list_tabcontents_provider.h | 35 - chrome/browser/debugger/devtools_file_helper.cc | 199 ----- chrome/browser/debugger/devtools_file_helper.h | 60 -- .../debugger/devtools_sanity_browsertest.cc | 600 -------------- chrome/browser/debugger/devtools_toggle_action.h | 15 - chrome/browser/debugger/devtools_window.cc | 914 --------------------- chrome/browser/debugger/devtools_window.h | 214 ----- .../debugger/frontend/devtools_discovery_page.html | 142 ---- .../frontend/devtools_discovery_page_resources.grd | 21 - chrome/browser/debugger/remote_debugging_server.cc | 27 - chrome/browser/debugger/remote_debugging_server.h | 32 - chrome/browser/devtools/OWNERS | 2 + .../devtools/browser_list_tabcontents_provider.cc | 96 +++ .../devtools/browser_list_tabcontents_provider.h | 35 + chrome/browser/devtools/devtools_file_helper.cc | 199 +++++ chrome/browser/devtools/devtools_file_helper.h | 60 ++ .../devtools/devtools_sanity_browsertest.cc | 600 ++++++++++++++ chrome/browser/devtools/devtools_toggle_action.h | 15 + chrome/browser/devtools/devtools_window.cc | 914 +++++++++++++++++++++ chrome/browser/devtools/devtools_window.h | 214 +++++ .../devtools/frontend/devtools_discovery_page.html | 142 ++++ .../frontend/devtools_discovery_page_resources.grd | 21 + chrome/browser/devtools/remote_debugging_server.cc | 27 + chrome/browser/devtools/remote_debugging_server.h | 32 + .../extensions/api/app_window/app_window_api.cc | 2 +- .../api/developer_private/developer_private_api.cc | 2 +- chrome/browser/extensions/extension_service.cc | 2 +- .../browser/extensions/platform_app_browsertest.cc | 2 +- chrome/browser/policy/policy_browsertest.cc | 2 +- chrome/browser/prefs/browser_prefs.cc | 2 +- chrome/browser/printing/print_dialog_cloud.cc | 2 +- .../chrome_render_widget_host_view_mac_delegate.mm | 2 +- .../render_process_host_chrome_browsertest.cc | 2 +- .../tab_contents/render_view_context_menu.cc | 2 +- .../task_manager_notification_resource_provider.cc | 2 +- .../task_manager_resource_providers.cc | 2 +- .../task_manager_worker_resource_provider.cc | 2 +- chrome/browser/ui/browser.cc | 4 +- chrome/browser/ui/browser.h | 2 +- chrome/browser/ui/browser_commands.cc | 2 +- chrome/browser/ui/browser_commands.h | 2 +- chrome/browser/ui/cocoa/dev_tools_controller.h | 2 +- .../cocoa/extensions/extension_popup_controller.mm | 2 +- chrome/browser/ui/cocoa/tabpose_window.mm | 2 +- .../browser/ui/cocoa/tabs/tab_strip_controller.mm | 2 +- chrome/browser/ui/gtk/browser_window_gtk.h | 2 +- .../ui/gtk/extensions/extension_popup_gtk.cc | 2 +- chrome/browser/ui/panels/panel.cc | 2 +- chrome/browser/ui/panels/panel_browsertest.cc | 2 +- .../browser/ui/views/extensions/extension_popup.cc | 2 +- .../browser/ui/views/external_tab_container_win.cc | 4 +- chrome/browser/ui/views/frame/browser_view.h | 2 +- .../webui/extensions/extension_settings_handler.cc | 2 +- chrome/browser/ui/webui/inspect_ui.cc | 2 +- chrome/chrome.gyp | 24 +- chrome/chrome_resources.gyp | 4 +- chrome/chrome_tests.gypi | 2 +- content/browser/debugger/DEPS | 4 - content/browser/debugger/OWNERS | 3 - content/browser/debugger/devtools_agent_host.cc | 57 -- content/browser/debugger/devtools_agent_host.h | 59 -- .../browser/debugger/devtools_browser_target.cc | 118 --- content/browser/debugger/devtools_browser_target.h | 68 -- content/browser/debugger/devtools_frontend_host.cc | 125 --- content/browser/debugger/devtools_frontend_host.h | 59 -- .../browser/debugger/devtools_http_handler_impl.cc | 873 -------------------- .../browser/debugger/devtools_http_handler_impl.h | 143 ---- .../debugger/devtools_http_handler_unittest.cc | 103 --- content/browser/debugger/devtools_manager_impl.cc | 302 ------- content/browser/debugger/devtools_manager_impl.h | 131 --- .../browser/debugger/devtools_manager_unittest.cc | 243 ------ .../browser/debugger/devtools_netlog_observer.cc | 329 -------- .../browser/debugger/devtools_netlog_observer.h | 70 -- content/browser/debugger/devtools_resources.gyp | 58 -- .../browser/debugger/devtools_tracing_handler.cc | 103 --- .../browser/debugger/devtools_tracing_handler.h | 50 -- .../manual_tests/console-call-line-numbers.html | 15 - .../manual_tests/debugger-exception-on-load.html | 5 - .../debugger-execution-while-paused.html | 17 - .../manual_tests/debugger-fake-workers.html | 102 --- .../debugger-pause-on-else-statements.html | 16 - .../debugger-pause-on-for-in-statements.html | 16 - .../debugger-pause-on-for-statements.html | 14 - .../debugger-step-on-do-while-statements.html | 27 - .../debugger-step-on-for-in-statements.html | 35 - .../debugger-step-on-for-statements.html | 25 - .../debugger-step-on-while-statements.html | 28 - .../manual_tests/debugger-watch-expressions.html | 79 -- .../debugger/manual_tests/dom-mutation.html | 32 - .../debugger/manual_tests/element-styles.html | 40 - .../debugger/manual_tests/error-warning-count.html | 58 -- .../debugger/manual_tests/event-listeners.html | 30 - ...eap-profiler-test-basic-grid-functionality.html | 32 - .../heap-profiler-test-snapshots-comparison.html | 83 -- .../debugger/manual_tests/highlight-nodes.html | 23 - .../manual_tests/highlight-source-line.html | 3 - .../profiler-test-basic-grid-functionality.html | 38 - .../profiler-test-console-control.html | 27 - .../profiler-test-focus-and-exclude.html | 71 -- .../manual_tests/profiler-test-re-opening.html | 37 - .../browser/debugger/manual_tests/resources/fib.js | 20 - .../manual_tests/resources/loop-statements.js | 22 - .../manual_tests/resources/mutate-frame-2.html | 12 - .../manual_tests/resources/mutate-frame.html | 10 - .../debugger/manual_tests/resources/primes.js | 13 - .../manual_tests/resources/script-console-calls.js | 8 - .../manual_tests/resources/worker-primes.js | 10 - .../debugger/render_view_devtools_agent_host.cc | 154 ---- .../debugger/render_view_devtools_agent_host.h | 51 -- .../browser/debugger/worker_devtools_manager.cc | 472 ----------- content/browser/debugger/worker_devtools_manager.h | 109 --- .../debugger/worker_devtools_message_filter.cc | 50 -- .../debugger/worker_devtools_message_filter.h | 35 - content/browser/devtools/DEPS | 4 + content/browser/devtools/OWNERS | 2 + content/browser/devtools/devtools_agent_host.cc | 57 ++ content/browser/devtools/devtools_agent_host.h | 59 ++ .../browser/devtools/devtools_browser_target.cc | 118 +++ content/browser/devtools/devtools_browser_target.h | 68 ++ content/browser/devtools/devtools_frontend_host.cc | 125 +++ content/browser/devtools/devtools_frontend_host.h | 59 ++ .../browser/devtools/devtools_http_handler_impl.cc | 873 ++++++++++++++++++++ .../browser/devtools/devtools_http_handler_impl.h | 143 ++++ .../devtools/devtools_http_handler_unittest.cc | 103 +++ content/browser/devtools/devtools_manager_impl.cc | 302 +++++++ content/browser/devtools/devtools_manager_impl.h | 131 +++ .../browser/devtools/devtools_manager_unittest.cc | 243 ++++++ .../browser/devtools/devtools_netlog_observer.cc | 329 ++++++++ .../browser/devtools/devtools_netlog_observer.h | 70 ++ content/browser/devtools/devtools_resources.gyp | 58 ++ .../browser/devtools/devtools_tracing_handler.cc | 103 +++ .../browser/devtools/devtools_tracing_handler.h | 50 ++ .../devtools/render_view_devtools_agent_host.cc | 154 ++++ .../devtools/render_view_devtools_agent_host.h | 51 ++ .../browser/devtools/worker_devtools_manager.cc | 472 +++++++++++ content/browser/devtools/worker_devtools_manager.h | 109 +++ .../devtools/worker_devtools_message_filter.cc | 50 ++ .../devtools/worker_devtools_message_filter.h | 35 + content/browser/loader/async_resource_handler.cc | 2 +- content/browser/loader/sync_resource_handler.cc | 2 +- .../web_contents/render_view_host_manager.cc | 2 +- content/browser/web_contents/web_contents_impl.cc | 2 +- content/browser/worker_host/worker_process_host.cc | 4 +- content/browser/worker_host/worker_service_impl.cc | 2 +- content/content_browser.gypi | 42 +- content/content_renderer.gypi | 12 +- content/content_shell.gypi | 2 +- content/content_tests.gypi | 4 +- content/renderer/devtools/OWNERS | 2 + content/renderer/devtools/devtools_agent.cc | 245 ++++++ content/renderer/devtools/devtools_agent.h | 73 ++ content/renderer/devtools/devtools_agent_filter.cc | 77 ++ content/renderer/devtools/devtools_agent_filter.h | 48 ++ content/renderer/devtools/devtools_client.cc | 97 +++ content/renderer/devtools/devtools_client.h | 63 ++ content/renderer/devtools_agent.cc | 245 ------ content/renderer/devtools_agent.h | 73 -- content/renderer/devtools_agent_filter.cc | 77 -- content/renderer/devtools_agent_filter.h | 48 -- content/renderer/devtools_client.cc | 97 --- content/renderer/devtools_client.h | 63 -- content/renderer/render_thread_impl.cc | 2 +- content/renderer/render_view_impl.cc | 2 +- tools/code_coverage/coverage_posix.py | 2 +- tools/gritsettings/resource_ids | 2 +- 170 files changed, 6821 insertions(+), 7769 deletions(-) delete mode 100644 chrome/browser/debugger/OWNERS delete mode 100644 chrome/browser/debugger/browser_list_tabcontents_provider.cc delete mode 100644 chrome/browser/debugger/browser_list_tabcontents_provider.h delete mode 100644 chrome/browser/debugger/devtools_file_helper.cc delete mode 100644 chrome/browser/debugger/devtools_file_helper.h delete mode 100644 chrome/browser/debugger/devtools_sanity_browsertest.cc delete mode 100644 chrome/browser/debugger/devtools_toggle_action.h delete mode 100644 chrome/browser/debugger/devtools_window.cc delete mode 100644 chrome/browser/debugger/devtools_window.h delete mode 100644 chrome/browser/debugger/frontend/devtools_discovery_page.html delete mode 100644 chrome/browser/debugger/frontend/devtools_discovery_page_resources.grd delete mode 100644 chrome/browser/debugger/remote_debugging_server.cc delete mode 100644 chrome/browser/debugger/remote_debugging_server.h create mode 100644 chrome/browser/devtools/OWNERS create mode 100644 chrome/browser/devtools/browser_list_tabcontents_provider.cc create mode 100644 chrome/browser/devtools/browser_list_tabcontents_provider.h create mode 100644 chrome/browser/devtools/devtools_file_helper.cc create mode 100644 chrome/browser/devtools/devtools_file_helper.h create mode 100644 chrome/browser/devtools/devtools_sanity_browsertest.cc create mode 100644 chrome/browser/devtools/devtools_toggle_action.h create mode 100644 chrome/browser/devtools/devtools_window.cc create mode 100644 chrome/browser/devtools/devtools_window.h create mode 100644 chrome/browser/devtools/frontend/devtools_discovery_page.html create mode 100644 chrome/browser/devtools/frontend/devtools_discovery_page_resources.grd create mode 100644 chrome/browser/devtools/remote_debugging_server.cc create mode 100644 chrome/browser/devtools/remote_debugging_server.h delete mode 100644 content/browser/debugger/DEPS delete mode 100644 content/browser/debugger/OWNERS delete mode 100644 content/browser/debugger/devtools_agent_host.cc delete mode 100644 content/browser/debugger/devtools_agent_host.h delete mode 100644 content/browser/debugger/devtools_browser_target.cc delete mode 100644 content/browser/debugger/devtools_browser_target.h delete mode 100644 content/browser/debugger/devtools_frontend_host.cc delete mode 100644 content/browser/debugger/devtools_frontend_host.h delete mode 100644 content/browser/debugger/devtools_http_handler_impl.cc delete mode 100644 content/browser/debugger/devtools_http_handler_impl.h delete mode 100644 content/browser/debugger/devtools_http_handler_unittest.cc delete mode 100644 content/browser/debugger/devtools_manager_impl.cc delete mode 100644 content/browser/debugger/devtools_manager_impl.h delete mode 100644 content/browser/debugger/devtools_manager_unittest.cc delete mode 100644 content/browser/debugger/devtools_netlog_observer.cc delete mode 100644 content/browser/debugger/devtools_netlog_observer.h delete mode 100644 content/browser/debugger/devtools_resources.gyp delete mode 100644 content/browser/debugger/devtools_tracing_handler.cc delete mode 100644 content/browser/debugger/devtools_tracing_handler.h delete mode 100644 content/browser/debugger/manual_tests/console-call-line-numbers.html delete mode 100644 content/browser/debugger/manual_tests/debugger-exception-on-load.html delete mode 100644 content/browser/debugger/manual_tests/debugger-execution-while-paused.html delete mode 100644 content/browser/debugger/manual_tests/debugger-fake-workers.html delete mode 100644 content/browser/debugger/manual_tests/debugger-pause-on-else-statements.html delete mode 100644 content/browser/debugger/manual_tests/debugger-pause-on-for-in-statements.html delete mode 100644 content/browser/debugger/manual_tests/debugger-pause-on-for-statements.html delete mode 100644 content/browser/debugger/manual_tests/debugger-step-on-do-while-statements.html delete mode 100644 content/browser/debugger/manual_tests/debugger-step-on-for-in-statements.html delete mode 100644 content/browser/debugger/manual_tests/debugger-step-on-for-statements.html delete mode 100644 content/browser/debugger/manual_tests/debugger-step-on-while-statements.html delete mode 100644 content/browser/debugger/manual_tests/debugger-watch-expressions.html delete mode 100644 content/browser/debugger/manual_tests/dom-mutation.html delete mode 100644 content/browser/debugger/manual_tests/element-styles.html delete mode 100644 content/browser/debugger/manual_tests/error-warning-count.html delete mode 100644 content/browser/debugger/manual_tests/event-listeners.html delete mode 100644 content/browser/debugger/manual_tests/heap-profiler-test-basic-grid-functionality.html delete mode 100644 content/browser/debugger/manual_tests/heap-profiler-test-snapshots-comparison.html delete mode 100644 content/browser/debugger/manual_tests/highlight-nodes.html delete mode 100644 content/browser/debugger/manual_tests/highlight-source-line.html delete mode 100644 content/browser/debugger/manual_tests/profiler-test-basic-grid-functionality.html delete mode 100644 content/browser/debugger/manual_tests/profiler-test-console-control.html delete mode 100644 content/browser/debugger/manual_tests/profiler-test-focus-and-exclude.html delete mode 100644 content/browser/debugger/manual_tests/profiler-test-re-opening.html delete mode 100644 content/browser/debugger/manual_tests/resources/fib.js delete mode 100644 content/browser/debugger/manual_tests/resources/loop-statements.js delete mode 100644 content/browser/debugger/manual_tests/resources/mutate-frame-2.html delete mode 100644 content/browser/debugger/manual_tests/resources/mutate-frame.html delete mode 100644 content/browser/debugger/manual_tests/resources/primes.js delete mode 100644 content/browser/debugger/manual_tests/resources/script-console-calls.js delete mode 100644 content/browser/debugger/manual_tests/resources/worker-primes.js delete mode 100644 content/browser/debugger/render_view_devtools_agent_host.cc delete mode 100644 content/browser/debugger/render_view_devtools_agent_host.h delete mode 100644 content/browser/debugger/worker_devtools_manager.cc delete mode 100644 content/browser/debugger/worker_devtools_manager.h delete mode 100644 content/browser/debugger/worker_devtools_message_filter.cc delete mode 100644 content/browser/debugger/worker_devtools_message_filter.h create mode 100644 content/browser/devtools/DEPS create mode 100644 content/browser/devtools/OWNERS create mode 100644 content/browser/devtools/devtools_agent_host.cc create mode 100644 content/browser/devtools/devtools_agent_host.h create mode 100644 content/browser/devtools/devtools_browser_target.cc create mode 100644 content/browser/devtools/devtools_browser_target.h create mode 100644 content/browser/devtools/devtools_frontend_host.cc create mode 100644 content/browser/devtools/devtools_frontend_host.h create mode 100644 content/browser/devtools/devtools_http_handler_impl.cc create mode 100644 content/browser/devtools/devtools_http_handler_impl.h create mode 100644 content/browser/devtools/devtools_http_handler_unittest.cc create mode 100644 content/browser/devtools/devtools_manager_impl.cc create mode 100644 content/browser/devtools/devtools_manager_impl.h create mode 100644 content/browser/devtools/devtools_manager_unittest.cc create mode 100644 content/browser/devtools/devtools_netlog_observer.cc create mode 100644 content/browser/devtools/devtools_netlog_observer.h create mode 100644 content/browser/devtools/devtools_resources.gyp create mode 100644 content/browser/devtools/devtools_tracing_handler.cc create mode 100644 content/browser/devtools/devtools_tracing_handler.h create mode 100644 content/browser/devtools/render_view_devtools_agent_host.cc create mode 100644 content/browser/devtools/render_view_devtools_agent_host.h create mode 100644 content/browser/devtools/worker_devtools_manager.cc create mode 100644 content/browser/devtools/worker_devtools_manager.h create mode 100644 content/browser/devtools/worker_devtools_message_filter.cc create mode 100644 content/browser/devtools/worker_devtools_message_filter.h create mode 100644 content/renderer/devtools/OWNERS create mode 100644 content/renderer/devtools/devtools_agent.cc create mode 100644 content/renderer/devtools/devtools_agent.h create mode 100644 content/renderer/devtools/devtools_agent_filter.cc create mode 100644 content/renderer/devtools/devtools_agent_filter.h create mode 100644 content/renderer/devtools/devtools_client.cc create mode 100644 content/renderer/devtools/devtools_client.h delete mode 100644 content/renderer/devtools_agent.cc delete mode 100644 content/renderer/devtools_agent.h delete mode 100644 content/renderer/devtools_agent_filter.cc delete mode 100644 content/renderer/devtools_agent_filter.h delete mode 100644 content/renderer/devtools_client.cc delete mode 100644 content/renderer/devtools_client.h diff --git a/android_webview/android_webview.gyp b/android_webview/android_webview.gyp index 12066d7..b84cf06 100644 --- a/android_webview/android_webview.gyp +++ b/android_webview/android_webview.gyp @@ -37,7 +37,7 @@ 'target_name': 'android_webview_pak', 'type': 'none', 'dependencies': [ - '<(DEPTH)/content/browser/debugger/devtools_resources.gyp:devtools_resources', + '<(DEPTH)/content/browser/devtools/devtools_resources.gyp:devtools_resources', '<(DEPTH)/content/content_resources.gyp:content_resources', '<(DEPTH)/net/net.gyp:net_resources', '<(DEPTH)/ui/ui.gyp:ui_resources', diff --git a/chrome/browser/automation/testing_automation_provider.cc b/chrome/browser/automation/testing_automation_provider.cc index 2bfddae..03f1b34 100644 --- a/chrome/browser/automation/testing_automation_provider.cc +++ b/chrome/browser/automation/testing_automation_provider.cc @@ -43,7 +43,7 @@ #include "chrome/browser/browser_process.h" #include "chrome/browser/browser_shutdown.h" #include "chrome/browser/content_settings/host_content_settings_map.h" -#include "chrome/browser/debugger/devtools_window.h" +#include "chrome/browser/devtools/devtools_window.h" #include "chrome/browser/download/download_prefs.h" #include "chrome/browser/download/download_service.h" #include "chrome/browser/download/download_service_factory.h" diff --git a/chrome/browser/browser_process_impl.cc b/chrome/browser/browser_process_impl.cc index bd0b15e..f4a72dd 100644 --- a/chrome/browser/browser_process_impl.cc +++ b/chrome/browser/browser_process_impl.cc @@ -26,8 +26,8 @@ #include "chrome/browser/chrome_plugin_service_filter.h" #include "chrome/browser/component_updater/component_updater_configurator.h" #include "chrome/browser/component_updater/component_updater_service.h" -#include "chrome/browser/debugger/remote_debugging_server.h" #include "chrome/browser/defaults.h" +#include "chrome/browser/devtools/remote_debugging_server.h" #include "chrome/browser/download/download_request_limiter.h" #include "chrome/browser/download/download_status_updater.h" #include "chrome/browser/extensions/event_router_forwarder.h" diff --git a/chrome/browser/debugger/OWNERS b/chrome/browser/debugger/OWNERS deleted file mode 100644 index 3f23035..0000000 --- a/chrome/browser/debugger/OWNERS +++ /dev/null @@ -1,3 +0,0 @@ -apavlov@chromium.org -pfeldman@chromium.org -yurys@chromium.org diff --git a/chrome/browser/debugger/browser_list_tabcontents_provider.cc b/chrome/browser/debugger/browser_list_tabcontents_provider.cc deleted file mode 100644 index 145728c..0000000 --- a/chrome/browser/debugger/browser_list_tabcontents_provider.cc +++ /dev/null @@ -1,96 +0,0 @@ -// Copyright (c) 2012 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/debugger/browser_list_tabcontents_provider.h" - -#include "base/path_service.h" -#include "chrome/browser/history/top_sites.h" -#include "chrome/browser/profiles/profile.h" -#include "chrome/browser/profiles/profile_manager.h" -#include "chrome/browser/ui/browser.h" -#include "chrome/browser/ui/browser_commands.h" -#include "chrome/browser/ui/browser_list.h" -#include "chrome/browser/ui/browser_tabstrip.h" -#include "chrome/common/chrome_paths.h" -#include "content/public/browser/browser_thread.h" -#include "content/public/browser/web_contents.h" -#include "content/public/common/url_constants.h" -#include "grit/devtools_discovery_page_resources.h" -#include "net/url_request/url_request_context_getter.h" -#include "ui/base/resource/resource_bundle.h" - -using content::DevToolsHttpHandlerDelegate; -using content::RenderViewHost; - -BrowserListTabContentsProvider::BrowserListTabContentsProvider( - Profile* profile) - : profile_(profile) { -} - -BrowserListTabContentsProvider::~BrowserListTabContentsProvider() { -} - -std::string BrowserListTabContentsProvider::GetDiscoveryPageHTML() { - std::set profiles; - for (BrowserList::const_iterator it = BrowserList::begin(), - end = BrowserList::end(); it != end; ++it) { - profiles.insert((*it)->profile()); - } - for (std::set::iterator it = profiles.begin(); - it != profiles.end(); ++it) { - history::TopSites* ts = (*it)->GetTopSites(); - if (ts) { - // TopSites updates itself after a delay. Ask TopSites to update itself - // when we're about to show the remote debugging landing page. - ts->SyncWithHistory(); - } - } - return ResourceBundle::GetSharedInstance().GetRawDataResource( - IDR_DEVTOOLS_DISCOVERY_PAGE_HTML).as_string(); -} - -bool BrowserListTabContentsProvider::BundlesFrontendResources() { - return true; -} - -FilePath BrowserListTabContentsProvider::GetDebugFrontendDir() { -#if defined(DEBUG_DEVTOOLS) - FilePath inspector_dir; - PathService::Get(chrome::DIR_INSPECTOR, &inspector_dir); - return inspector_dir; -#else - return FilePath(); -#endif -} - -std::string BrowserListTabContentsProvider::GetPageThumbnailData( - const GURL& url) { - for (BrowserList::const_iterator it = BrowserList::begin(), - end = BrowserList::end(); it != end; ++it) { - Profile* profile = (*it)->profile(); - history::TopSites* top_sites = profile->GetTopSites(); - if (!top_sites) - continue; - scoped_refptr data; - if (top_sites->GetPageThumbnail(url, &data)) - return std::string( - reinterpret_cast(data->front()), data->size()); - } - - return std::string(); -} - -RenderViewHost* BrowserListTabContentsProvider::CreateNewTarget() { - if (BrowserList::empty()) - chrome::NewEmptyWindow(profile_); - - if (BrowserList::empty()) - return NULL; - - content::WebContents* web_contents = chrome::AddSelectedTabWithURL( - *BrowserList::begin(), - GURL(chrome::kAboutBlankURL), - content::PAGE_TRANSITION_LINK); - return web_contents->GetRenderViewHost(); -} diff --git a/chrome/browser/debugger/browser_list_tabcontents_provider.h b/chrome/browser/debugger/browser_list_tabcontents_provider.h deleted file mode 100644 index e6e8039..0000000 --- a/chrome/browser/debugger/browser_list_tabcontents_provider.h +++ /dev/null @@ -1,35 +0,0 @@ -// Copyright (c) 2012 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_DEBUGGER_BROWSER_LIST_TABCONTENTS_PROVIDER_H_ -#define CHROME_BROWSER_DEBUGGER_BROWSER_LIST_TABCONTENTS_PROVIDER_H_ - -#include -#include - -#include "base/basictypes.h" -#include "base/compiler_specific.h" -#include "content/public/browser/devtools_http_handler_delegate.h" - -class Profile; - -class BrowserListTabContentsProvider - : public content::DevToolsHttpHandlerDelegate { - public: - explicit BrowserListTabContentsProvider(Profile* profile); - virtual ~BrowserListTabContentsProvider(); - - // DevToolsHttpProtocolHandler::Delegate overrides. - virtual std::string GetDiscoveryPageHTML() OVERRIDE; - virtual bool BundlesFrontendResources() OVERRIDE; - virtual FilePath GetDebugFrontendDir() OVERRIDE; - virtual std::string GetPageThumbnailData(const GURL& url) OVERRIDE; - virtual content::RenderViewHost* CreateNewTarget() OVERRIDE; - - private: - Profile* profile_; - DISALLOW_COPY_AND_ASSIGN(BrowserListTabContentsProvider); -}; - -#endif // CHROME_BROWSER_DEBUGGER_BROWSER_LIST_TABCONTENTS_PROVIDER_H_ diff --git a/chrome/browser/debugger/devtools_file_helper.cc b/chrome/browser/debugger/devtools_file_helper.cc deleted file mode 100644 index 2acebea..0000000 --- a/chrome/browser/debugger/devtools_file_helper.cc +++ /dev/null @@ -1,199 +0,0 @@ -// Copyright (c) 2012 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/debugger/devtools_file_helper.h" - -#include - -#include "base/bind.h" -#include "base/callback.h" -#include "base/file_util.h" -#include "base/lazy_instance.h" -#include "base/md5.h" -#include "base/value_conversions.h" -#include "chrome/browser/browser_process.h" -#include "chrome/browser/download/download_prefs.h" -#include "chrome/browser/prefs/pref_service.h" -#include "chrome/browser/prefs/scoped_user_pref_update.h" -#include "chrome/browser/profiles/profile.h" -#include "chrome/browser/ui/chrome_select_file_policy.h" -#include "chrome/common/pref_names.h" -#include "content/public/browser/browser_context.h" -#include "content/public/browser/download_manager.h" -#include "ui/base/dialogs/select_file_dialog.h" - -using content::BrowserContext; -using content::BrowserThread; -using content::DownloadManager; - -namespace { - -base::LazyInstance::Leaky - g_last_save_path = LAZY_INSTANCE_INITIALIZER; - -} // namespace - -class DevToolsFileHelper::SaveAsDialog : public ui::SelectFileDialog::Listener, - public base::RefCounted { - public: - explicit SaveAsDialog(DevToolsFileHelper* helper) - : helper_(helper) { - select_file_dialog_ = ui::SelectFileDialog::Create( - this, new ChromeSelectFilePolicy(NULL)); - } - - void ResetHelper() { - helper_ = NULL; - } - - void Show(const std::string& url, - const FilePath& initial_path, - const std::string& content) { - AddRef(); // Balanced in the three listener outcomes. - - url_ = url; - content_ = content; - - select_file_dialog_->SelectFile(ui::SelectFileDialog::SELECT_SAVEAS_FILE, - string16(), - initial_path, - NULL, - 0, - FILE_PATH_LITERAL(""), - NULL, - NULL); - } - - // ui::SelectFileDialog::Listener implementation. - virtual void FileSelected(const FilePath& path, - int index, void* params) { - if (helper_) - helper_->FileSelected(url_, path, content_); - Release(); // Balanced in ::Show. - } - - virtual void MultiFilesSelected( - const std::vector& files, void* params) { - Release(); // Balanced in ::Show. - NOTREACHED() << "Should not be able to select multiple files"; - } - - virtual void FileSelectionCanceled(void* params) { - Release(); // Balanced in ::Show. - } - - private: - friend class base::RefCounted; - virtual ~SaveAsDialog() {} - - scoped_refptr select_file_dialog_; - std::string url_; - std::string content_; - DevToolsFileHelper* helper_; -}; - -// static -void DevToolsFileHelper::WriteFile(const FilePath& path, - const std::string& content) { - DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE)); - DCHECK(!path.empty()); - - file_util::WriteFile(path, content.c_str(), content.length()); -} - -// static -void DevToolsFileHelper::AppendToFile(const FilePath& path, - const std::string& content) { - DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE)); - DCHECK(!path.empty()); - - file_util::AppendToFile(path, content.c_str(), content.length()); -} - -DevToolsFileHelper::DevToolsFileHelper(Profile* profile, Delegate* delegate) - : profile_(profile), - delegate_(delegate) { -} - -DevToolsFileHelper::~DevToolsFileHelper() { - if (save_as_dialog_) - save_as_dialog_->ResetHelper(); -} - -void DevToolsFileHelper::Save(const std::string& url, - const std::string& content, - bool save_as) { - PathsMap::iterator it = saved_files_.find(url); - if (it != saved_files_.end() && !save_as) { - FileSelected(url, it->second, content); - return; - } - - if (save_as_dialog_) - save_as_dialog_->ResetHelper(); - - const DictionaryValue* file_map = - profile_->GetPrefs()->GetDictionary(prefs::kDevToolsEditedFiles); - FilePath initial_path; - - const Value* path_value; - if (file_map->Get(base::MD5String(url), &path_value)) - base::GetValueAsFilePath(*path_value, &initial_path); - - if (initial_path.empty()) { - GURL gurl(url); - std::string suggested_file_name = gurl.is_valid() ? - gurl.ExtractFileName() : url; - - if (suggested_file_name.length() > 64) - suggested_file_name = suggested_file_name.substr(0, 64); - - if (!g_last_save_path.Pointer()->empty()) { - initial_path = g_last_save_path.Pointer()->DirName().AppendASCII( - suggested_file_name); - } else { - FilePath download_path = DownloadPrefs::FromDownloadManager( - BrowserContext::GetDownloadManager(profile_))->DownloadPath(); - initial_path = download_path.AppendASCII(suggested_file_name); - } - } - - save_as_dialog_ = new SaveAsDialog(this); - save_as_dialog_->Show(url, initial_path, content); -} - -void DevToolsFileHelper::Append(const std::string& url, - const std::string& content) { - PathsMap::iterator it = saved_files_.find(url); - if (it == saved_files_.end()) - return; - - delegate_->AppendedTo(url); - - BrowserThread::PostTask( - BrowserThread::FILE, FROM_HERE, - base::Bind(&DevToolsFileHelper::AppendToFile, - it->second, - content)); -} - -void DevToolsFileHelper::FileSelected(const std::string& url, - const FilePath& path, - const std::string& content) { - *g_last_save_path.Pointer() = path; - saved_files_[url] = path; - - DictionaryPrefUpdate update(profile_->GetPrefs(), - prefs::kDevToolsEditedFiles); - DictionaryValue* files_map = update.Get(); - files_map->SetWithoutPathExpansion(base::MD5String(url), - base::CreateFilePathValue(path)); - delegate_->FileSavedAs(url); - - BrowserThread::PostTask( - BrowserThread::FILE, FROM_HERE, - base::Bind(&DevToolsFileHelper::WriteFile, - path, - content)); -} diff --git a/chrome/browser/debugger/devtools_file_helper.h b/chrome/browser/debugger/devtools_file_helper.h deleted file mode 100644 index 641ca5c..0000000 --- a/chrome/browser/debugger/devtools_file_helper.h +++ /dev/null @@ -1,60 +0,0 @@ -// Copyright (c) 2012 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_DEBUGGER_DEVTOOLS_FILE_HELPER_H_ -#define CHROME_BROWSER_DEBUGGER_DEVTOOLS_FILE_HELPER_H_ - -#include -#include - -#include "base/basictypes.h" -#include "base/memory/ref_counted.h" - -class FilePath; -class Profile; - -class DevToolsFileHelper { - public: - class Delegate { - public: - virtual ~Delegate() {} - virtual void FileSavedAs(const std::string& url) = 0; - virtual void AppendedTo(const std::string& url) = 0; - }; - - DevToolsFileHelper(Profile* profile, Delegate* delegate); - ~DevToolsFileHelper(); - - // Saves |content| to the file and associates its path with given |url|. - // If client is calling this method with given |url| for the first time - // or |save_as| is true, confirmation dialog is shown to the user. - void Save(const std::string& url, - const std::string& content, - bool save_as); - - // Append |content| to the file that has been associated with given |url|. - // The |url| can be associated with a file via calling Save method. - // If the Save method has not been called for this |url|, then - // Append method does nothing. - void Append(const std::string& url, const std::string& content); - - void FileSelected(const std::string& url, - const FilePath& path, - const std::string& content); - - private: - static void WriteFile(const FilePath& path, const std::string& content); - static void AppendToFile(const FilePath& path, const std::string& content); - - class SaveAsDialog; - - Profile* profile_; - Delegate* delegate_; - scoped_refptr save_as_dialog_; - typedef std::map PathsMap; - PathsMap saved_files_; - DISALLOW_COPY_AND_ASSIGN(DevToolsFileHelper); -}; - -#endif // CHROME_BROWSER_DEBUGGER_DEVTOOLS_FILE_HELPER_H_ diff --git a/chrome/browser/debugger/devtools_sanity_browsertest.cc b/chrome/browser/debugger/devtools_sanity_browsertest.cc deleted file mode 100644 index 4266e66..0000000 --- a/chrome/browser/debugger/devtools_sanity_browsertest.cc +++ /dev/null @@ -1,600 +0,0 @@ -// Copyright (c) 2012 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 "base/bind.h" -#include "base/cancelable_callback.h" -#include "base/command_line.h" -#include "base/compiler_specific.h" -#include "base/memory/ref_counted.h" -#include "base/path_service.h" -#include "base/stringprintf.h" -#include "base/test/test_timeouts.h" -#include "base/utf_string_conversions.h" -#include "chrome/browser/debugger/devtools_window.h" -#include "chrome/browser/extensions/extension_service.h" -#include "chrome/browser/extensions/extension_system.h" -#include "chrome/browser/extensions/unpacked_installer.h" -#include "chrome/browser/profiles/profile.h" -#include "chrome/browser/ui/browser.h" -#include "chrome/browser/ui/browser_commands.h" -#include "chrome/browser/ui/browser_tabstrip.h" -#include "chrome/browser/ui/tabs/tab_strip_model.h" -#include "chrome/common/chrome_notification_types.h" -#include "chrome/common/chrome_paths.h" -#include "chrome/common/chrome_switches.h" -#include "chrome/test/base/in_process_browser_test.h" -#include "chrome/test/base/ui_test_utils.h" -#include "content/public/browser/child_process_data.h" -#include "content/public/browser/content_browser_client.h" -#include "content/public/browser/devtools_agent_host_registry.h" -#include "content/public/browser/devtools_client_host.h" -#include "content/public/browser/devtools_manager.h" -#include "content/public/browser/notification_registrar.h" -#include "content/public/browser/notification_service.h" -#include "content/public/browser/render_view_host.h" -#include "content/public/browser/web_contents.h" -#include "content/public/browser/worker_service.h" -#include "content/public/browser/worker_service_observer.h" -#include "content/public/test/browser_test_utils.h" -#include "net/test/test_server.h" - -using content::BrowserThread; -using content::DevToolsManager; -using content::DevToolsAgentHost; -using content::DevToolsAgentHostRegistry; -using content::NavigationController; -using content::RenderViewHost; -using content::WebContents; -using content::WorkerService; -using content::WorkerServiceObserver; - -namespace { - -// Used to block until a dev tools client window's browser is closed. -class BrowserClosedObserver : public content::NotificationObserver { - public: - explicit BrowserClosedObserver(Browser* browser) { - registrar_.Add(this, chrome::NOTIFICATION_BROWSER_CLOSED, - content::Source(browser)); - content::RunMessageLoop(); - } - - virtual void Observe(int type, - const content::NotificationSource& source, - const content::NotificationDetails& details) { - MessageLoopForUI::current()->Quit(); - } - - private: - content::NotificationRegistrar registrar_; - DISALLOW_COPY_AND_ASSIGN(BrowserClosedObserver); -}; - -// The delay waited in some cases where we don't have a notifications for an -// action we take. -const int kActionDelayMs = 500; - -const char kDebuggerTestPage[] = "files/devtools/debugger_test_page.html"; -const char kPauseWhenLoadingDevTools[] = - "files/devtools/pause_when_loading_devtools.html"; -const char kPauseWhenScriptIsRunning[] = - "files/devtools/pause_when_script_is_running.html"; -const char kPageWithContentScript[] = - "files/devtools/page_with_content_script.html"; -const char kNavigateBackTestPage[] = - "files/devtools/navigate_back.html"; -const char kChunkedTestPage[] = "chunked"; -const char kSlowTestPage[] = - "chunked?waitBeforeHeaders=100&waitBetweenChunks=100&chunksNumber=2"; -const char kSharedWorkerTestPage[] = - "files/workers/workers_ui_shared_worker.html"; -const char kReloadSharedWorkerTestPage[] = - "files/workers/debug_shared_worker_initialization.html"; - -void RunTestFunction(DevToolsWindow* window, const char* test_name) { - std::string result; - - // At first check that JavaScript part of the front-end is loaded by - // checking that global variable uiTests exists(it's created after all js - // files have been loaded) and has runTest method. - ASSERT_TRUE( - content::ExecuteJavaScriptAndExtractString( - window->GetRenderViewHost(), - L"", - L"window.domAutomationController.send(" - L"'' + (window.uiTests && (typeof uiTests.runTest)));", - &result)); - - if (result == "function") { - ASSERT_TRUE( - content::ExecuteJavaScriptAndExtractString( - window->GetRenderViewHost(), - L"", - UTF8ToWide(base::StringPrintf("uiTests.runTest('%s')", - test_name)), - &result)); - EXPECT_EQ("[OK]", result); - } else { - FAIL() << "DevTools front-end is broken."; - } -} - -class DevToolsSanityTest : public InProcessBrowserTest { - public: - DevToolsSanityTest() - : window_(NULL), - inspected_rvh_(NULL) {} - - protected: - void RunTest(const std::string& test_name, const std::string& test_page) { - OpenDevToolsWindow(test_page); - RunTestFunction(window_, test_name.c_str()); - CloseDevToolsWindow(); - } - - void OpenDevToolsWindow(const std::string& test_page) { - ASSERT_TRUE(test_server()->Start()); - GURL url = test_server()->GetURL(test_page); - ui_test_utils::NavigateToURL(browser(), url); - - content::WindowedNotificationObserver observer( - content::NOTIFICATION_LOAD_STOP, - content::NotificationService::AllSources()); - inspected_rvh_ = GetInspectedTab()->GetRenderViewHost(); - window_ = DevToolsWindow::OpenDevToolsWindow(inspected_rvh_); - observer.Wait(); - } - - WebContents* GetInspectedTab() { - return chrome::GetWebContentsAt(browser(), 0); - } - - void CloseDevToolsWindow() { - DevToolsManager* devtools_manager = DevToolsManager::GetInstance(); - // UnregisterDevToolsClientHostFor may destroy window_ so store the browser - // first. - Browser* browser = window_->browser(); - DevToolsAgentHost* agent = DevToolsAgentHostRegistry::GetDevToolsAgentHost( - inspected_rvh_); - devtools_manager->UnregisterDevToolsClientHostFor(agent); - - // Wait only when DevToolsWindow has a browser. For docked DevTools, this - // is NULL and we skip the wait. - if (browser) - BrowserClosedObserver close_observer(browser); - } - - DevToolsWindow* window_; - RenderViewHost* inspected_rvh_; -}; - -void TimeoutCallback(const std::string& timeout_message) { - FAIL() << timeout_message; - MessageLoop::current()->Quit(); -} - -// Base class for DevTools tests that test devtools functionality for -// extensions and content scripts. -class DevToolsExtensionTest : public DevToolsSanityTest, - public content::NotificationObserver { - public: - DevToolsExtensionTest() : DevToolsSanityTest() { - PathService::Get(chrome::DIR_TEST_DATA, &test_extensions_dir_); - test_extensions_dir_ = test_extensions_dir_.AppendASCII("devtools"); - test_extensions_dir_ = test_extensions_dir_.AppendASCII("extensions"); - } - - protected: - // Load an extension from test\data\devtools\extensions\ - void LoadExtension(const char* extension_name) { - FilePath path = test_extensions_dir_.AppendASCII(extension_name); - ASSERT_TRUE(LoadExtensionFromPath(path)) << "Failed to load extension."; - } - - private: - bool LoadExtensionFromPath(const FilePath& path) { - ExtensionService* service = extensions::ExtensionSystem::Get( - browser()->profile())->extension_service(); - size_t num_before = service->extensions()->size(); - { - content::NotificationRegistrar registrar; - registrar.Add(this, chrome::NOTIFICATION_EXTENSION_LOADED, - content::NotificationService::AllSources()); - base::CancelableClosure timeout( - base::Bind(&TimeoutCallback, "Extension load timed out.")); - MessageLoop::current()->PostDelayedTask( - FROM_HERE, timeout.callback(), base::TimeDelta::FromSeconds(4)); - extensions::UnpackedInstaller::Create(service)->Load(path); - content::RunMessageLoop(); - timeout.Cancel(); - } - size_t num_after = service->extensions()->size(); - if (num_after != (num_before + 1)) - return false; - - return WaitForExtensionViewsToLoad(); - } - - bool WaitForExtensionViewsToLoad() { - // Wait for all the extension render views that exist to finish loading. - // NOTE: This assumes that the extension views list is not changing while - // this method is running. - - content::NotificationRegistrar registrar; - registrar.Add(this, chrome::NOTIFICATION_EXTENSION_HOST_DID_STOP_LOADING, - content::NotificationService::AllSources()); - base::CancelableClosure timeout( - base::Bind(&TimeoutCallback, "Extension host load timed out.")); - MessageLoop::current()->PostDelayedTask( - FROM_HERE, timeout.callback(), base::TimeDelta::FromSeconds(4)); - - ExtensionProcessManager* manager = - extensions::ExtensionSystem::Get(browser()->profile())-> - process_manager(); - ExtensionProcessManager::ViewSet all_views = manager->GetAllViews(); - for (ExtensionProcessManager::ViewSet::const_iterator iter = - all_views.begin(); - iter != all_views.end();) { - if (!(*iter)->IsLoading()) - ++iter; - else - content::RunMessageLoop(); - } - - timeout.Cancel(); - return true; - } - - void Observe(int type, - const content::NotificationSource& source, - const content::NotificationDetails& details) { - switch (type) { - case chrome::NOTIFICATION_EXTENSION_LOADED: - case chrome::NOTIFICATION_EXTENSION_HOST_DID_STOP_LOADING: - MessageLoopForUI::current()->Quit(); - break; - default: - NOTREACHED(); - break; - } - } - - FilePath test_extensions_dir_; -}; - -class DevToolsExperimentalExtensionTest : public DevToolsExtensionTest { - public: - void SetUpCommandLine(CommandLine* command_line) OVERRIDE { - command_line->AppendSwitch(switches::kEnableExperimentalExtensionApis); - } -}; - -class WorkerDevToolsSanityTest : public InProcessBrowserTest { - public: - WorkerDevToolsSanityTest() : window_(NULL) {} - - protected: - class WorkerData : public base::RefCountedThreadSafe { - public: - WorkerData() : worker_process_id(0), worker_route_id(0) {} - int worker_process_id; - int worker_route_id; - - private: - friend class base::RefCountedThreadSafe; - ~WorkerData() {} - }; - - class WorkerCreationObserver : public WorkerServiceObserver { - public: - explicit WorkerCreationObserver(WorkerData* worker_data) - : worker_data_(worker_data) { - } - - private: - virtual ~WorkerCreationObserver() {} - - virtual void WorkerCreated ( - const GURL& url, - const string16& name, - int process_id, - int route_id) OVERRIDE { - worker_data_->worker_process_id = process_id; - worker_data_->worker_route_id = route_id; - WorkerService::GetInstance()->RemoveObserver(this); - BrowserThread::PostTask(BrowserThread::UI, FROM_HERE, - MessageLoop::QuitClosure()); - delete this; - } - scoped_refptr worker_data_; - }; - - class WorkerTerminationObserver : public WorkerServiceObserver { - public: - explicit WorkerTerminationObserver(WorkerData* worker_data) - : worker_data_(worker_data) { - } - - private: - virtual ~WorkerTerminationObserver() {} - - virtual void WorkerDestroyed(int process_id, int route_id) OVERRIDE { - ASSERT_EQ(worker_data_->worker_process_id, process_id); - ASSERT_EQ(worker_data_->worker_route_id, route_id); - WorkerService::GetInstance()->RemoveObserver(this); - BrowserThread::PostTask(BrowserThread::UI, FROM_HERE, - MessageLoop::QuitClosure()); - delete this; - } - scoped_refptr worker_data_; - }; - - void RunTest(const char* test_name, const char* test_page) { - ASSERT_TRUE(test_server()->Start()); - GURL url = test_server()->GetURL(test_page); - ui_test_utils::NavigateToURL(browser(), url); - - scoped_refptr worker_data = WaitForFirstSharedWorker(); - OpenDevToolsWindowForSharedWorker(worker_data.get()); - RunTestFunction(window_, test_name); - CloseDevToolsWindow(); - } - - static void TerminateWorkerOnIOThread(scoped_refptr worker_data) { - if (WorkerService::GetInstance()->TerminateWorker( - worker_data->worker_process_id, worker_data->worker_route_id)) { - WorkerService::GetInstance()->AddObserver( - new WorkerTerminationObserver(worker_data)); - return; - } - FAIL() << "Failed to terminate worker.\n"; - } - - static void TerminateWorker(scoped_refptr worker_data) { - BrowserThread::PostTask( - BrowserThread::IO, FROM_HERE, - base::Bind(&TerminateWorkerOnIOThread, worker_data)); - content::RunMessageLoop(); - } - - static void WaitForFirstSharedWorkerOnIOThread( - scoped_refptr worker_data) { - std::vector worker_info = - WorkerService::GetInstance()->GetWorkers(); - if (!worker_info.empty()) { - worker_data->worker_process_id = worker_info[0].process_id; - worker_data->worker_route_id = worker_info[0].route_id; - BrowserThread::PostTask(BrowserThread::UI, FROM_HERE, - MessageLoop::QuitClosure()); - return; - } - - WorkerService::GetInstance()->AddObserver( - new WorkerCreationObserver(worker_data.get())); - } - - static scoped_refptr WaitForFirstSharedWorker() { - scoped_refptr worker_data(new WorkerData()); - BrowserThread::PostTask( - BrowserThread::IO, FROM_HERE, - base::Bind(&WaitForFirstSharedWorkerOnIOThread, worker_data)); - content::RunMessageLoop(); - return worker_data; - } - - void OpenDevToolsWindowForSharedWorker(WorkerData* worker_data) { - Profile* profile = browser()->profile(); - window_ = DevToolsWindow::CreateDevToolsWindowForWorker(profile); - window_->Show(DEVTOOLS_TOGGLE_ACTION_SHOW); - DevToolsAgentHost* agent_host = - DevToolsAgentHostRegistry::GetDevToolsAgentHostForWorker( - worker_data->worker_process_id, - worker_data->worker_route_id); - DevToolsManager::GetInstance()->RegisterDevToolsClientHostFor( - agent_host, - window_->devtools_client_host()); - RenderViewHost* client_rvh = window_->GetRenderViewHost(); - WebContents* client_contents = WebContents::FromRenderViewHost(client_rvh); - if (client_contents->IsLoading()) { - content::WindowedNotificationObserver observer( - content::NOTIFICATION_LOAD_STOP, - content::Source( - &client_contents->GetController())); - observer.Wait(); - } - } - - void CloseDevToolsWindow() { - Browser* browser = window_->browser(); - browser->tab_strip_model()->CloseAllTabs(); - BrowserClosedObserver close_observer(browser); - } - - DevToolsWindow* window_; -}; - - -// Tests scripts panel showing. -IN_PROC_BROWSER_TEST_F(DevToolsSanityTest, TestShowScriptsTab) { - RunTest("testShowScriptsTab", kDebuggerTestPage); -} - -// Tests that scripts tab is populated with inspected scripts even if it -// hadn't been shown by the moment inspected paged refreshed. -// @see http://crbug.com/26312 -IN_PROC_BROWSER_TEST_F( - DevToolsSanityTest, - TestScriptsTabIsPopulatedOnInspectedPageRefresh) { - // Clear inspector settings to ensure that Elements will be - // current panel when DevTools window is open. - content::GetContentClient()->browser()->ClearInspectorSettings( - GetInspectedTab()->GetRenderViewHost()); - RunTest("testScriptsTabIsPopulatedOnInspectedPageRefresh", - kDebuggerTestPage); -} - -// Tests that chrome.devtools extension is correctly exposed. -IN_PROC_BROWSER_TEST_F(DevToolsExtensionTest, - TestDevToolsExtensionAPI) { - LoadExtension("devtools_extension"); - RunTest("waitForTestResultsInConsole", ""); -} - -// Tests that chrome.devtools extension can communicate with background page -// using extension messaging. -IN_PROC_BROWSER_TEST_F(DevToolsExtensionTest, - TestDevToolsExtensionMessaging) { - LoadExtension("devtools_messaging"); - RunTest("waitForTestResultsInConsole", ""); -} - -// Tests that chrome.experimental.devtools extension is correctly exposed -// when the extension has experimental permission. -IN_PROC_BROWSER_TEST_F(DevToolsExperimentalExtensionTest, - TestDevToolsExperimentalExtensionAPI) { - LoadExtension("devtools_experimental"); - RunTest("waitForTestResultsInConsole", ""); -} - -// Tests that a content script is in the scripts list. -// http://crbug.com/114104 -IN_PROC_BROWSER_TEST_F(DevToolsExtensionTest, - TestContentScriptIsPresent) { - LoadExtension("simple_content_script"); - RunTest("testContentScriptIsPresent", kPageWithContentScript); -} - -// Tests that scripts are not duplicated after Scripts Panel switch. -// Disabled - see http://crbug.com/124300 -IN_PROC_BROWSER_TEST_F(DevToolsSanityTest, - TestNoScriptDuplicatesOnPanelSwitch) { - RunTest("testNoScriptDuplicatesOnPanelSwitch", kDebuggerTestPage); -} - -// Tests that debugger works correctly if pause event occurs when DevTools -// frontend is being loaded. -// http://crbug.com/106114 -IN_PROC_BROWSER_TEST_F(DevToolsSanityTest, - TestPauseWhenLoadingDevTools) { - RunTest("testPauseWhenLoadingDevTools", kPauseWhenLoadingDevTools); -} - -// Tests that pressing 'Pause' will pause script execution if the script -// is already running. -IN_PROC_BROWSER_TEST_F(DevToolsSanityTest, TestPauseWhenScriptIsRunning) { - RunTest("testPauseWhenScriptIsRunning", kPauseWhenScriptIsRunning); -} - -// Tests network timing. -IN_PROC_BROWSER_TEST_F(DevToolsSanityTest, TestNetworkTiming) { - RunTest("testNetworkTiming", kSlowTestPage); -} - -// Tests network size. -IN_PROC_BROWSER_TEST_F(DevToolsSanityTest, TestNetworkSize) { - RunTest("testNetworkSize", kChunkedTestPage); -} - -// Tests raw headers text. -IN_PROC_BROWSER_TEST_F(DevToolsSanityTest, TestNetworkSyncSize) { - RunTest("testNetworkSyncSize", kChunkedTestPage); -} - -// Tests raw headers text. -IN_PROC_BROWSER_TEST_F(DevToolsSanityTest, TestNetworkRawHeadersText) { - RunTest("testNetworkRawHeadersText", kChunkedTestPage); -} - -// Tests that console messages are not duplicated on navigation back. -IN_PROC_BROWSER_TEST_F(DevToolsSanityTest, TestConsoleOnNavigateBack) { - RunTest("testConsoleOnNavigateBack", kNavigateBackTestPage); -} - -// Tests that inspector will reattach to inspected page when it is reloaded -// after a crash. See http://crbug.com/101952 -IN_PROC_BROWSER_TEST_F(DevToolsSanityTest, TestReattachAfterCrash) { - OpenDevToolsWindow(kDebuggerTestPage); - - content::CrashTab(GetInspectedTab()); - content::WindowedNotificationObserver observer( - content::NOTIFICATION_LOAD_STOP, - content::Source( - &chrome::GetActiveWebContents(browser())->GetController())); - chrome::Reload(browser(), CURRENT_TAB); - observer.Wait(); - - RunTestFunction(window_, "testReattachAfterCrash"); - CloseDevToolsWindow(); -} - -IN_PROC_BROWSER_TEST_F(DevToolsSanityTest, TestPageWithNoJavaScript) { - OpenDevToolsWindow("about:blank"); - std::string result; - ASSERT_TRUE( - content::ExecuteJavaScriptAndExtractString( - window_->GetRenderViewHost(), - L"", - L"window.domAutomationController.send(" - L"'' + (window.uiTests && (typeof uiTests.runTest)));", - &result)); - ASSERT_EQ("function", result) << "DevTools front-end is broken."; - CloseDevToolsWindow(); -} - -#if defined(OS_MACOSX) -#define MAYBE_InspectSharedWorker DISABLED_InspectSharedWorker -#else -#define MAYBE_InspectSharedWorker InspectSharedWorker -#endif -// Flakily fails with 25s timeout: http://crbug.com/89845 -IN_PROC_BROWSER_TEST_F(WorkerDevToolsSanityTest, MAYBE_InspectSharedWorker) { - RunTest("testSharedWorker", kSharedWorkerTestPage); -} - -// http://crbug.com/100538 -#if defined(OS_MACOSX) || defined(OS_WIN) -#define MAYBE_PauseInSharedWorkerInitialization DISABLED_PauseInSharedWorkerInitialization -#else -#define MAYBE_PauseInSharedWorkerInitialization PauseInSharedWorkerInitialization -#endif - -// http://crbug.com/106114 is masking -// MAYBE_PauseInSharedWorkerInitialization into -// DISABLED_PauseInSharedWorkerInitialization -IN_PROC_BROWSER_TEST_F(WorkerDevToolsSanityTest, - MAYBE_PauseInSharedWorkerInitialization) { - ASSERT_TRUE(test_server()->Start()); - GURL url = test_server()->GetURL(kReloadSharedWorkerTestPage); - ui_test_utils::NavigateToURL(browser(), url); - - scoped_refptr worker_data = WaitForFirstSharedWorker(); - OpenDevToolsWindowForSharedWorker(worker_data.get()); - - TerminateWorker(worker_data); - - // Reload page to restart the worker. - ui_test_utils::NavigateToURL(browser(), url); - - // Wait until worker script is paused on the debugger statement. - RunTestFunction(window_, "testPauseInSharedWorkerInitialization"); - CloseDevToolsWindow(); -} - -// Tests DevToolsAgentHost::AddMessageToConsole. -IN_PROC_BROWSER_TEST_F(DevToolsSanityTest, TestAddMessageToConsole) { - OpenDevToolsWindow("about:blank"); - DevToolsManager* devtools_manager = DevToolsManager::GetInstance(); - DevToolsAgentHost* agent_host = - DevToolsAgentHostRegistry::GetDevToolsAgentHost(inspected_rvh_); - devtools_manager->AddMessageToConsole(agent_host, - content::CONSOLE_MESSAGE_LEVEL_LOG, - "log"); - devtools_manager->AddMessageToConsole(agent_host, - content::CONSOLE_MESSAGE_LEVEL_ERROR, - "error"); - RunTestFunction(window_, "checkLogAndErrorMessages"); - CloseDevToolsWindow(); -} - -} // namespace diff --git a/chrome/browser/debugger/devtools_toggle_action.h b/chrome/browser/debugger/devtools_toggle_action.h deleted file mode 100644 index 83fbb5f..0000000 --- a/chrome/browser/debugger/devtools_toggle_action.h +++ /dev/null @@ -1,15 +0,0 @@ -// Copyright (c) 2011 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_DEBUGGER_DEVTOOLS_TOGGLE_ACTION_H_ -#define CHROME_BROWSER_DEBUGGER_DEVTOOLS_TOGGLE_ACTION_H_ - -enum DevToolsToggleAction { - DEVTOOLS_TOGGLE_ACTION_SHOW, - DEVTOOLS_TOGGLE_ACTION_SHOW_CONSOLE, - DEVTOOLS_TOGGLE_ACTION_INSPECT, - DEVTOOLS_TOGGLE_ACTION_TOGGLE -}; - -#endif // CHROME_BROWSER_DEBUGGER_DEVTOOLS_TOGGLE_ACTION_H_ diff --git a/chrome/browser/debugger/devtools_window.cc b/chrome/browser/debugger/devtools_window.cc deleted file mode 100644 index 3001b6b..0000000 --- a/chrome/browser/debugger/devtools_window.cc +++ /dev/null @@ -1,914 +0,0 @@ -// Copyright (c) 2012 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 - -#include "base/command_line.h" -#include "base/json/json_writer.h" -#include "base/lazy_instance.h" -#include "base/string_number_conversions.h" -#include "base/stringprintf.h" -#include "base/utf_string_conversions.h" -#include "base/values.h" -#include "chrome/browser/browser_process.h" -#include "chrome/browser/debugger/devtools_window.h" -#include "chrome/browser/extensions/api/debugger/debugger_api.h" -#include "chrome/browser/extensions/extension_service.h" -#include "chrome/browser/extensions/extension_system.h" -#include "chrome/browser/file_select_helper.h" -#include "chrome/browser/prefs/pref_service.h" -#include "chrome/browser/prefs/scoped_user_pref_update.h" -#include "chrome/browser/profiles/profile.h" -#include "chrome/browser/sessions/session_tab_helper.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_list.h" -#include "chrome/browser/ui/browser_list_impl.h" -#include "chrome/browser/ui/browser_window.h" -#include "chrome/browser/ui/tabs/tab_strip_model.h" -#include "chrome/common/chrome_notification_types.h" -#include "chrome/common/chrome_switches.h" -#include "chrome/common/pref_names.h" -#include "chrome/common/render_messages.h" -#include "chrome/common/url_constants.h" -#include "content/public/browser/content_browser_client.h" -#include "content/public/browser/devtools_agent_host_registry.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/navigation_controller.h" -#include "content/public/browser/navigation_entry.h" -#include "content/public/browser/notification_source.h" -#include "content/public/browser/render_process_host.h" -#include "content/public/browser/render_view_host.h" -#include "content/public/browser/web_contents.h" -#include "content/public/browser/web_contents_view.h" -#include "content/public/common/bindings_policy.h" -#include "content/public/common/page_transition_types.h" -#include "grit/generated_resources.h" - -typedef std::vector DevToolsWindowList; -namespace { -base::LazyInstance::Leaky - g_instances = LAZY_INSTANCE_INITIALIZER; -} // namespace - -using content::DevToolsAgentHost; -using content::DevToolsAgentHostRegistry; -using content::DevToolsClientHost; -using content::DevToolsManager; -using content::FileChooserParams; -using content::NativeWebKeyboardEvent; -using content::NavigationController; -using content::NavigationEntry; -using content::OpenURLParams; -using content::RenderViewHost; -using content::WebContents; - -const char DevToolsWindow::kDevToolsApp[] = "DevToolsApp"; - -const char kOldPrefBottom[] = "bottom"; -const char kOldPrefRight[] = "right"; - -const char kPrefBottom[] = "dock_bottom"; -const char kPrefRight[] = "dock_right"; -const char kPrefUndocked[] = "undocked"; - -const char kDockSideBottom[] = "bottom"; -const char kDockSideRight[] = "right"; -const char kDockSideUndocked[] = "undocked"; - -// Minimal height of devtools pane or content pane when devtools are docked -// to the browser window. -const int kMinDevToolsHeight = 50; -const int kMinDevToolsWidth = 150; -const int kMinContentsSize = 50; - -// static -void DevToolsWindow::RegisterUserPrefs(PrefService* prefs) { - prefs->RegisterBooleanPref(prefs::kDevToolsOpenDocked, - true, - PrefService::UNSYNCABLE_PREF); - prefs->RegisterStringPref(prefs::kDevToolsDockSide, - kDockSideBottom, - PrefService::UNSYNCABLE_PREF); - prefs->RegisterDictionaryPref(prefs::kDevToolsEditedFiles, - PrefService::UNSYNCABLE_PREF); -} - -// static -DevToolsWindow* DevToolsWindow::GetDockedInstanceForInspectedTab( - WebContents* inspected_web_contents) { - if (!inspected_web_contents) - return NULL; - - if (!DevToolsAgentHostRegistry::HasDevToolsAgentHost( - inspected_web_contents->GetRenderViewHost())) - return NULL; - DevToolsAgentHost* agent = DevToolsAgentHostRegistry::GetDevToolsAgentHost( - inspected_web_contents->GetRenderViewHost()); - DevToolsManager* manager = DevToolsManager::GetInstance(); - DevToolsClientHost* client_host = manager->GetDevToolsClientHostFor(agent); - DevToolsWindow* window = AsDevToolsWindow(client_host); - return window && window->IsDocked() ? window : NULL; -} - -// static -bool DevToolsWindow::IsDevToolsWindow(RenderViewHost* window_rvh) { - return AsDevToolsWindow(window_rvh) != NULL; -} - -// static -DevToolsWindow* DevToolsWindow::OpenDevToolsWindowForWorker( - Profile* profile, - DevToolsAgentHost* worker_agent) { - DevToolsWindow* window; - DevToolsClientHost* client = content::DevToolsManager::GetInstance()-> - GetDevToolsClientHostFor(worker_agent); - if (client) { - window = AsDevToolsWindow(client); - if (!window) - return NULL; - } else { - window = DevToolsWindow::CreateDevToolsWindowForWorker(profile); - DevToolsManager::GetInstance()->RegisterDevToolsClientHostFor( - worker_agent, - window->frontend_host_); - } - window->Show(DEVTOOLS_TOGGLE_ACTION_SHOW); - return window; -} - -// static -DevToolsWindow* DevToolsWindow::CreateDevToolsWindowForWorker( - Profile* profile) { - return Create(profile, NULL, DEVTOOLS_DOCK_SIDE_UNDOCKED, true); -} - -// static -DevToolsWindow* DevToolsWindow::OpenDevToolsWindow( - RenderViewHost* inspected_rvh) { - return ToggleDevToolsWindow(inspected_rvh, true, - DEVTOOLS_TOGGLE_ACTION_SHOW); -} - -// static -DevToolsWindow* DevToolsWindow::ToggleDevToolsWindow( - Browser* browser, - DevToolsToggleAction action) { - if (action == DEVTOOLS_TOGGLE_ACTION_TOGGLE && browser->is_devtools()) { - browser->tab_strip_model()->CloseAllTabs(); - return NULL; - } - RenderViewHost* inspected_rvh = - browser->tab_strip_model()->GetActiveWebContents()->GetRenderViewHost(); - - return ToggleDevToolsWindow(inspected_rvh, - action == DEVTOOLS_TOGGLE_ACTION_INSPECT, - action); -} - -void DevToolsWindow::InspectElement(RenderViewHost* inspected_rvh, - int x, - int y) { - DevToolsAgentHost* agent = DevToolsAgentHostRegistry::GetDevToolsAgentHost( - inspected_rvh); - DevToolsManager::GetInstance()->InspectElement(agent, x, y); - // TODO(loislo): we should initiate DevTools window opening from within - // renderer. Otherwise, we still can hit a race condition here. - OpenDevToolsWindow(inspected_rvh); -} - - -DevToolsWindow* DevToolsWindow::Create( - Profile* profile, - RenderViewHost* inspected_rvh, - DevToolsDockSide dock_side, - bool shared_worker_frontend) { - // Create WebContents with devtools. - WebContents* web_contents = - WebContents::Create(WebContents::CreateParams(profile)); - web_contents->GetRenderViewHost()->AllowBindings( - content::BINDINGS_POLICY_WEB_UI); - web_contents->GetController().LoadURL( - GetDevToolsUrl(profile, dock_side, shared_worker_frontend), - content::Referrer(), - content::PAGE_TRANSITION_AUTO_TOPLEVEL, - std::string()); - return new DevToolsWindow(web_contents, profile, inspected_rvh, dock_side); -} - -DevToolsWindow::DevToolsWindow(WebContents* web_contents, - Profile* profile, - RenderViewHost* inspected_rvh, - DevToolsDockSide dock_side) - : profile_(profile), - inspected_web_contents_(NULL), - web_contents_(web_contents), - browser_(NULL), - dock_side_(dock_side), - is_loaded_(false), - action_on_load_(DEVTOOLS_TOGGLE_ACTION_SHOW), - width_(-1), - height_(-1) { - frontend_host_ = DevToolsClientHost::CreateDevToolsFrontendHost(web_contents, - this); - file_helper_.reset(new DevToolsFileHelper(profile, this)); - - g_instances.Get().push_back(this); - // Wipe out page icon so that the default application icon is used. - NavigationEntry* entry = web_contents->GetController().GetActiveEntry(); - entry->GetFavicon().image = gfx::Image(); - entry->GetFavicon().valid = true; - - // Register on-load actions. - registrar_.Add( - this, - content::NOTIFICATION_LOAD_STOP, - content::Source(&web_contents->GetController())); - registrar_.Add( - this, - chrome::NOTIFICATION_TAB_CLOSING, - content::Source(&web_contents->GetController())); - registrar_.Add( - this, - chrome::NOTIFICATION_BROWSER_THEME_CHANGED, - content::Source( - ThemeServiceFactory::GetForProfile(profile_))); - // There is no inspected_rvh in case of shared workers. - if (inspected_rvh) - inspected_web_contents_ = WebContents::FromRenderViewHost(inspected_rvh); -} - -DevToolsWindow::~DevToolsWindow() { - DevToolsWindowList& instances = g_instances.Get(); - DevToolsWindowList::iterator it = std::find(instances.begin(), - instances.end(), - this); - DCHECK(it != instances.end()); - instances.erase(it); -} - -void DevToolsWindow::InspectedContentsClosing() { - if (IsDocked()) { - // Update dev tools to reflect removed dev tools window. - BrowserWindow* inspected_window = GetInspectedBrowserWindow(); - if (inspected_window) - inspected_window->UpdateDevTools(); - // In case of docked web_contents_, we own it so delete here. - delete web_contents_; - - delete this; - } else { - // First, initiate self-destruct to free all the registrars. - // Then close all tabs. Browser will take care of deleting web_contents_ - // for us. - Browser* browser = browser_; - delete this; - browser->tab_strip_model()->CloseAllTabs(); - } -} - -void DevToolsWindow::ContentsReplaced(WebContents* new_contents) { - inspected_web_contents_ = new_contents; -} - -void DevToolsWindow::Show(DevToolsToggleAction action) { - if (IsDocked()) { - Browser* inspected_browser; - int inspected_tab_index; - // Tell inspected browser to update splitter and switch to inspected panel. - if (!IsInspectedBrowserPopupOrPanel() && - FindInspectedBrowserAndTabIndex(&inspected_browser, - &inspected_tab_index)) { - BrowserWindow* inspected_window = inspected_browser->window(); - web_contents_->SetDelegate(this); - inspected_window->UpdateDevTools(); - web_contents_->GetView()->SetInitialFocus(); - inspected_window->Show(); - TabStripModel* tab_strip_model = inspected_browser->tab_strip_model(); - tab_strip_model->ActivateTabAt(inspected_tab_index, true); - ScheduleAction(action); - return; - } else { - // Sometimes we don't know where to dock. Stay undocked. - dock_side_ = DEVTOOLS_DOCK_SIDE_UNDOCKED; - } - } - - // Avoid consecutive window switching if the devtools window has been opened - // and the Inspect Element shortcut is pressed in the inspected tab. - bool should_show_window = - !browser_ || action != DEVTOOLS_TOGGLE_ACTION_INSPECT; - - if (!browser_) - CreateDevToolsBrowser(); - - if (should_show_window) { - browser_->window()->Show(); - web_contents_->GetView()->SetInitialFocus(); - } - - ScheduleAction(action); -} - -int DevToolsWindow::GetWidth(int container_width) { - if (width_ == -1) { - width_ = profile_->GetPrefs()-> - GetInteger(prefs::kDevToolsVSplitLocation); - } - - // By default, size devtools as 1/3 of the browser window. - if (width_ == -1) - width_ = container_width / 3; - - // Respect the minimum devtools width preset. - width_ = std::max(kMinDevToolsWidth, width_); - - // But it should never compromise the content window size unless the entire - // window is tiny. - width_ = std::min(container_width - kMinContentsSize, width_); - if (width_ < (kMinContentsSize / 2)) - width_ = container_width / 3; - return width_; -} - -int DevToolsWindow::GetHeight(int container_height) { - if (height_ == -1) { - height_ = profile_->GetPrefs()-> - GetInteger(prefs::kDevToolsHSplitLocation); - } - - // By default, size devtools as 1/3 of the browser window. - if (height_ == -1) - height_ = container_height / 3; - - // Respect the minimum devtools width preset. - height_ = std::max(kMinDevToolsHeight, height_); - - // But it should never compromise the content window size. - height_ = std::min(container_height - kMinContentsSize, height_); - if (height_ < (kMinContentsSize / 2)) - height_ = container_height / 3; - return height_; -} - -void DevToolsWindow::SetWidth(int width) { - width_ = width; - profile_->GetPrefs()->SetInteger(prefs::kDevToolsVSplitLocation, width); -} - -void DevToolsWindow::SetHeight(int height) { - height_ = height; - profile_->GetPrefs()->SetInteger(prefs::kDevToolsHSplitLocation, height); -} - -RenderViewHost* DevToolsWindow::GetRenderViewHost() { - return web_contents_->GetRenderViewHost(); -} - -void DevToolsWindow::CreateDevToolsBrowser() { - // TODO(pfeldman): Make browser's getter for this key static. - std::string wp_key; - wp_key.append(prefs::kBrowserWindowPlacement); - wp_key.append("_"); - wp_key.append(kDevToolsApp); - - PrefService* prefs = profile_->GetPrefs(); - if (!prefs->FindPreference(wp_key.c_str())) { - prefs->RegisterDictionaryPref(wp_key.c_str(), PrefService::UNSYNCABLE_PREF); - } - - const DictionaryValue* wp_pref = prefs->GetDictionary(wp_key.c_str()); - if (!wp_pref || wp_pref->empty()) { - DictionaryPrefUpdate update(prefs, wp_key.c_str()); - DictionaryValue* defaults = update.Get(); - defaults->SetInteger("left", 100); - defaults->SetInteger("top", 100); - defaults->SetInteger("right", 740); - defaults->SetInteger("bottom", 740); - defaults->SetBoolean("maximized", false); - defaults->SetBoolean("always_on_top", false); - } - - browser_ = new Browser(Browser::CreateParams::CreateForDevTools(profile_)); - browser_->tab_strip_model()->AddWebContents( - web_contents_, -1, content::PAGE_TRANSITION_AUTO_TOPLEVEL, - TabStripModel::ADD_ACTIVE); -} - -bool DevToolsWindow::FindInspectedBrowserAndTabIndex(Browser** browser, - int* tab) { - if (!inspected_web_contents_) - return false; - - bool found = FindInspectedBrowserAndTabIndexFromBrowserList( - chrome::BrowserListImpl::GetInstance(chrome::HOST_DESKTOP_TYPE_NATIVE), - browser, - tab); - // On Windows 8 we can have the desktop environment and the ASH environment - // active concurrently. If we fail to find the inspected web contents in the - // native browser list, then we should look in the ASH browser list. -#if defined(OS_WIN) && defined(USE_AURA) - if (!found) { - found = FindInspectedBrowserAndTabIndexFromBrowserList( - chrome::BrowserListImpl::GetInstance(chrome::HOST_DESKTOP_TYPE_ASH), - browser, - tab); - } -#endif - return found; -} - -bool DevToolsWindow::FindInspectedBrowserAndTabIndexFromBrowserList( - chrome::BrowserListImpl* browser_list, - Browser** browser, - int* tab) { - if (!inspected_web_contents_) - return false; - - for (chrome::BrowserListImpl::const_iterator it = browser_list->begin(); - it != browser_list->end(); ++it) { - int tab_index = (*it)->tab_strip_model()->GetIndexOfWebContents( - inspected_web_contents_); - if (tab_index != TabStripModel::kNoTab) { - *browser = *it; - *tab = tab_index; - return true; - } - } - return false; -} - -BrowserWindow* DevToolsWindow::GetInspectedBrowserWindow() { - Browser* browser = NULL; - int tab; - return FindInspectedBrowserAndTabIndex(&browser, &tab) ? - browser->window() : NULL; -} - -bool DevToolsWindow::IsInspectedBrowserPopupOrPanel() { - Browser* browser = NULL; - int tab; - if (!FindInspectedBrowserAndTabIndex(&browser, &tab)) - return false; - - return browser->is_type_popup() || browser->is_type_panel(); -} - -void DevToolsWindow::UpdateFrontendDockSide() { - base::StringValue dock_side(SideToString(dock_side_)); - CallClientFunction("InspectorFrontendAPI.setDockSide", &dock_side); - base::FundamentalValue docked(IsDocked()); - CallClientFunction("InspectorFrontendAPI.setAttachedWindow", &docked); -} - - -void DevToolsWindow::AddDevToolsExtensionsToClient() { - if (inspected_web_contents_) { - SessionTabHelper* session_tab_helper = - SessionTabHelper::FromWebContents(inspected_web_contents_); - if (session_tab_helper) { - base::FundamentalValue tabId(session_tab_helper->session_id().id()); - CallClientFunction("WebInspector.setInspectedTabId", &tabId); - } - } - ListValue results; - Profile* profile = - Profile::FromBrowserContext(web_contents_->GetBrowserContext()); - const ExtensionService* extension_service = extensions::ExtensionSystem::Get( - profile->GetOriginalProfile())->extension_service(); - if (!extension_service) - return; - - const ExtensionSet* extensions = extension_service->extensions(); - - for (ExtensionSet::const_iterator extension = extensions->begin(); - extension != extensions->end(); ++extension) { - if ((*extension)->devtools_url().is_empty()) - continue; - DictionaryValue* extension_info = new DictionaryValue(); - extension_info->Set("startPage", - new StringValue((*extension)->devtools_url().spec())); - extension_info->Set("name", new StringValue((*extension)->name())); - bool allow_experimental = (*extension)->HasAPIPermission( - extensions::APIPermission::kExperimental); - extension_info->Set("exposeExperimentalAPIs", - new base::FundamentalValue(allow_experimental)); - results.Append(extension_info); - } - CallClientFunction("WebInspector.addExtensions", &results); -} - -WebContents* DevToolsWindow::OpenURLFromTab(WebContents* source, - const OpenURLParams& params) { - if (inspected_web_contents_) - return inspected_web_contents_->OpenURL(params); - return NULL; -} - -void DevToolsWindow::CallClientFunction(const std::string& function_name, - const Value* arg) { - std::string json; - if (arg) - base::JSONWriter::Write(arg, &json); - - string16 javascript = - ASCIIToUTF16(function_name + "(" + json + ");"); - web_contents_->GetRenderViewHost()-> - ExecuteJavascriptInWebFrame(string16(), javascript); -} - -void DevToolsWindow::Observe(int type, - const content::NotificationSource& source, - const content::NotificationDetails& details) { - if (type == content::NOTIFICATION_LOAD_STOP && !is_loaded_) { - is_loaded_ = true; - UpdateTheme(); - DoAction(); - AddDevToolsExtensionsToClient(); - } else if (type == chrome::NOTIFICATION_TAB_CLOSING) { - if (content::Source(source).ptr() == - &web_contents_->GetController()) { - // This happens when browser closes all of its tabs as a result - // of window.Close event. - // Notify manager that this DevToolsClientHost no longer exists and - // initiate self-destuct here. - DevToolsManager::GetInstance()->ClientHostClosing(frontend_host_); - UpdateBrowserToolbar(); - delete this; - } - } else if (type == chrome::NOTIFICATION_BROWSER_THEME_CHANGED) { - UpdateTheme(); - } -} - -void DevToolsWindow::ScheduleAction(DevToolsToggleAction action) { - action_on_load_ = action; - if (is_loaded_) - DoAction(); -} - -void DevToolsWindow::DoAction() { - UpdateFrontendDockSide(); - switch (action_on_load_) { - case DEVTOOLS_TOGGLE_ACTION_SHOW_CONSOLE: - CallClientFunction("InspectorFrontendAPI.showConsole", NULL); - break; - case DEVTOOLS_TOGGLE_ACTION_INSPECT: - CallClientFunction("InspectorFrontendAPI.enterInspectElementMode", NULL); - case DEVTOOLS_TOGGLE_ACTION_SHOW: - case DEVTOOLS_TOGGLE_ACTION_TOGGLE: - // Do nothing. - break; - default: - NOTREACHED(); - } - action_on_load_ = DEVTOOLS_TOGGLE_ACTION_SHOW; -} - -std::string SkColorToRGBAString(SkColor color) { - // We convert the alpha using DoubleToString because StringPrintf will use - // locale specific formatters (e.g., use , instead of . in German). - return StringPrintf("rgba(%d,%d,%d,%s)", SkColorGetR(color), - SkColorGetG(color), SkColorGetB(color), - base::DoubleToString(SkColorGetA(color) / 255.0).c_str()); -} - -// static -GURL DevToolsWindow::GetDevToolsUrl(Profile* profile, - DevToolsDockSide dock_side, - bool shared_worker_frontend) { - ThemeService* tp = ThemeServiceFactory::GetForProfile(profile); - CHECK(tp); - - SkColor color_toolbar = - tp->GetColor(ThemeService::COLOR_TOOLBAR); - SkColor color_tab_text = - tp->GetColor(ThemeService::COLOR_BOOKMARK_TEXT); - - const CommandLine& command_line = *CommandLine::ForCurrentProcess(); - bool experiments_enabled = - command_line.HasSwitch(switches::kEnableDevToolsExperiments); - - std::string url_string = StringPrintf("%sdevtools.html?" - "dockSide=%s&toolbarColor=%s&textColor=%s%s%s", - chrome::kChromeUIDevToolsURL, - SideToString(dock_side).c_str(), - SkColorToRGBAString(color_toolbar).c_str(), - SkColorToRGBAString(color_tab_text).c_str(), - shared_worker_frontend ? "&isSharedWorker=true" : "", - experiments_enabled ? "&experiments=true" : ""); - return GURL(url_string); -} - -void DevToolsWindow::UpdateTheme() { - ThemeService* tp = ThemeServiceFactory::GetForProfile(profile_); - CHECK(tp); - - SkColor color_toolbar = - tp->GetColor(ThemeService::COLOR_TOOLBAR); - SkColor color_tab_text = - tp->GetColor(ThemeService::COLOR_BOOKMARK_TEXT); - std::string command = StringPrintf( - "InspectorFrontendAPI.setToolbarColors(\"%s\", \"%s\")", - SkColorToRGBAString(color_toolbar).c_str(), - SkColorToRGBAString(color_tab_text).c_str()); - web_contents_->GetRenderViewHost()-> - ExecuteJavascriptInWebFrame(string16(), UTF8ToUTF16(command)); -} - -void DevToolsWindow::AddNewContents(WebContents* source, - WebContents* new_contents, - WindowOpenDisposition disposition, - const gfx::Rect& initial_pos, - bool user_gesture, - bool* was_blocked) { - if (inspected_web_contents_) { - inspected_web_contents_->GetDelegate()->AddNewContents( - source, new_contents, disposition, initial_pos, user_gesture, - was_blocked); - } -} - -bool DevToolsWindow::PreHandleKeyboardEvent( - WebContents* source, - const NativeWebKeyboardEvent& event, bool* is_keyboard_shortcut) { - if (IsDocked()) { - BrowserWindow* inspected_window = GetInspectedBrowserWindow(); - if (inspected_window) - return inspected_window->PreHandleKeyboardEvent( - event, is_keyboard_shortcut); - } - return false; -} - -void DevToolsWindow::HandleKeyboardEvent(WebContents* source, - const NativeWebKeyboardEvent& event) { - if (IsDocked()) { - if (event.windowsKeyCode == 0x08) { - // Do not navigate back in history on Windows (http://crbug.com/74156). - return; - } - BrowserWindow* inspected_window = GetInspectedBrowserWindow(); - if (inspected_window) - inspected_window->HandleKeyboardEvent(event); - } -} - -// static -DevToolsWindow* DevToolsWindow::ToggleDevToolsWindow( - RenderViewHost* inspected_rvh, - bool force_open, - DevToolsToggleAction action) { - DevToolsAgentHost* agent = DevToolsAgentHostRegistry::GetDevToolsAgentHost( - inspected_rvh); - DevToolsManager* manager = DevToolsManager::GetInstance(); - DevToolsClientHost* host = manager->GetDevToolsClientHostFor(agent); - DevToolsWindow* window = AsDevToolsWindow(host); - if (host && !window) { - // Break remote debugging / extension debugging session. - host->ReplacedWithAnotherClient(); - manager->UnregisterDevToolsClientHostFor(agent); - } - - bool do_open = force_open; - if (!window) { - Profile* profile = Profile::FromBrowserContext( - inspected_rvh->GetProcess()->GetBrowserContext()); - DevToolsDockSide dock_side = GetDockSideFromPrefs(profile); - window = Create(profile, inspected_rvh, dock_side, false); - manager->RegisterDevToolsClientHostFor(agent, window->frontend_host_); - do_open = true; - } - - // Update toolbar to reflect DevTools changes. - window->UpdateBrowserToolbar(); - - // If window is docked and visible, we hide it on toggle. If window is - // undocked, we show (activate) it. - if (!window->IsDocked() || do_open) - window->Show(action); - else - manager->UnregisterDevToolsClientHostFor(agent); - - return window; -} - -// static -DevToolsWindow* DevToolsWindow::AsDevToolsWindow( - DevToolsClientHost* client_host) { - if (!client_host || g_instances == NULL) - return NULL; - DevToolsWindowList& instances = g_instances.Get(); - for (DevToolsWindowList::iterator it = instances.begin(); - it != instances.end(); ++it) { - if ((*it)->frontend_host_ == client_host) - return *it; - } - return NULL; -} - -// static -DevToolsWindow* DevToolsWindow::AsDevToolsWindow(RenderViewHost* window_rvh) { - if (g_instances == NULL) - return NULL; - DevToolsWindowList& instances = g_instances.Get(); - for (DevToolsWindowList::iterator it = instances.begin(); - it != instances.end(); ++it) { - if ((*it)->web_contents_->GetRenderViewHost() == window_rvh) - return *it; - } - return NULL; -} - -void DevToolsWindow::ActivateWindow() { - if (!IsDocked()) { - if (!browser_->window()->IsActive()) { - browser_->window()->Activate(); - } - } else { - BrowserWindow* inspected_window = GetInspectedBrowserWindow(); - if (inspected_window) - web_contents_->GetView()->Focus(); - } -} - -void DevToolsWindow::CloseWindow() { - DCHECK(IsDocked()); - DevToolsManager::GetInstance()->ClientHostClosing(frontend_host_); - InspectedContentsClosing(); -} - -void DevToolsWindow::MoveWindow(int x, int y) { - if (!IsDocked()) { - gfx::Rect bounds = browser_->window()->GetBounds(); - bounds.Offset(x, y); - browser_->window()->SetBounds(bounds); - } -} - -void DevToolsWindow::SetDockSide(const std::string& side) { - DevToolsDockSide requested_side = SideFromString(side); - bool dock_requested = requested_side != DEVTOOLS_DOCK_SIDE_UNDOCKED; - bool is_docked = IsDocked(); - - if (dock_requested && (!inspected_web_contents_ || - !GetInspectedBrowserWindow() || IsInspectedBrowserPopupOrPanel())) { - // Cannot dock, avoid window flashing due to close-reopen cycle. - return; - } - - dock_side_ = requested_side; - if (dock_requested) { - if (!is_docked) { - // Detach window from the external devtools browser. It will lead to - // 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_)); - browser_ = NULL; - } - } else if (is_docked) { - // Update inspected window to hide split and reset it. - BrowserWindow* inspected_window = GetInspectedBrowserWindow(); - if (inspected_window) - inspected_window->UpdateDevTools(); - } - - std::string pref_value = kPrefBottom; - switch (dock_side_) { - case DEVTOOLS_DOCK_SIDE_UNDOCKED: - pref_value = kPrefUndocked; - break; - case DEVTOOLS_DOCK_SIDE_RIGHT: - pref_value = kPrefRight; - break; - case DEVTOOLS_DOCK_SIDE_BOTTOM: - pref_value = kPrefBottom; - break; - } - profile_->GetPrefs()->SetString(prefs::kDevToolsDockSide, pref_value); - - Show(DEVTOOLS_TOGGLE_ACTION_SHOW); -} - -void DevToolsWindow::OpenInNewTab(const std::string& url) { - OpenURLParams params(GURL(url), - content::Referrer(), - NEW_FOREGROUND_TAB, - content::PAGE_TRANSITION_LINK, - false /* is_renderer_initiated */); - if (inspected_web_contents_) { - inspected_web_contents_->OpenURL(params); - } else { - for (BrowserList::const_iterator it = BrowserList::begin(); - it != BrowserList::end(); ++it) { - if ((*it)->type() == Browser::TYPE_TABBED) { - (*it)->OpenURL(params); - break; - } - } - } -} - -void DevToolsWindow::SaveToFile(const std::string& url, - const std::string& content, - bool save_as) { - file_helper_->Save(url, content, save_as); -} - -void DevToolsWindow::AppendToFile(const std::string& url, - const std::string& content) { - file_helper_->Append(url, content); -} - -void DevToolsWindow::FileSavedAs(const std::string& url) { - StringValue url_value(url); - CallClientFunction("InspectorFrontendAPI.savedURL", &url_value); -} - -void DevToolsWindow::AppendedTo(const std::string& url) { - StringValue url_value(url); - CallClientFunction("InspectorFrontendAPI.appendedToURL", &url_value); -} - -content::JavaScriptDialogCreator* DevToolsWindow::GetJavaScriptDialogCreator() { - if (inspected_web_contents_ && inspected_web_contents_->GetDelegate()) { - return inspected_web_contents_->GetDelegate()-> - GetJavaScriptDialogCreator(); - } - return content::WebContentsDelegate::GetJavaScriptDialogCreator(); -} - -void DevToolsWindow::RunFileChooser(WebContents* web_contents, - const FileChooserParams& params) { - FileSelectHelper::RunFileChooser(web_contents, params); -} - -void DevToolsWindow::WebContentsFocused(WebContents* contents) { - Browser* inspected_browser = NULL; - int inspected_tab_index = -1; - - if (IsDocked() && FindInspectedBrowserAndTabIndex(&inspected_browser, - &inspected_tab_index)) { - inspected_browser->window()->WebContentsFocused(contents); - } -} - -void DevToolsWindow::UpdateBrowserToolbar() { - if (!inspected_web_contents_) - return; - BrowserWindow* inspected_window = GetInspectedBrowserWindow(); - if (inspected_window) - inspected_window->UpdateToolbar(inspected_web_contents_, false); -} - -bool DevToolsWindow::IsDocked() { - return dock_side_ != DEVTOOLS_DOCK_SIDE_UNDOCKED; -} - -// static -DevToolsDockSide DevToolsWindow::GetDockSideFromPrefs(Profile* profile) { - std::string dock_side = - profile->GetPrefs()->GetString(prefs::kDevToolsDockSide); - - // Migrate prefs - if (dock_side == kOldPrefBottom || dock_side == kOldPrefRight) { - bool docked = profile->GetPrefs()->GetBoolean(prefs::kDevToolsOpenDocked); - if (dock_side == kOldPrefBottom) - return docked ? DEVTOOLS_DOCK_SIDE_BOTTOM : DEVTOOLS_DOCK_SIDE_UNDOCKED; - else - return docked ? DEVTOOLS_DOCK_SIDE_RIGHT : DEVTOOLS_DOCK_SIDE_UNDOCKED; - } - - if (dock_side == kPrefUndocked) - return DEVTOOLS_DOCK_SIDE_UNDOCKED; - else if (dock_side == kPrefRight) - return DEVTOOLS_DOCK_SIDE_RIGHT; - // Default to docked to bottom - return DEVTOOLS_DOCK_SIDE_BOTTOM; -} - -// static -std::string DevToolsWindow::SideToString(DevToolsDockSide dock_side) { - std::string dock_side_string; - switch (dock_side) { - case DEVTOOLS_DOCK_SIDE_UNDOCKED: return kDockSideUndocked; - case DEVTOOLS_DOCK_SIDE_RIGHT: return kDockSideRight; - case DEVTOOLS_DOCK_SIDE_BOTTOM: return kDockSideBottom; - } - return kDockSideUndocked; -} - -// static -DevToolsDockSide DevToolsWindow::SideFromString( - const std::string& dock_side) { - if (dock_side == kDockSideRight) - return DEVTOOLS_DOCK_SIDE_RIGHT; - if (dock_side == kDockSideBottom) - return DEVTOOLS_DOCK_SIDE_BOTTOM; - return DEVTOOLS_DOCK_SIDE_UNDOCKED; -} diff --git a/chrome/browser/debugger/devtools_window.h b/chrome/browser/debugger/devtools_window.h deleted file mode 100644 index b0b72a0..0000000 --- a/chrome/browser/debugger/devtools_window.h +++ /dev/null @@ -1,214 +0,0 @@ -// Copyright (c) 2012 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_DEBUGGER_DEVTOOLS_WINDOW_H_ -#define CHROME_BROWSER_DEBUGGER_DEVTOOLS_WINDOW_H_ - -#include -#include - -#include "base/basictypes.h" -#include "base/memory/scoped_ptr.h" -#include "chrome/browser/debugger/devtools_file_helper.h" -#include "chrome/browser/debugger/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 "content/public/browser/web_contents_delegate.h" - -class Browser; -class BrowserWindow; -class PrefService; -class Profile; - -namespace base { -class Value; -} - -namespace chrome { -class BrowserListImpl; -} - -namespace content { -class DevToolsAgentHost; -class DevToolsClientHost; -struct FileChooserParams; -class RenderViewHost; -class WebContents; -} - -namespace IPC { -class Message; -} - -enum DevToolsDockSide { - DEVTOOLS_DOCK_SIDE_UNDOCKED = 0, - DEVTOOLS_DOCK_SIDE_BOTTOM, - DEVTOOLS_DOCK_SIDE_RIGHT -}; - -class DevToolsWindow : private content::NotificationObserver, - private content::WebContentsDelegate, - private content::DevToolsFrontendHostDelegate, - private DevToolsFileHelper::Delegate { - public: - static const char kDevToolsApp[]; - static void RegisterUserPrefs(PrefService* prefs); - static DevToolsWindow* GetDockedInstanceForInspectedTab( - content::WebContents* inspected_tab); - static bool IsDevToolsWindow(content::RenderViewHost* window_rvh); - - static DevToolsWindow* OpenDevToolsWindowForWorker( - Profile* profile, - content::DevToolsAgentHost* worker_agent); - static DevToolsWindow* CreateDevToolsWindowForWorker(Profile* profile); - static DevToolsWindow* OpenDevToolsWindow( - content::RenderViewHost* inspected_rvh); - static DevToolsWindow* ToggleDevToolsWindow( - Browser* browser, - DevToolsToggleAction action); - - // Exposed for testing, normal clients should not use this method. - static DevToolsWindow* ToggleDevToolsWindow( - content::RenderViewHost* inspected_rvh, - bool force_open, - DevToolsToggleAction action); - static void InspectElement( - content::RenderViewHost* inspected_rvh, int x, int y); - - virtual ~DevToolsWindow(); - - // Overridden from DevToolsClientHost. - virtual void InspectedContentsClosing() OVERRIDE; - virtual void ContentsReplaced(content::WebContents* new_contents) OVERRIDE; - content::RenderViewHost* GetRenderViewHost(); - - void Show(DevToolsToggleAction action); - - content::WebContents* web_contents() { return web_contents_; } - Browser* browser() { return browser_; } // For tests. - DevToolsDockSide dock_side() { return dock_side_; } - content::DevToolsClientHost* devtools_client_host() { return frontend_host_; } - - // Returns preferred devtools window width for given |container_width|. It - // tries to use the saved window width, or, if none exists, 1/3 of the - // container width, then clamps to try and ensure both devtools and content - // are at least somewhat visible. - // Called only for the case when devtools window is docked to the side. - int GetWidth(int container_width); - - // Returns preferred devtools window height for given |container_height|. - // Uses the same logic as GetWidth. - // Called only for the case when devtools window is docked to bottom. - int GetHeight(int container_height); - - // Stores preferred devtools window width for this instance. - void SetWidth(int width); - - // Stores preferred devtools window height for this instance. - void SetHeight(int height); - - private: - static DevToolsWindow* Create(Profile* profile, - content::RenderViewHost* inspected_rvh, - DevToolsDockSide dock_side, - bool shared_worker_frontend); - DevToolsWindow(content::WebContents* web_contents, - Profile* profile, - content::RenderViewHost* inspected_rvh, - DevToolsDockSide dock_side); - - void CreateDevToolsBrowser(); - bool FindInspectedBrowserAndTabIndex(Browser**, int* tab); - bool FindInspectedBrowserAndTabIndexFromBrowserList( - chrome::BrowserListImpl* browser_list, - Browser** browser, - int* tab); - BrowserWindow* GetInspectedBrowserWindow(); - bool IsInspectedBrowserPopupOrPanel(); - void UpdateFrontendDockSide(); - - // Overridden from content::NotificationObserver. - virtual void Observe(int type, - const content::NotificationSource& source, - const content::NotificationDetails& details) OVERRIDE; - - void ScheduleAction(DevToolsToggleAction action); - void DoAction(); - static GURL GetDevToolsUrl(Profile* profile, - DevToolsDockSide dock_side, - bool shared_worker_frontend); - void UpdateTheme(); - void AddDevToolsExtensionsToClient(); - void CallClientFunction(const std::string& function_name, - const base::Value* arg); - // Overridden from content::WebContentsDelegate. - virtual content::WebContents* OpenURLFromTab( - content::WebContents* source, - const content::OpenURLParams& params) OVERRIDE; - virtual void AddNewContents(content::WebContents* source, - content::WebContents* new_contents, - WindowOpenDisposition disposition, - const gfx::Rect& initial_pos, - bool user_gesture, - bool* was_blocked) OVERRIDE; - virtual void CloseContents(content::WebContents* source) OVERRIDE {} - virtual bool PreHandleKeyboardEvent( - content::WebContents* source, - const content::NativeWebKeyboardEvent& event, - bool* is_keyboard_shortcut) OVERRIDE; - virtual void HandleKeyboardEvent( - content::WebContents* source, - const content::NativeWebKeyboardEvent& event) OVERRIDE; - virtual content::JavaScriptDialogCreator* - GetJavaScriptDialogCreator() OVERRIDE; - virtual void RunFileChooser( - content::WebContents* web_contents, - const content::FileChooserParams& params) OVERRIDE; - virtual void WebContentsFocused(content::WebContents* contents) OVERRIDE; - - virtual void FrameNavigating(const std::string& url) OVERRIDE {} - - static DevToolsWindow* AsDevToolsWindow(content::DevToolsClientHost*); - static DevToolsWindow* AsDevToolsWindow(content::RenderViewHost*); - - // content::DevToolsFrontendHostDelegate overrides. - virtual void ActivateWindow() OVERRIDE; - virtual void CloseWindow() OVERRIDE; - virtual void MoveWindow(int x, int y) OVERRIDE; - virtual void SetDockSide(const std::string& side) 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; - - // Overridden from DevToolsFileHelper::Delegate - virtual void FileSavedAs(const std::string& url) OVERRIDE; - virtual void AppendedTo(const std::string& url) OVERRIDE; - - void UpdateBrowserToolbar(); - bool IsDocked(); - static DevToolsDockSide GetDockSideFromPrefs(Profile* profile); - static std::string SideToString(DevToolsDockSide dock_side); - static DevToolsDockSide SideFromString(const std::string& dock_side); - - Profile* profile_; - content::WebContents* inspected_web_contents_; - content::WebContents* web_contents_; - Browser* browser_; - DevToolsDockSide dock_side_; - bool is_loaded_; - DevToolsToggleAction action_on_load_; - content::NotificationRegistrar registrar_; - content::DevToolsClientHost* frontend_host_; - scoped_ptr file_helper_; - int width_; - int height_; - DISALLOW_COPY_AND_ASSIGN(DevToolsWindow); -}; - -#endif // CHROME_BROWSER_DEBUGGER_DEVTOOLS_WINDOW_H_ diff --git a/chrome/browser/debugger/frontend/devtools_discovery_page.html b/chrome/browser/debugger/frontend/devtools_discovery_page.html deleted file mode 100644 index 85c03b8..0000000 --- a/chrome/browser/debugger/frontend/devtools_discovery_page.html +++ /dev/null @@ -1,142 +0,0 @@ - - -Inspectable pages - - - - - -
Inspectable pages
-
-
-
- - diff --git a/chrome/browser/debugger/frontend/devtools_discovery_page_resources.grd b/chrome/browser/debugger/frontend/devtools_discovery_page_resources.grd deleted file mode 100644 index 85ad2aa..0000000 --- a/chrome/browser/debugger/frontend/devtools_discovery_page_resources.grd +++ /dev/null @@ -1,21 +0,0 @@ - - - - - - - - - - - - - - - diff --git a/chrome/browser/debugger/remote_debugging_server.cc b/chrome/browser/debugger/remote_debugging_server.cc deleted file mode 100644 index b951206..0000000 --- a/chrome/browser/debugger/remote_debugging_server.cc +++ /dev/null @@ -1,27 +0,0 @@ -// Copyright (c) 2012 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/debugger/remote_debugging_server.h" - -#include "chrome/browser/debugger/browser_list_tabcontents_provider.h" -#include "chrome/browser/ui/webui/devtools_ui.h" -#include "content/public/browser/devtools_http_handler.h" -#include "net/base/tcp_listen_socket.h" - -RemoteDebuggingServer::RemoteDebuggingServer(Profile* profile, - const std::string& ip, - int port, - const std::string& frontend_url) { - // Initialize DevTools data source. - DevToolsUI::RegisterDevToolsDataSource(profile); - - devtools_http_handler_ = content::DevToolsHttpHandler::Start( - new net::TCPListenSocketFactory(ip, port), - frontend_url, - new BrowserListTabContentsProvider(profile)); -} - -RemoteDebuggingServer::~RemoteDebuggingServer() { - devtools_http_handler_->Stop(); -} diff --git a/chrome/browser/debugger/remote_debugging_server.h b/chrome/browser/debugger/remote_debugging_server.h deleted file mode 100644 index e1c2785..0000000 --- a/chrome/browser/debugger/remote_debugging_server.h +++ /dev/null @@ -1,32 +0,0 @@ -// Copyright (c) 2011 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_DEBUGGER_REMOTE_DEBUGGING_SERVER_H_ -#define CHROME_BROWSER_DEBUGGER_REMOTE_DEBUGGING_SERVER_H_ - -#include - -#include "base/basictypes.h" - -class Profile; - -namespace content { -class DevToolsHttpHandler; -} - -class RemoteDebuggingServer { - public: - RemoteDebuggingServer(Profile* profile, - const std::string& ip, - int port, - const std::string& frontend_url); - - virtual ~RemoteDebuggingServer(); - - private: - content::DevToolsHttpHandler* devtools_http_handler_; - DISALLOW_COPY_AND_ASSIGN(RemoteDebuggingServer); -}; - -#endif // CHROME_BROWSER_DEBUGGER_REMOTE_DEBUGGING_SERVER_H_ diff --git a/chrome/browser/devtools/OWNERS b/chrome/browser/devtools/OWNERS new file mode 100644 index 0000000..bb6028e --- /dev/null +++ b/chrome/browser/devtools/OWNERS @@ -0,0 +1,2 @@ +pfeldman@chromium.org +yurys@chromium.org diff --git a/chrome/browser/devtools/browser_list_tabcontents_provider.cc b/chrome/browser/devtools/browser_list_tabcontents_provider.cc new file mode 100644 index 0000000..7390453 --- /dev/null +++ b/chrome/browser/devtools/browser_list_tabcontents_provider.cc @@ -0,0 +1,96 @@ +// Copyright (c) 2012 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/browser_list_tabcontents_provider.h" + +#include "base/path_service.h" +#include "chrome/browser/history/top_sites.h" +#include "chrome/browser/profiles/profile.h" +#include "chrome/browser/profiles/profile_manager.h" +#include "chrome/browser/ui/browser.h" +#include "chrome/browser/ui/browser_commands.h" +#include "chrome/browser/ui/browser_list.h" +#include "chrome/browser/ui/browser_tabstrip.h" +#include "chrome/common/chrome_paths.h" +#include "content/public/browser/browser_thread.h" +#include "content/public/browser/web_contents.h" +#include "content/public/common/url_constants.h" +#include "grit/devtools_discovery_page_resources.h" +#include "net/url_request/url_request_context_getter.h" +#include "ui/base/resource/resource_bundle.h" + +using content::DevToolsHttpHandlerDelegate; +using content::RenderViewHost; + +BrowserListTabContentsProvider::BrowserListTabContentsProvider( + Profile* profile) + : profile_(profile) { +} + +BrowserListTabContentsProvider::~BrowserListTabContentsProvider() { +} + +std::string BrowserListTabContentsProvider::GetDiscoveryPageHTML() { + std::set profiles; + for (BrowserList::const_iterator it = BrowserList::begin(), + end = BrowserList::end(); it != end; ++it) { + profiles.insert((*it)->profile()); + } + for (std::set::iterator it = profiles.begin(); + it != profiles.end(); ++it) { + history::TopSites* ts = (*it)->GetTopSites(); + if (ts) { + // TopSites updates itself after a delay. Ask TopSites to update itself + // when we're about to show the remote debugging landing page. + ts->SyncWithHistory(); + } + } + return ResourceBundle::GetSharedInstance().GetRawDataResource( + IDR_DEVTOOLS_DISCOVERY_PAGE_HTML).as_string(); +} + +bool BrowserListTabContentsProvider::BundlesFrontendResources() { + return true; +} + +FilePath BrowserListTabContentsProvider::GetDebugFrontendDir() { +#if defined(DEBUG_DEVTOOLS) + FilePath inspector_dir; + PathService::Get(chrome::DIR_INSPECTOR, &inspector_dir); + return inspector_dir; +#else + return FilePath(); +#endif +} + +std::string BrowserListTabContentsProvider::GetPageThumbnailData( + const GURL& url) { + for (BrowserList::const_iterator it = BrowserList::begin(), + end = BrowserList::end(); it != end; ++it) { + Profile* profile = (*it)->profile(); + history::TopSites* top_sites = profile->GetTopSites(); + if (!top_sites) + continue; + scoped_refptr data; + if (top_sites->GetPageThumbnail(url, &data)) + return std::string( + reinterpret_cast(data->front()), data->size()); + } + + return std::string(); +} + +RenderViewHost* BrowserListTabContentsProvider::CreateNewTarget() { + if (BrowserList::empty()) + chrome::NewEmptyWindow(profile_); + + if (BrowserList::empty()) + return NULL; + + content::WebContents* web_contents = chrome::AddSelectedTabWithURL( + *BrowserList::begin(), + GURL(chrome::kAboutBlankURL), + content::PAGE_TRANSITION_LINK); + return web_contents->GetRenderViewHost(); +} diff --git a/chrome/browser/devtools/browser_list_tabcontents_provider.h b/chrome/browser/devtools/browser_list_tabcontents_provider.h new file mode 100644 index 0000000..a09af44 --- /dev/null +++ b/chrome/browser/devtools/browser_list_tabcontents_provider.h @@ -0,0 +1,35 @@ +// Copyright (c) 2012 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_BROWSER_LIST_TABCONTENTS_PROVIDER_H_ +#define CHROME_BROWSER_DEVTOOLS_BROWSER_LIST_TABCONTENTS_PROVIDER_H_ + +#include +#include + +#include "base/basictypes.h" +#include "base/compiler_specific.h" +#include "content/public/browser/devtools_http_handler_delegate.h" + +class Profile; + +class BrowserListTabContentsProvider + : public content::DevToolsHttpHandlerDelegate { + public: + explicit BrowserListTabContentsProvider(Profile* profile); + virtual ~BrowserListTabContentsProvider(); + + // DevToolsHttpProtocolHandler::Delegate overrides. + virtual std::string GetDiscoveryPageHTML() OVERRIDE; + virtual bool BundlesFrontendResources() OVERRIDE; + virtual FilePath GetDebugFrontendDir() OVERRIDE; + virtual std::string GetPageThumbnailData(const GURL& url) OVERRIDE; + virtual content::RenderViewHost* CreateNewTarget() OVERRIDE; + + private: + Profile* profile_; + DISALLOW_COPY_AND_ASSIGN(BrowserListTabContentsProvider); +}; + +#endif // CHROME_BROWSER_DEVTOOLS_BROWSER_LIST_TABCONTENTS_PROVIDER_H_ diff --git a/chrome/browser/devtools/devtools_file_helper.cc b/chrome/browser/devtools/devtools_file_helper.cc new file mode 100644 index 0000000..6eab113 --- /dev/null +++ b/chrome/browser/devtools/devtools_file_helper.cc @@ -0,0 +1,199 @@ +// Copyright (c) 2012 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_file_helper.h" + +#include + +#include "base/bind.h" +#include "base/callback.h" +#include "base/file_util.h" +#include "base/lazy_instance.h" +#include "base/md5.h" +#include "base/value_conversions.h" +#include "chrome/browser/browser_process.h" +#include "chrome/browser/download/download_prefs.h" +#include "chrome/browser/prefs/pref_service.h" +#include "chrome/browser/prefs/scoped_user_pref_update.h" +#include "chrome/browser/profiles/profile.h" +#include "chrome/browser/ui/chrome_select_file_policy.h" +#include "chrome/common/pref_names.h" +#include "content/public/browser/browser_context.h" +#include "content/public/browser/download_manager.h" +#include "ui/base/dialogs/select_file_dialog.h" + +using content::BrowserContext; +using content::BrowserThread; +using content::DownloadManager; + +namespace { + +base::LazyInstance::Leaky + g_last_save_path = LAZY_INSTANCE_INITIALIZER; + +} // namespace + +class DevToolsFileHelper::SaveAsDialog : public ui::SelectFileDialog::Listener, + public base::RefCounted { + public: + explicit SaveAsDialog(DevToolsFileHelper* helper) + : helper_(helper) { + select_file_dialog_ = ui::SelectFileDialog::Create( + this, new ChromeSelectFilePolicy(NULL)); + } + + void ResetHelper() { + helper_ = NULL; + } + + void Show(const std::string& url, + const FilePath& initial_path, + const std::string& content) { + AddRef(); // Balanced in the three listener outcomes. + + url_ = url; + content_ = content; + + select_file_dialog_->SelectFile(ui::SelectFileDialog::SELECT_SAVEAS_FILE, + string16(), + initial_path, + NULL, + 0, + FILE_PATH_LITERAL(""), + NULL, + NULL); + } + + // ui::SelectFileDialog::Listener implementation. + virtual void FileSelected(const FilePath& path, + int index, void* params) { + if (helper_) + helper_->FileSelected(url_, path, content_); + Release(); // Balanced in ::Show. + } + + virtual void MultiFilesSelected( + const std::vector& files, void* params) { + Release(); // Balanced in ::Show. + NOTREACHED() << "Should not be able to select multiple files"; + } + + virtual void FileSelectionCanceled(void* params) { + Release(); // Balanced in ::Show. + } + + private: + friend class base::RefCounted; + virtual ~SaveAsDialog() {} + + scoped_refptr select_file_dialog_; + std::string url_; + std::string content_; + DevToolsFileHelper* helper_; +}; + +// static +void DevToolsFileHelper::WriteFile(const FilePath& path, + const std::string& content) { + DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE)); + DCHECK(!path.empty()); + + file_util::WriteFile(path, content.c_str(), content.length()); +} + +// static +void DevToolsFileHelper::AppendToFile(const FilePath& path, + const std::string& content) { + DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE)); + DCHECK(!path.empty()); + + file_util::AppendToFile(path, content.c_str(), content.length()); +} + +DevToolsFileHelper::DevToolsFileHelper(Profile* profile, Delegate* delegate) + : profile_(profile), + delegate_(delegate) { +} + +DevToolsFileHelper::~DevToolsFileHelper() { + if (save_as_dialog_) + save_as_dialog_->ResetHelper(); +} + +void DevToolsFileHelper::Save(const std::string& url, + const std::string& content, + bool save_as) { + PathsMap::iterator it = saved_files_.find(url); + if (it != saved_files_.end() && !save_as) { + FileSelected(url, it->second, content); + return; + } + + if (save_as_dialog_) + save_as_dialog_->ResetHelper(); + + const DictionaryValue* file_map = + profile_->GetPrefs()->GetDictionary(prefs::kDevToolsEditedFiles); + FilePath initial_path; + + const Value* path_value; + if (file_map->Get(base::MD5String(url), &path_value)) + base::GetValueAsFilePath(*path_value, &initial_path); + + if (initial_path.empty()) { + GURL gurl(url); + std::string suggested_file_name = gurl.is_valid() ? + gurl.ExtractFileName() : url; + + if (suggested_file_name.length() > 64) + suggested_file_name = suggested_file_name.substr(0, 64); + + if (!g_last_save_path.Pointer()->empty()) { + initial_path = g_last_save_path.Pointer()->DirName().AppendASCII( + suggested_file_name); + } else { + FilePath download_path = DownloadPrefs::FromDownloadManager( + BrowserContext::GetDownloadManager(profile_))->DownloadPath(); + initial_path = download_path.AppendASCII(suggested_file_name); + } + } + + save_as_dialog_ = new SaveAsDialog(this); + save_as_dialog_->Show(url, initial_path, content); +} + +void DevToolsFileHelper::Append(const std::string& url, + const std::string& content) { + PathsMap::iterator it = saved_files_.find(url); + if (it == saved_files_.end()) + return; + + delegate_->AppendedTo(url); + + BrowserThread::PostTask( + BrowserThread::FILE, FROM_HERE, + base::Bind(&DevToolsFileHelper::AppendToFile, + it->second, + content)); +} + +void DevToolsFileHelper::FileSelected(const std::string& url, + const FilePath& path, + const std::string& content) { + *g_last_save_path.Pointer() = path; + saved_files_[url] = path; + + DictionaryPrefUpdate update(profile_->GetPrefs(), + prefs::kDevToolsEditedFiles); + DictionaryValue* files_map = update.Get(); + files_map->SetWithoutPathExpansion(base::MD5String(url), + base::CreateFilePathValue(path)); + delegate_->FileSavedAs(url); + + BrowserThread::PostTask( + BrowserThread::FILE, FROM_HERE, + base::Bind(&DevToolsFileHelper::WriteFile, + path, + content)); +} diff --git a/chrome/browser/devtools/devtools_file_helper.h b/chrome/browser/devtools/devtools_file_helper.h new file mode 100644 index 0000000..3c1e9dc --- /dev/null +++ b/chrome/browser/devtools/devtools_file_helper.h @@ -0,0 +1,60 @@ +// Copyright (c) 2012 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_FILE_HELPER_H_ +#define CHROME_BROWSER_DEVTOOLS_DEVTOOLS_FILE_HELPER_H_ + +#include +#include + +#include "base/basictypes.h" +#include "base/memory/ref_counted.h" + +class FilePath; +class Profile; + +class DevToolsFileHelper { + public: + class Delegate { + public: + virtual ~Delegate() {} + virtual void FileSavedAs(const std::string& url) = 0; + virtual void AppendedTo(const std::string& url) = 0; + }; + + DevToolsFileHelper(Profile* profile, Delegate* delegate); + ~DevToolsFileHelper(); + + // Saves |content| to the file and associates its path with given |url|. + // If client is calling this method with given |url| for the first time + // or |save_as| is true, confirmation dialog is shown to the user. + void Save(const std::string& url, + const std::string& content, + bool save_as); + + // Append |content| to the file that has been associated with given |url|. + // The |url| can be associated with a file via calling Save method. + // If the Save method has not been called for this |url|, then + // Append method does nothing. + void Append(const std::string& url, const std::string& content); + + void FileSelected(const std::string& url, + const FilePath& path, + const std::string& content); + + private: + static void WriteFile(const FilePath& path, const std::string& content); + static void AppendToFile(const FilePath& path, const std::string& content); + + class SaveAsDialog; + + Profile* profile_; + Delegate* delegate_; + scoped_refptr save_as_dialog_; + typedef std::map PathsMap; + PathsMap saved_files_; + DISALLOW_COPY_AND_ASSIGN(DevToolsFileHelper); +}; + +#endif // CHROME_BROWSER_DEVTOOLS_DEVTOOLS_FILE_HELPER_H_ diff --git a/chrome/browser/devtools/devtools_sanity_browsertest.cc b/chrome/browser/devtools/devtools_sanity_browsertest.cc new file mode 100644 index 0000000..73c6249 --- /dev/null +++ b/chrome/browser/devtools/devtools_sanity_browsertest.cc @@ -0,0 +1,600 @@ +// Copyright (c) 2012 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 "base/bind.h" +#include "base/cancelable_callback.h" +#include "base/command_line.h" +#include "base/compiler_specific.h" +#include "base/memory/ref_counted.h" +#include "base/path_service.h" +#include "base/stringprintf.h" +#include "base/test/test_timeouts.h" +#include "base/utf_string_conversions.h" +#include "chrome/browser/devtools/devtools_window.h" +#include "chrome/browser/extensions/extension_service.h" +#include "chrome/browser/extensions/extension_system.h" +#include "chrome/browser/extensions/unpacked_installer.h" +#include "chrome/browser/profiles/profile.h" +#include "chrome/browser/ui/browser.h" +#include "chrome/browser/ui/browser_commands.h" +#include "chrome/browser/ui/browser_tabstrip.h" +#include "chrome/browser/ui/tabs/tab_strip_model.h" +#include "chrome/common/chrome_notification_types.h" +#include "chrome/common/chrome_paths.h" +#include "chrome/common/chrome_switches.h" +#include "chrome/test/base/in_process_browser_test.h" +#include "chrome/test/base/ui_test_utils.h" +#include "content/public/browser/child_process_data.h" +#include "content/public/browser/content_browser_client.h" +#include "content/public/browser/devtools_agent_host_registry.h" +#include "content/public/browser/devtools_client_host.h" +#include "content/public/browser/devtools_manager.h" +#include "content/public/browser/notification_registrar.h" +#include "content/public/browser/notification_service.h" +#include "content/public/browser/render_view_host.h" +#include "content/public/browser/web_contents.h" +#include "content/public/browser/worker_service.h" +#include "content/public/browser/worker_service_observer.h" +#include "content/public/test/browser_test_utils.h" +#include "net/test/test_server.h" + +using content::BrowserThread; +using content::DevToolsManager; +using content::DevToolsAgentHost; +using content::DevToolsAgentHostRegistry; +using content::NavigationController; +using content::RenderViewHost; +using content::WebContents; +using content::WorkerService; +using content::WorkerServiceObserver; + +namespace { + +// Used to block until a dev tools client window's browser is closed. +class BrowserClosedObserver : public content::NotificationObserver { + public: + explicit BrowserClosedObserver(Browser* browser) { + registrar_.Add(this, chrome::NOTIFICATION_BROWSER_CLOSED, + content::Source(browser)); + content::RunMessageLoop(); + } + + virtual void Observe(int type, + const content::NotificationSource& source, + const content::NotificationDetails& details) { + MessageLoopForUI::current()->Quit(); + } + + private: + content::NotificationRegistrar registrar_; + DISALLOW_COPY_AND_ASSIGN(BrowserClosedObserver); +}; + +// The delay waited in some cases where we don't have a notifications for an +// action we take. +const int kActionDelayMs = 500; + +const char kDebuggerTestPage[] = "files/devtools/debugger_test_page.html"; +const char kPauseWhenLoadingDevTools[] = + "files/devtools/pause_when_loading_devtools.html"; +const char kPauseWhenScriptIsRunning[] = + "files/devtools/pause_when_script_is_running.html"; +const char kPageWithContentScript[] = + "files/devtools/page_with_content_script.html"; +const char kNavigateBackTestPage[] = + "files/devtools/navigate_back.html"; +const char kChunkedTestPage[] = "chunked"; +const char kSlowTestPage[] = + "chunked?waitBeforeHeaders=100&waitBetweenChunks=100&chunksNumber=2"; +const char kSharedWorkerTestPage[] = + "files/workers/workers_ui_shared_worker.html"; +const char kReloadSharedWorkerTestPage[] = + "files/workers/debug_shared_worker_initialization.html"; + +void RunTestFunction(DevToolsWindow* window, const char* test_name) { + std::string result; + + // At first check that JavaScript part of the front-end is loaded by + // checking that global variable uiTests exists(it's created after all js + // files have been loaded) and has runTest method. + ASSERT_TRUE( + content::ExecuteJavaScriptAndExtractString( + window->GetRenderViewHost(), + L"", + L"window.domAutomationController.send(" + L"'' + (window.uiTests && (typeof uiTests.runTest)));", + &result)); + + if (result == "function") { + ASSERT_TRUE( + content::ExecuteJavaScriptAndExtractString( + window->GetRenderViewHost(), + L"", + UTF8ToWide(base::StringPrintf("uiTests.runTest('%s')", + test_name)), + &result)); + EXPECT_EQ("[OK]", result); + } else { + FAIL() << "DevTools front-end is broken."; + } +} + +class DevToolsSanityTest : public InProcessBrowserTest { + public: + DevToolsSanityTest() + : window_(NULL), + inspected_rvh_(NULL) {} + + protected: + void RunTest(const std::string& test_name, const std::string& test_page) { + OpenDevToolsWindow(test_page); + RunTestFunction(window_, test_name.c_str()); + CloseDevToolsWindow(); + } + + void OpenDevToolsWindow(const std::string& test_page) { + ASSERT_TRUE(test_server()->Start()); + GURL url = test_server()->GetURL(test_page); + ui_test_utils::NavigateToURL(browser(), url); + + content::WindowedNotificationObserver observer( + content::NOTIFICATION_LOAD_STOP, + content::NotificationService::AllSources()); + inspected_rvh_ = GetInspectedTab()->GetRenderViewHost(); + window_ = DevToolsWindow::OpenDevToolsWindow(inspected_rvh_); + observer.Wait(); + } + + WebContents* GetInspectedTab() { + return chrome::GetWebContentsAt(browser(), 0); + } + + void CloseDevToolsWindow() { + DevToolsManager* devtools_manager = DevToolsManager::GetInstance(); + // UnregisterDevToolsClientHostFor may destroy window_ so store the browser + // first. + Browser* browser = window_->browser(); + DevToolsAgentHost* agent = DevToolsAgentHostRegistry::GetDevToolsAgentHost( + inspected_rvh_); + devtools_manager->UnregisterDevToolsClientHostFor(agent); + + // Wait only when DevToolsWindow has a browser. For docked DevTools, this + // is NULL and we skip the wait. + if (browser) + BrowserClosedObserver close_observer(browser); + } + + DevToolsWindow* window_; + RenderViewHost* inspected_rvh_; +}; + +void TimeoutCallback(const std::string& timeout_message) { + FAIL() << timeout_message; + MessageLoop::current()->Quit(); +} + +// Base class for DevTools tests that test devtools functionality for +// extensions and content scripts. +class DevToolsExtensionTest : public DevToolsSanityTest, + public content::NotificationObserver { + public: + DevToolsExtensionTest() : DevToolsSanityTest() { + PathService::Get(chrome::DIR_TEST_DATA, &test_extensions_dir_); + test_extensions_dir_ = test_extensions_dir_.AppendASCII("devtools"); + test_extensions_dir_ = test_extensions_dir_.AppendASCII("extensions"); + } + + protected: + // Load an extension from test\data\devtools\extensions\ + void LoadExtension(const char* extension_name) { + FilePath path = test_extensions_dir_.AppendASCII(extension_name); + ASSERT_TRUE(LoadExtensionFromPath(path)) << "Failed to load extension."; + } + + private: + bool LoadExtensionFromPath(const FilePath& path) { + ExtensionService* service = extensions::ExtensionSystem::Get( + browser()->profile())->extension_service(); + size_t num_before = service->extensions()->size(); + { + content::NotificationRegistrar registrar; + registrar.Add(this, chrome::NOTIFICATION_EXTENSION_LOADED, + content::NotificationService::AllSources()); + base::CancelableClosure timeout( + base::Bind(&TimeoutCallback, "Extension load timed out.")); + MessageLoop::current()->PostDelayedTask( + FROM_HERE, timeout.callback(), base::TimeDelta::FromSeconds(4)); + extensions::UnpackedInstaller::Create(service)->Load(path); + content::RunMessageLoop(); + timeout.Cancel(); + } + size_t num_after = service->extensions()->size(); + if (num_after != (num_before + 1)) + return false; + + return WaitForExtensionViewsToLoad(); + } + + bool WaitForExtensionViewsToLoad() { + // Wait for all the extension render views that exist to finish loading. + // NOTE: This assumes that the extension views list is not changing while + // this method is running. + + content::NotificationRegistrar registrar; + registrar.Add(this, chrome::NOTIFICATION_EXTENSION_HOST_DID_STOP_LOADING, + content::NotificationService::AllSources()); + base::CancelableClosure timeout( + base::Bind(&TimeoutCallback, "Extension host load timed out.")); + MessageLoop::current()->PostDelayedTask( + FROM_HERE, timeout.callback(), base::TimeDelta::FromSeconds(4)); + + ExtensionProcessManager* manager = + extensions::ExtensionSystem::Get(browser()->profile())-> + process_manager(); + ExtensionProcessManager::ViewSet all_views = manager->GetAllViews(); + for (ExtensionProcessManager::ViewSet::const_iterator iter = + all_views.begin(); + iter != all_views.end();) { + if (!(*iter)->IsLoading()) + ++iter; + else + content::RunMessageLoop(); + } + + timeout.Cancel(); + return true; + } + + void Observe(int type, + const content::NotificationSource& source, + const content::NotificationDetails& details) { + switch (type) { + case chrome::NOTIFICATION_EXTENSION_LOADED: + case chrome::NOTIFICATION_EXTENSION_HOST_DID_STOP_LOADING: + MessageLoopForUI::current()->Quit(); + break; + default: + NOTREACHED(); + break; + } + } + + FilePath test_extensions_dir_; +}; + +class DevToolsExperimentalExtensionTest : public DevToolsExtensionTest { + public: + void SetUpCommandLine(CommandLine* command_line) OVERRIDE { + command_line->AppendSwitch(switches::kEnableExperimentalExtensionApis); + } +}; + +class WorkerDevToolsSanityTest : public InProcessBrowserTest { + public: + WorkerDevToolsSanityTest() : window_(NULL) {} + + protected: + class WorkerData : public base::RefCountedThreadSafe { + public: + WorkerData() : worker_process_id(0), worker_route_id(0) {} + int worker_process_id; + int worker_route_id; + + private: + friend class base::RefCountedThreadSafe; + ~WorkerData() {} + }; + + class WorkerCreationObserver : public WorkerServiceObserver { + public: + explicit WorkerCreationObserver(WorkerData* worker_data) + : worker_data_(worker_data) { + } + + private: + virtual ~WorkerCreationObserver() {} + + virtual void WorkerCreated ( + const GURL& url, + const string16& name, + int process_id, + int route_id) OVERRIDE { + worker_data_->worker_process_id = process_id; + worker_data_->worker_route_id = route_id; + WorkerService::GetInstance()->RemoveObserver(this); + BrowserThread::PostTask(BrowserThread::UI, FROM_HERE, + MessageLoop::QuitClosure()); + delete this; + } + scoped_refptr worker_data_; + }; + + class WorkerTerminationObserver : public WorkerServiceObserver { + public: + explicit WorkerTerminationObserver(WorkerData* worker_data) + : worker_data_(worker_data) { + } + + private: + virtual ~WorkerTerminationObserver() {} + + virtual void WorkerDestroyed(int process_id, int route_id) OVERRIDE { + ASSERT_EQ(worker_data_->worker_process_id, process_id); + ASSERT_EQ(worker_data_->worker_route_id, route_id); + WorkerService::GetInstance()->RemoveObserver(this); + BrowserThread::PostTask(BrowserThread::UI, FROM_HERE, + MessageLoop::QuitClosure()); + delete this; + } + scoped_refptr worker_data_; + }; + + void RunTest(const char* test_name, const char* test_page) { + ASSERT_TRUE(test_server()->Start()); + GURL url = test_server()->GetURL(test_page); + ui_test_utils::NavigateToURL(browser(), url); + + scoped_refptr worker_data = WaitForFirstSharedWorker(); + OpenDevToolsWindowForSharedWorker(worker_data.get()); + RunTestFunction(window_, test_name); + CloseDevToolsWindow(); + } + + static void TerminateWorkerOnIOThread(scoped_refptr worker_data) { + if (WorkerService::GetInstance()->TerminateWorker( + worker_data->worker_process_id, worker_data->worker_route_id)) { + WorkerService::GetInstance()->AddObserver( + new WorkerTerminationObserver(worker_data)); + return; + } + FAIL() << "Failed to terminate worker.\n"; + } + + static void TerminateWorker(scoped_refptr worker_data) { + BrowserThread::PostTask( + BrowserThread::IO, FROM_HERE, + base::Bind(&TerminateWorkerOnIOThread, worker_data)); + content::RunMessageLoop(); + } + + static void WaitForFirstSharedWorkerOnIOThread( + scoped_refptr worker_data) { + std::vector worker_info = + WorkerService::GetInstance()->GetWorkers(); + if (!worker_info.empty()) { + worker_data->worker_process_id = worker_info[0].process_id; + worker_data->worker_route_id = worker_info[0].route_id; + BrowserThread::PostTask(BrowserThread::UI, FROM_HERE, + MessageLoop::QuitClosure()); + return; + } + + WorkerService::GetInstance()->AddObserver( + new WorkerCreationObserver(worker_data.get())); + } + + static scoped_refptr WaitForFirstSharedWorker() { + scoped_refptr worker_data(new WorkerData()); + BrowserThread::PostTask( + BrowserThread::IO, FROM_HERE, + base::Bind(&WaitForFirstSharedWorkerOnIOThread, worker_data)); + content::RunMessageLoop(); + return worker_data; + } + + void OpenDevToolsWindowForSharedWorker(WorkerData* worker_data) { + Profile* profile = browser()->profile(); + window_ = DevToolsWindow::CreateDevToolsWindowForWorker(profile); + window_->Show(DEVTOOLS_TOGGLE_ACTION_SHOW); + DevToolsAgentHost* agent_host = + DevToolsAgentHostRegistry::GetDevToolsAgentHostForWorker( + worker_data->worker_process_id, + worker_data->worker_route_id); + DevToolsManager::GetInstance()->RegisterDevToolsClientHostFor( + agent_host, + window_->devtools_client_host()); + RenderViewHost* client_rvh = window_->GetRenderViewHost(); + WebContents* client_contents = WebContents::FromRenderViewHost(client_rvh); + if (client_contents->IsLoading()) { + content::WindowedNotificationObserver observer( + content::NOTIFICATION_LOAD_STOP, + content::Source( + &client_contents->GetController())); + observer.Wait(); + } + } + + void CloseDevToolsWindow() { + Browser* browser = window_->browser(); + browser->tab_strip_model()->CloseAllTabs(); + BrowserClosedObserver close_observer(browser); + } + + DevToolsWindow* window_; +}; + + +// Tests scripts panel showing. +IN_PROC_BROWSER_TEST_F(DevToolsSanityTest, TestShowScriptsTab) { + RunTest("testShowScriptsTab", kDebuggerTestPage); +} + +// Tests that scripts tab is populated with inspected scripts even if it +// hadn't been shown by the moment inspected paged refreshed. +// @see http://crbug.com/26312 +IN_PROC_BROWSER_TEST_F( + DevToolsSanityTest, + TestScriptsTabIsPopulatedOnInspectedPageRefresh) { + // Clear inspector settings to ensure that Elements will be + // current panel when DevTools window is open. + content::GetContentClient()->browser()->ClearInspectorSettings( + GetInspectedTab()->GetRenderViewHost()); + RunTest("testScriptsTabIsPopulatedOnInspectedPageRefresh", + kDebuggerTestPage); +} + +// Tests that chrome.devtools extension is correctly exposed. +IN_PROC_BROWSER_TEST_F(DevToolsExtensionTest, + TestDevToolsExtensionAPI) { + LoadExtension("devtools_extension"); + RunTest("waitForTestResultsInConsole", ""); +} + +// Tests that chrome.devtools extension can communicate with background page +// using extension messaging. +IN_PROC_BROWSER_TEST_F(DevToolsExtensionTest, + TestDevToolsExtensionMessaging) { + LoadExtension("devtools_messaging"); + RunTest("waitForTestResultsInConsole", ""); +} + +// Tests that chrome.experimental.devtools extension is correctly exposed +// when the extension has experimental permission. +IN_PROC_BROWSER_TEST_F(DevToolsExperimentalExtensionTest, + TestDevToolsExperimentalExtensionAPI) { + LoadExtension("devtools_experimental"); + RunTest("waitForTestResultsInConsole", ""); +} + +// Tests that a content script is in the scripts list. +// http://crbug.com/114104 +IN_PROC_BROWSER_TEST_F(DevToolsExtensionTest, + TestContentScriptIsPresent) { + LoadExtension("simple_content_script"); + RunTest("testContentScriptIsPresent", kPageWithContentScript); +} + +// Tests that scripts are not duplicated after Scripts Panel switch. +// Disabled - see http://crbug.com/124300 +IN_PROC_BROWSER_TEST_F(DevToolsSanityTest, + TestNoScriptDuplicatesOnPanelSwitch) { + RunTest("testNoScriptDuplicatesOnPanelSwitch", kDebuggerTestPage); +} + +// Tests that debugger works correctly if pause event occurs when DevTools +// frontend is being loaded. +// http://crbug.com/106114 +IN_PROC_BROWSER_TEST_F(DevToolsSanityTest, + TestPauseWhenLoadingDevTools) { + RunTest("testPauseWhenLoadingDevTools", kPauseWhenLoadingDevTools); +} + +// Tests that pressing 'Pause' will pause script execution if the script +// is already running. +IN_PROC_BROWSER_TEST_F(DevToolsSanityTest, TestPauseWhenScriptIsRunning) { + RunTest("testPauseWhenScriptIsRunning", kPauseWhenScriptIsRunning); +} + +// Tests network timing. +IN_PROC_BROWSER_TEST_F(DevToolsSanityTest, TestNetworkTiming) { + RunTest("testNetworkTiming", kSlowTestPage); +} + +// Tests network size. +IN_PROC_BROWSER_TEST_F(DevToolsSanityTest, TestNetworkSize) { + RunTest("testNetworkSize", kChunkedTestPage); +} + +// Tests raw headers text. +IN_PROC_BROWSER_TEST_F(DevToolsSanityTest, TestNetworkSyncSize) { + RunTest("testNetworkSyncSize", kChunkedTestPage); +} + +// Tests raw headers text. +IN_PROC_BROWSER_TEST_F(DevToolsSanityTest, TestNetworkRawHeadersText) { + RunTest("testNetworkRawHeadersText", kChunkedTestPage); +} + +// Tests that console messages are not duplicated on navigation back. +IN_PROC_BROWSER_TEST_F(DevToolsSanityTest, TestConsoleOnNavigateBack) { + RunTest("testConsoleOnNavigateBack", kNavigateBackTestPage); +} + +// Tests that inspector will reattach to inspected page when it is reloaded +// after a crash. See http://crbug.com/101952 +IN_PROC_BROWSER_TEST_F(DevToolsSanityTest, TestReattachAfterCrash) { + OpenDevToolsWindow(kDebuggerTestPage); + + content::CrashTab(GetInspectedTab()); + content::WindowedNotificationObserver observer( + content::NOTIFICATION_LOAD_STOP, + content::Source( + &chrome::GetActiveWebContents(browser())->GetController())); + chrome::Reload(browser(), CURRENT_TAB); + observer.Wait(); + + RunTestFunction(window_, "testReattachAfterCrash"); + CloseDevToolsWindow(); +} + +IN_PROC_BROWSER_TEST_F(DevToolsSanityTest, TestPageWithNoJavaScript) { + OpenDevToolsWindow("about:blank"); + std::string result; + ASSERT_TRUE( + content::ExecuteJavaScriptAndExtractString( + window_->GetRenderViewHost(), + L"", + L"window.domAutomationController.send(" + L"'' + (window.uiTests && (typeof uiTests.runTest)));", + &result)); + ASSERT_EQ("function", result) << "DevTools front-end is broken."; + CloseDevToolsWindow(); +} + +#if defined(OS_MACOSX) +#define MAYBE_InspectSharedWorker DISABLED_InspectSharedWorker +#else +#define MAYBE_InspectSharedWorker InspectSharedWorker +#endif +// Flakily fails with 25s timeout: http://crbug.com/89845 +IN_PROC_BROWSER_TEST_F(WorkerDevToolsSanityTest, MAYBE_InspectSharedWorker) { + RunTest("testSharedWorker", kSharedWorkerTestPage); +} + +// http://crbug.com/100538 +#if defined(OS_MACOSX) || defined(OS_WIN) +#define MAYBE_PauseInSharedWorkerInitialization DISABLED_PauseInSharedWorkerInitialization +#else +#define MAYBE_PauseInSharedWorkerInitialization PauseInSharedWorkerInitialization +#endif + +// http://crbug.com/106114 is masking +// MAYBE_PauseInSharedWorkerInitialization into +// DISABLED_PauseInSharedWorkerInitialization +IN_PROC_BROWSER_TEST_F(WorkerDevToolsSanityTest, + MAYBE_PauseInSharedWorkerInitialization) { + ASSERT_TRUE(test_server()->Start()); + GURL url = test_server()->GetURL(kReloadSharedWorkerTestPage); + ui_test_utils::NavigateToURL(browser(), url); + + scoped_refptr worker_data = WaitForFirstSharedWorker(); + OpenDevToolsWindowForSharedWorker(worker_data.get()); + + TerminateWorker(worker_data); + + // Reload page to restart the worker. + ui_test_utils::NavigateToURL(browser(), url); + + // Wait until worker script is paused on the debugger statement. + RunTestFunction(window_, "testPauseInSharedWorkerInitialization"); + CloseDevToolsWindow(); +} + +// Tests DevToolsAgentHost::AddMessageToConsole. +IN_PROC_BROWSER_TEST_F(DevToolsSanityTest, TestAddMessageToConsole) { + OpenDevToolsWindow("about:blank"); + DevToolsManager* devtools_manager = DevToolsManager::GetInstance(); + DevToolsAgentHost* agent_host = + DevToolsAgentHostRegistry::GetDevToolsAgentHost(inspected_rvh_); + devtools_manager->AddMessageToConsole(agent_host, + content::CONSOLE_MESSAGE_LEVEL_LOG, + "log"); + devtools_manager->AddMessageToConsole(agent_host, + content::CONSOLE_MESSAGE_LEVEL_ERROR, + "error"); + RunTestFunction(window_, "checkLogAndErrorMessages"); + CloseDevToolsWindow(); +} + +} // namespace diff --git a/chrome/browser/devtools/devtools_toggle_action.h b/chrome/browser/devtools/devtools_toggle_action.h new file mode 100644 index 0000000..ff5c94c --- /dev/null +++ b/chrome/browser/devtools/devtools_toggle_action.h @@ -0,0 +1,15 @@ +// Copyright (c) 2011 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_TOGGLE_ACTION_H_ +#define CHROME_BROWSER_DEVTOOLS_DEVTOOLS_TOGGLE_ACTION_H_ + +enum DevToolsToggleAction { + DEVTOOLS_TOGGLE_ACTION_SHOW, + DEVTOOLS_TOGGLE_ACTION_SHOW_CONSOLE, + DEVTOOLS_TOGGLE_ACTION_INSPECT, + DEVTOOLS_TOGGLE_ACTION_TOGGLE +}; + +#endif // CHROME_BROWSER_DEVTOOLS_DEVTOOLS_TOGGLE_ACTION_H_ diff --git a/chrome/browser/devtools/devtools_window.cc b/chrome/browser/devtools/devtools_window.cc new file mode 100644 index 0000000..18d33ad --- /dev/null +++ b/chrome/browser/devtools/devtools_window.cc @@ -0,0 +1,914 @@ +// Copyright (c) 2012 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 + +#include "base/command_line.h" +#include "base/json/json_writer.h" +#include "base/lazy_instance.h" +#include "base/string_number_conversions.h" +#include "base/stringprintf.h" +#include "base/utf_string_conversions.h" +#include "base/values.h" +#include "chrome/browser/browser_process.h" +#include "chrome/browser/devtools/devtools_window.h" +#include "chrome/browser/extensions/api/debugger/debugger_api.h" +#include "chrome/browser/extensions/extension_service.h" +#include "chrome/browser/extensions/extension_system.h" +#include "chrome/browser/file_select_helper.h" +#include "chrome/browser/prefs/pref_service.h" +#include "chrome/browser/prefs/scoped_user_pref_update.h" +#include "chrome/browser/profiles/profile.h" +#include "chrome/browser/sessions/session_tab_helper.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_list.h" +#include "chrome/browser/ui/browser_list_impl.h" +#include "chrome/browser/ui/browser_window.h" +#include "chrome/browser/ui/tabs/tab_strip_model.h" +#include "chrome/common/chrome_notification_types.h" +#include "chrome/common/chrome_switches.h" +#include "chrome/common/pref_names.h" +#include "chrome/common/render_messages.h" +#include "chrome/common/url_constants.h" +#include "content/public/browser/content_browser_client.h" +#include "content/public/browser/devtools_agent_host_registry.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/navigation_controller.h" +#include "content/public/browser/navigation_entry.h" +#include "content/public/browser/notification_source.h" +#include "content/public/browser/render_process_host.h" +#include "content/public/browser/render_view_host.h" +#include "content/public/browser/web_contents.h" +#include "content/public/browser/web_contents_view.h" +#include "content/public/common/bindings_policy.h" +#include "content/public/common/page_transition_types.h" +#include "grit/generated_resources.h" + +typedef std::vector DevToolsWindowList; +namespace { +base::LazyInstance::Leaky + g_instances = LAZY_INSTANCE_INITIALIZER; +} // namespace + +using content::DevToolsAgentHost; +using content::DevToolsAgentHostRegistry; +using content::DevToolsClientHost; +using content::DevToolsManager; +using content::FileChooserParams; +using content::NativeWebKeyboardEvent; +using content::NavigationController; +using content::NavigationEntry; +using content::OpenURLParams; +using content::RenderViewHost; +using content::WebContents; + +const char DevToolsWindow::kDevToolsApp[] = "DevToolsApp"; + +const char kOldPrefBottom[] = "bottom"; +const char kOldPrefRight[] = "right"; + +const char kPrefBottom[] = "dock_bottom"; +const char kPrefRight[] = "dock_right"; +const char kPrefUndocked[] = "undocked"; + +const char kDockSideBottom[] = "bottom"; +const char kDockSideRight[] = "right"; +const char kDockSideUndocked[] = "undocked"; + +// Minimal height of devtools pane or content pane when devtools are docked +// to the browser window. +const int kMinDevToolsHeight = 50; +const int kMinDevToolsWidth = 150; +const int kMinContentsSize = 50; + +// static +void DevToolsWindow::RegisterUserPrefs(PrefService* prefs) { + prefs->RegisterBooleanPref(prefs::kDevToolsOpenDocked, + true, + PrefService::UNSYNCABLE_PREF); + prefs->RegisterStringPref(prefs::kDevToolsDockSide, + kDockSideBottom, + PrefService::UNSYNCABLE_PREF); + prefs->RegisterDictionaryPref(prefs::kDevToolsEditedFiles, + PrefService::UNSYNCABLE_PREF); +} + +// static +DevToolsWindow* DevToolsWindow::GetDockedInstanceForInspectedTab( + WebContents* inspected_web_contents) { + if (!inspected_web_contents) + return NULL; + + if (!DevToolsAgentHostRegistry::HasDevToolsAgentHost( + inspected_web_contents->GetRenderViewHost())) + return NULL; + DevToolsAgentHost* agent = DevToolsAgentHostRegistry::GetDevToolsAgentHost( + inspected_web_contents->GetRenderViewHost()); + DevToolsManager* manager = DevToolsManager::GetInstance(); + DevToolsClientHost* client_host = manager->GetDevToolsClientHostFor(agent); + DevToolsWindow* window = AsDevToolsWindow(client_host); + return window && window->IsDocked() ? window : NULL; +} + +// static +bool DevToolsWindow::IsDevToolsWindow(RenderViewHost* window_rvh) { + return AsDevToolsWindow(window_rvh) != NULL; +} + +// static +DevToolsWindow* DevToolsWindow::OpenDevToolsWindowForWorker( + Profile* profile, + DevToolsAgentHost* worker_agent) { + DevToolsWindow* window; + DevToolsClientHost* client = content::DevToolsManager::GetInstance()-> + GetDevToolsClientHostFor(worker_agent); + if (client) { + window = AsDevToolsWindow(client); + if (!window) + return NULL; + } else { + window = DevToolsWindow::CreateDevToolsWindowForWorker(profile); + DevToolsManager::GetInstance()->RegisterDevToolsClientHostFor( + worker_agent, + window->frontend_host_); + } + window->Show(DEVTOOLS_TOGGLE_ACTION_SHOW); + return window; +} + +// static +DevToolsWindow* DevToolsWindow::CreateDevToolsWindowForWorker( + Profile* profile) { + return Create(profile, NULL, DEVTOOLS_DOCK_SIDE_UNDOCKED, true); +} + +// static +DevToolsWindow* DevToolsWindow::OpenDevToolsWindow( + RenderViewHost* inspected_rvh) { + return ToggleDevToolsWindow(inspected_rvh, true, + DEVTOOLS_TOGGLE_ACTION_SHOW); +} + +// static +DevToolsWindow* DevToolsWindow::ToggleDevToolsWindow( + Browser* browser, + DevToolsToggleAction action) { + if (action == DEVTOOLS_TOGGLE_ACTION_TOGGLE && browser->is_devtools()) { + browser->tab_strip_model()->CloseAllTabs(); + return NULL; + } + RenderViewHost* inspected_rvh = + browser->tab_strip_model()->GetActiveWebContents()->GetRenderViewHost(); + + return ToggleDevToolsWindow(inspected_rvh, + action == DEVTOOLS_TOGGLE_ACTION_INSPECT, + action); +} + +void DevToolsWindow::InspectElement(RenderViewHost* inspected_rvh, + int x, + int y) { + DevToolsAgentHost* agent = DevToolsAgentHostRegistry::GetDevToolsAgentHost( + inspected_rvh); + DevToolsManager::GetInstance()->InspectElement(agent, x, y); + // TODO(loislo): we should initiate DevTools window opening from within + // renderer. Otherwise, we still can hit a race condition here. + OpenDevToolsWindow(inspected_rvh); +} + + +DevToolsWindow* DevToolsWindow::Create( + Profile* profile, + RenderViewHost* inspected_rvh, + DevToolsDockSide dock_side, + bool shared_worker_frontend) { + // Create WebContents with devtools. + WebContents* web_contents = + WebContents::Create(WebContents::CreateParams(profile)); + web_contents->GetRenderViewHost()->AllowBindings( + content::BINDINGS_POLICY_WEB_UI); + web_contents->GetController().LoadURL( + GetDevToolsUrl(profile, dock_side, shared_worker_frontend), + content::Referrer(), + content::PAGE_TRANSITION_AUTO_TOPLEVEL, + std::string()); + return new DevToolsWindow(web_contents, profile, inspected_rvh, dock_side); +} + +DevToolsWindow::DevToolsWindow(WebContents* web_contents, + Profile* profile, + RenderViewHost* inspected_rvh, + DevToolsDockSide dock_side) + : profile_(profile), + inspected_web_contents_(NULL), + web_contents_(web_contents), + browser_(NULL), + dock_side_(dock_side), + is_loaded_(false), + action_on_load_(DEVTOOLS_TOGGLE_ACTION_SHOW), + width_(-1), + height_(-1) { + frontend_host_ = DevToolsClientHost::CreateDevToolsFrontendHost(web_contents, + this); + file_helper_.reset(new DevToolsFileHelper(profile, this)); + + g_instances.Get().push_back(this); + // Wipe out page icon so that the default application icon is used. + NavigationEntry* entry = web_contents->GetController().GetActiveEntry(); + entry->GetFavicon().image = gfx::Image(); + entry->GetFavicon().valid = true; + + // Register on-load actions. + registrar_.Add( + this, + content::NOTIFICATION_LOAD_STOP, + content::Source(&web_contents->GetController())); + registrar_.Add( + this, + chrome::NOTIFICATION_TAB_CLOSING, + content::Source(&web_contents->GetController())); + registrar_.Add( + this, + chrome::NOTIFICATION_BROWSER_THEME_CHANGED, + content::Source( + ThemeServiceFactory::GetForProfile(profile_))); + // There is no inspected_rvh in case of shared workers. + if (inspected_rvh) + inspected_web_contents_ = WebContents::FromRenderViewHost(inspected_rvh); +} + +DevToolsWindow::~DevToolsWindow() { + DevToolsWindowList& instances = g_instances.Get(); + DevToolsWindowList::iterator it = std::find(instances.begin(), + instances.end(), + this); + DCHECK(it != instances.end()); + instances.erase(it); +} + +void DevToolsWindow::InspectedContentsClosing() { + if (IsDocked()) { + // Update dev tools to reflect removed dev tools window. + BrowserWindow* inspected_window = GetInspectedBrowserWindow(); + if (inspected_window) + inspected_window->UpdateDevTools(); + // In case of docked web_contents_, we own it so delete here. + delete web_contents_; + + delete this; + } else { + // First, initiate self-destruct to free all the registrars. + // Then close all tabs. Browser will take care of deleting web_contents_ + // for us. + Browser* browser = browser_; + delete this; + browser->tab_strip_model()->CloseAllTabs(); + } +} + +void DevToolsWindow::ContentsReplaced(WebContents* new_contents) { + inspected_web_contents_ = new_contents; +} + +void DevToolsWindow::Show(DevToolsToggleAction action) { + if (IsDocked()) { + Browser* inspected_browser; + int inspected_tab_index; + // Tell inspected browser to update splitter and switch to inspected panel. + if (!IsInspectedBrowserPopupOrPanel() && + FindInspectedBrowserAndTabIndex(&inspected_browser, + &inspected_tab_index)) { + BrowserWindow* inspected_window = inspected_browser->window(); + web_contents_->SetDelegate(this); + inspected_window->UpdateDevTools(); + web_contents_->GetView()->SetInitialFocus(); + inspected_window->Show(); + TabStripModel* tab_strip_model = inspected_browser->tab_strip_model(); + tab_strip_model->ActivateTabAt(inspected_tab_index, true); + ScheduleAction(action); + return; + } else { + // Sometimes we don't know where to dock. Stay undocked. + dock_side_ = DEVTOOLS_DOCK_SIDE_UNDOCKED; + } + } + + // Avoid consecutive window switching if the devtools window has been opened + // and the Inspect Element shortcut is pressed in the inspected tab. + bool should_show_window = + !browser_ || action != DEVTOOLS_TOGGLE_ACTION_INSPECT; + + if (!browser_) + CreateDevToolsBrowser(); + + if (should_show_window) { + browser_->window()->Show(); + web_contents_->GetView()->SetInitialFocus(); + } + + ScheduleAction(action); +} + +int DevToolsWindow::GetWidth(int container_width) { + if (width_ == -1) { + width_ = profile_->GetPrefs()-> + GetInteger(prefs::kDevToolsVSplitLocation); + } + + // By default, size devtools as 1/3 of the browser window. + if (width_ == -1) + width_ = container_width / 3; + + // Respect the minimum devtools width preset. + width_ = std::max(kMinDevToolsWidth, width_); + + // But it should never compromise the content window size unless the entire + // window is tiny. + width_ = std::min(container_width - kMinContentsSize, width_); + if (width_ < (kMinContentsSize / 2)) + width_ = container_width / 3; + return width_; +} + +int DevToolsWindow::GetHeight(int container_height) { + if (height_ == -1) { + height_ = profile_->GetPrefs()-> + GetInteger(prefs::kDevToolsHSplitLocation); + } + + // By default, size devtools as 1/3 of the browser window. + if (height_ == -1) + height_ = container_height / 3; + + // Respect the minimum devtools width preset. + height_ = std::max(kMinDevToolsHeight, height_); + + // But it should never compromise the content window size. + height_ = std::min(container_height - kMinContentsSize, height_); + if (height_ < (kMinContentsSize / 2)) + height_ = container_height / 3; + return height_; +} + +void DevToolsWindow::SetWidth(int width) { + width_ = width; + profile_->GetPrefs()->SetInteger(prefs::kDevToolsVSplitLocation, width); +} + +void DevToolsWindow::SetHeight(int height) { + height_ = height; + profile_->GetPrefs()->SetInteger(prefs::kDevToolsHSplitLocation, height); +} + +RenderViewHost* DevToolsWindow::GetRenderViewHost() { + return web_contents_->GetRenderViewHost(); +} + +void DevToolsWindow::CreateDevToolsBrowser() { + // TODO(pfeldman): Make browser's getter for this key static. + std::string wp_key; + wp_key.append(prefs::kBrowserWindowPlacement); + wp_key.append("_"); + wp_key.append(kDevToolsApp); + + PrefService* prefs = profile_->GetPrefs(); + if (!prefs->FindPreference(wp_key.c_str())) { + prefs->RegisterDictionaryPref(wp_key.c_str(), PrefService::UNSYNCABLE_PREF); + } + + const DictionaryValue* wp_pref = prefs->GetDictionary(wp_key.c_str()); + if (!wp_pref || wp_pref->empty()) { + DictionaryPrefUpdate update(prefs, wp_key.c_str()); + DictionaryValue* defaults = update.Get(); + defaults->SetInteger("left", 100); + defaults->SetInteger("top", 100); + defaults->SetInteger("right", 740); + defaults->SetInteger("bottom", 740); + defaults->SetBoolean("maximized", false); + defaults->SetBoolean("always_on_top", false); + } + + browser_ = new Browser(Browser::CreateParams::CreateForDevTools(profile_)); + browser_->tab_strip_model()->AddWebContents( + web_contents_, -1, content::PAGE_TRANSITION_AUTO_TOPLEVEL, + TabStripModel::ADD_ACTIVE); +} + +bool DevToolsWindow::FindInspectedBrowserAndTabIndex(Browser** browser, + int* tab) { + if (!inspected_web_contents_) + return false; + + bool found = FindInspectedBrowserAndTabIndexFromBrowserList( + chrome::BrowserListImpl::GetInstance(chrome::HOST_DESKTOP_TYPE_NATIVE), + browser, + tab); + // On Windows 8 we can have the desktop environment and the ASH environment + // active concurrently. If we fail to find the inspected web contents in the + // native browser list, then we should look in the ASH browser list. +#if defined(OS_WIN) && defined(USE_AURA) + if (!found) { + found = FindInspectedBrowserAndTabIndexFromBrowserList( + chrome::BrowserListImpl::GetInstance(chrome::HOST_DESKTOP_TYPE_ASH), + browser, + tab); + } +#endif + return found; +} + +bool DevToolsWindow::FindInspectedBrowserAndTabIndexFromBrowserList( + chrome::BrowserListImpl* browser_list, + Browser** browser, + int* tab) { + if (!inspected_web_contents_) + return false; + + for (chrome::BrowserListImpl::const_iterator it = browser_list->begin(); + it != browser_list->end(); ++it) { + int tab_index = (*it)->tab_strip_model()->GetIndexOfWebContents( + inspected_web_contents_); + if (tab_index != TabStripModel::kNoTab) { + *browser = *it; + *tab = tab_index; + return true; + } + } + return false; +} + +BrowserWindow* DevToolsWindow::GetInspectedBrowserWindow() { + Browser* browser = NULL; + int tab; + return FindInspectedBrowserAndTabIndex(&browser, &tab) ? + browser->window() : NULL; +} + +bool DevToolsWindow::IsInspectedBrowserPopupOrPanel() { + Browser* browser = NULL; + int tab; + if (!FindInspectedBrowserAndTabIndex(&browser, &tab)) + return false; + + return browser->is_type_popup() || browser->is_type_panel(); +} + +void DevToolsWindow::UpdateFrontendDockSide() { + base::StringValue dock_side(SideToString(dock_side_)); + CallClientFunction("InspectorFrontendAPI.setDockSide", &dock_side); + base::FundamentalValue docked(IsDocked()); + CallClientFunction("InspectorFrontendAPI.setAttachedWindow", &docked); +} + + +void DevToolsWindow::AddDevToolsExtensionsToClient() { + if (inspected_web_contents_) { + SessionTabHelper* session_tab_helper = + SessionTabHelper::FromWebContents(inspected_web_contents_); + if (session_tab_helper) { + base::FundamentalValue tabId(session_tab_helper->session_id().id()); + CallClientFunction("WebInspector.setInspectedTabId", &tabId); + } + } + ListValue results; + Profile* profile = + Profile::FromBrowserContext(web_contents_->GetBrowserContext()); + const ExtensionService* extension_service = extensions::ExtensionSystem::Get( + profile->GetOriginalProfile())->extension_service(); + if (!extension_service) + return; + + const ExtensionSet* extensions = extension_service->extensions(); + + for (ExtensionSet::const_iterator extension = extensions->begin(); + extension != extensions->end(); ++extension) { + if ((*extension)->devtools_url().is_empty()) + continue; + DictionaryValue* extension_info = new DictionaryValue(); + extension_info->Set("startPage", + new StringValue((*extension)->devtools_url().spec())); + extension_info->Set("name", new StringValue((*extension)->name())); + bool allow_experimental = (*extension)->HasAPIPermission( + extensions::APIPermission::kExperimental); + extension_info->Set("exposeExperimentalAPIs", + new base::FundamentalValue(allow_experimental)); + results.Append(extension_info); + } + CallClientFunction("WebInspector.addExtensions", &results); +} + +WebContents* DevToolsWindow::OpenURLFromTab(WebContents* source, + const OpenURLParams& params) { + if (inspected_web_contents_) + return inspected_web_contents_->OpenURL(params); + return NULL; +} + +void DevToolsWindow::CallClientFunction(const std::string& function_name, + const Value* arg) { + std::string json; + if (arg) + base::JSONWriter::Write(arg, &json); + + string16 javascript = + ASCIIToUTF16(function_name + "(" + json + ");"); + web_contents_->GetRenderViewHost()-> + ExecuteJavascriptInWebFrame(string16(), javascript); +} + +void DevToolsWindow::Observe(int type, + const content::NotificationSource& source, + const content::NotificationDetails& details) { + if (type == content::NOTIFICATION_LOAD_STOP && !is_loaded_) { + is_loaded_ = true; + UpdateTheme(); + DoAction(); + AddDevToolsExtensionsToClient(); + } else if (type == chrome::NOTIFICATION_TAB_CLOSING) { + if (content::Source(source).ptr() == + &web_contents_->GetController()) { + // This happens when browser closes all of its tabs as a result + // of window.Close event. + // Notify manager that this DevToolsClientHost no longer exists and + // initiate self-destuct here. + DevToolsManager::GetInstance()->ClientHostClosing(frontend_host_); + UpdateBrowserToolbar(); + delete this; + } + } else if (type == chrome::NOTIFICATION_BROWSER_THEME_CHANGED) { + UpdateTheme(); + } +} + +void DevToolsWindow::ScheduleAction(DevToolsToggleAction action) { + action_on_load_ = action; + if (is_loaded_) + DoAction(); +} + +void DevToolsWindow::DoAction() { + UpdateFrontendDockSide(); + switch (action_on_load_) { + case DEVTOOLS_TOGGLE_ACTION_SHOW_CONSOLE: + CallClientFunction("InspectorFrontendAPI.showConsole", NULL); + break; + case DEVTOOLS_TOGGLE_ACTION_INSPECT: + CallClientFunction("InspectorFrontendAPI.enterInspectElementMode", NULL); + case DEVTOOLS_TOGGLE_ACTION_SHOW: + case DEVTOOLS_TOGGLE_ACTION_TOGGLE: + // Do nothing. + break; + default: + NOTREACHED(); + } + action_on_load_ = DEVTOOLS_TOGGLE_ACTION_SHOW; +} + +std::string SkColorToRGBAString(SkColor color) { + // We convert the alpha using DoubleToString because StringPrintf will use + // locale specific formatters (e.g., use , instead of . in German). + return StringPrintf("rgba(%d,%d,%d,%s)", SkColorGetR(color), + SkColorGetG(color), SkColorGetB(color), + base::DoubleToString(SkColorGetA(color) / 255.0).c_str()); +} + +// static +GURL DevToolsWindow::GetDevToolsUrl(Profile* profile, + DevToolsDockSide dock_side, + bool shared_worker_frontend) { + ThemeService* tp = ThemeServiceFactory::GetForProfile(profile); + CHECK(tp); + + SkColor color_toolbar = + tp->GetColor(ThemeService::COLOR_TOOLBAR); + SkColor color_tab_text = + tp->GetColor(ThemeService::COLOR_BOOKMARK_TEXT); + + const CommandLine& command_line = *CommandLine::ForCurrentProcess(); + bool experiments_enabled = + command_line.HasSwitch(switches::kEnableDevToolsExperiments); + + std::string url_string = StringPrintf("%sdevtools.html?" + "dockSide=%s&toolbarColor=%s&textColor=%s%s%s", + chrome::kChromeUIDevToolsURL, + SideToString(dock_side).c_str(), + SkColorToRGBAString(color_toolbar).c_str(), + SkColorToRGBAString(color_tab_text).c_str(), + shared_worker_frontend ? "&isSharedWorker=true" : "", + experiments_enabled ? "&experiments=true" : ""); + return GURL(url_string); +} + +void DevToolsWindow::UpdateTheme() { + ThemeService* tp = ThemeServiceFactory::GetForProfile(profile_); + CHECK(tp); + + SkColor color_toolbar = + tp->GetColor(ThemeService::COLOR_TOOLBAR); + SkColor color_tab_text = + tp->GetColor(ThemeService::COLOR_BOOKMARK_TEXT); + std::string command = StringPrintf( + "InspectorFrontendAPI.setToolbarColors(\"%s\", \"%s\")", + SkColorToRGBAString(color_toolbar).c_str(), + SkColorToRGBAString(color_tab_text).c_str()); + web_contents_->GetRenderViewHost()-> + ExecuteJavascriptInWebFrame(string16(), UTF8ToUTF16(command)); +} + +void DevToolsWindow::AddNewContents(WebContents* source, + WebContents* new_contents, + WindowOpenDisposition disposition, + const gfx::Rect& initial_pos, + bool user_gesture, + bool* was_blocked) { + if (inspected_web_contents_) { + inspected_web_contents_->GetDelegate()->AddNewContents( + source, new_contents, disposition, initial_pos, user_gesture, + was_blocked); + } +} + +bool DevToolsWindow::PreHandleKeyboardEvent( + WebContents* source, + const NativeWebKeyboardEvent& event, bool* is_keyboard_shortcut) { + if (IsDocked()) { + BrowserWindow* inspected_window = GetInspectedBrowserWindow(); + if (inspected_window) + return inspected_window->PreHandleKeyboardEvent( + event, is_keyboard_shortcut); + } + return false; +} + +void DevToolsWindow::HandleKeyboardEvent(WebContents* source, + const NativeWebKeyboardEvent& event) { + if (IsDocked()) { + if (event.windowsKeyCode == 0x08) { + // Do not navigate back in history on Windows (http://crbug.com/74156). + return; + } + BrowserWindow* inspected_window = GetInspectedBrowserWindow(); + if (inspected_window) + inspected_window->HandleKeyboardEvent(event); + } +} + +// static +DevToolsWindow* DevToolsWindow::ToggleDevToolsWindow( + RenderViewHost* inspected_rvh, + bool force_open, + DevToolsToggleAction action) { + DevToolsAgentHost* agent = DevToolsAgentHostRegistry::GetDevToolsAgentHost( + inspected_rvh); + DevToolsManager* manager = DevToolsManager::GetInstance(); + DevToolsClientHost* host = manager->GetDevToolsClientHostFor(agent); + DevToolsWindow* window = AsDevToolsWindow(host); + if (host && !window) { + // Break remote debugging / extension debugging session. + host->ReplacedWithAnotherClient(); + manager->UnregisterDevToolsClientHostFor(agent); + } + + bool do_open = force_open; + if (!window) { + Profile* profile = Profile::FromBrowserContext( + inspected_rvh->GetProcess()->GetBrowserContext()); + DevToolsDockSide dock_side = GetDockSideFromPrefs(profile); + window = Create(profile, inspected_rvh, dock_side, false); + manager->RegisterDevToolsClientHostFor(agent, window->frontend_host_); + do_open = true; + } + + // Update toolbar to reflect DevTools changes. + window->UpdateBrowserToolbar(); + + // If window is docked and visible, we hide it on toggle. If window is + // undocked, we show (activate) it. + if (!window->IsDocked() || do_open) + window->Show(action); + else + manager->UnregisterDevToolsClientHostFor(agent); + + return window; +} + +// static +DevToolsWindow* DevToolsWindow::AsDevToolsWindow( + DevToolsClientHost* client_host) { + if (!client_host || g_instances == NULL) + return NULL; + DevToolsWindowList& instances = g_instances.Get(); + for (DevToolsWindowList::iterator it = instances.begin(); + it != instances.end(); ++it) { + if ((*it)->frontend_host_ == client_host) + return *it; + } + return NULL; +} + +// static +DevToolsWindow* DevToolsWindow::AsDevToolsWindow(RenderViewHost* window_rvh) { + if (g_instances == NULL) + return NULL; + DevToolsWindowList& instances = g_instances.Get(); + for (DevToolsWindowList::iterator it = instances.begin(); + it != instances.end(); ++it) { + if ((*it)->web_contents_->GetRenderViewHost() == window_rvh) + return *it; + } + return NULL; +} + +void DevToolsWindow::ActivateWindow() { + if (!IsDocked()) { + if (!browser_->window()->IsActive()) { + browser_->window()->Activate(); + } + } else { + BrowserWindow* inspected_window = GetInspectedBrowserWindow(); + if (inspected_window) + web_contents_->GetView()->Focus(); + } +} + +void DevToolsWindow::CloseWindow() { + DCHECK(IsDocked()); + DevToolsManager::GetInstance()->ClientHostClosing(frontend_host_); + InspectedContentsClosing(); +} + +void DevToolsWindow::MoveWindow(int x, int y) { + if (!IsDocked()) { + gfx::Rect bounds = browser_->window()->GetBounds(); + bounds.Offset(x, y); + browser_->window()->SetBounds(bounds); + } +} + +void DevToolsWindow::SetDockSide(const std::string& side) { + DevToolsDockSide requested_side = SideFromString(side); + bool dock_requested = requested_side != DEVTOOLS_DOCK_SIDE_UNDOCKED; + bool is_docked = IsDocked(); + + if (dock_requested && (!inspected_web_contents_ || + !GetInspectedBrowserWindow() || IsInspectedBrowserPopupOrPanel())) { + // Cannot dock, avoid window flashing due to close-reopen cycle. + return; + } + + dock_side_ = requested_side; + if (dock_requested) { + if (!is_docked) { + // Detach window from the external devtools browser. It will lead to + // 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_)); + browser_ = NULL; + } + } else if (is_docked) { + // Update inspected window to hide split and reset it. + BrowserWindow* inspected_window = GetInspectedBrowserWindow(); + if (inspected_window) + inspected_window->UpdateDevTools(); + } + + std::string pref_value = kPrefBottom; + switch (dock_side_) { + case DEVTOOLS_DOCK_SIDE_UNDOCKED: + pref_value = kPrefUndocked; + break; + case DEVTOOLS_DOCK_SIDE_RIGHT: + pref_value = kPrefRight; + break; + case DEVTOOLS_DOCK_SIDE_BOTTOM: + pref_value = kPrefBottom; + break; + } + profile_->GetPrefs()->SetString(prefs::kDevToolsDockSide, pref_value); + + Show(DEVTOOLS_TOGGLE_ACTION_SHOW); +} + +void DevToolsWindow::OpenInNewTab(const std::string& url) { + OpenURLParams params(GURL(url), + content::Referrer(), + NEW_FOREGROUND_TAB, + content::PAGE_TRANSITION_LINK, + false /* is_renderer_initiated */); + if (inspected_web_contents_) { + inspected_web_contents_->OpenURL(params); + } else { + for (BrowserList::const_iterator it = BrowserList::begin(); + it != BrowserList::end(); ++it) { + if ((*it)->type() == Browser::TYPE_TABBED) { + (*it)->OpenURL(params); + break; + } + } + } +} + +void DevToolsWindow::SaveToFile(const std::string& url, + const std::string& content, + bool save_as) { + file_helper_->Save(url, content, save_as); +} + +void DevToolsWindow::AppendToFile(const std::string& url, + const std::string& content) { + file_helper_->Append(url, content); +} + +void DevToolsWindow::FileSavedAs(const std::string& url) { + StringValue url_value(url); + CallClientFunction("InspectorFrontendAPI.savedURL", &url_value); +} + +void DevToolsWindow::AppendedTo(const std::string& url) { + StringValue url_value(url); + CallClientFunction("InspectorFrontendAPI.appendedToURL", &url_value); +} + +content::JavaScriptDialogCreator* DevToolsWindow::GetJavaScriptDialogCreator() { + if (inspected_web_contents_ && inspected_web_contents_->GetDelegate()) { + return inspected_web_contents_->GetDelegate()-> + GetJavaScriptDialogCreator(); + } + return content::WebContentsDelegate::GetJavaScriptDialogCreator(); +} + +void DevToolsWindow::RunFileChooser(WebContents* web_contents, + const FileChooserParams& params) { + FileSelectHelper::RunFileChooser(web_contents, params); +} + +void DevToolsWindow::WebContentsFocused(WebContents* contents) { + Browser* inspected_browser = NULL; + int inspected_tab_index = -1; + + if (IsDocked() && FindInspectedBrowserAndTabIndex(&inspected_browser, + &inspected_tab_index)) { + inspected_browser->window()->WebContentsFocused(contents); + } +} + +void DevToolsWindow::UpdateBrowserToolbar() { + if (!inspected_web_contents_) + return; + BrowserWindow* inspected_window = GetInspectedBrowserWindow(); + if (inspected_window) + inspected_window->UpdateToolbar(inspected_web_contents_, false); +} + +bool DevToolsWindow::IsDocked() { + return dock_side_ != DEVTOOLS_DOCK_SIDE_UNDOCKED; +} + +// static +DevToolsDockSide DevToolsWindow::GetDockSideFromPrefs(Profile* profile) { + std::string dock_side = + profile->GetPrefs()->GetString(prefs::kDevToolsDockSide); + + // Migrate prefs + if (dock_side == kOldPrefBottom || dock_side == kOldPrefRight) { + bool docked = profile->GetPrefs()->GetBoolean(prefs::kDevToolsOpenDocked); + if (dock_side == kOldPrefBottom) + return docked ? DEVTOOLS_DOCK_SIDE_BOTTOM : DEVTOOLS_DOCK_SIDE_UNDOCKED; + else + return docked ? DEVTOOLS_DOCK_SIDE_RIGHT : DEVTOOLS_DOCK_SIDE_UNDOCKED; + } + + if (dock_side == kPrefUndocked) + return DEVTOOLS_DOCK_SIDE_UNDOCKED; + else if (dock_side == kPrefRight) + return DEVTOOLS_DOCK_SIDE_RIGHT; + // Default to docked to bottom + return DEVTOOLS_DOCK_SIDE_BOTTOM; +} + +// static +std::string DevToolsWindow::SideToString(DevToolsDockSide dock_side) { + std::string dock_side_string; + switch (dock_side) { + case DEVTOOLS_DOCK_SIDE_UNDOCKED: return kDockSideUndocked; + case DEVTOOLS_DOCK_SIDE_RIGHT: return kDockSideRight; + case DEVTOOLS_DOCK_SIDE_BOTTOM: return kDockSideBottom; + } + return kDockSideUndocked; +} + +// static +DevToolsDockSide DevToolsWindow::SideFromString( + const std::string& dock_side) { + if (dock_side == kDockSideRight) + return DEVTOOLS_DOCK_SIDE_RIGHT; + if (dock_side == kDockSideBottom) + return DEVTOOLS_DOCK_SIDE_BOTTOM; + return DEVTOOLS_DOCK_SIDE_UNDOCKED; +} diff --git a/chrome/browser/devtools/devtools_window.h b/chrome/browser/devtools/devtools_window.h new file mode 100644 index 0000000..06033f7 --- /dev/null +++ b/chrome/browser/devtools/devtools_window.h @@ -0,0 +1,214 @@ +// Copyright (c) 2012 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_H_ +#define CHROME_BROWSER_DEVTOOLS_DEVTOOLS_WINDOW_H_ + +#include +#include + +#include "base/basictypes.h" +#include "base/memory/scoped_ptr.h" +#include "chrome/browser/devtools/devtools_file_helper.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 "content/public/browser/web_contents_delegate.h" + +class Browser; +class BrowserWindow; +class PrefService; +class Profile; + +namespace base { +class Value; +} + +namespace chrome { +class BrowserListImpl; +} + +namespace content { +class DevToolsAgentHost; +class DevToolsClientHost; +struct FileChooserParams; +class RenderViewHost; +class WebContents; +} + +namespace IPC { +class Message; +} + +enum DevToolsDockSide { + DEVTOOLS_DOCK_SIDE_UNDOCKED = 0, + DEVTOOLS_DOCK_SIDE_BOTTOM, + DEVTOOLS_DOCK_SIDE_RIGHT +}; + +class DevToolsWindow : private content::NotificationObserver, + private content::WebContentsDelegate, + private content::DevToolsFrontendHostDelegate, + private DevToolsFileHelper::Delegate { + public: + static const char kDevToolsApp[]; + static void RegisterUserPrefs(PrefService* prefs); + static DevToolsWindow* GetDockedInstanceForInspectedTab( + content::WebContents* inspected_tab); + static bool IsDevToolsWindow(content::RenderViewHost* window_rvh); + + static DevToolsWindow* OpenDevToolsWindowForWorker( + Profile* profile, + content::DevToolsAgentHost* worker_agent); + static DevToolsWindow* CreateDevToolsWindowForWorker(Profile* profile); + static DevToolsWindow* OpenDevToolsWindow( + content::RenderViewHost* inspected_rvh); + static DevToolsWindow* ToggleDevToolsWindow( + Browser* browser, + DevToolsToggleAction action); + + // Exposed for testing, normal clients should not use this method. + static DevToolsWindow* ToggleDevToolsWindow( + content::RenderViewHost* inspected_rvh, + bool force_open, + DevToolsToggleAction action); + static void InspectElement( + content::RenderViewHost* inspected_rvh, int x, int y); + + virtual ~DevToolsWindow(); + + // Overridden from DevToolsClientHost. + virtual void InspectedContentsClosing() OVERRIDE; + virtual void ContentsReplaced(content::WebContents* new_contents) OVERRIDE; + content::RenderViewHost* GetRenderViewHost(); + + void Show(DevToolsToggleAction action); + + content::WebContents* web_contents() { return web_contents_; } + Browser* browser() { return browser_; } // For tests. + DevToolsDockSide dock_side() { return dock_side_; } + content::DevToolsClientHost* devtools_client_host() { return frontend_host_; } + + // Returns preferred devtools window width for given |container_width|. It + // tries to use the saved window width, or, if none exists, 1/3 of the + // container width, then clamps to try and ensure both devtools and content + // are at least somewhat visible. + // Called only for the case when devtools window is docked to the side. + int GetWidth(int container_width); + + // Returns preferred devtools window height for given |container_height|. + // Uses the same logic as GetWidth. + // Called only for the case when devtools window is docked to bottom. + int GetHeight(int container_height); + + // Stores preferred devtools window width for this instance. + void SetWidth(int width); + + // Stores preferred devtools window height for this instance. + void SetHeight(int height); + + private: + static DevToolsWindow* Create(Profile* profile, + content::RenderViewHost* inspected_rvh, + DevToolsDockSide dock_side, + bool shared_worker_frontend); + DevToolsWindow(content::WebContents* web_contents, + Profile* profile, + content::RenderViewHost* inspected_rvh, + DevToolsDockSide dock_side); + + void CreateDevToolsBrowser(); + bool FindInspectedBrowserAndTabIndex(Browser**, int* tab); + bool FindInspectedBrowserAndTabIndexFromBrowserList( + chrome::BrowserListImpl* browser_list, + Browser** browser, + int* tab); + BrowserWindow* GetInspectedBrowserWindow(); + bool IsInspectedBrowserPopupOrPanel(); + void UpdateFrontendDockSide(); + + // Overridden from content::NotificationObserver. + virtual void Observe(int type, + const content::NotificationSource& source, + const content::NotificationDetails& details) OVERRIDE; + + void ScheduleAction(DevToolsToggleAction action); + void DoAction(); + static GURL GetDevToolsUrl(Profile* profile, + DevToolsDockSide dock_side, + bool shared_worker_frontend); + void UpdateTheme(); + void AddDevToolsExtensionsToClient(); + void CallClientFunction(const std::string& function_name, + const base::Value* arg); + // Overridden from content::WebContentsDelegate. + virtual content::WebContents* OpenURLFromTab( + content::WebContents* source, + const content::OpenURLParams& params) OVERRIDE; + virtual void AddNewContents(content::WebContents* source, + content::WebContents* new_contents, + WindowOpenDisposition disposition, + const gfx::Rect& initial_pos, + bool user_gesture, + bool* was_blocked) OVERRIDE; + virtual void CloseContents(content::WebContents* source) OVERRIDE {} + virtual bool PreHandleKeyboardEvent( + content::WebContents* source, + const content::NativeWebKeyboardEvent& event, + bool* is_keyboard_shortcut) OVERRIDE; + virtual void HandleKeyboardEvent( + content::WebContents* source, + const content::NativeWebKeyboardEvent& event) OVERRIDE; + virtual content::JavaScriptDialogCreator* + GetJavaScriptDialogCreator() OVERRIDE; + virtual void RunFileChooser( + content::WebContents* web_contents, + const content::FileChooserParams& params) OVERRIDE; + virtual void WebContentsFocused(content::WebContents* contents) OVERRIDE; + + virtual void FrameNavigating(const std::string& url) OVERRIDE {} + + static DevToolsWindow* AsDevToolsWindow(content::DevToolsClientHost*); + static DevToolsWindow* AsDevToolsWindow(content::RenderViewHost*); + + // content::DevToolsFrontendHostDelegate overrides. + virtual void ActivateWindow() OVERRIDE; + virtual void CloseWindow() OVERRIDE; + virtual void MoveWindow(int x, int y) OVERRIDE; + virtual void SetDockSide(const std::string& side) 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; + + // Overridden from DevToolsFileHelper::Delegate + virtual void FileSavedAs(const std::string& url) OVERRIDE; + virtual void AppendedTo(const std::string& url) OVERRIDE; + + void UpdateBrowserToolbar(); + bool IsDocked(); + static DevToolsDockSide GetDockSideFromPrefs(Profile* profile); + static std::string SideToString(DevToolsDockSide dock_side); + static DevToolsDockSide SideFromString(const std::string& dock_side); + + Profile* profile_; + content::WebContents* inspected_web_contents_; + content::WebContents* web_contents_; + Browser* browser_; + DevToolsDockSide dock_side_; + bool is_loaded_; + DevToolsToggleAction action_on_load_; + content::NotificationRegistrar registrar_; + content::DevToolsClientHost* frontend_host_; + scoped_ptr file_helper_; + int width_; + int height_; + DISALLOW_COPY_AND_ASSIGN(DevToolsWindow); +}; + +#endif // CHROME_BROWSER_DEVTOOLS_DEVTOOLS_WINDOW_H_ diff --git a/chrome/browser/devtools/frontend/devtools_discovery_page.html b/chrome/browser/devtools/frontend/devtools_discovery_page.html new file mode 100644 index 0000000..85c03b8 --- /dev/null +++ b/chrome/browser/devtools/frontend/devtools_discovery_page.html @@ -0,0 +1,142 @@ + + +Inspectable pages + + + + + +
Inspectable pages
+
+
+
+ + diff --git a/chrome/browser/devtools/frontend/devtools_discovery_page_resources.grd b/chrome/browser/devtools/frontend/devtools_discovery_page_resources.grd new file mode 100644 index 0000000..85ad2aa --- /dev/null +++ b/chrome/browser/devtools/frontend/devtools_discovery_page_resources.grd @@ -0,0 +1,21 @@ + + + + + + + + + + + + + + + diff --git a/chrome/browser/devtools/remote_debugging_server.cc b/chrome/browser/devtools/remote_debugging_server.cc new file mode 100644 index 0000000..2d05199 --- /dev/null +++ b/chrome/browser/devtools/remote_debugging_server.cc @@ -0,0 +1,27 @@ +// Copyright (c) 2012 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/remote_debugging_server.h" + +#include "chrome/browser/devtools/browser_list_tabcontents_provider.h" +#include "chrome/browser/ui/webui/devtools_ui.h" +#include "content/public/browser/devtools_http_handler.h" +#include "net/base/tcp_listen_socket.h" + +RemoteDebuggingServer::RemoteDebuggingServer(Profile* profile, + const std::string& ip, + int port, + const std::string& frontend_url) { + // Initialize DevTools data source. + DevToolsUI::RegisterDevToolsDataSource(profile); + + devtools_http_handler_ = content::DevToolsHttpHandler::Start( + new net::TCPListenSocketFactory(ip, port), + frontend_url, + new BrowserListTabContentsProvider(profile)); +} + +RemoteDebuggingServer::~RemoteDebuggingServer() { + devtools_http_handler_->Stop(); +} diff --git a/chrome/browser/devtools/remote_debugging_server.h b/chrome/browser/devtools/remote_debugging_server.h new file mode 100644 index 0000000..d872f29 --- /dev/null +++ b/chrome/browser/devtools/remote_debugging_server.h @@ -0,0 +1,32 @@ +// Copyright (c) 2011 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_REMOTE_DEBUGGING_SERVER_H_ +#define CHROME_BROWSER_DEVTOOLS_REMOTE_DEBUGGING_SERVER_H_ + +#include + +#include "base/basictypes.h" + +class Profile; + +namespace content { +class DevToolsHttpHandler; +} + +class RemoteDebuggingServer { + public: + RemoteDebuggingServer(Profile* profile, + const std::string& ip, + int port, + const std::string& frontend_url); + + virtual ~RemoteDebuggingServer(); + + private: + content::DevToolsHttpHandler* devtools_http_handler_; + DISALLOW_COPY_AND_ASSIGN(RemoteDebuggingServer); +}; + +#endif // CHROME_BROWSER_DEVTOOLS_REMOTE_DEBUGGING_SERVER_H_ diff --git a/chrome/browser/extensions/api/app_window/app_window_api.cc b/chrome/browser/extensions/api/app_window/app_window_api.cc index d474f50..0c94ff6 100644 --- a/chrome/browser/extensions/api/app_window/app_window_api.cc +++ b/chrome/browser/extensions/api/app_window/app_window_api.cc @@ -7,7 +7,7 @@ #include "base/command_line.h" #include "base/time.h" #include "base/values.h" -#include "chrome/browser/debugger/devtools_window.h" +#include "chrome/browser/devtools/devtools_window.h" #include "chrome/browser/extensions/shell_window_registry.h" #include "chrome/browser/extensions/window_controller.h" #include "chrome/browser/ui/extensions/native_app_window.h" diff --git a/chrome/browser/extensions/api/developer_private/developer_private_api.cc b/chrome/browser/extensions/api/developer_private/developer_private_api.cc index 7c006e6..8732781 100644 --- a/chrome/browser/extensions/api/developer_private/developer_private_api.cc +++ b/chrome/browser/extensions/api/developer_private/developer_private_api.cc @@ -7,7 +7,7 @@ #include "base/string_number_conversions.h" #include "base/utf_string_conversions.h" #include "base/values.h" -#include "chrome/browser/debugger/devtools_window.h" +#include "chrome/browser/devtools/devtools_window.h" #include "chrome/browser/extensions/api/developer_private/developer_private_api_factory.h" #include "chrome/browser/extensions/extension_service.h" #include "chrome/browser/extensions/extension_system.h" diff --git a/chrome/browser/extensions/extension_service.cc b/chrome/browser/extensions/extension_service.cc index 5b9d714..11e2c9d 100644 --- a/chrome/browser/extensions/extension_service.cc +++ b/chrome/browser/extensions/extension_service.cc @@ -30,7 +30,7 @@ #include "chrome/browser/bookmarks/bookmark_model_factory.h" #include "chrome/browser/browser_process.h" #include "chrome/browser/chrome_plugin_service_filter.h" -#include "chrome/browser/debugger/devtools_window.h" +#include "chrome/browser/devtools/devtools_window.h" #include "chrome/browser/extensions/api/app_runtime/app_runtime_api.h" #include "chrome/browser/extensions/api/declarative/rules_registry_service.h" #include "chrome/browser/extensions/api/extension_action/extension_actions_api.h" diff --git a/chrome/browser/extensions/platform_app_browsertest.cc b/chrome/browser/extensions/platform_app_browsertest.cc index 7902b4f..b658083 100644 --- a/chrome/browser/extensions/platform_app_browsertest.cc +++ b/chrome/browser/extensions/platform_app_browsertest.cc @@ -8,7 +8,7 @@ #include "base/utf_string_conversions.h" #include "chrome/app/chrome_command_ids.h" #include "chrome/browser/automation/automation_util.h" -#include "chrome/browser/debugger/devtools_window.h" +#include "chrome/browser/devtools/devtools_window.h" #include "chrome/browser/extensions/api/permissions/permissions_api.h" #include "chrome/browser/extensions/app_restore_service_factory.h" #include "chrome/browser/extensions/app_restore_service.h" diff --git a/chrome/browser/policy/policy_browsertest.cc b/chrome/browser/policy/policy_browsertest.cc index 2789aba..8632a2d2 100644 --- a/chrome/browser/policy/policy_browsertest.cc +++ b/chrome/browser/policy/policy_browsertest.cc @@ -22,7 +22,7 @@ #include "chrome/app/chrome_command_ids.h" #include "chrome/browser/autocomplete/autocomplete_controller.h" #include "chrome/browser/browser_process.h" -#include "chrome/browser/debugger/devtools_window.h" +#include "chrome/browser/devtools/devtools_window.h" #include "chrome/browser/download/download_prefs.h" #include "chrome/browser/extensions/crx_installer.h" #include "chrome/browser/extensions/extension_service.h" diff --git a/chrome/browser/prefs/browser_prefs.cc b/chrome/browser/prefs/browser_prefs.cc index 153d286..7247c6a 100644 --- a/chrome/browser/prefs/browser_prefs.cc +++ b/chrome/browser/prefs/browser_prefs.cc @@ -14,7 +14,7 @@ #include "chrome/browser/chrome_content_browser_client.h" #include "chrome/browser/content_settings/host_content_settings_map.h" #include "chrome/browser/custom_handlers/protocol_handler_registry.h" -#include "chrome/browser/debugger/devtools_window.h" +#include "chrome/browser/devtools/devtools_window.h" #include "chrome/browser/download/download_prefs.h" #include "chrome/browser/extensions/api/commands/command_service.h" #include "chrome/browser/extensions/api/tabs/tabs.h" diff --git a/chrome/browser/printing/print_dialog_cloud.cc b/chrome/browser/printing/print_dialog_cloud.cc index 689da2d..774f63d 100644 --- a/chrome/browser/printing/print_dialog_cloud.cc +++ b/chrome/browser/printing/print_dialog_cloud.cc @@ -13,7 +13,7 @@ #include "base/json/json_reader.h" #include "base/utf_string_conversions.h" #include "base/values.h" -#include "chrome/browser/debugger/devtools_window.h" +#include "chrome/browser/devtools/devtools_window.h" #include "chrome/browser/lifetime/application_lifetime.h" #include "chrome/browser/prefs/pref_service.h" #include "chrome/browser/printing/cloud_print/cloud_print_url.h" diff --git a/chrome/browser/renderer_host/chrome_render_widget_host_view_mac_delegate.mm b/chrome/browser/renderer_host/chrome_render_widget_host_view_mac_delegate.mm index 9bab39f..0a0adcc 100644 --- a/chrome/browser/renderer_host/chrome_render_widget_host_view_mac_delegate.mm +++ b/chrome/browser/renderer_host/chrome_render_widget_host_view_mac_delegate.mm @@ -7,7 +7,7 @@ #include #include "base/sys_string_conversions.h" -#include "chrome/browser/debugger/devtools_window.h" +#include "chrome/browser/devtools/devtools_window.h" #include "chrome/browser/prefs/pref_service.h" #include "chrome/browser/profiles/profile.h" #include "chrome/browser/spellchecker/spellcheck_platform_mac.h" diff --git a/chrome/browser/renderer_host/render_process_host_chrome_browsertest.cc b/chrome/browser/renderer_host/render_process_host_chrome_browsertest.cc index 8595857..7ed2efd 100644 --- a/chrome/browser/renderer_host/render_process_host_chrome_browsertest.cc +++ b/chrome/browser/renderer_host/render_process_host_chrome_browsertest.cc @@ -3,7 +3,7 @@ // found in the LICENSE file. #include "base/command_line.h" -#include "chrome/browser/debugger/devtools_window.h" +#include "chrome/browser/devtools/devtools_window.h" #include "chrome/browser/ui/browser.h" #include "chrome/browser/ui/browser_commands.h" #include "chrome/browser/ui/browser_tabstrip.h" diff --git a/chrome/browser/tab_contents/render_view_context_menu.cc b/chrome/browser/tab_contents/render_view_context_menu.cc index e9e2b75..3a39e5e 100644 --- a/chrome/browser/tab_contents/render_view_context_menu.cc +++ b/chrome/browser/tab_contents/render_view_context_menu.cc @@ -21,7 +21,7 @@ #include "chrome/browser/autocomplete/autocomplete_classifier_factory.h" #include "chrome/browser/autocomplete/autocomplete_match.h" #include "chrome/browser/browser_process.h" -#include "chrome/browser/debugger/devtools_window.h" +#include "chrome/browser/devtools/devtools_window.h" #include "chrome/browser/download/download_service.h" #include "chrome/browser/download/download_service_factory.h" #include "chrome/browser/download/download_util.h" diff --git a/chrome/browser/task_manager/task_manager_notification_resource_provider.cc b/chrome/browser/task_manager/task_manager_notification_resource_provider.cc index 8fbbce0..748cca6 100644 --- a/chrome/browser/task_manager/task_manager_notification_resource_provider.cc +++ b/chrome/browser/task_manager/task_manager_notification_resource_provider.cc @@ -7,7 +7,7 @@ #include "base/basictypes.h" #include "base/stl_util.h" #include "chrome/browser/browser_process.h" -#include "chrome/browser/debugger/devtools_window.h" +#include "chrome/browser/devtools/devtools_window.h" #include "chrome/browser/notifications/balloon.h" #include "chrome/browser/notifications/balloon_collection.h" #include "chrome/browser/notifications/balloon_host.h" diff --git a/chrome/browser/task_manager/task_manager_resource_providers.cc b/chrome/browser/task_manager/task_manager_resource_providers.cc index cc4f580..75e7671 100644 --- a/chrome/browser/task_manager/task_manager_resource_providers.cc +++ b/chrome/browser/task_manager/task_manager_resource_providers.cc @@ -22,7 +22,7 @@ #include "chrome/browser/background/background_contents_service.h" #include "chrome/browser/background/background_contents_service_factory.h" #include "chrome/browser/browser_process.h" -#include "chrome/browser/debugger/devtools_window.h" +#include "chrome/browser/devtools/devtools_window.h" #include "chrome/browser/extensions/extension_host.h" #include "chrome/browser/extensions/extension_process_manager.h" #include "chrome/browser/extensions/extension_service.h" diff --git a/chrome/browser/task_manager/task_manager_worker_resource_provider.cc b/chrome/browser/task_manager/task_manager_worker_resource_provider.cc index 514e0f3..83723ce 100644 --- a/chrome/browser/task_manager/task_manager_worker_resource_provider.cc +++ b/chrome/browser/task_manager/task_manager_worker_resource_provider.cc @@ -9,7 +9,7 @@ #include "base/stl_util.h" #include "base/utf_string_conversions.h" #include "chrome/browser/browser_process.h" -#include "chrome/browser/debugger/devtools_window.h" +#include "chrome/browser/devtools/devtools_window.h" #include "chrome/browser/profiles/profile_manager.h" #include "content/public/browser/browser_thread.h" #include "content/public/browser/child_process_data.h" diff --git a/chrome/browser/ui/browser.cc b/chrome/browser/ui/browser.cc index f1d1d7d..a7f6cf9 100644 --- a/chrome/browser/ui/browser.cc +++ b/chrome/browser/ui/browser.cc @@ -41,8 +41,8 @@ #include "chrome/browser/content_settings/tab_specific_content_settings.h" #include "chrome/browser/custom_handlers/protocol_handler_registry.h" #include "chrome/browser/custom_handlers/register_protocol_handler_infobar_delegate.h" -#include "chrome/browser/debugger/devtools_toggle_action.h" -#include "chrome/browser/debugger/devtools_window.h" +#include "chrome/browser/devtools/devtools_toggle_action.h" +#include "chrome/browser/devtools/devtools_window.h" #include "chrome/browser/download/download_crx_util.h" #include "chrome/browser/download/download_item_model.h" #include "chrome/browser/download/download_service.h" diff --git a/chrome/browser/ui/browser.h b/chrome/browser/ui/browser.h index 735fd96..e9f2ce9 100644 --- a/chrome/browser/ui/browser.h +++ b/chrome/browser/ui/browser.h @@ -18,7 +18,7 @@ #include "base/prefs/public/pref_change_registrar.h" #include "base/prefs/public/pref_member.h" #include "base/string16.h" -#include "chrome/browser/debugger/devtools_toggle_action.h" +#include "chrome/browser/devtools/devtools_toggle_action.h" #include "chrome/browser/event_disposition.h" #include "chrome/browser/sessions/session_id.h" #include "chrome/browser/ui/blocked_content/blocked_content_tab_helper_delegate.h" diff --git a/chrome/browser/ui/browser_commands.cc b/chrome/browser/ui/browser_commands.cc index 49ade84..e657147a 100644 --- a/chrome/browser/ui/browser_commands.cc +++ b/chrome/browser/ui/browser_commands.cc @@ -14,7 +14,7 @@ #include "chrome/browser/browsing_data/browsing_data_helper.h" #include "chrome/browser/browsing_data/browsing_data_remover.h" #include "chrome/browser/chrome_page_zoom.h" -#include "chrome/browser/debugger/devtools_window.h" +#include "chrome/browser/devtools/devtools_window.h" #include "chrome/browser/download/download_util.h" #include "chrome/browser/extensions/extension_service.h" #include "chrome/browser/extensions/tab_helper.h" diff --git a/chrome/browser/ui/browser_commands.h b/chrome/browser/ui/browser_commands.h index 6776240c..3b362c4 100644 --- a/chrome/browser/ui/browser_commands.h +++ b/chrome/browser/ui/browser_commands.h @@ -7,7 +7,7 @@ #include -#include "chrome/browser/debugger/devtools_toggle_action.h" +#include "chrome/browser/devtools/devtools_toggle_action.h" #include "chrome/browser/ui/host_desktop.h" #include "content/public/common/page_zoom.h" #include "webkit/glue/window_open_disposition.h" diff --git a/chrome/browser/ui/cocoa/dev_tools_controller.h b/chrome/browser/ui/cocoa/dev_tools_controller.h index 3f27c5dec..05e3241 100644 --- a/chrome/browser/ui/cocoa/dev_tools_controller.h +++ b/chrome/browser/ui/cocoa/dev_tools_controller.h @@ -8,7 +8,7 @@ #import #include "base/memory/scoped_nsobject.h" -#include "chrome/browser/debugger/devtools_window.h" +#include "chrome/browser/devtools/devtools_window.h" @class NSSplitView; @class NSView; diff --git a/chrome/browser/ui/cocoa/extensions/extension_popup_controller.mm b/chrome/browser/ui/cocoa/extensions/extension_popup_controller.mm index 948f706..12d24a604d 100644 --- a/chrome/browser/ui/cocoa/extensions/extension_popup_controller.mm +++ b/chrome/browser/ui/cocoa/extensions/extension_popup_controller.mm @@ -6,7 +6,7 @@ #include -#include "chrome/browser/debugger/devtools_window.h" +#include "chrome/browser/devtools/devtools_window.h" #include "chrome/browser/extensions/extension_host.h" #include "chrome/browser/extensions/extension_process_manager.h" #include "chrome/browser/extensions/extension_system.h" diff --git a/chrome/browser/ui/cocoa/tabpose_window.mm b/chrome/browser/ui/cocoa/tabpose_window.mm index d85d5ed..f9adc9f 100644 --- a/chrome/browser/ui/cocoa/tabpose_window.mm +++ b/chrome/browser/ui/cocoa/tabpose_window.mm @@ -14,7 +14,7 @@ #include "base/sys_string_conversions.h" #include "chrome/app/chrome_command_ids.h" #include "chrome/browser/browser_process.h" -#include "chrome/browser/debugger/devtools_window.h" +#include "chrome/browser/devtools/devtools_window.h" #include "chrome/browser/extensions/tab_helper.h" #include "chrome/browser/prefs/pref_service.h" #include "chrome/browser/profiles/profile.h" diff --git a/chrome/browser/ui/cocoa/tabs/tab_strip_controller.mm b/chrome/browser/ui/cocoa/tabs/tab_strip_controller.mm index d80f004..83d2dd3 100644 --- a/chrome/browser/ui/cocoa/tabs/tab_strip_controller.mm +++ b/chrome/browser/ui/cocoa/tabs/tab_strip_controller.mm @@ -19,7 +19,7 @@ #include "chrome/browser/autocomplete/autocomplete_classifier.h" #include "chrome/browser/autocomplete/autocomplete_classifier_factory.h" #include "chrome/browser/autocomplete/autocomplete_match.h" -#include "chrome/browser/debugger/devtools_window.h" +#include "chrome/browser/devtools/devtools_window.h" #include "chrome/browser/extensions/tab_helper.h" #include "chrome/browser/favicon/favicon_tab_helper.h" #include "chrome/browser/net/url_fixer_upper.h" diff --git a/chrome/browser/ui/gtk/browser_window_gtk.h b/chrome/browser/ui/gtk/browser_window_gtk.h index 5203eed..1900b93 100644 --- a/chrome/browser/ui/gtk/browser_window_gtk.h +++ b/chrome/browser/ui/gtk/browser_window_gtk.h @@ -15,7 +15,7 @@ #include "base/prefs/public/pref_member.h" #include "base/timer.h" #include "build/build_config.h" -#include "chrome/browser/debugger/devtools_window.h" +#include "chrome/browser/devtools/devtools_window.h" #include "chrome/browser/extensions/extension_keybinding_registry.h" #include "chrome/browser/infobars/infobar_container.h" #include "chrome/browser/ui/browser_window.h" diff --git a/chrome/browser/ui/gtk/extensions/extension_popup_gtk.cc b/chrome/browser/ui/gtk/extensions/extension_popup_gtk.cc index 006657b..e0b0605 100644 --- a/chrome/browser/ui/gtk/extensions/extension_popup_gtk.cc +++ b/chrome/browser/ui/gtk/extensions/extension_popup_gtk.cc @@ -13,7 +13,7 @@ #include "base/callback.h" #include "base/i18n/rtl.h" #include "base/message_loop.h" -#include "chrome/browser/debugger/devtools_window.h" +#include "chrome/browser/devtools/devtools_window.h" #include "chrome/browser/extensions/extension_host.h" #include "chrome/browser/extensions/extension_process_manager.h" #include "chrome/browser/extensions/extension_system.h" diff --git a/chrome/browser/ui/panels/panel.cc b/chrome/browser/ui/panels/panel.cc index 5780b16..35900ca 100644 --- a/chrome/browser/ui/panels/panel.cc +++ b/chrome/browser/ui/panels/panel.cc @@ -8,7 +8,7 @@ #include "base/message_loop.h" #include "base/utf_string_conversions.h" #include "chrome/app/chrome_command_ids.h" -#include "chrome/browser/debugger/devtools_window.h" +#include "chrome/browser/devtools/devtools_window.h" #include "chrome/browser/extensions/api/tabs/tabs_constants.h" #include "chrome/browser/extensions/api/tabs/tabs_windows_api.h" #include "chrome/browser/extensions/api/tabs/windows_event_router.h" diff --git a/chrome/browser/ui/panels/panel_browsertest.cc b/chrome/browser/ui/panels/panel_browsertest.cc index ed945b4..228ca2b 100644 --- a/chrome/browser/ui/panels/panel_browsertest.cc +++ b/chrome/browser/ui/panels/panel_browsertest.cc @@ -5,7 +5,7 @@ #include "base/bind.h" #include "base/utf_string_conversions.h" #include "chrome/app/chrome_command_ids.h" -#include "chrome/browser/debugger/devtools_window.h" +#include "chrome/browser/devtools/devtools_window.h" #include "chrome/browser/extensions/extension_apitest.h" #include "chrome/browser/net/url_request_mock_util.h" #include "chrome/browser/prefs/browser_prefs.h" diff --git a/chrome/browser/ui/views/extensions/extension_popup.cc b/chrome/browser/ui/views/extensions/extension_popup.cc index 12461f7..f9ea609 100644 --- a/chrome/browser/ui/views/extensions/extension_popup.cc +++ b/chrome/browser/ui/views/extensions/extension_popup.cc @@ -6,7 +6,7 @@ #include "base/bind.h" #include "base/message_loop.h" -#include "chrome/browser/debugger/devtools_window.h" +#include "chrome/browser/devtools/devtools_window.h" #include "chrome/browser/extensions/extension_process_manager.h" #include "chrome/browser/extensions/extension_system.h" #include "chrome/browser/platform_util.h" diff --git a/chrome/browser/ui/views/external_tab_container_win.cc b/chrome/browser/ui/views/external_tab_container_win.cc index a6aa395..3d66c3e 100644 --- a/chrome/browser/ui/views/external_tab_container_win.cc +++ b/chrome/browser/ui/views/external_tab_container_win.cc @@ -19,8 +19,8 @@ #include "chrome/app/chrome_command_ids.h" #include "chrome/app/chrome_dll_resource.h" #include "chrome/browser/automation/automation_provider.h" -#include "chrome/browser/debugger/devtools_toggle_action.h" -#include "chrome/browser/debugger/devtools_window.h" +#include "chrome/browser/devtools/devtools_toggle_action.h" +#include "chrome/browser/devtools/devtools_window.h" #include "chrome/browser/file_select_helper.h" #include "chrome/browser/history/history_tab_helper.h" #include "chrome/browser/history/history_types.h" diff --git a/chrome/browser/ui/views/frame/browser_view.h b/chrome/browser/ui/views/frame/browser_view.h index 7fa6ca9..0590ca0 100644 --- a/chrome/browser/ui/views/frame/browser_view.h +++ b/chrome/browser/ui/views/frame/browser_view.h @@ -13,7 +13,7 @@ #include "base/memory/scoped_ptr.h" #include "base/timer.h" #include "build/build_config.h" -#include "chrome/browser/debugger/devtools_window.h" +#include "chrome/browser/devtools/devtools_window.h" #include "chrome/browser/infobars/infobar_container.h" #include "chrome/browser/ui/browser.h" #include "chrome/browser/ui/browser_window.h" diff --git a/chrome/browser/ui/webui/extensions/extension_settings_handler.cc b/chrome/browser/ui/webui/extensions/extension_settings_handler.cc index fa4f929..fef8fa1 100644 --- a/chrome/browser/ui/webui/extensions/extension_settings_handler.cc +++ b/chrome/browser/ui/webui/extensions/extension_settings_handler.cc @@ -16,7 +16,7 @@ #include "base/values.h" #include "base/version.h" #include "chrome/browser/browser_process.h" -#include "chrome/browser/debugger/devtools_window.h" +#include "chrome/browser/devtools/devtools_window.h" #include "chrome/browser/extensions/crx_installer.h" #include "chrome/browser/extensions/extension_action_manager.h" #include "chrome/browser/extensions/extension_disabled_ui.h" diff --git a/chrome/browser/ui/webui/inspect_ui.cc b/chrome/browser/ui/webui/inspect_ui.cc index 877292d..f677218 100644 --- a/chrome/browser/ui/webui/inspect_ui.cc +++ b/chrome/browser/ui/webui/inspect_ui.cc @@ -14,7 +14,7 @@ #include "base/string_util.h" #include "base/utf_string_conversions.h" #include "base/values.h" -#include "chrome/browser/debugger/devtools_window.h" +#include "chrome/browser/devtools/devtools_window.h" #include "chrome/browser/extensions/extension_service.h" #include "chrome/browser/profiles/profile.h" #include "chrome/browser/ui/tab_contents/tab_contents_iterator.h" diff --git a/chrome/chrome.gyp b/chrome/chrome.gyp index e5a31f5..6e0cb29 100644 --- a/chrome/chrome.gyp +++ b/chrome/chrome.gyp @@ -206,15 +206,15 @@ '..', ], 'sources': [ - 'browser/debugger/browser_list_tabcontents_provider.cc', - 'browser/debugger/browser_list_tabcontents_provider.h', - 'browser/debugger/devtools_file_helper.cc', - 'browser/debugger/devtools_file_helper.h', - 'browser/debugger/devtools_toggle_action.h', - 'browser/debugger/devtools_window.cc', - 'browser/debugger/devtools_window.h', - 'browser/debugger/remote_debugging_server.cc', - 'browser/debugger/remote_debugging_server.h', + 'browser/devtools/browser_list_tabcontents_provider.cc', + 'browser/devtools/browser_list_tabcontents_provider.h', + 'browser/devtools/devtools_file_helper.cc', + 'browser/devtools/devtools_file_helper.h', + 'browser/devtools/devtools_toggle_action.h', + 'browser/devtools/devtools_window.cc', + 'browser/devtools/devtools_window.h', + 'browser/devtools/remote_debugging_server.cc', + 'browser/devtools/remote_debugging_server.h', ], 'conditions': [ ['toolkit_uses_gtk == 1', { @@ -224,9 +224,9 @@ }], ['OS=="android"', { 'sources!': [ - 'browser/debugger/browser_list_tabcontents_provider.cc', - 'browser/debugger/devtools_window.cc', - 'browser/debugger/remote_debugging_server.cc', + 'browser/devtools/browser_list_tabcontents_provider.cc', + 'browser/devtools/devtools_window.cc', + 'browser/devtools/remote_debugging_server.cc', ], }], ['debug_devtools==1', { diff --git a/chrome/chrome_resources.gyp b/chrome/chrome_resources.gyp index 1f8fd41..7b7d29c 100644 --- a/chrome/chrome_resources.gyp +++ b/chrome/chrome_resources.gyp @@ -47,7 +47,7 @@ 'conditions': [ ['OS != "ios"', { 'dependencies': [ - '../content/browser/debugger/devtools_resources.gyp:devtools_resources', + '../content/browser/devtools/devtools_resources.gyp:devtools_resources', ], 'actions': [ { @@ -75,7 +75,7 @@ 'action_name': 'devtools_discovery_page_resources', 'variables': { 'grit_grd_file': - 'browser/debugger/frontend/devtools_discovery_page_resources.grd', + 'browser/devtools/frontend/devtools_discovery_page_resources.grd', }, 'includes': [ '../build/grit_action.gypi' ] }, diff --git a/chrome/chrome_tests.gypi b/chrome/chrome_tests.gypi index e012e4e..30758a3 100644 --- a/chrome/chrome_tests.gypi +++ b/chrome/chrome_tests.gypi @@ -925,7 +925,7 @@ 'browser/content_settings/content_settings_browsertest.cc', 'browser/crash_recovery_browsertest.cc', 'browser/custom_handlers/protocol_handler_registry_browsertest.cc', - 'browser/debugger/devtools_sanity_browsertest.cc', + 'browser/devtools/devtools_sanity_browsertest.cc', 'browser/do_not_track_browsertest.cc', 'browser/download/download_browsertest.cc', 'browser/download/download_danger_prompt_browsertest.cc', diff --git a/content/browser/debugger/DEPS b/content/browser/debugger/DEPS deleted file mode 100644 index 3e98aee..0000000 --- a/content/browser/debugger/DEPS +++ /dev/null @@ -1,4 +0,0 @@ -include_rules = [ - # Generated by the local devtools_resources.gyp:devtools_resources - "+grit/devtools_resources_map.h", -] diff --git a/content/browser/debugger/OWNERS b/content/browser/debugger/OWNERS deleted file mode 100644 index 1b8b683..0000000 --- a/content/browser/debugger/OWNERS +++ /dev/null @@ -1,3 +0,0 @@ -joi@chromium.org -pfeldman@chromium.org -yurys@chromium.org diff --git a/content/browser/debugger/devtools_agent_host.cc b/content/browser/debugger/devtools_agent_host.cc deleted file mode 100644 index 6ea8f5d..0000000 --- a/content/browser/debugger/devtools_agent_host.cc +++ /dev/null @@ -1,57 +0,0 @@ -// Copyright (c) 2012 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 "content/browser/debugger/devtools_agent_host.h" - -#include "base/basictypes.h" -#include "content/common/devtools_messages.h" - -namespace content { - -DevToolsAgentHost::DevToolsAgentHost() : close_listener_(NULL) { -} - -void DevToolsAgentHost::Attach() { - SendMessageToAgent(new DevToolsAgentMsg_Attach(MSG_ROUTING_NONE)); - NotifyClientAttaching(); -} - -void DevToolsAgentHost::Reattach(const std::string& saved_agent_state) { - SendMessageToAgent(new DevToolsAgentMsg_Reattach( - MSG_ROUTING_NONE, - saved_agent_state)); - NotifyClientAttaching(); -} - -void DevToolsAgentHost::Detach() { - SendMessageToAgent(new DevToolsAgentMsg_Detach(MSG_ROUTING_NONE)); - NotifyClientDetaching(); -} - -void DevToolsAgentHost::DipatchOnInspectorBackend(const std::string& message) { - SendMessageToAgent(new DevToolsAgentMsg_DispatchOnInspectorBackend( - MSG_ROUTING_NONE, message)); -} - -void DevToolsAgentHost::InspectElement(int x, int y) { - SendMessageToAgent(new DevToolsAgentMsg_InspectElement(MSG_ROUTING_NONE, - x, y)); -} - -void DevToolsAgentHost::AddMessageToConsole(ConsoleMessageLevel level, - const std::string& message) { - SendMessageToAgent(new DevToolsAgentMsg_AddMessageToConsole( - MSG_ROUTING_NONE, - level, - message)); -} - -void DevToolsAgentHost::NotifyCloseListener() { - if (close_listener_) { - close_listener_->AgentHostClosing(this); - close_listener_ = NULL; - } -} - -} // namespace content diff --git a/content/browser/debugger/devtools_agent_host.h b/content/browser/debugger/devtools_agent_host.h deleted file mode 100644 index 944315b..0000000 --- a/content/browser/debugger/devtools_agent_host.h +++ /dev/null @@ -1,59 +0,0 @@ -// Copyright (c) 2012 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 CONTENT_BROWSER_DEBUGGER_DEVTOOLS_AGENT_HOST_H_ -#define CONTENT_BROWSER_DEBUGGER_DEVTOOLS_AGENT_HOST_H_ - -#include - -#include "content/common/content_export.h" -#include "content/public/common/console_message_level.h" - -namespace IPC { -class Message; -} - -namespace content { - -// Describes interface for managing devtools agents from the browser process. -class CONTENT_EXPORT DevToolsAgentHost { - public: - class CONTENT_EXPORT CloseListener { - public: - virtual void AgentHostClosing(DevToolsAgentHost*) = 0; - protected: - virtual ~CloseListener() {} - }; - - // Sends the message to the devtools agent hosted by this object. - void Attach(); - void Reattach(const std::string& saved_agent_state); - void Detach(); - void DipatchOnInspectorBackend(const std::string& message); - void InspectElement(int x, int y); - void AddMessageToConsole(ConsoleMessageLevel level, - const std::string& message); - - virtual int GetRenderProcessId() = 0; - - void set_close_listener(CloseListener* listener) { - close_listener_ = listener; - } - - protected: - DevToolsAgentHost(); - virtual ~DevToolsAgentHost() {} - - virtual void SendMessageToAgent(IPC::Message* msg) = 0; - virtual void NotifyClientAttaching() = 0; - virtual void NotifyClientDetaching() = 0; - - void NotifyCloseListener(); - - CloseListener* close_listener_; -}; - -} // namespace content - -#endif // CONTENT_BROWSER_DEBUGGER_DEVTOOLS_AGENT_HOST_H_ diff --git a/content/browser/debugger/devtools_browser_target.cc b/content/browser/debugger/devtools_browser_target.cc deleted file mode 100644 index 95d57a9..0000000 --- a/content/browser/debugger/devtools_browser_target.cc +++ /dev/null @@ -1,118 +0,0 @@ -// Copyright (c) 2012 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 "content/browser/debugger/devtools_browser_target.h" - -#include "base/json/json_reader.h" -#include "base/json/json_writer.h" -#include "base/logging.h" -#include "base/memory/scoped_ptr.h" -#include "base/values.h" - - -namespace content { - -DevToolsBrowserTarget::DevToolsBrowserTarget(int connection_id) - : connection_id_(connection_id) { -} - -DevToolsBrowserTarget::~DevToolsBrowserTarget() { - for (HandlersMap::iterator i = handlers_.begin(); i != handlers_.end(); ++i) - delete i->second; -} - -void DevToolsBrowserTarget::RegisterHandler(Handler* handler) { - std::string domain = handler->Domain(); - DCHECK(handlers_.find(domain) == handlers_.end()); - handlers_[domain] = handler; -} - -std::string DevToolsBrowserTarget::HandleMessage(const std::string& data) { - int error_code; - std::string error_message; - scoped_ptr command( - base::JSONReader::ReadAndReturnError( - data, 0, &error_code, &error_message)); - - if (!command || !command->IsType(base::Value::TYPE_DICTIONARY)) - return SerializeErrorResponse( - -1, CreateErrorObject(error_code, error_message)); - - int request_id; - std::string domain; - std::string method; - base::DictionaryValue* command_dict = NULL; - bool ok = true; - ok &= command->GetAsDictionary(&command_dict); - ok &= command_dict->GetInteger("id", &request_id); - ok &= command_dict->GetString("method", &method); - if (!ok) - return SerializeErrorResponse( - request_id, CreateErrorObject(-1, "Malformed request")); - - base::DictionaryValue* params = NULL; - command_dict->GetDictionary("params", ¶ms); - - size_t pos = method.find("."); - if (pos == std::string::npos) - return SerializeErrorResponse( - request_id, CreateErrorObject(-1, "Method unsupported")); - - domain = method.substr(0, pos); - if (domain.empty() || handlers_.find(domain) == handlers_.end()) - return SerializeErrorResponse( - request_id, CreateErrorObject(-1, "Domain unsupported")); - - base::Value* error_object = NULL; - base::Value* domain_result = handlers_[domain]->OnProtocolCommand( - method, params, &error_object); - - if (error_object) - return SerializeErrorResponse(request_id, error_object); - - if (!domain_result) - return SerializeErrorResponse( - request_id, CreateErrorObject(-1, "Invalid call")); - - DictionaryValue* response = new DictionaryValue(); - response->Set("result", domain_result); - return SerializeResponse(request_id, response); -} - -std::string DevToolsBrowserTarget::SerializeErrorResponse( - int request_id, base::Value* error_object) { - scoped_ptr error_response(new base::DictionaryValue()); - error_response->SetInteger("id", request_id); - error_response->Set("error", error_object); - // Serialize response. - std::string json_response; - base::JSONWriter::WriteWithOptions(error_response.get(), - base::JSONWriter::OPTIONS_PRETTY_PRINT, - &json_response); - return json_response; -} - -base::Value* DevToolsBrowserTarget::CreateErrorObject( - int error_code, const std::string& message) { - base::DictionaryValue* error_object = new base::DictionaryValue(); - error_object->SetInteger("code", error_code); - error_object->SetString("message", message); - return error_object; -} - -std::string DevToolsBrowserTarget::SerializeResponse( - int request_id, base::Value* response) { - scoped_ptr ret(new base::DictionaryValue()); - ret->SetInteger("id", request_id); - ret->Set("response", response); - - // Serialize response. - std::string json_response; - base::JSONWriter::WriteWithOptions(ret.get(), - base::JSONWriter::OPTIONS_PRETTY_PRINT, - &json_response); - return json_response; -} - -} // namespace content diff --git a/content/browser/debugger/devtools_browser_target.h b/content/browser/debugger/devtools_browser_target.h deleted file mode 100644 index 14e141f..0000000 --- a/content/browser/debugger/devtools_browser_target.h +++ /dev/null @@ -1,68 +0,0 @@ -// Copyright (c) 2012 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 CONTENT_BROWSER_DEBUGGER_DEVTOOLS_BROWSER_TARGET_H_ -#define CONTENT_BROWSER_DEBUGGER_DEVTOOLS_BROWSER_TARGET_H_ - -#include -#include - -#include "base/basictypes.h" - -namespace base { - -class DictionaryValue; -class Value; - -} // namespace base - -namespace content { - -// This class handles the "Browser" target for remote debugging. -class DevToolsBrowserTarget { - public: - class Handler { - public: - virtual ~Handler() {} - - // Returns the domain name for this handler. - virtual std::string Domain() = 0; - - // |return_value| and |error_message_out| ownership is transferred to the - // caller. - virtual base::Value* OnProtocolCommand( - const std::string& method, - const base::DictionaryValue* params, - base::Value** error_message_out) = 0; - }; - - explicit DevToolsBrowserTarget(int connection_id); - ~DevToolsBrowserTarget(); - - int connection_id() const { return connection_id_; } - - // Takes ownership of |handler|. - void RegisterHandler(Handler* handler); - - std::string HandleMessage(const std::string& data); - - private: - const int connection_id_; - - typedef std::map HandlersMap; - HandlersMap handlers_; - - // Takes ownership of |error_object|. - std::string SerializeErrorResponse(int request_id, base::Value* error_object); - - base::Value* CreateErrorObject(int error_code, const std::string& message); - - std::string SerializeResponse(int request_id, base::Value* response); - - DISALLOW_COPY_AND_ASSIGN(DevToolsBrowserTarget); -}; - -} // namespace content - -#endif // CONTENT_BROWSER_DEBUGGER_DEVTOOLS_BROWSER_TARGET_H_ diff --git a/content/browser/debugger/devtools_frontend_host.cc b/content/browser/debugger/devtools_frontend_host.cc deleted file mode 100644 index 49bac66..0000000 --- a/content/browser/debugger/devtools_frontend_host.cc +++ /dev/null @@ -1,125 +0,0 @@ -// Copyright (c) 2012 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 "content/browser/debugger/devtools_frontend_host.h" - -#include "content/browser/debugger/devtools_manager_impl.h" -#include "content/browser/renderer_host/render_view_host_impl.h" -#include "content/browser/web_contents/web_contents_impl.h" -#include "content/common/devtools_messages.h" -#include "content/public/browser/devtools_client_host.h" -#include "content/public/browser/devtools_frontend_host_delegate.h" - -namespace content { - -// static -DevToolsClientHost* DevToolsClientHost::CreateDevToolsFrontendHost( - WebContents* client_web_contents, - DevToolsFrontendHostDelegate* delegate) { - return new DevToolsFrontendHost( - static_cast(client_web_contents), delegate); -} - -// static -void DevToolsClientHost::SetupDevToolsFrontendClient( - RenderViewHost* frontend_rvh) { - frontend_rvh->Send(new DevToolsMsg_SetupDevToolsClient( - frontend_rvh->GetRoutingID())); -} - -DevToolsFrontendHost::DevToolsFrontendHost( - WebContentsImpl* web_contents, - DevToolsFrontendHostDelegate* delegate) - : RenderViewHostObserver(web_contents->GetRenderViewHost()), - web_contents_(web_contents), - delegate_(delegate) { -} - -DevToolsFrontendHost::~DevToolsFrontendHost() { - DevToolsManager::GetInstance()->ClientHostClosing(this); -} - -void DevToolsFrontendHost::DispatchOnInspectorFrontend( - const std::string& message) { - RenderViewHostImpl* target_host = - static_cast(web_contents_->GetRenderViewHost()); - target_host->Send(new DevToolsClientMsg_DispatchOnInspectorFrontend( - target_host->GetRoutingID(), - message)); -} - -void DevToolsFrontendHost::InspectedContentsClosing() { - delegate_->InspectedContentsClosing(); -} - -void DevToolsFrontendHost::FrameNavigating(const std::string& url) { - delegate_->FrameNavigating(url); -} - -void DevToolsFrontendHost::ContentsReplaced(WebContents* new_contents) { - delegate_->ContentsReplaced(new_contents); -} - -void DevToolsFrontendHost::ReplacedWithAnotherClient() { -} - -bool DevToolsFrontendHost::OnMessageReceived( - const IPC::Message& message) { - bool handled = true; - IPC_BEGIN_MESSAGE_MAP(DevToolsFrontendHost, message) - IPC_MESSAGE_HANDLER(DevToolsAgentMsg_DispatchOnInspectorBackend, - OnDispatchOnInspectorBackend) - IPC_MESSAGE_HANDLER(DevToolsHostMsg_ActivateWindow, OnActivateWindow) - IPC_MESSAGE_HANDLER(DevToolsHostMsg_CloseWindow, OnCloseWindow) - IPC_MESSAGE_HANDLER(DevToolsHostMsg_MoveWindow, OnMoveWindow) - IPC_MESSAGE_HANDLER(DevToolsHostMsg_RequestSetDockSide, - OnRequestSetDockSide) - IPC_MESSAGE_HANDLER(DevToolsHostMsg_OpenInNewTab, OnOpenInNewTab) - IPC_MESSAGE_HANDLER(DevToolsHostMsg_Save, OnSave) - IPC_MESSAGE_HANDLER(DevToolsHostMsg_Append, OnAppend) - IPC_MESSAGE_UNHANDLED(handled = false) - IPC_END_MESSAGE_MAP() - return handled; -} - -void DevToolsFrontendHost::OnDispatchOnInspectorBackend( - const std::string& message) { - DevToolsManagerImpl::GetInstance()->DispatchOnInspectorBackend(this, message); -// delegate_->DispatchOnInspectorBackend(message); -} - -void DevToolsFrontendHost::OnActivateWindow() { - delegate_->ActivateWindow(); -} - -void DevToolsFrontendHost::OnCloseWindow() { - delegate_->CloseWindow(); -} - -void DevToolsFrontendHost::OnMoveWindow(int x, int y) { - delegate_->MoveWindow(x, y); -} - -void DevToolsFrontendHost::OnOpenInNewTab(const std::string& url) { - delegate_->OpenInNewTab(url); -} - -void DevToolsFrontendHost::OnSave( - const std::string& url, - const std::string& content, - bool save_as) { - delegate_->SaveToFile(url, content, save_as); -} - -void DevToolsFrontendHost::OnAppend( - const std::string& url, - const std::string& content) { - delegate_->AppendToFile(url, content); -} - -void DevToolsFrontendHost::OnRequestSetDockSide(const std::string& side) { - delegate_->SetDockSide(side); -} - -} // namespace content diff --git a/content/browser/debugger/devtools_frontend_host.h b/content/browser/debugger/devtools_frontend_host.h deleted file mode 100644 index fd04fd1..0000000 --- a/content/browser/debugger/devtools_frontend_host.h +++ /dev/null @@ -1,59 +0,0 @@ -// Copyright (c) 2012 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 CONTENT_BROWSER_DEBUGGER_DEVTOOLS_FRONTEND_HOST_H_ -#define CONTENT_BROWSER_DEBUGGER_DEVTOOLS_FRONTEND_HOST_H_ - -#include - -#include "base/basictypes.h" -#include "base/compiler_specific.h" -#include "content/public/browser/devtools_client_host.h" -#include "content/public/browser/render_view_host_observer.h" - -namespace content { - -class DevToolsFrontendHostDelegate; -class WebContentsImpl; - -// This class handles messages from DevToolsClient and calls corresponding -// methods on DevToolsFrontendHostDelegate which is implemented by the -// embedder. This allows us to avoid exposing DevTools client messages through -// the content public API. -class DevToolsFrontendHost : public DevToolsClientHost, - public RenderViewHostObserver { - public: - DevToolsFrontendHost(WebContentsImpl* web_contents, - DevToolsFrontendHostDelegate* delegate); - - private: - virtual ~DevToolsFrontendHost(); - - // DevToolsClientHost implementation. - virtual void DispatchOnInspectorFrontend(const std::string& message) OVERRIDE; - virtual void InspectedContentsClosing() OVERRIDE; - virtual void FrameNavigating(const std::string& url) OVERRIDE; - virtual void ContentsReplaced(WebContents* new_contents) OVERRIDE; - virtual void ReplacedWithAnotherClient() OVERRIDE; - - // RenderViewHostObserver overrides. - virtual bool OnMessageReceived(const IPC::Message& message) OVERRIDE; - - void OnDispatchOnInspectorBackend(const std::string& message); - void OnActivateWindow(); - void OnCloseWindow(); - void OnMoveWindow(int x, int y); - void OnRequestSetDockSide(const std::string& side); - void OnOpenInNewTab(const std::string& url); - void OnSave(const std::string& url, const std::string& content, bool save_as); - void OnAppend(const std::string& url, const std::string& content); - - WebContentsImpl* web_contents_; - DevToolsFrontendHostDelegate* delegate_; - DISALLOW_COPY_AND_ASSIGN(DevToolsFrontendHost); -}; - -} // namespace content - -#endif // CONTENT_BROWSER_DEBUGGER_DEVTOOLS_FRONTEND_HOST_H_ diff --git a/content/browser/debugger/devtools_http_handler_impl.cc b/content/browser/debugger/devtools_http_handler_impl.cc deleted file mode 100644 index a62d4bd..0000000 --- a/content/browser/debugger/devtools_http_handler_impl.cc +++ /dev/null @@ -1,873 +0,0 @@ -// Copyright (c) 2012 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 "content/browser/debugger/devtools_http_handler_impl.h" - -#include -#include - -#include "base/bind.h" -#include "base/compiler_specific.h" -#include "base/file_util.h" -#include "base/json/json_writer.h" -#include "base/lazy_instance.h" -#include "base/logging.h" -#include "base/message_loop_proxy.h" -#include "base/string_number_conversions.h" -#include "base/stringprintf.h" -#include "base/threading/thread.h" -#include "base/utf_string_conversions.h" -#include "base/values.h" -#include "content/browser/debugger/devtools_browser_target.h" -#include "content/browser/debugger/devtools_tracing_handler.h" -#include "content/browser/web_contents/web_contents_impl.h" -#include "content/common/devtools_messages.h" -#include "content/public/browser/browser_thread.h" -#include "content/public/browser/devtools_agent_host_registry.h" -#include "content/public/browser/devtools_client_host.h" -#include "content/public/browser/devtools_http_handler_delegate.h" -#include "content/public/browser/devtools_manager.h" -#include "content/public/browser/favicon_status.h" -#include "content/public/browser/navigation_entry.h" -#include "content/public/browser/notification_service.h" -#include "content/public/browser/notification_types.h" -#include "content/public/browser/render_process_host.h" -#include "content/public/browser/render_view_host.h" -#include "content/public/browser/render_widget_host.h" -#include "content/public/common/content_client.h" -#include "content/public/common/url_constants.h" -#include "googleurl/src/gurl.h" -#include "grit/devtools_resources_map.h" -#include "net/base/escape.h" -#include "net/base/io_buffer.h" -#include "net/base/ip_endpoint.h" -#include "net/server/http_server_request_info.h" -#include "third_party/WebKit/Source/WebKit/chromium/public/WebDevToolsAgent.h" -#include "third_party/WebKit/Source/WebKit/chromium/public/platform/WebString.h" -#include "ui/base/layout.h" -#include "webkit/user_agent/user_agent.h" -#include "webkit/user_agent/user_agent_util.h" - -namespace content { - -const int kBufferSize = 16 * 1024; - -namespace { - -static const char* kDevToolsHandlerThreadName = "Chrome_DevToolsHandlerThread"; - -class DevToolsDefaultBindingHandler - : public DevToolsHttpHandler::RenderViewHostBinding { - public: - DevToolsDefaultBindingHandler() { - } - - virtual std::string GetIdentifier(RenderViewHost* rvh) OVERRIDE { - int process_id = rvh->GetProcess()->GetID(); - int routing_id = rvh->GetRoutingID(); - return base::StringPrintf("%d_%d", process_id, routing_id); - } - - virtual RenderViewHost* ForIdentifier( - const std::string& identifier) OVERRIDE { - size_t pos = identifier.find("_"); - if (pos == std::string::npos) - return NULL; - - int process_id; - if (!base::StringToInt(identifier.substr(0, pos), &process_id)) - return NULL; - - int routing_id; - if (!base::StringToInt(identifier.substr(pos+1), &routing_id)) - return NULL; - - return RenderViewHost::FromID(process_id, routing_id); - } -}; - - -// An internal implementation of DevToolsClientHost that delegates -// messages sent for DevToolsClient to a DebuggerShell instance. -class DevToolsClientHostImpl : public DevToolsClientHost { - public: - DevToolsClientHostImpl( - MessageLoop* message_loop, - net::HttpServer* server, - int connection_id) - : message_loop_(message_loop), - server_(server), - connection_id_(connection_id), - is_closed_(false), - detach_reason_("target_closed") { - } - - ~DevToolsClientHostImpl() {} - - // DevToolsClientHost interface - virtual void InspectedContentsClosing() { - if (is_closed_) - return; - is_closed_ = true; - - std::string response = - WebKit::WebDevToolsAgent::inspectorDetachedEvent( - WebKit::WebString::fromUTF8(detach_reason_)).utf8(); - message_loop_->PostTask( - FROM_HERE, - base::Bind(&net::HttpServer::SendOverWebSocket, - server_, - connection_id_, - response)); - - message_loop_->PostTask( - FROM_HERE, - base::Bind(&net::HttpServer::Close, server_, connection_id_)); - } - - virtual void DispatchOnInspectorFrontend(const std::string& data) { - message_loop_->PostTask( - FROM_HERE, - base::Bind(&net::HttpServer::SendOverWebSocket, - server_, - connection_id_, - data)); - } - - virtual void ContentsReplaced(WebContents* new_contents) { - } - - virtual void ReplacedWithAnotherClient() { - detach_reason_ = "replaced_with_devtools"; - } - - private: - virtual void FrameNavigating(const std::string& url) {} - MessageLoop* message_loop_; - net::HttpServer* server_; - int connection_id_; - bool is_closed_; - std::string detach_reason_; -}; - -} // namespace - -// static -int DevToolsHttpHandler::GetFrontendResourceId(const std::string& name) { - for (size_t i = 0; i < kDevtoolsResourcesSize; ++i) { - if (name == kDevtoolsResources[i].name) - return kDevtoolsResources[i].value; - } - return -1; -} - -// static -DevToolsHttpHandler* DevToolsHttpHandler::Start( - const net::StreamListenSocketFactory* socket_factory, - const std::string& frontend_url, - DevToolsHttpHandlerDelegate* delegate) { - DevToolsHttpHandlerImpl* http_handler = - new DevToolsHttpHandlerImpl(socket_factory, - frontend_url, - delegate); - http_handler->Start(); - return http_handler; -} - -DevToolsHttpHandlerImpl::~DevToolsHttpHandlerImpl() { - DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); - // Stop() must be called prior to destruction. - DCHECK(server_.get() == NULL); - DCHECK(thread_.get() == NULL); -} - -void DevToolsHttpHandlerImpl::Start() { - if (thread_.get()) - return; - thread_.reset(new base::Thread(kDevToolsHandlerThreadName)); - BrowserThread::PostTask( - BrowserThread::FILE, FROM_HERE, - base::Bind(&DevToolsHttpHandlerImpl::StartHandlerThread, this)); -} - -// Runs on FILE thread. -void DevToolsHttpHandlerImpl::StartHandlerThread() { - base::Thread::Options options; - options.message_loop_type = MessageLoop::TYPE_IO; - if (!thread_->StartWithOptions(options)) { - BrowserThread::PostTask( - BrowserThread::UI, FROM_HERE, - base::Bind(&DevToolsHttpHandlerImpl::ResetHandlerThread, this)); - return; - } - - thread_->message_loop()->PostTask( - FROM_HERE, - base::Bind(&DevToolsHttpHandlerImpl::Init, this)); -} - -void DevToolsHttpHandlerImpl::ResetHandlerThread() { - thread_.reset(); -} - -void DevToolsHttpHandlerImpl::ResetHandlerThreadAndRelease() { - ResetHandlerThread(); - Release(); -} - -void DevToolsHttpHandlerImpl::Stop() { - if (!thread_.get()) - return; - BrowserThread::PostTaskAndReply( - BrowserThread::FILE, FROM_HERE, - base::Bind(&DevToolsHttpHandlerImpl::StopHandlerThread, this), - base::Bind(&DevToolsHttpHandlerImpl::ResetHandlerThreadAndRelease, this)); -} - -void DevToolsHttpHandlerImpl::SetRenderViewHostBinding( - RenderViewHostBinding* binding) { - if (binding) - binding_ = binding; - else - binding_ = default_binding_.get(); -} - -GURL DevToolsHttpHandlerImpl::GetFrontendURL(RenderViewHost* render_view_host) { - net::IPEndPoint ip_address; - if (server_->GetLocalAddress(&ip_address)) - return GURL(); - std::string host = ip_address.ToString(); - std::string id = binding_->GetIdentifier(render_view_host); - return GURL(std::string("http://") + - ip_address.ToString() + - GetFrontendURLInternal(id, host)); -} - -static std::string PathWithoutParams(const std::string& path) { - size_t query_position = path.find("?"); - if (query_position != std::string::npos) - return path.substr(0, query_position); - return path; -} - -static std::string GetMimeType(const std::string& filename) { - if (EndsWith(filename, ".html", false)) { - return "text/html"; - } else if (EndsWith(filename, ".css", false)) { - return "text/css"; - } else if (EndsWith(filename, ".js", false)) { - return "application/javascript"; - } else if (EndsWith(filename, ".png", false)) { - return "image/png"; - } else if (EndsWith(filename, ".gif", false)) { - return "image/gif"; - } - NOTREACHED(); - return "text/plain"; -} - -void DevToolsHttpHandlerImpl::Observe(int type, - const NotificationSource& source, - const NotificationDetails& details) { - RenderProcessHost* process = Source(source).ptr(); - DevToolsManager* manager = DevToolsManager::GetInstance(); - for (ConnectionToClientHostMap::iterator it = - connection_to_client_host_ui_.begin(); - it != connection_to_client_host_ui_.end(); ++it) { - DevToolsAgentHost* agent = manager->GetDevToolsAgentHostFor(it->second); - if (!agent) - continue; - RenderViewHost* rvh = DevToolsAgentHostRegistry::GetRenderViewHost(agent); - if (rvh && rvh->GetProcess() == process) - it->second->InspectedContentsClosing(); - } -} - -void DevToolsHttpHandlerImpl::OnHttpRequest( - int connection_id, - const net::HttpServerRequestInfo& info) { - if (info.path.find("/json") == 0) { - BrowserThread::PostTask( - BrowserThread::UI, - FROM_HERE, - base::Bind(&DevToolsHttpHandlerImpl::OnJsonRequestUI, - this, - connection_id, - info)); - return; - } - - if (info.path.find("/thumb/") == 0) { - // Thumbnail request. - BrowserThread::PostTask( - BrowserThread::UI, - FROM_HERE, - base::Bind(&DevToolsHttpHandlerImpl::OnThumbnailRequestUI, - this, - connection_id, - info)); - return; - } - - if (info.path == "" || info.path == "/") { - // Discovery page request. - BrowserThread::PostTask( - BrowserThread::UI, - FROM_HERE, - base::Bind(&DevToolsHttpHandlerImpl::OnDiscoveryPageRequestUI, - this, - connection_id)); - return; - } - - if (info.path.find("/devtools/") != 0) { - server_->Send404(connection_id); - return; - } - - std::string filename = PathWithoutParams(info.path.substr(10)); - std::string mime_type = GetMimeType(filename); - - FilePath frontend_dir = delegate_->GetDebugFrontendDir(); - if (!frontend_dir.empty()) { - FilePath path = frontend_dir.AppendASCII(filename); - std::string data; - file_util::ReadFileToString(path, &data); - server_->Send200(connection_id, data, mime_type); - return; - } - if (delegate_->BundlesFrontendResources()) { - int resource_id = DevToolsHttpHandler::GetFrontendResourceId(filename); - if (resource_id != -1) { - base::StringPiece data = GetContentClient()->GetDataResource( - resource_id, ui::SCALE_FACTOR_NONE); - server_->Send200(connection_id, data.as_string(), mime_type); - return; - } - } - server_->Send404(connection_id); -} - -void DevToolsHttpHandlerImpl::OnWebSocketRequest( - int connection_id, - const net::HttpServerRequestInfo& request) { - BrowserThread::PostTask( - BrowserThread::UI, - FROM_HERE, - base::Bind( - &DevToolsHttpHandlerImpl::OnWebSocketRequestUI, - this, - connection_id, - request)); -} - -void DevToolsHttpHandlerImpl::OnWebSocketMessage( - int connection_id, - const std::string& data) { - BrowserThread::PostTask( - BrowserThread::UI, - FROM_HERE, - base::Bind( - &DevToolsHttpHandlerImpl::OnWebSocketMessageUI, - this, - connection_id, - data)); -} - -void DevToolsHttpHandlerImpl::OnClose(int connection_id) { - BrowserThread::PostTask( - BrowserThread::UI, - FROM_HERE, - base::Bind( - &DevToolsHttpHandlerImpl::OnCloseUI, - this, - connection_id)); -} - -struct DevToolsHttpHandlerImpl::PageInfo { - PageInfo() - : attached(false) { - } - - std::string id; - std::string url; - bool attached; - std::string title; - std::string thumbnail_url; - std::string favicon_url; - base::TimeTicks last_selected_time; -}; - -// static -bool DevToolsHttpHandlerImpl::SortPageListByTime(const PageInfo& info1, - const PageInfo& info2) { - return info1.last_selected_time > info2.last_selected_time; -} - -DevToolsHttpHandlerImpl::PageList DevToolsHttpHandlerImpl::GeneratePageList() { - PageList page_list; - for (RenderProcessHost::iterator it(RenderProcessHost::AllHostsIterator()); - !it.IsAtEnd(); it.Advance()) { - RenderProcessHost* render_process_host = it.GetCurrentValue(); - DCHECK(render_process_host); - - // Ignore processes that don't have a connection, such as crashed contents. - if (!render_process_host->HasConnection()) - continue; - - RenderProcessHost::RenderWidgetHostsIterator rwit( - render_process_host->GetRenderWidgetHostsIterator()); - for (; !rwit.IsAtEnd(); rwit.Advance()) { - const RenderWidgetHost* widget = rwit.GetCurrentValue(); - DCHECK(widget); - if (!widget || !widget->IsRenderView()) - continue; - - RenderViewHost* host = - RenderViewHost::From(const_cast(widget)); - page_list.push_back(CreatePageInfo(host)); - } - } - std::sort(page_list.begin(), page_list.end(), SortPageListByTime); - return page_list; -} - -std::string DevToolsHttpHandlerImpl::GetFrontendURLInternal( - const std::string rvh_id, - const std::string& host) { - return base::StringPrintf( - "%s%sws=%s/devtools/page/%s", - overridden_frontend_url_.c_str(), - overridden_frontend_url_.find("?") == std::string::npos ? "?" : "&", - host.c_str(), - rvh_id.c_str()); -} - -static bool ParseJsonPath( - const std::string& path, - std::string* command, - std::string* target_id) { - - // Fall back to list in case of empty query. - if (path.empty()) { - *command = "list"; - return true; - } - - if (path.find("/") != 0) { - // Malformed command. - return false; - } - *command = path.substr(1); - - size_t separator_pos = command->find("/"); - if (separator_pos != std::string::npos) { - *target_id = command->substr(separator_pos + 1); - *command = command->substr(0, separator_pos); - } - return true; -} - -void DevToolsHttpHandlerImpl::OnJsonRequestUI( - int connection_id, - const net::HttpServerRequestInfo& info) { - // Trim /json and ?jsonp=... - std::string path = info.path.substr(5); - std::string jsonp; - size_t jsonp_pos = path.find("?jsonp="); - if (jsonp_pos != std::string::npos) { - jsonp = path.substr(jsonp_pos + 7); - path = path.substr(0, jsonp_pos); - } - - // Trim fragment and query - size_t query_pos = path.find("?"); - if (query_pos != std::string::npos) - path = path.substr(0, query_pos); - - size_t fragment_pos = path.find("#"); - if (fragment_pos != std::string::npos) - path = path.substr(0, fragment_pos); - - std::string command; - std::string target_id; - if (!ParseJsonPath(path, &command, &target_id)) { - SendJson(connection_id, - net::HTTP_NOT_FOUND, - NULL, - "Malformed query: " + info.path, - jsonp); - return; - } - - if (command == "version") { - DictionaryValue version; - version.SetString("Protocol-Version", - WebKit::WebDevToolsAgent::inspectorProtocolVersion()); - version.SetString("WebKit-Version", - webkit_glue::GetWebKitVersion()); - version.SetString("User-Agent", - webkit_glue::GetUserAgent(GURL(chrome::kAboutBlankURL))); - SendJson(connection_id, net::HTTP_OK, &version, "", jsonp); - return; - } - - if (command == "list") { - PageList page_list = GeneratePageList(); - ListValue json_pages_list; - std::string host = info.headers["Host"]; - for (PageList::iterator i = page_list.begin(); i != page_list.end(); ++i) - json_pages_list.Append(SerializePageInfo(*i, host)); - SendJson(connection_id, net::HTTP_OK, &json_pages_list, "", jsonp); - return; - } - - if (command == "new") { - RenderViewHost* rvh = delegate_->CreateNewTarget(); - if (!rvh) { - SendJson(connection_id, - net::HTTP_INTERNAL_SERVER_ERROR, - NULL, - "Could not create new page", - jsonp); - return; - } - PageInfo page_info = CreatePageInfo(rvh); - std::string host = info.headers["Host"]; - scoped_ptr dictionary(SerializePageInfo(page_info, host)); - SendJson(connection_id, net::HTTP_OK, dictionary.get(), "", jsonp); - return; - } - - if (command == "activate" || command == "close") { - RenderViewHost* rvh = binding_->ForIdentifier(target_id); - if (!rvh) { - SendJson(connection_id, - net::HTTP_NOT_FOUND, - NULL, - "No such target id: " + target_id, - jsonp); - return; - } - - if (command == "activate") { - rvh->GetDelegate()->Activate(); - SendJson(connection_id, net::HTTP_OK, NULL, "Target activated", jsonp); - return; - } - - if (command == "close") { - rvh->ClosePage(); - SendJson(connection_id, net::HTTP_OK, NULL, "Target is closing", jsonp); - return; - } - } - SendJson(connection_id, - net::HTTP_NOT_FOUND, - NULL, - "Unknown command: " + command, - jsonp); - return; -} - -void DevToolsHttpHandlerImpl::OnThumbnailRequestUI( - int connection_id, - const net::HttpServerRequestInfo& info) { - std::string prefix = "/thumb/"; - size_t pos = info.path.find(prefix); - if (pos != 0) { - Send404(connection_id); - return; - } - - std::string page_url = info.path.substr(prefix.length()); - std::string data = delegate_->GetPageThumbnailData(GURL(page_url)); - if (!data.empty()) - Send200(connection_id, data, "image/png"); - else - Send404(connection_id); -} - -void DevToolsHttpHandlerImpl::OnDiscoveryPageRequestUI(int connection_id) { - std::string response = delegate_->GetDiscoveryPageHTML(); - Send200(connection_id, response, "text/html; charset=UTF-8"); -} - -void DevToolsHttpHandlerImpl::OnWebSocketRequestUI( - int connection_id, - const net::HttpServerRequestInfo& request) { - if (!thread_.get()) - return; - std::string browser_prefix = "/devtools/browser"; - size_t browser_pos = request.path.find(browser_prefix); - if (browser_pos == 0) { - if (browser_target_) { - Send500(connection_id, "Another client already attached"); - return; - } - browser_target_.reset(new DevToolsBrowserTarget(connection_id)); - browser_target_->RegisterHandler(new DevToolsTracingHandler()); - AcceptWebSocket(connection_id, request); - return; - } - - std::string page_prefix = "/devtools/page/"; - size_t pos = request.path.find(page_prefix); - if (pos != 0) { - Send404(connection_id); - return; - } - - std::string page_id = request.path.substr(page_prefix.length()); - RenderViewHost* rvh = binding_->ForIdentifier(page_id); - if (!rvh) { - Send500(connection_id, "No such target id: " + page_id); - return; - } - - DevToolsManager* manager = DevToolsManager::GetInstance(); - DevToolsAgentHost* agent = DevToolsAgentHostRegistry::GetDevToolsAgentHost( - rvh); - if (manager->GetDevToolsClientHostFor(agent)) { - Send500(connection_id, - "Target with given id is being inspected: " + page_id); - return; - } - - DevToolsClientHostImpl* client_host = - new DevToolsClientHostImpl(thread_->message_loop(), - server_, - connection_id); - connection_to_client_host_ui_[connection_id] = client_host; - - manager->RegisterDevToolsClientHostFor(agent, client_host); - - AcceptWebSocket(connection_id, request); -} - -void DevToolsHttpHandlerImpl::OnWebSocketMessageUI( - int connection_id, - const std::string& data) { - if (browser_target_ && connection_id == browser_target_->connection_id()) { - std::string json_response = browser_target_->HandleMessage(data); - - thread_->message_loop()->PostTask( - FROM_HERE, - base::Bind(&net::HttpServer::SendOverWebSocket, - server_.get(), - connection_id, - json_response)); - return; - } - - ConnectionToClientHostMap::iterator it = - connection_to_client_host_ui_.find(connection_id); - if (it == connection_to_client_host_ui_.end()) - return; - - DevToolsManager* manager = DevToolsManager::GetInstance(); - manager->DispatchOnInspectorBackend(it->second, data); -} - -void DevToolsHttpHandlerImpl::OnCloseUI(int connection_id) { - ConnectionToClientHostMap::iterator it = - connection_to_client_host_ui_.find(connection_id); - if (it != connection_to_client_host_ui_.end()) { - DevToolsClientHostImpl* client_host = - static_cast(it->second); - DevToolsManager::GetInstance()->ClientHostClosing(client_host); - delete client_host; - connection_to_client_host_ui_.erase(connection_id); - } - if (browser_target_ && browser_target_->connection_id() == connection_id) { - browser_target_.reset(); - return; - } -} - -DevToolsHttpHandlerImpl::DevToolsHttpHandlerImpl( - const net::StreamListenSocketFactory* socket_factory, - const std::string& frontend_url, - DevToolsHttpHandlerDelegate* delegate) - : overridden_frontend_url_(frontend_url), - socket_factory_(socket_factory), - delegate_(delegate) { - if (overridden_frontend_url_.empty()) - overridden_frontend_url_ = "/devtools/devtools.html"; - - default_binding_.reset(new DevToolsDefaultBindingHandler); - binding_ = default_binding_.get(); - - registrar_.Add(this, NOTIFICATION_RENDERER_PROCESS_TERMINATED, - NotificationService::AllBrowserContextsAndSources()); - registrar_.Add(this, NOTIFICATION_RENDERER_PROCESS_CLOSED, - NotificationService::AllBrowserContextsAndSources()); - - // Balanced in ResetHandlerThreadAndRelease(). - AddRef(); -} - -// Runs on the handler thread -void DevToolsHttpHandlerImpl::Init() { - server_ = new net::HttpServer(*socket_factory_.get(), this); -} - -// Runs on the handler thread -void DevToolsHttpHandlerImpl::Teardown() { - server_ = NULL; -} - -// Runs on FILE thread to make sure that it is serialized against -// {Start|Stop}HandlerThread and to allow calling pthread_join. -void DevToolsHttpHandlerImpl::StopHandlerThread() { - if (!thread_->message_loop()) - return; - thread_->message_loop()->PostTask( - FROM_HERE, - base::Bind(&DevToolsHttpHandlerImpl::Teardown, this)); - // Thread::Stop joins the thread. - thread_->Stop(); -} - -void DevToolsHttpHandlerImpl::SendJson(int connection_id, - net::HttpStatusCode status_code, - Value* value, - const std::string& message, - const std::string& jsonp) { - if (!thread_.get()) - return; - - // Serialize value and message. - std::string json_value; - if (value) { - base::JSONWriter::WriteWithOptions(value, - base::JSONWriter::OPTIONS_PRETTY_PRINT, - &json_value); - } - std::string json_message; - scoped_ptr message_object(Value::CreateStringValue(message)); - base::JSONWriter::Write(message_object.get(), &json_message); - - std::string response; - std::string mime_type = "application/json; charset=UTF-8"; - - // Wrap jsonp if necessary. - if (!jsonp.empty()) { - mime_type = "text/javascript; charset=UTF-8"; - response = StringPrintf("%s(%s, %d, %s);", - jsonp.c_str(), - json_value.empty() ? "undefined" - : json_value.c_str(), - status_code, - json_message.c_str()); - // JSONP always returns 200. - status_code = net::HTTP_OK; - } else { - response = StringPrintf("%s%s", json_value.c_str(), message.c_str()); - } - - thread_->message_loop()->PostTask( - FROM_HERE, - base::Bind(&net::HttpServer::Send, - server_.get(), - connection_id, - status_code, - response, - mime_type)); -} - -void DevToolsHttpHandlerImpl::Send200(int connection_id, - const std::string& data, - const std::string& mime_type) { - if (!thread_.get()) - return; - thread_->message_loop()->PostTask( - FROM_HERE, - base::Bind(&net::HttpServer::Send200, - server_.get(), - connection_id, - data, - mime_type)); -} - -void DevToolsHttpHandlerImpl::Send404(int connection_id) { - if (!thread_.get()) - return; - thread_->message_loop()->PostTask( - FROM_HERE, - base::Bind(&net::HttpServer::Send404, server_.get(), connection_id)); -} - -void DevToolsHttpHandlerImpl::Send500(int connection_id, - const std::string& message) { - if (!thread_.get()) - return; - thread_->message_loop()->PostTask( - FROM_HERE, - base::Bind(&net::HttpServer::Send500, server_.get(), connection_id, - message)); -} - -void DevToolsHttpHandlerImpl::AcceptWebSocket( - int connection_id, - const net::HttpServerRequestInfo& request) { - if (!thread_.get()) - return; - thread_->message_loop()->PostTask( - FROM_HERE, - base::Bind(&net::HttpServer::AcceptWebSocket, server_.get(), - connection_id, request)); -} - -DevToolsHttpHandlerImpl::PageInfo -DevToolsHttpHandlerImpl::CreatePageInfo(RenderViewHost* rvh) -{ - RenderViewHostDelegate* host_delegate = rvh->GetDelegate(); - DevToolsAgentHost* agent = - DevToolsAgentHostRegistry::GetDevToolsAgentHost(rvh); - DevToolsClientHost* client_host = DevToolsManager::GetInstance()-> - GetDevToolsClientHostFor(agent); - PageInfo page_info; - page_info.id = binding_->GetIdentifier(rvh); - page_info.attached = client_host != NULL; - page_info.url = host_delegate->GetURL().spec(); - - WebContents* web_contents = host_delegate->GetAsWebContents(); - if (web_contents) { - page_info.title = UTF16ToUTF8( - net::EscapeForHTML(web_contents->GetTitle())); - page_info.last_selected_time = web_contents->GetLastSelectedTime(); - - NavigationController& controller = web_contents->GetController(); - NavigationEntry* entry = controller.GetActiveEntry(); - if (entry != NULL && entry->GetURL().is_valid()) { - page_info.thumbnail_url = "/thumb/" + entry->GetURL().spec(); - page_info.favicon_url = entry->GetFavicon().url.spec(); - } - } - return page_info; -} - -DictionaryValue* DevToolsHttpHandlerImpl::SerializePageInfo( - const PageInfo& page_info, - const std::string& host) { - DictionaryValue* dictionary = new DictionaryValue; - dictionary->SetString("title", page_info.title); - dictionary->SetString("url", page_info.url); - dictionary->SetString("thumbnailUrl", page_info.thumbnail_url); - dictionary->SetString("faviconUrl", page_info.favicon_url); - if (!page_info.attached) { - dictionary->SetString("webSocketDebuggerUrl", - base::StringPrintf("ws://%s/devtools/page/%s", - host.c_str(), - page_info.id.c_str())); - std::string devtools_frontend_url = GetFrontendURLInternal( - page_info.id.c_str(), - host); - dictionary->SetString("devtoolsFrontendUrl", devtools_frontend_url); - } - return dictionary; -} - -} // namespace content diff --git a/content/browser/debugger/devtools_http_handler_impl.h b/content/browser/debugger/devtools_http_handler_impl.h deleted file mode 100644 index ef36be8..0000000 --- a/content/browser/debugger/devtools_http_handler_impl.h +++ /dev/null @@ -1,143 +0,0 @@ -// Copyright (c) 2012 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 CONTENT_BROWSER_DEBUGGER_DEVTOOLS_HTTP_HANDLER_IMPL_H_ -#define CONTENT_BROWSER_DEBUGGER_DEVTOOLS_HTTP_HANDLER_IMPL_H_ - -#include -#include -#include -#include - -#include "base/memory/ref_counted.h" -#include "base/memory/scoped_ptr.h" -#include "content/common/content_export.h" -#include "content/public/browser/devtools_http_handler.h" -#include "content/public/browser/devtools_http_handler_delegate.h" -#include "content/public/browser/notification_observer.h" -#include "content/public/browser/notification_registrar.h" -#include "net/server/http_server.h" - -namespace base { -class DictionaryValue; -class Thread; -class Value; -} - -namespace net { -class StreamListenSocketFactory; -class URLRequestContextGetter; -} - -namespace content { - -class DevToolsBrowserTarget; -class DevToolsClientHost; -class RenderViewHost; - -class DevToolsHttpHandlerImpl - : public DevToolsHttpHandler, - public NotificationObserver, - public base::RefCountedThreadSafe, - public net::HttpServer::Delegate { - private: - struct PageInfo; - typedef std::vector PageList; - friend class base::RefCountedThreadSafe; - friend class DevToolsHttpHandler; - - static bool SortPageListByTime(const PageInfo& info1, const PageInfo& info2); - - // Takes ownership over |socket_factory|. - DevToolsHttpHandlerImpl(const net::StreamListenSocketFactory* socket_factory, - const std::string& frontend_url, - DevToolsHttpHandlerDelegate* delegate); - virtual ~DevToolsHttpHandlerImpl(); - void Start(); - - // DevToolsHttpHandler implementation. - virtual void Stop() OVERRIDE; - virtual void SetRenderViewHostBinding( - RenderViewHostBinding* binding) OVERRIDE; - virtual GURL GetFrontendURL(RenderViewHost* render_view_host) OVERRIDE; - - // NotificationObserver implementation. - virtual void Observe(int type, - const NotificationSource& source, - const NotificationDetails& details) OVERRIDE; - - // net::HttpServer::Delegate implementation. - virtual void OnHttpRequest(int connection_id, - const net::HttpServerRequestInfo& info) OVERRIDE; - virtual void OnWebSocketRequest( - int connection_id, - const net::HttpServerRequestInfo& info) OVERRIDE; - virtual void OnWebSocketMessage(int connection_id, - const std::string& data) OVERRIDE; - virtual void OnClose(int connection_id) OVERRIDE; - - void OnJsonRequestUI(int connection_id, - const net::HttpServerRequestInfo& info); - void OnThumbnailRequestUI(int connection_id, - const net::HttpServerRequestInfo& info); - void OnDiscoveryPageRequestUI(int connection_id); - - void OnWebSocketRequestUI(int connection_id, - const net::HttpServerRequestInfo& info); - void OnWebSocketMessageUI(int connection_id, const std::string& data); - void OnCloseUI(int connection_id); - - void ResetHandlerThread(); - void ResetHandlerThreadAndRelease(); - - void Init(); - void Teardown(); - - void StartHandlerThread(); - void StopHandlerThread(); - - void SendJson(int connection_id, - net::HttpStatusCode status_code, - base::Value* value, - const std::string& message, - const std::string& jsonp); - void Send200(int connection_id, - const std::string& data, - const std::string& mime_type); - void Send404(int connection_id); - void Send500(int connection_id, - const std::string& message); - void AcceptWebSocket(int connection_id, - const net::HttpServerRequestInfo& request); - - PageList GeneratePageList(); - - // Returns the front end url without the host at the beginning. - std::string GetFrontendURLInternal(const std::string rvh_id, - const std::string& host); - - PageInfo CreatePageInfo(RenderViewHost* rvh); - - base::DictionaryValue* SerializePageInfo(const PageInfo& page_info, - const std::string& host); - - // The thread used by the devtools handler to run server socket. - scoped_ptr thread_; - - std::string overridden_frontend_url_; - scoped_ptr socket_factory_; - scoped_refptr server_; - typedef std::map ConnectionToClientHostMap; - ConnectionToClientHostMap connection_to_client_host_ui_; - scoped_ptr delegate_; - RenderViewHostBinding* binding_; - scoped_ptr default_binding_; - NotificationRegistrar registrar_; - scoped_ptr browser_target_; - DISALLOW_COPY_AND_ASSIGN(DevToolsHttpHandlerImpl); -}; - -} // namespace content - -#endif // CONTENT_BROWSER_DEBUGGER_DEVTOOLS_HTTP_HANDLER_IMPL_H_ diff --git a/content/browser/debugger/devtools_http_handler_unittest.cc b/content/browser/debugger/devtools_http_handler_unittest.cc deleted file mode 100644 index b01c9d9..0000000 --- a/content/browser/debugger/devtools_http_handler_unittest.cc +++ /dev/null @@ -1,103 +0,0 @@ -// Copyright (c) 2012 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 "base/message_loop.h" -#include "base/run_loop.h" -#include "content/browser/browser_thread_impl.h" -#include "content/public/browser/devtools_http_handler.h" -#include "content/public/browser/devtools_http_handler_delegate.h" -#include "net/base/stream_listen_socket.h" -#include "testing/gtest/include/gtest/gtest.h" - -namespace content { -namespace { - -using net::StreamListenSocket; - -class DummyListenSocket : public StreamListenSocket, - public StreamListenSocket::Delegate { - public: - DummyListenSocket() - : ALLOW_THIS_IN_INITIALIZER_LIST(StreamListenSocket(0, this)) {} - - // StreamListenSocket::Delegate "implementation" - virtual void DidAccept(StreamListenSocket* server, - StreamListenSocket* connection) OVERRIDE {} - virtual void DidRead(StreamListenSocket* connection, - const char* data, - int len) OVERRIDE {} - virtual void DidClose(StreamListenSocket* sock) OVERRIDE {} - protected: - virtual ~DummyListenSocket() {} - virtual void Accept() OVERRIDE {} -}; - -class DummyListenSocketFactory : public net::StreamListenSocketFactory { - public: - DummyListenSocketFactory( - base::Closure quit_closure_1, base::Closure quit_closure_2) - : quit_closure_1_(quit_closure_1), quit_closure_2_(quit_closure_2) {} - virtual ~DummyListenSocketFactory() { - BrowserThread::PostTask( - BrowserThread::UI, FROM_HERE, quit_closure_2_); - } - - virtual scoped_refptr CreateAndListen( - StreamListenSocket::Delegate* delegate) const OVERRIDE { - BrowserThread::PostTask( - BrowserThread::UI, FROM_HERE, quit_closure_1_); - return new DummyListenSocket(); - } - private: - base::Closure quit_closure_1_; - base::Closure quit_closure_2_; -}; - -class DummyDelegate : public DevToolsHttpHandlerDelegate { - public: - virtual std::string GetDiscoveryPageHTML() OVERRIDE { return ""; } - virtual bool BundlesFrontendResources() OVERRIDE { return true; } - virtual FilePath GetDebugFrontendDir() OVERRIDE { return FilePath(); } - virtual std::string GetPageThumbnailData(const GURL& url) { return ""; } - virtual RenderViewHost* CreateNewTarget() { return NULL; } -}; - -} - -class DevToolsHttpHandlerTest : public testing::Test { - public: - DevToolsHttpHandlerTest() - : ui_thread_(BrowserThread::UI, &message_loop_) { - } - protected: - virtual void SetUp() { - file_thread_.reset(new BrowserThreadImpl(BrowserThread::FILE)); - file_thread_->Start(); - } - virtual void TearDown() { - file_thread_->Stop(); - } - private: - MessageLoopForIO message_loop_; - BrowserThreadImpl ui_thread_; - scoped_ptr file_thread_; -}; - -TEST_F(DevToolsHttpHandlerTest, TestStartStop) { - base::RunLoop run_loop, run_loop_2; - content::DevToolsHttpHandler* devtools_http_handler_ = - content::DevToolsHttpHandler::Start( - new DummyListenSocketFactory( - run_loop.QuitClosure(), run_loop_2.QuitClosure()), - "", - new DummyDelegate()); - // Our dummy socket factory will post a quit message once the server will - // become ready. - run_loop.Run(); - devtools_http_handler_->Stop(); - // Make sure the handler actually stops. - run_loop_2.Run(); -} - -} // namespace content diff --git a/content/browser/debugger/devtools_manager_impl.cc b/content/browser/debugger/devtools_manager_impl.cc deleted file mode 100644 index 92158e2..0000000 --- a/content/browser/debugger/devtools_manager_impl.cc +++ /dev/null @@ -1,302 +0,0 @@ -// Copyright (c) 2012 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 "content/browser/debugger/devtools_manager_impl.h" - -#include - -#include "base/bind.h" -#include "base/message_loop.h" -#include "content/browser/child_process_security_policy_impl.h" -#include "content/browser/debugger/devtools_netlog_observer.h" -#include "content/browser/debugger/render_view_devtools_agent_host.h" -#include "content/browser/renderer_host/render_view_host_impl.h" -#include "content/browser/web_contents/web_contents_impl.h" -#include "content/public/browser/browser_thread.h" -#include "content/public/browser/devtools_client_host.h" -#include "content/public/browser/devtools_agent_host_registry.h" -#include "googleurl/src/gurl.h" - -namespace content { - -// static -DevToolsManager* DevToolsManager::GetInstance() { - return DevToolsManagerImpl::GetInstance(); -} - -// static -DevToolsManagerImpl* DevToolsManagerImpl::GetInstance() { - return Singleton::get(); -} - -DevToolsManagerImpl::DevToolsManagerImpl() - : last_orphan_cookie_(0) { -} - -DevToolsManagerImpl::~DevToolsManagerImpl() { - DCHECK(agent_to_client_host_.empty()); - DCHECK(client_to_agent_host_.empty()); - // By the time we destroy devtools manager, all orphan client hosts should - // have been deleted; no need to notify them upon contents closing. - DCHECK(orphan_client_hosts_.empty()); -} - -DevToolsClientHost* DevToolsManagerImpl::GetDevToolsClientHostFor( - DevToolsAgentHost* agent_host) { - AgentToClientHostMap::iterator it = agent_to_client_host_.find(agent_host); - if (it != agent_to_client_host_.end()) - return it->second; - return NULL; -} - -DevToolsAgentHost* DevToolsManagerImpl::GetDevToolsAgentHostFor( - DevToolsClientHost* client_host) { - ClientToAgentHostMap::iterator it = client_to_agent_host_.find(client_host); - if (it != client_to_agent_host_.end()) - return it->second; - return NULL; -} - -void DevToolsManagerImpl::RegisterDevToolsClientHostFor( - DevToolsAgentHost* agent_host, - DevToolsClientHost* client_host) { - BindClientHost(agent_host, client_host); - agent_host->Attach(); -} - -bool DevToolsManagerImpl::DispatchOnInspectorBackend( - DevToolsClientHost* from, - const std::string& message) { - DevToolsAgentHost* agent_host = GetDevToolsAgentHostFor(from); - if (!agent_host) - return false; - - agent_host->DipatchOnInspectorBackend(message); - return true; -} - -void DevToolsManagerImpl::DispatchOnInspectorFrontend( - DevToolsAgentHost* agent_host, - const std::string& message) { - DevToolsClientHost* client_host = GetDevToolsClientHostFor(agent_host); - if (!client_host) { - // Client window was closed while there were messages - // being sent to it. - return; - } - client_host->DispatchOnInspectorFrontend(message); -} - -void DevToolsManagerImpl::SaveAgentRuntimeState(DevToolsAgentHost* agent_host, - const std::string& state) { - agent_runtime_states_[agent_host] = state; -} - -void DevToolsManagerImpl::InspectElement(DevToolsAgentHost* agent_host, - int x, int y) { - agent_host->InspectElement(x, y); -} - -void DevToolsManagerImpl::AddMessageToConsole(DevToolsAgentHost* agent_host, - ConsoleMessageLevel level, - const std::string& message) { - agent_host->AddMessageToConsole(level, message); -} - -void DevToolsManagerImpl::ClientHostClosing(DevToolsClientHost* client_host) { - DevToolsAgentHost* agent_host = GetDevToolsAgentHostFor(client_host); - if (!agent_host) { - // It might be in the list of orphan client hosts, remove it from there. - for (OrphanClientHosts::iterator it = orphan_client_hosts_.begin(); - it != orphan_client_hosts_.end(); ++it) { - if (it->second.first == client_host) { - orphan_client_hosts_.erase(it->first); - return; - } - } - return; - } - - UnbindClientHost(agent_host, client_host); -} - -void DevToolsManagerImpl::AgentHostClosing(DevToolsAgentHost* agent_host) { - UnregisterDevToolsClientHostFor(agent_host); -} - -void DevToolsManagerImpl::UnregisterDevToolsClientHostFor( - DevToolsAgentHost* agent_host) { - DevToolsClientHost* client_host = GetDevToolsClientHostFor(agent_host); - if (!client_host) - return; - UnbindClientHost(agent_host, client_host); - client_host->InspectedContentsClosing(); -} - -void DevToolsManagerImpl::OnNavigatingToPendingEntry( - RenderViewHost* rvh, - RenderViewHost* dest_rvh, - const GURL& gurl) { - if (rvh == dest_rvh && static_cast( - rvh)->render_view_termination_status() == - base::TERMINATION_STATUS_STILL_RUNNING) - return; - int cookie = DetachClientHost(rvh); - if (cookie != -1) { - // Navigating to URL in the inspected window. - AttachClientHost(cookie, dest_rvh); - - DevToolsAgentHost* dest_agent_host = - DevToolsAgentHostRegistry::GetDevToolsAgentHost(dest_rvh); - DevToolsClientHost* client_host = GetDevToolsClientHostFor( - dest_agent_host); - client_host->FrameNavigating(gurl.spec()); - } -} - -void DevToolsManagerImpl::OnCancelPendingNavigation( - RenderViewHost* pending, - RenderViewHost* current) { - int cookie = DetachClientHost(pending); - if (cookie != -1) { - // Navigating to URL in the inspected window. - AttachClientHost(cookie, current); - } -} - -void DevToolsManagerImpl::ContentsReplaced(WebContents* old_contents, - WebContents* new_contents) { - RenderViewHost* old_rvh = old_contents->GetRenderViewHost(); - if (!DevToolsAgentHostRegistry::HasDevToolsAgentHost(old_rvh)) - return; - - DevToolsAgentHost* old_agent_host = - DevToolsAgentHostRegistry::GetDevToolsAgentHost(old_rvh); - DevToolsClientHost* client_host = GetDevToolsClientHostFor(old_agent_host); - if (!client_host) - return; // Didn't know about old_contents. - int cookie = DetachClientHost(old_rvh); - if (cookie == -1) - return; // Didn't know about old_contents. - - client_host->ContentsReplaced(new_contents); - AttachClientHost(cookie, new_contents->GetRenderViewHost()); -} - -int DevToolsManagerImpl::DetachClientHost(RenderViewHost* from_rvh) { - DevToolsAgentHost* agent_host = - DevToolsAgentHostRegistry::GetDevToolsAgentHost(from_rvh); - return DetachClientHost(agent_host); -} - -int DevToolsManagerImpl::DetachClientHost(DevToolsAgentHost* agent_host) { - DevToolsClientHost* client_host = GetDevToolsClientHostFor(agent_host); - if (!client_host) - return -1; - - int cookie = last_orphan_cookie_++; - orphan_client_hosts_[cookie] = - std::pair( - client_host, agent_runtime_states_[agent_host]); - - UnbindClientHost(agent_host, client_host); - return cookie; -} - -void DevToolsManagerImpl::AttachClientHost(int client_host_cookie, - RenderViewHost* to_rvh) { - DevToolsAgentHost* agent_host = - DevToolsAgentHostRegistry::GetDevToolsAgentHost(to_rvh); - AttachClientHost(client_host_cookie, agent_host); -} - -void DevToolsManagerImpl::AttachClientHost(int client_host_cookie, - DevToolsAgentHost* agent_host) { - OrphanClientHosts::iterator it = orphan_client_hosts_.find( - client_host_cookie); - if (it == orphan_client_hosts_.end()) - return; - - DevToolsClientHost* client_host = (*it).second.first; - const std::string& state = (*it).second.second; - BindClientHost(agent_host, client_host); - agent_host->Reattach(state); - agent_runtime_states_[agent_host] = state; - - orphan_client_hosts_.erase(it); -} - -void DevToolsManagerImpl::BindClientHost( - DevToolsAgentHost* agent_host, - DevToolsClientHost* client_host) { - DCHECK(agent_to_client_host_.find(agent_host) == - agent_to_client_host_.end()); - DCHECK(client_to_agent_host_.find(client_host) == - client_to_agent_host_.end()); - - if (client_to_agent_host_.empty()) { - BrowserThread::PostTask( - BrowserThread::IO, - FROM_HERE, - base::Bind(&DevToolsNetLogObserver::Attach)); - } - agent_to_client_host_[agent_host] = client_host; - client_to_agent_host_[client_host] = agent_host; - agent_host->set_close_listener(this); - - int process_id = agent_host->GetRenderProcessId(); - if (process_id != -1) - ChildProcessSecurityPolicyImpl::GetInstance()->GrantReadRawCookies( - process_id); -} - -void DevToolsManagerImpl::UnbindClientHost(DevToolsAgentHost* agent_host, - DevToolsClientHost* client_host) { - DCHECK(agent_host); - DCHECK(agent_to_client_host_.find(agent_host)->second == - client_host); - DCHECK(client_to_agent_host_.find(client_host)->second == - agent_host); - agent_host->set_close_listener(NULL); - - agent_to_client_host_.erase(agent_host); - client_to_agent_host_.erase(client_host); - agent_runtime_states_.erase(agent_host); - - if (client_to_agent_host_.empty()) { - BrowserThread::PostTask( - BrowserThread::IO, - FROM_HERE, - base::Bind(&DevToolsNetLogObserver::Detach)); - } - agent_host->Detach(); - - int process_id = agent_host->GetRenderProcessId(); - if (process_id == -1) - return; - for (AgentToClientHostMap::iterator it = agent_to_client_host_.begin(); - it != agent_to_client_host_.end(); - ++it) { - if (it->first->GetRenderProcessId() == process_id) - return; - } - // We've disconnected from the last renderer -> revoke cookie permissions. - ChildProcessSecurityPolicyImpl::GetInstance()->RevokeReadRawCookies( - process_id); -} - -void DevToolsManagerImpl::CloseAllClientHosts() { - std::vector agents; - for (AgentToClientHostMap::iterator it = - agent_to_client_host_.begin(); - it != agent_to_client_host_.end(); ++it) { - agents.push_back(it->first); - } - for (std::vector::iterator it = agents.begin(); - it != agents.end(); ++it) { - UnregisterDevToolsClientHostFor(*it); - } -} - -} // namespace content diff --git a/content/browser/debugger/devtools_manager_impl.h b/content/browser/debugger/devtools_manager_impl.h deleted file mode 100644 index 2df870e..0000000 --- a/content/browser/debugger/devtools_manager_impl.h +++ /dev/null @@ -1,131 +0,0 @@ -// Copyright (c) 2012 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 CONTENT_BROWSER_DEBUGGER_DEVTOOLS_MANAGER_IMPL_H_ -#define CONTENT_BROWSER_DEBUGGER_DEVTOOLS_MANAGER_IMPL_H_ - -#include -#include - -#include "base/compiler_specific.h" -#include "base/memory/singleton.h" -#include "content/browser/debugger/devtools_agent_host.h" -#include "content/common/content_export.h" -#include "content/public/browser/devtools_client_host.h" -#include "content/public/browser/devtools_manager.h" - -class GURL; - -namespace IPC { -class Message; -} - -namespace content { - -class DevToolsAgentHost; -class RenderViewHost; - -// This class is a singleton that manages DevToolsClientHost instances and -// routes messages between developer tools clients and agents. -// -// Methods below that accept inspected RenderViewHost as a parameter are -// just convenience methods that call corresponding methods accepting -// DevToolAgentHost. -class CONTENT_EXPORT DevToolsManagerImpl - : public DevToolsAgentHost::CloseListener, - public DevToolsManager { - public: - // Returns single instance of this class. The instance is destroyed on the - // browser main loop exit so this method MUST NOT be called after that point. - static DevToolsManagerImpl* GetInstance(); - - DevToolsManagerImpl(); - virtual ~DevToolsManagerImpl(); - - void DispatchOnInspectorFrontend(DevToolsAgentHost* agent_host, - const std::string& message); - - void SaveAgentRuntimeState(DevToolsAgentHost* agent_host, - const std::string& state); - - // Sends 'Attach' message to the agent using |dest_rvh| in case - // there is a DevToolsClientHost registered for the |inspected_rvh|. - void OnNavigatingToPendingEntry(RenderViewHost* inspected_rvh, - RenderViewHost* dest_rvh, - const GURL& gurl); - void OnCancelPendingNavigation(RenderViewHost* pending, - RenderViewHost* current); - - // DevToolsManager implementation - virtual bool DispatchOnInspectorBackend(DevToolsClientHost* from, - const std::string& message) OVERRIDE; - virtual void ContentsReplaced(WebContents* old_contents, - WebContents* new_contents) OVERRIDE; - virtual void CloseAllClientHosts() OVERRIDE; - virtual void AttachClientHost(int client_host_cookie, - DevToolsAgentHost* to_agent) OVERRIDE; - virtual DevToolsClientHost* GetDevToolsClientHostFor( - DevToolsAgentHost* agent_host) OVERRIDE; - virtual DevToolsAgentHost* GetDevToolsAgentHostFor( - DevToolsClientHost* client_host) OVERRIDE; - virtual void RegisterDevToolsClientHostFor( - DevToolsAgentHost* agent_host, - DevToolsClientHost* client_host) OVERRIDE; - virtual void UnregisterDevToolsClientHostFor( - DevToolsAgentHost* agent_host) OVERRIDE; - virtual int DetachClientHost(DevToolsAgentHost* from_agent) OVERRIDE; - virtual void ClientHostClosing(DevToolsClientHost* host) OVERRIDE; - virtual void InspectElement(DevToolsAgentHost* agent_host, - int x, int y) OVERRIDE; - virtual void AddMessageToConsole(DevToolsAgentHost* agent_host, - ConsoleMessageLevel level, - const std::string& message) OVERRIDE; - - private: - friend struct DefaultSingletonTraits; - - // DevToolsAgentHost::CloseListener implementation. - virtual void AgentHostClosing(DevToolsAgentHost* host) OVERRIDE; - - void BindClientHost(DevToolsAgentHost* agent_host, - DevToolsClientHost* client_host); - void UnbindClientHost(DevToolsAgentHost* agent_host, - DevToolsClientHost* client_host); - - // Detaches client host and returns cookie that can be used in - // AttachClientHost. - int DetachClientHost(RenderViewHost* from_rvh); - - // Attaches orphan client host to new render view host. - void AttachClientHost(int client_host_cookie, - RenderViewHost* to_rvh); - - // These two maps are for tracking dependencies between inspected contents and - // their DevToolsClientHosts. They are useful for routing devtools messages - // and allow us to have at most one devtools client host per contents. - // - // DevToolsManagerImpl starts listening to DevToolsClientHosts when they are - // put into these maps and removes them when they are closing. - typedef std::map - AgentToClientHostMap; - AgentToClientHostMap agent_to_client_host_; - - typedef std::map - ClientToAgentHostMap; - ClientToAgentHostMap client_to_agent_host_; - - typedef std::map AgentRuntimeStates; - AgentRuntimeStates agent_runtime_states_; - - typedef std::map > - OrphanClientHosts; - OrphanClientHosts orphan_client_hosts_; - int last_orphan_cookie_; - - DISALLOW_COPY_AND_ASSIGN(DevToolsManagerImpl); -}; - -} // namespace content - -#endif // CONTENT_BROWSER_DEBUGGER_DEVTOOLS_MANAGER_IMPL_H_ diff --git a/content/browser/debugger/devtools_manager_unittest.cc b/content/browser/debugger/devtools_manager_unittest.cc deleted file mode 100644 index 7b6bc6d..0000000 --- a/content/browser/debugger/devtools_manager_unittest.cc +++ /dev/null @@ -1,243 +0,0 @@ -// Copyright (c) 2012 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 "base/basictypes.h" -#include "base/time.h" -#include "content/browser/debugger/devtools_manager_impl.h" -#include "content/browser/debugger/render_view_devtools_agent_host.h" -#include "content/browser/renderer_host/test_render_view_host.h" -#include "content/browser/web_contents/test_web_contents.h" -#include "content/common/view_messages.h" -#include "content/public/browser/content_browser_client.h" -#include "content/public/browser/devtools_agent_host_registry.h" -#include "content/public/browser/devtools_client_host.h" -#include "content/public/browser/web_contents_delegate.h" -#include "content/test/test_content_browser_client.h" -#include "testing/gtest/include/gtest/gtest.h" - -using base::TimeDelta; - -namespace content { -namespace { - -class TestDevToolsClientHost : public DevToolsClientHost { - public: - TestDevToolsClientHost() - : last_sent_message(NULL), - closed_(false) { - } - - virtual ~TestDevToolsClientHost() { - EXPECT_TRUE(closed_); - } - - virtual void Close(DevToolsManager* manager) { - EXPECT_FALSE(closed_); - close_counter++; - manager->ClientHostClosing(this); - closed_ = true; - } - virtual void InspectedContentsClosing() { - FAIL(); - } - - virtual void DispatchOnInspectorFrontend(const std::string& message) { - last_sent_message = &message; - } - - virtual void ContentsReplaced(WebContents* new_contents) { - } - - virtual void ReplacedWithAnotherClient() { - } - - static void ResetCounters() { - close_counter = 0; - } - - static int close_counter; - - const std::string* last_sent_message; - - private: - bool closed_; - - virtual void FrameNavigating(const std::string& url) {} - - DISALLOW_COPY_AND_ASSIGN(TestDevToolsClientHost); -}; - -int TestDevToolsClientHost::close_counter = 0; - - -class TestWebContentsDelegate : public WebContentsDelegate { - public: - TestWebContentsDelegate() : renderer_unresponsive_received_(false) {} - - // Notification that the contents is hung. - virtual void RendererUnresponsive(WebContents* source) { - renderer_unresponsive_received_ = true; - } - - bool renderer_unresponsive_received() const { - return renderer_unresponsive_received_; - } - - private: - bool renderer_unresponsive_received_; -}; - -class DevToolsManagerTestBrowserClient : public TestContentBrowserClient { - public: - DevToolsManagerTestBrowserClient() { - } - - virtual bool ShouldSwapProcessesForNavigation( - const GURL& current_url, - const GURL& new_url) OVERRIDE { - return true; - } - - private: - DISALLOW_COPY_AND_ASSIGN(DevToolsManagerTestBrowserClient); -}; - -} // namespace - -class DevToolsManagerTest : public RenderViewHostImplTestHarness { - public: - DevToolsManagerTest() { - } - - protected: - virtual void SetUp() OVERRIDE { - original_browser_client_ = GetContentClient()->browser(); - GetContentClient()->set_browser_for_testing(&browser_client_); - - RenderViewHostImplTestHarness::SetUp(); - TestDevToolsClientHost::ResetCounters(); - } - - virtual void TearDown() OVERRIDE { - RenderViewHostImplTestHarness::TearDown(); - GetContentClient()->set_browser_for_testing(original_browser_client_); - } - - private: - ContentBrowserClient* original_browser_client_; - DevToolsManagerTestBrowserClient browser_client_; -}; - -TEST_F(DevToolsManagerTest, OpenAndManuallyCloseDevToolsClientHost) { - DevToolsManagerImpl manager; - - DevToolsAgentHost* agent = - DevToolsAgentHostRegistry::GetDevToolsAgentHost(rvh()); - DevToolsClientHost* host = manager.GetDevToolsClientHostFor(agent); - EXPECT_TRUE(NULL == host); - - TestDevToolsClientHost client_host; - manager.RegisterDevToolsClientHostFor(agent, &client_host); - // Test that just registered devtools host is returned. - host = manager.GetDevToolsClientHostFor(agent); - EXPECT_TRUE(&client_host == host); - EXPECT_EQ(0, TestDevToolsClientHost::close_counter); - - // Test that the same devtools host is returned. - host = manager.GetDevToolsClientHostFor(agent); - EXPECT_TRUE(&client_host == host); - EXPECT_EQ(0, TestDevToolsClientHost::close_counter); - - client_host.Close(&manager); - EXPECT_EQ(1, TestDevToolsClientHost::close_counter); - host = manager.GetDevToolsClientHostFor(agent); - EXPECT_TRUE(NULL == host); -} - -TEST_F(DevToolsManagerTest, ForwardMessageToClient) { - DevToolsManagerImpl manager; - - TestDevToolsClientHost client_host; - DevToolsAgentHost* agent_host = - DevToolsAgentHostRegistry::GetDevToolsAgentHost(rvh()); - manager.RegisterDevToolsClientHostFor(agent_host, &client_host); - EXPECT_EQ(0, TestDevToolsClientHost::close_counter); - - std::string m = "test message"; - agent_host = DevToolsAgentHostRegistry::GetDevToolsAgentHost(rvh()); - manager.DispatchOnInspectorFrontend(agent_host, m); - EXPECT_TRUE(&m == client_host.last_sent_message); - - client_host.Close(&manager); - EXPECT_EQ(1, TestDevToolsClientHost::close_counter); -} - -TEST_F(DevToolsManagerTest, NoUnresponsiveDialogInInspectedContents) { - TestRenderViewHost* inspected_rvh = test_rvh(); - inspected_rvh->set_render_view_created(true); - EXPECT_FALSE(contents()->GetDelegate()); - TestWebContentsDelegate delegate; - contents()->SetDelegate(&delegate); - - TestDevToolsClientHost client_host; - DevToolsAgentHost* agent_host = - DevToolsAgentHostRegistry::GetDevToolsAgentHost(inspected_rvh); - DevToolsManager::GetInstance()-> - RegisterDevToolsClientHostFor(agent_host, &client_host); - - // Start with a short timeout. - inspected_rvh->StartHangMonitorTimeout(TimeDelta::FromMilliseconds(10)); - // Wait long enough for first timeout and see if it fired. - MessageLoop::current()->PostDelayedTask( - FROM_HERE, MessageLoop::QuitClosure(), TimeDelta::FromMilliseconds(10)); - MessageLoop::current()->Run(); - EXPECT_FALSE(delegate.renderer_unresponsive_received()); - - // Now close devtools and check that the notification is delivered. - client_host.Close(DevToolsManager::GetInstance()); - // Start with a short timeout. - inspected_rvh->StartHangMonitorTimeout(TimeDelta::FromMilliseconds(10)); - // Wait long enough for first timeout and see if it fired. - MessageLoop::current()->PostDelayedTask( - FROM_HERE, MessageLoop::QuitClosure(), TimeDelta::FromMilliseconds(10)); - MessageLoop::current()->Run(); - EXPECT_TRUE(delegate.renderer_unresponsive_received()); - - contents()->SetDelegate(NULL); -} - -TEST_F(DevToolsManagerTest, ReattachOnCancelPendingNavigation) { - contents()->transition_cross_site = true; - // Navigate to URL. First URL should use first RenderViewHost. - const GURL url("http://www.google.com"); - controller().LoadURL( - url, Referrer(), PAGE_TRANSITION_TYPED, std::string()); - contents()->TestDidNavigate(rvh(), 1, url, PAGE_TRANSITION_TYPED); - EXPECT_FALSE(contents()->cross_navigation_pending()); - - TestDevToolsClientHost client_host; - DevToolsManager* devtools_manager = DevToolsManager::GetInstance(); - devtools_manager->RegisterDevToolsClientHostFor( - DevToolsAgentHostRegistry::GetDevToolsAgentHost(rvh()), - &client_host); - - // Navigate to new site which should get a new RenderViewHost. - const GURL url2("http://www.yahoo.com"); - controller().LoadURL( - url2, Referrer(), PAGE_TRANSITION_TYPED, std::string()); - EXPECT_TRUE(contents()->cross_navigation_pending()); - EXPECT_EQ(&client_host, devtools_manager->GetDevToolsClientHostFor( - DevToolsAgentHostRegistry::GetDevToolsAgentHost(pending_rvh()))); - - // Interrupt pending navigation and navigate back to the original site. - controller().LoadURL( - url, Referrer(), PAGE_TRANSITION_TYPED, std::string()); - contents()->TestDidNavigate(rvh(), 1, url, PAGE_TRANSITION_TYPED); - EXPECT_FALSE(contents()->cross_navigation_pending()); - EXPECT_EQ(&client_host, devtools_manager->GetDevToolsClientHostFor( - DevToolsAgentHostRegistry::GetDevToolsAgentHost(rvh()))); - client_host.Close(DevToolsManager::GetInstance()); -} - -} // namespace content diff --git a/content/browser/debugger/devtools_netlog_observer.cc b/content/browser/debugger/devtools_netlog_observer.cc deleted file mode 100644 index fc02443..0000000 --- a/content/browser/debugger/devtools_netlog_observer.cc +++ /dev/null @@ -1,329 +0,0 @@ -// Copyright (c) 2012 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 "content/browser/debugger/devtools_netlog_observer.h" - -#include "base/string_tokenizer.h" -#include "base/string_util.h" -#include "base/values.h" -#include "content/public/browser/browser_thread.h" -#include "content/public/browser/content_browser_client.h" -#include "content/public/common/resource_response.h" -#include "net/base/load_flags.h" -#include "net/http/http_response_headers.h" -#include "net/http/http_util.h" -#include "net/spdy/spdy_header_block.h" -#include "net/url_request/url_request.h" -#include "net/url_request/url_request_netlog_params.h" -#include "webkit/glue/resource_loader_bridge.h" - -namespace content { -const size_t kMaxNumEntries = 1000; - -DevToolsNetLogObserver* DevToolsNetLogObserver::instance_ = NULL; - -DevToolsNetLogObserver::DevToolsNetLogObserver() { -} - -DevToolsNetLogObserver::~DevToolsNetLogObserver() { -} - -DevToolsNetLogObserver::ResourceInfo* -DevToolsNetLogObserver::GetResourceInfo(uint32 id) { - RequestToInfoMap::iterator it = request_to_info_.find(id); - if (it != request_to_info_.end()) - return it->second; - return NULL; -} - -void DevToolsNetLogObserver::OnAddEntry(const net::NetLog::Entry& entry) { - // The events that the Observer is interested in only occur on the IO thread. - if (!BrowserThread::CurrentlyOn(BrowserThread::IO)) - return; - - if (entry.source().type == net::NetLog::SOURCE_URL_REQUEST) - OnAddURLRequestEntry(entry); - else if (entry.source().type == net::NetLog::SOURCE_HTTP_STREAM_JOB) - OnAddHTTPStreamJobEntry(entry); - else if (entry.source().type == net::NetLog::SOURCE_SOCKET) - OnAddSocketEntry(entry); -} - -void DevToolsNetLogObserver::OnAddURLRequestEntry( - const net::NetLog::Entry& entry) { - DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); - - bool is_begin = entry.phase() == net::NetLog::PHASE_BEGIN; - bool is_end = entry.phase() == net::NetLog::PHASE_END; - - if (entry.type() == net::NetLog::TYPE_URL_REQUEST_START_JOB) { - if (is_begin) { - int load_flags; - scoped_ptr event_param(entry.ParametersToValue()); - if (!net::StartEventLoadFlagsFromEventParams(event_param.get(), - &load_flags)) { - return; - } - - if (!(load_flags & net::LOAD_REPORT_RAW_HEADERS)) - return; - - if (request_to_info_.size() > kMaxNumEntries) { - LOG(WARNING) << "The raw headers observer url request count has grown " - "larger than expected, resetting"; - request_to_info_.clear(); - } - - request_to_info_[entry.source().id] = new ResourceInfo(); - - if (request_to_encoded_data_length_.size() > kMaxNumEntries) { - LOG(WARNING) << "The encoded data length observer url request count " - "has grown larger than expected, resetting"; - request_to_encoded_data_length_.clear(); - } - - request_to_encoded_data_length_[entry.source().id] = 0; - } - return; - } else if (entry.type() == net::NetLog::TYPE_REQUEST_ALIVE) { - // Cleanup records based on the TYPE_REQUEST_ALIVE entry. - if (is_end) { - request_to_info_.erase(entry.source().id); - request_to_encoded_data_length_.erase(entry.source().id); - } - return; - } - - ResourceInfo* info = GetResourceInfo(entry.source().id); - if (!info) - return; - - switch (entry.type()) { - case net::NetLog::TYPE_HTTP_TRANSACTION_SEND_REQUEST_HEADERS: { - scoped_ptr event_params(entry.ParametersToValue()); - std::string request_line; - net::HttpRequestHeaders request_headers; - - if (!net::HttpRequestHeaders::FromNetLogParam(event_params.get(), - &request_headers, - &request_line)) { - NOTREACHED(); - } - - // We need to clear headers in case the same url_request is reused for - // several http requests (e.g. see http://crbug.com/80157). - info->request_headers.clear(); - - for (net::HttpRequestHeaders::Iterator it(request_headers); - it.GetNext();) { - info->request_headers.push_back(std::make_pair(it.name(), it.value())); - } - info->request_headers_text = request_line + request_headers.ToString(); - break; - } - case net::NetLog::TYPE_HTTP_TRANSACTION_SPDY_SEND_REQUEST_HEADERS: { - scoped_ptr event_params(entry.ParametersToValue()); - net::SpdyHeaderBlock request_headers; - - if (!net::SpdyHeaderBlockFromNetLogParam(event_params.get(), - &request_headers)) { - NOTREACHED(); - } - - // We need to clear headers in case the same url_request is reused for - // several http requests (e.g. see http://crbug.com/80157). - info->request_headers.clear(); - - for (net::SpdyHeaderBlock::const_iterator it = request_headers.begin(); - it != request_headers.end(); ++it) { - info->request_headers.push_back(std::make_pair(it->first, it->second)); - } - info->request_headers_text = ""; - break; - } - case net::NetLog::TYPE_HTTP_TRANSACTION_READ_RESPONSE_HEADERS: { - scoped_ptr event_params(entry.ParametersToValue()); - - scoped_refptr response_headers; - - if (!net::HttpResponseHeaders::FromNetLogParam(event_params.get(), - &response_headers)) { - NOTREACHED(); - } - - info->http_status_code = response_headers->response_code(); - info->http_status_text = response_headers->GetStatusText(); - std::string name, value; - - // We need to clear headers in case the same url_request is reused for - // several http requests (e.g. see http://crbug.com/80157). - info->response_headers.clear(); - - for (void* it = NULL; - response_headers->EnumerateHeaderLines(&it, &name, &value); ) { - info->response_headers.push_back(std::make_pair(name, value)); - } - info->response_headers_text = - net::HttpUtil::ConvertHeadersBackToHTTPResponse( - response_headers->raw_headers()); - break; - } - case net::NetLog::TYPE_HTTP_STREAM_REQUEST_BOUND_TO_JOB: { - scoped_ptr event_params(entry.ParametersToValue()); - net::NetLog::Source http_stream_job_source; - if (!net::NetLog::Source::FromEventParameters(event_params.get(), - &http_stream_job_source)) { - NOTREACHED(); - break; - } - - uint32 http_stream_job_id = http_stream_job_source.id; - HTTPStreamJobToSocketMap::iterator it = - http_stream_job_to_socket_.find(http_stream_job_id); - if (it == http_stream_job_to_socket_.end()) - return; - uint32 socket_id = it->second; - - if (socket_to_request_.size() > kMaxNumEntries) { - LOG(WARNING) << "The url request observer socket count has grown " - "larger than expected, resetting"; - socket_to_request_.clear(); - } - - socket_to_request_[socket_id] = entry.source().id; - http_stream_job_to_socket_.erase(http_stream_job_id); - break; - } - default: - break; - } -} - -void DevToolsNetLogObserver::OnAddHTTPStreamJobEntry( - const net::NetLog::Entry& entry) { - DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); - - if (entry.type() == net::NetLog::TYPE_SOCKET_POOL_BOUND_TO_SOCKET) { - scoped_ptr event_params(entry.ParametersToValue()); - net::NetLog::Source socket_source; - if (!net::NetLog::Source::FromEventParameters(event_params.get(), - &socket_source)) { - NOTREACHED(); - return; - } - - // Prevents us from passively growing the memory unbounded in - // case something went wrong. Should not happen. - if (http_stream_job_to_socket_.size() > kMaxNumEntries) { - LOG(WARNING) << "The load timing observer http stream job count " - "has grown larger than expected, resetting"; - http_stream_job_to_socket_.clear(); - } - http_stream_job_to_socket_[entry.source().id] = socket_source.id; - } -} - -void DevToolsNetLogObserver::OnAddSocketEntry( - const net::NetLog::Entry& entry) { - DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); - - bool is_end = entry.phase() == net::NetLog::PHASE_END; - - SocketToRequestMap::iterator it = - socket_to_request_.find(entry.source().id); - if (it == socket_to_request_.end()) - return; - uint32 request_id = it->second; - - if (entry.type() == net::NetLog::TYPE_SOCKET_IN_USE) { - if (is_end) - socket_to_request_.erase(entry.source().id); - return; - } - - RequestToEncodedDataLengthMap::iterator encoded_data_length_it = - request_to_encoded_data_length_.find(request_id); - if (encoded_data_length_it == request_to_encoded_data_length_.end()) - return; - - if (net::NetLog::TYPE_SOCKET_BYTES_RECEIVED == entry.type()) { - int byte_count = 0; - scoped_ptr value(entry.ParametersToValue()); - if (!value->IsType(Value::TYPE_DICTIONARY)) - return; - - DictionaryValue* dValue = static_cast(value.get()); - if (!dValue->GetInteger("byte_count", &byte_count)) - return; - - encoded_data_length_it->second += byte_count; - } -} - -void DevToolsNetLogObserver::Attach() { - DCHECK(!instance_); - net::NetLog* net_log = GetContentClient()->browser()->GetNetLog(); - if (net_log) { - instance_ = new DevToolsNetLogObserver(); - net_log->AddThreadSafeObserver(instance_, net::NetLog::LOG_ALL_BUT_BYTES); - } -} - -void DevToolsNetLogObserver::Detach() { - DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); - - if (instance_) { - // Safest not to do this in the destructor to maintain thread safety across - // refactorings. - instance_->net_log()->RemoveThreadSafeObserver(instance_); - delete instance_; - instance_ = NULL; - } -} - -DevToolsNetLogObserver* DevToolsNetLogObserver::GetInstance() { - DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); - - return instance_; -} - -// static -void DevToolsNetLogObserver::PopulateResponseInfo( - net::URLRequest* request, - ResourceResponse* response) { - if (!(request->load_flags() & net::LOAD_REPORT_RAW_HEADERS)) - return; - - uint32 source_id = request->net_log().source().id; - DevToolsNetLogObserver* dev_tools_net_log_observer = - DevToolsNetLogObserver::GetInstance(); - if (dev_tools_net_log_observer == NULL) - return; - response->head.devtools_info = - dev_tools_net_log_observer->GetResourceInfo(source_id); -} - -// static -int DevToolsNetLogObserver::GetAndResetEncodedDataLength( - net::URLRequest* request) { - if (!(request->load_flags() & net::LOAD_REPORT_RAW_HEADERS)) - return -1; - - uint32 source_id = request->net_log().source().id; - DevToolsNetLogObserver* dev_tools_net_log_observer = - DevToolsNetLogObserver::GetInstance(); - if (dev_tools_net_log_observer == NULL) - return -1; - - RequestToEncodedDataLengthMap::iterator it = - dev_tools_net_log_observer->request_to_encoded_data_length_.find( - source_id); - if (it == dev_tools_net_log_observer->request_to_encoded_data_length_.end()) - return -1; - int encoded_data_length = it->second; - it->second = 0; - return encoded_data_length; -} - -} // namespace content diff --git a/content/browser/debugger/devtools_netlog_observer.h b/content/browser/debugger/devtools_netlog_observer.h deleted file mode 100644 index 3306bc2..0000000 --- a/content/browser/debugger/devtools_netlog_observer.h +++ /dev/null @@ -1,70 +0,0 @@ -// Copyright (c) 2012 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 CONTENT_BROWSER_DEBUGGER_DEVTOOLS_NETLOG_OBSERVER_H_ -#define CONTENT_BROWSER_DEBUGGER_DEVTOOLS_NETLOG_OBSERVER_H_ - -#include "base/hash_tables.h" -#include "base/memory/ref_counted.h" -#include "net/base/net_log.h" -#include "webkit/glue/resource_loader_bridge.h" - -namespace net { -class URLRequest; -} // namespace net - -namespace content { -struct ResourceResponse; - -// DevToolsNetLogObserver watches the NetLog event stream and collects the -// stuff that may be of interest to DevTools. Currently, this only includes -// actual HTTP/SPDY headers sent and received over the network. -// -// As DevToolsNetLogObserver shares live data with objects that live on the -// IO Thread, it must also reside on the IO Thread. Only OnAddEntry can be -// called from other threads. -class DevToolsNetLogObserver : public net::NetLog::ThreadSafeObserver { - typedef webkit_glue::ResourceDevToolsInfo ResourceInfo; - - public: - // net::NetLog::ThreadSafeObserver implementation: - virtual void OnAddEntry(const net::NetLog::Entry& entry) OVERRIDE; - - void OnAddURLRequestEntry(const net::NetLog::Entry& entry); - void OnAddHTTPStreamJobEntry(const net::NetLog::Entry& entry); - void OnAddSocketEntry(const net::NetLog::Entry& entry); - - static void Attach(); - static void Detach(); - - // Must be called on the IO thread. May return NULL if no observers - // are active. - static DevToolsNetLogObserver* GetInstance(); - static void PopulateResponseInfo(net::URLRequest*, - ResourceResponse*); - static int GetAndResetEncodedDataLength(net::URLRequest* request); - - private: - static DevToolsNetLogObserver* instance_; - - DevToolsNetLogObserver(); - virtual ~DevToolsNetLogObserver(); - - ResourceInfo* GetResourceInfo(uint32 id); - - typedef base::hash_map > RequestToInfoMap; - typedef base::hash_map RequestToEncodedDataLengthMap; - typedef base::hash_map HTTPStreamJobToSocketMap; - typedef base::hash_map SocketToRequestMap; - RequestToInfoMap request_to_info_; - RequestToEncodedDataLengthMap request_to_encoded_data_length_; - HTTPStreamJobToSocketMap http_stream_job_to_socket_; - SocketToRequestMap socket_to_request_; - - DISALLOW_COPY_AND_ASSIGN(DevToolsNetLogObserver); -}; - -} // namespace content - -#endif // CONTENT_BROWSER_DEBUGGER_DEVTOOLS_NETLOG_OBSERVER_H_ diff --git a/content/browser/debugger/devtools_resources.gyp b/content/browser/debugger/devtools_resources.gyp deleted file mode 100644 index 9ee2076..0000000 --- a/content/browser/debugger/devtools_resources.gyp +++ /dev/null @@ -1,58 +0,0 @@ -# Copyright (c) 2012 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. - -{ - 'variables': { - 'conditions': [ - ['inside_chromium_build==0', { - 'webkit_src_dir': '../../../../../..', - },{ - 'webkit_src_dir': '../../../third_party/WebKit', - }], - ], - }, - 'targets': [ - { - 'target_name': 'devtools_resources', - 'type': 'none', - 'dependencies': [ - '<(webkit_src_dir)/Source/WebKit/chromium/WebKit.gyp:generate_devtools_grd', - ], - 'variables': { - 'grit_out_dir': '<(SHARED_INTERMEDIATE_DIR)/webkit', - }, - 'actions': [ - { - 'action_name': 'devtools_resources', - # This can't use build/grit_action.gypi because the grd file - # is generated at build time, so the trick of using grit_info to get - # the real inputs/outputs at GYP time isn't possible. - 'variables': { - 'grit_cmd': ['python', '../../../tools/grit/grit.py'], - 'grit_grd_file': '<(SHARED_INTERMEDIATE_DIR)/devtools/devtools_resources.grd', - }, - 'inputs': [ - '<(grit_grd_file)', - '& trace_fragment) { - buffer_.push_back(trace_fragment->data()); - buffer_data_size_ += trace_fragment->data().size(); -} - -base::Value* DevToolsTracingHandler::OnProtocolCommand( - const std::string& method, - const base::DictionaryValue* params, - base::Value** error_out) { - if (method == "Tracing.start") - return Start(params); - else if (method == "Tracing.end") - return End(params); - else if (method == "Tracing.hasCompleted") - return HasCompleted(params); - else if (method == "Tracing.getTraceAndReset") - return GetTraceAndReset(params); - - base::DictionaryValue* error_object = new base::DictionaryValue(); - error_object->SetInteger("code", -1); - error_object->SetString("message", "Invalid method"); - - *error_out = error_object; - - return NULL; -} - -base::Value* DevToolsTracingHandler::Start( - const base::DictionaryValue* params) { - std::string categories; - if (params && params->HasKey("categories")) - params->GetString("categories", &categories); - TraceController::GetInstance()->BeginTracing(this, categories); - - return base::Value::CreateBooleanValue(true); -} - -base::Value* DevToolsTracingHandler::End( - const base::DictionaryValue* /* params */) { - TraceController::GetInstance()->EndTracingAsync(this); - - return base::Value::CreateBooleanValue(true); -} - - -base::Value* DevToolsTracingHandler::HasCompleted( - const base::DictionaryValue* /* params */) { - - return base::Value::CreateBooleanValue(has_completed_); -} - -base::Value* DevToolsTracingHandler::GetTraceAndReset( - const base::DictionaryValue* /* params */) { - std::string ret; - ret.reserve(buffer_data_size_); - for (std::vector::const_iterator i = buffer_.begin(); - i != buffer_.end(); ++i) { - if (!ret.empty()) - ret.append(","); - ret.append(*i); - } - buffer_.clear(); - has_completed_ = false; - buffer_data_size_ = 0; - - return base::Value::CreateStringValue(ret); -} - -} // namespace content diff --git a/content/browser/debugger/devtools_tracing_handler.h b/content/browser/debugger/devtools_tracing_handler.h deleted file mode 100644 index a5858fc..0000000 --- a/content/browser/debugger/devtools_tracing_handler.h +++ /dev/null @@ -1,50 +0,0 @@ -// Copyright (c) 2012 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 CONTENT_BROWSER_DEBUGGER_DEVTOOLS_TRACING_HANDLER_H_ -#define CONTENT_BROWSER_DEBUGGER_DEVTOOLS_TRACING_HANDLER_H_ - -#include "content/browser/debugger/devtools_browser_target.h" -#include "content/public/browser/trace_subscriber.h" - -namespace content { - -// This class bridges DevTools remote debugging server with the trace -// infrastructure. -class DevToolsTracingHandler - : public TraceSubscriber, - public DevToolsBrowserTarget::Handler { - public: - DevToolsTracingHandler(); - virtual ~DevToolsTracingHandler(); - - // TraceSubscriber: - virtual void OnEndTracingComplete() OVERRIDE;; - virtual void OnTraceDataCollected( - const scoped_refptr& trace_fragment) OVERRIDE; - - // DevToolBrowserTarget::Handler: - virtual std::string Domain() OVERRIDE; - virtual base::Value* OnProtocolCommand( - const std::string& method, - const base::DictionaryValue* params, - base::Value** error_out) OVERRIDE; - - private: - base::Value* Start(const base::DictionaryValue* params); - base::Value* End(const base::DictionaryValue* params); - base::Value* HasCompleted(const base::DictionaryValue* params); - base::Value* GetTraceAndReset(const base::DictionaryValue* params); - - bool has_completed_; - - std::vector buffer_; - int buffer_data_size_; - - DISALLOW_COPY_AND_ASSIGN(DevToolsTracingHandler); -}; - -} // namespace content - -#endif // CONTENT_BROWSER_DEBUGGER_DEVTOOLS_TRACING_HANDLER_H_ diff --git a/content/browser/debugger/manual_tests/console-call-line-numbers.html b/content/browser/debugger/manual_tests/console-call-line-numbers.html deleted file mode 100644 index 98bb918..0000000 --- a/content/browser/debugger/manual_tests/console-call-line-numbers.html +++ /dev/null @@ -1,15 +0,0 @@ - - - -

To test, open the DevTools's Console (Ctrl+Shift+J) and verify that all console messages have correct -resource URLs and line numbers. Also verify that errors and warnings show up inline as bubbles in the -Resource panel file list and each individual resource view.

diff --git a/content/browser/debugger/manual_tests/debugger-exception-on-load.html b/content/browser/debugger/manual_tests/debugger-exception-on-load.html deleted file mode 100644 index ef2384f..0000000 --- a/content/browser/debugger/manual_tests/debugger-exception-on-load.html +++ /dev/null @@ -1,5 +0,0 @@ - - -

To test, open the DevTools (Ctrl+Shift+I) and reload the page. You should see this file and execution line in the Scripts panel.

diff --git a/content/browser/debugger/manual_tests/debugger-execution-while-paused.html b/content/browser/debugger/manual_tests/debugger-execution-while-paused.html deleted file mode 100644 index f33abea..0000000 --- a/content/browser/debugger/manual_tests/debugger-execution-while-paused.html +++ /dev/null @@ -1,17 +0,0 @@ - - -

To test, open the DevTools (Ctrl+Shift+I) and reload the page. Set a break point inside the stepOne() function. -Now click the Step One button in the page. The breakpoint should be hit. While paused at the breakpoint -click on the Step Two button. You should not see an alert dialog. Continue script.

-

- diff --git a/content/browser/debugger/manual_tests/debugger-fake-workers.html b/content/browser/debugger/manual_tests/debugger-fake-workers.html deleted file mode 100644 index 6a7cb03..0000000 --- a/content/browser/debugger/manual_tests/debugger-fake-workers.html +++ /dev/null @@ -1,102 +0,0 @@ - - - - -

Tests debugging of HTML5 Workers

- -
    - -
  1. Open DevTools, Scripts Panel; Tick Debug on Workers sidebar.
  2. -
  3. Reload the page.
  4. -
  5. -
  6. Observe 2 workers appear in the worker sidebar pane (including non-existent-worker.js)"
  7. -
  8. Observe worker-primes.js and primes.js appear in scripts drop-down box.
  9. -
  10. Assure primes are being logged to test console below.
  11. -
  12. Set a breakpoint on one of worker scripts, assure it's hit.
  13. -
  14. Try causing an error in worker, observe it's logged in DevTools console and in test console below. - -
  15. - -
- -
-
- - - diff --git a/content/browser/debugger/manual_tests/debugger-pause-on-else-statements.html b/content/browser/debugger/manual_tests/debugger-pause-on-else-statements.html deleted file mode 100644 index 3c80a43..0000000 --- a/content/browser/debugger/manual_tests/debugger-pause-on-else-statements.html +++ /dev/null @@ -1,16 +0,0 @@ - - -

To test, open the DevTools (Ctrl+Shift+I) and reload the page. When the debugger breaks, select the (anonymous function) node -in the call stack, you should see the execution line on the call to test().

-

-Also set a breakpoint on the call to test(), and reload. It should break before the test() function is called. diff --git a/content/browser/debugger/manual_tests/debugger-pause-on-for-in-statements.html b/content/browser/debugger/manual_tests/debugger-pause-on-for-in-statements.html deleted file mode 100644 index 79f7983..0000000 --- a/content/browser/debugger/manual_tests/debugger-pause-on-for-in-statements.html +++ /dev/null @@ -1,16 +0,0 @@ - - -

To test, open the DevTools (Ctrl+Shift+I) and reload the page. When the debugger breaks, select -the (anonymous function) node in the call stack, you should see the execution line on the call to test(). -

-Also set a breakpoint on the call to test(), and reload. It should break before the test() function is called. diff --git a/content/browser/debugger/manual_tests/debugger-pause-on-for-statements.html b/content/browser/debugger/manual_tests/debugger-pause-on-for-statements.html deleted file mode 100644 index 1a9e274..0000000 --- a/content/browser/debugger/manual_tests/debugger-pause-on-for-statements.html +++ /dev/null @@ -1,14 +0,0 @@ - - -

To test, open the DevTools (Ctrl+Shift+I) and reload the page. When the debugger breaks, select the -(anonymous function) node in the call stack, you should see the execution line on the call to test().

-

-Also set a breakpoint on the call to test(), and reload. It should break before the test() function is called. diff --git a/content/browser/debugger/manual_tests/debugger-step-on-do-while-statements.html b/content/browser/debugger/manual_tests/debugger-step-on-do-while-statements.html deleted file mode 100644 index f60dd6a..0000000 --- a/content/browser/debugger/manual_tests/debugger-step-on-do-while-statements.html +++ /dev/null @@ -1,27 +0,0 @@ - - -

To test, open the DevTools (Ctrl+Shift+I) and reload the page. -

-Before running the tests please perform the following: -Make sure the execution is not paused in the debugger.
-Click the button and when the debugger breaks, set a breakpoint on the first line in the loop -(as indicated by the comment), and click continue.
-The debugger should stop at the beggining of the loop.
-The above actions should be performed before each of the following tests.

-

- -

-TEST 1: Click 'continue'. Execution should continue without stopping on the loop breakpoint again.
-TEST 2: Click 'Step into'. Debugger should step inside each function.
-TEST 3: 'Step over' to the end of the loop (and 'while' statement) and step over again. Debugger -should go to the beggining of the loop.
diff --git a/content/browser/debugger/manual_tests/debugger-step-on-for-in-statements.html b/content/browser/debugger/manual_tests/debugger-step-on-for-in-statements.html deleted file mode 100644 index e360394..0000000 --- a/content/browser/debugger/manual_tests/debugger-step-on-for-in-statements.html +++ /dev/null @@ -1,35 +0,0 @@ - -

To test, open the DevTools (Ctrl+Shift+I) and reload the page. -

-Before running the tests please perform the following: -Make sure the execution is not paused in the debugger.
-Click the button and when the debugger breaks, set a breakpoint on the first line in the loop -(as indicated by the comment), and click continue.
-The debugger should stop at the beggining of the loop.
-The above actions should be performed before each of the following tests.

-

- -

-TEST 1: Click 'continue'. Execution should continue without stopping on the loop breakpoint again.
-TEST 2: Click 'Step over'. Debugger should step inside the loop to the next statement line.
-TEST 3: Click 'Step into'. Debugger should step into 'getObject' function.
-TEST 4: 'Step over' to the statement line and then 'Step over' again. Debugger should pause on -the for-in loop again.
diff --git a/content/browser/debugger/manual_tests/debugger-step-on-for-statements.html b/content/browser/debugger/manual_tests/debugger-step-on-for-statements.html deleted file mode 100644 index 75289e5f..0000000 --- a/content/browser/debugger/manual_tests/debugger-step-on-for-statements.html +++ /dev/null @@ -1,25 +0,0 @@ - - -

To test, open the DevTools (Ctrl+Shift+I) and reload the page. -

-Before running the tests please perform the following: -Make sure the execution is not paused in the debugger.
-Click the button and when the debugger breaks, set a breakpoint on the first line in the loop -(as indicated by the comment), and click continue.
-The debugger should stop at the beggining of the loop.
-The above actions should be performed before each of the following tests.

-

- -

-TEST 1: Click 'continue'. Execution should continue without stopping on the loop breakpoint again.
-TEST 2: Click 'Step over'. Debugger should step inside the loop to the next statement line.
-TEST 3: Click 'Step into'. Debugger should step into 'initialize' function. Click 'Step into' until -outside of the 'initialize' function - debugger should enter the 'condition' function.
-function.
diff --git a/content/browser/debugger/manual_tests/debugger-step-on-while-statements.html b/content/browser/debugger/manual_tests/debugger-step-on-while-statements.html deleted file mode 100644 index 7967172..0000000 --- a/content/browser/debugger/manual_tests/debugger-step-on-while-statements.html +++ /dev/null @@ -1,28 +0,0 @@ - - -

To test, open the DevTools (Ctrl+Shift+I) and reload the page. -

-Before running the tests please perform the following: -Make sure the execution is not paused in the debugger.
-Click the button and when the debugger breaks, set a breakpoint on the first line in the loop -(as indicated by the comment), and click continue.
-The debugger should stop at the beggining of the loop.
-The above actions should be performed before each of the following tests.

-

- -

-TEST 1: Click 'continue'. Execution should continue without stopping on the loop breakpoint again.
-TEST 2: Click 'Step over'. Debugger should step inside the loop to the next statement line.
-TEST 3: Click 'Step into'. Debugger should step into 'condition' function.
-step over to the beggingin of the while loop again. Click 'Step into'. Debugger should step into -the 'condition' function.
diff --git a/content/browser/debugger/manual_tests/debugger-watch-expressions.html b/content/browser/debugger/manual_tests/debugger-watch-expressions.html deleted file mode 100644 index a2e9258..0000000 --- a/content/browser/debugger/manual_tests/debugger-watch-expressions.html +++ /dev/null @@ -1,79 +0,0 @@ -

Test for watched expression

- -

To begin test, open DevTools, go the Scripts Panel -and then click this link: [begin test]. - -

Perform the following steps, and note the expected results: - -

    - -
  1. After clicking the link above, you should now be paused in the body of -the test method, thanks to the debugger statement. - -

  2. Add the following expressions to the "Watch Expressions" section of the -Scripts panel sidebar pane: "this", "a", -"b", "c" and "d". Do NOT enter the quotes. - -

  3. The values of the expressions as shown in the window should be -Object for this, undefined for -the a, b, and c variables, and a -value of ReferenceError: d is not defined -for the d variable. - -

  4. Note that the value for d should not change for the life of -the test, as the variable d is never introduced in the program. - -

  5. Step through the code, and you'll see the values of a, -b, and c change, as the variables are assigned. -Also note that as the scope changes due to the function invocation, values -will be changed to refer to their current scope. The this -expression will change when the method is invoked on the object constructed by -the test. - -

  6. Click different stack frames in the Call Stack section to ensure the -expressions change value appropriately as the current stack frame changes. - -

- - diff --git a/content/browser/debugger/manual_tests/dom-mutation.html b/content/browser/debugger/manual_tests/dom-mutation.html deleted file mode 100644 index a03b03c..0000000 --- a/content/browser/debugger/manual_tests/dom-mutation.html +++ /dev/null @@ -1,32 +0,0 @@ - -

To begin test, open DevTools, Elements Panel and watch the DOM change to match the page. -Clicking the buttons will navigate the subframe, and the all the subframe child nodes should change. -Expand DOM nodes in the Elements Panel to see new nodes appearing in the list live.

-
- - -
-
- -
-
diff --git a/content/browser/debugger/manual_tests/element-styles.html b/content/browser/debugger/manual_tests/element-styles.html deleted file mode 100644 index cb33919..0000000 --- a/content/browser/debugger/manual_tests/element-styles.html +++ /dev/null @@ -1,40 +0,0 @@ - -

To begin test, open DevTools, select the Elements panel. Expand the Styles pane in the sidebar.

-
    -
  • Choose the <div class="classTest"...> element in the DOM tree. -You should see the following element styles in the ".classTest (inline stylesheet)" section: -
    -  -webkit-transform:skew(-10deg,-3deg);
    -  color: green;
    -  background: #CCC;
    -  border: 2px solid blue;
    -  padding: 5px 6px 7px 8px;
    -
    - While changing all the property values, you should see corresponding live page changes. -
  • Double click the "-webkit-transform" rule and place the cursor at the second argument (-3deg). -
  • Press Up/Down keys do see the argument value change in 1.0 steps (0.1 steps in the [-1; 1] range). -
  • Press Shift+Up/Down keys to see the argument value change in 10.0 steps. -
  • Press Alt(Cmd)+Up/Downkeys to see the argument value change in 0.1 steps (1.0 steps in the [-1; 1] range). -
  • Move the mouse pointer within the section to display checkboxes to the right of the property values. -
  • Click the checkboxes to disable/enable the corresponding style properties and observe the page changes. -You can disable the "-webkit-transform" property if the element overlaps the instructions. -
  • Double-click the "background" rule and alter the color to "#FFF". The text background should turn white. -
  • Double-click the "color" rule and alter the color to "black". The text background should turn black. -
  • Expand the "padding" shorthand property using the arrow at the left. You should see the following -property values beneath: padding-top: 5px; padding-right: 6px; padding-bottom: 7px; padding-left: 8px; -
  • In the "Styles" pane titlebar click the gear button and choose "New Style Rule". In the editbox that appears, type: -
    -font-family: monospace;
    -
    - The font of the test string should alter to a monospaced one. -
- -
CLASS_TEST CLASS_TEST CLASS_TEST CLASS_TEST CLASS_TEST CLASS_TEST CLASS_TEST
\ No newline at end of file diff --git a/content/browser/debugger/manual_tests/error-warning-count.html b/content/browser/debugger/manual_tests/error-warning-count.html deleted file mode 100644 index 3296742..0000000 --- a/content/browser/debugger/manual_tests/error-warning-count.html +++ /dev/null @@ -1,58 +0,0 @@ - - -

To begin test, open DevTools and click one of the buttons below. You should -see an error and/or warning count in the Inspector's status bar. Clicking on -the error/warning count should open the Console. Hovering over the -error/warning count should show you a tooltip that matches the text in the -button you clicked.

-

Note: You must reload the page between each button press.

diff --git a/content/browser/debugger/manual_tests/event-listeners.html b/content/browser/debugger/manual_tests/event-listeners.html deleted file mode 100644 index 4dff96d..0000000 --- a/content/browser/debugger/manual_tests/event-listeners.html +++ /dev/null @@ -1,30 +0,0 @@ - - - - -
-
-
-

To begin test, open DevTools, select the Elements panel. Expand the Event Listeners -pane in the sidebar. -

    -
  • Choose the <div id="targetParent"...> element. -You should see the "click" section in the Event Listeners pane. Expand the section to see -the "listenerFunctionParent" function (at "div#targetParent") under it. -
  • Expand the targetParent node in the tree and choose the <div id="target"...> -element. You should see the "click" section in the Event Listeners pane. Expand the section -to see two functions, "listenerFunctionParent" (at "div#targetParent") and -"listenerFunction" (at "div#target") under it. -
- diff --git a/content/browser/debugger/manual_tests/heap-profiler-test-basic-grid-functionality.html b/content/browser/debugger/manual_tests/heap-profiler-test-basic-grid-functionality.html deleted file mode 100644 index 5aa4555..0000000 --- a/content/browser/debugger/manual_tests/heap-profiler-test-basic-grid-functionality.html +++ /dev/null @@ -1,32 +0,0 @@ - - - Heap Profiler: basic grid functionality test - - - This is the test for basic functionality of heap snapshot view grid. -
-
- To use this test: -
    -
  • load file in the browser; -
  • open DevTools (Ctrl+Shift+I on Win/Linux, Command+Option+I on Mac); -
  • go to 'Profiles' page; -
  • press 'Take heap snapshot' button - (eye icon on the left side of status bar); -
-
- On the left pane under 'Heap snapshots' section, an item called - 'Snapshot 1' must appear, and a grid with snapshot data must - appear on the right. Now test the following functionality in the grid: -
    -
  • change sorting order in each column by clicking on its header; -
  • resize each column; -
  • toggle between showing absolute times and percents - (button with percent sign on the status bar); -
  • double-click on numbers in 'Count' and - 'Size' columns to toggle between times and percents for - this column only; -
  • expanding and collapsing tree nodes. -
- - diff --git a/content/browser/debugger/manual_tests/heap-profiler-test-snapshots-comparison.html b/content/browser/debugger/manual_tests/heap-profiler-test-snapshots-comparison.html deleted file mode 100644 index 3a419d4e..0000000 --- a/content/browser/debugger/manual_tests/heap-profiler-test-snapshots-comparison.html +++ /dev/null @@ -1,83 +0,0 @@ - - - Heap Profiler: heap snapshots comparison test - - - - This is the test for heap snapshot comparison functionality. -
-
- To use this test: -
    -
  • load file in the browser; -
  • open DevTools (Ctrl+Shift+I on Win/Linux, Command+Option+I on Mac); -
  • go to 'Profiles' page; -
  • press 'Take heap snapshot' button - (eye icon on the left side of the status bar); -
  • press - ; -
  • press 'Take heap snapshot' button again; -
-
- On the left pane under 'Heap snapshots' section, items called - 'Snapshot 1' and 'Snapshot 2' must appear. Select 'Snapshot 2'. - Ensure that absolute values are shown (not percents). -
-
- TEST 1. Verify the following: -
    -
  • the value in '+/- Count' column for 'A' must be '-25'; -
  • after expanding 'A' item, the value in '+/- Count' column - for 'Array' child entry must also be '-25'; -
  • the value in '+/- Count' column for 'B' must be '+25'; -
  • after expanding 'B' item, the value in '+/- Count' column - for 'Array' child entry must also be '+25'; the value for 'A' - child must be '-25'; -
-
- TEST 2. Change display to percent view (using the percent button on the - status bar). Verify the following: -
    -
  • values in '+/- Count' and '+/- Size' columns for 'C' must be 'deleted'; -
  • values in '+/- Count' and '+/- Size' columns for 'D' must be 'new'; -
- - diff --git a/content/browser/debugger/manual_tests/highlight-nodes.html b/content/browser/debugger/manual_tests/highlight-nodes.html deleted file mode 100644 index cbeae6f..0000000 --- a/content/browser/debugger/manual_tests/highlight-nodes.html +++ /dev/null @@ -1,23 +0,0 @@ - -

This page has basic tests of node highlighting in the inspected page. To test, load this page, open the DevTools and mouseover the nodes in the treeview of the inspector. You should see the highlights happen with the appropriate padding/border/margin/content highlights.

-
padding:10px; border: 10px; margin: 10px;
-
padding:10px; border: 10px;
-
padding:10px; margin: 10px;
-
border: 10px; margin: 10px;
-
padding:10px;
-
border: 10px;
-
margin: 10px;
-
no padding, border, or margin
-
-webkit-transform:skew(-5deg,-5deg); padding:10px; border: 10px; margin: 10px;
-
-webkit-transform:skew(-5deg,-5deg); padding:10px; border: 10px;
-
-webkit-transform:skew(-5deg,-5deg); padding:10px; margin: 10px;
-
-webkit-transform:skew(-5deg,-5deg); border: 10px; margin: 10px;
-
-webkit-transform:skew(-5deg,-5deg); padding:10px;
-
-webkit-transform:skew(-5deg,-5deg); border: 10px;
-
-webkit-transform:skew(-5deg,-5deg); margin: 10px;
-
-webkit-transform:skew(-5deg,-5deg); no padding, border, or margin
- diff --git a/content/browser/debugger/manual_tests/highlight-source-line.html b/content/browser/debugger/manual_tests/highlight-source-line.html deleted file mode 100644 index a56ed97..0000000 --- a/content/browser/debugger/manual_tests/highlight-source-line.html +++ /dev/null @@ -1,3 +0,0 @@ -

To test, open the DevTools and reload this page. Then open the Console and click the link for the markup error. You should see the line containing the error briefly highlighted in the source view.

- -

This line contains a markup error.

diff --git a/content/browser/debugger/manual_tests/profiler-test-basic-grid-functionality.html b/content/browser/debugger/manual_tests/profiler-test-basic-grid-functionality.html deleted file mode 100644 index 1841715..0000000 --- a/content/browser/debugger/manual_tests/profiler-test-basic-grid-functionality.html +++ /dev/null @@ -1,38 +0,0 @@ - - - Profiler: basic grid functionality test - - - - This test runs a simple looped computation to test basic - functionality of profile view grid. -
-
- To use this test: -
    -
  • load file in the browser; -
  • open DevTools (Ctrl+Shift+I on Win/Linux, Command+Option+I on Mac); -
  • go to 'Profiles' page; -
  • press 'Start profiling' button - (gray dot on the left side of status bar); -
  • wait for 5 seconds; -
  • press 'Stop profiling' button - (red dot on the left side of status bar); -
-
- On the left pane under 'CPU profiles' section, an item called - 'Profile 1' must appear, and a grid with profile data must - appear on the right. Now test the following functionality in the grid: -
    -
  • change sorting order in each column by clicking on its header; -
  • resize each column; -
  • toggle between showing absolute times and percents - (button with percent sign on the status bar); -
  • double-click on numbers in 'Self' and - 'Total' columns to toggle between times and percents for - this column only; -
  • expanding and collapsing tree nodes; -
  • toggling between "Heavy" and "Tree" views. -
- - diff --git a/content/browser/debugger/manual_tests/profiler-test-console-control.html b/content/browser/debugger/manual_tests/profiler-test-console-control.html deleted file mode 100644 index 4f2001a..0000000 --- a/content/browser/debugger/manual_tests/profiler-test-console-control.html +++ /dev/null @@ -1,27 +0,0 @@ - - - Profiler: test console controlling of CPU profiling - - - - - This test runs and profiles a simple looped computation. -
-
- TEST -
    -
  • load file in the browser; -
  • open DevTools with console (Ctrl+Shift+I on Win/Linux, Command+Option+I on Mac); -
  • go to 'Profiles' page; -
  • observe that 'Profile 1' item has appeared under 'CPU profiles' section; -
  • check for presence of 'eternal_fib' entry in the profile view. -
-
- - diff --git a/content/browser/debugger/manual_tests/profiler-test-focus-and-exclude.html b/content/browser/debugger/manual_tests/profiler-test-focus-and-exclude.html deleted file mode 100644 index d33e3eb..0000000 --- a/content/browser/debugger/manual_tests/profiler-test-focus-and-exclude.html +++ /dev/null @@ -1,71 +0,0 @@ - - - Profiler: focusing and exclusion test - - - - This test runs a simple looped computation to test focusing and - exclusion functionality of profile view grid. -
-
- To use this test: -
    -
  • load file in the browser; -
  • open DevTools (Ctrl+Shift+I on Win/Linux, Command+Option+I on Mac); -
  • go to 'Profiles' page; -
  • press 'Start profiling' button - (gray dot on the left side of status bar); -
  • wait for 5 seconds; -
  • press 'Stop profiling' button - (red dot on the left side of status bar); -
-
- On the left pane under 'CPU profiles' section, an item called - 'Profile 1' must appear, and a grid with profile data must - appear on the right. Now test the following functionality in the grid: -
- TEST 1: -
    -
  • select 'eternal_fib' function entry (without expanding it), - press 'Focus - on selected function' button (eye on the right of the status bar); -
  • ensure that only 'eternal_fib' function and its children are - left in the tree, and 'Total' column for the function shows - '100%' value; -
  • expand 'eternal_fib' function node; -
  • press 'Restore all functions' button; -
  • verify that the value in 'Total' column is less than 100%; -
  • verify that 'eternal_fib' function node is can still be - collapsed and expanded back; -
-
- TEST 2: -
    -
  • expand two levels of 'Script:' node, select the second-level - node; -
  • repeat the same steps for the selected node (in this case, immediate - parent nodes of the focused node must also remain visible after - focusing); -
-
- TEST 3: -
    -
  • by expanding 'Script:' node, make sure that at least 3 - 'eternal_fib' function nodes are visible; -
  • select any of 'eternal_fib' nodes and press - 'Exclude selected function' (cross) button on the status bar; -
  • verify that all 'eternal_fib' nodes are no more visible; -
  • expand more 'Script:' node levels, verify that no new - 'eternal_fib' nodes appear with expansion; -
  • press 'Restore all functions' button; -
  • verify that 'eternal_fib' nodes are now visible; -
-
- TESTS 4 and 5: -
- Now switch to 'Tree (Top Down)' view and repeat testing steps. - For the 'Exclude selected function' function test, use - 'Script:' function node, as 'eternal_fib' has only - one entry in this view. - - diff --git a/content/browser/debugger/manual_tests/profiler-test-re-opening.html b/content/browser/debugger/manual_tests/profiler-test-re-opening.html deleted file mode 100644 index a615afa..0000000 --- a/content/browser/debugger/manual_tests/profiler-test-re-opening.html +++ /dev/null @@ -1,37 +0,0 @@ - - - Profiler: test profiles population on DevTools re-opening - - - - - This test runs and profiles a simple looped computation. -
-
- TEST -
    -
  • load file in the browser; -
  • open DevTools with console (Ctrl+Shift+I on Win/Linux, Command+Option+I on Mac); -
  • go to 'Profiles' page; -
  • observe that 'Profile 1' item has appeared under 'CPU profiles' section; -
  • reload page in browser; -
  • observe that after 5 seconds, 'Profile 2' item has appeared under - 'CPU profiles' section; -
  • take a couple of heap snapshots by pressing 'Take heap snapshot.' - button (eye icon on the left of the status bar); -
  • close DevTools window; -
  • re-open DevTools window; -
  • go to 'Profiles' page; -
  • verify that CPU profiles 'Profile 1' and 'Profile 2', and heap profiles - taken previously are restored back (Warning: it may take some - time to re-process them). -
-
- - diff --git a/content/browser/debugger/manual_tests/resources/fib.js b/content/browser/debugger/manual_tests/resources/fib.js deleted file mode 100644 index 804c866..0000000 --- a/content/browser/debugger/manual_tests/resources/fib.js +++ /dev/null @@ -1,20 +0,0 @@ -function fib(n) { - return n < 2 ? 1 : fib(n - 1) + fib(n - 2); -} - -function eternal_fib() { - var started = Date.now(); - while(true) { - fib(20); - // Make page responsive by making a break every 100 ms. - if (Date.now() - started >= 100) { - setTimeout(eternal_fib, 0); - return; - } - } -} - -function run_fib() { - // Let the page do initial rendering, then go. - setTimeout(eternal_fib, 200); -} diff --git a/content/browser/debugger/manual_tests/resources/loop-statements.js b/content/browser/debugger/manual_tests/resources/loop-statements.js deleted file mode 100644 index cbb4e0d..0000000 --- a/content/browser/debugger/manual_tests/resources/loop-statements.js +++ /dev/null @@ -1,22 +0,0 @@ -var i; -var a; - -function initialize() -{ - i = false; -} - -function condition() -{ - return !i; -} - -function increment() -{ - i = !i; -} - -function statement() -{ - a = i; -} diff --git a/content/browser/debugger/manual_tests/resources/mutate-frame-2.html b/content/browser/debugger/manual_tests/resources/mutate-frame-2.html deleted file mode 100644 index 9d413b9..0000000 --- a/content/browser/debugger/manual_tests/resources/mutate-frame-2.html +++ /dev/null @@ -1,12 +0,0 @@ - diff --git a/content/browser/debugger/manual_tests/resources/mutate-frame.html b/content/browser/debugger/manual_tests/resources/mutate-frame.html deleted file mode 100644 index 08fc656..0000000 --- a/content/browser/debugger/manual_tests/resources/mutate-frame.html +++ /dev/null @@ -1,10 +0,0 @@ - diff --git a/content/browser/debugger/manual_tests/resources/primes.js b/content/browser/debugger/manual_tests/resources/primes.js deleted file mode 100644 index 64d38dc..0000000 --- a/content/browser/debugger/manual_tests/resources/primes.js +++ /dev/null @@ -1,13 +0,0 @@ -function Primes() { - this.primes_ = {}; -} - -Primes.prototype.test = function(p) { - for (var divisor in this.primes_) { - if (p % divisor === 0) return false; - if (divisor * divisor > p) - break; - } - this.primes_[p] = 1; - return true; -} diff --git a/content/browser/debugger/manual_tests/resources/script-console-calls.js b/content/browser/debugger/manual_tests/resources/script-console-calls.js deleted file mode 100644 index 9c7bc35..0000000 --- a/content/browser/debugger/manual_tests/resources/script-console-calls.js +++ /dev/null @@ -1,8 +0,0 @@ -console.info("Test console.info"); -console.log("Test console.log"); -console.warn("Test console.warn"); -console.error("Test console.error"); -console.time("Test console.time"); -console.timeEnd("Test console.time"); -console.count("Test console.count"); -console.assert(false, "Test console.assert"); diff --git a/content/browser/debugger/manual_tests/resources/worker-primes.js b/content/browser/debugger/manual_tests/resources/worker-primes.js deleted file mode 100644 index 8be021f..0000000 --- a/content/browser/debugger/manual_tests/resources/worker-primes.js +++ /dev/null @@ -1,10 +0,0 @@ -importScripts('primes.js'); - -var primes = new Primes(); - -onmessage = function(event) { - var p = event.data; - if (p != parseInt(p)) - throw 'invalid argument'; - postMessage([p, primes.test(p)]); -} diff --git a/content/browser/debugger/render_view_devtools_agent_host.cc b/content/browser/debugger/render_view_devtools_agent_host.cc deleted file mode 100644 index 716ffa3..0000000 --- a/content/browser/debugger/render_view_devtools_agent_host.cc +++ /dev/null @@ -1,154 +0,0 @@ -// Copyright (c) 2012 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 "content/browser/debugger/render_view_devtools_agent_host.h" - -#include "base/basictypes.h" -#include "base/lazy_instance.h" -#include "content/browser/debugger/devtools_manager_impl.h" -#include "content/browser/debugger/render_view_devtools_agent_host.h" -#include "content/browser/renderer_host/render_process_host_impl.h" -#include "content/browser/renderer_host/render_view_host_impl.h" -#include "content/browser/site_instance_impl.h" -#include "content/browser/web_contents/web_contents_impl.h" -#include "content/common/devtools_messages.h" -#include "content/public/browser/content_browser_client.h" -#include "content/public/browser/devtools_agent_host_registry.h" -#include "content/public/browser/notification_service.h" -#include "content/public/browser/notification_types.h" - -namespace content { - -typedef std::map Instances; - -namespace { -base::LazyInstance::Leaky g_instances = LAZY_INSTANCE_INITIALIZER; -} // namespace - -// static -DevToolsAgentHost* DevToolsAgentHostRegistry::GetDevToolsAgentHost( - RenderViewHost* rvh) { - Instances::iterator it = g_instances.Get().find(rvh); - if (it != g_instances.Get().end()) - return it->second; - return new RenderViewDevToolsAgentHost(rvh); -} - -// static -RenderViewHost* DevToolsAgentHostRegistry::GetRenderViewHost( - DevToolsAgentHost* agent_host) { - for (Instances::iterator it = g_instances.Get().begin(); - it != g_instances.Get().end(); ++it) { - if (agent_host == it->second) - return it->first; - } - return NULL; -} - -// static -bool DevToolsAgentHostRegistry::HasDevToolsAgentHost(RenderViewHost* rvh) { - if (g_instances == NULL) - return false; - Instances::iterator it = g_instances.Get().find(rvh); - return it != g_instances.Get().end(); -} - -bool DevToolsAgentHostRegistry::IsDebuggerAttached(WebContents* web_contents) { - if (g_instances == NULL) - return false; - DevToolsManager* devtools_manager = DevToolsManager::GetInstance(); - if (!devtools_manager) - return false; - RenderViewHostDelegate* delegate = - static_cast(web_contents); - for (Instances::iterator it = g_instances.Get().begin(); - it != g_instances.Get().end(); ++it) { - if (it->first->GetDelegate() != delegate) - continue; - if (devtools_manager->GetDevToolsClientHostFor(it->second)) - return true; - } - return false; -} - -RenderViewDevToolsAgentHost::RenderViewDevToolsAgentHost( - RenderViewHost* rvh) - : RenderViewHostObserver(rvh), - render_view_host_(rvh) { - g_instances.Get()[rvh] = this; -} - -void RenderViewDevToolsAgentHost::SendMessageToAgent(IPC::Message* msg) { - msg->set_routing_id(render_view_host_->GetRoutingID()); - render_view_host_->Send(msg); -} - -void RenderViewDevToolsAgentHost::NotifyClientAttaching() { - NotificationService::current()->Notify( - NOTIFICATION_DEVTOOLS_AGENT_ATTACHED, - Source( - render_view_host_->GetSiteInstance()->GetProcess()-> - GetBrowserContext()), - Details(render_view_host_)); -} - -void RenderViewDevToolsAgentHost::NotifyClientDetaching() { - NotificationService::current()->Notify( - NOTIFICATION_DEVTOOLS_AGENT_DETACHED, - Source( - render_view_host_->GetSiteInstance()->GetProcess()-> - GetBrowserContext()), - Details(render_view_host_)); -} - -int RenderViewDevToolsAgentHost::GetRenderProcessId() { - return render_view_host_->GetProcess()->GetID(); -} - -RenderViewDevToolsAgentHost::~RenderViewDevToolsAgentHost() { - g_instances.Get().erase(render_view_host_); -} - -void RenderViewDevToolsAgentHost::RenderViewHostDestroyed( - RenderViewHost* rvh) { - NotifyCloseListener(); - delete this; -} - -bool RenderViewDevToolsAgentHost::OnMessageReceived( - const IPC::Message& message) { - bool handled = true; - IPC_BEGIN_MESSAGE_MAP(RenderViewDevToolsAgentHost, message) - IPC_MESSAGE_HANDLER(DevToolsClientMsg_DispatchOnInspectorFrontend, - OnDispatchOnInspectorFrontend) - IPC_MESSAGE_HANDLER(DevToolsHostMsg_SaveAgentRuntimeState, - OnSaveAgentRuntimeState) - IPC_MESSAGE_HANDLER(DevToolsHostMsg_ClearBrowserCache, OnClearBrowserCache) - IPC_MESSAGE_HANDLER(DevToolsHostMsg_ClearBrowserCookies, - OnClearBrowserCookies) - IPC_MESSAGE_UNHANDLED(handled = false) - IPC_END_MESSAGE_MAP() - return handled; -} - -void RenderViewDevToolsAgentHost::OnSaveAgentRuntimeState( - const std::string& state) { - DevToolsManagerImpl::GetInstance()->SaveAgentRuntimeState(this, state); -} - -void RenderViewDevToolsAgentHost::OnDispatchOnInspectorFrontend( - const std::string& message) { - DevToolsManagerImpl::GetInstance()->DispatchOnInspectorFrontend( - this, message); -} - -void RenderViewDevToolsAgentHost::OnClearBrowserCache() { - GetContentClient()->browser()->ClearCache(render_view_host_); -} - -void RenderViewDevToolsAgentHost::OnClearBrowserCookies() { - GetContentClient()->browser()->ClearCookies(render_view_host_); -} - -} // namespace content diff --git a/content/browser/debugger/render_view_devtools_agent_host.h b/content/browser/debugger/render_view_devtools_agent_host.h deleted file mode 100644 index 4235467..0000000 --- a/content/browser/debugger/render_view_devtools_agent_host.h +++ /dev/null @@ -1,51 +0,0 @@ -// Copyright (c) 2012 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 CONTENT_BROWSER_DEBUGGER_RENDER_VIEW_DEVTOOLS_AGENT_HOST_H_ -#define CONTENT_BROWSER_DEBUGGER_RENDER_VIEW_DEVTOOLS_AGENT_HOST_H_ - -#include - -#include "base/basictypes.h" -#include "base/compiler_specific.h" -#include "content/browser/debugger/devtools_agent_host.h" -#include "content/common/content_export.h" -#include "content/public/browser/render_view_host_observer.h" - -namespace content { - -class RenderViewHost; - -class CONTENT_EXPORT RenderViewDevToolsAgentHost - : public DevToolsAgentHost, - private RenderViewHostObserver { - public: - RenderViewDevToolsAgentHost(RenderViewHost*); - - private: - virtual ~RenderViewDevToolsAgentHost(); - - // DevToolsAgentHost implementation. - virtual void SendMessageToAgent(IPC::Message* msg) OVERRIDE; - virtual void NotifyClientAttaching() OVERRIDE; - virtual void NotifyClientDetaching() OVERRIDE; - virtual int GetRenderProcessId() OVERRIDE; - - // RenderViewHostObserver overrides. - virtual void RenderViewHostDestroyed(RenderViewHost* rvh) OVERRIDE; - virtual bool OnMessageReceived(const IPC::Message& message) OVERRIDE; - - void OnDispatchOnInspectorFrontend(const std::string& message); - void OnSaveAgentRuntimeState(const std::string& state); - void OnClearBrowserCache(); - void OnClearBrowserCookies(); - - RenderViewHost* render_view_host_; - - DISALLOW_COPY_AND_ASSIGN(RenderViewDevToolsAgentHost); -}; - -} // namespace content - -#endif // CONTENT_BROWSER_DEBUGGER_RENDER_VIEW_DEVTOOLS_AGENT_HOST_H_ diff --git a/content/browser/debugger/worker_devtools_manager.cc b/content/browser/debugger/worker_devtools_manager.cc deleted file mode 100644 index 3dda612..0000000 --- a/content/browser/debugger/worker_devtools_manager.cc +++ /dev/null @@ -1,472 +0,0 @@ -// Copyright (c) 2011 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 "content/browser/debugger/worker_devtools_manager.h" - -#include -#include - -#include "base/bind.h" -#include "content/browser/debugger/devtools_agent_host.h" -#include "content/browser/debugger/devtools_manager_impl.h" -#include "content/browser/debugger/worker_devtools_message_filter.h" -#include "content/browser/worker_host/worker_service_impl.h" -#include "content/common/devtools_messages.h" -#include "content/public/browser/browser_thread.h" -#include "content/public/browser/child_process_data.h" -#include "content/public/browser/devtools_agent_host_registry.h" -#include "content/public/common/process_type.h" -#include "third_party/WebKit/Source/WebKit/chromium/public/platform/WebCString.h" -#include "third_party/WebKit/Source/WebKit/chromium/public/WebDevToolsAgent.h" -#include "third_party/WebKit/Source/WebKit/chromium/public/platform/WebString.h" - -namespace content { - -// Called on the UI thread. -// static -DevToolsAgentHost* DevToolsAgentHostRegistry::GetDevToolsAgentHostForWorker( - int worker_process_id, - int worker_route_id) { - return WorkerDevToolsManager::GetDevToolsAgentHostForWorker( - worker_process_id, - worker_route_id); -} - -class WorkerDevToolsManager::AgentHosts { -public: - static void Add(WorkerId id, WorkerDevToolsAgentHost* host) { - DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); - if (!instance_) - instance_ = new AgentHosts(); - instance_->map_[id] = host; - } - static void Remove(WorkerId id) { - DCHECK(instance_); - DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); - Instances& map = instance_->map_; - map.erase(id); - if (map.empty()) { - delete instance_; - instance_ = NULL; - } - } - - static WorkerDevToolsAgentHost* GetAgentHost(WorkerId id) { - DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); - if (!instance_) - return NULL; - Instances& map = instance_->map_; - Instances::iterator it = map.find(id); - if (it == map.end()) - return NULL; - return it->second; - } - -private: - AgentHosts() { - } - ~AgentHosts() {} - - static AgentHosts* instance_; - typedef std::map Instances; - Instances map_; -}; - -WorkerDevToolsManager::AgentHosts* - WorkerDevToolsManager::AgentHosts::instance_ = NULL; - - -struct WorkerDevToolsManager::TerminatedInspectedWorker { - TerminatedInspectedWorker(WorkerId id, const GURL& url, const string16& name) - : old_worker_id(id), - worker_url(url), - worker_name(name) {} - WorkerId old_worker_id; - GURL worker_url; - string16 worker_name; -}; - - -class WorkerDevToolsManager::WorkerDevToolsAgentHost - : public DevToolsAgentHost { - public: - explicit WorkerDevToolsAgentHost(WorkerId worker_id) - : worker_id_(worker_id) { - AgentHosts::Add(worker_id, this); - BrowserThread::PostTask( - BrowserThread::IO, - FROM_HERE, - base::Bind( - &RegisterAgent, - worker_id.first, - worker_id.second)); - } - - void WorkerDestroyed() { - NotifyCloseListener(); - delete this; - } - - private: - virtual ~WorkerDevToolsAgentHost() { - AgentHosts::Remove(worker_id_); - } - - static void RegisterAgent( - int worker_process_id, - int worker_route_id) { - WorkerDevToolsManager::GetInstance()->RegisterDevToolsAgentHostForWorker( - worker_process_id, worker_route_id); - } - - static void ForwardToWorkerDevToolsAgent( - int worker_process_id, - int worker_route_id, - IPC::Message* message) { - WorkerDevToolsManager::GetInstance()->ForwardToWorkerDevToolsAgent( - worker_process_id, worker_route_id, *message); - } - - // DevToolsAgentHost implementation. - virtual void SendMessageToAgent(IPC::Message* message) OVERRIDE { - BrowserThread::PostTask( - BrowserThread::IO, FROM_HERE, - base::Bind( - &WorkerDevToolsAgentHost::ForwardToWorkerDevToolsAgent, - worker_id_.first, - worker_id_.second, - base::Owned(message))); - } - virtual void NotifyClientAttaching() OVERRIDE {} - virtual void NotifyClientDetaching() OVERRIDE {} - virtual int GetRenderProcessId() OVERRIDE { return -1; } - - WorkerId worker_id_; - - DISALLOW_COPY_AND_ASSIGN(WorkerDevToolsAgentHost); -}; - - -class WorkerDevToolsManager::DetachedClientHosts { - public: - static void WorkerReloaded(WorkerId old_id, WorkerId new_id) { - DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); - if (instance_ && instance_->ReattachClient(old_id, new_id)) - return; - RemovePendingWorkerData(old_id); - } - - static void WorkerDestroyed(WorkerId id) { - DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); - WorkerDevToolsAgentHost* agent = AgentHosts::GetAgentHost(id); - if (!agent) { - RemovePendingWorkerData(id); - return; - } - DevToolsManagerImpl::GetInstance()->DispatchOnInspectorFrontend( - agent, - WebKit::WebDevToolsAgent::workerDisconnectedFromWorkerEvent().utf8()); - int cookie = DevToolsManagerImpl::GetInstance()->DetachClientHost(agent); - agent->WorkerDestroyed(); - if (cookie == -1) { - RemovePendingWorkerData(id); - return; - } - if (!instance_) - new DetachedClientHosts(); - instance_->worker_id_to_cookie_[id] = cookie; - } - - private: - DetachedClientHosts() { - instance_ = this; - } - ~DetachedClientHosts() { - instance_ = NULL; - } - - bool ReattachClient(WorkerId old_id, WorkerId new_id) { - WorkerIdToCookieMap::iterator it = worker_id_to_cookie_.find(old_id); - if (it == worker_id_to_cookie_.end()) - return false; - DevToolsAgentHost* agent = - WorkerDevToolsManager::GetDevToolsAgentHostForWorker( - new_id.first, - new_id.second); - DevToolsManagerImpl::GetInstance()->AttachClientHost( - it->second, - agent); - worker_id_to_cookie_.erase(it); - if (worker_id_to_cookie_.empty()) - delete this; - return true; - } - - static void RemovePendingWorkerData(WorkerId id) { - BrowserThread::PostTask( - BrowserThread::IO, FROM_HERE, - base::Bind(&RemoveInspectedWorkerDataOnIOThread, id)); - } - - static void RemoveInspectedWorkerDataOnIOThread(WorkerId id) { - WorkerDevToolsManager::GetInstance()->RemoveInspectedWorkerData(id); - } - - static DetachedClientHosts* instance_; - typedef std::map WorkerIdToCookieMap; - WorkerIdToCookieMap worker_id_to_cookie_; -}; - -WorkerDevToolsManager::DetachedClientHosts* - WorkerDevToolsManager::DetachedClientHosts::instance_ = NULL; - -struct WorkerDevToolsManager::InspectedWorker { - InspectedWorker(WorkerProcessHost* host, int route_id, const GURL& url, - const string16& name) - : host(host), - route_id(route_id), - worker_url(url), - worker_name(name) {} - WorkerProcessHost* const host; - int const route_id; - GURL worker_url; - string16 worker_name; -}; - -// static -WorkerDevToolsManager* WorkerDevToolsManager::GetInstance() { - DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); - return Singleton::get(); -} - -// static -DevToolsAgentHost* WorkerDevToolsManager::GetDevToolsAgentHostForWorker( - int worker_process_id, - int worker_route_id) { - WorkerId id(worker_process_id, worker_route_id); - WorkerDevToolsAgentHost* result = AgentHosts::GetAgentHost(id); - if (!result) - result = new WorkerDevToolsAgentHost(id); - return result; -} - -WorkerDevToolsManager::WorkerDevToolsManager() { -} - -WorkerDevToolsManager::~WorkerDevToolsManager() { -} - -void WorkerDevToolsManager::WorkerCreated( - WorkerProcessHost* worker, - const WorkerProcessHost::WorkerInstance& instance) { - for (TerminatedInspectedWorkers::iterator it = terminated_workers_.begin(); - it != terminated_workers_.end(); ++it) { - if (instance.Matches(it->worker_url, it->worker_name, - instance.partition(), - instance.resource_context())) { - worker->Send(new DevToolsAgentMsg_PauseWorkerContextOnStart( - instance.worker_route_id())); - WorkerId new_worker_id(worker->GetData().id, instance.worker_route_id()); - paused_workers_[new_worker_id] = it->old_worker_id; - terminated_workers_.erase(it); - return; - } - } -} - -void WorkerDevToolsManager::WorkerDestroyed( - WorkerProcessHost* worker, - int worker_route_id) { - InspectedWorkersList::iterator it = FindInspectedWorker( - worker->GetData().id, - worker_route_id); - if (it == inspected_workers_.end()) - return; - - WorkerId worker_id(worker->GetData().id, worker_route_id); - terminated_workers_.push_back(TerminatedInspectedWorker( - worker_id, - it->worker_url, - it->worker_name)); - inspected_workers_.erase(it); - BrowserThread::PostTask( - BrowserThread::UI, FROM_HERE, - base::Bind(&DetachedClientHosts::WorkerDestroyed, worker_id)); -} - -void WorkerDevToolsManager::WorkerContextStarted(WorkerProcessHost* process, - int worker_route_id) { - WorkerId new_worker_id(process->GetData().id, worker_route_id); - PausedWorkers::iterator it = paused_workers_.find(new_worker_id); - if (it == paused_workers_.end()) - return; - - BrowserThread::PostTask( - BrowserThread::UI, FROM_HERE, - base::Bind( - &DetachedClientHosts::WorkerReloaded, - it->second, - new_worker_id)); - paused_workers_.erase(it); -} - -void WorkerDevToolsManager::RemoveInspectedWorkerData( - const WorkerId& id) { - for (TerminatedInspectedWorkers::iterator it = terminated_workers_.begin(); - it != terminated_workers_.end(); ++it) { - if (it->old_worker_id == id) { - terminated_workers_.erase(it); - return; - } - } - - for (PausedWorkers::iterator it = paused_workers_.begin(); - it != paused_workers_.end(); ++it) { - if (it->second == id) { - SendResumeToWorker(it->first); - paused_workers_.erase(it); - return; - } - } -} - -WorkerDevToolsManager::InspectedWorkersList::iterator -WorkerDevToolsManager::FindInspectedWorker( - int host_id, int route_id) { - InspectedWorkersList::iterator it = inspected_workers_.begin(); - while (it != inspected_workers_.end()) { - if (it->host->GetData().id == host_id && it->route_id == route_id) - break; - ++it; - } - return it; -} - -static WorkerProcessHost* FindWorkerProcess(int worker_process_id) { - for (WorkerProcessHostIterator iter; !iter.Done(); ++iter) { - if (iter.GetData().id == worker_process_id) - return *iter; - } - return NULL; -} - -void WorkerDevToolsManager::RegisterDevToolsAgentHostForWorker( - int worker_process_id, - int worker_route_id) { - if (WorkerProcessHost* process = FindWorkerProcess(worker_process_id)) { - const WorkerProcessHost::Instances& instances = process->instances(); - for (WorkerProcessHost::Instances::const_iterator i = instances.begin(); - i != instances.end(); ++i) { - if (i->worker_route_id() == worker_route_id) { - DCHECK(FindInspectedWorker(worker_process_id, worker_route_id) == - inspected_workers_.end()); - inspected_workers_.push_back( - InspectedWorker(process, worker_route_id, i->url(), i->name())); - return; - } - } - } - NotifyWorkerDestroyedOnIOThread(worker_process_id, worker_route_id); -} - -void WorkerDevToolsManager::ForwardToDevToolsClient( - int worker_process_id, - int worker_route_id, - const std::string& message) { - if (FindInspectedWorker(worker_process_id, worker_route_id) == - inspected_workers_.end()) { - NOTREACHED(); - return; - } - BrowserThread::PostTask( - BrowserThread::UI, FROM_HERE, - base::Bind( - &ForwardToDevToolsClientOnUIThread, - worker_process_id, - worker_route_id, - message)); -} - -void WorkerDevToolsManager::SaveAgentRuntimeState(int worker_process_id, - int worker_route_id, - const std::string& state) { - BrowserThread::PostTask( - BrowserThread::UI, FROM_HERE, - base::Bind( - &SaveAgentRuntimeStateOnUIThread, - worker_process_id, - worker_route_id, - state)); -} - -void WorkerDevToolsManager::ForwardToWorkerDevToolsAgent( - int worker_process_id, - int worker_route_id, - const IPC::Message& message) { - InspectedWorkersList::iterator it = FindInspectedWorker( - worker_process_id, - worker_route_id); - if (it == inspected_workers_.end()) - return; - IPC::Message* msg = new IPC::Message(message); - msg->set_routing_id(worker_route_id); - it->host->Send(msg); -} - -// static -void WorkerDevToolsManager::ForwardToDevToolsClientOnUIThread( - int worker_process_id, - int worker_route_id, - const std::string& message) { - WorkerDevToolsAgentHost* agent_host = AgentHosts::GetAgentHost(WorkerId( - worker_process_id, - worker_route_id)); - if (!agent_host) - return; - DevToolsManagerImpl::GetInstance()->DispatchOnInspectorFrontend(agent_host, - message); -} - -// static -void WorkerDevToolsManager::SaveAgentRuntimeStateOnUIThread( - int worker_process_id, - int worker_route_id, - const std::string& state) { - WorkerDevToolsAgentHost* agent_host = AgentHosts::GetAgentHost(WorkerId( - worker_process_id, - worker_route_id)); - if (!agent_host) - return; - DevToolsManagerImpl::GetInstance()->SaveAgentRuntimeState(agent_host, state); -} - -// static -void WorkerDevToolsManager::NotifyWorkerDestroyedOnIOThread( - int worker_process_id, - int worker_route_id) { - BrowserThread::PostTask( - BrowserThread::UI, FROM_HERE, - base::Bind( - &WorkerDevToolsManager::NotifyWorkerDestroyedOnUIThread, - worker_process_id, - worker_route_id)); -} - -// static -void WorkerDevToolsManager::NotifyWorkerDestroyedOnUIThread( - int worker_process_id, - int worker_route_id) { - WorkerDevToolsAgentHost* host = - AgentHosts::GetAgentHost(WorkerId(worker_process_id, worker_route_id)); - if (host) - host->WorkerDestroyed(); -} - -// static -void WorkerDevToolsManager::SendResumeToWorker(const WorkerId& id) { - if (WorkerProcessHost* process = FindWorkerProcess(id.first)) - process->Send(new DevToolsAgentMsg_ResumeWorkerContext(id.second)); -} - -} // namespace content diff --git a/content/browser/debugger/worker_devtools_manager.h b/content/browser/debugger/worker_devtools_manager.h deleted file mode 100644 index e416727..0000000 --- a/content/browser/debugger/worker_devtools_manager.h +++ /dev/null @@ -1,109 +0,0 @@ -// Copyright (c) 2012 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 CONTENT_BROWSER_DEBUGGER_WORKER_DEVTOOLS_MANAGER_H_ -#define CONTENT_BROWSER_DEBUGGER_WORKER_DEVTOOLS_MANAGER_H_ - -#include -#include -#include - -#include "base/basictypes.h" -#include "base/memory/singleton.h" -#include "content/common/content_export.h" -#include "content/browser/worker_host/worker_process_host.h" - -namespace content { - -class DevToolsAgentHost; - -// All methods are supposed to be called on the IO thread. -class WorkerDevToolsManager { - public: - // Returns the WorkerDevToolsManager singleton. - static WorkerDevToolsManager* GetInstance(); - - // Called on the UI thread. - static DevToolsAgentHost* GetDevToolsAgentHostForWorker( - int worker_process_id, - int worker_route_id); - - void ForwardToDevToolsClient(int worker_process_id, - int worker_route_id, - const std::string& message); - void SaveAgentRuntimeState(int worker_process_id, - int worker_route_id, - const std::string& state); - - // Called on the IO thread. - void WorkerCreated( - WorkerProcessHost* process, - const WorkerProcessHost::WorkerInstance& instance); - void WorkerDestroyed(WorkerProcessHost* process, int worker_route_id); - void WorkerContextStarted(WorkerProcessHost* process, int worker_route_id); - - private: - friend struct DefaultSingletonTraits; - typedef std::pair WorkerId; - class AgentHosts; - class DetachedClientHosts; - class WorkerDevToolsAgentHost; - struct InspectedWorker; - typedef std::list InspectedWorkersList; - - WorkerDevToolsManager(); - virtual ~WorkerDevToolsManager(); - - void RemoveInspectedWorkerData(const WorkerId& id); - InspectedWorkersList::iterator FindInspectedWorker(int host_id, int route_id); - - void RegisterDevToolsAgentHostForWorker(int worker_process_id, - int worker_route_id); - void ForwardToWorkerDevToolsAgent(int worker_process_host_id, - int worker_route_id, - const IPC::Message& message); - static void ForwardToDevToolsClientOnUIThread( - int worker_process_id, - int worker_route_id, - const std::string& message); - static void SaveAgentRuntimeStateOnUIThread( - int worker_process_id, - int worker_route_id, - const std::string& state); - static void NotifyWorkerDestroyedOnIOThread(int worker_process_id, - int worker_route_id); - static void NotifyWorkerDestroyedOnUIThread(int worker_process_id, - int worker_route_id); - static void SendResumeToWorker(const WorkerId& id); - - InspectedWorkersList inspected_workers_; - - struct TerminatedInspectedWorker; - typedef std::list TerminatedInspectedWorkers; - // List of terminated workers for which there may be a devtools client on - // the UI thread. Worker entry is added into this list when inspected worker - // is terminated and will be removed in one of two cases: - // - shared worker with the same URL and name is started(in wich case we will - // try to reattach existing DevTools client to the new worker). - // - DevTools client which was inspecting terminated worker is closed on the - // UI thread and and WorkerDevToolsManager is notified about that on the IO - // thread. - TerminatedInspectedWorkers terminated_workers_; - - typedef std::map PausedWorkers; - // Map from old to new worker id for the inspected workers that have been - // terminated and started again in paused state. Worker data will be removed - // from this list in one of two cases: - // - DevTools client is closed on the UI thread, WorkerDevToolsManager was - // notified about that on the IO thread and sent "resume" message to the - // worker. - // - Existing DevTools client was reattached to the new worker. - PausedWorkers paused_workers_; - - DISALLOW_COPY_AND_ASSIGN(WorkerDevToolsManager); -}; - -} // namespace content - -#endif // CONTENT_BROWSER_DEBUGGER_WORKER_DEVTOOLS_MANAGER_H_ diff --git a/content/browser/debugger/worker_devtools_message_filter.cc b/content/browser/debugger/worker_devtools_message_filter.cc deleted file mode 100644 index 5a1fba5..0000000 --- a/content/browser/debugger/worker_devtools_message_filter.cc +++ /dev/null @@ -1,50 +0,0 @@ -// Copyright (c) 2011 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 "content/browser/debugger/worker_devtools_message_filter.h" - -#include "content/browser/debugger/worker_devtools_manager.h" -#include "content/common/devtools_messages.h" -#include "content/common/worker_messages.h" - -namespace content { - -WorkerDevToolsMessageFilter::WorkerDevToolsMessageFilter( - int worker_process_host_id) - : worker_process_host_id_(worker_process_host_id), - current_routing_id_(0) { -} - -WorkerDevToolsMessageFilter::~WorkerDevToolsMessageFilter() { -} - -bool WorkerDevToolsMessageFilter::OnMessageReceived( - const IPC::Message& message, - bool* message_was_ok) { - bool handled = true; - current_routing_id_ = message.routing_id(); - IPC_BEGIN_MESSAGE_MAP_EX(WorkerDevToolsMessageFilter, message, - *message_was_ok) - IPC_MESSAGE_HANDLER(DevToolsClientMsg_DispatchOnInspectorFrontend, - OnDispatchOnInspectorFrontend) - IPC_MESSAGE_HANDLER(DevToolsHostMsg_SaveAgentRuntimeState, - OnSaveAgentRumtimeState) - IPC_MESSAGE_UNHANDLED(handled = false) - IPC_END_MESSAGE_MAP_EX() - return handled; -} - -void WorkerDevToolsMessageFilter::OnDispatchOnInspectorFrontend( - const std::string& message) { - WorkerDevToolsManager::GetInstance()->ForwardToDevToolsClient( - worker_process_host_id_, current_routing_id_, message); -} - -void WorkerDevToolsMessageFilter::OnSaveAgentRumtimeState( - const std::string& state) { - WorkerDevToolsManager::GetInstance()->SaveAgentRuntimeState( - worker_process_host_id_, current_routing_id_, state); -} - -} // namespace content diff --git a/content/browser/debugger/worker_devtools_message_filter.h b/content/browser/debugger/worker_devtools_message_filter.h deleted file mode 100644 index e50dfa8..0000000 --- a/content/browser/debugger/worker_devtools_message_filter.h +++ /dev/null @@ -1,35 +0,0 @@ -// Copyright (c) 2012 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 CONTENT_BROWSER_DEBUGGER_WORKER_DEVTOOLS_MESSAGE_FILTER_H_ -#define CONTENT_BROWSER_DEBUGGER_WORKER_DEVTOOLS_MESSAGE_FILTER_H_ - -#include "base/callback_forward.h" -#include "content/public/browser/browser_message_filter.h" - -namespace content { - -class WorkerDevToolsMessageFilter : public BrowserMessageFilter { - public: - explicit WorkerDevToolsMessageFilter(int worker_process_host_id); - - private: - virtual ~WorkerDevToolsMessageFilter(); - - // BrowserMessageFilter implementation. - virtual bool OnMessageReceived(const IPC::Message& message, - bool* message_was_ok) OVERRIDE; - // Message handlers. - void OnDispatchOnInspectorFrontend(const std::string& message); - void OnSaveAgentRumtimeState(const std::string& state); - - int worker_process_host_id_; - int current_routing_id_; - - DISALLOW_COPY_AND_ASSIGN(WorkerDevToolsMessageFilter); -}; - -} // namespace content - -#endif // CONTENT_BROWSER_DEBUGGER_WORKER_DEVTOOLS_MESSAGE_FILTER_H_ diff --git a/content/browser/devtools/DEPS b/content/browser/devtools/DEPS new file mode 100644 index 0000000..3e98aee --- /dev/null +++ b/content/browser/devtools/DEPS @@ -0,0 +1,4 @@ +include_rules = [ + # Generated by the local devtools_resources.gyp:devtools_resources + "+grit/devtools_resources_map.h", +] diff --git a/content/browser/devtools/OWNERS b/content/browser/devtools/OWNERS new file mode 100644 index 0000000..bb6028e --- /dev/null +++ b/content/browser/devtools/OWNERS @@ -0,0 +1,2 @@ +pfeldman@chromium.org +yurys@chromium.org diff --git a/content/browser/devtools/devtools_agent_host.cc b/content/browser/devtools/devtools_agent_host.cc new file mode 100644 index 0000000..fa5bc0e --- /dev/null +++ b/content/browser/devtools/devtools_agent_host.cc @@ -0,0 +1,57 @@ +// Copyright (c) 2012 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 "content/browser/devtools/devtools_agent_host.h" + +#include "base/basictypes.h" +#include "content/common/devtools_messages.h" + +namespace content { + +DevToolsAgentHost::DevToolsAgentHost() : close_listener_(NULL) { +} + +void DevToolsAgentHost::Attach() { + SendMessageToAgent(new DevToolsAgentMsg_Attach(MSG_ROUTING_NONE)); + NotifyClientAttaching(); +} + +void DevToolsAgentHost::Reattach(const std::string& saved_agent_state) { + SendMessageToAgent(new DevToolsAgentMsg_Reattach( + MSG_ROUTING_NONE, + saved_agent_state)); + NotifyClientAttaching(); +} + +void DevToolsAgentHost::Detach() { + SendMessageToAgent(new DevToolsAgentMsg_Detach(MSG_ROUTING_NONE)); + NotifyClientDetaching(); +} + +void DevToolsAgentHost::DipatchOnInspectorBackend(const std::string& message) { + SendMessageToAgent(new DevToolsAgentMsg_DispatchOnInspectorBackend( + MSG_ROUTING_NONE, message)); +} + +void DevToolsAgentHost::InspectElement(int x, int y) { + SendMessageToAgent(new DevToolsAgentMsg_InspectElement(MSG_ROUTING_NONE, + x, y)); +} + +void DevToolsAgentHost::AddMessageToConsole(ConsoleMessageLevel level, + const std::string& message) { + SendMessageToAgent(new DevToolsAgentMsg_AddMessageToConsole( + MSG_ROUTING_NONE, + level, + message)); +} + +void DevToolsAgentHost::NotifyCloseListener() { + if (close_listener_) { + close_listener_->AgentHostClosing(this); + close_listener_ = NULL; + } +} + +} // namespace content diff --git a/content/browser/devtools/devtools_agent_host.h b/content/browser/devtools/devtools_agent_host.h new file mode 100644 index 0000000..ae44862 --- /dev/null +++ b/content/browser/devtools/devtools_agent_host.h @@ -0,0 +1,59 @@ +// Copyright (c) 2012 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 CONTENT_BROWSER_DEVTOOLS_DEVTOOLS_AGENT_HOST_H_ +#define CONTENT_BROWSER_DEVTOOLS_DEVTOOLS_AGENT_HOST_H_ + +#include + +#include "content/common/content_export.h" +#include "content/public/common/console_message_level.h" + +namespace IPC { +class Message; +} + +namespace content { + +// Describes interface for managing devtools agents from the browser process. +class CONTENT_EXPORT DevToolsAgentHost { + public: + class CONTENT_EXPORT CloseListener { + public: + virtual void AgentHostClosing(DevToolsAgentHost*) = 0; + protected: + virtual ~CloseListener() {} + }; + + // Sends the message to the devtools agent hosted by this object. + void Attach(); + void Reattach(const std::string& saved_agent_state); + void Detach(); + void DipatchOnInspectorBackend(const std::string& message); + void InspectElement(int x, int y); + void AddMessageToConsole(ConsoleMessageLevel level, + const std::string& message); + + virtual int GetRenderProcessId() = 0; + + void set_close_listener(CloseListener* listener) { + close_listener_ = listener; + } + + protected: + DevToolsAgentHost(); + virtual ~DevToolsAgentHost() {} + + virtual void SendMessageToAgent(IPC::Message* msg) = 0; + virtual void NotifyClientAttaching() = 0; + virtual void NotifyClientDetaching() = 0; + + void NotifyCloseListener(); + + CloseListener* close_listener_; +}; + +} // namespace content + +#endif // CONTENT_BROWSER_DEVTOOLS_DEVTOOLS_AGENT_HOST_H_ diff --git a/content/browser/devtools/devtools_browser_target.cc b/content/browser/devtools/devtools_browser_target.cc new file mode 100644 index 0000000..44291b4 --- /dev/null +++ b/content/browser/devtools/devtools_browser_target.cc @@ -0,0 +1,118 @@ +// Copyright (c) 2012 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 "content/browser/devtools/devtools_browser_target.h" + +#include "base/json/json_reader.h" +#include "base/json/json_writer.h" +#include "base/logging.h" +#include "base/memory/scoped_ptr.h" +#include "base/values.h" + + +namespace content { + +DevToolsBrowserTarget::DevToolsBrowserTarget(int connection_id) + : connection_id_(connection_id) { +} + +DevToolsBrowserTarget::~DevToolsBrowserTarget() { + for (HandlersMap::iterator i = handlers_.begin(); i != handlers_.end(); ++i) + delete i->second; +} + +void DevToolsBrowserTarget::RegisterHandler(Handler* handler) { + std::string domain = handler->Domain(); + DCHECK(handlers_.find(domain) == handlers_.end()); + handlers_[domain] = handler; +} + +std::string DevToolsBrowserTarget::HandleMessage(const std::string& data) { + int error_code; + std::string error_message; + scoped_ptr command( + base::JSONReader::ReadAndReturnError( + data, 0, &error_code, &error_message)); + + if (!command || !command->IsType(base::Value::TYPE_DICTIONARY)) + return SerializeErrorResponse( + -1, CreateErrorObject(error_code, error_message)); + + int request_id; + std::string domain; + std::string method; + base::DictionaryValue* command_dict = NULL; + bool ok = true; + ok &= command->GetAsDictionary(&command_dict); + ok &= command_dict->GetInteger("id", &request_id); + ok &= command_dict->GetString("method", &method); + if (!ok) + return SerializeErrorResponse( + request_id, CreateErrorObject(-1, "Malformed request")); + + base::DictionaryValue* params = NULL; + command_dict->GetDictionary("params", ¶ms); + + size_t pos = method.find("."); + if (pos == std::string::npos) + return SerializeErrorResponse( + request_id, CreateErrorObject(-1, "Method unsupported")); + + domain = method.substr(0, pos); + if (domain.empty() || handlers_.find(domain) == handlers_.end()) + return SerializeErrorResponse( + request_id, CreateErrorObject(-1, "Domain unsupported")); + + base::Value* error_object = NULL; + base::Value* domain_result = handlers_[domain]->OnProtocolCommand( + method, params, &error_object); + + if (error_object) + return SerializeErrorResponse(request_id, error_object); + + if (!domain_result) + return SerializeErrorResponse( + request_id, CreateErrorObject(-1, "Invalid call")); + + DictionaryValue* response = new DictionaryValue(); + response->Set("result", domain_result); + return SerializeResponse(request_id, response); +} + +std::string DevToolsBrowserTarget::SerializeErrorResponse( + int request_id, base::Value* error_object) { + scoped_ptr error_response(new base::DictionaryValue()); + error_response->SetInteger("id", request_id); + error_response->Set("error", error_object); + // Serialize response. + std::string json_response; + base::JSONWriter::WriteWithOptions(error_response.get(), + base::JSONWriter::OPTIONS_PRETTY_PRINT, + &json_response); + return json_response; +} + +base::Value* DevToolsBrowserTarget::CreateErrorObject( + int error_code, const std::string& message) { + base::DictionaryValue* error_object = new base::DictionaryValue(); + error_object->SetInteger("code", error_code); + error_object->SetString("message", message); + return error_object; +} + +std::string DevToolsBrowserTarget::SerializeResponse( + int request_id, base::Value* response) { + scoped_ptr ret(new base::DictionaryValue()); + ret->SetInteger("id", request_id); + ret->Set("response", response); + + // Serialize response. + std::string json_response; + base::JSONWriter::WriteWithOptions(ret.get(), + base::JSONWriter::OPTIONS_PRETTY_PRINT, + &json_response); + return json_response; +} + +} // namespace content diff --git a/content/browser/devtools/devtools_browser_target.h b/content/browser/devtools/devtools_browser_target.h new file mode 100644 index 0000000..a0a34e3 --- /dev/null +++ b/content/browser/devtools/devtools_browser_target.h @@ -0,0 +1,68 @@ +// Copyright (c) 2012 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 CONTENT_BROWSER_DEVTOOLS_DEVTOOLS_BROWSER_TARGET_H_ +#define CONTENT_BROWSER_DEVTOOLS_DEVTOOLS_BROWSER_TARGET_H_ + +#include +#include + +#include "base/basictypes.h" + +namespace base { + +class DictionaryValue; +class Value; + +} // namespace base + +namespace content { + +// This class handles the "Browser" target for remote debugging. +class DevToolsBrowserTarget { + public: + class Handler { + public: + virtual ~Handler() {} + + // Returns the domain name for this handler. + virtual std::string Domain() = 0; + + // |return_value| and |error_message_out| ownership is transferred to the + // caller. + virtual base::Value* OnProtocolCommand( + const std::string& method, + const base::DictionaryValue* params, + base::Value** error_message_out) = 0; + }; + + explicit DevToolsBrowserTarget(int connection_id); + ~DevToolsBrowserTarget(); + + int connection_id() const { return connection_id_; } + + // Takes ownership of |handler|. + void RegisterHandler(Handler* handler); + + std::string HandleMessage(const std::string& data); + + private: + const int connection_id_; + + typedef std::map HandlersMap; + HandlersMap handlers_; + + // Takes ownership of |error_object|. + std::string SerializeErrorResponse(int request_id, base::Value* error_object); + + base::Value* CreateErrorObject(int error_code, const std::string& message); + + std::string SerializeResponse(int request_id, base::Value* response); + + DISALLOW_COPY_AND_ASSIGN(DevToolsBrowserTarget); +}; + +} // namespace content + +#endif // CONTENT_BROWSER_DEVTOOLS_DEVTOOLS_BROWSER_TARGET_H_ diff --git a/content/browser/devtools/devtools_frontend_host.cc b/content/browser/devtools/devtools_frontend_host.cc new file mode 100644 index 0000000..fe7e82d --- /dev/null +++ b/content/browser/devtools/devtools_frontend_host.cc @@ -0,0 +1,125 @@ +// Copyright (c) 2012 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 "content/browser/devtools/devtools_frontend_host.h" + +#include "content/browser/devtools/devtools_manager_impl.h" +#include "content/browser/renderer_host/render_view_host_impl.h" +#include "content/browser/web_contents/web_contents_impl.h" +#include "content/common/devtools_messages.h" +#include "content/public/browser/devtools_client_host.h" +#include "content/public/browser/devtools_frontend_host_delegate.h" + +namespace content { + +// static +DevToolsClientHost* DevToolsClientHost::CreateDevToolsFrontendHost( + WebContents* client_web_contents, + DevToolsFrontendHostDelegate* delegate) { + return new DevToolsFrontendHost( + static_cast(client_web_contents), delegate); +} + +// static +void DevToolsClientHost::SetupDevToolsFrontendClient( + RenderViewHost* frontend_rvh) { + frontend_rvh->Send(new DevToolsMsg_SetupDevToolsClient( + frontend_rvh->GetRoutingID())); +} + +DevToolsFrontendHost::DevToolsFrontendHost( + WebContentsImpl* web_contents, + DevToolsFrontendHostDelegate* delegate) + : RenderViewHostObserver(web_contents->GetRenderViewHost()), + web_contents_(web_contents), + delegate_(delegate) { +} + +DevToolsFrontendHost::~DevToolsFrontendHost() { + DevToolsManager::GetInstance()->ClientHostClosing(this); +} + +void DevToolsFrontendHost::DispatchOnInspectorFrontend( + const std::string& message) { + RenderViewHostImpl* target_host = + static_cast(web_contents_->GetRenderViewHost()); + target_host->Send(new DevToolsClientMsg_DispatchOnInspectorFrontend( + target_host->GetRoutingID(), + message)); +} + +void DevToolsFrontendHost::InspectedContentsClosing() { + delegate_->InspectedContentsClosing(); +} + +void DevToolsFrontendHost::FrameNavigating(const std::string& url) { + delegate_->FrameNavigating(url); +} + +void DevToolsFrontendHost::ContentsReplaced(WebContents* new_contents) { + delegate_->ContentsReplaced(new_contents); +} + +void DevToolsFrontendHost::ReplacedWithAnotherClient() { +} + +bool DevToolsFrontendHost::OnMessageReceived( + const IPC::Message& message) { + bool handled = true; + IPC_BEGIN_MESSAGE_MAP(DevToolsFrontendHost, message) + IPC_MESSAGE_HANDLER(DevToolsAgentMsg_DispatchOnInspectorBackend, + OnDispatchOnInspectorBackend) + IPC_MESSAGE_HANDLER(DevToolsHostMsg_ActivateWindow, OnActivateWindow) + IPC_MESSAGE_HANDLER(DevToolsHostMsg_CloseWindow, OnCloseWindow) + IPC_MESSAGE_HANDLER(DevToolsHostMsg_MoveWindow, OnMoveWindow) + IPC_MESSAGE_HANDLER(DevToolsHostMsg_RequestSetDockSide, + OnRequestSetDockSide) + IPC_MESSAGE_HANDLER(DevToolsHostMsg_OpenInNewTab, OnOpenInNewTab) + IPC_MESSAGE_HANDLER(DevToolsHostMsg_Save, OnSave) + IPC_MESSAGE_HANDLER(DevToolsHostMsg_Append, OnAppend) + IPC_MESSAGE_UNHANDLED(handled = false) + IPC_END_MESSAGE_MAP() + return handled; +} + +void DevToolsFrontendHost::OnDispatchOnInspectorBackend( + const std::string& message) { + DevToolsManagerImpl::GetInstance()->DispatchOnInspectorBackend(this, message); +// delegate_->DispatchOnInspectorBackend(message); +} + +void DevToolsFrontendHost::OnActivateWindow() { + delegate_->ActivateWindow(); +} + +void DevToolsFrontendHost::OnCloseWindow() { + delegate_->CloseWindow(); +} + +void DevToolsFrontendHost::OnMoveWindow(int x, int y) { + delegate_->MoveWindow(x, y); +} + +void DevToolsFrontendHost::OnOpenInNewTab(const std::string& url) { + delegate_->OpenInNewTab(url); +} + +void DevToolsFrontendHost::OnSave( + const std::string& url, + const std::string& content, + bool save_as) { + delegate_->SaveToFile(url, content, save_as); +} + +void DevToolsFrontendHost::OnAppend( + const std::string& url, + const std::string& content) { + delegate_->AppendToFile(url, content); +} + +void DevToolsFrontendHost::OnRequestSetDockSide(const std::string& side) { + delegate_->SetDockSide(side); +} + +} // namespace content diff --git a/content/browser/devtools/devtools_frontend_host.h b/content/browser/devtools/devtools_frontend_host.h new file mode 100644 index 0000000..6168692 --- /dev/null +++ b/content/browser/devtools/devtools_frontend_host.h @@ -0,0 +1,59 @@ +// Copyright (c) 2012 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 CONTENT_BROWSER_DEVTOOLS_DEVTOOLS_FRONTEND_HOST_H_ +#define CONTENT_BROWSER_DEVTOOLS_DEVTOOLS_FRONTEND_HOST_H_ + +#include + +#include "base/basictypes.h" +#include "base/compiler_specific.h" +#include "content/public/browser/devtools_client_host.h" +#include "content/public/browser/render_view_host_observer.h" + +namespace content { + +class DevToolsFrontendHostDelegate; +class WebContentsImpl; + +// This class handles messages from DevToolsClient and calls corresponding +// methods on DevToolsFrontendHostDelegate which is implemented by the +// embedder. This allows us to avoid exposing DevTools client messages through +// the content public API. +class DevToolsFrontendHost : public DevToolsClientHost, + public RenderViewHostObserver { + public: + DevToolsFrontendHost(WebContentsImpl* web_contents, + DevToolsFrontendHostDelegate* delegate); + + private: + virtual ~DevToolsFrontendHost(); + + // DevToolsClientHost implementation. + virtual void DispatchOnInspectorFrontend(const std::string& message) OVERRIDE; + virtual void InspectedContentsClosing() OVERRIDE; + virtual void FrameNavigating(const std::string& url) OVERRIDE; + virtual void ContentsReplaced(WebContents* new_contents) OVERRIDE; + virtual void ReplacedWithAnotherClient() OVERRIDE; + + // RenderViewHostObserver overrides. + virtual bool OnMessageReceived(const IPC::Message& message) OVERRIDE; + + void OnDispatchOnInspectorBackend(const std::string& message); + void OnActivateWindow(); + void OnCloseWindow(); + void OnMoveWindow(int x, int y); + void OnRequestSetDockSide(const std::string& side); + void OnOpenInNewTab(const std::string& url); + void OnSave(const std::string& url, const std::string& content, bool save_as); + void OnAppend(const std::string& url, const std::string& content); + + WebContentsImpl* web_contents_; + DevToolsFrontendHostDelegate* delegate_; + DISALLOW_COPY_AND_ASSIGN(DevToolsFrontendHost); +}; + +} // namespace content + +#endif // CONTENT_BROWSER_DEVTOOLS_DEVTOOLS_FRONTEND_HOST_H_ diff --git a/content/browser/devtools/devtools_http_handler_impl.cc b/content/browser/devtools/devtools_http_handler_impl.cc new file mode 100644 index 0000000..6d214ab --- /dev/null +++ b/content/browser/devtools/devtools_http_handler_impl.cc @@ -0,0 +1,873 @@ +// Copyright (c) 2012 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 "content/browser/devtools/devtools_http_handler_impl.h" + +#include +#include + +#include "base/bind.h" +#include "base/compiler_specific.h" +#include "base/file_util.h" +#include "base/json/json_writer.h" +#include "base/lazy_instance.h" +#include "base/logging.h" +#include "base/message_loop_proxy.h" +#include "base/string_number_conversions.h" +#include "base/stringprintf.h" +#include "base/threading/thread.h" +#include "base/utf_string_conversions.h" +#include "base/values.h" +#include "content/browser/devtools/devtools_browser_target.h" +#include "content/browser/devtools/devtools_tracing_handler.h" +#include "content/browser/web_contents/web_contents_impl.h" +#include "content/common/devtools_messages.h" +#include "content/public/browser/browser_thread.h" +#include "content/public/browser/devtools_agent_host_registry.h" +#include "content/public/browser/devtools_client_host.h" +#include "content/public/browser/devtools_http_handler_delegate.h" +#include "content/public/browser/devtools_manager.h" +#include "content/public/browser/favicon_status.h" +#include "content/public/browser/navigation_entry.h" +#include "content/public/browser/notification_service.h" +#include "content/public/browser/notification_types.h" +#include "content/public/browser/render_process_host.h" +#include "content/public/browser/render_view_host.h" +#include "content/public/browser/render_widget_host.h" +#include "content/public/common/content_client.h" +#include "content/public/common/url_constants.h" +#include "googleurl/src/gurl.h" +#include "grit/devtools_resources_map.h" +#include "net/base/escape.h" +#include "net/base/io_buffer.h" +#include "net/base/ip_endpoint.h" +#include "net/server/http_server_request_info.h" +#include "third_party/WebKit/Source/WebKit/chromium/public/WebDevToolsAgent.h" +#include "third_party/WebKit/Source/WebKit/chromium/public/platform/WebString.h" +#include "ui/base/layout.h" +#include "webkit/user_agent/user_agent.h" +#include "webkit/user_agent/user_agent_util.h" + +namespace content { + +const int kBufferSize = 16 * 1024; + +namespace { + +static const char* kDevToolsHandlerThreadName = "Chrome_DevToolsHandlerThread"; + +class DevToolsDefaultBindingHandler + : public DevToolsHttpHandler::RenderViewHostBinding { + public: + DevToolsDefaultBindingHandler() { + } + + virtual std::string GetIdentifier(RenderViewHost* rvh) OVERRIDE { + int process_id = rvh->GetProcess()->GetID(); + int routing_id = rvh->GetRoutingID(); + return base::StringPrintf("%d_%d", process_id, routing_id); + } + + virtual RenderViewHost* ForIdentifier( + const std::string& identifier) OVERRIDE { + size_t pos = identifier.find("_"); + if (pos == std::string::npos) + return NULL; + + int process_id; + if (!base::StringToInt(identifier.substr(0, pos), &process_id)) + return NULL; + + int routing_id; + if (!base::StringToInt(identifier.substr(pos+1), &routing_id)) + return NULL; + + return RenderViewHost::FromID(process_id, routing_id); + } +}; + + +// An internal implementation of DevToolsClientHost that delegates +// messages sent for DevToolsClient to a DebuggerShell instance. +class DevToolsClientHostImpl : public DevToolsClientHost { + public: + DevToolsClientHostImpl( + MessageLoop* message_loop, + net::HttpServer* server, + int connection_id) + : message_loop_(message_loop), + server_(server), + connection_id_(connection_id), + is_closed_(false), + detach_reason_("target_closed") { + } + + ~DevToolsClientHostImpl() {} + + // DevToolsClientHost interface + virtual void InspectedContentsClosing() { + if (is_closed_) + return; + is_closed_ = true; + + std::string response = + WebKit::WebDevToolsAgent::inspectorDetachedEvent( + WebKit::WebString::fromUTF8(detach_reason_)).utf8(); + message_loop_->PostTask( + FROM_HERE, + base::Bind(&net::HttpServer::SendOverWebSocket, + server_, + connection_id_, + response)); + + message_loop_->PostTask( + FROM_HERE, + base::Bind(&net::HttpServer::Close, server_, connection_id_)); + } + + virtual void DispatchOnInspectorFrontend(const std::string& data) { + message_loop_->PostTask( + FROM_HERE, + base::Bind(&net::HttpServer::SendOverWebSocket, + server_, + connection_id_, + data)); + } + + virtual void ContentsReplaced(WebContents* new_contents) { + } + + virtual void ReplacedWithAnotherClient() { + detach_reason_ = "replaced_with_devtools"; + } + + private: + virtual void FrameNavigating(const std::string& url) {} + MessageLoop* message_loop_; + net::HttpServer* server_; + int connection_id_; + bool is_closed_; + std::string detach_reason_; +}; + +} // namespace + +// static +int DevToolsHttpHandler::GetFrontendResourceId(const std::string& name) { + for (size_t i = 0; i < kDevtoolsResourcesSize; ++i) { + if (name == kDevtoolsResources[i].name) + return kDevtoolsResources[i].value; + } + return -1; +} + +// static +DevToolsHttpHandler* DevToolsHttpHandler::Start( + const net::StreamListenSocketFactory* socket_factory, + const std::string& frontend_url, + DevToolsHttpHandlerDelegate* delegate) { + DevToolsHttpHandlerImpl* http_handler = + new DevToolsHttpHandlerImpl(socket_factory, + frontend_url, + delegate); + http_handler->Start(); + return http_handler; +} + +DevToolsHttpHandlerImpl::~DevToolsHttpHandlerImpl() { + DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); + // Stop() must be called prior to destruction. + DCHECK(server_.get() == NULL); + DCHECK(thread_.get() == NULL); +} + +void DevToolsHttpHandlerImpl::Start() { + if (thread_.get()) + return; + thread_.reset(new base::Thread(kDevToolsHandlerThreadName)); + BrowserThread::PostTask( + BrowserThread::FILE, FROM_HERE, + base::Bind(&DevToolsHttpHandlerImpl::StartHandlerThread, this)); +} + +// Runs on FILE thread. +void DevToolsHttpHandlerImpl::StartHandlerThread() { + base::Thread::Options options; + options.message_loop_type = MessageLoop::TYPE_IO; + if (!thread_->StartWithOptions(options)) { + BrowserThread::PostTask( + BrowserThread::UI, FROM_HERE, + base::Bind(&DevToolsHttpHandlerImpl::ResetHandlerThread, this)); + return; + } + + thread_->message_loop()->PostTask( + FROM_HERE, + base::Bind(&DevToolsHttpHandlerImpl::Init, this)); +} + +void DevToolsHttpHandlerImpl::ResetHandlerThread() { + thread_.reset(); +} + +void DevToolsHttpHandlerImpl::ResetHandlerThreadAndRelease() { + ResetHandlerThread(); + Release(); +} + +void DevToolsHttpHandlerImpl::Stop() { + if (!thread_.get()) + return; + BrowserThread::PostTaskAndReply( + BrowserThread::FILE, FROM_HERE, + base::Bind(&DevToolsHttpHandlerImpl::StopHandlerThread, this), + base::Bind(&DevToolsHttpHandlerImpl::ResetHandlerThreadAndRelease, this)); +} + +void DevToolsHttpHandlerImpl::SetRenderViewHostBinding( + RenderViewHostBinding* binding) { + if (binding) + binding_ = binding; + else + binding_ = default_binding_.get(); +} + +GURL DevToolsHttpHandlerImpl::GetFrontendURL(RenderViewHost* render_view_host) { + net::IPEndPoint ip_address; + if (server_->GetLocalAddress(&ip_address)) + return GURL(); + std::string host = ip_address.ToString(); + std::string id = binding_->GetIdentifier(render_view_host); + return GURL(std::string("http://") + + ip_address.ToString() + + GetFrontendURLInternal(id, host)); +} + +static std::string PathWithoutParams(const std::string& path) { + size_t query_position = path.find("?"); + if (query_position != std::string::npos) + return path.substr(0, query_position); + return path; +} + +static std::string GetMimeType(const std::string& filename) { + if (EndsWith(filename, ".html", false)) { + return "text/html"; + } else if (EndsWith(filename, ".css", false)) { + return "text/css"; + } else if (EndsWith(filename, ".js", false)) { + return "application/javascript"; + } else if (EndsWith(filename, ".png", false)) { + return "image/png"; + } else if (EndsWith(filename, ".gif", false)) { + return "image/gif"; + } + NOTREACHED(); + return "text/plain"; +} + +void DevToolsHttpHandlerImpl::Observe(int type, + const NotificationSource& source, + const NotificationDetails& details) { + RenderProcessHost* process = Source(source).ptr(); + DevToolsManager* manager = DevToolsManager::GetInstance(); + for (ConnectionToClientHostMap::iterator it = + connection_to_client_host_ui_.begin(); + it != connection_to_client_host_ui_.end(); ++it) { + DevToolsAgentHost* agent = manager->GetDevToolsAgentHostFor(it->second); + if (!agent) + continue; + RenderViewHost* rvh = DevToolsAgentHostRegistry::GetRenderViewHost(agent); + if (rvh && rvh->GetProcess() == process) + it->second->InspectedContentsClosing(); + } +} + +void DevToolsHttpHandlerImpl::OnHttpRequest( + int connection_id, + const net::HttpServerRequestInfo& info) { + if (info.path.find("/json") == 0) { + BrowserThread::PostTask( + BrowserThread::UI, + FROM_HERE, + base::Bind(&DevToolsHttpHandlerImpl::OnJsonRequestUI, + this, + connection_id, + info)); + return; + } + + if (info.path.find("/thumb/") == 0) { + // Thumbnail request. + BrowserThread::PostTask( + BrowserThread::UI, + FROM_HERE, + base::Bind(&DevToolsHttpHandlerImpl::OnThumbnailRequestUI, + this, + connection_id, + info)); + return; + } + + if (info.path == "" || info.path == "/") { + // Discovery page request. + BrowserThread::PostTask( + BrowserThread::UI, + FROM_HERE, + base::Bind(&DevToolsHttpHandlerImpl::OnDiscoveryPageRequestUI, + this, + connection_id)); + return; + } + + if (info.path.find("/devtools/") != 0) { + server_->Send404(connection_id); + return; + } + + std::string filename = PathWithoutParams(info.path.substr(10)); + std::string mime_type = GetMimeType(filename); + + FilePath frontend_dir = delegate_->GetDebugFrontendDir(); + if (!frontend_dir.empty()) { + FilePath path = frontend_dir.AppendASCII(filename); + std::string data; + file_util::ReadFileToString(path, &data); + server_->Send200(connection_id, data, mime_type); + return; + } + if (delegate_->BundlesFrontendResources()) { + int resource_id = DevToolsHttpHandler::GetFrontendResourceId(filename); + if (resource_id != -1) { + base::StringPiece data = GetContentClient()->GetDataResource( + resource_id, ui::SCALE_FACTOR_NONE); + server_->Send200(connection_id, data.as_string(), mime_type); + return; + } + } + server_->Send404(connection_id); +} + +void DevToolsHttpHandlerImpl::OnWebSocketRequest( + int connection_id, + const net::HttpServerRequestInfo& request) { + BrowserThread::PostTask( + BrowserThread::UI, + FROM_HERE, + base::Bind( + &DevToolsHttpHandlerImpl::OnWebSocketRequestUI, + this, + connection_id, + request)); +} + +void DevToolsHttpHandlerImpl::OnWebSocketMessage( + int connection_id, + const std::string& data) { + BrowserThread::PostTask( + BrowserThread::UI, + FROM_HERE, + base::Bind( + &DevToolsHttpHandlerImpl::OnWebSocketMessageUI, + this, + connection_id, + data)); +} + +void DevToolsHttpHandlerImpl::OnClose(int connection_id) { + BrowserThread::PostTask( + BrowserThread::UI, + FROM_HERE, + base::Bind( + &DevToolsHttpHandlerImpl::OnCloseUI, + this, + connection_id)); +} + +struct DevToolsHttpHandlerImpl::PageInfo { + PageInfo() + : attached(false) { + } + + std::string id; + std::string url; + bool attached; + std::string title; + std::string thumbnail_url; + std::string favicon_url; + base::TimeTicks last_selected_time; +}; + +// static +bool DevToolsHttpHandlerImpl::SortPageListByTime(const PageInfo& info1, + const PageInfo& info2) { + return info1.last_selected_time > info2.last_selected_time; +} + +DevToolsHttpHandlerImpl::PageList DevToolsHttpHandlerImpl::GeneratePageList() { + PageList page_list; + for (RenderProcessHost::iterator it(RenderProcessHost::AllHostsIterator()); + !it.IsAtEnd(); it.Advance()) { + RenderProcessHost* render_process_host = it.GetCurrentValue(); + DCHECK(render_process_host); + + // Ignore processes that don't have a connection, such as crashed contents. + if (!render_process_host->HasConnection()) + continue; + + RenderProcessHost::RenderWidgetHostsIterator rwit( + render_process_host->GetRenderWidgetHostsIterator()); + for (; !rwit.IsAtEnd(); rwit.Advance()) { + const RenderWidgetHost* widget = rwit.GetCurrentValue(); + DCHECK(widget); + if (!widget || !widget->IsRenderView()) + continue; + + RenderViewHost* host = + RenderViewHost::From(const_cast(widget)); + page_list.push_back(CreatePageInfo(host)); + } + } + std::sort(page_list.begin(), page_list.end(), SortPageListByTime); + return page_list; +} + +std::string DevToolsHttpHandlerImpl::GetFrontendURLInternal( + const std::string rvh_id, + const std::string& host) { + return base::StringPrintf( + "%s%sws=%s/devtools/page/%s", + overridden_frontend_url_.c_str(), + overridden_frontend_url_.find("?") == std::string::npos ? "?" : "&", + host.c_str(), + rvh_id.c_str()); +} + +static bool ParseJsonPath( + const std::string& path, + std::string* command, + std::string* target_id) { + + // Fall back to list in case of empty query. + if (path.empty()) { + *command = "list"; + return true; + } + + if (path.find("/") != 0) { + // Malformed command. + return false; + } + *command = path.substr(1); + + size_t separator_pos = command->find("/"); + if (separator_pos != std::string::npos) { + *target_id = command->substr(separator_pos + 1); + *command = command->substr(0, separator_pos); + } + return true; +} + +void DevToolsHttpHandlerImpl::OnJsonRequestUI( + int connection_id, + const net::HttpServerRequestInfo& info) { + // Trim /json and ?jsonp=... + std::string path = info.path.substr(5); + std::string jsonp; + size_t jsonp_pos = path.find("?jsonp="); + if (jsonp_pos != std::string::npos) { + jsonp = path.substr(jsonp_pos + 7); + path = path.substr(0, jsonp_pos); + } + + // Trim fragment and query + size_t query_pos = path.find("?"); + if (query_pos != std::string::npos) + path = path.substr(0, query_pos); + + size_t fragment_pos = path.find("#"); + if (fragment_pos != std::string::npos) + path = path.substr(0, fragment_pos); + + std::string command; + std::string target_id; + if (!ParseJsonPath(path, &command, &target_id)) { + SendJson(connection_id, + net::HTTP_NOT_FOUND, + NULL, + "Malformed query: " + info.path, + jsonp); + return; + } + + if (command == "version") { + DictionaryValue version; + version.SetString("Protocol-Version", + WebKit::WebDevToolsAgent::inspectorProtocolVersion()); + version.SetString("WebKit-Version", + webkit_glue::GetWebKitVersion()); + version.SetString("User-Agent", + webkit_glue::GetUserAgent(GURL(chrome::kAboutBlankURL))); + SendJson(connection_id, net::HTTP_OK, &version, "", jsonp); + return; + } + + if (command == "list") { + PageList page_list = GeneratePageList(); + ListValue json_pages_list; + std::string host = info.headers["Host"]; + for (PageList::iterator i = page_list.begin(); i != page_list.end(); ++i) + json_pages_list.Append(SerializePageInfo(*i, host)); + SendJson(connection_id, net::HTTP_OK, &json_pages_list, "", jsonp); + return; + } + + if (command == "new") { + RenderViewHost* rvh = delegate_->CreateNewTarget(); + if (!rvh) { + SendJson(connection_id, + net::HTTP_INTERNAL_SERVER_ERROR, + NULL, + "Could not create new page", + jsonp); + return; + } + PageInfo page_info = CreatePageInfo(rvh); + std::string host = info.headers["Host"]; + scoped_ptr dictionary(SerializePageInfo(page_info, host)); + SendJson(connection_id, net::HTTP_OK, dictionary.get(), "", jsonp); + return; + } + + if (command == "activate" || command == "close") { + RenderViewHost* rvh = binding_->ForIdentifier(target_id); + if (!rvh) { + SendJson(connection_id, + net::HTTP_NOT_FOUND, + NULL, + "No such target id: " + target_id, + jsonp); + return; + } + + if (command == "activate") { + rvh->GetDelegate()->Activate(); + SendJson(connection_id, net::HTTP_OK, NULL, "Target activated", jsonp); + return; + } + + if (command == "close") { + rvh->ClosePage(); + SendJson(connection_id, net::HTTP_OK, NULL, "Target is closing", jsonp); + return; + } + } + SendJson(connection_id, + net::HTTP_NOT_FOUND, + NULL, + "Unknown command: " + command, + jsonp); + return; +} + +void DevToolsHttpHandlerImpl::OnThumbnailRequestUI( + int connection_id, + const net::HttpServerRequestInfo& info) { + std::string prefix = "/thumb/"; + size_t pos = info.path.find(prefix); + if (pos != 0) { + Send404(connection_id); + return; + } + + std::string page_url = info.path.substr(prefix.length()); + std::string data = delegate_->GetPageThumbnailData(GURL(page_url)); + if (!data.empty()) + Send200(connection_id, data, "image/png"); + else + Send404(connection_id); +} + +void DevToolsHttpHandlerImpl::OnDiscoveryPageRequestUI(int connection_id) { + std::string response = delegate_->GetDiscoveryPageHTML(); + Send200(connection_id, response, "text/html; charset=UTF-8"); +} + +void DevToolsHttpHandlerImpl::OnWebSocketRequestUI( + int connection_id, + const net::HttpServerRequestInfo& request) { + if (!thread_.get()) + return; + std::string browser_prefix = "/devtools/browser"; + size_t browser_pos = request.path.find(browser_prefix); + if (browser_pos == 0) { + if (browser_target_) { + Send500(connection_id, "Another client already attached"); + return; + } + browser_target_.reset(new DevToolsBrowserTarget(connection_id)); + browser_target_->RegisterHandler(new DevToolsTracingHandler()); + AcceptWebSocket(connection_id, request); + return; + } + + std::string page_prefix = "/devtools/page/"; + size_t pos = request.path.find(page_prefix); + if (pos != 0) { + Send404(connection_id); + return; + } + + std::string page_id = request.path.substr(page_prefix.length()); + RenderViewHost* rvh = binding_->ForIdentifier(page_id); + if (!rvh) { + Send500(connection_id, "No such target id: " + page_id); + return; + } + + DevToolsManager* manager = DevToolsManager::GetInstance(); + DevToolsAgentHost* agent = DevToolsAgentHostRegistry::GetDevToolsAgentHost( + rvh); + if (manager->GetDevToolsClientHostFor(agent)) { + Send500(connection_id, + "Target with given id is being inspected: " + page_id); + return; + } + + DevToolsClientHostImpl* client_host = + new DevToolsClientHostImpl(thread_->message_loop(), + server_, + connection_id); + connection_to_client_host_ui_[connection_id] = client_host; + + manager->RegisterDevToolsClientHostFor(agent, client_host); + + AcceptWebSocket(connection_id, request); +} + +void DevToolsHttpHandlerImpl::OnWebSocketMessageUI( + int connection_id, + const std::string& data) { + if (browser_target_ && connection_id == browser_target_->connection_id()) { + std::string json_response = browser_target_->HandleMessage(data); + + thread_->message_loop()->PostTask( + FROM_HERE, + base::Bind(&net::HttpServer::SendOverWebSocket, + server_.get(), + connection_id, + json_response)); + return; + } + + ConnectionToClientHostMap::iterator it = + connection_to_client_host_ui_.find(connection_id); + if (it == connection_to_client_host_ui_.end()) + return; + + DevToolsManager* manager = DevToolsManager::GetInstance(); + manager->DispatchOnInspectorBackend(it->second, data); +} + +void DevToolsHttpHandlerImpl::OnCloseUI(int connection_id) { + ConnectionToClientHostMap::iterator it = + connection_to_client_host_ui_.find(connection_id); + if (it != connection_to_client_host_ui_.end()) { + DevToolsClientHostImpl* client_host = + static_cast(it->second); + DevToolsManager::GetInstance()->ClientHostClosing(client_host); + delete client_host; + connection_to_client_host_ui_.erase(connection_id); + } + if (browser_target_ && browser_target_->connection_id() == connection_id) { + browser_target_.reset(); + return; + } +} + +DevToolsHttpHandlerImpl::DevToolsHttpHandlerImpl( + const net::StreamListenSocketFactory* socket_factory, + const std::string& frontend_url, + DevToolsHttpHandlerDelegate* delegate) + : overridden_frontend_url_(frontend_url), + socket_factory_(socket_factory), + delegate_(delegate) { + if (overridden_frontend_url_.empty()) + overridden_frontend_url_ = "/devtools/devtools.html"; + + default_binding_.reset(new DevToolsDefaultBindingHandler); + binding_ = default_binding_.get(); + + registrar_.Add(this, NOTIFICATION_RENDERER_PROCESS_TERMINATED, + NotificationService::AllBrowserContextsAndSources()); + registrar_.Add(this, NOTIFICATION_RENDERER_PROCESS_CLOSED, + NotificationService::AllBrowserContextsAndSources()); + + // Balanced in ResetHandlerThreadAndRelease(). + AddRef(); +} + +// Runs on the handler thread +void DevToolsHttpHandlerImpl::Init() { + server_ = new net::HttpServer(*socket_factory_.get(), this); +} + +// Runs on the handler thread +void DevToolsHttpHandlerImpl::Teardown() { + server_ = NULL; +} + +// Runs on FILE thread to make sure that it is serialized against +// {Start|Stop}HandlerThread and to allow calling pthread_join. +void DevToolsHttpHandlerImpl::StopHandlerThread() { + if (!thread_->message_loop()) + return; + thread_->message_loop()->PostTask( + FROM_HERE, + base::Bind(&DevToolsHttpHandlerImpl::Teardown, this)); + // Thread::Stop joins the thread. + thread_->Stop(); +} + +void DevToolsHttpHandlerImpl::SendJson(int connection_id, + net::HttpStatusCode status_code, + Value* value, + const std::string& message, + const std::string& jsonp) { + if (!thread_.get()) + return; + + // Serialize value and message. + std::string json_value; + if (value) { + base::JSONWriter::WriteWithOptions(value, + base::JSONWriter::OPTIONS_PRETTY_PRINT, + &json_value); + } + std::string json_message; + scoped_ptr message_object(Value::CreateStringValue(message)); + base::JSONWriter::Write(message_object.get(), &json_message); + + std::string response; + std::string mime_type = "application/json; charset=UTF-8"; + + // Wrap jsonp if necessary. + if (!jsonp.empty()) { + mime_type = "text/javascript; charset=UTF-8"; + response = StringPrintf("%s(%s, %d, %s);", + jsonp.c_str(), + json_value.empty() ? "undefined" + : json_value.c_str(), + status_code, + json_message.c_str()); + // JSONP always returns 200. + status_code = net::HTTP_OK; + } else { + response = StringPrintf("%s%s", json_value.c_str(), message.c_str()); + } + + thread_->message_loop()->PostTask( + FROM_HERE, + base::Bind(&net::HttpServer::Send, + server_.get(), + connection_id, + status_code, + response, + mime_type)); +} + +void DevToolsHttpHandlerImpl::Send200(int connection_id, + const std::string& data, + const std::string& mime_type) { + if (!thread_.get()) + return; + thread_->message_loop()->PostTask( + FROM_HERE, + base::Bind(&net::HttpServer::Send200, + server_.get(), + connection_id, + data, + mime_type)); +} + +void DevToolsHttpHandlerImpl::Send404(int connection_id) { + if (!thread_.get()) + return; + thread_->message_loop()->PostTask( + FROM_HERE, + base::Bind(&net::HttpServer::Send404, server_.get(), connection_id)); +} + +void DevToolsHttpHandlerImpl::Send500(int connection_id, + const std::string& message) { + if (!thread_.get()) + return; + thread_->message_loop()->PostTask( + FROM_HERE, + base::Bind(&net::HttpServer::Send500, server_.get(), connection_id, + message)); +} + +void DevToolsHttpHandlerImpl::AcceptWebSocket( + int connection_id, + const net::HttpServerRequestInfo& request) { + if (!thread_.get()) + return; + thread_->message_loop()->PostTask( + FROM_HERE, + base::Bind(&net::HttpServer::AcceptWebSocket, server_.get(), + connection_id, request)); +} + +DevToolsHttpHandlerImpl::PageInfo +DevToolsHttpHandlerImpl::CreatePageInfo(RenderViewHost* rvh) +{ + RenderViewHostDelegate* host_delegate = rvh->GetDelegate(); + DevToolsAgentHost* agent = + DevToolsAgentHostRegistry::GetDevToolsAgentHost(rvh); + DevToolsClientHost* client_host = DevToolsManager::GetInstance()-> + GetDevToolsClientHostFor(agent); + PageInfo page_info; + page_info.id = binding_->GetIdentifier(rvh); + page_info.attached = client_host != NULL; + page_info.url = host_delegate->GetURL().spec(); + + WebContents* web_contents = host_delegate->GetAsWebContents(); + if (web_contents) { + page_info.title = UTF16ToUTF8( + net::EscapeForHTML(web_contents->GetTitle())); + page_info.last_selected_time = web_contents->GetLastSelectedTime(); + + NavigationController& controller = web_contents->GetController(); + NavigationEntry* entry = controller.GetActiveEntry(); + if (entry != NULL && entry->GetURL().is_valid()) { + page_info.thumbnail_url = "/thumb/" + entry->GetURL().spec(); + page_info.favicon_url = entry->GetFavicon().url.spec(); + } + } + return page_info; +} + +DictionaryValue* DevToolsHttpHandlerImpl::SerializePageInfo( + const PageInfo& page_info, + const std::string& host) { + DictionaryValue* dictionary = new DictionaryValue; + dictionary->SetString("title", page_info.title); + dictionary->SetString("url", page_info.url); + dictionary->SetString("thumbnailUrl", page_info.thumbnail_url); + dictionary->SetString("faviconUrl", page_info.favicon_url); + if (!page_info.attached) { + dictionary->SetString("webSocketDebuggerUrl", + base::StringPrintf("ws://%s/devtools/page/%s", + host.c_str(), + page_info.id.c_str())); + std::string devtools_frontend_url = GetFrontendURLInternal( + page_info.id.c_str(), + host); + dictionary->SetString("devtoolsFrontendUrl", devtools_frontend_url); + } + return dictionary; +} + +} // namespace content diff --git a/content/browser/devtools/devtools_http_handler_impl.h b/content/browser/devtools/devtools_http_handler_impl.h new file mode 100644 index 0000000..9ee6f92 --- /dev/null +++ b/content/browser/devtools/devtools_http_handler_impl.h @@ -0,0 +1,143 @@ +// Copyright (c) 2012 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 CONTENT_BROWSER_DEVTOOLS_DEVTOOLS_HTTP_HANDLER_IMPL_H_ +#define CONTENT_BROWSER_DEVTOOLS_DEVTOOLS_HTTP_HANDLER_IMPL_H_ + +#include +#include +#include +#include + +#include "base/memory/ref_counted.h" +#include "base/memory/scoped_ptr.h" +#include "content/common/content_export.h" +#include "content/public/browser/devtools_http_handler.h" +#include "content/public/browser/devtools_http_handler_delegate.h" +#include "content/public/browser/notification_observer.h" +#include "content/public/browser/notification_registrar.h" +#include "net/server/http_server.h" + +namespace base { +class DictionaryValue; +class Thread; +class Value; +} + +namespace net { +class StreamListenSocketFactory; +class URLRequestContextGetter; +} + +namespace content { + +class DevToolsBrowserTarget; +class DevToolsClientHost; +class RenderViewHost; + +class DevToolsHttpHandlerImpl + : public DevToolsHttpHandler, + public NotificationObserver, + public base::RefCountedThreadSafe, + public net::HttpServer::Delegate { + private: + struct PageInfo; + typedef std::vector PageList; + friend class base::RefCountedThreadSafe; + friend class DevToolsHttpHandler; + + static bool SortPageListByTime(const PageInfo& info1, const PageInfo& info2); + + // Takes ownership over |socket_factory|. + DevToolsHttpHandlerImpl(const net::StreamListenSocketFactory* socket_factory, + const std::string& frontend_url, + DevToolsHttpHandlerDelegate* delegate); + virtual ~DevToolsHttpHandlerImpl(); + void Start(); + + // DevToolsHttpHandler implementation. + virtual void Stop() OVERRIDE; + virtual void SetRenderViewHostBinding( + RenderViewHostBinding* binding) OVERRIDE; + virtual GURL GetFrontendURL(RenderViewHost* render_view_host) OVERRIDE; + + // NotificationObserver implementation. + virtual void Observe(int type, + const NotificationSource& source, + const NotificationDetails& details) OVERRIDE; + + // net::HttpServer::Delegate implementation. + virtual void OnHttpRequest(int connection_id, + const net::HttpServerRequestInfo& info) OVERRIDE; + virtual void OnWebSocketRequest( + int connection_id, + const net::HttpServerRequestInfo& info) OVERRIDE; + virtual void OnWebSocketMessage(int connection_id, + const std::string& data) OVERRIDE; + virtual void OnClose(int connection_id) OVERRIDE; + + void OnJsonRequestUI(int connection_id, + const net::HttpServerRequestInfo& info); + void OnThumbnailRequestUI(int connection_id, + const net::HttpServerRequestInfo& info); + void OnDiscoveryPageRequestUI(int connection_id); + + void OnWebSocketRequestUI(int connection_id, + const net::HttpServerRequestInfo& info); + void OnWebSocketMessageUI(int connection_id, const std::string& data); + void OnCloseUI(int connection_id); + + void ResetHandlerThread(); + void ResetHandlerThreadAndRelease(); + + void Init(); + void Teardown(); + + void StartHandlerThread(); + void StopHandlerThread(); + + void SendJson(int connection_id, + net::HttpStatusCode status_code, + base::Value* value, + const std::string& message, + const std::string& jsonp); + void Send200(int connection_id, + const std::string& data, + const std::string& mime_type); + void Send404(int connection_id); + void Send500(int connection_id, + const std::string& message); + void AcceptWebSocket(int connection_id, + const net::HttpServerRequestInfo& request); + + PageList GeneratePageList(); + + // Returns the front end url without the host at the beginning. + std::string GetFrontendURLInternal(const std::string rvh_id, + const std::string& host); + + PageInfo CreatePageInfo(RenderViewHost* rvh); + + base::DictionaryValue* SerializePageInfo(const PageInfo& page_info, + const std::string& host); + + // The thread used by the devtools handler to run server socket. + scoped_ptr thread_; + + std::string overridden_frontend_url_; + scoped_ptr socket_factory_; + scoped_refptr server_; + typedef std::map ConnectionToClientHostMap; + ConnectionToClientHostMap connection_to_client_host_ui_; + scoped_ptr delegate_; + RenderViewHostBinding* binding_; + scoped_ptr default_binding_; + NotificationRegistrar registrar_; + scoped_ptr browser_target_; + DISALLOW_COPY_AND_ASSIGN(DevToolsHttpHandlerImpl); +}; + +} // namespace content + +#endif // CONTENT_BROWSER_DEVTOOLS_DEVTOOLS_HTTP_HANDLER_IMPL_H_ diff --git a/content/browser/devtools/devtools_http_handler_unittest.cc b/content/browser/devtools/devtools_http_handler_unittest.cc new file mode 100644 index 0000000..b01c9d9 --- /dev/null +++ b/content/browser/devtools/devtools_http_handler_unittest.cc @@ -0,0 +1,103 @@ +// Copyright (c) 2012 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 "base/message_loop.h" +#include "base/run_loop.h" +#include "content/browser/browser_thread_impl.h" +#include "content/public/browser/devtools_http_handler.h" +#include "content/public/browser/devtools_http_handler_delegate.h" +#include "net/base/stream_listen_socket.h" +#include "testing/gtest/include/gtest/gtest.h" + +namespace content { +namespace { + +using net::StreamListenSocket; + +class DummyListenSocket : public StreamListenSocket, + public StreamListenSocket::Delegate { + public: + DummyListenSocket() + : ALLOW_THIS_IN_INITIALIZER_LIST(StreamListenSocket(0, this)) {} + + // StreamListenSocket::Delegate "implementation" + virtual void DidAccept(StreamListenSocket* server, + StreamListenSocket* connection) OVERRIDE {} + virtual void DidRead(StreamListenSocket* connection, + const char* data, + int len) OVERRIDE {} + virtual void DidClose(StreamListenSocket* sock) OVERRIDE {} + protected: + virtual ~DummyListenSocket() {} + virtual void Accept() OVERRIDE {} +}; + +class DummyListenSocketFactory : public net::StreamListenSocketFactory { + public: + DummyListenSocketFactory( + base::Closure quit_closure_1, base::Closure quit_closure_2) + : quit_closure_1_(quit_closure_1), quit_closure_2_(quit_closure_2) {} + virtual ~DummyListenSocketFactory() { + BrowserThread::PostTask( + BrowserThread::UI, FROM_HERE, quit_closure_2_); + } + + virtual scoped_refptr CreateAndListen( + StreamListenSocket::Delegate* delegate) const OVERRIDE { + BrowserThread::PostTask( + BrowserThread::UI, FROM_HERE, quit_closure_1_); + return new DummyListenSocket(); + } + private: + base::Closure quit_closure_1_; + base::Closure quit_closure_2_; +}; + +class DummyDelegate : public DevToolsHttpHandlerDelegate { + public: + virtual std::string GetDiscoveryPageHTML() OVERRIDE { return ""; } + virtual bool BundlesFrontendResources() OVERRIDE { return true; } + virtual FilePath GetDebugFrontendDir() OVERRIDE { return FilePath(); } + virtual std::string GetPageThumbnailData(const GURL& url) { return ""; } + virtual RenderViewHost* CreateNewTarget() { return NULL; } +}; + +} + +class DevToolsHttpHandlerTest : public testing::Test { + public: + DevToolsHttpHandlerTest() + : ui_thread_(BrowserThread::UI, &message_loop_) { + } + protected: + virtual void SetUp() { + file_thread_.reset(new BrowserThreadImpl(BrowserThread::FILE)); + file_thread_->Start(); + } + virtual void TearDown() { + file_thread_->Stop(); + } + private: + MessageLoopForIO message_loop_; + BrowserThreadImpl ui_thread_; + scoped_ptr file_thread_; +}; + +TEST_F(DevToolsHttpHandlerTest, TestStartStop) { + base::RunLoop run_loop, run_loop_2; + content::DevToolsHttpHandler* devtools_http_handler_ = + content::DevToolsHttpHandler::Start( + new DummyListenSocketFactory( + run_loop.QuitClosure(), run_loop_2.QuitClosure()), + "", + new DummyDelegate()); + // Our dummy socket factory will post a quit message once the server will + // become ready. + run_loop.Run(); + devtools_http_handler_->Stop(); + // Make sure the handler actually stops. + run_loop_2.Run(); +} + +} // namespace content diff --git a/content/browser/devtools/devtools_manager_impl.cc b/content/browser/devtools/devtools_manager_impl.cc new file mode 100644 index 0000000..b548ba2 --- /dev/null +++ b/content/browser/devtools/devtools_manager_impl.cc @@ -0,0 +1,302 @@ +// Copyright (c) 2012 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 "content/browser/devtools/devtools_manager_impl.h" + +#include + +#include "base/bind.h" +#include "base/message_loop.h" +#include "content/browser/child_process_security_policy_impl.h" +#include "content/browser/devtools/devtools_netlog_observer.h" +#include "content/browser/devtools/render_view_devtools_agent_host.h" +#include "content/browser/renderer_host/render_view_host_impl.h" +#include "content/browser/web_contents/web_contents_impl.h" +#include "content/public/browser/browser_thread.h" +#include "content/public/browser/devtools_agent_host_registry.h" +#include "content/public/browser/devtools_client_host.h" +#include "googleurl/src/gurl.h" + +namespace content { + +// static +DevToolsManager* DevToolsManager::GetInstance() { + return DevToolsManagerImpl::GetInstance(); +} + +// static +DevToolsManagerImpl* DevToolsManagerImpl::GetInstance() { + return Singleton::get(); +} + +DevToolsManagerImpl::DevToolsManagerImpl() + : last_orphan_cookie_(0) { +} + +DevToolsManagerImpl::~DevToolsManagerImpl() { + DCHECK(agent_to_client_host_.empty()); + DCHECK(client_to_agent_host_.empty()); + // By the time we destroy devtools manager, all orphan client hosts should + // have been deleted; no need to notify them upon contents closing. + DCHECK(orphan_client_hosts_.empty()); +} + +DevToolsClientHost* DevToolsManagerImpl::GetDevToolsClientHostFor( + DevToolsAgentHost* agent_host) { + AgentToClientHostMap::iterator it = agent_to_client_host_.find(agent_host); + if (it != agent_to_client_host_.end()) + return it->second; + return NULL; +} + +DevToolsAgentHost* DevToolsManagerImpl::GetDevToolsAgentHostFor( + DevToolsClientHost* client_host) { + ClientToAgentHostMap::iterator it = client_to_agent_host_.find(client_host); + if (it != client_to_agent_host_.end()) + return it->second; + return NULL; +} + +void DevToolsManagerImpl::RegisterDevToolsClientHostFor( + DevToolsAgentHost* agent_host, + DevToolsClientHost* client_host) { + BindClientHost(agent_host, client_host); + agent_host->Attach(); +} + +bool DevToolsManagerImpl::DispatchOnInspectorBackend( + DevToolsClientHost* from, + const std::string& message) { + DevToolsAgentHost* agent_host = GetDevToolsAgentHostFor(from); + if (!agent_host) + return false; + + agent_host->DipatchOnInspectorBackend(message); + return true; +} + +void DevToolsManagerImpl::DispatchOnInspectorFrontend( + DevToolsAgentHost* agent_host, + const std::string& message) { + DevToolsClientHost* client_host = GetDevToolsClientHostFor(agent_host); + if (!client_host) { + // Client window was closed while there were messages + // being sent to it. + return; + } + client_host->DispatchOnInspectorFrontend(message); +} + +void DevToolsManagerImpl::SaveAgentRuntimeState(DevToolsAgentHost* agent_host, + const std::string& state) { + agent_runtime_states_[agent_host] = state; +} + +void DevToolsManagerImpl::InspectElement(DevToolsAgentHost* agent_host, + int x, int y) { + agent_host->InspectElement(x, y); +} + +void DevToolsManagerImpl::AddMessageToConsole(DevToolsAgentHost* agent_host, + ConsoleMessageLevel level, + const std::string& message) { + agent_host->AddMessageToConsole(level, message); +} + +void DevToolsManagerImpl::ClientHostClosing(DevToolsClientHost* client_host) { + DevToolsAgentHost* agent_host = GetDevToolsAgentHostFor(client_host); + if (!agent_host) { + // It might be in the list of orphan client hosts, remove it from there. + for (OrphanClientHosts::iterator it = orphan_client_hosts_.begin(); + it != orphan_client_hosts_.end(); ++it) { + if (it->second.first == client_host) { + orphan_client_hosts_.erase(it->first); + return; + } + } + return; + } + + UnbindClientHost(agent_host, client_host); +} + +void DevToolsManagerImpl::AgentHostClosing(DevToolsAgentHost* agent_host) { + UnregisterDevToolsClientHostFor(agent_host); +} + +void DevToolsManagerImpl::UnregisterDevToolsClientHostFor( + DevToolsAgentHost* agent_host) { + DevToolsClientHost* client_host = GetDevToolsClientHostFor(agent_host); + if (!client_host) + return; + UnbindClientHost(agent_host, client_host); + client_host->InspectedContentsClosing(); +} + +void DevToolsManagerImpl::OnNavigatingToPendingEntry( + RenderViewHost* rvh, + RenderViewHost* dest_rvh, + const GURL& gurl) { + if (rvh == dest_rvh && static_cast( + rvh)->render_view_termination_status() == + base::TERMINATION_STATUS_STILL_RUNNING) + return; + int cookie = DetachClientHost(rvh); + if (cookie != -1) { + // Navigating to URL in the inspected window. + AttachClientHost(cookie, dest_rvh); + + DevToolsAgentHost* dest_agent_host = + DevToolsAgentHostRegistry::GetDevToolsAgentHost(dest_rvh); + DevToolsClientHost* client_host = GetDevToolsClientHostFor( + dest_agent_host); + client_host->FrameNavigating(gurl.spec()); + } +} + +void DevToolsManagerImpl::OnCancelPendingNavigation( + RenderViewHost* pending, + RenderViewHost* current) { + int cookie = DetachClientHost(pending); + if (cookie != -1) { + // Navigating to URL in the inspected window. + AttachClientHost(cookie, current); + } +} + +void DevToolsManagerImpl::ContentsReplaced(WebContents* old_contents, + WebContents* new_contents) { + RenderViewHost* old_rvh = old_contents->GetRenderViewHost(); + if (!DevToolsAgentHostRegistry::HasDevToolsAgentHost(old_rvh)) + return; + + DevToolsAgentHost* old_agent_host = + DevToolsAgentHostRegistry::GetDevToolsAgentHost(old_rvh); + DevToolsClientHost* client_host = GetDevToolsClientHostFor(old_agent_host); + if (!client_host) + return; // Didn't know about old_contents. + int cookie = DetachClientHost(old_rvh); + if (cookie == -1) + return; // Didn't know about old_contents. + + client_host->ContentsReplaced(new_contents); + AttachClientHost(cookie, new_contents->GetRenderViewHost()); +} + +int DevToolsManagerImpl::DetachClientHost(RenderViewHost* from_rvh) { + DevToolsAgentHost* agent_host = + DevToolsAgentHostRegistry::GetDevToolsAgentHost(from_rvh); + return DetachClientHost(agent_host); +} + +int DevToolsManagerImpl::DetachClientHost(DevToolsAgentHost* agent_host) { + DevToolsClientHost* client_host = GetDevToolsClientHostFor(agent_host); + if (!client_host) + return -1; + + int cookie = last_orphan_cookie_++; + orphan_client_hosts_[cookie] = + std::pair( + client_host, agent_runtime_states_[agent_host]); + + UnbindClientHost(agent_host, client_host); + return cookie; +} + +void DevToolsManagerImpl::AttachClientHost(int client_host_cookie, + RenderViewHost* to_rvh) { + DevToolsAgentHost* agent_host = + DevToolsAgentHostRegistry::GetDevToolsAgentHost(to_rvh); + AttachClientHost(client_host_cookie, agent_host); +} + +void DevToolsManagerImpl::AttachClientHost(int client_host_cookie, + DevToolsAgentHost* agent_host) { + OrphanClientHosts::iterator it = orphan_client_hosts_.find( + client_host_cookie); + if (it == orphan_client_hosts_.end()) + return; + + DevToolsClientHost* client_host = (*it).second.first; + const std::string& state = (*it).second.second; + BindClientHost(agent_host, client_host); + agent_host->Reattach(state); + agent_runtime_states_[agent_host] = state; + + orphan_client_hosts_.erase(it); +} + +void DevToolsManagerImpl::BindClientHost( + DevToolsAgentHost* agent_host, + DevToolsClientHost* client_host) { + DCHECK(agent_to_client_host_.find(agent_host) == + agent_to_client_host_.end()); + DCHECK(client_to_agent_host_.find(client_host) == + client_to_agent_host_.end()); + + if (client_to_agent_host_.empty()) { + BrowserThread::PostTask( + BrowserThread::IO, + FROM_HERE, + base::Bind(&DevToolsNetLogObserver::Attach)); + } + agent_to_client_host_[agent_host] = client_host; + client_to_agent_host_[client_host] = agent_host; + agent_host->set_close_listener(this); + + int process_id = agent_host->GetRenderProcessId(); + if (process_id != -1) + ChildProcessSecurityPolicyImpl::GetInstance()->GrantReadRawCookies( + process_id); +} + +void DevToolsManagerImpl::UnbindClientHost(DevToolsAgentHost* agent_host, + DevToolsClientHost* client_host) { + DCHECK(agent_host); + DCHECK(agent_to_client_host_.find(agent_host)->second == + client_host); + DCHECK(client_to_agent_host_.find(client_host)->second == + agent_host); + agent_host->set_close_listener(NULL); + + agent_to_client_host_.erase(agent_host); + client_to_agent_host_.erase(client_host); + agent_runtime_states_.erase(agent_host); + + if (client_to_agent_host_.empty()) { + BrowserThread::PostTask( + BrowserThread::IO, + FROM_HERE, + base::Bind(&DevToolsNetLogObserver::Detach)); + } + agent_host->Detach(); + + int process_id = agent_host->GetRenderProcessId(); + if (process_id == -1) + return; + for (AgentToClientHostMap::iterator it = agent_to_client_host_.begin(); + it != agent_to_client_host_.end(); + ++it) { + if (it->first->GetRenderProcessId() == process_id) + return; + } + // We've disconnected from the last renderer -> revoke cookie permissions. + ChildProcessSecurityPolicyImpl::GetInstance()->RevokeReadRawCookies( + process_id); +} + +void DevToolsManagerImpl::CloseAllClientHosts() { + std::vector agents; + for (AgentToClientHostMap::iterator it = + agent_to_client_host_.begin(); + it != agent_to_client_host_.end(); ++it) { + agents.push_back(it->first); + } + for (std::vector::iterator it = agents.begin(); + it != agents.end(); ++it) { + UnregisterDevToolsClientHostFor(*it); + } +} + +} // namespace content diff --git a/content/browser/devtools/devtools_manager_impl.h b/content/browser/devtools/devtools_manager_impl.h new file mode 100644 index 0000000..ed213b7 --- /dev/null +++ b/content/browser/devtools/devtools_manager_impl.h @@ -0,0 +1,131 @@ +// Copyright (c) 2012 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 CONTENT_BROWSER_DEVTOOLS_DEVTOOLS_MANAGER_IMPL_H_ +#define CONTENT_BROWSER_DEVTOOLS_DEVTOOLS_MANAGER_IMPL_H_ + +#include +#include + +#include "base/compiler_specific.h" +#include "base/memory/singleton.h" +#include "content/browser/devtools/devtools_agent_host.h" +#include "content/common/content_export.h" +#include "content/public/browser/devtools_client_host.h" +#include "content/public/browser/devtools_manager.h" + +class GURL; + +namespace IPC { +class Message; +} + +namespace content { + +class DevToolsAgentHost; +class RenderViewHost; + +// This class is a singleton that manages DevToolsClientHost instances and +// routes messages between developer tools clients and agents. +// +// Methods below that accept inspected RenderViewHost as a parameter are +// just convenience methods that call corresponding methods accepting +// DevToolAgentHost. +class CONTENT_EXPORT DevToolsManagerImpl + : public DevToolsAgentHost::CloseListener, + public DevToolsManager { + public: + // Returns single instance of this class. The instance is destroyed on the + // browser main loop exit so this method MUST NOT be called after that point. + static DevToolsManagerImpl* GetInstance(); + + DevToolsManagerImpl(); + virtual ~DevToolsManagerImpl(); + + void DispatchOnInspectorFrontend(DevToolsAgentHost* agent_host, + const std::string& message); + + void SaveAgentRuntimeState(DevToolsAgentHost* agent_host, + const std::string& state); + + // Sends 'Attach' message to the agent using |dest_rvh| in case + // there is a DevToolsClientHost registered for the |inspected_rvh|. + void OnNavigatingToPendingEntry(RenderViewHost* inspected_rvh, + RenderViewHost* dest_rvh, + const GURL& gurl); + void OnCancelPendingNavigation(RenderViewHost* pending, + RenderViewHost* current); + + // DevToolsManager implementation + virtual bool DispatchOnInspectorBackend(DevToolsClientHost* from, + const std::string& message) OVERRIDE; + virtual void ContentsReplaced(WebContents* old_contents, + WebContents* new_contents) OVERRIDE; + virtual void CloseAllClientHosts() OVERRIDE; + virtual void AttachClientHost(int client_host_cookie, + DevToolsAgentHost* to_agent) OVERRIDE; + virtual DevToolsClientHost* GetDevToolsClientHostFor( + DevToolsAgentHost* agent_host) OVERRIDE; + virtual DevToolsAgentHost* GetDevToolsAgentHostFor( + DevToolsClientHost* client_host) OVERRIDE; + virtual void RegisterDevToolsClientHostFor( + DevToolsAgentHost* agent_host, + DevToolsClientHost* client_host) OVERRIDE; + virtual void UnregisterDevToolsClientHostFor( + DevToolsAgentHost* agent_host) OVERRIDE; + virtual int DetachClientHost(DevToolsAgentHost* from_agent) OVERRIDE; + virtual void ClientHostClosing(DevToolsClientHost* host) OVERRIDE; + virtual void InspectElement(DevToolsAgentHost* agent_host, + int x, int y) OVERRIDE; + virtual void AddMessageToConsole(DevToolsAgentHost* agent_host, + ConsoleMessageLevel level, + const std::string& message) OVERRIDE; + + private: + friend struct DefaultSingletonTraits; + + // DevToolsAgentHost::CloseListener implementation. + virtual void AgentHostClosing(DevToolsAgentHost* host) OVERRIDE; + + void BindClientHost(DevToolsAgentHost* agent_host, + DevToolsClientHost* client_host); + void UnbindClientHost(DevToolsAgentHost* agent_host, + DevToolsClientHost* client_host); + + // Detaches client host and returns cookie that can be used in + // AttachClientHost. + int DetachClientHost(RenderViewHost* from_rvh); + + // Attaches orphan client host to new render view host. + void AttachClientHost(int client_host_cookie, + RenderViewHost* to_rvh); + + // These two maps are for tracking dependencies between inspected contents and + // their DevToolsClientHosts. They are useful for routing devtools messages + // and allow us to have at most one devtools client host per contents. + // + // DevToolsManagerImpl starts listening to DevToolsClientHosts when they are + // put into these maps and removes them when they are closing. + typedef std::map + AgentToClientHostMap; + AgentToClientHostMap agent_to_client_host_; + + typedef std::map + ClientToAgentHostMap; + ClientToAgentHostMap client_to_agent_host_; + + typedef std::map AgentRuntimeStates; + AgentRuntimeStates agent_runtime_states_; + + typedef std::map > + OrphanClientHosts; + OrphanClientHosts orphan_client_hosts_; + int last_orphan_cookie_; + + DISALLOW_COPY_AND_ASSIGN(DevToolsManagerImpl); +}; + +} // namespace content + +#endif // CONTENT_BROWSER_DEVTOOLS_DEVTOOLS_MANAGER_IMPL_H_ diff --git a/content/browser/devtools/devtools_manager_unittest.cc b/content/browser/devtools/devtools_manager_unittest.cc new file mode 100644 index 0000000..d2a47a5 --- /dev/null +++ b/content/browser/devtools/devtools_manager_unittest.cc @@ -0,0 +1,243 @@ +// Copyright (c) 2012 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 "base/basictypes.h" +#include "base/time.h" +#include "content/browser/devtools/devtools_manager_impl.h" +#include "content/browser/devtools/render_view_devtools_agent_host.h" +#include "content/browser/renderer_host/test_render_view_host.h" +#include "content/browser/web_contents/test_web_contents.h" +#include "content/common/view_messages.h" +#include "content/public/browser/content_browser_client.h" +#include "content/public/browser/devtools_agent_host_registry.h" +#include "content/public/browser/devtools_client_host.h" +#include "content/public/browser/web_contents_delegate.h" +#include "content/test/test_content_browser_client.h" +#include "testing/gtest/include/gtest/gtest.h" + +using base::TimeDelta; + +namespace content { +namespace { + +class TestDevToolsClientHost : public DevToolsClientHost { + public: + TestDevToolsClientHost() + : last_sent_message(NULL), + closed_(false) { + } + + virtual ~TestDevToolsClientHost() { + EXPECT_TRUE(closed_); + } + + virtual void Close(DevToolsManager* manager) { + EXPECT_FALSE(closed_); + close_counter++; + manager->ClientHostClosing(this); + closed_ = true; + } + virtual void InspectedContentsClosing() { + FAIL(); + } + + virtual void DispatchOnInspectorFrontend(const std::string& message) { + last_sent_message = &message; + } + + virtual void ContentsReplaced(WebContents* new_contents) { + } + + virtual void ReplacedWithAnotherClient() { + } + + static void ResetCounters() { + close_counter = 0; + } + + static int close_counter; + + const std::string* last_sent_message; + + private: + bool closed_; + + virtual void FrameNavigating(const std::string& url) {} + + DISALLOW_COPY_AND_ASSIGN(TestDevToolsClientHost); +}; + +int TestDevToolsClientHost::close_counter = 0; + + +class TestWebContentsDelegate : public WebContentsDelegate { + public: + TestWebContentsDelegate() : renderer_unresponsive_received_(false) {} + + // Notification that the contents is hung. + virtual void RendererUnresponsive(WebContents* source) { + renderer_unresponsive_received_ = true; + } + + bool renderer_unresponsive_received() const { + return renderer_unresponsive_received_; + } + + private: + bool renderer_unresponsive_received_; +}; + +class DevToolsManagerTestBrowserClient : public TestContentBrowserClient { + public: + DevToolsManagerTestBrowserClient() { + } + + virtual bool ShouldSwapProcessesForNavigation( + const GURL& current_url, + const GURL& new_url) OVERRIDE { + return true; + } + + private: + DISALLOW_COPY_AND_ASSIGN(DevToolsManagerTestBrowserClient); +}; + +} // namespace + +class DevToolsManagerTest : public RenderViewHostImplTestHarness { + public: + DevToolsManagerTest() { + } + + protected: + virtual void SetUp() OVERRIDE { + original_browser_client_ = GetContentClient()->browser(); + GetContentClient()->set_browser_for_testing(&browser_client_); + + RenderViewHostImplTestHarness::SetUp(); + TestDevToolsClientHost::ResetCounters(); + } + + virtual void TearDown() OVERRIDE { + RenderViewHostImplTestHarness::TearDown(); + GetContentClient()->set_browser_for_testing(original_browser_client_); + } + + private: + ContentBrowserClient* original_browser_client_; + DevToolsManagerTestBrowserClient browser_client_; +}; + +TEST_F(DevToolsManagerTest, OpenAndManuallyCloseDevToolsClientHost) { + DevToolsManagerImpl manager; + + DevToolsAgentHost* agent = + DevToolsAgentHostRegistry::GetDevToolsAgentHost(rvh()); + DevToolsClientHost* host = manager.GetDevToolsClientHostFor(agent); + EXPECT_TRUE(NULL == host); + + TestDevToolsClientHost client_host; + manager.RegisterDevToolsClientHostFor(agent, &client_host); + // Test that just registered devtools host is returned. + host = manager.GetDevToolsClientHostFor(agent); + EXPECT_TRUE(&client_host == host); + EXPECT_EQ(0, TestDevToolsClientHost::close_counter); + + // Test that the same devtools host is returned. + host = manager.GetDevToolsClientHostFor(agent); + EXPECT_TRUE(&client_host == host); + EXPECT_EQ(0, TestDevToolsClientHost::close_counter); + + client_host.Close(&manager); + EXPECT_EQ(1, TestDevToolsClientHost::close_counter); + host = manager.GetDevToolsClientHostFor(agent); + EXPECT_TRUE(NULL == host); +} + +TEST_F(DevToolsManagerTest, ForwardMessageToClient) { + DevToolsManagerImpl manager; + + TestDevToolsClientHost client_host; + DevToolsAgentHost* agent_host = + DevToolsAgentHostRegistry::GetDevToolsAgentHost(rvh()); + manager.RegisterDevToolsClientHostFor(agent_host, &client_host); + EXPECT_EQ(0, TestDevToolsClientHost::close_counter); + + std::string m = "test message"; + agent_host = DevToolsAgentHostRegistry::GetDevToolsAgentHost(rvh()); + manager.DispatchOnInspectorFrontend(agent_host, m); + EXPECT_TRUE(&m == client_host.last_sent_message); + + client_host.Close(&manager); + EXPECT_EQ(1, TestDevToolsClientHost::close_counter); +} + +TEST_F(DevToolsManagerTest, NoUnresponsiveDialogInInspectedContents) { + TestRenderViewHost* inspected_rvh = test_rvh(); + inspected_rvh->set_render_view_created(true); + EXPECT_FALSE(contents()->GetDelegate()); + TestWebContentsDelegate delegate; + contents()->SetDelegate(&delegate); + + TestDevToolsClientHost client_host; + DevToolsAgentHost* agent_host = + DevToolsAgentHostRegistry::GetDevToolsAgentHost(inspected_rvh); + DevToolsManager::GetInstance()-> + RegisterDevToolsClientHostFor(agent_host, &client_host); + + // Start with a short timeout. + inspected_rvh->StartHangMonitorTimeout(TimeDelta::FromMilliseconds(10)); + // Wait long enough for first timeout and see if it fired. + MessageLoop::current()->PostDelayedTask( + FROM_HERE, MessageLoop::QuitClosure(), TimeDelta::FromMilliseconds(10)); + MessageLoop::current()->Run(); + EXPECT_FALSE(delegate.renderer_unresponsive_received()); + + // Now close devtools and check that the notification is delivered. + client_host.Close(DevToolsManager::GetInstance()); + // Start with a short timeout. + inspected_rvh->StartHangMonitorTimeout(TimeDelta::FromMilliseconds(10)); + // Wait long enough for first timeout and see if it fired. + MessageLoop::current()->PostDelayedTask( + FROM_HERE, MessageLoop::QuitClosure(), TimeDelta::FromMilliseconds(10)); + MessageLoop::current()->Run(); + EXPECT_TRUE(delegate.renderer_unresponsive_received()); + + contents()->SetDelegate(NULL); +} + +TEST_F(DevToolsManagerTest, ReattachOnCancelPendingNavigation) { + contents()->transition_cross_site = true; + // Navigate to URL. First URL should use first RenderViewHost. + const GURL url("http://www.google.com"); + controller().LoadURL( + url, Referrer(), PAGE_TRANSITION_TYPED, std::string()); + contents()->TestDidNavigate(rvh(), 1, url, PAGE_TRANSITION_TYPED); + EXPECT_FALSE(contents()->cross_navigation_pending()); + + TestDevToolsClientHost client_host; + DevToolsManager* devtools_manager = DevToolsManager::GetInstance(); + devtools_manager->RegisterDevToolsClientHostFor( + DevToolsAgentHostRegistry::GetDevToolsAgentHost(rvh()), + &client_host); + + // Navigate to new site which should get a new RenderViewHost. + const GURL url2("http://www.yahoo.com"); + controller().LoadURL( + url2, Referrer(), PAGE_TRANSITION_TYPED, std::string()); + EXPECT_TRUE(contents()->cross_navigation_pending()); + EXPECT_EQ(&client_host, devtools_manager->GetDevToolsClientHostFor( + DevToolsAgentHostRegistry::GetDevToolsAgentHost(pending_rvh()))); + + // Interrupt pending navigation and navigate back to the original site. + controller().LoadURL( + url, Referrer(), PAGE_TRANSITION_TYPED, std::string()); + contents()->TestDidNavigate(rvh(), 1, url, PAGE_TRANSITION_TYPED); + EXPECT_FALSE(contents()->cross_navigation_pending()); + EXPECT_EQ(&client_host, devtools_manager->GetDevToolsClientHostFor( + DevToolsAgentHostRegistry::GetDevToolsAgentHost(rvh()))); + client_host.Close(DevToolsManager::GetInstance()); +} + +} // namespace content diff --git a/content/browser/devtools/devtools_netlog_observer.cc b/content/browser/devtools/devtools_netlog_observer.cc new file mode 100644 index 0000000..f65bc42 --- /dev/null +++ b/content/browser/devtools/devtools_netlog_observer.cc @@ -0,0 +1,329 @@ +// Copyright (c) 2012 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 "content/browser/devtools/devtools_netlog_observer.h" + +#include "base/string_tokenizer.h" +#include "base/string_util.h" +#include "base/values.h" +#include "content/public/browser/browser_thread.h" +#include "content/public/browser/content_browser_client.h" +#include "content/public/common/resource_response.h" +#include "net/base/load_flags.h" +#include "net/http/http_response_headers.h" +#include "net/http/http_util.h" +#include "net/spdy/spdy_header_block.h" +#include "net/url_request/url_request.h" +#include "net/url_request/url_request_netlog_params.h" +#include "webkit/glue/resource_loader_bridge.h" + +namespace content { +const size_t kMaxNumEntries = 1000; + +DevToolsNetLogObserver* DevToolsNetLogObserver::instance_ = NULL; + +DevToolsNetLogObserver::DevToolsNetLogObserver() { +} + +DevToolsNetLogObserver::~DevToolsNetLogObserver() { +} + +DevToolsNetLogObserver::ResourceInfo* +DevToolsNetLogObserver::GetResourceInfo(uint32 id) { + RequestToInfoMap::iterator it = request_to_info_.find(id); + if (it != request_to_info_.end()) + return it->second; + return NULL; +} + +void DevToolsNetLogObserver::OnAddEntry(const net::NetLog::Entry& entry) { + // The events that the Observer is interested in only occur on the IO thread. + if (!BrowserThread::CurrentlyOn(BrowserThread::IO)) + return; + + if (entry.source().type == net::NetLog::SOURCE_URL_REQUEST) + OnAddURLRequestEntry(entry); + else if (entry.source().type == net::NetLog::SOURCE_HTTP_STREAM_JOB) + OnAddHTTPStreamJobEntry(entry); + else if (entry.source().type == net::NetLog::SOURCE_SOCKET) + OnAddSocketEntry(entry); +} + +void DevToolsNetLogObserver::OnAddURLRequestEntry( + const net::NetLog::Entry& entry) { + DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); + + bool is_begin = entry.phase() == net::NetLog::PHASE_BEGIN; + bool is_end = entry.phase() == net::NetLog::PHASE_END; + + if (entry.type() == net::NetLog::TYPE_URL_REQUEST_START_JOB) { + if (is_begin) { + int load_flags; + scoped_ptr event_param(entry.ParametersToValue()); + if (!net::StartEventLoadFlagsFromEventParams(event_param.get(), + &load_flags)) { + return; + } + + if (!(load_flags & net::LOAD_REPORT_RAW_HEADERS)) + return; + + if (request_to_info_.size() > kMaxNumEntries) { + LOG(WARNING) << "The raw headers observer url request count has grown " + "larger than expected, resetting"; + request_to_info_.clear(); + } + + request_to_info_[entry.source().id] = new ResourceInfo(); + + if (request_to_encoded_data_length_.size() > kMaxNumEntries) { + LOG(WARNING) << "The encoded data length observer url request count " + "has grown larger than expected, resetting"; + request_to_encoded_data_length_.clear(); + } + + request_to_encoded_data_length_[entry.source().id] = 0; + } + return; + } else if (entry.type() == net::NetLog::TYPE_REQUEST_ALIVE) { + // Cleanup records based on the TYPE_REQUEST_ALIVE entry. + if (is_end) { + request_to_info_.erase(entry.source().id); + request_to_encoded_data_length_.erase(entry.source().id); + } + return; + } + + ResourceInfo* info = GetResourceInfo(entry.source().id); + if (!info) + return; + + switch (entry.type()) { + case net::NetLog::TYPE_HTTP_TRANSACTION_SEND_REQUEST_HEADERS: { + scoped_ptr event_params(entry.ParametersToValue()); + std::string request_line; + net::HttpRequestHeaders request_headers; + + if (!net::HttpRequestHeaders::FromNetLogParam(event_params.get(), + &request_headers, + &request_line)) { + NOTREACHED(); + } + + // We need to clear headers in case the same url_request is reused for + // several http requests (e.g. see http://crbug.com/80157). + info->request_headers.clear(); + + for (net::HttpRequestHeaders::Iterator it(request_headers); + it.GetNext();) { + info->request_headers.push_back(std::make_pair(it.name(), it.value())); + } + info->request_headers_text = request_line + request_headers.ToString(); + break; + } + case net::NetLog::TYPE_HTTP_TRANSACTION_SPDY_SEND_REQUEST_HEADERS: { + scoped_ptr event_params(entry.ParametersToValue()); + net::SpdyHeaderBlock request_headers; + + if (!net::SpdyHeaderBlockFromNetLogParam(event_params.get(), + &request_headers)) { + NOTREACHED(); + } + + // We need to clear headers in case the same url_request is reused for + // several http requests (e.g. see http://crbug.com/80157). + info->request_headers.clear(); + + for (net::SpdyHeaderBlock::const_iterator it = request_headers.begin(); + it != request_headers.end(); ++it) { + info->request_headers.push_back(std::make_pair(it->first, it->second)); + } + info->request_headers_text = ""; + break; + } + case net::NetLog::TYPE_HTTP_TRANSACTION_READ_RESPONSE_HEADERS: { + scoped_ptr event_params(entry.ParametersToValue()); + + scoped_refptr response_headers; + + if (!net::HttpResponseHeaders::FromNetLogParam(event_params.get(), + &response_headers)) { + NOTREACHED(); + } + + info->http_status_code = response_headers->response_code(); + info->http_status_text = response_headers->GetStatusText(); + std::string name, value; + + // We need to clear headers in case the same url_request is reused for + // several http requests (e.g. see http://crbug.com/80157). + info->response_headers.clear(); + + for (void* it = NULL; + response_headers->EnumerateHeaderLines(&it, &name, &value); ) { + info->response_headers.push_back(std::make_pair(name, value)); + } + info->response_headers_text = + net::HttpUtil::ConvertHeadersBackToHTTPResponse( + response_headers->raw_headers()); + break; + } + case net::NetLog::TYPE_HTTP_STREAM_REQUEST_BOUND_TO_JOB: { + scoped_ptr event_params(entry.ParametersToValue()); + net::NetLog::Source http_stream_job_source; + if (!net::NetLog::Source::FromEventParameters(event_params.get(), + &http_stream_job_source)) { + NOTREACHED(); + break; + } + + uint32 http_stream_job_id = http_stream_job_source.id; + HTTPStreamJobToSocketMap::iterator it = + http_stream_job_to_socket_.find(http_stream_job_id); + if (it == http_stream_job_to_socket_.end()) + return; + uint32 socket_id = it->second; + + if (socket_to_request_.size() > kMaxNumEntries) { + LOG(WARNING) << "The url request observer socket count has grown " + "larger than expected, resetting"; + socket_to_request_.clear(); + } + + socket_to_request_[socket_id] = entry.source().id; + http_stream_job_to_socket_.erase(http_stream_job_id); + break; + } + default: + break; + } +} + +void DevToolsNetLogObserver::OnAddHTTPStreamJobEntry( + const net::NetLog::Entry& entry) { + DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); + + if (entry.type() == net::NetLog::TYPE_SOCKET_POOL_BOUND_TO_SOCKET) { + scoped_ptr event_params(entry.ParametersToValue()); + net::NetLog::Source socket_source; + if (!net::NetLog::Source::FromEventParameters(event_params.get(), + &socket_source)) { + NOTREACHED(); + return; + } + + // Prevents us from passively growing the memory unbounded in + // case something went wrong. Should not happen. + if (http_stream_job_to_socket_.size() > kMaxNumEntries) { + LOG(WARNING) << "The load timing observer http stream job count " + "has grown larger than expected, resetting"; + http_stream_job_to_socket_.clear(); + } + http_stream_job_to_socket_[entry.source().id] = socket_source.id; + } +} + +void DevToolsNetLogObserver::OnAddSocketEntry( + const net::NetLog::Entry& entry) { + DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); + + bool is_end = entry.phase() == net::NetLog::PHASE_END; + + SocketToRequestMap::iterator it = + socket_to_request_.find(entry.source().id); + if (it == socket_to_request_.end()) + return; + uint32 request_id = it->second; + + if (entry.type() == net::NetLog::TYPE_SOCKET_IN_USE) { + if (is_end) + socket_to_request_.erase(entry.source().id); + return; + } + + RequestToEncodedDataLengthMap::iterator encoded_data_length_it = + request_to_encoded_data_length_.find(request_id); + if (encoded_data_length_it == request_to_encoded_data_length_.end()) + return; + + if (net::NetLog::TYPE_SOCKET_BYTES_RECEIVED == entry.type()) { + int byte_count = 0; + scoped_ptr value(entry.ParametersToValue()); + if (!value->IsType(Value::TYPE_DICTIONARY)) + return; + + DictionaryValue* dValue = static_cast(value.get()); + if (!dValue->GetInteger("byte_count", &byte_count)) + return; + + encoded_data_length_it->second += byte_count; + } +} + +void DevToolsNetLogObserver::Attach() { + DCHECK(!instance_); + net::NetLog* net_log = GetContentClient()->browser()->GetNetLog(); + if (net_log) { + instance_ = new DevToolsNetLogObserver(); + net_log->AddThreadSafeObserver(instance_, net::NetLog::LOG_ALL_BUT_BYTES); + } +} + +void DevToolsNetLogObserver::Detach() { + DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); + + if (instance_) { + // Safest not to do this in the destructor to maintain thread safety across + // refactorings. + instance_->net_log()->RemoveThreadSafeObserver(instance_); + delete instance_; + instance_ = NULL; + } +} + +DevToolsNetLogObserver* DevToolsNetLogObserver::GetInstance() { + DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); + + return instance_; +} + +// static +void DevToolsNetLogObserver::PopulateResponseInfo( + net::URLRequest* request, + ResourceResponse* response) { + if (!(request->load_flags() & net::LOAD_REPORT_RAW_HEADERS)) + return; + + uint32 source_id = request->net_log().source().id; + DevToolsNetLogObserver* dev_tools_net_log_observer = + DevToolsNetLogObserver::GetInstance(); + if (dev_tools_net_log_observer == NULL) + return; + response->head.devtools_info = + dev_tools_net_log_observer->GetResourceInfo(source_id); +} + +// static +int DevToolsNetLogObserver::GetAndResetEncodedDataLength( + net::URLRequest* request) { + if (!(request->load_flags() & net::LOAD_REPORT_RAW_HEADERS)) + return -1; + + uint32 source_id = request->net_log().source().id; + DevToolsNetLogObserver* dev_tools_net_log_observer = + DevToolsNetLogObserver::GetInstance(); + if (dev_tools_net_log_observer == NULL) + return -1; + + RequestToEncodedDataLengthMap::iterator it = + dev_tools_net_log_observer->request_to_encoded_data_length_.find( + source_id); + if (it == dev_tools_net_log_observer->request_to_encoded_data_length_.end()) + return -1; + int encoded_data_length = it->second; + it->second = 0; + return encoded_data_length; +} + +} // namespace content diff --git a/content/browser/devtools/devtools_netlog_observer.h b/content/browser/devtools/devtools_netlog_observer.h new file mode 100644 index 0000000..4e74edd --- /dev/null +++ b/content/browser/devtools/devtools_netlog_observer.h @@ -0,0 +1,70 @@ +// Copyright (c) 2012 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 CONTENT_BROWSER_DEVTOOLS_DEVTOOLS_NETLOG_OBSERVER_H_ +#define CONTENT_BROWSER_DEVTOOLS_DEVTOOLS_NETLOG_OBSERVER_H_ + +#include "base/hash_tables.h" +#include "base/memory/ref_counted.h" +#include "net/base/net_log.h" +#include "webkit/glue/resource_loader_bridge.h" + +namespace net { +class URLRequest; +} // namespace net + +namespace content { +struct ResourceResponse; + +// DevToolsNetLogObserver watches the NetLog event stream and collects the +// stuff that may be of interest to DevTools. Currently, this only includes +// actual HTTP/SPDY headers sent and received over the network. +// +// As DevToolsNetLogObserver shares live data with objects that live on the +// IO Thread, it must also reside on the IO Thread. Only OnAddEntry can be +// called from other threads. +class DevToolsNetLogObserver : public net::NetLog::ThreadSafeObserver { + typedef webkit_glue::ResourceDevToolsInfo ResourceInfo; + + public: + // net::NetLog::ThreadSafeObserver implementation: + virtual void OnAddEntry(const net::NetLog::Entry& entry) OVERRIDE; + + void OnAddURLRequestEntry(const net::NetLog::Entry& entry); + void OnAddHTTPStreamJobEntry(const net::NetLog::Entry& entry); + void OnAddSocketEntry(const net::NetLog::Entry& entry); + + static void Attach(); + static void Detach(); + + // Must be called on the IO thread. May return NULL if no observers + // are active. + static DevToolsNetLogObserver* GetInstance(); + static void PopulateResponseInfo(net::URLRequest*, + ResourceResponse*); + static int GetAndResetEncodedDataLength(net::URLRequest* request); + + private: + static DevToolsNetLogObserver* instance_; + + DevToolsNetLogObserver(); + virtual ~DevToolsNetLogObserver(); + + ResourceInfo* GetResourceInfo(uint32 id); + + typedef base::hash_map > RequestToInfoMap; + typedef base::hash_map RequestToEncodedDataLengthMap; + typedef base::hash_map HTTPStreamJobToSocketMap; + typedef base::hash_map SocketToRequestMap; + RequestToInfoMap request_to_info_; + RequestToEncodedDataLengthMap request_to_encoded_data_length_; + HTTPStreamJobToSocketMap http_stream_job_to_socket_; + SocketToRequestMap socket_to_request_; + + DISALLOW_COPY_AND_ASSIGN(DevToolsNetLogObserver); +}; + +} // namespace content + +#endif // CONTENT_BROWSER_DEVTOOLS_DEVTOOLS_NETLOG_OBSERVER_H_ diff --git a/content/browser/devtools/devtools_resources.gyp b/content/browser/devtools/devtools_resources.gyp new file mode 100644 index 0000000..9ee2076 --- /dev/null +++ b/content/browser/devtools/devtools_resources.gyp @@ -0,0 +1,58 @@ +# Copyright (c) 2012 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. + +{ + 'variables': { + 'conditions': [ + ['inside_chromium_build==0', { + 'webkit_src_dir': '../../../../../..', + },{ + 'webkit_src_dir': '../../../third_party/WebKit', + }], + ], + }, + 'targets': [ + { + 'target_name': 'devtools_resources', + 'type': 'none', + 'dependencies': [ + '<(webkit_src_dir)/Source/WebKit/chromium/WebKit.gyp:generate_devtools_grd', + ], + 'variables': { + 'grit_out_dir': '<(SHARED_INTERMEDIATE_DIR)/webkit', + }, + 'actions': [ + { + 'action_name': 'devtools_resources', + # This can't use build/grit_action.gypi because the grd file + # is generated at build time, so the trick of using grit_info to get + # the real inputs/outputs at GYP time isn't possible. + 'variables': { + 'grit_cmd': ['python', '../../../tools/grit/grit.py'], + 'grit_grd_file': '<(SHARED_INTERMEDIATE_DIR)/devtools/devtools_resources.grd', + }, + 'inputs': [ + '<(grit_grd_file)', + '& trace_fragment) { + buffer_.push_back(trace_fragment->data()); + buffer_data_size_ += trace_fragment->data().size(); +} + +base::Value* DevToolsTracingHandler::OnProtocolCommand( + const std::string& method, + const base::DictionaryValue* params, + base::Value** error_out) { + if (method == "Tracing.start") + return Start(params); + else if (method == "Tracing.end") + return End(params); + else if (method == "Tracing.hasCompleted") + return HasCompleted(params); + else if (method == "Tracing.getTraceAndReset") + return GetTraceAndReset(params); + + base::DictionaryValue* error_object = new base::DictionaryValue(); + error_object->SetInteger("code", -1); + error_object->SetString("message", "Invalid method"); + + *error_out = error_object; + + return NULL; +} + +base::Value* DevToolsTracingHandler::Start( + const base::DictionaryValue* params) { + std::string categories; + if (params && params->HasKey("categories")) + params->GetString("categories", &categories); + TraceController::GetInstance()->BeginTracing(this, categories); + + return base::Value::CreateBooleanValue(true); +} + +base::Value* DevToolsTracingHandler::End( + const base::DictionaryValue* /* params */) { + TraceController::GetInstance()->EndTracingAsync(this); + + return base::Value::CreateBooleanValue(true); +} + + +base::Value* DevToolsTracingHandler::HasCompleted( + const base::DictionaryValue* /* params */) { + + return base::Value::CreateBooleanValue(has_completed_); +} + +base::Value* DevToolsTracingHandler::GetTraceAndReset( + const base::DictionaryValue* /* params */) { + std::string ret; + ret.reserve(buffer_data_size_); + for (std::vector::const_iterator i = buffer_.begin(); + i != buffer_.end(); ++i) { + if (!ret.empty()) + ret.append(","); + ret.append(*i); + } + buffer_.clear(); + has_completed_ = false; + buffer_data_size_ = 0; + + return base::Value::CreateStringValue(ret); +} + +} // namespace content diff --git a/content/browser/devtools/devtools_tracing_handler.h b/content/browser/devtools/devtools_tracing_handler.h new file mode 100644 index 0000000..c01896a --- /dev/null +++ b/content/browser/devtools/devtools_tracing_handler.h @@ -0,0 +1,50 @@ +// Copyright (c) 2012 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 CONTENT_BROWSER_DEVTOOLS_DEVTOOLS_TRACING_HANDLER_H_ +#define CONTENT_BROWSER_DEVTOOLS_DEVTOOLS_TRACING_HANDLER_H_ + +#include "content/browser/devtools/devtools_browser_target.h" +#include "content/public/browser/trace_subscriber.h" + +namespace content { + +// This class bridges DevTools remote debugging server with the trace +// infrastructure. +class DevToolsTracingHandler + : public TraceSubscriber, + public DevToolsBrowserTarget::Handler { + public: + DevToolsTracingHandler(); + virtual ~DevToolsTracingHandler(); + + // TraceSubscriber: + virtual void OnEndTracingComplete() OVERRIDE;; + virtual void OnTraceDataCollected( + const scoped_refptr& trace_fragment) OVERRIDE; + + // DevToolBrowserTarget::Handler: + virtual std::string Domain() OVERRIDE; + virtual base::Value* OnProtocolCommand( + const std::string& method, + const base::DictionaryValue* params, + base::Value** error_out) OVERRIDE; + + private: + base::Value* Start(const base::DictionaryValue* params); + base::Value* End(const base::DictionaryValue* params); + base::Value* HasCompleted(const base::DictionaryValue* params); + base::Value* GetTraceAndReset(const base::DictionaryValue* params); + + bool has_completed_; + + std::vector buffer_; + int buffer_data_size_; + + DISALLOW_COPY_AND_ASSIGN(DevToolsTracingHandler); +}; + +} // namespace content + +#endif // CONTENT_BROWSER_DEVTOOLS_DEVTOOLS_TRACING_HANDLER_H_ diff --git a/content/browser/devtools/render_view_devtools_agent_host.cc b/content/browser/devtools/render_view_devtools_agent_host.cc new file mode 100644 index 0000000..4de7545 --- /dev/null +++ b/content/browser/devtools/render_view_devtools_agent_host.cc @@ -0,0 +1,154 @@ +// Copyright (c) 2012 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 "content/browser/devtools/render_view_devtools_agent_host.h" + +#include "base/basictypes.h" +#include "base/lazy_instance.h" +#include "content/browser/devtools/devtools_manager_impl.h" +#include "content/browser/devtools/render_view_devtools_agent_host.h" +#include "content/browser/renderer_host/render_process_host_impl.h" +#include "content/browser/renderer_host/render_view_host_impl.h" +#include "content/browser/site_instance_impl.h" +#include "content/browser/web_contents/web_contents_impl.h" +#include "content/common/devtools_messages.h" +#include "content/public/browser/content_browser_client.h" +#include "content/public/browser/devtools_agent_host_registry.h" +#include "content/public/browser/notification_service.h" +#include "content/public/browser/notification_types.h" + +namespace content { + +typedef std::map Instances; + +namespace { +base::LazyInstance::Leaky g_instances = LAZY_INSTANCE_INITIALIZER; +} // namespace + +// static +DevToolsAgentHost* DevToolsAgentHostRegistry::GetDevToolsAgentHost( + RenderViewHost* rvh) { + Instances::iterator it = g_instances.Get().find(rvh); + if (it != g_instances.Get().end()) + return it->second; + return new RenderViewDevToolsAgentHost(rvh); +} + +// static +RenderViewHost* DevToolsAgentHostRegistry::GetRenderViewHost( + DevToolsAgentHost* agent_host) { + for (Instances::iterator it = g_instances.Get().begin(); + it != g_instances.Get().end(); ++it) { + if (agent_host == it->second) + return it->first; + } + return NULL; +} + +// static +bool DevToolsAgentHostRegistry::HasDevToolsAgentHost(RenderViewHost* rvh) { + if (g_instances == NULL) + return false; + Instances::iterator it = g_instances.Get().find(rvh); + return it != g_instances.Get().end(); +} + +bool DevToolsAgentHostRegistry::IsDebuggerAttached(WebContents* web_contents) { + if (g_instances == NULL) + return false; + DevToolsManager* devtools_manager = DevToolsManager::GetInstance(); + if (!devtools_manager) + return false; + RenderViewHostDelegate* delegate = + static_cast(web_contents); + for (Instances::iterator it = g_instances.Get().begin(); + it != g_instances.Get().end(); ++it) { + if (it->first->GetDelegate() != delegate) + continue; + if (devtools_manager->GetDevToolsClientHostFor(it->second)) + return true; + } + return false; +} + +RenderViewDevToolsAgentHost::RenderViewDevToolsAgentHost( + RenderViewHost* rvh) + : RenderViewHostObserver(rvh), + render_view_host_(rvh) { + g_instances.Get()[rvh] = this; +} + +void RenderViewDevToolsAgentHost::SendMessageToAgent(IPC::Message* msg) { + msg->set_routing_id(render_view_host_->GetRoutingID()); + render_view_host_->Send(msg); +} + +void RenderViewDevToolsAgentHost::NotifyClientAttaching() { + NotificationService::current()->Notify( + NOTIFICATION_DEVTOOLS_AGENT_ATTACHED, + Source( + render_view_host_->GetSiteInstance()->GetProcess()-> + GetBrowserContext()), + Details(render_view_host_)); +} + +void RenderViewDevToolsAgentHost::NotifyClientDetaching() { + NotificationService::current()->Notify( + NOTIFICATION_DEVTOOLS_AGENT_DETACHED, + Source( + render_view_host_->GetSiteInstance()->GetProcess()-> + GetBrowserContext()), + Details(render_view_host_)); +} + +int RenderViewDevToolsAgentHost::GetRenderProcessId() { + return render_view_host_->GetProcess()->GetID(); +} + +RenderViewDevToolsAgentHost::~RenderViewDevToolsAgentHost() { + g_instances.Get().erase(render_view_host_); +} + +void RenderViewDevToolsAgentHost::RenderViewHostDestroyed( + RenderViewHost* rvh) { + NotifyCloseListener(); + delete this; +} + +bool RenderViewDevToolsAgentHost::OnMessageReceived( + const IPC::Message& message) { + bool handled = true; + IPC_BEGIN_MESSAGE_MAP(RenderViewDevToolsAgentHost, message) + IPC_MESSAGE_HANDLER(DevToolsClientMsg_DispatchOnInspectorFrontend, + OnDispatchOnInspectorFrontend) + IPC_MESSAGE_HANDLER(DevToolsHostMsg_SaveAgentRuntimeState, + OnSaveAgentRuntimeState) + IPC_MESSAGE_HANDLER(DevToolsHostMsg_ClearBrowserCache, OnClearBrowserCache) + IPC_MESSAGE_HANDLER(DevToolsHostMsg_ClearBrowserCookies, + OnClearBrowserCookies) + IPC_MESSAGE_UNHANDLED(handled = false) + IPC_END_MESSAGE_MAP() + return handled; +} + +void RenderViewDevToolsAgentHost::OnSaveAgentRuntimeState( + const std::string& state) { + DevToolsManagerImpl::GetInstance()->SaveAgentRuntimeState(this, state); +} + +void RenderViewDevToolsAgentHost::OnDispatchOnInspectorFrontend( + const std::string& message) { + DevToolsManagerImpl::GetInstance()->DispatchOnInspectorFrontend( + this, message); +} + +void RenderViewDevToolsAgentHost::OnClearBrowserCache() { + GetContentClient()->browser()->ClearCache(render_view_host_); +} + +void RenderViewDevToolsAgentHost::OnClearBrowserCookies() { + GetContentClient()->browser()->ClearCookies(render_view_host_); +} + +} // namespace content diff --git a/content/browser/devtools/render_view_devtools_agent_host.h b/content/browser/devtools/render_view_devtools_agent_host.h new file mode 100644 index 0000000..afd3173 --- /dev/null +++ b/content/browser/devtools/render_view_devtools_agent_host.h @@ -0,0 +1,51 @@ +// Copyright (c) 2012 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 CONTENT_BROWSER_DEVTOOLS_RENDER_VIEW_DEVTOOLS_AGENT_HOST_H_ +#define CONTENT_BROWSER_DEVTOOLS_RENDER_VIEW_DEVTOOLS_AGENT_HOST_H_ + +#include + +#include "base/basictypes.h" +#include "base/compiler_specific.h" +#include "content/browser/devtools/devtools_agent_host.h" +#include "content/common/content_export.h" +#include "content/public/browser/render_view_host_observer.h" + +namespace content { + +class RenderViewHost; + +class CONTENT_EXPORT RenderViewDevToolsAgentHost + : public DevToolsAgentHost, + private RenderViewHostObserver { + public: + RenderViewDevToolsAgentHost(RenderViewHost*); + + private: + virtual ~RenderViewDevToolsAgentHost(); + + // DevToolsAgentHost implementation. + virtual void SendMessageToAgent(IPC::Message* msg) OVERRIDE; + virtual void NotifyClientAttaching() OVERRIDE; + virtual void NotifyClientDetaching() OVERRIDE; + virtual int GetRenderProcessId() OVERRIDE; + + // RenderViewHostObserver overrides. + virtual void RenderViewHostDestroyed(RenderViewHost* rvh) OVERRIDE; + virtual bool OnMessageReceived(const IPC::Message& message) OVERRIDE; + + void OnDispatchOnInspectorFrontend(const std::string& message); + void OnSaveAgentRuntimeState(const std::string& state); + void OnClearBrowserCache(); + void OnClearBrowserCookies(); + + RenderViewHost* render_view_host_; + + DISALLOW_COPY_AND_ASSIGN(RenderViewDevToolsAgentHost); +}; + +} // namespace content + +#endif // CONTENT_BROWSER_DEVTOOLS_RENDER_VIEW_DEVTOOLS_AGENT_HOST_H_ diff --git a/content/browser/devtools/worker_devtools_manager.cc b/content/browser/devtools/worker_devtools_manager.cc new file mode 100644 index 0000000..f341c82 --- /dev/null +++ b/content/browser/devtools/worker_devtools_manager.cc @@ -0,0 +1,472 @@ +// Copyright (c) 2011 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 "content/browser/devtools/worker_devtools_manager.h" + +#include +#include + +#include "base/bind.h" +#include "content/browser/devtools/devtools_agent_host.h" +#include "content/browser/devtools/devtools_manager_impl.h" +#include "content/browser/devtools/worker_devtools_message_filter.h" +#include "content/browser/worker_host/worker_service_impl.h" +#include "content/common/devtools_messages.h" +#include "content/public/browser/browser_thread.h" +#include "content/public/browser/child_process_data.h" +#include "content/public/browser/devtools_agent_host_registry.h" +#include "content/public/common/process_type.h" +#include "third_party/WebKit/Source/WebKit/chromium/public/WebDevToolsAgent.h" +#include "third_party/WebKit/Source/WebKit/chromium/public/platform/WebCString.h" +#include "third_party/WebKit/Source/WebKit/chromium/public/platform/WebString.h" + +namespace content { + +// Called on the UI thread. +// static +DevToolsAgentHost* DevToolsAgentHostRegistry::GetDevToolsAgentHostForWorker( + int worker_process_id, + int worker_route_id) { + return WorkerDevToolsManager::GetDevToolsAgentHostForWorker( + worker_process_id, + worker_route_id); +} + +class WorkerDevToolsManager::AgentHosts { +public: + static void Add(WorkerId id, WorkerDevToolsAgentHost* host) { + DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); + if (!instance_) + instance_ = new AgentHosts(); + instance_->map_[id] = host; + } + static void Remove(WorkerId id) { + DCHECK(instance_); + DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); + Instances& map = instance_->map_; + map.erase(id); + if (map.empty()) { + delete instance_; + instance_ = NULL; + } + } + + static WorkerDevToolsAgentHost* GetAgentHost(WorkerId id) { + DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); + if (!instance_) + return NULL; + Instances& map = instance_->map_; + Instances::iterator it = map.find(id); + if (it == map.end()) + return NULL; + return it->second; + } + +private: + AgentHosts() { + } + ~AgentHosts() {} + + static AgentHosts* instance_; + typedef std::map Instances; + Instances map_; +}; + +WorkerDevToolsManager::AgentHosts* + WorkerDevToolsManager::AgentHosts::instance_ = NULL; + + +struct WorkerDevToolsManager::TerminatedInspectedWorker { + TerminatedInspectedWorker(WorkerId id, const GURL& url, const string16& name) + : old_worker_id(id), + worker_url(url), + worker_name(name) {} + WorkerId old_worker_id; + GURL worker_url; + string16 worker_name; +}; + + +class WorkerDevToolsManager::WorkerDevToolsAgentHost + : public DevToolsAgentHost { + public: + explicit WorkerDevToolsAgentHost(WorkerId worker_id) + : worker_id_(worker_id) { + AgentHosts::Add(worker_id, this); + BrowserThread::PostTask( + BrowserThread::IO, + FROM_HERE, + base::Bind( + &RegisterAgent, + worker_id.first, + worker_id.second)); + } + + void WorkerDestroyed() { + NotifyCloseListener(); + delete this; + } + + private: + virtual ~WorkerDevToolsAgentHost() { + AgentHosts::Remove(worker_id_); + } + + static void RegisterAgent( + int worker_process_id, + int worker_route_id) { + WorkerDevToolsManager::GetInstance()->RegisterDevToolsAgentHostForWorker( + worker_process_id, worker_route_id); + } + + static void ForwardToWorkerDevToolsAgent( + int worker_process_id, + int worker_route_id, + IPC::Message* message) { + WorkerDevToolsManager::GetInstance()->ForwardToWorkerDevToolsAgent( + worker_process_id, worker_route_id, *message); + } + + // DevToolsAgentHost implementation. + virtual void SendMessageToAgent(IPC::Message* message) OVERRIDE { + BrowserThread::PostTask( + BrowserThread::IO, FROM_HERE, + base::Bind( + &WorkerDevToolsAgentHost::ForwardToWorkerDevToolsAgent, + worker_id_.first, + worker_id_.second, + base::Owned(message))); + } + virtual void NotifyClientAttaching() OVERRIDE {} + virtual void NotifyClientDetaching() OVERRIDE {} + virtual int GetRenderProcessId() OVERRIDE { return -1; } + + WorkerId worker_id_; + + DISALLOW_COPY_AND_ASSIGN(WorkerDevToolsAgentHost); +}; + + +class WorkerDevToolsManager::DetachedClientHosts { + public: + static void WorkerReloaded(WorkerId old_id, WorkerId new_id) { + DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); + if (instance_ && instance_->ReattachClient(old_id, new_id)) + return; + RemovePendingWorkerData(old_id); + } + + static void WorkerDestroyed(WorkerId id) { + DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); + WorkerDevToolsAgentHost* agent = AgentHosts::GetAgentHost(id); + if (!agent) { + RemovePendingWorkerData(id); + return; + } + DevToolsManagerImpl::GetInstance()->DispatchOnInspectorFrontend( + agent, + WebKit::WebDevToolsAgent::workerDisconnectedFromWorkerEvent().utf8()); + int cookie = DevToolsManagerImpl::GetInstance()->DetachClientHost(agent); + agent->WorkerDestroyed(); + if (cookie == -1) { + RemovePendingWorkerData(id); + return; + } + if (!instance_) + new DetachedClientHosts(); + instance_->worker_id_to_cookie_[id] = cookie; + } + + private: + DetachedClientHosts() { + instance_ = this; + } + ~DetachedClientHosts() { + instance_ = NULL; + } + + bool ReattachClient(WorkerId old_id, WorkerId new_id) { + WorkerIdToCookieMap::iterator it = worker_id_to_cookie_.find(old_id); + if (it == worker_id_to_cookie_.end()) + return false; + DevToolsAgentHost* agent = + WorkerDevToolsManager::GetDevToolsAgentHostForWorker( + new_id.first, + new_id.second); + DevToolsManagerImpl::GetInstance()->AttachClientHost( + it->second, + agent); + worker_id_to_cookie_.erase(it); + if (worker_id_to_cookie_.empty()) + delete this; + return true; + } + + static void RemovePendingWorkerData(WorkerId id) { + BrowserThread::PostTask( + BrowserThread::IO, FROM_HERE, + base::Bind(&RemoveInspectedWorkerDataOnIOThread, id)); + } + + static void RemoveInspectedWorkerDataOnIOThread(WorkerId id) { + WorkerDevToolsManager::GetInstance()->RemoveInspectedWorkerData(id); + } + + static DetachedClientHosts* instance_; + typedef std::map WorkerIdToCookieMap; + WorkerIdToCookieMap worker_id_to_cookie_; +}; + +WorkerDevToolsManager::DetachedClientHosts* + WorkerDevToolsManager::DetachedClientHosts::instance_ = NULL; + +struct WorkerDevToolsManager::InspectedWorker { + InspectedWorker(WorkerProcessHost* host, int route_id, const GURL& url, + const string16& name) + : host(host), + route_id(route_id), + worker_url(url), + worker_name(name) {} + WorkerProcessHost* const host; + int const route_id; + GURL worker_url; + string16 worker_name; +}; + +// static +WorkerDevToolsManager* WorkerDevToolsManager::GetInstance() { + DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); + return Singleton::get(); +} + +// static +DevToolsAgentHost* WorkerDevToolsManager::GetDevToolsAgentHostForWorker( + int worker_process_id, + int worker_route_id) { + WorkerId id(worker_process_id, worker_route_id); + WorkerDevToolsAgentHost* result = AgentHosts::GetAgentHost(id); + if (!result) + result = new WorkerDevToolsAgentHost(id); + return result; +} + +WorkerDevToolsManager::WorkerDevToolsManager() { +} + +WorkerDevToolsManager::~WorkerDevToolsManager() { +} + +void WorkerDevToolsManager::WorkerCreated( + WorkerProcessHost* worker, + const WorkerProcessHost::WorkerInstance& instance) { + for (TerminatedInspectedWorkers::iterator it = terminated_workers_.begin(); + it != terminated_workers_.end(); ++it) { + if (instance.Matches(it->worker_url, it->worker_name, + instance.partition(), + instance.resource_context())) { + worker->Send(new DevToolsAgentMsg_PauseWorkerContextOnStart( + instance.worker_route_id())); + WorkerId new_worker_id(worker->GetData().id, instance.worker_route_id()); + paused_workers_[new_worker_id] = it->old_worker_id; + terminated_workers_.erase(it); + return; + } + } +} + +void WorkerDevToolsManager::WorkerDestroyed( + WorkerProcessHost* worker, + int worker_route_id) { + InspectedWorkersList::iterator it = FindInspectedWorker( + worker->GetData().id, + worker_route_id); + if (it == inspected_workers_.end()) + return; + + WorkerId worker_id(worker->GetData().id, worker_route_id); + terminated_workers_.push_back(TerminatedInspectedWorker( + worker_id, + it->worker_url, + it->worker_name)); + inspected_workers_.erase(it); + BrowserThread::PostTask( + BrowserThread::UI, FROM_HERE, + base::Bind(&DetachedClientHosts::WorkerDestroyed, worker_id)); +} + +void WorkerDevToolsManager::WorkerContextStarted(WorkerProcessHost* process, + int worker_route_id) { + WorkerId new_worker_id(process->GetData().id, worker_route_id); + PausedWorkers::iterator it = paused_workers_.find(new_worker_id); + if (it == paused_workers_.end()) + return; + + BrowserThread::PostTask( + BrowserThread::UI, FROM_HERE, + base::Bind( + &DetachedClientHosts::WorkerReloaded, + it->second, + new_worker_id)); + paused_workers_.erase(it); +} + +void WorkerDevToolsManager::RemoveInspectedWorkerData( + const WorkerId& id) { + for (TerminatedInspectedWorkers::iterator it = terminated_workers_.begin(); + it != terminated_workers_.end(); ++it) { + if (it->old_worker_id == id) { + terminated_workers_.erase(it); + return; + } + } + + for (PausedWorkers::iterator it = paused_workers_.begin(); + it != paused_workers_.end(); ++it) { + if (it->second == id) { + SendResumeToWorker(it->first); + paused_workers_.erase(it); + return; + } + } +} + +WorkerDevToolsManager::InspectedWorkersList::iterator +WorkerDevToolsManager::FindInspectedWorker( + int host_id, int route_id) { + InspectedWorkersList::iterator it = inspected_workers_.begin(); + while (it != inspected_workers_.end()) { + if (it->host->GetData().id == host_id && it->route_id == route_id) + break; + ++it; + } + return it; +} + +static WorkerProcessHost* FindWorkerProcess(int worker_process_id) { + for (WorkerProcessHostIterator iter; !iter.Done(); ++iter) { + if (iter.GetData().id == worker_process_id) + return *iter; + } + return NULL; +} + +void WorkerDevToolsManager::RegisterDevToolsAgentHostForWorker( + int worker_process_id, + int worker_route_id) { + if (WorkerProcessHost* process = FindWorkerProcess(worker_process_id)) { + const WorkerProcessHost::Instances& instances = process->instances(); + for (WorkerProcessHost::Instances::const_iterator i = instances.begin(); + i != instances.end(); ++i) { + if (i->worker_route_id() == worker_route_id) { + DCHECK(FindInspectedWorker(worker_process_id, worker_route_id) == + inspected_workers_.end()); + inspected_workers_.push_back( + InspectedWorker(process, worker_route_id, i->url(), i->name())); + return; + } + } + } + NotifyWorkerDestroyedOnIOThread(worker_process_id, worker_route_id); +} + +void WorkerDevToolsManager::ForwardToDevToolsClient( + int worker_process_id, + int worker_route_id, + const std::string& message) { + if (FindInspectedWorker(worker_process_id, worker_route_id) == + inspected_workers_.end()) { + NOTREACHED(); + return; + } + BrowserThread::PostTask( + BrowserThread::UI, FROM_HERE, + base::Bind( + &ForwardToDevToolsClientOnUIThread, + worker_process_id, + worker_route_id, + message)); +} + +void WorkerDevToolsManager::SaveAgentRuntimeState(int worker_process_id, + int worker_route_id, + const std::string& state) { + BrowserThread::PostTask( + BrowserThread::UI, FROM_HERE, + base::Bind( + &SaveAgentRuntimeStateOnUIThread, + worker_process_id, + worker_route_id, + state)); +} + +void WorkerDevToolsManager::ForwardToWorkerDevToolsAgent( + int worker_process_id, + int worker_route_id, + const IPC::Message& message) { + InspectedWorkersList::iterator it = FindInspectedWorker( + worker_process_id, + worker_route_id); + if (it == inspected_workers_.end()) + return; + IPC::Message* msg = new IPC::Message(message); + msg->set_routing_id(worker_route_id); + it->host->Send(msg); +} + +// static +void WorkerDevToolsManager::ForwardToDevToolsClientOnUIThread( + int worker_process_id, + int worker_route_id, + const std::string& message) { + WorkerDevToolsAgentHost* agent_host = AgentHosts::GetAgentHost(WorkerId( + worker_process_id, + worker_route_id)); + if (!agent_host) + return; + DevToolsManagerImpl::GetInstance()->DispatchOnInspectorFrontend(agent_host, + message); +} + +// static +void WorkerDevToolsManager::SaveAgentRuntimeStateOnUIThread( + int worker_process_id, + int worker_route_id, + const std::string& state) { + WorkerDevToolsAgentHost* agent_host = AgentHosts::GetAgentHost(WorkerId( + worker_process_id, + worker_route_id)); + if (!agent_host) + return; + DevToolsManagerImpl::GetInstance()->SaveAgentRuntimeState(agent_host, state); +} + +// static +void WorkerDevToolsManager::NotifyWorkerDestroyedOnIOThread( + int worker_process_id, + int worker_route_id) { + BrowserThread::PostTask( + BrowserThread::UI, FROM_HERE, + base::Bind( + &WorkerDevToolsManager::NotifyWorkerDestroyedOnUIThread, + worker_process_id, + worker_route_id)); +} + +// static +void WorkerDevToolsManager::NotifyWorkerDestroyedOnUIThread( + int worker_process_id, + int worker_route_id) { + WorkerDevToolsAgentHost* host = + AgentHosts::GetAgentHost(WorkerId(worker_process_id, worker_route_id)); + if (host) + host->WorkerDestroyed(); +} + +// static +void WorkerDevToolsManager::SendResumeToWorker(const WorkerId& id) { + if (WorkerProcessHost* process = FindWorkerProcess(id.first)) + process->Send(new DevToolsAgentMsg_ResumeWorkerContext(id.second)); +} + +} // namespace content diff --git a/content/browser/devtools/worker_devtools_manager.h b/content/browser/devtools/worker_devtools_manager.h new file mode 100644 index 0000000..13ef33b --- /dev/null +++ b/content/browser/devtools/worker_devtools_manager.h @@ -0,0 +1,109 @@ +// Copyright (c) 2012 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 CONTENT_BROWSER_DEVTOOLS_WORKER_DEVTOOLS_MANAGER_H_ +#define CONTENT_BROWSER_DEVTOOLS_WORKER_DEVTOOLS_MANAGER_H_ + +#include +#include +#include + +#include "base/basictypes.h" +#include "base/memory/singleton.h" +#include "content/browser/worker_host/worker_process_host.h" +#include "content/common/content_export.h" + +namespace content { + +class DevToolsAgentHost; + +// All methods are supposed to be called on the IO thread. +class WorkerDevToolsManager { + public: + // Returns the WorkerDevToolsManager singleton. + static WorkerDevToolsManager* GetInstance(); + + // Called on the UI thread. + static DevToolsAgentHost* GetDevToolsAgentHostForWorker( + int worker_process_id, + int worker_route_id); + + void ForwardToDevToolsClient(int worker_process_id, + int worker_route_id, + const std::string& message); + void SaveAgentRuntimeState(int worker_process_id, + int worker_route_id, + const std::string& state); + + // Called on the IO thread. + void WorkerCreated( + WorkerProcessHost* process, + const WorkerProcessHost::WorkerInstance& instance); + void WorkerDestroyed(WorkerProcessHost* process, int worker_route_id); + void WorkerContextStarted(WorkerProcessHost* process, int worker_route_id); + + private: + friend struct DefaultSingletonTraits; + typedef std::pair WorkerId; + class AgentHosts; + class DetachedClientHosts; + class WorkerDevToolsAgentHost; + struct InspectedWorker; + typedef std::list InspectedWorkersList; + + WorkerDevToolsManager(); + virtual ~WorkerDevToolsManager(); + + void RemoveInspectedWorkerData(const WorkerId& id); + InspectedWorkersList::iterator FindInspectedWorker(int host_id, int route_id); + + void RegisterDevToolsAgentHostForWorker(int worker_process_id, + int worker_route_id); + void ForwardToWorkerDevToolsAgent(int worker_process_host_id, + int worker_route_id, + const IPC::Message& message); + static void ForwardToDevToolsClientOnUIThread( + int worker_process_id, + int worker_route_id, + const std::string& message); + static void SaveAgentRuntimeStateOnUIThread( + int worker_process_id, + int worker_route_id, + const std::string& state); + static void NotifyWorkerDestroyedOnIOThread(int worker_process_id, + int worker_route_id); + static void NotifyWorkerDestroyedOnUIThread(int worker_process_id, + int worker_route_id); + static void SendResumeToWorker(const WorkerId& id); + + InspectedWorkersList inspected_workers_; + + struct TerminatedInspectedWorker; + typedef std::list TerminatedInspectedWorkers; + // List of terminated workers for which there may be a devtools client on + // the UI thread. Worker entry is added into this list when inspected worker + // is terminated and will be removed in one of two cases: + // - shared worker with the same URL and name is started(in wich case we will + // try to reattach existing DevTools client to the new worker). + // - DevTools client which was inspecting terminated worker is closed on the + // UI thread and and WorkerDevToolsManager is notified about that on the IO + // thread. + TerminatedInspectedWorkers terminated_workers_; + + typedef std::map PausedWorkers; + // Map from old to new worker id for the inspected workers that have been + // terminated and started again in paused state. Worker data will be removed + // from this list in one of two cases: + // - DevTools client is closed on the UI thread, WorkerDevToolsManager was + // notified about that on the IO thread and sent "resume" message to the + // worker. + // - Existing DevTools client was reattached to the new worker. + PausedWorkers paused_workers_; + + DISALLOW_COPY_AND_ASSIGN(WorkerDevToolsManager); +}; + +} // namespace content + +#endif // CONTENT_BROWSER_DEVTOOLS_WORKER_DEVTOOLS_MANAGER_H_ diff --git a/content/browser/devtools/worker_devtools_message_filter.cc b/content/browser/devtools/worker_devtools_message_filter.cc new file mode 100644 index 0000000..3f5553f1 --- /dev/null +++ b/content/browser/devtools/worker_devtools_message_filter.cc @@ -0,0 +1,50 @@ +// Copyright (c) 2011 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 "content/browser/devtools/worker_devtools_message_filter.h" + +#include "content/browser/devtools/worker_devtools_manager.h" +#include "content/common/devtools_messages.h" +#include "content/common/worker_messages.h" + +namespace content { + +WorkerDevToolsMessageFilter::WorkerDevToolsMessageFilter( + int worker_process_host_id) + : worker_process_host_id_(worker_process_host_id), + current_routing_id_(0) { +} + +WorkerDevToolsMessageFilter::~WorkerDevToolsMessageFilter() { +} + +bool WorkerDevToolsMessageFilter::OnMessageReceived( + const IPC::Message& message, + bool* message_was_ok) { + bool handled = true; + current_routing_id_ = message.routing_id(); + IPC_BEGIN_MESSAGE_MAP_EX(WorkerDevToolsMessageFilter, message, + *message_was_ok) + IPC_MESSAGE_HANDLER(DevToolsClientMsg_DispatchOnInspectorFrontend, + OnDispatchOnInspectorFrontend) + IPC_MESSAGE_HANDLER(DevToolsHostMsg_SaveAgentRuntimeState, + OnSaveAgentRumtimeState) + IPC_MESSAGE_UNHANDLED(handled = false) + IPC_END_MESSAGE_MAP_EX() + return handled; +} + +void WorkerDevToolsMessageFilter::OnDispatchOnInspectorFrontend( + const std::string& message) { + WorkerDevToolsManager::GetInstance()->ForwardToDevToolsClient( + worker_process_host_id_, current_routing_id_, message); +} + +void WorkerDevToolsMessageFilter::OnSaveAgentRumtimeState( + const std::string& state) { + WorkerDevToolsManager::GetInstance()->SaveAgentRuntimeState( + worker_process_host_id_, current_routing_id_, state); +} + +} // namespace content diff --git a/content/browser/devtools/worker_devtools_message_filter.h b/content/browser/devtools/worker_devtools_message_filter.h new file mode 100644 index 0000000..73ba6f84 --- /dev/null +++ b/content/browser/devtools/worker_devtools_message_filter.h @@ -0,0 +1,35 @@ +// Copyright (c) 2012 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 CONTENT_BROWSER_DEVTOOLS_WORKER_DEVTOOLS_MESSAGE_FILTER_H_ +#define CONTENT_BROWSER_DEVTOOLS_WORKER_DEVTOOLS_MESSAGE_FILTER_H_ + +#include "base/callback_forward.h" +#include "content/public/browser/browser_message_filter.h" + +namespace content { + +class WorkerDevToolsMessageFilter : public BrowserMessageFilter { + public: + explicit WorkerDevToolsMessageFilter(int worker_process_host_id); + + private: + virtual ~WorkerDevToolsMessageFilter(); + + // BrowserMessageFilter implementation. + virtual bool OnMessageReceived(const IPC::Message& message, + bool* message_was_ok) OVERRIDE; + // Message handlers. + void OnDispatchOnInspectorFrontend(const std::string& message); + void OnSaveAgentRumtimeState(const std::string& state); + + int worker_process_host_id_; + int current_routing_id_; + + DISALLOW_COPY_AND_ASSIGN(WorkerDevToolsMessageFilter); +}; + +} // namespace content + +#endif // CONTENT_BROWSER_DEVTOOLS_WORKER_DEVTOOLS_MESSAGE_FILTER_H_ diff --git a/content/browser/loader/async_resource_handler.cc b/content/browser/loader/async_resource_handler.cc index c47e46f..eee07f3 100644 --- a/content/browser/loader/async_resource_handler.cc +++ b/content/browser/loader/async_resource_handler.cc @@ -14,7 +14,7 @@ #include "base/metrics/histogram.h" #include "base/shared_memory.h" #include "base/string_number_conversions.h" -#include "content/browser/debugger/devtools_netlog_observer.h" +#include "content/browser/devtools/devtools_netlog_observer.h" #include "content/browser/host_zoom_map_impl.h" #include "content/browser/loader/resource_buffer.h" #include "content/browser/loader/resource_dispatcher_host_impl.h" diff --git a/content/browser/loader/sync_resource_handler.cc b/content/browser/loader/sync_resource_handler.cc index 9f6a60b..390deed 100644 --- a/content/browser/loader/sync_resource_handler.cc +++ b/content/browser/loader/sync_resource_handler.cc @@ -5,7 +5,7 @@ #include "content/browser/loader/sync_resource_handler.h" #include "base/logging.h" -#include "content/browser/debugger/devtools_netlog_observer.h" +#include "content/browser/devtools/devtools_netlog_observer.h" #include "content/browser/loader/resource_dispatcher_host_impl.h" #include "content/browser/loader/resource_message_filter.h" #include "content/common/resource_messages.h" diff --git a/content/browser/web_contents/render_view_host_manager.cc b/content/browser/web_contents/render_view_host_manager.cc index 25a4559..9bfad55 100644 --- a/content/browser/web_contents/render_view_host_manager.cc +++ b/content/browser/web_contents/render_view_host_manager.cc @@ -8,7 +8,7 @@ #include "base/command_line.h" #include "base/logging.h" -#include "content/browser/debugger/devtools_manager_impl.h" +#include "content/browser/devtools/devtools_manager_impl.h" #include "content/browser/renderer_host/render_process_host_impl.h" #include "content/browser/renderer_host/render_view_host_factory.h" #include "content/browser/renderer_host/render_view_host_impl.h" diff --git a/content/browser/web_contents/web_contents_impl.cc b/content/browser/web_contents/web_contents_impl.cc index dfbb76d..d324987 100644 --- a/content/browser/web_contents/web_contents_impl.cc +++ b/content/browser/web_contents/web_contents_impl.cc @@ -19,7 +19,7 @@ #include "content/browser/browser_plugin/browser_plugin_embedder.h" #include "content/browser/browser_plugin/browser_plugin_guest.h" #include "content/browser/child_process_security_policy_impl.h" -#include "content/browser/debugger/devtools_manager_impl.h" +#include "content/browser/devtools/devtools_manager_impl.h" #include "content/browser/dom_storage/dom_storage_context_impl.h" #include "content/browser/dom_storage/session_storage_namespace_impl.h" #include "content/browser/download/download_stats.h" diff --git a/content/browser/worker_host/worker_process_host.cc b/content/browser/worker_host/worker_process_host.cc index 953e868..eaf34fa 100644 --- a/content/browser/worker_host/worker_process_host.cc +++ b/content/browser/worker_host/worker_process_host.cc @@ -20,8 +20,8 @@ #include "content/browser/appcache/chrome_appcache_service.h" #include "content/browser/browser_child_process_host_impl.h" #include "content/browser/child_process_security_policy_impl.h" -#include "content/browser/debugger/worker_devtools_manager.h" -#include "content/browser/debugger/worker_devtools_message_filter.h" +#include "content/browser/devtools/worker_devtools_manager.h" +#include "content/browser/devtools/worker_devtools_message_filter.h" #include "content/browser/fileapi/fileapi_message_filter.h" #include "content/browser/in_process_webkit/indexed_db_dispatcher_host.h" #include "content/browser/mime_registry_message_filter.h" diff --git a/content/browser/worker_host/worker_service_impl.cc b/content/browser/worker_host/worker_service_impl.cc index c19a389..703b31f 100644 --- a/content/browser/worker_host/worker_service_impl.cc +++ b/content/browser/worker_host/worker_service_impl.cc @@ -9,7 +9,7 @@ #include "base/command_line.h" #include "base/logging.h" #include "base/threading/thread.h" -#include "content/browser/debugger/worker_devtools_manager.h" +#include "content/browser/devtools/worker_devtools_manager.h" #include "content/browser/worker_host/worker_message_filter.h" #include "content/browser/worker_host/worker_process_host.h" #include "content/common/view_messages.h" diff --git a/content/content_browser.gypi b/content/content_browser.gypi index 368ba681..2e473e9 100644 --- a/content/content_browser.gypi +++ b/content/content_browser.gypi @@ -284,26 +284,26 @@ 'browser/child_process_security_policy_impl.h', 'browser/cross_site_request_manager.cc', 'browser/cross_site_request_manager.h', - 'browser/debugger/devtools_agent_host.cc', - 'browser/debugger/devtools_agent_host.h', - 'browser/debugger/devtools_browser_target.cc', - 'browser/debugger/devtools_browser_target.h', - 'browser/debugger/devtools_frontend_host.cc', - 'browser/debugger/devtools_frontend_host.h', - 'browser/debugger/devtools_http_handler_impl.cc', - 'browser/debugger/devtools_http_handler_impl.h', - 'browser/debugger/devtools_manager_impl.cc', - 'browser/debugger/devtools_manager_impl.h', - 'browser/debugger/devtools_netlog_observer.cc', - 'browser/debugger/devtools_netlog_observer.h', - 'browser/debugger/devtools_tracing_handler.h', - 'browser/debugger/devtools_tracing_handler.cc', - 'browser/debugger/render_view_devtools_agent_host.cc', - 'browser/debugger/render_view_devtools_agent_host.h', - 'browser/debugger/worker_devtools_manager.cc', - 'browser/debugger/worker_devtools_manager.h', - 'browser/debugger/worker_devtools_message_filter.cc', - 'browser/debugger/worker_devtools_message_filter.h', + 'browser/devtools/devtools_agent_host.cc', + 'browser/devtools/devtools_agent_host.h', + 'browser/devtools/devtools_browser_target.cc', + 'browser/devtools/devtools_browser_target.h', + 'browser/devtools/devtools_frontend_host.cc', + 'browser/devtools/devtools_frontend_host.h', + 'browser/devtools/devtools_http_handler_impl.cc', + 'browser/devtools/devtools_http_handler_impl.h', + 'browser/devtools/devtools_manager_impl.cc', + 'browser/devtools/devtools_manager_impl.h', + 'browser/devtools/devtools_netlog_observer.cc', + 'browser/devtools/devtools_netlog_observer.h', + 'browser/devtools/devtools_tracing_handler.h', + 'browser/devtools/devtools_tracing_handler.cc', + 'browser/devtools/render_view_devtools_agent_host.cc', + 'browser/devtools/render_view_devtools_agent_host.h', + 'browser/devtools/worker_devtools_manager.cc', + 'browser/devtools/worker_devtools_manager.h', + 'browser/devtools/worker_devtools_message_filter.cc', + 'browser/devtools/worker_devtools_message_filter.h', 'browser/device_monitor_linux.cc', 'browser/device_monitor_linux.h', 'browser/device_monitor_mac.h', @@ -939,7 +939,7 @@ ], }, { # OS!="ios" 'dependencies': [ - 'browser/debugger/devtools_resources.gyp:devtools_resources', + 'browser/devtools/devtools_resources.gyp:devtools_resources', '../cc/cc.gyp:cc', '../net/net.gyp:http_server', '../printing/printing.gyp:printing', diff --git a/content/content_renderer.gypi b/content/content_renderer.gypi index 9a3f36f..3c6db0d 100644 --- a/content/content_renderer.gypi +++ b/content/content_renderer.gypi @@ -61,12 +61,12 @@ 'renderer/android/phone_number_detector.h', 'renderer/device_orientation_dispatcher.cc', 'renderer/device_orientation_dispatcher.h', - 'renderer/devtools_agent.cc', - 'renderer/devtools_agent.h', - 'renderer/devtools_agent_filter.cc', - 'renderer/devtools_agent_filter.h', - 'renderer/devtools_client.cc', - 'renderer/devtools_client.h', + 'renderer/devtools/devtools_agent.cc', + 'renderer/devtools/devtools_agent.h', + 'renderer/devtools/devtools_agent_filter.cc', + 'renderer/devtools/devtools_agent_filter.h', + 'renderer/devtools/devtools_client.cc', + 'renderer/devtools/devtools_client.h', 'renderer/disambiguation_popup_helper.cc', 'renderer/disambiguation_popup_helper.h', 'renderer/do_not_track_bindings.cc', diff --git a/content/content_shell.gypi b/content/content_shell.gypi index 197ecf0..7153cc8 100644 --- a/content/content_shell.gypi +++ b/content/content_shell.gypi @@ -246,7 +246,7 @@ 'target_name': 'content_shell_pak', 'type': 'none', 'dependencies': [ - 'browser/debugger/devtools_resources.gyp:devtools_resources', + 'browser/devtools/devtools_resources.gyp:devtools_resources', 'content_shell_resources', '<(DEPTH)/ui/ui.gyp:ui_resources', ], diff --git a/content/content_tests.gypi b/content/content_tests.gypi index c46ae02..92dcfa5 100644 --- a/content/content_tests.gypi +++ b/content/content_tests.gypi @@ -258,8 +258,8 @@ 'browser/browser_thread_unittest.cc', 'browser/browser_url_handler_impl_unittest.cc', 'browser/child_process_security_policy_unittest.cc', - 'browser/debugger/devtools_http_handler_unittest.cc', - 'browser/debugger/devtools_manager_unittest.cc', + 'browser/devtools/devtools_http_handler_unittest.cc', + 'browser/devtools/devtools_manager_unittest.cc', 'browser/device_orientation/provider_unittest.cc', 'browser/download/base_file_unittest.cc', 'browser/download/byte_stream_unittest.cc', diff --git a/content/renderer/devtools/OWNERS b/content/renderer/devtools/OWNERS new file mode 100644 index 0000000..bb6028e --- /dev/null +++ b/content/renderer/devtools/OWNERS @@ -0,0 +1,2 @@ +pfeldman@chromium.org +yurys@chromium.org diff --git a/content/renderer/devtools/devtools_agent.cc b/content/renderer/devtools/devtools_agent.cc new file mode 100644 index 0000000..31269b0 --- /dev/null +++ b/content/renderer/devtools/devtools_agent.cc @@ -0,0 +1,245 @@ +// Copyright (c) 2012 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 "content/renderer/devtools/devtools_agent.h" + +#include + +#include "base/lazy_instance.h" +#include "base/message_loop.h" +#include "base/process.h" +#include "base/string_number_conversions.h" +#include "content/common/devtools_messages.h" +#include "content/common/view_messages.h" +#include "content/renderer/devtools/devtools_agent_filter.h" +#include "content/renderer/devtools/devtools_client.h" +#include "content/renderer/render_view_impl.h" +#include "third_party/WebKit/Source/WebKit/chromium/public/WebConsoleMessage.h" +#include "third_party/WebKit/Source/WebKit/chromium/public/WebConsoleMessage.h" +#include "third_party/WebKit/Source/WebKit/chromium/public/WebDevToolsAgent.h" +#include "third_party/WebKit/Source/WebKit/chromium/public/WebFrame.h" +#include "third_party/WebKit/Source/WebKit/chromium/public/WebView.h" +#include "third_party/WebKit/Source/WebKit/chromium/public/platform/WebPoint.h" +#include "third_party/WebKit/Source/WebKit/chromium/public/platform/WebString.h" + +#if defined(USE_TCMALLOC) +#include "third_party/tcmalloc/chromium/src/gperftools/heap-profiler.h" +#endif + +using WebKit::WebConsoleMessage; +using WebKit::WebDevToolsAgent; +using WebKit::WebDevToolsAgentClient; +using WebKit::WebFrame; +using WebKit::WebPoint; +using WebKit::WebString; +using WebKit::WebCString; +using WebKit::WebVector; +using WebKit::WebView; + +namespace content { + +namespace { + +class WebKitClientMessageLoopImpl + : public WebDevToolsAgentClient::WebKitClientMessageLoop { + public: + WebKitClientMessageLoopImpl() : message_loop_(MessageLoop::current()) { } + virtual ~WebKitClientMessageLoopImpl() { + message_loop_ = NULL; + } + virtual void run() { + MessageLoop::ScopedNestableTaskAllower allow(message_loop_); + message_loop_->Run(); + } + virtual void quitNow() { + message_loop_->QuitNow(); + } + private: + MessageLoop* message_loop_; +}; + +typedef std::map IdToAgentMap; +base::LazyInstance::Leaky + g_agent_for_routing_id = LAZY_INSTANCE_INITIALIZER; + +} // namespace + +DevToolsAgent::DevToolsAgent(RenderViewImpl* render_view) + : RenderViewObserver(render_view), is_attached_(false) { + g_agent_for_routing_id.Get()[routing_id()] = this; + + render_view->webview()->setDevToolsAgentClient(this); + render_view->webview()->devToolsAgent()->setProcessId( + base::Process::Current().pid()); +} + +DevToolsAgent::~DevToolsAgent() { + g_agent_for_routing_id.Get().erase(routing_id()); +} + +// Called on the Renderer thread. +bool DevToolsAgent::OnMessageReceived(const IPC::Message& message) { + bool handled = true; + IPC_BEGIN_MESSAGE_MAP(DevToolsAgent, message) + IPC_MESSAGE_HANDLER(DevToolsAgentMsg_Attach, OnAttach) + IPC_MESSAGE_HANDLER(DevToolsAgentMsg_Reattach, OnReattach) + IPC_MESSAGE_HANDLER(DevToolsAgentMsg_Detach, OnDetach) + IPC_MESSAGE_HANDLER(DevToolsAgentMsg_DispatchOnInspectorBackend, + OnDispatchOnInspectorBackend) + IPC_MESSAGE_HANDLER(DevToolsAgentMsg_InspectElement, OnInspectElement) + IPC_MESSAGE_HANDLER(DevToolsAgentMsg_AddMessageToConsole, + OnAddMessageToConsole) + IPC_MESSAGE_HANDLER(DevToolsMsg_SetupDevToolsClient, OnSetupDevToolsClient) + IPC_MESSAGE_UNHANDLED(handled = false) + IPC_END_MESSAGE_MAP() + + if (message.type() == ViewMsg_Navigate::ID || + message.type() == ViewMsg_Close::ID) + ContinueProgram(); // Don't want to swallow the message. + + return handled; +} + +void DevToolsAgent::sendMessageToInspectorFrontend( + const WebKit::WebString& message) { + Send(new DevToolsClientMsg_DispatchOnInspectorFrontend(routing_id(), + message.utf8())); +} + +int DevToolsAgent::hostIdentifier() { + return routing_id(); +} + +void DevToolsAgent::saveAgentRuntimeState( + const WebKit::WebString& state) { + Send(new DevToolsHostMsg_SaveAgentRuntimeState(routing_id(), state.utf8())); +} + +WebKit::WebDevToolsAgentClient::WebKitClientMessageLoop* + DevToolsAgent::createClientMessageLoop() { + return new WebKitClientMessageLoopImpl(); +} + +void DevToolsAgent::clearBrowserCache() { + Send(new DevToolsHostMsg_ClearBrowserCache(routing_id())); +} + +void DevToolsAgent::clearBrowserCookies() { + Send(new DevToolsHostMsg_ClearBrowserCookies(routing_id())); +} + +#if defined(USE_TCMALLOC) && !defined(OS_WIN) +static void AllocationVisitor(void* data, const void* ptr) { + typedef WebKit::WebDevToolsAgentClient::AllocatedObjectVisitor Visitor; + Visitor* visitor = reinterpret_cast(data); + visitor->visitObject(ptr); +} +#endif + +void DevToolsAgent::visitAllocatedObjects(AllocatedObjectVisitor* visitor) { +#if defined(USE_TCMALLOC) && !defined(OS_WIN) + IterateAllocatedObjects(&AllocationVisitor, visitor); +#endif +} + +// static +DevToolsAgent* DevToolsAgent::FromHostId(int host_id) { + IdToAgentMap::iterator it = g_agent_for_routing_id.Get().find(host_id); + if (it != g_agent_for_routing_id.Get().end()) { + return it->second; + } + return NULL; +} + +void DevToolsAgent::OnAttach() { + WebDevToolsAgent* web_agent = GetWebAgent(); + if (web_agent) { + web_agent->attach(); + is_attached_ = true; + } +} + +void DevToolsAgent::OnReattach(const std::string& agent_state) { + WebDevToolsAgent* web_agent = GetWebAgent(); + if (web_agent) { + web_agent->reattach(WebString::fromUTF8(agent_state)); + is_attached_ = true; + } +} + +void DevToolsAgent::OnDetach() { + WebDevToolsAgent* web_agent = GetWebAgent(); + if (web_agent) { + web_agent->detach(); + is_attached_ = false; + } +} + +void DevToolsAgent::OnDispatchOnInspectorBackend(const std::string& message) { + WebDevToolsAgent* web_agent = GetWebAgent(); + if (web_agent) + web_agent->dispatchOnInspectorBackend(WebString::fromUTF8(message)); +} + +void DevToolsAgent::OnInspectElement(int x, int y) { + WebDevToolsAgent* web_agent = GetWebAgent(); + if (web_agent) { + web_agent->attach(); + web_agent->inspectElementAt(WebPoint(x, y)); + } +} + +void DevToolsAgent::OnAddMessageToConsole(ConsoleMessageLevel level, + const std::string& message) { + WebView* web_view = render_view()->GetWebView(); + if (!web_view) + return; + + WebFrame* main_frame = web_view-> mainFrame(); + if (!main_frame) + return; + + WebConsoleMessage::Level target_level = WebConsoleMessage::LevelLog; + switch (level) { + case CONSOLE_MESSAGE_LEVEL_TIP: + target_level = WebConsoleMessage::LevelTip; + break; + case CONSOLE_MESSAGE_LEVEL_LOG: + target_level = WebConsoleMessage::LevelLog; + break; + case CONSOLE_MESSAGE_LEVEL_WARNING: + target_level = WebConsoleMessage::LevelWarning; + break; + case CONSOLE_MESSAGE_LEVEL_ERROR: + target_level = WebConsoleMessage::LevelError; + break; + } + main_frame->addMessageToConsole( + WebConsoleMessage(target_level, WebString::fromUTF8(message))); +} + +void DevToolsAgent::ContinueProgram() { + WebDevToolsAgent* web_agent = GetWebAgent(); + // TODO(pfeldman): rename didNavigate to continueProgram upstream. + // That is in fact the purpose of the signal. + if (web_agent) + web_agent->didNavigate(); +} + +void DevToolsAgent::OnSetupDevToolsClient() { + new DevToolsClient(static_cast(render_view())); +} + +WebDevToolsAgent* DevToolsAgent::GetWebAgent() { + WebView* web_view = render_view()->GetWebView(); + if (!web_view) + return NULL; + return web_view->devToolsAgent(); +} + +bool DevToolsAgent::IsAttached() { + return is_attached_; +} + +} // namespace content diff --git a/content/renderer/devtools/devtools_agent.h b/content/renderer/devtools/devtools_agent.h new file mode 100644 index 0000000..9efe05ee --- /dev/null +++ b/content/renderer/devtools/devtools_agent.h @@ -0,0 +1,73 @@ +// Copyright (c) 2012 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 CONTENT_RENDERER_DEVTOOLS_DEVTOOLS_AGENT_H_ +#define CONTENT_RENDERER_DEVTOOLS_DEVTOOLS_AGENT_H_ + +#include + +#include "base/basictypes.h" +#include "content/public/common/console_message_level.h" +#include "content/public/renderer/render_view_observer.h" +#include "third_party/WebKit/Source/WebKit/chromium/public/WebDevToolsAgentClient.h" + +namespace WebKit { +class WebDevToolsAgent; +} + +namespace content { +class RenderViewImpl; + +// DevToolsAgent belongs to the inspectable RenderView and provides Glue's +// agents with the communication capabilities. All messages from/to Glue's +// agents infrastructure are flowing through this communication agent. +// There is a corresponding DevToolsClient object on the client side. +class DevToolsAgent : public RenderViewObserver, + public WebKit::WebDevToolsAgentClient { + public: + explicit DevToolsAgent(RenderViewImpl* render_view); + virtual ~DevToolsAgent(); + + // Returns agent instance for its host id. + static DevToolsAgent* FromHostId(int host_id); + + WebKit::WebDevToolsAgent* GetWebAgent(); + + bool IsAttached(); + + private: + friend class DevToolsAgentFilter; + + // RenderView::Observer implementation. + virtual bool OnMessageReceived(const IPC::Message& message) OVERRIDE; + + // WebDevToolsAgentClient implementation + virtual void sendMessageToInspectorFrontend(const WebKit::WebString& data); + + virtual int hostIdentifier(); + virtual void saveAgentRuntimeState(const WebKit::WebString& state); + virtual WebKit::WebDevToolsAgentClient::WebKitClientMessageLoop* + createClientMessageLoop(); + virtual void clearBrowserCache(); + virtual void clearBrowserCookies(); + virtual void visitAllocatedObjects(AllocatedObjectVisitor* visitor); + + void OnAttach(); + void OnReattach(const std::string& agent_state); + void OnDetach(); + void OnDispatchOnInspectorBackend(const std::string& message); + void OnInspectElement(int x, int y); + void OnAddMessageToConsole(ConsoleMessageLevel level, + const std::string& message); + void ContinueProgram(); + void OnSetupDevToolsClient(); + + bool is_attached_; + + DISALLOW_COPY_AND_ASSIGN(DevToolsAgent); +}; + +} // namespace content + +#endif // CONTENT_RENDERER_DEVTOOLS_DEVTOOLS_AGENT_H_ diff --git a/content/renderer/devtools/devtools_agent_filter.cc b/content/renderer/devtools/devtools_agent_filter.cc new file mode 100644 index 0000000..4aca9ac --- /dev/null +++ b/content/renderer/devtools/devtools_agent_filter.cc @@ -0,0 +1,77 @@ +// Copyright (c) 2012 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 "content/renderer/devtools/devtools_agent_filter.h" + +#include "base/bind.h" +#include "base/message_loop.h" +#include "content/common/devtools_messages.h" +#include "content/renderer/devtools/devtools_agent.h" +#include "content/renderer/plugin_channel_host.h" +#include "third_party/WebKit/Source/WebKit/chromium/public/WebDevToolsAgent.h" +#include "third_party/WebKit/Source/WebKit/chromium/public/platform/WebString.h" + +using WebKit::WebDevToolsAgent; +using WebKit::WebString; + +namespace content { + +namespace { + +class MessageImpl : public WebDevToolsAgent::MessageDescriptor { + public: + MessageImpl(const std::string& message, int host_id) + : msg(message), + host_id(host_id) { + } + virtual ~MessageImpl() {} + virtual WebDevToolsAgent* agent() { + DevToolsAgent* agent = DevToolsAgent::FromHostId(host_id); + if (!agent) + return 0; + return agent->GetWebAgent(); + } + virtual WebString message() { return WebString::fromUTF8(msg); } + private: + std::string msg; + int host_id; +}; + +} // namespace + +DevToolsAgentFilter::DevToolsAgentFilter() + : message_handled_(false), + render_thread_loop_(MessageLoop::current()), + current_routing_id_(0) { +} + +bool DevToolsAgentFilter::OnMessageReceived(const IPC::Message& message) { + // Dispatch debugger commands directly from IO. + message_handled_ = true; + current_routing_id_ = message.routing_id(); + IPC_BEGIN_MESSAGE_MAP(DevToolsAgentFilter, message) + IPC_MESSAGE_HANDLER(DevToolsAgentMsg_DispatchOnInspectorBackend, + OnDispatchOnInspectorBackend) + IPC_MESSAGE_UNHANDLED(message_handled_ = false) + IPC_END_MESSAGE_MAP() + return message_handled_; +} + +DevToolsAgentFilter::~DevToolsAgentFilter() {} + +void DevToolsAgentFilter::OnDispatchOnInspectorBackend( + const std::string& message) { + if (!WebDevToolsAgent::shouldInterruptForMessage( + WebString::fromUTF8(message))) { + message_handled_ = false; + return; + } + WebDevToolsAgent::interruptAndDispatch( + new MessageImpl(message, current_routing_id_)); + + render_thread_loop_->PostTask( + FROM_HERE, base::Bind(&WebDevToolsAgent::processPendingMessages)); +} + +} // namespace content diff --git a/content/renderer/devtools/devtools_agent_filter.h b/content/renderer/devtools/devtools_agent_filter.h new file mode 100644 index 0000000..9e4f8ae --- /dev/null +++ b/content/renderer/devtools/devtools_agent_filter.h @@ -0,0 +1,48 @@ +// Copyright (c) 2012 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 CONTENT_RENDERER_DEVTOOLS_DEVTOOLS_AGENT_FILTER_H_ +#define CONTENT_RENDERER_DEVTOOLS_DEVTOOLS_AGENT_FILTER_H_ + +#include + +#include "ipc/ipc_channel_proxy.h" + +class MessageLoop; +struct DevToolsMessageData; + +namespace content { + +// DevToolsAgentFilter is registered as an IPC filter in order to be able to +// dispatch messages while on the IO thread. The reason for that is that while +// debugging, Render thread is being held by the v8 and hence no messages +// are being dispatched there. While holding the thread in a tight loop, +// v8 provides thread-safe Api for controlling debugger. In our case v8's Api +// is being used from this communication agent on the IO thread. +class DevToolsAgentFilter : public IPC::ChannelProxy::MessageFilter { + public: + // There is a single instance of this class instantiated by the RenderThread. + DevToolsAgentFilter(); + + static void SendRpcMessage(const DevToolsMessageData& data); + + // IPC::ChannelProxy::MessageFilter override. Called on IO thread. + virtual bool OnMessageReceived(const IPC::Message& message) OVERRIDE; + + protected: + virtual ~DevToolsAgentFilter(); + + private: + void OnDispatchOnInspectorBackend(const std::string& message); + + bool message_handled_; + MessageLoop* render_thread_loop_; + int current_routing_id_; + + DISALLOW_COPY_AND_ASSIGN(DevToolsAgentFilter); +}; + +} // namespace content + +#endif // CONTENT_RENDERER_DEVTOOLS_DEVTOOLS_AGENT_FILTER_H_ diff --git a/content/renderer/devtools/devtools_client.cc b/content/renderer/devtools/devtools_client.cc new file mode 100644 index 0000000..09ec506 --- /dev/null +++ b/content/renderer/devtools/devtools_client.cc @@ -0,0 +1,97 @@ +// Copyright (c) 2012 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 "content/renderer/devtools/devtools_client.h" + +#include "base/command_line.h" +#include "base/message_loop.h" +#include "base/utf_string_conversions.h" +#include "content/common/devtools_messages.h" +#include "content/public/common/content_switches.h" +#include "content/renderer/render_thread_impl.h" +#include "content/renderer/render_view_impl.h" +#include "third_party/WebKit/Source/WebKit/chromium/public/WebDevToolsFrontend.h" +#include "third_party/WebKit/Source/WebKit/chromium/public/platform/WebFloatPoint.h" +#include "third_party/WebKit/Source/WebKit/chromium/public/platform/WebString.h" +#include "ui/base/ui_base_switches.h" + +using WebKit::WebDevToolsFrontend; +using WebKit::WebString; + +namespace content { + +DevToolsClient::DevToolsClient(RenderViewImpl* render_view) + : RenderViewObserver(render_view) { + const CommandLine& command_line = *CommandLine::ForCurrentProcess(); + web_tools_frontend_.reset( + WebDevToolsFrontend::create( + render_view->webview(), + this, + ASCIIToUTF16(command_line.GetSwitchValueASCII(switches::kLang)))); +} + +DevToolsClient::~DevToolsClient() { +} + +bool DevToolsClient::OnMessageReceived(const IPC::Message& message) { + DCHECK(RenderThreadImpl::current()); + + bool handled = true; + IPC_BEGIN_MESSAGE_MAP(DevToolsClient, message) + IPC_MESSAGE_HANDLER(DevToolsClientMsg_DispatchOnInspectorFrontend, + OnDispatchOnInspectorFrontend) + IPC_MESSAGE_UNHANDLED(handled = false); + IPC_END_MESSAGE_MAP() + + return handled; +} + +void DevToolsClient::sendMessageToBackend(const WebString& message) { + Send(new DevToolsAgentMsg_DispatchOnInspectorBackend(routing_id(), + message.utf8())); +} + +void DevToolsClient::activateWindow() { + Send(new DevToolsHostMsg_ActivateWindow(routing_id())); +} + +void DevToolsClient::closeWindow() { + Send(new DevToolsHostMsg_CloseWindow(routing_id())); +} + +void DevToolsClient::moveWindowBy(const WebKit::WebFloatPoint& offset) { + Send(new DevToolsHostMsg_MoveWindow(routing_id(), offset.x, offset.y)); +} + +void DevToolsClient::requestSetDockSide(const WebKit::WebString& side) { + Send(new DevToolsHostMsg_RequestSetDockSide(routing_id(), side.utf8())); +} + +void DevToolsClient::openInNewTab(const WebKit::WebString& url) { + Send(new DevToolsHostMsg_OpenInNewTab(routing_id(), + url.utf8())); +} + +void DevToolsClient::save(const WebKit::WebString& url, + const WebKit::WebString& content, + bool save_as) { + Send(new DevToolsHostMsg_Save(routing_id(), + url.utf8(), + content.utf8(), + save_as)); +} + +void DevToolsClient::append(const WebKit::WebString& url, + const WebKit::WebString& content) { + Send(new DevToolsHostMsg_Append(routing_id(), + url.utf8(), + content.utf8())); +} + +void DevToolsClient::OnDispatchOnInspectorFrontend(const std::string& message) { + web_tools_frontend_->dispatchOnInspectorFrontend( + WebString::fromUTF8(message)); +} + +} // namespace content diff --git a/content/renderer/devtools/devtools_client.h b/content/renderer/devtools/devtools_client.h new file mode 100644 index 0000000..f5fa8f0 --- /dev/null +++ b/content/renderer/devtools/devtools_client.h @@ -0,0 +1,63 @@ +// Copyright (c) 2012 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 CONTENT_RENDERER_DEVTOOLS_DEVTOOLS_CLIENT_H_ +#define CONTENT_RENDERER_DEVTOOLS_DEVTOOLS_CLIENT_H_ + +#include + +#include "base/basictypes.h" +#include "base/memory/scoped_ptr.h" +#include "content/public/renderer/render_view_observer.h" +#include "third_party/WebKit/Source/WebKit/chromium/public/WebDevToolsFrontendClient.h" + +namespace WebKit { +class WebDevToolsFrontend; +class WebString; +} + +namespace content { + +class RenderViewImpl; + +// Developer tools UI end of communication channel between the render process of +// the page being inspected and tools UI renderer process. All messages will +// go through browser process. On the side of the inspected page there's +// corresponding DevToolsAgent object. +// TODO(yurys): now the client is almost empty later it will delegate calls to +// code in glue +class DevToolsClient : public RenderViewObserver, + public WebKit::WebDevToolsFrontendClient { + public: + explicit DevToolsClient(RenderViewImpl* render_view); + virtual ~DevToolsClient(); + + private: + // RenderView::Observer implementation. + virtual bool OnMessageReceived(const IPC::Message& message) OVERRIDE; + + // WebDevToolsFrontendClient implementation. + virtual void sendMessageToBackend(const WebKit::WebString&) OVERRIDE; + + virtual void activateWindow() OVERRIDE; + virtual void closeWindow() OVERRIDE; + virtual void moveWindowBy(const WebKit::WebFloatPoint& offset) OVERRIDE; + virtual void requestSetDockSide(const WebKit::WebString& side) OVERRIDE; + virtual void openInNewTab(const WebKit::WebString& side) OVERRIDE; + virtual void save(const WebKit::WebString& url, + const WebKit::WebString& content, + bool save_as) OVERRIDE; + virtual void append(const WebKit::WebString& url, + const WebKit::WebString& content) OVERRIDE; + + void OnDispatchOnInspectorFrontend(const std::string& message); + + scoped_ptr web_tools_frontend_; + + DISALLOW_COPY_AND_ASSIGN(DevToolsClient); +}; + +} // namespace content + +#endif // CONTENT_RENDERER_DEVTOOLS_DEVTOOLS_CLIENT_H_ diff --git a/content/renderer/devtools_agent.cc b/content/renderer/devtools_agent.cc deleted file mode 100644 index 91fc3b3..0000000 --- a/content/renderer/devtools_agent.cc +++ /dev/null @@ -1,245 +0,0 @@ -// Copyright (c) 2012 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 "content/renderer/devtools_agent.h" - -#include - -#include "base/lazy_instance.h" -#include "base/message_loop.h" -#include "base/process.h" -#include "base/string_number_conversions.h" -#include "content/common/devtools_messages.h" -#include "content/common/view_messages.h" -#include "content/renderer/devtools_agent_filter.h" -#include "content/renderer/devtools_client.h" -#include "content/renderer/render_view_impl.h" -#include "third_party/WebKit/Source/WebKit/chromium/public/WebConsoleMessage.h" -#include "third_party/WebKit/Source/WebKit/chromium/public/WebDevToolsAgent.h" -#include "third_party/WebKit/Source/WebKit/chromium/public/platform/WebPoint.h" -#include "third_party/WebKit/Source/WebKit/chromium/public/platform/WebString.h" -#include "third_party/WebKit/Source/WebKit/chromium/public/WebConsoleMessage.h" -#include "third_party/WebKit/Source/WebKit/chromium/public/WebFrame.h" -#include "third_party/WebKit/Source/WebKit/chromium/public/WebView.h" - -#if defined(USE_TCMALLOC) -#include "third_party/tcmalloc/chromium/src/gperftools/heap-profiler.h" -#endif - -using WebKit::WebConsoleMessage; -using WebKit::WebDevToolsAgent; -using WebKit::WebDevToolsAgentClient; -using WebKit::WebFrame; -using WebKit::WebPoint; -using WebKit::WebString; -using WebKit::WebCString; -using WebKit::WebVector; -using WebKit::WebView; - -namespace content { - -namespace { - -class WebKitClientMessageLoopImpl - : public WebDevToolsAgentClient::WebKitClientMessageLoop { - public: - WebKitClientMessageLoopImpl() : message_loop_(MessageLoop::current()) { } - virtual ~WebKitClientMessageLoopImpl() { - message_loop_ = NULL; - } - virtual void run() { - MessageLoop::ScopedNestableTaskAllower allow(message_loop_); - message_loop_->Run(); - } - virtual void quitNow() { - message_loop_->QuitNow(); - } - private: - MessageLoop* message_loop_; -}; - -typedef std::map IdToAgentMap; -base::LazyInstance::Leaky - g_agent_for_routing_id = LAZY_INSTANCE_INITIALIZER; - -} // namespace - -DevToolsAgent::DevToolsAgent(RenderViewImpl* render_view) - : RenderViewObserver(render_view), is_attached_(false) { - g_agent_for_routing_id.Get()[routing_id()] = this; - - render_view->webview()->setDevToolsAgentClient(this); - render_view->webview()->devToolsAgent()->setProcessId( - base::Process::Current().pid()); -} - -DevToolsAgent::~DevToolsAgent() { - g_agent_for_routing_id.Get().erase(routing_id()); -} - -// Called on the Renderer thread. -bool DevToolsAgent::OnMessageReceived(const IPC::Message& message) { - bool handled = true; - IPC_BEGIN_MESSAGE_MAP(DevToolsAgent, message) - IPC_MESSAGE_HANDLER(DevToolsAgentMsg_Attach, OnAttach) - IPC_MESSAGE_HANDLER(DevToolsAgentMsg_Reattach, OnReattach) - IPC_MESSAGE_HANDLER(DevToolsAgentMsg_Detach, OnDetach) - IPC_MESSAGE_HANDLER(DevToolsAgentMsg_DispatchOnInspectorBackend, - OnDispatchOnInspectorBackend) - IPC_MESSAGE_HANDLER(DevToolsAgentMsg_InspectElement, OnInspectElement) - IPC_MESSAGE_HANDLER(DevToolsAgentMsg_AddMessageToConsole, - OnAddMessageToConsole) - IPC_MESSAGE_HANDLER(DevToolsMsg_SetupDevToolsClient, OnSetupDevToolsClient) - IPC_MESSAGE_UNHANDLED(handled = false) - IPC_END_MESSAGE_MAP() - - if (message.type() == ViewMsg_Navigate::ID || - message.type() == ViewMsg_Close::ID) - ContinueProgram(); // Don't want to swallow the message. - - return handled; -} - -void DevToolsAgent::sendMessageToInspectorFrontend( - const WebKit::WebString& message) { - Send(new DevToolsClientMsg_DispatchOnInspectorFrontend(routing_id(), - message.utf8())); -} - -int DevToolsAgent::hostIdentifier() { - return routing_id(); -} - -void DevToolsAgent::saveAgentRuntimeState( - const WebKit::WebString& state) { - Send(new DevToolsHostMsg_SaveAgentRuntimeState(routing_id(), state.utf8())); -} - -WebKit::WebDevToolsAgentClient::WebKitClientMessageLoop* - DevToolsAgent::createClientMessageLoop() { - return new WebKitClientMessageLoopImpl(); -} - -void DevToolsAgent::clearBrowserCache() { - Send(new DevToolsHostMsg_ClearBrowserCache(routing_id())); -} - -void DevToolsAgent::clearBrowserCookies() { - Send(new DevToolsHostMsg_ClearBrowserCookies(routing_id())); -} - -#if defined(USE_TCMALLOC) && !defined(OS_WIN) -static void AllocationVisitor(void* data, const void* ptr) { - typedef WebKit::WebDevToolsAgentClient::AllocatedObjectVisitor Visitor; - Visitor* visitor = reinterpret_cast(data); - visitor->visitObject(ptr); -} -#endif - -void DevToolsAgent::visitAllocatedObjects(AllocatedObjectVisitor* visitor) { -#if defined(USE_TCMALLOC) && !defined(OS_WIN) - IterateAllocatedObjects(&AllocationVisitor, visitor); -#endif -} - -// static -DevToolsAgent* DevToolsAgent::FromHostId(int host_id) { - IdToAgentMap::iterator it = g_agent_for_routing_id.Get().find(host_id); - if (it != g_agent_for_routing_id.Get().end()) { - return it->second; - } - return NULL; -} - -void DevToolsAgent::OnAttach() { - WebDevToolsAgent* web_agent = GetWebAgent(); - if (web_agent) { - web_agent->attach(); - is_attached_ = true; - } -} - -void DevToolsAgent::OnReattach(const std::string& agent_state) { - WebDevToolsAgent* web_agent = GetWebAgent(); - if (web_agent) { - web_agent->reattach(WebString::fromUTF8(agent_state)); - is_attached_ = true; - } -} - -void DevToolsAgent::OnDetach() { - WebDevToolsAgent* web_agent = GetWebAgent(); - if (web_agent) { - web_agent->detach(); - is_attached_ = false; - } -} - -void DevToolsAgent::OnDispatchOnInspectorBackend(const std::string& message) { - WebDevToolsAgent* web_agent = GetWebAgent(); - if (web_agent) - web_agent->dispatchOnInspectorBackend(WebString::fromUTF8(message)); -} - -void DevToolsAgent::OnInspectElement(int x, int y) { - WebDevToolsAgent* web_agent = GetWebAgent(); - if (web_agent) { - web_agent->attach(); - web_agent->inspectElementAt(WebPoint(x, y)); - } -} - -void DevToolsAgent::OnAddMessageToConsole(ConsoleMessageLevel level, - const std::string& message) { - WebView* web_view = render_view()->GetWebView(); - if (!web_view) - return; - - WebFrame* main_frame = web_view-> mainFrame(); - if (!main_frame) - return; - - WebConsoleMessage::Level target_level = WebConsoleMessage::LevelLog; - switch (level) { - case CONSOLE_MESSAGE_LEVEL_TIP: - target_level = WebConsoleMessage::LevelTip; - break; - case CONSOLE_MESSAGE_LEVEL_LOG: - target_level = WebConsoleMessage::LevelLog; - break; - case CONSOLE_MESSAGE_LEVEL_WARNING: - target_level = WebConsoleMessage::LevelWarning; - break; - case CONSOLE_MESSAGE_LEVEL_ERROR: - target_level = WebConsoleMessage::LevelError; - break; - } - main_frame->addMessageToConsole( - WebConsoleMessage(target_level, WebString::fromUTF8(message))); -} - -void DevToolsAgent::ContinueProgram() { - WebDevToolsAgent* web_agent = GetWebAgent(); - // TODO(pfeldman): rename didNavigate to continueProgram upstream. - // That is in fact the purpose of the signal. - if (web_agent) - web_agent->didNavigate(); -} - -void DevToolsAgent::OnSetupDevToolsClient() { - new DevToolsClient(static_cast(render_view())); -} - -WebDevToolsAgent* DevToolsAgent::GetWebAgent() { - WebView* web_view = render_view()->GetWebView(); - if (!web_view) - return NULL; - return web_view->devToolsAgent(); -} - -bool DevToolsAgent::IsAttached() { - return is_attached_; -} - -} // namespace content diff --git a/content/renderer/devtools_agent.h b/content/renderer/devtools_agent.h deleted file mode 100644 index 219a767..0000000 --- a/content/renderer/devtools_agent.h +++ /dev/null @@ -1,73 +0,0 @@ -// Copyright (c) 2012 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 CONTENT_RENDERER_DEVTOOLS_AGENT_H_ -#define CONTENT_RENDERER_DEVTOOLS_AGENT_H_ - -#include - -#include "base/basictypes.h" -#include "content/public/common/console_message_level.h" -#include "content/public/renderer/render_view_observer.h" -#include "third_party/WebKit/Source/WebKit/chromium/public/WebDevToolsAgentClient.h" - -namespace WebKit { -class WebDevToolsAgent; -} - -namespace content { -class RenderViewImpl; - -// DevToolsAgent belongs to the inspectable RenderView and provides Glue's -// agents with the communication capabilities. All messages from/to Glue's -// agents infrastructure are flowing through this communication agent. -// There is a corresponding DevToolsClient object on the client side. -class DevToolsAgent : public RenderViewObserver, - public WebKit::WebDevToolsAgentClient { - public: - explicit DevToolsAgent(RenderViewImpl* render_view); - virtual ~DevToolsAgent(); - - // Returns agent instance for its host id. - static DevToolsAgent* FromHostId(int host_id); - - WebKit::WebDevToolsAgent* GetWebAgent(); - - bool IsAttached(); - - private: - friend class DevToolsAgentFilter; - - // RenderView::Observer implementation. - virtual bool OnMessageReceived(const IPC::Message& message) OVERRIDE; - - // WebDevToolsAgentClient implementation - virtual void sendMessageToInspectorFrontend(const WebKit::WebString& data); - - virtual int hostIdentifier(); - virtual void saveAgentRuntimeState(const WebKit::WebString& state); - virtual WebKit::WebDevToolsAgentClient::WebKitClientMessageLoop* - createClientMessageLoop(); - virtual void clearBrowserCache(); - virtual void clearBrowserCookies(); - virtual void visitAllocatedObjects(AllocatedObjectVisitor* visitor); - - void OnAttach(); - void OnReattach(const std::string& agent_state); - void OnDetach(); - void OnDispatchOnInspectorBackend(const std::string& message); - void OnInspectElement(int x, int y); - void OnAddMessageToConsole(ConsoleMessageLevel level, - const std::string& message); - void ContinueProgram(); - void OnSetupDevToolsClient(); - - bool is_attached_; - - DISALLOW_COPY_AND_ASSIGN(DevToolsAgent); -}; - -} // namespace content - -#endif // CONTENT_RENDERER_DEVTOOLS_AGENT_H_ diff --git a/content/renderer/devtools_agent_filter.cc b/content/renderer/devtools_agent_filter.cc deleted file mode 100644 index f640c59..0000000 --- a/content/renderer/devtools_agent_filter.cc +++ /dev/null @@ -1,77 +0,0 @@ -// Copyright (c) 2012 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 "content/renderer/devtools_agent_filter.h" - -#include "base/bind.h" -#include "base/message_loop.h" -#include "content/common/devtools_messages.h" -#include "content/renderer/devtools_agent.h" -#include "content/renderer/plugin_channel_host.h" -#include "third_party/WebKit/Source/WebKit/chromium/public/WebDevToolsAgent.h" -#include "third_party/WebKit/Source/WebKit/chromium/public/platform/WebString.h" - -using WebKit::WebDevToolsAgent; -using WebKit::WebString; - -namespace content { - -namespace { - -class MessageImpl : public WebDevToolsAgent::MessageDescriptor { - public: - MessageImpl(const std::string& message, int host_id) - : msg(message), - host_id(host_id) { - } - virtual ~MessageImpl() {} - virtual WebDevToolsAgent* agent() { - DevToolsAgent* agent = DevToolsAgent::FromHostId(host_id); - if (!agent) - return 0; - return agent->GetWebAgent(); - } - virtual WebString message() { return WebString::fromUTF8(msg); } - private: - std::string msg; - int host_id; -}; - -} // namespace - -DevToolsAgentFilter::DevToolsAgentFilter() - : message_handled_(false), - render_thread_loop_(MessageLoop::current()), - current_routing_id_(0) { -} - -bool DevToolsAgentFilter::OnMessageReceived(const IPC::Message& message) { - // Dispatch debugger commands directly from IO. - message_handled_ = true; - current_routing_id_ = message.routing_id(); - IPC_BEGIN_MESSAGE_MAP(DevToolsAgentFilter, message) - IPC_MESSAGE_HANDLER(DevToolsAgentMsg_DispatchOnInspectorBackend, - OnDispatchOnInspectorBackend) - IPC_MESSAGE_UNHANDLED(message_handled_ = false) - IPC_END_MESSAGE_MAP() - return message_handled_; -} - -DevToolsAgentFilter::~DevToolsAgentFilter() {} - -void DevToolsAgentFilter::OnDispatchOnInspectorBackend( - const std::string& message) { - if (!WebDevToolsAgent::shouldInterruptForMessage( - WebString::fromUTF8(message))) { - message_handled_ = false; - return; - } - WebDevToolsAgent::interruptAndDispatch( - new MessageImpl(message, current_routing_id_)); - - render_thread_loop_->PostTask( - FROM_HERE, base::Bind(&WebDevToolsAgent::processPendingMessages)); -} - -} // namespace content diff --git a/content/renderer/devtools_agent_filter.h b/content/renderer/devtools_agent_filter.h deleted file mode 100644 index 627f749..0000000 --- a/content/renderer/devtools_agent_filter.h +++ /dev/null @@ -1,48 +0,0 @@ -// Copyright (c) 2012 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 CONTENT_RENDERER_DEVTOOLS_AGENT_FILTER_H_ -#define CONTENT_RENDERER_DEVTOOLS_AGENT_FILTER_H_ - -#include - -#include "ipc/ipc_channel_proxy.h" - -class MessageLoop; -struct DevToolsMessageData; - -namespace content { - -// DevToolsAgentFilter is registered as an IPC filter in order to be able to -// dispatch messages while on the IO thread. The reason for that is that while -// debugging, Render thread is being held by the v8 and hence no messages -// are being dispatched there. While holding the thread in a tight loop, -// v8 provides thread-safe Api for controlling debugger. In our case v8's Api -// is being used from this communication agent on the IO thread. -class DevToolsAgentFilter : public IPC::ChannelProxy::MessageFilter { - public: - // There is a single instance of this class instantiated by the RenderThread. - DevToolsAgentFilter(); - - static void SendRpcMessage(const DevToolsMessageData& data); - - // IPC::ChannelProxy::MessageFilter override. Called on IO thread. - virtual bool OnMessageReceived(const IPC::Message& message) OVERRIDE; - - protected: - virtual ~DevToolsAgentFilter(); - - private: - void OnDispatchOnInspectorBackend(const std::string& message); - - bool message_handled_; - MessageLoop* render_thread_loop_; - int current_routing_id_; - - DISALLOW_COPY_AND_ASSIGN(DevToolsAgentFilter); -}; - -} // namespace content - -#endif // CONTENT_RENDERER_DEVTOOLS_AGENT_FILTER_H_ diff --git a/content/renderer/devtools_client.cc b/content/renderer/devtools_client.cc deleted file mode 100644 index d4ea447..0000000 --- a/content/renderer/devtools_client.cc +++ /dev/null @@ -1,97 +0,0 @@ -// Copyright (c) 2012 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 "content/renderer/devtools_client.h" - -#include "base/command_line.h" -#include "base/message_loop.h" -#include "base/utf_string_conversions.h" -#include "content/common/devtools_messages.h" -#include "content/public/common/content_switches.h" -#include "content/renderer/render_thread_impl.h" -#include "content/renderer/render_view_impl.h" -#include "third_party/WebKit/Source/WebKit/chromium/public/WebDevToolsFrontend.h" -#include "third_party/WebKit/Source/WebKit/chromium/public/platform/WebFloatPoint.h" -#include "third_party/WebKit/Source/WebKit/chromium/public/platform/WebString.h" -#include "ui/base/ui_base_switches.h" - -using WebKit::WebDevToolsFrontend; -using WebKit::WebString; - -namespace content { - -DevToolsClient::DevToolsClient(RenderViewImpl* render_view) - : RenderViewObserver(render_view) { - const CommandLine& command_line = *CommandLine::ForCurrentProcess(); - web_tools_frontend_.reset( - WebDevToolsFrontend::create( - render_view->webview(), - this, - ASCIIToUTF16(command_line.GetSwitchValueASCII(switches::kLang)))); -} - -DevToolsClient::~DevToolsClient() { -} - -bool DevToolsClient::OnMessageReceived(const IPC::Message& message) { - DCHECK(RenderThreadImpl::current()); - - bool handled = true; - IPC_BEGIN_MESSAGE_MAP(DevToolsClient, message) - IPC_MESSAGE_HANDLER(DevToolsClientMsg_DispatchOnInspectorFrontend, - OnDispatchOnInspectorFrontend) - IPC_MESSAGE_UNHANDLED(handled = false); - IPC_END_MESSAGE_MAP() - - return handled; -} - -void DevToolsClient::sendMessageToBackend(const WebString& message) { - Send(new DevToolsAgentMsg_DispatchOnInspectorBackend(routing_id(), - message.utf8())); -} - -void DevToolsClient::activateWindow() { - Send(new DevToolsHostMsg_ActivateWindow(routing_id())); -} - -void DevToolsClient::closeWindow() { - Send(new DevToolsHostMsg_CloseWindow(routing_id())); -} - -void DevToolsClient::moveWindowBy(const WebKit::WebFloatPoint& offset) { - Send(new DevToolsHostMsg_MoveWindow(routing_id(), offset.x, offset.y)); -} - -void DevToolsClient::requestSetDockSide(const WebKit::WebString& side) { - Send(new DevToolsHostMsg_RequestSetDockSide(routing_id(), side.utf8())); -} - -void DevToolsClient::openInNewTab(const WebKit::WebString& url) { - Send(new DevToolsHostMsg_OpenInNewTab(routing_id(), - url.utf8())); -} - -void DevToolsClient::save(const WebKit::WebString& url, - const WebKit::WebString& content, - bool save_as) { - Send(new DevToolsHostMsg_Save(routing_id(), - url.utf8(), - content.utf8(), - save_as)); -} - -void DevToolsClient::append(const WebKit::WebString& url, - const WebKit::WebString& content) { - Send(new DevToolsHostMsg_Append(routing_id(), - url.utf8(), - content.utf8())); -} - -void DevToolsClient::OnDispatchOnInspectorFrontend(const std::string& message) { - web_tools_frontend_->dispatchOnInspectorFrontend( - WebString::fromUTF8(message)); -} - -} // namespace content diff --git a/content/renderer/devtools_client.h b/content/renderer/devtools_client.h deleted file mode 100644 index 7e93008..0000000 --- a/content/renderer/devtools_client.h +++ /dev/null @@ -1,63 +0,0 @@ -// Copyright (c) 2012 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 CONTENT_RENDERER_DEVTOOLS_CLIENT_H_ -#define CONTENT_RENDERER_DEVTOOLS_CLIENT_H_ - -#include - -#include "base/basictypes.h" -#include "base/memory/scoped_ptr.h" -#include "content/public/renderer/render_view_observer.h" -#include "third_party/WebKit/Source/WebKit/chromium/public/WebDevToolsFrontendClient.h" - -namespace WebKit { -class WebDevToolsFrontend; -class WebString; -} - -namespace content { - -class RenderViewImpl; - -// Developer tools UI end of communication channel between the render process of -// the page being inspected and tools UI renderer process. All messages will -// go through browser process. On the side of the inspected page there's -// corresponding DevToolsAgent object. -// TODO(yurys): now the client is almost empty later it will delegate calls to -// code in glue -class DevToolsClient : public RenderViewObserver, - public WebKit::WebDevToolsFrontendClient { - public: - explicit DevToolsClient(RenderViewImpl* render_view); - virtual ~DevToolsClient(); - - private: - // RenderView::Observer implementation. - virtual bool OnMessageReceived(const IPC::Message& message) OVERRIDE; - - // WebDevToolsFrontendClient implementation. - virtual void sendMessageToBackend(const WebKit::WebString&) OVERRIDE; - - virtual void activateWindow() OVERRIDE; - virtual void closeWindow() OVERRIDE; - virtual void moveWindowBy(const WebKit::WebFloatPoint& offset) OVERRIDE; - virtual void requestSetDockSide(const WebKit::WebString& side) OVERRIDE; - virtual void openInNewTab(const WebKit::WebString& side) OVERRIDE; - virtual void save(const WebKit::WebString& url, - const WebKit::WebString& content, - bool save_as) OVERRIDE; - virtual void append(const WebKit::WebString& url, - const WebKit::WebString& content) OVERRIDE; - - void OnDispatchOnInspectorFrontend(const std::string& message); - - scoped_ptr web_tools_frontend_; - - DISALLOW_COPY_AND_ASSIGN(DevToolsClient); -}; - -} // namespace content - -#endif // CONTENT_RENDERER_DEVTOOLS_CLIENT_H_ diff --git a/content/renderer/render_thread_impl.cc b/content/renderer/render_thread_impl.cc index 7b52bf1..f7da814 100644 --- a/content/renderer/render_thread_impl.cc +++ b/content/renderer/render_thread_impl.cc @@ -48,7 +48,7 @@ #include "content/public/renderer/content_renderer_client.h" #include "content/public/renderer/render_process_observer.h" #include "content/public/renderer/render_view_visitor.h" -#include "content/renderer/devtools_agent_filter.h" +#include "content/renderer/devtools/devtools_agent_filter.h" #include "content/renderer/dom_storage/dom_storage_dispatcher.h" #include "content/renderer/dom_storage/webstoragearea_impl.h" #include "content/renderer/dom_storage/webstoragenamespace_impl.h" diff --git a/content/renderer/render_view_impl.cc b/content/renderer/render_view_impl.cc index 628d3cd..478898b 100644 --- a/content/renderer/render_view_impl.cc +++ b/content/renderer/render_view_impl.cc @@ -68,7 +68,7 @@ #include "content/renderer/browser_plugin/browser_plugin_manager.h" #include "content/renderer/browser_plugin/browser_plugin_manager_impl.h" #include "content/renderer/device_orientation_dispatcher.h" -#include "content/renderer/devtools_agent.h" +#include "content/renderer/devtools/devtools_agent.h" #include "content/renderer/disambiguation_popup_helper.h" #include "content/renderer/dom_automation_controller.h" #include "content/renderer/dom_storage/webstoragenamespace_impl.h" diff --git a/tools/code_coverage/coverage_posix.py b/tools/code_coverage/coverage_posix.py index a8670a8..5f29b82 100755 --- a/tools/code_coverage/coverage_posix.py +++ b/tools/code_coverage/coverage_posix.py @@ -332,7 +332,7 @@ gTestInclusions = { 'GeolocationBrowserTest.*', # 'src/chrome/browser/nacl_host' 'NaClGdbTest.*', - # 'src/chrome/browser/debugger' + # 'src/chrome/browser/devtools' 'DevToolsSanityTest.*', 'DevToolsExtensionTest.*', 'DevToolsExperimentalExtensionTest.*', diff --git a/tools/gritsettings/resource_ids b/tools/gritsettings/resource_ids index ab4e344..a78d55c 100644 --- a/tools/gritsettings/resource_ids +++ b/tools/gritsettings/resource_ids @@ -167,7 +167,7 @@ "includes": [22000], }, # This file is generated during the build. - "chrome/browser/debugger/frontend/devtools_discovery_page_resources.grd": { + "chrome/browser/devtools/frontend/devtools_discovery_page_resources.grd": { "includes": [22500], }, "chrome/browser/resources/options_resources.grd": { -- cgit v1.1