summaryrefslogtreecommitdiffstats
path: root/chrome/common
diff options
context:
space:
mode:
authorBen Murdoch <benm@google.com>2010-08-06 12:13:06 +0100
committerBen Murdoch <benm@google.com>2010-08-18 15:49:13 +0100
commit06741cbc25cd4227a9fba40dfd0273bfcc1a587a (patch)
treeca6f21dec86a8c4f6d3c50e78628c0cf31da0353 /chrome/common
parentaa0bf16ed53445f227734aee4274c7aef056f032 (diff)
downloadexternal_chromium-06741cbc25cd4227a9fba40dfd0273bfcc1a587a.zip
external_chromium-06741cbc25cd4227a9fba40dfd0273bfcc1a587a.tar.gz
external_chromium-06741cbc25cd4227a9fba40dfd0273bfcc1a587a.tar.bz2
Add chrome/common @ 52593
Needed by autofill Change-Id: Ibfea9ab92382af0bd0cfc6e94d21e4baa4b9d896
Diffstat (limited to 'chrome/common')
-rw-r--r--chrome/common/DEPS22
-rw-r--r--chrome/common/about_handler.cc34
-rw-r--r--chrome/common/about_handler.h23
-rw-r--r--chrome/common/app_mode_common_mac.h66
-rw-r--r--chrome/common/app_mode_common_mac.mm17
-rw-r--r--chrome/common/appcache/appcache_backend_proxy.cc65
-rw-r--r--chrome/common/appcache/appcache_backend_proxy.h43
-rw-r--r--chrome/common/appcache/appcache_dispatcher.cc61
-rw-r--r--chrome/common/appcache/appcache_dispatcher.h46
-rw-r--r--chrome/common/automation_constants.cc15
-rw-r--r--chrome/common/automation_constants.h19
-rw-r--r--chrome/common/bindings_policy.h42
-rw-r--r--chrome/common/bzip2_unittest.cc72
-rw-r--r--chrome/common/child_process.cc97
-rw-r--r--chrome/common/child_process.h70
-rw-r--r--chrome/common/child_process_host.cc190
-rw-r--r--chrome/common/child_process_host.h123
-rw-r--r--chrome/common/child_process_info.cc130
-rw-r--r--chrome/common/child_process_info.h113
-rw-r--r--chrome/common/child_process_logging.h81
-rw-r--r--chrome/common/child_process_logging_linux.cc42
-rw-r--r--chrome/common/child_process_logging_mac.mm136
-rw-r--r--chrome/common/child_process_logging_mac_unittest.mm141
-rw-r--r--chrome/common/child_process_logging_win.cc115
-rw-r--r--chrome/common/child_thread.cc182
-rw-r--r--chrome/common/child_thread.h123
-rw-r--r--chrome/common/chrome_constants.cc139
-rw-r--r--chrome/common/chrome_constants.h95
-rw-r--r--chrome/common/chrome_counters.cc52
-rw-r--r--chrome/common/chrome_counters.h39
-rw-r--r--chrome/common/chrome_descriptors.h16
-rw-r--r--chrome/common/chrome_paths.cc316
-rw-r--r--chrome/common/chrome_paths.h80
-rw-r--r--chrome/common/chrome_paths_internal.h60
-rw-r--r--chrome/common/chrome_paths_linux.cc76
-rw-r--r--chrome/common/chrome_paths_mac.mm108
-rw-r--r--chrome/common/chrome_paths_win.cc94
-rw-r--r--chrome/common/chrome_plugin_api.h566
-rw-r--r--chrome/common/chrome_plugin_lib.cc290
-rw-r--r--chrome/common/chrome_plugin_lib.h106
-rw-r--r--chrome/common/chrome_plugin_util.cc182
-rw-r--r--chrome/common/chrome_plugin_util.h87
-rw-r--r--chrome/common/chrome_switches.cc1129
-rw-r--r--chrome/common/chrome_switches.h354
-rw-r--r--chrome/common/chrome_version_info.cc52
-rw-r--r--chrome/common/chrome_version_info.h18
-rw-r--r--chrome/common/chrome_version_info_posix.h.version26
-rw-r--r--chrome/common/common.sb33
-rw-r--r--chrome/common/common.vsprops8
-rw-r--r--chrome/common/common_glue.cc49
-rw-r--r--chrome/common/common_param_traits.cc458
-rw-r--r--chrome/common/common_param_traits.h428
-rw-r--r--chrome/common/common_param_traits_unittest.cc279
-rw-r--r--chrome/common/common_resources.grd17
-rw-r--r--chrome/common/content_settings.cc11
-rw-r--r--chrome/common/content_settings.h40
-rw-r--r--chrome/common/content_settings_helper.cc22
-rw-r--r--chrome/common/content_settings_helper.h20
-rw-r--r--chrome/common/content_settings_helper_unittest.cc42
-rw-r--r--chrome/common/content_settings_types.h24
-rw-r--r--chrome/common/css_colors.h25
-rw-r--r--chrome/common/database_util.cc53
-rw-r--r--chrome/common/database_util.h22
-rw-r--r--chrome/common/db_message_filter.cc37
-rw-r--r--chrome/common/db_message_filter.h27
-rw-r--r--chrome/common/debug_flags.cc50
-rw-r--r--chrome/common/debug_flags.h28
-rw-r--r--chrome/common/default_plugin.cc33
-rw-r--r--chrome/common/default_plugin.h15
-rw-r--r--chrome/common/deprecated/event_sys-inl.h341
-rw-r--r--chrome/common/deprecated/event_sys.h45
-rw-r--r--chrome/common/deprecated/event_sys_unittest.cc271
-rw-r--r--chrome/common/desktop_notifications/active_notification_tracker.cc70
-rw-r--r--chrome/common/desktop_notifications/active_notification_tracker.h52
-rw-r--r--chrome/common/desktop_notifications/active_notification_tracker_unittest.cc25
-rw-r--r--chrome/common/devtools_messages.h38
-rw-r--r--chrome/common/devtools_messages_internal.h96
-rw-r--r--chrome/common/dom_storage_common.h16
-rw-r--r--chrome/common/edit_command.h24
-rw-r--r--chrome/common/env_vars.cc40
-rw-r--r--chrome/common/env_vars.h24
-rw-r--r--chrome/common/extra_defines.vsprops7
-rw-r--r--chrome/common/font_descriptor_mac.h32
-rw-r--r--chrome/common/font_descriptor_mac.mm20
-rw-r--r--chrome/common/font_descriptor_mac_unittest.mm91
-rw-r--r--chrome/common/font_loader_mac.h55
-rw-r--r--chrome/common/font_loader_mac.mm116
-rw-r--r--chrome/common/gears_api.h97
-rw-r--r--chrome/common/geoposition.cc66
-rw-r--r--chrome/common/geoposition.h64
-rw-r--r--chrome/common/googleurl_dummy.cc18
-rw-r--r--chrome/common/gpu_info.cc41
-rw-r--r--chrome/common/gpu_info.h54
-rw-r--r--chrome/common/gpu_info_unittest.cc17
-rw-r--r--chrome/common/gpu_messages.h87
-rw-r--r--chrome/common/gpu_messages_internal.h213
-rw-r--r--chrome/common/gpu_messages_unittest.cc35
-rw-r--r--chrome/common/gpu_native_window_handle.h41
-rw-r--r--chrome/common/gpu_plugin.cc44
-rw-r--r--chrome/common/gpu_plugin.h15
-rw-r--r--chrome/common/important_file_writer.cc150
-rw-r--r--chrome/common/important_file_writer.h112
-rw-r--r--chrome/common/important_file_writer_unittest.cc115
-rw-r--r--chrome/common/indexed_db_key.cc54
-rw-r--r--chrome/common/indexed_db_key.h34
-rw-r--r--chrome/common/ipc_test_sink.cc57
-rw-r--r--chrome/common/ipc_test_sink.h89
-rw-r--r--chrome/common/json_pref_store.cc130
-rw-r--r--chrome/common/json_pref_store.h56
-rw-r--r--chrome/common/json_pref_store_unittest.cc150
-rw-r--r--chrome/common/json_value_serializer.cc108
-rw-r--r--chrome/common/json_value_serializer.h127
-rw-r--r--chrome/common/json_value_serializer_perftest.cc90
-rw-r--r--chrome/common/json_value_serializer_unittest.cc348
-rw-r--r--chrome/common/jstemplate_builder.cc116
-rw-r--r--chrome/common/jstemplate_builder.h69
-rw-r--r--chrome/common/libxml_utils.cc143
-rw-r--r--chrome/common/libxml_utils.h182
-rw-r--r--chrome/common/logging_chrome.cc294
-rw-r--r--chrome/common/logging_chrome.h68
-rw-r--r--chrome/common/logging_chrome_uitest.cc189
-rw-r--r--chrome/common/mach_message_source_mac.cc66
-rw-r--r--chrome/common/mach_message_source_mac.h59
-rw-r--r--chrome/common/main_function_params.h33
-rw-r--r--chrome/common/message_router.cc46
-rw-r--r--chrome/common/message_router.h62
-rw-r--r--chrome/common/metrics_helpers.cc516
-rw-r--r--chrome/common/metrics_helpers.h223
-rw-r--r--chrome/common/mru_cache.h252
-rw-r--r--chrome/common/mru_cache_unittest.cc253
-rw-r--r--chrome/common/nacl_cmd_line.cc40
-rw-r--r--chrome/common/nacl_cmd_line.h16
-rw-r--r--chrome/common/nacl_messages.h19
-rw-r--r--chrome/common/nacl_messages_internal.h30
-rw-r--r--chrome/common/nacl_types.h29
-rw-r--r--chrome/common/native_web_keyboard_event.h63
-rw-r--r--chrome/common/native_web_keyboard_event_linux.cc76
-rw-r--r--chrome/common/native_web_keyboard_event_mac.mm56
-rw-r--r--chrome/common/native_web_keyboard_event_win.cc54
-rw-r--r--chrome/common/native_window_notification_source.h29
-rw-r--r--chrome/common/navigation_gesture.h22
-rw-r--r--chrome/common/navigation_types.h66
-rw-r--r--chrome/common/net/gaia/gaia_auth_consumer.h73
-rw-r--r--chrome/common/net/gaia/gaia_authenticator.cc376
-rw-r--r--chrome/common/net/gaia/gaia_authenticator.h302
-rw-r--r--chrome/common/net/gaia/gaia_authenticator2.cc292
-rw-r--r--chrome/common/net/gaia/gaia_authenticator2.h157
-rw-r--r--chrome/common/net/gaia/gaia_authenticator2_unittest.cc360
-rw-r--r--chrome/common/net/gaia/gaia_authenticator2_unittest.h71
-rw-r--r--chrome/common/net/gaia/gaia_authenticator_unittest.cc49
-rw-r--r--chrome/common/net/http_return.h17
-rw-r--r--chrome/common/net/net_resource_provider.cc63
-rw-r--r--chrome/common/net/net_resource_provider.h19
-rw-r--r--chrome/common/net/predictor_common.h29
-rw-r--r--chrome/common/net/socket_stream.h14
-rw-r--r--chrome/common/net/test_url_fetcher_factory.cc27
-rw-r--r--chrome/common/net/test_url_fetcher_factory.h82
-rw-r--r--chrome/common/net/url_fetcher.cc377
-rw-r--r--chrome/common/net/url_fetcher.h192
-rw-r--r--chrome/common/net/url_fetcher_protect.cc176
-rw-r--r--chrome/common/net/url_fetcher_protect.h146
-rw-r--r--chrome/common/net/url_fetcher_unittest.cc613
-rw-r--r--chrome/common/net/url_request_context_getter.cc27
-rw-r--r--chrome/common/net/url_request_context_getter.h55
-rw-r--r--chrome/common/net/url_request_intercept_job.cc226
-rw-r--r--chrome/common/net/url_request_intercept_job.h67
-rw-r--r--chrome/common/notification_details.cc18
-rw-r--r--chrome/common/notification_details.h56
-rw-r--r--chrome/common/notification_observer.h24
-rw-r--r--chrome/common/notification_observer_mock.h24
-rw-r--r--chrome/common/notification_registrar.cc108
-rw-r--r--chrome/common/notification_registrar.h56
-rw-r--r--chrome/common/notification_service.cc152
-rw-r--r--chrome/common/notification_service.h108
-rw-r--r--chrome/common/notification_service_unittest.cc163
-rw-r--r--chrome/common/notification_source.cc17
-rw-r--r--chrome/common/notification_source.h54
-rw-r--r--chrome/common/notification_type.h1114
-rw-r--r--chrome/common/owned_widget_gtk.cc38
-rw-r--r--chrome/common/owned_widget_gtk.h89
-rw-r--r--chrome/common/page_transition_types.cc36
-rw-r--r--chrome/common/page_transition_types.h161
-rw-r--r--chrome/common/page_zoom.h22
-rw-r--r--chrome/common/pepper_plugin_registry.cc163
-rw-r--r--chrome/common/pepper_plugin_registry.h52
-rw-r--r--chrome/common/plugin_carbon_interpose_constants_mac.cc17
-rw-r--r--chrome/common/plugin_carbon_interpose_constants_mac.h20
-rw-r--r--chrome/common/plugin_group.cc343
-rw-r--r--chrome/common/plugin_group.h129
-rw-r--r--chrome/common/plugin_group_unittest.cc113
-rw-r--r--chrome/common/plugin_messages.h433
-rw-r--r--chrome/common/plugin_messages_internal.h514
-rw-r--r--chrome/common/pref_names.cc945
-rw-r--r--chrome/common/pref_names.h353
-rw-r--r--chrome/common/pref_store.h49
-rw-r--r--chrome/common/process_watcher.h44
-rw-r--r--chrome/common/process_watcher_mac.cc170
-rw-r--r--chrome/common/process_watcher_posix.cc105
-rw-r--r--chrome/common/process_watcher_unittest.cc64
-rw-r--r--chrome/common/process_watcher_win.cc95
-rw-r--r--chrome/common/property_bag.cc55
-rw-r--r--chrome/common/property_bag.h173
-rw-r--r--chrome/common/property_bag_unittest.cc62
-rw-r--r--chrome/common/ref_counted_util.h26
-rw-r--r--chrome/common/render_messages.h3214
-rw-r--r--chrome/common/render_messages_internal.h2529
-rw-r--r--chrome/common/render_messages_unittest.cc92
-rw-r--r--chrome/common/renderer_preferences.h93
-rw-r--r--chrome/common/resource_dispatcher.cc628
-rw-r--r--chrome/common/resource_dispatcher.h138
-rw-r--r--chrome/common/resource_dispatcher_dummy.cc35
-rw-r--r--chrome/common/resource_dispatcher_unittest.cc325
-rw-r--r--chrome/common/resource_response.h50
-rw-r--r--chrome/common/result_codes.h63
-rw-r--r--chrome/common/sandbox_init_wrapper.h68
-rw-r--r--chrome/common/sandbox_init_wrapper_linux.cc14
-rw-r--r--chrome/common/sandbox_init_wrapper_mac.cc77
-rw-r--r--chrome/common/sandbox_init_wrapper_win.cc33
-rw-r--r--chrome/common/sandbox_mac.h60
-rw-r--r--chrome/common/sandbox_mac.mm434
-rw-r--r--chrome/common/sandbox_mac_diraccess_unittest.mm250
-rw-r--r--chrome/common/sandbox_mac_fontloading_unittest.mm183
-rw-r--r--chrome/common/sandbox_mac_system_access_unittest.mm96
-rw-r--r--chrome/common/sandbox_mac_unittest_helper.h114
-rw-r--r--chrome/common/sandbox_mac_unittest_helper.mm153
-rw-r--r--chrome/common/sandbox_methods_linux.h24
-rw-r--r--chrome/common/sandbox_policy.cc503
-rw-r--r--chrome/common/sandbox_policy.h26
-rw-r--r--chrome/common/security_filter_peer.cc210
-rw-r--r--chrome/common/security_filter_peer.h122
-rw-r--r--chrome/common/serialized_script_value.cc37
-rw-r--r--chrome/common/serialized_script_value.h34
-rw-r--r--chrome/common/socket_stream_dispatcher.cc215
-rw-r--r--chrome/common/socket_stream_dispatcher.h38
-rw-r--r--chrome/common/socket_stream_dispatcher_dummy.cc18
-rw-r--r--chrome/common/spellcheck_common.cc179
-rw-r--r--chrome/common/spellcheck_common.h36
-rw-r--r--chrome/common/sqlite_compiled_statement.cc85
-rw-r--r--chrome/common/sqlite_compiled_statement.h135
-rw-r--r--chrome/common/sqlite_utils.cc508
-rw-r--r--chrome/common/sqlite_utils.h399
-rw-r--r--chrome/common/task_queue.cc46
-rw-r--r--chrome/common/task_queue.h42
-rw-r--r--chrome/common/thumbnail_score.cc118
-rw-r--r--chrome/common/thumbnail_score.h82
-rw-r--r--chrome/common/thumbnail_score_unittest.cc54
-rw-r--r--chrome/common/time_format.cc338
-rw-r--r--chrome/common/time_format.h52
-rw-r--r--chrome/common/time_format_unittest.cc69
-rw-r--r--chrome/common/translate_errors.h30
-rw-r--r--chrome/common/url_constants.cc134
-rw-r--r--chrome/common/url_constants.h118
-rw-r--r--chrome/common/utility_messages.h78
-rw-r--r--chrome/common/utility_messages_internal.h114
-rw-r--r--chrome/common/view_types.cc14
-rw-r--r--chrome/common/view_types.h45
-rw-r--r--chrome/common/visitedlink_common.cc89
-rw-r--r--chrome/common/visitedlink_common.h137
-rw-r--r--chrome/common/web_database_observer_impl.cc52
-rw-r--r--chrome/common/web_database_observer_impl.h27
-rw-r--r--chrome/common/web_resource/web_resource_unpacker.cc38
-rw-r--r--chrome/common/web_resource/web_resource_unpacker.h57
-rw-r--r--chrome/common/webkit_param_traits.h442
-rw-r--r--chrome/common/webmessageportchannel_impl.cc237
-rw-r--r--chrome/common/webmessageportchannel_impl.h74
-rw-r--r--chrome/common/win_safe_util.cc120
-rw-r--r--chrome/common/win_safe_util.h51
-rw-r--r--chrome/common/window_container_type.cc41
-rw-r--r--chrome/common/window_container_type.h35
-rw-r--r--chrome/common/worker_messages.h133
-rw-r--r--chrome/common/worker_messages_internal.h126
-rw-r--r--chrome/common/worker_thread_ticker.cc101
-rw-r--r--chrome/common/worker_thread_ticker.h90
-rw-r--r--chrome/common/worker_thread_ticker_unittest.cc108
-rw-r--r--chrome/common/zip.cc313
-rw-r--r--chrome/common/zip.h23
-rw-r--r--chrome/common/zip_unittest.cc145
277 files changed, 39486 insertions, 0 deletions
diff --git a/chrome/common/DEPS b/chrome/common/DEPS
new file mode 100644
index 0000000..2f3b9b0
--- /dev/null
+++ b/chrome/common/DEPS
@@ -0,0 +1,22 @@
+include_rules = [
+ "+chrome/plugin", # For checking whether we're a plugin process.
+ "+chrome/default_plugin",
+ "+grit", # For generated headers
+ "+libxml",
+ "+media/audio",
+ "+remoting/client/plugin",
+ "+sandbox/src",
+ "+skia/include",
+ "+webkit/glue",
+
+ # Other libraries.
+ "+chrome/third_party/xdg_user_dirs",
+ "+third_party/bzip2",
+ "+third_party/npapi",
+ "+third_party/sqlite",
+ "+third_party/zlib",
+
+ # FIXME - refactor code and remove these dependencies
+ "+chrome/app",
+ "+chrome/installer",
+]
diff --git a/chrome/common/about_handler.cc b/chrome/common/about_handler.cc
new file mode 100644
index 0000000..84658a0
--- /dev/null
+++ b/chrome/common/about_handler.cc
@@ -0,0 +1,34 @@
+// Copyright (c) 2010 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/common/about_handler.h"
+
+namespace chrome_about_handler {
+
+// This needs to match up with about_urls_handlers in
+// chrome/renderer/about_handler.cc.
+const char* const about_urls[] = {
+ chrome::kAboutCrashURL,
+ chrome::kAboutHangURL,
+ chrome::kAboutShorthangURL,
+ NULL,
+};
+const size_t about_urls_size = arraysize(about_urls);
+
+const char* const kAboutScheme = "about";
+
+bool WillHandle(const GURL& url) {
+ if (url.scheme() != kAboutScheme)
+ return false;
+
+ const char* const* url_handler = about_urls;
+ while (*url_handler) {
+ if (GURL(*url_handler) == url)
+ return true;
+ url_handler++;
+ }
+ return false;
+}
+
+} // namespace chrome_about_handler
diff --git a/chrome/common/about_handler.h b/chrome/common/about_handler.h
new file mode 100644
index 0000000..f5d0818
--- /dev/null
+++ b/chrome/common/about_handler.h
@@ -0,0 +1,23 @@
+// Copyright (c) 2010 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_COMMON_ABOUT_HANDLER_H__
+#define CHROME_COMMON_ABOUT_HANDLER_H__
+
+#include "chrome/common/url_constants.h"
+#include "googleurl/src/gurl.h"
+
+namespace chrome_about_handler {
+
+extern const char* const about_urls[];
+extern const size_t about_urls_size; // Only used for testing
+extern const char* const kAboutScheme;
+
+// Returns true if the URL is one that AboutHandler will handle when
+// AboutHandler::MaybeHandle is called.
+bool WillHandle(const GURL& url);
+
+} // namespace chrome_about_handler
+
+#endif // CHROME_COMMON_ABOUT_HANDLER_H__
diff --git a/chrome/common/app_mode_common_mac.h b/chrome/common/app_mode_common_mac.h
new file mode 100644
index 0000000..046324a
--- /dev/null
+++ b/chrome/common/app_mode_common_mac.h
@@ -0,0 +1,66 @@
+// Copyright (c) 2010 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_COMMON_APP_MODE_COMMON_MAC_H_
+#define CHROME_COMMON_APP_MODE_COMMON_MAC_H_
+
+#include <CoreFoundation/CoreFoundation.h>
+
+// This file contains constants, interfaces, etc. which are common to the
+// browser application and the app mode loader (a.k.a. shim).
+
+namespace app_mode {
+
+// The ID under which app mode preferences will be recorded
+// ("org.chromium.Chromium" or "com.google.Chrome").
+extern const CFStringRef kAppPrefsID;
+
+// The key under which to record the path to the (user-visible) application
+// bundle; this key is recorded under the ID given by |kAppPrefsID|.
+extern const CFStringRef kLastRunAppBundlePathPrefsKey;
+
+// Current major/minor version numbers of |ChromeAppModeInfo| (defined below).
+const unsigned kCurrentChromeAppModeInfoMajorVersion = 1;
+const unsigned kCurrentChromeAppModeInfoMinorVersion = 0;
+
+// The structure used to pass information from the app mode loader to the
+// (browser) framework. This is versioned using major and minor version numbers,
+// written below as v<major>.<minor>. Version-number checking is done by the
+// framework, and the framework must accept all structures with the same major
+// version number. It may refuse to load if the major version of the structure
+// is different from the one it accepts.
+struct ChromeAppModeInfo {
+ // Major and minor version number of this structure.
+ unsigned major_version; // Required: all versions
+ unsigned minor_version; // Required: all versions
+
+ // Original |argc| and |argv|.
+ int argc; // Required: v1.0
+ char** argv; // Required: v1.0
+
+ // Versioned path to the browser which is being loaded.
+ char* chrome_versioned_path; // Required: v1.0
+
+ // Information about the App Mode shortcut:
+
+ // Path to the App Mode Loader application bundle originally run.
+ char* app_mode_bundle_path; // Optional: v1.0
+
+ // Short ID string, preferably derived from |app_mode_short_name|. Should be
+ // safe for the file system.
+ char* app_mode_id; // Required: v1.0
+
+ // Short (e.g., one-word) UTF8-encoded name for the shortcut.
+ char* app_mode_short_name; // Optional: v1.0
+
+ // Unrestricted (e.g., several-word) UTF8-encoded name for the shortcut.
+ char* app_mode_name; // Optional: v1.0
+
+ // URL for the shortcut. Must be a valid URL.
+ char* app_mode_url; // Required: v1.0
+};
+
+} // namespace app_mode
+
+#endif // CHROME_COMMON_APP_MODE_COMMON_MAC_H_
diff --git a/chrome/common/app_mode_common_mac.mm b/chrome/common/app_mode_common_mac.mm
new file mode 100644
index 0000000..3705c34
--- /dev/null
+++ b/chrome/common/app_mode_common_mac.mm
@@ -0,0 +1,17 @@
+// Copyright (c) 2010 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/common/app_mode_common_mac.h"
+
+namespace app_mode {
+
+#if defined(GOOGLE_CHROME_BUILD)
+const CFStringRef kAppPrefsID = CFSTR("com.google.Chrome");
+#else
+const CFStringRef kAppPrefsID = CFSTR("org.chromium.Chromium");
+#endif
+
+const CFStringRef kLastRunAppBundlePathPrefsKey = CFSTR("LastRunAppBundlePath");
+
+} // namespace app_mode
diff --git a/chrome/common/appcache/appcache_backend_proxy.cc b/chrome/common/appcache/appcache_backend_proxy.cc
new file mode 100644
index 0000000..e1776db
--- /dev/null
+++ b/chrome/common/appcache/appcache_backend_proxy.cc
@@ -0,0 +1,65 @@
+// Copyright (c) 2009 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/common/appcache/appcache_backend_proxy.h"
+
+#include "chrome/common/render_messages.h"
+
+void AppCacheBackendProxy::RegisterHost(int host_id) {
+ sender_->Send(new AppCacheMsg_RegisterHost(host_id));
+}
+
+void AppCacheBackendProxy::UnregisterHost(int host_id) {
+ sender_->Send(new AppCacheMsg_UnregisterHost(host_id));
+}
+
+void AppCacheBackendProxy::SelectCache(
+ int host_id,
+ const GURL& document_url,
+ const int64 cache_document_was_loaded_from,
+ const GURL& manifest_url) {
+ sender_->Send(new AppCacheMsg_SelectCache(
+ host_id, document_url,
+ cache_document_was_loaded_from,
+ manifest_url));
+}
+
+void AppCacheBackendProxy::SelectCacheForWorker(
+ int host_id, int parent_process_id, int parent_host_id) {
+ sender_->Send(new AppCacheMsg_SelectCacheForWorker(
+ host_id, parent_process_id,
+ parent_host_id));
+}
+
+void AppCacheBackendProxy::SelectCacheForSharedWorker(
+ int host_id, int64 appcache_id) {
+ sender_->Send(new AppCacheMsg_SelectCacheForSharedWorker(
+ host_id, appcache_id));
+}
+
+void AppCacheBackendProxy::MarkAsForeignEntry(
+ int host_id, const GURL& document_url,
+ int64 cache_document_was_loaded_from) {
+ sender_->Send(new AppCacheMsg_MarkAsForeignEntry(
+ host_id, document_url,
+ cache_document_was_loaded_from));
+}
+
+appcache::Status AppCacheBackendProxy::GetStatus(int host_id) {
+ appcache::Status status = appcache::UNCACHED;
+ sender_->Send(new AppCacheMsg_GetStatus(host_id, &status));
+ return status;
+}
+
+bool AppCacheBackendProxy::StartUpdate(int host_id) {
+ bool result = false;
+ sender_->Send(new AppCacheMsg_StartUpdate(host_id, &result));
+ return result;
+}
+
+bool AppCacheBackendProxy::SwapCache(int host_id) {
+ bool result = false;
+ sender_->Send(new AppCacheMsg_SwapCache(host_id, &result));
+ return result;
+}
diff --git a/chrome/common/appcache/appcache_backend_proxy.h b/chrome/common/appcache/appcache_backend_proxy.h
new file mode 100644
index 0000000..2ef2660
--- /dev/null
+++ b/chrome/common/appcache/appcache_backend_proxy.h
@@ -0,0 +1,43 @@
+// Copyright (c) 2009 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_COMMON_APPCACHE_APPCACHE_BACKEND_PROXY_H_
+#define CHROME_COMMON_APPCACHE_APPCACHE_BACKEND_PROXY_H_
+
+#include "ipc/ipc_message.h"
+#include "webkit/appcache/appcache_interfaces.h"
+
+// Sends appcache related messages to the main process.
+class AppCacheBackendProxy : public appcache::AppCacheBackend {
+ public:
+ explicit AppCacheBackendProxy(IPC::Message::Sender* sender)
+ : sender_(sender) {}
+
+ IPC::Message::Sender* sender() const { return sender_; }
+
+ // AppCacheBackend methods
+ virtual void RegisterHost(int host_id);
+ virtual void UnregisterHost(int host_id);
+ virtual void SelectCache(int host_id,
+ const GURL& document_url,
+ const int64 cache_document_was_loaded_from,
+ const GURL& manifest_url);
+ virtual void SelectCacheForWorker(
+ int host_id,
+ int parent_process_id,
+ int parent_host_id);
+ virtual void SelectCacheForSharedWorker(
+ int host_id,
+ int64 appcache_id);
+ virtual void MarkAsForeignEntry(int host_id, const GURL& document_url,
+ int64 cache_document_was_loaded_from);
+ virtual appcache::Status GetStatus(int host_id);
+ virtual bool StartUpdate(int host_id);
+ virtual bool SwapCache(int host_id);
+
+ private:
+ IPC::Message::Sender* sender_;
+};
+
+#endif // CHROME_COMMON_APPCACHE_APPCACHE_BACKEND_PROXY_H_
diff --git a/chrome/common/appcache/appcache_dispatcher.cc b/chrome/common/appcache/appcache_dispatcher.cc
new file mode 100644
index 0000000..6cf40cc
--- /dev/null
+++ b/chrome/common/appcache/appcache_dispatcher.cc
@@ -0,0 +1,61 @@
+// Copyright (c) 2010 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/common/appcache/appcache_dispatcher.h"
+
+#include "chrome/common/render_messages.h"
+#include "webkit/appcache/web_application_cache_host_impl.h"
+
+bool AppCacheDispatcher::OnMessageReceived(const IPC::Message& msg) {
+ bool handled = true;
+ IPC_BEGIN_MESSAGE_MAP(AppCacheDispatcher, msg)
+ IPC_MESSAGE_HANDLER(AppCacheMsg_CacheSelected, OnCacheSelected)
+ IPC_MESSAGE_HANDLER(AppCacheMsg_StatusChanged, OnStatusChanged)
+ IPC_MESSAGE_HANDLER(AppCacheMsg_EventRaised, OnEventRaised)
+ IPC_MESSAGE_HANDLER(AppCacheMsg_ProgressEventRaised, OnProgressEventRaised)
+ IPC_MESSAGE_HANDLER(AppCacheMsg_ErrorEventRaised, OnErrorEventRaised)
+ IPC_MESSAGE_HANDLER(AppCacheMsg_LogMessage, OnLogMessage)
+ IPC_MESSAGE_HANDLER(AppCacheMsg_ContentBlocked, OnContentBlocked)
+ IPC_MESSAGE_UNHANDLED(handled = false)
+ IPC_END_MESSAGE_MAP()
+ return handled;
+}
+
+void AppCacheDispatcher::OnCacheSelected(int host_id, int64 cache_id,
+ appcache::Status status) {
+ frontend_impl_.OnCacheSelected(host_id, cache_id, status);
+}
+
+void AppCacheDispatcher::OnStatusChanged(const std::vector<int>& host_ids,
+ appcache::Status status) {
+ frontend_impl_.OnStatusChanged(host_ids, status);
+}
+
+void AppCacheDispatcher::OnEventRaised(const std::vector<int>& host_ids,
+ appcache::EventID event_id) {
+ frontend_impl_.OnEventRaised(host_ids, event_id);
+}
+
+void AppCacheDispatcher::OnProgressEventRaised(
+ const std::vector<int>& host_ids,
+ const GURL& url, int num_total, int num_complete) {
+ frontend_impl_.OnProgressEventRaised(host_ids, url, num_total, num_complete);
+}
+
+void AppCacheDispatcher::OnErrorEventRaised(
+ const std::vector<int>& host_ids,
+ const std::string& message) {
+ frontend_impl_.OnErrorEventRaised(host_ids, message);
+}
+
+void AppCacheDispatcher::OnLogMessage(
+ int host_id, int log_level, const std::string& message) {
+ frontend_impl_.OnLogMessage(
+ host_id, static_cast<appcache::LogLevel>(log_level), message);
+}
+
+void AppCacheDispatcher::OnContentBlocked(int host_id,
+ const GURL& manifest_url) {
+ frontend_impl_.OnContentBlocked(host_id, manifest_url);
+}
diff --git a/chrome/common/appcache/appcache_dispatcher.h b/chrome/common/appcache/appcache_dispatcher.h
new file mode 100644
index 0000000..d21be54
--- /dev/null
+++ b/chrome/common/appcache/appcache_dispatcher.h
@@ -0,0 +1,46 @@
+// Copyright (c) 2010 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_COMMON_APPCACHE_APPCACHE_DISPATCHER_H_
+#define CHROME_COMMON_APPCACHE_APPCACHE_DISPATCHER_H_
+
+#include <vector>
+#include "chrome/common/appcache/appcache_backend_proxy.h"
+#include "ipc/ipc_message.h"
+#include "webkit/appcache/appcache_frontend_impl.h"
+
+// Dispatches appcache related messages sent to a child process from the
+// main browser process. There is one instance per child process. Messages
+// are dispatched on the main child thread. The ChildThread base class
+// creates an instance and delegates calls to it.
+class AppCacheDispatcher {
+ public:
+ explicit AppCacheDispatcher(IPC::Message::Sender* sender)
+ : backend_proxy_(sender) {}
+
+ AppCacheBackendProxy* backend_proxy() { return &backend_proxy_; }
+
+ bool OnMessageReceived(const IPC::Message& msg);
+
+ private:
+ // Ipc message handlers
+ void OnCacheSelected(int host_id, int64 cache_id,
+ appcache::Status status);
+ void OnStatusChanged(const std::vector<int>& host_ids,
+ appcache::Status status);
+ void OnEventRaised(const std::vector<int>& host_ids,
+ appcache::EventID event_id);
+ void OnProgressEventRaised(const std::vector<int>& host_ids,
+ const GURL& url, int num_total, int num_complete);
+ void OnErrorEventRaised(const std::vector<int>& host_ids,
+ const std::string& message);
+ void OnLogMessage(int host_id, int log_level, const std::string& message);
+ void OnContentBlocked(int host_id,
+ const GURL& manifest_url);
+
+ AppCacheBackendProxy backend_proxy_;
+ appcache::AppCacheFrontendImpl frontend_impl_;
+};
+
+#endif // CHROME_COMMON_APPCACHE_APPCACHE_DISPATCHER_H_
diff --git a/chrome/common/automation_constants.cc b/chrome/common/automation_constants.cc
new file mode 100644
index 0000000..185d57b
--- /dev/null
+++ b/chrome/common/automation_constants.cc
@@ -0,0 +1,15 @@
+// Copyright (c) 2006-2009 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/common/automation_constants.h"
+
+namespace automation {
+// JSON value labels for proxy settings that are passed in via
+// AutomationMsg_SetProxyConfig.
+const wchar_t kJSONProxyAutoconfig[] = L"proxy.autoconfig";
+const wchar_t kJSONProxyNoProxy[] = L"proxy.no_proxy";
+const wchar_t kJSONProxyPacUrl[] = L"proxy.pac_url";
+const wchar_t kJSONProxyBypassList[] = L"proxy.bypass_list";
+const wchar_t kJSONProxyServer[] = L"proxy.server";
+}
diff --git a/chrome/common/automation_constants.h b/chrome/common/automation_constants.h
new file mode 100644
index 0000000..9c31bd1
--- /dev/null
+++ b/chrome/common/automation_constants.h
@@ -0,0 +1,19 @@
+// Copyright (c) 2006-2009 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_COMMON_AUTOMATION_CONSTANTS_H__
+#define CHROME_COMMON_AUTOMATION_CONSTANTS_H__
+
+namespace automation {
+// JSON value labels for proxy settings that are passed in via
+// AutomationMsg_SetProxyConfig. These are here since they are used by both
+// AutomationProvider and AutomationProxy.
+extern const wchar_t kJSONProxyAutoconfig[];
+extern const wchar_t kJSONProxyNoProxy[];
+extern const wchar_t kJSONProxyPacUrl[];
+extern const wchar_t kJSONProxyBypassList[];
+extern const wchar_t kJSONProxyServer[];
+}
+
+#endif // CHROME_COMMON_AUTOMATION_CONSTANTS_H__
diff --git a/chrome/common/bindings_policy.h b/chrome/common/bindings_policy.h
new file mode 100644
index 0000000..eccce17
--- /dev/null
+++ b/chrome/common/bindings_policy.h
@@ -0,0 +1,42 @@
+// Copyright (c) 2006-2009 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_COMMON_BINDINGS_POLICY_H__
+#define CHROME_COMMON_BINDINGS_POLICY_H__
+
+// This is a utility class that specifies flag values for the types of
+// JavaScript bindings exposed to renderers.
+class BindingsPolicy {
+ public:
+ enum {
+ // HTML-based UI bindings that allows he js content to send JSON-encoded
+ // data back to the browser process.
+ DOM_UI = 1 << 0,
+ // DOM automation bindings that allows the js content to send JSON-encoded
+ // data back to automation in the parent process. (By default this isn't
+ // allowed unless the app has been started up with the --dom-automation
+ // switch.)
+ DOM_AUTOMATION = 1 << 1,
+ // Bindings that allow access to the external host (through automation).
+ EXTERNAL_HOST = 1 << 2,
+ // Special bindings with privileged APIs for code running in the extension
+ // process.
+ EXTENSION = 1 << 3,
+ };
+
+ static bool is_dom_ui_enabled(int flags) {
+ return (flags & DOM_UI) != 0;
+ }
+ static bool is_dom_automation_enabled(int flags) {
+ return (flags & DOM_AUTOMATION) != 0;
+ }
+ static bool is_external_host_enabled(int flags) {
+ return (flags & EXTERNAL_HOST) != 0;
+ }
+ static bool is_extension_enabled(int flags) {
+ return (flags & EXTENSION) != 0;
+ }
+};
+
+#endif // CHROME_COMMON_BINDINGS_POLICY_H__
diff --git a/chrome/common/bzip2_unittest.cc b/chrome/common/bzip2_unittest.cc
new file mode 100644
index 0000000..0f14205
--- /dev/null
+++ b/chrome/common/bzip2_unittest.cc
@@ -0,0 +1,72 @@
+// Copyright (c) 2006-2008 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.
+
+#if defined(USE_SYSTEM_LIBBZ2)
+#include <bzlib.h>
+#else
+#include "third_party/bzip2/bzlib.h"
+#endif
+
+#include "base/basictypes.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+namespace {
+ class Bzip2Test : public testing::Test {
+ };
+};
+
+// This test does a simple round trip to test that the bzip2 library is
+// present and working.
+TEST(Bzip2Test, Roundtrip) {
+ char input[] = "Test Data, More Test Data, Even More Data of Test";
+ char output[256];
+
+ memset(output, 0, arraysize(output));
+
+ bz_stream stream;
+ stream.bzalloc = NULL;
+ stream.bzfree = NULL;
+ stream.opaque = NULL;
+ int result = BZ2_bzCompressInit(&stream,
+ 9, // 900k block size
+ 0, // quiet
+ 0); // default work factor
+ ASSERT_EQ(BZ_OK, result);
+
+ stream.next_in = input;
+ stream.avail_in = arraysize(input) - 1;
+ stream.next_out = output;
+ stream.avail_out = arraysize(output);
+ do {
+ result = BZ2_bzCompress(&stream, BZ_FINISH);
+ } while (result == BZ_FINISH_OK);
+ ASSERT_EQ(BZ_STREAM_END, result);
+ result = BZ2_bzCompressEnd(&stream);
+ ASSERT_EQ(BZ_OK, result);
+ int written = stream.total_out_lo32;
+
+ // Make sure we wrote something; otherwise not sure what to expect
+ ASSERT_GT(written, 0);
+
+ // Now decompress and check that we got the same thing.
+ result = BZ2_bzDecompressInit(&stream, 0, 0);
+ ASSERT_EQ(BZ_OK, result);
+ char output2[256];
+ memset(output2, 0, arraysize(output2));
+
+ stream.next_in = output;
+ stream.avail_in = written;
+ stream.next_out = output2;
+ stream.avail_out = arraysize(output2);
+
+ do {
+ result = BZ2_bzDecompress(&stream);
+ } while (result == BZ_OK);
+ ASSERT_EQ(result, BZ_STREAM_END);
+ result = BZ2_bzDecompressEnd(&stream);
+ ASSERT_EQ(result, BZ_OK);
+
+ EXPECT_EQ(arraysize(input) - 1, stream.total_out_lo32);
+ EXPECT_STREQ(input, output2);
+}
diff --git a/chrome/common/child_process.cc b/chrome/common/child_process.cc
new file mode 100644
index 0000000..328ca14
--- /dev/null
+++ b/chrome/common/child_process.cc
@@ -0,0 +1,97 @@
+// Copyright (c) 2006-2008 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/common/child_process.h"
+
+#include "app/l10n_util.h"
+#include "base/message_loop.h"
+#include "base/process_util.h"
+#include "base/string_util.h"
+#include "chrome/common/child_thread.h"
+#include "grit/chromium_strings.h"
+
+#if defined(OS_POSIX)
+#include <signal.h>
+
+static void SigUSR1Handler(int signal) { }
+#endif
+
+ChildProcess* ChildProcess::child_process_;
+
+ChildProcess::ChildProcess()
+ : ref_count_(0),
+ shutdown_event_(true, false),
+ io_thread_("Chrome_ChildIOThread") {
+ DCHECK(!child_process_);
+ child_process_ = this;
+
+ io_thread_.StartWithOptions(base::Thread::Options(MessageLoop::TYPE_IO, 0));
+}
+
+ChildProcess::~ChildProcess() {
+ DCHECK(child_process_ == this);
+
+ // Signal this event before destroying the child process. That way all
+ // background threads can cleanup.
+ // For example, in the renderer the RenderThread instances will be able to
+ // notice shutdown before the render process begins waiting for them to exit.
+ shutdown_event_.Signal();
+
+ // Kill the main thread object before nulling child_process_, since
+ // destruction code might depend on it.
+ main_thread_.reset();
+
+ child_process_ = NULL;
+}
+
+void ChildProcess::AddRefProcess() {
+ DCHECK(!main_thread_.get() || // null in unittests.
+ MessageLoop::current() == main_thread_->message_loop());
+ ref_count_++;
+}
+
+void ChildProcess::ReleaseProcess() {
+ DCHECK(!main_thread_.get() || // null in unittests.
+ MessageLoop::current() == main_thread_->message_loop());
+ DCHECK(ref_count_);
+ DCHECK(child_process_);
+ if (--ref_count_)
+ return;
+
+ if (main_thread_.get()) // null in unittests.
+ main_thread_->OnProcessFinalRelease();
+}
+
+base::WaitableEvent* ChildProcess::GetShutDownEvent() {
+ DCHECK(child_process_);
+ return &child_process_->shutdown_event_;
+}
+
+void ChildProcess::WaitForDebugger(const std::wstring& label) {
+#if defined(OS_WIN)
+ std::wstring title = l10n_util::GetString(IDS_PRODUCT_NAME);
+ std::wstring message = label;
+ message += L" starting with pid: ";
+ message += IntToWString(base::GetCurrentProcId());
+ title += L" ";
+ title += label; // makes attaching to process easier
+ ::MessageBox(NULL, message.c_str(), title.c_str(),
+ MB_OK | MB_SETFOREGROUND);
+#elif defined(OS_POSIX)
+ // TODO(playmobil): In the long term, overriding this flag doesn't seem
+ // right, either use our own flag or open a dialog we can use.
+ // This is just to ease debugging in the interim.
+ LOG(WARNING) << label
+ << " ("
+ << getpid()
+ << ") paused waiting for debugger to attach @ pid";
+ // Install a signal handler so that pause can be woken.
+ struct sigaction sa;
+ memset(&sa, 0, sizeof(sa));
+ sa.sa_handler = SigUSR1Handler;
+ sigaction(SIGUSR1, &sa, NULL);
+
+ pause();
+#endif // defined(OS_POSIX)
+}
diff --git a/chrome/common/child_process.h b/chrome/common/child_process.h
new file mode 100644
index 0000000..fb2c660
--- /dev/null
+++ b/chrome/common/child_process.h
@@ -0,0 +1,70 @@
+// Copyright (c) 2006-2008 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_COMMON_CHILD_PROCESS_H__
+#define CHROME_COMMON_CHILD_PROCESS_H__
+
+#include "base/basictypes.h"
+#include "base/scoped_ptr.h"
+#include "base/thread.h"
+#include "base/waitable_event.h"
+#include "chrome/common/child_thread.h"
+
+// Base class for child processes of the browser process (i.e. renderer and
+// plugin host). This is a singleton object for each child process.
+class ChildProcess {
+ public:
+ // Child processes should have an object that derives from this class.
+ ChildProcess();
+ virtual ~ChildProcess();
+
+ // Getter for the child process' main thread.
+ ChildThread* main_thread() { return main_thread_.get(); }
+ void set_main_thread(ChildThread* thread) { main_thread_.reset(thread); }
+
+ MessageLoop* io_message_loop() { return io_thread_.message_loop(); }
+
+ // A global event object that is signalled when the main thread's message
+ // loop exits. This gives background threads a way to observe the main
+ // thread shutting down. This can be useful when a background thread is
+ // waiting for some information from the browser process. If the browser
+ // process goes away prematurely, the background thread can at least notice
+ // the child processes's main thread exiting to determine that it should give
+ // up waiting.
+ // For example, see the renderer code used to implement
+ // webkit_glue::GetCookies.
+ base::WaitableEvent* GetShutDownEvent();
+
+ // These are used for ref-counting the child process. The process shuts
+ // itself down when the ref count reaches 0.
+ // For example, in the renderer process, generally each tab managed by this
+ // process will hold a reference to the process, and release when closed.
+ void AddRefProcess();
+ void ReleaseProcess();
+
+ // Getter for the one ChildProcess object for this process.
+ static ChildProcess* current() { return child_process_; }
+
+ static void WaitForDebugger(const std::wstring& label);
+ private:
+ int ref_count_;
+
+ // An event that will be signalled when we shutdown.
+ base::WaitableEvent shutdown_event_;
+
+ // The thread that handles IO events.
+ base::Thread io_thread_;
+
+ // NOTE: make sure that main_thread_ is listed after shutdown_event_, since
+ // it depends on it (indirectly through IPC::SyncChannel). Same for
+ // io_thread_.
+ scoped_ptr<ChildThread> main_thread_;
+
+ // The singleton instance for this process.
+ static ChildProcess* child_process_;
+
+ DISALLOW_COPY_AND_ASSIGN(ChildProcess);
+};
+
+#endif // CHROME_COMMON_CHILD_PROCESS_H__
diff --git a/chrome/common/child_process_host.cc b/chrome/common/child_process_host.cc
new file mode 100644
index 0000000..bcd0c3d
--- /dev/null
+++ b/chrome/common/child_process_host.cc
@@ -0,0 +1,190 @@
+// Copyright (c) 2010 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/common/child_process_host.h"
+
+#include "base/command_line.h"
+#include "base/histogram.h"
+#include "base/path_service.h"
+#include "chrome/common/child_process_info.h"
+#include "chrome/common/chrome_constants.h"
+#include "chrome/common/chrome_paths_internal.h"
+#include "chrome/common/chrome_switches.h"
+#include "chrome/common/plugin_messages.h"
+
+#if defined(OS_LINUX)
+#include "base/linux_util.h"
+#endif // OS_LINUX
+
+ChildProcessHost::ChildProcessHost()
+ : ALLOW_THIS_IN_INITIALIZER_LIST(listener_(this)),
+ opening_channel_(false) {
+}
+
+ChildProcessHost::~ChildProcessHost() {
+}
+
+// static
+FilePath ChildProcessHost::GetChildPath(bool allow_self) {
+ FilePath child_path;
+
+ child_path = CommandLine::ForCurrentProcess()->GetSwitchValuePath(
+ switches::kBrowserSubprocessPath);
+ if (!child_path.empty())
+ return child_path;
+
+#if defined(OS_MACOSX)
+ // On the Mac, the child executable lives at a predefined location within
+ // the app bundle's versioned directory.
+ return chrome::GetVersionedDirectory().
+ Append(chrome::kHelperProcessExecutablePath);
+#endif
+
+#if defined(OS_LINUX)
+ // Use /proc/self/exe rather than our known binary path so updates
+ // can't swap out the binary from underneath us.
+ if (allow_self)
+ return FilePath("/proc/self/exe");
+#endif
+
+ // On most platforms, the child executable is the same as the current
+ // executable.
+ PathService::Get(base::FILE_EXE, &child_path);
+ return child_path;
+}
+
+#if defined(OS_WIN)
+// static
+void ChildProcessHost::PreCacheFont(LOGFONT font) {
+ // If a child process is running in a sandbox, GetTextMetrics()
+ // can sometimes fail. If a font has not been loaded
+ // previously, GetTextMetrics() will try to load the font
+ // from the font file. However, the sandboxed process does
+ // not have permissions to access any font files and
+ // the call fails. So we make the browser pre-load the
+ // font for us by using a dummy call to GetTextMetrics of
+ // the same font.
+
+ // Maintain a circular queue for the fonts and DCs to be cached.
+ // font_index maintains next available location in the queue.
+ static const int kFontCacheSize = 32;
+ static HFONT fonts[kFontCacheSize] = {0};
+ static HDC hdcs[kFontCacheSize] = {0};
+ static size_t font_index = 0;
+
+ UMA_HISTOGRAM_COUNTS_100("Memory.CachedFontAndDC",
+ fonts[kFontCacheSize-1] ? kFontCacheSize : static_cast<int>(font_index));
+
+ HDC hdc = GetDC(NULL);
+ HFONT font_handle = CreateFontIndirect(&font);
+ DCHECK(NULL != font_handle);
+
+ HGDIOBJ old_font = SelectObject(hdc, font_handle);
+ DCHECK(NULL != old_font);
+
+ TEXTMETRIC tm;
+ BOOL ret = GetTextMetrics(hdc, &tm);
+ DCHECK(ret);
+
+ if (fonts[font_index] || hdcs[font_index]) {
+ // We already have too many fonts, we will delete one and take it's place.
+ DeleteObject(fonts[font_index]);
+ ReleaseDC(NULL, hdcs[font_index]);
+ }
+
+ fonts[font_index] = font_handle;
+ hdcs[font_index] = hdc;
+ font_index = (font_index + 1) % kFontCacheSize;
+}
+#endif // OS_WIN
+
+
+bool ChildProcessHost::CreateChannel() {
+ channel_id_ = ChildProcessInfo::GenerateRandomChannelID(this);
+ channel_.reset(new IPC::Channel(
+ channel_id_, IPC::Channel::MODE_SERVER, &listener_));
+ if (!channel_->Connect())
+ return false;
+
+ // Make sure these messages get sent first.
+#if defined(IPC_MESSAGE_LOG_ENABLED)
+ bool enabled = IPC::Logging::current()->Enabled();
+ SendOnChannel(new PluginProcessMsg_SetIPCLoggingEnabled(enabled));
+#endif
+
+ SendOnChannel(new PluginProcessMsg_AskBeforeShutdown());
+
+ opening_channel_ = true;
+
+ return true;
+}
+
+void ChildProcessHost::InstanceCreated() {
+ Notify(NotificationType::CHILD_INSTANCE_CREATED);
+}
+
+bool ChildProcessHost::SendOnChannel(IPC::Message* msg) {
+ if (!channel_.get()) {
+ delete msg;
+ return false;
+ }
+ return channel_->Send(msg);
+}
+
+void ChildProcessHost::OnChildDied() {
+ delete this;
+}
+
+ChildProcessHost::ListenerHook::ListenerHook(ChildProcessHost* host)
+ : host_(host) {
+}
+
+void ChildProcessHost::ListenerHook::OnMessageReceived(
+ const IPC::Message& msg) {
+#ifdef IPC_MESSAGE_LOG_ENABLED
+ IPC::Logging* logger = IPC::Logging::current();
+ if (msg.type() == IPC_LOGGING_ID) {
+ logger->OnReceivedLoggingMessage(msg);
+ return;
+ }
+
+ if (logger->Enabled())
+ logger->OnPreDispatchMessage(msg);
+#endif
+
+ bool handled = host_->InterceptMessageFromChild(msg);
+
+ if (!handled) {
+ if (msg.type() == PluginProcessHostMsg_ShutdownRequest::ID) {
+ if (host_->CanShutdown())
+ host_->SendOnChannel(new PluginProcessMsg_Shutdown());
+ } else {
+ host_->OnMessageReceived(msg);
+ }
+ }
+
+#ifdef IPC_MESSAGE_LOG_ENABLED
+ if (logger->Enabled())
+ logger->OnPostDispatchMessage(msg, host_->channel_id_);
+#endif
+}
+
+void ChildProcessHost::ListenerHook::OnChannelConnected(int32 peer_pid) {
+ host_->opening_channel_ = false;
+ host_->OnChannelConnected(peer_pid);
+ // Notify in the main loop of the connection.
+ host_->Notify(NotificationType::CHILD_PROCESS_HOST_CONNECTED);
+}
+
+void ChildProcessHost::ListenerHook::OnChannelError() {
+ host_->opening_channel_ = false;
+ host_->OnChannelError();
+
+ // This will delete host_, which will also destroy this!
+ host_->OnChildDied();
+}
+
+void ChildProcessHost::ForceShutdown() {
+ SendOnChannel(new PluginProcessMsg_Shutdown());
+}
diff --git a/chrome/common/child_process_host.h b/chrome/common/child_process_host.h
new file mode 100644
index 0000000..865a1ac
--- /dev/null
+++ b/chrome/common/child_process_host.h
@@ -0,0 +1,123 @@
+// Copyright (c) 2010 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_COMMON_CHILD_PROCESS_HOST_H_
+#define CHROME_COMMON_CHILD_PROCESS_HOST_H_
+
+#include <list>
+#include <string>
+
+// Must be included early (e.g. before chrome/common/plugin_messages.h)
+#include "ipc/ipc_logging.h"
+
+// Putting this before ipc_logging.h does not work (OS_WIN isn't defined)
+#if defined(OS_WIN)
+#include <windows.h>
+#endif // defined(OS_WIN)
+
+#include "base/basictypes.h"
+#include "base/file_path.h"
+#include "base/scoped_ptr.h"
+#include "chrome/common/notification_type.h"
+#include "ipc/ipc_channel.h"
+
+
+class CommandLine;
+
+// Provides common functionality for hosting a child process and processing IPC
+// messages between the host and the child process. Subclasses are responsible
+// for the actual launching and terminating of the child processes.
+//
+class ChildProcessHost : public IPC::Channel::Listener {
+ public:
+ virtual ~ChildProcessHost();
+
+ // Returns the pathname to be used for a child process. If a subprocess
+ // pathname was specified on the command line, that will be used. Otherwise,
+ // the default child process pathname will be returned. On most platforms,
+ // this will be the same as the currently-executing process.
+ //
+ // The argument allow_self is used on Linux to indicate that we allow us to
+ // fork from /proc/self/exe rather than using the "real" app path. This
+ // prevents autoupdate from confusing us if it changes the file out from
+ // under us. You will generally want to set this to true, except when there
+ // is an override to the command line (for example, we're forking a renderer
+ // in gdb). In this case, you'd use GetChildPath to get the real executable
+ // file name, and then prepend the GDB command to the command line.
+ //
+ // On failure, returns an empty FilePath.
+ static FilePath GetChildPath(bool allow_self);
+
+#if defined(OS_WIN)
+ // See comments in the cc file. This is a common hack needed for a process
+ // hosting a sandboxed child process. Hence it lives in this file.
+ static void PreCacheFont(LOGFONT font);
+#endif // defined(OS_WIN)
+
+ protected:
+ ChildProcessHost();
+
+ // A helper method to send an IPC message to the child on the channel.
+ // It behavies just like IPC::Message::Sender::Send. The implementor takes
+ // ownership of the given Message regardless of whether or not this method
+ // succeeds. This class does not implement IPC::Message::Sender to prevent
+ // conflicts with subclasses which indirectly could inherit from
+ // IPC::Message::Sender.
+ bool SendOnChannel(IPC::Message* msg);
+
+ // Derived classes return true if it's ok to shut down the child process.
+ virtual bool CanShutdown() = 0;
+
+ // Send the shutdown message to the child process.
+ // Does not check if CanShutdown is true.
+ virtual void ForceShutdown();
+
+ // Creates the IPC channel. Returns true iff it succeeded.
+ virtual bool CreateChannel();
+
+ // Notifies us that an instance has been created on this child process.
+ virtual void InstanceCreated();
+
+ // IPC::Channel::Listener implementation:
+ virtual void OnMessageReceived(const IPC::Message& msg) { }
+ virtual void OnChannelConnected(int32 peer_pid) { }
+ virtual void OnChannelError() { }
+
+ bool opening_channel() { return opening_channel_; }
+ const std::string& channel_id() { return channel_id_; }
+ IPC::Channel* channel() { return channel_.get(); }
+
+ // Called when the child process goes away.
+ virtual void OnChildDied();
+ // Allows the derived implementation to intercept a message before it is
+ // handed to the IPC::Channel::Listener::OnMessageReceived implementation.
+ virtual bool InterceptMessageFromChild(const IPC::Message& msg) {
+ return false;
+ }
+ // Subclasses can implement specific notification methods.
+ virtual void Notify(NotificationType type) { }
+
+ private:
+ // By using an internal class as the IPC::Channel::Listener, we can intercept
+ // OnMessageReceived/OnChannelConnected and do our own processing before
+ // calling the subclass' implementation.
+ class ListenerHook : public IPC::Channel::Listener {
+ public:
+ explicit ListenerHook(ChildProcessHost* host);
+ virtual void OnMessageReceived(const IPC::Message& msg);
+ virtual void OnChannelConnected(int32 peer_pid);
+ virtual void OnChannelError();
+ private:
+ ChildProcessHost* host_;
+ };
+
+ ListenerHook listener_;
+
+ bool opening_channel_; // True while we're waiting the channel to be opened.
+ scoped_ptr<IPC::Channel> channel_;
+ std::string channel_id_;
+};
+
+#endif // CHROME_COMMON_CHILD_PROCESS_HOST_H_
+
diff --git a/chrome/common/child_process_info.cc b/chrome/common/child_process_info.cc
new file mode 100644
index 0000000..f08cb55
--- /dev/null
+++ b/chrome/common/child_process_info.cc
@@ -0,0 +1,130 @@
+// Copyright (c) 2009 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/common/child_process_info.h"
+
+#include <limits>
+
+#include "app/l10n_util.h"
+#include "base/atomicops.h"
+#include "base/i18n/rtl.h"
+#include "base/logging.h"
+#include "base/process_util.h"
+#include "base/rand_util.h"
+#include "base/string_util.h"
+#include "grit/generated_resources.h"
+
+ChildProcessInfo::ChildProcessInfo(const ChildProcessInfo& original)
+ : type_(original.type_),
+ name_(original.name_),
+ version_(original.version_),
+ id_(original.id_),
+ process_(original.process_) {
+}
+
+ChildProcessInfo::~ChildProcessInfo() {
+}
+
+ChildProcessInfo& ChildProcessInfo::operator=(
+ const ChildProcessInfo& original) {
+ if (&original != this) {
+ type_ = original.type_;
+ name_ = original.name_;
+ version_ = original.version_;
+ id_ = original.id_;
+ process_ = original.process_;
+ }
+ return *this;
+}
+
+std::wstring ChildProcessInfo::GetTypeNameInEnglish(
+ ChildProcessInfo::ProcessType type) {
+ switch (type) {
+ case BROWSER_PROCESS:
+ return L"Browser";
+ case RENDER_PROCESS:
+ return L"Tab";
+ case PLUGIN_PROCESS:
+ return L"Plug-in";
+ case WORKER_PROCESS:
+ return L"Web Worker";
+ case UTILITY_PROCESS:
+ return L"Utility";
+ case PROFILE_IMPORT_PROCESS:
+ return L"Profile Import helper";
+ case ZYGOTE_PROCESS:
+ return L"Zygote";
+ case SANDBOX_HELPER_PROCESS:
+ return L"Sandbox helper";
+ case NACL_LOADER_PROCESS:
+ return L"Native Client module";
+ case NACL_BROKER_PROCESS:
+ return L"Native Client broker";
+ case GPU_PROCESS:
+ return L"GPU";
+ case UNKNOWN_PROCESS:
+ default:
+ DCHECK(false) << "Unknown child process type!";
+ return L"Unknown";
+ }
+}
+
+std::wstring ChildProcessInfo::GetLocalizedTitle() const {
+ std::wstring title = name_;
+ if (type_ == ChildProcessInfo::PLUGIN_PROCESS && title.empty())
+ title = l10n_util::GetString(IDS_TASK_MANAGER_UNKNOWN_PLUGIN_NAME);
+
+ // Explicitly mark name as LTR if there is no strong RTL character,
+ // to avoid the wrong concatenation result similar to "!Yahoo! Mail: the
+ // best web-based Email: NIGULP", in which "NIGULP" stands for the Hebrew
+ // or Arabic word for "plugin".
+ base::i18n::AdjustStringForLocaleDirection(title, &title);
+
+ int message_id;
+ if (type_ == ChildProcessInfo::PLUGIN_PROCESS) {
+ message_id = IDS_TASK_MANAGER_PLUGIN_PREFIX;
+ return l10n_util::GetStringF(message_id, title, version_.c_str());
+ } else if (type_ == ChildProcessInfo::WORKER_PROCESS) {
+ message_id = IDS_TASK_MANAGER_WORKER_PREFIX;
+ } else if (type_ == ChildProcessInfo::UTILITY_PROCESS) {
+ message_id = IDS_TASK_MANAGER_UTILITY_PREFIX;
+ } else if (type_ == ChildProcessInfo::PROFILE_IMPORT_PROCESS) {
+ message_id = IDS_TASK_MANAGER_PROFILE_IMPORT_PREFIX;
+ } else if (type_ == ChildProcessInfo::NACL_LOADER_PROCESS) {
+ message_id = IDS_TASK_MANAGER_NACL_PREFIX;
+ } else if (type_ == ChildProcessInfo::NACL_BROKER_PROCESS) {
+ message_id = IDS_TASK_MANAGER_NACL_BROKER_PREFIX;
+ } else {
+ DCHECK(false) << "Need localized name for child process type.";
+ return title;
+ }
+
+ return l10n_util::GetStringF(message_id, title);
+}
+
+ChildProcessInfo::ChildProcessInfo(ProcessType type, int id) : type_(type) {
+ if (id == -1)
+ id_ = GenerateChildProcessUniqueId();
+ else
+ id_ = id;
+}
+
+std::string ChildProcessInfo::GenerateRandomChannelID(void* instance) {
+ // Note: the string must start with the current process id, this is how
+ // child processes determine the pid of the parent.
+ // Build the channel ID. This is composed of a unique identifier for the
+ // parent browser process, an identifier for the child instance, and a random
+ // component. We use a random component so that a hacked child process can't
+ // cause denial of service by causing future named pipe creation to fail.
+ return StringPrintf("%d.%p.%d",
+ base::GetCurrentProcId(), instance,
+ base::RandInt(0, std::numeric_limits<int>::max()));
+}
+
+// static
+int ChildProcessInfo::GenerateChildProcessUniqueId() {
+ // This function must be threadsafe.
+ static base::subtle::Atomic32 last_unique_child_id = 0;
+ return base::subtle::NoBarrier_AtomicIncrement(&last_unique_child_id, 1);
+}
diff --git a/chrome/common/child_process_info.h b/chrome/common/child_process_info.h
new file mode 100644
index 0000000..bc36c18
--- /dev/null
+++ b/chrome/common/child_process_info.h
@@ -0,0 +1,113 @@
+// Copyright (c) 2009 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_COMMON_CHILD_PROCESS_INFO_H_
+#define CHROME_COMMON_CHILD_PROCESS_INFO_H_
+
+#include <string>
+
+#include "base/process.h"
+
+// Holds information about a child process.
+class ChildProcessInfo {
+ public:
+ // NOTE: Do not remove or reorder the elements in this enum, and only add new
+ // items at the end. We depend on these specific values in a histogram.
+ enum ProcessType {
+ UNKNOWN_PROCESS = 1,
+ BROWSER_PROCESS,
+ RENDER_PROCESS,
+ PLUGIN_PROCESS,
+ WORKER_PROCESS,
+ NACL_LOADER_PROCESS,
+ UTILITY_PROCESS,
+ PROFILE_IMPORT_PROCESS,
+ ZYGOTE_PROCESS,
+ SANDBOX_HELPER_PROCESS,
+ NACL_BROKER_PROCESS,
+ GPU_PROCESS
+ };
+
+ ChildProcessInfo(const ChildProcessInfo& original);
+ virtual ~ChildProcessInfo();
+
+ ChildProcessInfo& operator=(const ChildProcessInfo& original);
+
+ // Returns the type of the process.
+ ProcessType type() const { return type_; }
+
+ // Returns the name of the process. i.e. for plugins it might be Flash, while
+ // for workers it might be the domain that it's from.
+ std::wstring name() const { return name_; }
+
+ // Returns the version of the exe, this only appliest to plugins. Otherwise
+ // the string is empty.
+ std::wstring version() const { return version_; }
+
+ // Getter to the process handle.
+ base::ProcessHandle handle() const { return process_.handle(); }
+
+ // The unique identifier for this child process. This identifier is NOT a
+ // process ID, and will be unique for all types of child process for
+ // one run of the browser.
+ int id() const { return id_; }
+
+ void SetProcessBackgrounded() const { process_.SetProcessBackgrounded(true); }
+
+ // Returns an English name of the process type, should only be used for non
+ // user-visible strings, or debugging pages like about:memory.
+ static std::wstring GetTypeNameInEnglish(ProcessType type);
+
+ // Returns a localized title for the child process. For example, a plugin
+ // process would be "Plug-in: Flash" when name is "Flash".
+ std::wstring GetLocalizedTitle() const;
+
+ // We define the < operator so that the ChildProcessInfo can be used as a key
+ // in a std::map.
+ bool operator <(const ChildProcessInfo& rhs) const {
+ if (process_.handle() != rhs.process_.handle())
+ return process_ .handle() < rhs.process_.handle();
+ return false;
+ }
+
+ bool operator ==(const ChildProcessInfo& rhs) const {
+ return process_.handle() == rhs.process_.handle();
+ }
+
+ // Generates a unique channel name for a child renderer/plugin process.
+ // The "instance" pointer value is baked into the channel id.
+ static std::string GenerateRandomChannelID(void* instance);
+
+ // Returns a unique ID to identify a child process. On construction, this
+ // function will be used to generate the id_, but it is also used to generate
+ // IDs for the RenderProcessHost, which doesn't inherit from us, and whose IDs
+ // must be unique for all child processes.
+ //
+ // This function is threadsafe since RenderProcessHost is on the UI thread,
+ // but normally this will be used on the IO thread.
+ static int GenerateChildProcessUniqueId();
+
+ protected:
+ // Derived objects need to use this constructor so we know what type we are.
+ // If the caller has already generated a unique ID for this child process,
+ // it should pass it as the second argument. Otherwise, -1 should be passed
+ // and a unique ID will be automatically generated.
+ ChildProcessInfo(ProcessType type, int id);
+
+ void set_type(ProcessType type) { type_ = type; }
+ void set_name(const std::wstring& name) { name_ = name; }
+ void set_version(const std::wstring& ver) { version_ = ver; }
+ void set_handle(base::ProcessHandle handle) { process_.set_handle(handle); }
+
+ private:
+ ProcessType type_;
+ std::wstring name_;
+ std::wstring version_;
+ int id_;
+
+ // The handle to the process.
+ mutable base::Process process_;
+};
+
+#endif // CHROME_COMMON_CHILD_PROCESS_INFO_H_
diff --git a/chrome/common/child_process_logging.h b/chrome/common/child_process_logging.h
new file mode 100644
index 0000000..84a288c
--- /dev/null
+++ b/chrome/common/child_process_logging.h
@@ -0,0 +1,81 @@
+// Copyright (c) 2010 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_COMMON_CHILD_PROCESS_LOGGING_H_
+#define CHROME_COMMON_CHILD_PROCESS_LOGGING_H_
+
+#include <set>
+#include <string>
+
+#include "base/basictypes.h"
+#include "chrome/common/gpu_info.h"
+#include "googleurl/src/gurl.h"
+
+#if defined(OS_WIN)
+// The maximum number of active extensions we will report.
+// Also used in chrome/app, but we define it here to avoid a common->app
+// dependency.
+static const int kMaxReportedActiveExtensions = 10;
+#endif
+
+namespace child_process_logging {
+
+// Sets the URL that is logged if the child process crashes. Use GURL() to clear
+// the URL.
+void SetActiveURL(const GURL& url);
+
+// Sets the Client ID that is used as GUID if a Chrome process crashes.
+void SetClientId(const std::string& client_id);
+
+// Sets the list of "active" extensions in this process. We overload "active" to
+// mean different things depending on the process type:
+// - browser: all enabled extensions
+// - renderer: the unique set of extension ids from all content scripts
+// - extension: the id of each extension running in this process (there can be
+// multiple because of process collapsing).
+void SetActiveExtensions(const std::set<std::string>& extension_ids);
+
+// Sets the data on the gpu to send along with crash reports.
+void SetGpuInfo(const GPUInfo& gpu_info);
+
+// Simple wrapper class that sets the active URL in it's constructor and clears
+// the active URL in the destructor.
+class ScopedActiveURLSetter {
+ public:
+ explicit ScopedActiveURLSetter(const GURL& url) {
+ SetActiveURL(url);
+ }
+
+ ~ScopedActiveURLSetter() {
+ SetActiveURL(GURL());
+ }
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(ScopedActiveURLSetter);
+};
+
+} // namespace child_process_logging
+
+#if defined(OS_MACOSX) && __OBJC__
+
+@class NSString;
+
+typedef void (*SetCrashKeyValueFuncPtr)(NSString*, NSString*);
+typedef void (*ClearCrashKeyValueFuncPtr)(NSString*);
+
+namespace child_process_logging {
+void SetCrashKeyFunctions(SetCrashKeyValueFuncPtr set_key_func,
+ ClearCrashKeyValueFuncPtr clear_key_func);
+void SetActiveURLImpl(const GURL& url,
+ SetCrashKeyValueFuncPtr set_key_func,
+ ClearCrashKeyValueFuncPtr clear_key_func);
+
+extern const int kMaxNumCrashURLChunks;
+extern const int kMaxNumURLChunkValueLength;
+extern const char *kUrlChunkFormatStr;
+} // namespace child_process_logging
+
+#endif // defined(OS_MACOSX) && __OBJC__
+
+#endif // CHROME_COMMON_CHILD_PROCESS_LOGGING_H_
diff --git a/chrome/common/child_process_logging_linux.cc b/chrome/common/child_process_logging_linux.cc
new file mode 100644
index 0000000..94cb34b
--- /dev/null
+++ b/chrome/common/child_process_logging_linux.cc
@@ -0,0 +1,42 @@
+// Copyright (c) 2010 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/common/child_process_logging.h"
+
+#include "base/logging.h"
+#include "base/string_util.h"
+#include "chrome/common/gpu_info.h"
+#include "chrome/installer/util/google_update_settings.h"
+#include "googleurl/src/gurl.h"
+
+namespace child_process_logging {
+
+// We use a static string to hold the most recent active url. If we crash, the
+// crash handler code will send the contents of this string to the browser.
+std::string active_url;
+
+void SetActiveURL(const GURL& url) {
+ active_url = url.possibly_invalid_spec();
+}
+
+void SetClientId(const std::string& client_id) {
+ std::string str(client_id);
+ ReplaceSubstringsAfterOffset(&str, 0, "-", "");
+
+ if (str.empty())
+ return;
+
+ std::wstring wstr = ASCIIToWide(str);
+ GoogleUpdateSettings::SetMetricsId(wstr);
+}
+
+void SetActiveExtensions(const std::set<std::string>& extension_ids) {
+ // TODO(port)
+}
+
+void SetGpuInfo(const GPUInfo& gpu_info) {
+ // TODO(rlp): Bug 38737.
+}
+
+} // namespace child_process_logging
diff --git a/chrome/common/child_process_logging_mac.mm b/chrome/common/child_process_logging_mac.mm
new file mode 100644
index 0000000..f0356cd
--- /dev/null
+++ b/chrome/common/child_process_logging_mac.mm
@@ -0,0 +1,136 @@
+// Copyright (c) 2009 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/common/child_process_logging.h"
+
+#import <Foundation/Foundation.h>
+
+#include "base/string_util.h"
+#include "chrome/common/gpu_info.h"
+#include "chrome/installer/util/google_update_settings.h"
+#include "googleurl/src/gurl.h"
+
+namespace child_process_logging {
+
+const int kMaxNumCrashURLChunks = 8;
+const int kMaxNumURLChunkValueLength = 255;
+const char *kUrlChunkFormatStr = "url-chunk-%d";
+const char *kGuidParamName = "guid";
+const char *kGPUVendorIdParamName = "vendid";
+const char *kGPUDeviceIdParamName = "devid";
+const char *kGPUDriverVersionParamName = "driver";
+const char *kGPUPixelShaderVersionParamName = "psver";
+const char *kGPUVertexShaderVersionParamName = "vsver";
+
+static SetCrashKeyValueFuncPtr g_set_key_func;
+static ClearCrashKeyValueFuncPtr g_clear_key_func;
+
+void SetCrashKeyFunctions(SetCrashKeyValueFuncPtr set_key_func,
+ ClearCrashKeyValueFuncPtr clear_key_func) {
+ g_set_key_func = set_key_func;
+ g_clear_key_func = clear_key_func;
+}
+
+void SetActiveURLImpl(const GURL& url,
+ SetCrashKeyValueFuncPtr set_key_func,
+ ClearCrashKeyValueFuncPtr clear_key_func) {
+
+ NSString *kUrlChunkFormatStr_utf8 = [NSString
+ stringWithUTF8String:kUrlChunkFormatStr];
+
+ // First remove any old url chunks we might have lying around.
+ for (int i = 0; i < kMaxNumCrashURLChunks; i++) {
+ // On Windows the url-chunk items are 1-based, so match that.
+ NSString *key = [NSString stringWithFormat:kUrlChunkFormatStr_utf8, i+1];
+ clear_key_func(key);
+ }
+
+ const std::string& raw_url_utf8 = url.possibly_invalid_spec();
+ NSString *raw_url = [NSString stringWithUTF8String:raw_url_utf8.c_str()];
+ size_t raw_url_length = [raw_url length];
+
+ // Bail on zero-length URLs.
+ if (raw_url_length == 0) {
+ return;
+ }
+
+ // Parcel the URL up into up to 8, 255 byte segments.
+ size_t start_ofs = 0;
+ for (int i = 0;
+ i < kMaxNumCrashURLChunks && start_ofs < raw_url_length;
+ ++i) {
+
+ // On Windows the url-chunk items are 1-based, so match that.
+ NSString *key = [NSString stringWithFormat:kUrlChunkFormatStr_utf8, i+1];
+ NSRange range;
+ range.location = start_ofs;
+ range.length = std::min((size_t)kMaxNumURLChunkValueLength,
+ raw_url_length - start_ofs);
+ NSString *value = [raw_url substringWithRange:range];
+ set_key_func(key, value);
+
+ // Next chunk.
+ start_ofs += kMaxNumURLChunkValueLength;
+ }
+}
+
+void SetClientIdImpl(const std::string& client_id,
+ SetCrashKeyValueFuncPtr set_key_func) {
+ NSString *key = [NSString stringWithUTF8String:kGuidParamName];
+ NSString *value = [NSString stringWithUTF8String:client_id.c_str()];
+ set_key_func(key, value);
+}
+
+void SetActiveURL(const GURL& url) {
+ if (g_set_key_func && g_clear_key_func)
+ SetActiveURLImpl(url, g_set_key_func, g_clear_key_func);
+}
+
+void SetClientId(const std::string& client_id) {
+ std::string str(client_id);
+ ReplaceSubstringsAfterOffset(&str, 0, "-", "");
+
+ if (g_set_key_func)
+ SetClientIdImpl(str, g_set_key_func);
+
+ std::wstring wstr = ASCIIToWide(str);
+ GoogleUpdateSettings::SetMetricsId(wstr);
+}
+
+void SetActiveExtensions(const std::set<std::string>& extension_ids) {
+ // TODO(port)
+}
+
+void SetGpuKeyValue(const char* param_name, const std::string& value_str,
+ SetCrashKeyValueFuncPtr set_key_func) {
+ NSString *key = [NSString stringWithUTF8String:param_name];
+ NSString *value = [NSString stringWithUTF8String:value_str.c_str()];
+ set_key_func(key, value);
+}
+
+void SetGpuInfoImpl(const GPUInfo& gpu_info,
+ SetCrashKeyValueFuncPtr set_key_func) {
+ SetGpuKeyValue(kGPUVendorIdParamName,
+ UintToString(gpu_info.vendor_id()),
+ set_key_func);
+ SetGpuKeyValue(kGPUDeviceIdParamName,
+ UintToString(gpu_info.device_id()),
+ set_key_func);
+ SetGpuKeyValue(kGPUDriverVersionParamName,
+ WideToASCII(gpu_info.driver_version()),
+ set_key_func);
+ SetGpuKeyValue(kGPUPixelShaderVersionParamName,
+ UintToString(gpu_info.pixel_shader_version()),
+ set_key_func);
+ SetGpuKeyValue(kGPUVertexShaderVersionParamName,
+ UintToString(gpu_info.vertex_shader_version()),
+ set_key_func);
+}
+
+void SetGpuInfo(const GPUInfo& gpu_info) {
+ if (g_set_key_func)
+ SetGpuInfoImpl(gpu_info, g_set_key_func);
+}
+
+} // namespace child_process_logging
diff --git a/chrome/common/child_process_logging_mac_unittest.mm b/chrome/common/child_process_logging_mac_unittest.mm
new file mode 100644
index 0000000..a751287
--- /dev/null
+++ b/chrome/common/child_process_logging_mac_unittest.mm
@@ -0,0 +1,141 @@
+// Copyright (c) 2009 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/common/child_process_logging.h"
+
+#import <Foundation/Foundation.h>
+
+#include "base/logging.h"
+#include "testing/gtest/include/gtest/gtest.h"
+#include "testing/platform_test.h"
+
+typedef PlatformTest ChildProcessLoggingTest;
+
+namespace {
+
+// Class to mock breakpad's setkeyvalue/clearkeyvalue functions needed for
+// SetActiveRendererURLImpl.
+// The Keys are stored in a static dictionary and methods are provided to
+// verify correctness.
+class MockBreakpadKeyValueStore {
+ public:
+ MockBreakpadKeyValueStore() {
+ // Only one of these objects can be active at once.
+ DCHECK(dict == NULL);
+ dict = [[NSMutableDictionary alloc] init];
+ }
+
+ ~MockBreakpadKeyValueStore() {
+ // Only one of these objects can be active at once.
+ DCHECK(dict != NULL);
+ [dict release];
+ dict = NULL;
+ }
+
+ static void SetKeyValue(NSString* key, NSString* value) {
+ DCHECK(dict != NULL);
+ [dict setObject:value forKey:key];
+ }
+
+ static void ClearKeyValue(NSString *key) {
+ DCHECK(dict != NULL);
+ [dict removeObjectForKey:key];
+ }
+
+ int CountDictionaryEntries() {
+ return [dict count];
+ }
+
+ bool VerifyDictionaryContents(const std::string &url) {
+ using child_process_logging::kMaxNumCrashURLChunks;
+ using child_process_logging::kMaxNumURLChunkValueLength;
+ using child_process_logging::kUrlChunkFormatStr;
+
+ int num_url_chunks = CountDictionaryEntries();
+ EXPECT_TRUE(num_url_chunks <= kMaxNumCrashURLChunks);
+
+ NSString *kUrlChunkFormatStr_utf8 = [NSString
+ stringWithUTF8String:kUrlChunkFormatStr];
+
+ NSString *accumulated_url = @"";
+ for (int i = 0; i < num_url_chunks; ++i) {
+ // URL chunk names are 1-based.
+ NSString *key = [NSString stringWithFormat:kUrlChunkFormatStr_utf8, i+1];
+ EXPECT_TRUE(key != NULL);
+ NSString *value = [dict objectForKey:key];
+ EXPECT_TRUE([value length] > 0);
+ EXPECT_TRUE([value length] <= (unsigned)kMaxNumURLChunkValueLength);
+ accumulated_url = [accumulated_url stringByAppendingString:value];
+ }
+
+ NSString *expected_url = [NSString stringWithUTF8String:url.c_str()];
+ return([accumulated_url isEqualToString:expected_url]);
+ }
+
+ private:
+ static NSMutableDictionary* dict;
+ DISALLOW_COPY_AND_ASSIGN(MockBreakpadKeyValueStore);
+};
+
+// static
+NSMutableDictionary* MockBreakpadKeyValueStore::dict;
+
+} // namespace
+
+// Call through to SetActiveURLImpl using the functions from
+// MockBreakpadKeyValueStore.
+void SetActiveURLWithMock(const GURL& url) {
+ using child_process_logging::SetActiveURLImpl;
+
+ SetCrashKeyValueFuncPtr setFunc = MockBreakpadKeyValueStore::SetKeyValue;
+ ClearCrashKeyValueFuncPtr clearFunc =
+ MockBreakpadKeyValueStore::ClearKeyValue;
+
+ SetActiveURLImpl(url, setFunc, clearFunc);
+}
+
+TEST_F(ChildProcessLoggingTest, TestUrlSplitting) {
+ using child_process_logging::kMaxNumCrashURLChunks;
+ using child_process_logging::kMaxNumURLChunkValueLength;
+
+ const std::string short_url("http://abc/");
+ std::string long_url("http://");
+ std::string overflow_url("http://");
+
+ long_url += std::string(kMaxNumURLChunkValueLength * 2, 'a');
+ long_url += "/";
+
+ int max_num_chars_stored_in_dump = kMaxNumURLChunkValueLength *
+ kMaxNumCrashURLChunks;
+ overflow_url += std::string(max_num_chars_stored_in_dump + 1, 'a');
+ overflow_url += "/";
+
+ // Check that Clearing NULL URL works.
+ MockBreakpadKeyValueStore mock;
+ SetActiveURLWithMock(GURL());
+ EXPECT_EQ(mock.CountDictionaryEntries(), 0);
+
+ // Check that we can set a URL.
+ SetActiveURLWithMock(GURL(short_url.c_str()));
+ EXPECT_TRUE(mock.VerifyDictionaryContents(short_url));
+ EXPECT_EQ(mock.CountDictionaryEntries(), 1);
+ SetActiveURLWithMock(GURL());
+ EXPECT_EQ(mock.CountDictionaryEntries(), 0);
+
+ // Check that we can replace a long url with a short url.
+ SetActiveURLWithMock(GURL(long_url.c_str()));
+ EXPECT_TRUE(mock.VerifyDictionaryContents(long_url));
+ SetActiveURLWithMock(GURL(short_url.c_str()));
+ EXPECT_TRUE(mock.VerifyDictionaryContents(short_url));
+ SetActiveURLWithMock(GURL());
+ EXPECT_EQ(mock.CountDictionaryEntries(), 0);
+
+
+ // Check that overflow works correctly.
+ SetActiveURLWithMock(GURL(overflow_url.c_str()));
+ EXPECT_TRUE(mock.VerifyDictionaryContents(
+ overflow_url.substr(0, max_num_chars_stored_in_dump)));
+ SetActiveURLWithMock(GURL());
+ EXPECT_EQ(mock.CountDictionaryEntries(), 0);
+}
diff --git a/chrome/common/child_process_logging_win.cc b/chrome/common/child_process_logging_win.cc
new file mode 100644
index 0000000..1b18e6e
--- /dev/null
+++ b/chrome/common/child_process_logging_win.cc
@@ -0,0 +1,115 @@
+// Copyright (c) 2010 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/common/child_process_logging.h"
+
+#include <windows.h>
+
+#include "base/string_util.h"
+#include "base/utf_string_conversions.h"
+#include "chrome/common/chrome_constants.h"
+#include "chrome/installer/util/google_update_settings.h"
+#include "googleurl/src/gurl.h"
+
+namespace child_process_logging {
+// exported in breakpad_win.cc: void __declspec(dllexport) __cdecl SetActiveURL.
+typedef void (__cdecl *MainSetActiveURL)(const wchar_t*);
+
+// exported in breakpad_win.cc: void __declspec(dllexport) __cdecl SetClientId.
+typedef void (__cdecl *MainSetClientId)(const wchar_t*);
+
+// exported in breakpad_win.cc:
+// void __declspec(dllexport) __cdecl SetExtensionID.
+typedef void (__cdecl *MainSetExtensionID)(size_t, const wchar_t*);
+
+// exported in breakpad_win.cc: void __declspec(dllexport) __cdecl SetGpuInfo.
+typedef void (__cdecl *MainSetGpuInfo)(const wchar_t*, const wchar_t*,
+ const wchar_t*, const wchar_t*,
+ const wchar_t*);
+
+void SetActiveURL(const GURL& url) {
+ static MainSetActiveURL set_active_url = NULL;
+ // note: benign race condition on set_active_url.
+ if (!set_active_url) {
+ HMODULE exe_module = GetModuleHandle(chrome::kBrowserProcessExecutableName);
+ if (!exe_module)
+ return;
+ set_active_url = reinterpret_cast<MainSetActiveURL>(
+ GetProcAddress(exe_module, "SetActiveURL"));
+ if (!set_active_url)
+ return;
+ }
+
+ (set_active_url)(UTF8ToWide(url.possibly_invalid_spec()).c_str());
+}
+
+void SetClientId(const std::string& client_id) {
+ std::string str(client_id);
+ // Remove all instance of '-' char from the GUID. So BCD-WXY becomes BCDWXY.
+ ReplaceSubstringsAfterOffset(&str, 0, "-", "");
+
+ if (str.empty())
+ return;
+
+ std::wstring wstr = ASCIIToWide(str);
+ std::wstring old_wstr;
+ if (!GoogleUpdateSettings::GetMetricsId(&old_wstr) ||
+ wstr != old_wstr)
+ GoogleUpdateSettings::SetMetricsId(wstr);
+
+ static MainSetClientId set_client_id = NULL;
+ if (!set_client_id) {
+ HMODULE exe_module = GetModuleHandle(chrome::kBrowserProcessExecutableName);
+ if (!exe_module)
+ return;
+ set_client_id = reinterpret_cast<MainSetClientId>(
+ GetProcAddress(exe_module, "SetClientId"));
+ if (!set_client_id)
+ return;
+ }
+ (set_client_id)(wstr.c_str());
+}
+
+void SetActiveExtensions(const std::set<std::string>& extension_ids) {
+ static MainSetExtensionID set_extension_id = NULL;
+ if (!set_extension_id) {
+ HMODULE exe_module = GetModuleHandle(chrome::kBrowserProcessExecutableName);
+ if (!exe_module)
+ return;
+ set_extension_id = reinterpret_cast<MainSetExtensionID>(
+ GetProcAddress(exe_module, "SetExtensionID"));
+ if (!set_extension_id)
+ return;
+ }
+
+ std::set<std::string>::const_iterator iter = extension_ids.begin();
+ for (size_t i = 0; i < kMaxReportedActiveExtensions; ++i) {
+ if (iter != extension_ids.end()) {
+ (set_extension_id)(i, ASCIIToWide(iter->c_str()).c_str());
+ ++iter;
+ } else {
+ (set_extension_id)(i, L"");
+ }
+ }
+}
+
+void SetGpuInfo(const GPUInfo& gpu_info) {
+ static MainSetGpuInfo set_gpu_info = NULL;
+ if (!set_gpu_info) {
+ HMODULE exe_module = GetModuleHandle(chrome::kBrowserProcessExecutableName);
+ if (!exe_module)
+ return;
+ set_gpu_info = reinterpret_cast<MainSetGpuInfo>(
+ GetProcAddress(exe_module, "SetGpuInfo"));
+ if (!set_gpu_info)
+ return;
+ }
+ (set_gpu_info)(UintToWString(gpu_info.vendor_id()).c_str(),
+ UintToWString(gpu_info.device_id()).c_str(),
+ gpu_info.driver_version().c_str(),
+ UintToWString(gpu_info.pixel_shader_version()).c_str(),
+ UintToWString(gpu_info.vertex_shader_version()).c_str());
+}
+
+} // namespace child_process_logging
diff --git a/chrome/common/child_thread.cc b/chrome/common/child_thread.cc
new file mode 100644
index 0000000..91d276e
--- /dev/null
+++ b/chrome/common/child_thread.cc
@@ -0,0 +1,182 @@
+// Copyright (c) 2009 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/common/child_thread.h"
+
+#include "base/string_util.h"
+#include "base/command_line.h"
+#include "chrome/common/child_process.h"
+#include "chrome/common/chrome_switches.h"
+#include "chrome/common/notification_service.h"
+#include "chrome/common/plugin_messages.h"
+#include "chrome/common/socket_stream_dispatcher.h"
+#include "ipc/ipc_logging.h"
+#include "ipc/ipc_message.h"
+#include "ipc/ipc_sync_message_filter.h"
+#include "ipc/ipc_switches.h"
+#include "webkit/glue/webkit_glue.h"
+
+
+ChildThread::ChildThread() {
+ channel_name_ = CommandLine::ForCurrentProcess()->GetSwitchValueASCII(
+ switches::kProcessChannelID);
+ Init();
+}
+
+ChildThread::ChildThread(const std::string& channel_name)
+ : channel_name_(channel_name) {
+ Init();
+}
+
+void ChildThread::Init() {
+ check_with_browser_before_shutdown_ = false;
+ on_channel_error_called_ = false;
+ message_loop_ = MessageLoop::current();
+ if (CommandLine::ForCurrentProcess()->HasSwitch(switches::kUserAgent)) {
+ webkit_glue::SetUserAgent(
+ CommandLine::ForCurrentProcess()->GetSwitchValueASCII(
+ switches::kUserAgent));
+ }
+
+ channel_.reset(new IPC::SyncChannel(channel_name_,
+ IPC::Channel::MODE_CLIENT, this, NULL,
+ ChildProcess::current()->io_message_loop(), true,
+ ChildProcess::current()->GetShutDownEvent()));
+#ifdef IPC_MESSAGE_LOG_ENABLED
+ IPC::Logging::current()->SetIPCSender(this);
+#endif
+
+ resource_dispatcher_.reset(new ResourceDispatcher(this));
+ socket_stream_dispatcher_.reset(new SocketStreamDispatcher());
+
+ sync_message_filter_ =
+ new IPC::SyncMessageFilter(ChildProcess::current()->GetShutDownEvent());
+ channel_->AddFilter(sync_message_filter_.get());
+
+ // When running in unit tests, there is already a NotificationService object.
+ // Since only one can exist at a time per thread, check first.
+ if (!NotificationService::current())
+ notification_service_.reset(new NotificationService);
+}
+
+ChildThread::~ChildThread() {
+#ifdef IPC_MESSAGE_LOG_ENABLED
+ IPC::Logging::current()->SetIPCSender(NULL);
+#endif
+
+ channel_->RemoveFilter(sync_message_filter_.get());
+
+ // The ChannelProxy object caches a pointer to the IPC thread, so need to
+ // reset it as it's not guaranteed to outlive this object.
+ // NOTE: this also has the side-effect of not closing the main IPC channel to
+ // the browser process. This is needed because this is the signal that the
+ // browser uses to know that this process has died, so we need it to be alive
+ // until this process is shut down, and the OS closes the handle
+ // automatically. We used to watch the object handle on Windows to do this,
+ // but it wasn't possible to do so on POSIX.
+ channel_->ClearIPCMessageLoop();
+}
+
+void ChildThread::OnChannelError() {
+ set_on_channel_error_called(true);
+ MessageLoop::current()->Quit();
+}
+
+bool ChildThread::Send(IPC::Message* msg) {
+ if (!channel_.get()) {
+ delete msg;
+ return false;
+ }
+
+ return channel_->Send(msg);
+}
+
+void ChildThread::AddRoute(int32 routing_id, IPC::Channel::Listener* listener) {
+ DCHECK(MessageLoop::current() == message_loop());
+
+ router_.AddRoute(routing_id, listener);
+}
+
+void ChildThread::RemoveRoute(int32 routing_id) {
+ DCHECK(MessageLoop::current() == message_loop());
+
+ router_.RemoveRoute(routing_id);
+}
+
+IPC::Channel::Listener* ChildThread::ResolveRoute(int32 routing_id) {
+ DCHECK(MessageLoop::current() == message_loop());
+
+ return router_.ResolveRoute(routing_id);
+}
+
+webkit_glue::ResourceLoaderBridge* ChildThread::CreateBridge(
+ const webkit_glue::ResourceLoaderBridge::RequestInfo& request_info,
+ int host_renderer_id,
+ int host_render_view_id) {
+ return resource_dispatcher()->
+ CreateBridge(request_info, host_renderer_id, host_render_view_id);
+}
+
+
+void ChildThread::OnMessageReceived(const IPC::Message& msg) {
+ // Resource responses are sent to the resource dispatcher.
+ if (resource_dispatcher_->OnMessageReceived(msg))
+ return;
+ if (socket_stream_dispatcher_->OnMessageReceived(msg))
+ return;
+
+ bool handled = true;
+ IPC_BEGIN_MESSAGE_MAP(ChildThread, msg)
+ IPC_MESSAGE_HANDLER(PluginProcessMsg_AskBeforeShutdown, OnAskBeforeShutdown)
+ IPC_MESSAGE_HANDLER(PluginProcessMsg_Shutdown, OnShutdown)
+#if defined(IPC_MESSAGE_LOG_ENABLED)
+ IPC_MESSAGE_HANDLER(PluginProcessMsg_SetIPCLoggingEnabled,
+ OnSetIPCLoggingEnabled)
+#endif
+ IPC_MESSAGE_UNHANDLED(handled = false)
+ IPC_END_MESSAGE_MAP()
+
+ if (handled)
+ return;
+
+ if (msg.routing_id() == MSG_ROUTING_CONTROL) {
+ OnControlMessageReceived(msg);
+ } else {
+ router_.OnMessageReceived(msg);
+ }
+}
+
+void ChildThread::OnAskBeforeShutdown() {
+ check_with_browser_before_shutdown_ = true;
+}
+
+void ChildThread::OnShutdown() {
+ MessageLoop::current()->Quit();
+}
+
+#if defined(IPC_MESSAGE_LOG_ENABLED)
+void ChildThread::OnSetIPCLoggingEnabled(bool enable) {
+ if (enable)
+ IPC::Logging::current()->Enable();
+ else
+ IPC::Logging::current()->Disable();
+}
+#endif // IPC_MESSAGE_LOG_ENABLED
+
+ChildThread* ChildThread::current() {
+ return ChildProcess::current()->main_thread();
+}
+
+void ChildThread::OnProcessFinalRelease() {
+ if (on_channel_error_called_ || !check_with_browser_before_shutdown_) {
+ MessageLoop::current()->Quit();
+ return;
+ }
+
+ // The child process shutdown sequence is a request response based mechanism,
+ // where we send out an initial feeler request to the child process host
+ // instance in the browser to verify if it's ok to shutdown the child process.
+ // The browser then sends back a response if it's ok to shutdown.
+ Send(new PluginProcessHostMsg_ShutdownRequest);
+}
diff --git a/chrome/common/child_thread.h b/chrome/common/child_thread.h
new file mode 100644
index 0000000..72af5aa
--- /dev/null
+++ b/chrome/common/child_thread.h
@@ -0,0 +1,123 @@
+// Copyright (c) 2009 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_COMMON_CHILD_THREAD_H_
+#define CHROME_COMMON_CHILD_THREAD_H_
+
+#include "base/basictypes.h"
+#include "base/scoped_ptr.h"
+#include "chrome/common/message_router.h"
+#include "chrome/common/resource_dispatcher.h"
+#include "ipc/ipc_sync_channel.h"
+#include "ipc/ipc_message.h"
+
+class NotificationService;
+class SocketStreamDispatcher;
+
+namespace IPC {
+class SyncMessageFilter;
+}
+
+// The main thread of a child process derives from this class.
+class ChildThread : public IPC::Channel::Listener,
+ public IPC::Message::Sender {
+ public:
+ // Creates the thread.
+ ChildThread();
+ // Used for single-process mode.
+ explicit ChildThread(const std::string& channel_name);
+ virtual ~ChildThread();
+
+ // IPC::Message::Sender implementation:
+ virtual bool Send(IPC::Message* msg);
+
+ // See documentation on MessageRouter for AddRoute and RemoveRoute
+ void AddRoute(int32 routing_id, IPC::Channel::Listener* listener);
+ void RemoveRoute(int32 routing_id);
+
+ IPC::Channel::Listener* ResolveRoute(int32 routing_id);
+
+ // Creates a ResourceLoaderBridge.
+ // Tests can override this method if they want a custom loading behavior.
+ virtual webkit_glue::ResourceLoaderBridge* CreateBridge(
+ const webkit_glue::ResourceLoaderBridge::RequestInfo& request_info,
+ int host_renderer_id,
+ int host_render_view_id);
+
+ ResourceDispatcher* resource_dispatcher() {
+ return resource_dispatcher_.get();
+ }
+
+ SocketStreamDispatcher* socket_stream_dispatcher() {
+ return socket_stream_dispatcher_.get();
+ }
+
+ // Safe to call on any thread, as long as it's guaranteed that the thread's
+ // lifetime is less than the main thread.
+ IPC::SyncMessageFilter* sync_message_filter() { return sync_message_filter_; }
+
+ MessageLoop* message_loop() { return message_loop_; }
+
+ // Returns the one child thread.
+ static ChildThread* current();
+
+ protected:
+ friend class ChildProcess;
+
+ // Called when the process refcount is 0.
+ void OnProcessFinalRelease();
+
+ virtual void OnControlMessageReceived(const IPC::Message& msg) { }
+ virtual void OnAskBeforeShutdown();
+ virtual void OnShutdown();
+
+#ifdef IPC_MESSAGE_LOG_ENABLED
+ virtual void OnSetIPCLoggingEnabled(bool enable);
+#endif
+
+ IPC::SyncChannel* channel() { return channel_.get(); }
+
+ void set_on_channel_error_called(bool on_channel_error_called) {
+ on_channel_error_called_ = on_channel_error_called;
+ }
+
+ private:
+ void Init();
+
+ // IPC::Channel::Listener implementation:
+ virtual void OnMessageReceived(const IPC::Message& msg);
+ virtual void OnChannelError();
+
+ std::string channel_name_;
+ scoped_ptr<IPC::SyncChannel> channel_;
+
+ // Allows threads other than the main thread to send sync messages.
+ scoped_refptr<IPC::SyncMessageFilter> sync_message_filter_;
+
+ // Implements message routing functionality to the consumers of ChildThread.
+ MessageRouter router_;
+
+ // Handles resource loads for this process.
+ scoped_ptr<ResourceDispatcher> resource_dispatcher_;
+
+ // Handles SocketStream for this process.
+ scoped_ptr<SocketStreamDispatcher> socket_stream_dispatcher_;
+
+ // If true, checks with the browser process before shutdown. This avoids race
+ // conditions if the process refcount is 0 but there's an IPC message inflight
+ // that would addref it.
+ bool check_with_browser_before_shutdown_;
+
+ // The OnChannelError() callback was invoked - the channel is dead, don't
+ // attempt to communicate.
+ bool on_channel_error_called_;
+
+ MessageLoop* message_loop_;
+
+ scoped_ptr<NotificationService> notification_service_;
+
+ DISALLOW_COPY_AND_ASSIGN(ChildThread);
+};
+
+#endif // CHROME_COMMON_CHILD_THREAD_H_
diff --git a/chrome/common/chrome_constants.cc b/chrome/common/chrome_constants.cc
new file mode 100644
index 0000000..47f0d52
--- /dev/null
+++ b/chrome/common/chrome_constants.cc
@@ -0,0 +1,139 @@
+// Copyright (c) 2006-2008 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/common/chrome_constants.h"
+
+#include "base/file_path.h"
+
+#define FPL FILE_PATH_LITERAL
+
+#if defined(OS_MACOSX)
+#if defined(GOOGLE_CHROME_BUILD)
+#define PRODUCT_STRING "Google Chrome"
+#define PRODUCT_STRING_W L"Google Chrome"
+#elif defined(CHROMIUM_BUILD)
+#define PRODUCT_STRING "Chromium"
+#define PRODUCT_STRING_W L"Chromium"
+#else
+#error Unknown branding
+#endif
+#endif // OS_MACOSX
+
+namespace chrome {
+
+// The following should not be used for UI strings; they are meant
+// for system strings only. UI changes should be made in the GRD.
+#if defined(OS_WIN)
+const wchar_t kBrowserProcessExecutableName[] = L"chrome.exe";
+const wchar_t kHelperProcessExecutableName[] = L"chrome.exe";
+#elif defined(OS_LINUX)
+const wchar_t kBrowserProcessExecutableName[] = L"chrome";
+// Helper processes end up with a name of "exe" due to execing via
+// /proc/self/exe. See bug 22703.
+const wchar_t kHelperProcessExecutableName[] = L"exe";
+#elif defined(OS_MACOSX)
+const wchar_t kBrowserProcessExecutableName[] = PRODUCT_STRING_W;
+const wchar_t kHelperProcessExecutableName[] = PRODUCT_STRING_W L" Helper";
+#endif // OS_*
+#if defined(OS_WIN)
+const wchar_t kBrowserProcessExecutablePath[] = L"chrome.exe";
+const FilePath::CharType kHelperProcessExecutablePath[] = FPL("chrome.exe");
+#elif defined(OS_LINUX)
+const wchar_t kBrowserProcessExecutablePath[] = L"chrome";
+const FilePath::CharType kHelperProcessExecutablePath[] = FPL("chrome");
+#elif defined(OS_MACOSX)
+const wchar_t kBrowserProcessExecutablePath[] =
+ PRODUCT_STRING_W L".app/Contents/MacOS/" PRODUCT_STRING_W;
+const FilePath::CharType kHelperProcessExecutablePath[] =
+ FPL(PRODUCT_STRING " Helper.app/Contents/MacOS/" PRODUCT_STRING " Helper");
+#endif // OS_*
+#if defined(OS_MACOSX)
+const FilePath::CharType kFrameworkName[] =
+ FPL(PRODUCT_STRING " Framework.framework");
+#endif // OS_MACOSX
+const wchar_t kNaClAppName[] = L"nacl64";
+#if defined(GOOGLE_CHROME_BUILD)
+const wchar_t kBrowserAppName[] = L"Chrome";
+const char kStatsFilename[] = "ChromeStats2";
+#else
+const wchar_t kBrowserAppName[] = L"Chromium";
+const char kStatsFilename[] = "ChromiumStats2";
+#endif
+
+#if defined(OS_WIN)
+const wchar_t kStatusTrayWindowClass[] = L"Chrome_StatusTrayWindow";
+#endif // defined(OS_WIN)
+
+const wchar_t kMessageWindowClass[] = L"Chrome_MessageWindow";
+const wchar_t kCrashReportLog[] = L"Reported Crashes.txt";
+const wchar_t kTestingInterfaceDLL[] = L"testing_interface.dll";
+const wchar_t kNotSignedInProfile[] = L"Default";
+const wchar_t kNotSignedInID[] = L"not-signed-in";
+const wchar_t kBrowserResourcesDll[] = L"chrome.dll";
+const FilePath::CharType kExtensionFileExtension[] = FPL("crx");
+
+// filenames
+const FilePath::CharType kArchivedHistoryFilename[] = FPL("Archived History");
+const FilePath::CharType kCacheDirname[] = FPL("Cache");
+const FilePath::CharType kMediaCacheDirname[] = FPL("Media Cache");
+const FilePath::CharType kOffTheRecordMediaCacheDirname[] =
+ FPL("Incognito Media Cache");
+const FilePath::CharType kAppCacheDirname[] = FPL("Application Cache");
+const FilePath::CharType kChromePluginDataDirname[] = FPL("Plugin Data");
+const FilePath::CharType kThemePackFilename[] = FPL("Cached Theme.pak");
+const FilePath::CharType kCookieFilename[] = FPL("Cookies");
+const FilePath::CharType kExtensionsCookieFilename[] = FPL("Extension Cookies");
+const FilePath::CharType kFaviconsFilename[] = FPL("Favicons");
+const FilePath::CharType kHistoryFilename[] = FPL("History");
+const FilePath::CharType kLocalStateFilename[] = FPL("Local State");
+const FilePath::CharType kPreferencesFilename[] = FPL("Preferences");
+const FilePath::CharType kSafeBrowsingFilename[] = FPL("Safe Browsing");
+// WARNING: SingletonSocket can't contain spaces, because otherwise
+// chrome_process_util_linux would be broken.
+const FilePath::CharType kSingletonSocketFilename[] = FPL("SingletonSocket");
+const FilePath::CharType kSingletonLockFilename[] = FPL("SingletonLock");
+const FilePath::CharType kThumbnailsFilename[] = FPL("Thumbnails");
+const FilePath::CharType kNewTabThumbnailsFilename[] = FPL("Top Thumbnails");
+const FilePath::CharType kTopSitesFilename[] = FPL("Top Sites");
+const wchar_t kUserDataDirname[] = L"User Data";
+const FilePath::CharType kUserScriptsDirname[] = FPL("User Scripts");
+const FilePath::CharType kWebDataFilename[] = FPL("Web Data");
+const FilePath::CharType kBookmarksFileName[] = FPL("Bookmarks");
+const FilePath::CharType kHistoryBookmarksFileName[] =
+ FPL("Bookmarks From History");
+const FilePath::CharType kCustomDictionaryFileName[] =
+ FPL("Custom Dictionary.txt");
+const FilePath::CharType kLoginDataFileName[] = FPL("Login Data");
+const FilePath::CharType kJumpListIconDirname[] = FPL("JumpListIcons");
+const FilePath::CharType kWebAppDirname[] = FPL("Web Applications");
+const FilePath::CharType kServiceStateFileName[] = FPL("Service State");
+
+// This number used to be limited to 32 in the past (see b/535234).
+const unsigned int kMaxRendererProcessCount = 42;
+const int kStatsMaxThreads = 32;
+const int kStatsMaxCounters = 300;
+
+const size_t kMaxTitleChars = 4 * 1024;
+const size_t kMaxURLChars = 2 * 1024 * 1024;
+const size_t kMaxURLDisplayChars = 32 * 1024;
+
+// We don't enable record mode in the released product because users could
+// potentially be tricked into running a product in record mode without
+// knowing it. Enable in debug builds. Playback mode is allowed always,
+// because it is useful for testing and not hazardous by itself.
+#ifndef NDEBUG
+const bool kRecordModeEnabled = true;
+#else
+const bool kRecordModeEnabled = false;
+#endif
+
+const int kHistogramSynchronizerReservedSequenceNumber = 0;
+
+const int kMaxSessionHistoryEntries = 50;
+
+const wchar_t kChromiumRendererIdProperty[] = L"ChromiumRendererId";
+
+} // namespace chrome
+
+#undef FPL
diff --git a/chrome/common/chrome_constants.h b/chrome/common/chrome_constants.h
new file mode 100644
index 0000000..a1efdbf
--- /dev/null
+++ b/chrome/common/chrome_constants.h
@@ -0,0 +1,95 @@
+// Copyright (c) 2006-2008 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.
+
+// A handful of resource-like constants related to the Chrome application.
+
+#ifndef CHROME_COMMON_CHROME_CONSTANTS_H_
+#define CHROME_COMMON_CHROME_CONSTANTS_H_
+
+#include "base/file_path.h"
+
+namespace chrome {
+
+extern const char kChromeVersion[];
+
+extern const wchar_t kBrowserProcessExecutableName[];
+extern const wchar_t kHelperProcessExecutableName[];
+extern const wchar_t kBrowserProcessExecutablePath[];
+extern const FilePath::CharType kHelperProcessExecutablePath[];
+#if defined(OS_MACOSX)
+extern const FilePath::CharType kFrameworkName[];
+#endif
+extern const wchar_t kBrowserAppName[];
+#if defined(OS_WIN)
+extern const wchar_t kStatusTrayWindowClass[];
+#endif // defined(OS_WIN)
+extern const wchar_t kMessageWindowClass[];
+extern const wchar_t kCrashReportLog[];
+extern const wchar_t kTestingInterfaceDLL[];
+extern const wchar_t kNotSignedInProfile[];
+extern const wchar_t kNotSignedInID[];
+extern const char kStatsFilename[];
+extern const wchar_t kBrowserResourcesDll[];
+extern const wchar_t kNaClAppName[];
+extern const FilePath::CharType kExtensionFileExtension[];
+
+// filenames
+extern const FilePath::CharType kArchivedHistoryFilename[];
+extern const FilePath::CharType kCacheDirname[];
+extern const FilePath::CharType kMediaCacheDirname[];
+extern const FilePath::CharType kOffTheRecordMediaCacheDirname[];
+extern const FilePath::CharType kAppCacheDirname[];
+extern const FilePath::CharType kChromePluginDataDirname[];
+extern const FilePath::CharType kThemePackFilename[];
+extern const FilePath::CharType kCookieFilename[];
+extern const FilePath::CharType kExtensionsCookieFilename[];
+extern const FilePath::CharType kFaviconsFilename[];
+extern const FilePath::CharType kHistoryFilename[];
+extern const FilePath::CharType kLocalStateFilename[];
+extern const FilePath::CharType kPreferencesFilename[];
+extern const FilePath::CharType kSafeBrowsingFilename[];
+extern const FilePath::CharType kSingletonSocketFilename[];
+extern const FilePath::CharType kSingletonLockFilename[];
+extern const FilePath::CharType kThumbnailsFilename[];
+extern const FilePath::CharType kNewTabThumbnailsFilename[];
+extern const FilePath::CharType kTopSitesFilename[];
+extern const wchar_t kUserDataDirname[];
+extern const FilePath::CharType kUserScriptsDirname[];
+extern const FilePath::CharType kWebDataFilename[];
+extern const FilePath::CharType kBookmarksFileName[];
+extern const FilePath::CharType kHistoryBookmarksFileName[];
+extern const FilePath::CharType kCustomDictionaryFileName[];
+extern const FilePath::CharType kLoginDataFileName[];
+extern const FilePath::CharType kJumpListIconDirname[];
+extern const FilePath::CharType kWebAppDirname[];
+extern const FilePath::CharType kServiceStateFileName[];
+
+extern const unsigned int kMaxRendererProcessCount;
+extern const int kStatsMaxThreads;
+extern const int kStatsMaxCounters;
+
+// The maximum number of characters of the document's title that we're willing
+// to accept in the browser process.
+extern const size_t kMaxTitleChars;
+// The maximum number of characters in the URL that we're willing to accept
+// in the browser process. It is set low enough to avoid damage to the browser
+// but high enough that a web site can abuse location.hash for a little storage.
+// We have different values for "max accepted" and "max displayed" because
+// a data: URI may be legitimately massive, but the full URI would kill all
+// known operating systems if you dropped it into a UI control.
+extern const size_t kMaxURLChars;
+extern const size_t kMaxURLDisplayChars;
+
+extern const bool kRecordModeEnabled;
+
+extern const int kHistogramSynchronizerReservedSequenceNumber;
+
+// The maximum number of session history entries per tab.
+extern const int kMaxSessionHistoryEntries;
+
+extern const wchar_t kChromiumRendererIdProperty[];
+
+} // namespace chrome
+
+#endif // CHROME_COMMON_CHROME_CONSTANTS_H_
diff --git a/chrome/common/chrome_counters.cc b/chrome/common/chrome_counters.cc
new file mode 100644
index 0000000..fea0906
--- /dev/null
+++ b/chrome/common/chrome_counters.cc
@@ -0,0 +1,52 @@
+// Copyright (c) 2006-2008 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/common/chrome_counters.h"
+
+#include "base/stats_counters.h"
+
+namespace chrome {
+
+// Note: We use the construct-on-first-use pattern here, because we don't
+// want to fight with any static initializer ordering problems later.
+// The downside of this is that the objects don't ever get cleaned up.
+// But they are small and this is okay.
+
+// Note: Because these are constructed on-first-use, there is a slight
+// race condition - two threads could initialize the same counter.
+// If this happened, the stats table would still work just fine;
+// we'd leak the extraneous StatsCounter object once, and that
+// would be it. But these are small objects, so this is ok.
+
+StatsCounterTimer& Counters::chrome_main() {
+ static StatsCounterTimer* ctr = new StatsCounterTimer("Chrome.Init");
+ return *ctr;
+}
+
+StatsCounterTimer& Counters::renderer_main() {
+ static StatsCounterTimer* ctr = new StatsCounterTimer("Chrome.RendererInit");
+ return *ctr;
+}
+
+StatsCounterTimer& Counters::spellcheck_init() {
+ static StatsCounterTimer* ctr = new StatsCounterTimer("SpellCheck.Init");
+ return *ctr;
+}
+
+StatsRate& Counters::spellcheck_lookup() {
+ static StatsRate* ctr = new StatsRate("SpellCheck.Lookup");
+ return *ctr;
+}
+
+StatsCounterTimer& Counters::plugin_load() {
+ static StatsCounterTimer* ctr = new StatsCounterTimer("ChromePlugin.Load");
+ return *ctr;
+}
+
+StatsRate& Counters::plugin_intercept() {
+ static StatsRate* ctr = new StatsRate("ChromePlugin.Intercept");
+ return *ctr;
+}
+
+} // namespace chrome
diff --git a/chrome/common/chrome_counters.h b/chrome/common/chrome_counters.h
new file mode 100644
index 0000000..14cfa21
--- /dev/null
+++ b/chrome/common/chrome_counters.h
@@ -0,0 +1,39 @@
+// Copyright (c) 2006-2008 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.
+
+// Counters used within the browser.
+
+#ifndef CHROME_COMMON_CHROME_COUNTERS_H_
+#define CHROME_COMMON_CHROME_COUNTERS_H_
+
+class StatsCounter;
+class StatsCounterTimer;
+class StatsRate;
+
+namespace chrome {
+
+class Counters {
+ public:
+ // The amount of time spent in chrome initialization.
+ static StatsCounterTimer& chrome_main();
+
+ // The amount of time spent in renderer initialization.
+ static StatsCounterTimer& renderer_main();
+
+ // Time spent in spellchecker initialization.
+ static StatsCounterTimer& spellcheck_init();
+
+ // Time/Count of spellcheck lookups.
+ static StatsRate& spellcheck_lookup();
+
+ // Time spent loading the Chrome plugins.
+ static StatsCounterTimer& plugin_load();
+
+ // Time/Count of plugin network interception.
+ static StatsRate& plugin_intercept();
+};
+
+} // namespace chrome
+
+#endif // CHROME_COMMON_CHROME_COUNTERS_H_
diff --git a/chrome/common/chrome_descriptors.h b/chrome/common/chrome_descriptors.h
new file mode 100644
index 0000000..8a4f6ee
--- /dev/null
+++ b/chrome/common/chrome_descriptors.h
@@ -0,0 +1,16 @@
+// Copyright (c) 2009 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_COMMON_CHROME_DESCRIPTORS_H_
+#define CHROME_COMMON_CHROME_DESCRIPTORS_H_
+
+#include "ipc/ipc_descriptors.h"
+// This is a list of global descriptor keys to be used with the
+// base::GlobalDescriptors object (see base/global_descriptors_posix.h)
+enum {
+ kCrashDumpSignal = kPrimaryIPCChannel + 1,
+ kSandboxIPCChannel = kPrimaryIPCChannel + 2, // http://code.google.com/p/chromium/LinuxSandboxIPC
+};
+
+#endif // CHROME_COMMON_CHROME_DESCRIPTORS_H_
diff --git a/chrome/common/chrome_paths.cc b/chrome/common/chrome_paths.cc
new file mode 100644
index 0000000..6f77510
--- /dev/null
+++ b/chrome/common/chrome_paths.cc
@@ -0,0 +1,316 @@
+// Copyright (c) 2006-2010 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/common/chrome_paths.h"
+
+#include "base/command_line.h"
+#include "base/file_util.h"
+#include "base/logging.h"
+#include "base/path_service.h"
+#include "base/string_util.h"
+#include "base/sys_info.h"
+#include "chrome/common/chrome_constants.h"
+#include "chrome/common/chrome_paths_internal.h"
+#include "chrome/common/chrome_switches.h"
+
+#if defined(OS_MACOSX)
+#include "base/mac_util.h"
+#endif
+
+namespace {
+
+// File name of the internal Flash plugin on different platforms.
+const FilePath::CharType kInternalFlashPluginFileName[] =
+#if defined(OS_MACOSX)
+ FILE_PATH_LITERAL("Flash Player Plugin for Chrome.plugin");
+#elif defined(OS_WIN)
+ FILE_PATH_LITERAL("gcswf32.dll");
+#else // OS_LINUX, etc.
+ FILE_PATH_LITERAL("libgcflashplayer.so");
+#endif
+
+} // namespace
+
+namespace chrome {
+
+// Gets the path for internal plugins.
+bool GetInternalPluginsDirectory(FilePath* result) {
+#if defined(OS_MACOSX)
+ // If called from Chrome, get internal plugins from a subdirectory of the
+ // framework.
+ if (mac_util::AmIBundled()) {
+ *result = chrome::GetFrameworkBundlePath();
+ DCHECK(!result->empty());
+ *result = result->Append("Internet Plug-Ins");
+ return true;
+ }
+ // In tests, just look in the module directory (below).
+#endif
+
+ // The rest of the world expects plugins in the module directory.
+ return PathService::Get(base::DIR_MODULE, result);
+}
+
+bool GetGearsPluginPathFromCommandLine(FilePath* path) {
+#ifndef NDEBUG
+ // for debugging, support a cmd line based override
+ FilePath plugin_path =
+ CommandLine::ForCurrentProcess()->GetSwitchValuePath(
+ switches::kGearsPluginPathOverride);
+ *path = plugin_path;
+ return !plugin_path.empty();
+#else
+ return false;
+#endif
+}
+
+bool PathProvider(int key, FilePath* result) {
+ // Some keys are just aliases...
+ switch (key) {
+ case chrome::DIR_APP:
+ return PathService::Get(base::DIR_MODULE, result);
+ case chrome::DIR_LOGS:
+#ifdef NDEBUG
+ // Release builds write to the data dir
+ return PathService::Get(chrome::DIR_USER_DATA, result);
+#else
+ // Debug builds write next to the binary (in the build tree)
+#if defined(OS_MACOSX)
+ if (!PathService::Get(base::DIR_EXE, result))
+ return false;
+ if (mac_util::AmIBundled()) {
+ // If we're called from chrome, dump it beside the app (outside the
+ // app bundle), if we're called from a unittest, we'll already
+ // outside the bundle so use the exe dir.
+ // exe_dir gave us .../Chromium.app/Contents/MacOS/Chromium.
+ *result = result->DirName();
+ *result = result->DirName();
+ *result = result->DirName();
+ }
+ return true;
+#else
+ return PathService::Get(base::DIR_EXE, result);
+#endif // defined(OS_MACOSX)
+#endif // NDEBUG
+ case chrome::FILE_RESOURCE_MODULE:
+ return PathService::Get(base::FILE_MODULE, result);
+ }
+
+ // Assume that we will not need to create the directory if it does not exist.
+ // This flag can be set to true for the cases where we want to create it.
+ bool create_dir = false;
+
+ FilePath cur;
+ switch (key) {
+ case chrome::DIR_USER_DATA:
+ if (!GetDefaultUserDataDirectory(&cur)) {
+ NOTREACHED();
+ return false;
+ }
+ create_dir = true;
+ break;
+ case chrome::DIR_USER_DOCUMENTS:
+ if (!GetUserDocumentsDirectory(&cur))
+ return false;
+ create_dir = true;
+ break;
+ case chrome::DIR_DEFAULT_DOWNLOADS_SAFE:
+#if defined(OS_WIN)
+ if (!GetUserDownloadsDirectorySafe(&cur))
+ return false;
+ break;
+#else
+ // Fall through for all other platforms.
+#endif
+ case chrome::DIR_DEFAULT_DOWNLOADS:
+ if (!GetUserDownloadsDirectory(&cur))
+ return false;
+ // Do not create the download directory here, we have done it twice now
+ // and annoyed a lot of users.
+ break;
+ case chrome::DIR_CRASH_DUMPS:
+ // The crash reports are always stored relative to the default user data
+ // directory. This avoids the problem of having to re-initialize the
+ // exception handler after parsing command line options, which may
+ // override the location of the app's profile directory.
+ if (!GetDefaultUserDataDirectory(&cur))
+ return false;
+ cur = cur.Append(FILE_PATH_LITERAL("Crash Reports"));
+ create_dir = true;
+ break;
+ case chrome::DIR_USER_DESKTOP:
+ if (!GetUserDesktop(&cur))
+ return false;
+ break;
+ case chrome::DIR_RESOURCES:
+#if defined(OS_MACOSX)
+ cur = mac_util::MainAppBundlePath();
+ cur = cur.Append(FILE_PATH_LITERAL("Resources"));
+#else
+ if (!PathService::Get(chrome::DIR_APP, &cur))
+ return false;
+ cur = cur.Append(FILE_PATH_LITERAL("resources"));
+#endif
+ break;
+ case chrome::DIR_SHARED_RESOURCES:
+ if (!PathService::Get(chrome::DIR_RESOURCES, &cur))
+ return false;
+ cur = cur.Append(FILE_PATH_LITERAL("shared"));
+ break;
+ case chrome::DIR_INSPECTOR:
+ if (!PathService::Get(chrome::DIR_RESOURCES, &cur))
+ return false;
+ cur = cur.Append(FILE_PATH_LITERAL("inspector"));
+ break;
+ case chrome::DIR_APP_DICTIONARIES:
+#if defined(OS_LINUX) || defined(OS_MACOSX)
+ // We can't write into the EXE dir on Linux, so keep dictionaries
+ // alongside the safe browsing database in the user data dir.
+ // And we don't want to write into the bundle on the Mac, so push
+ // it to the user data dir there also.
+ if (!PathService::Get(chrome::DIR_USER_DATA, &cur))
+ return false;
+#else
+ if (!PathService::Get(base::DIR_EXE, &cur))
+ return false;
+#endif
+ cur = cur.Append(FILE_PATH_LITERAL("Dictionaries"));
+ create_dir = true;
+ break;
+ case chrome::DIR_USER_DATA_TEMP:
+ if (!PathService::Get(chrome::DIR_USER_DATA, &cur))
+ return false;
+ cur = cur.Append(FILE_PATH_LITERAL("Temp"));
+ create_dir = true;
+ break;
+ case chrome::DIR_INTERNAL_PLUGINS:
+ if (!GetInternalPluginsDirectory(&cur))
+ return false;
+ break;
+ case chrome::FILE_LOCAL_STATE:
+ if (!PathService::Get(chrome::DIR_USER_DATA, &cur))
+ return false;
+ cur = cur.Append(chrome::kLocalStateFilename);
+ break;
+ case chrome::FILE_RECORDED_SCRIPT:
+ if (!PathService::Get(chrome::DIR_USER_DATA, &cur))
+ return false;
+ cur = cur.Append(FILE_PATH_LITERAL("script.log"));
+ break;
+ case chrome::FILE_GEARS_PLUGIN:
+ if (!GetGearsPluginPathFromCommandLine(&cur)) {
+#if defined(OS_WIN)
+ // Search for gears.dll alongside chrome.dll first. This new model
+ // allows us to package gears.dll with the Chrome installer and update
+ // it while Chrome is running.
+ if (!GetInternalPluginsDirectory(&cur))
+ return false;
+ cur = cur.Append(FILE_PATH_LITERAL("gears.dll"));
+
+ if (!file_util::PathExists(cur)) {
+ if (!PathService::Get(base::DIR_EXE, &cur))
+ return false;
+ cur = cur.Append(FILE_PATH_LITERAL("plugins"));
+ cur = cur.Append(FILE_PATH_LITERAL("gears"));
+ cur = cur.Append(FILE_PATH_LITERAL("gears.dll"));
+ }
+#else
+ // No gears.dll on non-Windows systems.
+ return false;
+#endif
+ }
+ break;
+ case chrome::FILE_FLASH_PLUGIN:
+ if (!GetInternalPluginsDirectory(&cur))
+ return false;
+ cur = cur.Append(kInternalFlashPluginFileName);
+ if (!file_util::PathExists(cur))
+ return false;
+ break;
+ case chrome::FILE_PDF_PLUGIN:
+ if (!GetInternalPluginsDirectory(&cur))
+ return false;
+#if defined(OS_WIN)
+ cur = cur.Append(FILE_PATH_LITERAL("pdf.dll"));
+#elif defined(OS_MACOSX)
+ cur = cur.Append(FILE_PATH_LITERAL("PDF.plugin"));
+#else // Linux and Chrome OS
+ cur = cur.Append(FILE_PATH_LITERAL("libpdf.so"));
+#endif
+ break;
+ case chrome::FILE_RESOURCES_PACK:
+#if defined(OS_MACOSX)
+ if (mac_util::AmIBundled()) {
+ cur = mac_util::MainAppBundlePath();
+ cur = cur.Append(FILE_PATH_LITERAL("Resources"))
+ .Append(FILE_PATH_LITERAL("resources.pak"));
+ break;
+ }
+ // If we're not bundled on mac, resources.pak should be next to the
+ // binary (e.g., for unit tests).
+#endif
+ if (!PathService::Get(base::DIR_MODULE, &cur))
+ return false;
+ cur = cur.Append(FILE_PATH_LITERAL("resources.pak"));
+ break;
+#if defined(OS_CHROMEOS)
+ case chrome::FILE_CHROMEOS_API:
+ if (!PathService::Get(base::DIR_MODULE, &cur))
+ return false;
+ cur = cur.Append(FILE_PATH_LITERAL("chromeos"));
+ cur = cur.Append(FILE_PATH_LITERAL("libcros.so"));
+ break;
+#endif
+ // The following are only valid in the development environment, and
+ // will fail if executed from an installed executable (because the
+ // generated path won't exist).
+ case chrome::DIR_TEST_DATA:
+ if (!PathService::Get(base::DIR_SOURCE_ROOT, &cur))
+ return false;
+ cur = cur.Append(FILE_PATH_LITERAL("chrome"));
+ cur = cur.Append(FILE_PATH_LITERAL("test"));
+ cur = cur.Append(FILE_PATH_LITERAL("data"));
+ if (!file_util::PathExists(cur)) // we don't want to create this
+ return false;
+ break;
+ case chrome::DIR_TEST_TOOLS:
+ if (!PathService::Get(base::DIR_SOURCE_ROOT, &cur))
+ return false;
+ cur = cur.Append(FILE_PATH_LITERAL("chrome"));
+ cur = cur.Append(FILE_PATH_LITERAL("tools"));
+ cur = cur.Append(FILE_PATH_LITERAL("test"));
+ if (!file_util::PathExists(cur)) // we don't want to create this
+ return false;
+ break;
+#if !defined(OS_MACOSX) && defined(OS_POSIX)
+ case chrome::DIR_POLICY_FILES: {
+#if defined(GOOGLE_CHROME_BUILD)
+ cur = FilePath(FILE_PATH_LITERAL("/etc/opt/chrome/policies"));
+#else
+ cur = FilePath(FILE_PATH_LITERAL("/etc/chromium/policies"));
+#endif
+ if (!file_util::PathExists(cur)) // we don't want to create this
+ return false;
+ break;
+ }
+#endif
+ default:
+ return false;
+ }
+
+ if (create_dir && !file_util::PathExists(cur) &&
+ !file_util::CreateDirectory(cur))
+ return false;
+
+ *result = cur;
+ return true;
+}
+
+// This cannot be done as a static initializer sadly since Visual Studio will
+// eliminate this object file if there is no direct entry point into it.
+void RegisterPathProvider() {
+ PathService::RegisterProvider(PathProvider, PATH_START, PATH_END);
+}
+
+} // namespace chrome
diff --git a/chrome/common/chrome_paths.h b/chrome/common/chrome_paths.h
new file mode 100644
index 0000000..2d90e0a
--- /dev/null
+++ b/chrome/common/chrome_paths.h
@@ -0,0 +1,80 @@
+// Copyright (c) 2006-2010 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_COMMON_CHROME_PATHS_H__
+#define CHROME_COMMON_CHROME_PATHS_H__
+
+#include "build/build_config.h"
+
+// This file declares path keys for the chrome module. These can be used with
+// the PathService to access various special directories and files.
+
+namespace chrome {
+
+enum {
+ PATH_START = 1000,
+
+ DIR_APP = PATH_START, // Directory where dlls and data reside.
+ DIR_LOGS, // Directory where logs should be written.
+ DIR_USER_DATA, // Directory where user data can be written.
+ DIR_CRASH_DUMPS, // Directory where crash dumps are written.
+ DIR_USER_DESKTOP, // Directory that correspond to the desktop.
+ DIR_RESOURCES, // Directory containing separate file resources
+ // used by Chrome at runtime.
+ DIR_SHARED_RESOURCES, // Directory containing js and css files used
+ // by DOMUI and component extensions.
+ DIR_INSPECTOR, // Directory where web inspector is located.
+ DIR_APP_DICTIONARIES, // Directory where the global dictionaries are.
+ DIR_USER_DOCUMENTS, // Directory for a user's "My Documents".
+ DIR_DEFAULT_DOWNLOADS_SAFE, // Directory for a user's
+ // "My Documents/Downloads".
+ DIR_DEFAULT_DOWNLOADS, // Directory for a user's downloads.
+ DIR_USER_DATA_TEMP, // A temp directory within DIR_USER_DATA. Use
+ // this when a temporary file or directory will
+ // be moved into the profile, to avoid issues
+ // moving across volumes. See crbug.com/13044 .
+ DIR_INTERNAL_PLUGINS, // Directory where internal plugins reside.
+#if !defined(OS_MACOSX) && defined(OS_POSIX)
+ DIR_POLICY_FILES, // Directory for system-wide read-only
+ // policy files that allow sys-admins
+ // to set policies for chrome. This directory
+ // contains subdirectories.
+#endif
+ FILE_RESOURCE_MODULE, // Full path and filename of the module that
+ // contains embedded resources (version,
+ // strings, images, etc.).
+ FILE_LOCAL_STATE, // Path and filename to the file in which
+ // machine/installation-specific state is saved.
+ FILE_RECORDED_SCRIPT, // Full path to the script.log file that
+ // contains recorded browser events for
+ // playback.
+ FILE_GEARS_PLUGIN, // Full path to the gears.dll plugin file.
+ FILE_FLASH_PLUGIN, // Full path to the internal Flash plugin file.
+ FILE_PDF_PLUGIN, // Full path to the internal PDF plugin file.
+ FILE_LIBAVCODEC, // Full path to libavcodec media decoding
+ // library.
+ FILE_LIBAVFORMAT, // Full path to libavformat media parsing
+ // library.
+ FILE_LIBAVUTIL, // Full path to libavutil media utility library.
+ FILE_RESOURCES_PACK, // Full path to the .pak file containing
+ // binary data (e.g., html files and images
+ // used by interal pages).
+#if defined(OS_CHROMEOS)
+ FILE_CHROMEOS_API, // Full path to chrome os api shared object.
+#endif
+
+
+ // Valid only in development environment; TODO(darin): move these
+ DIR_TEST_DATA, // Directory where unit test data resides.
+ DIR_TEST_TOOLS, // Directory where unit test tools reside.
+
+ PATH_END
+};
+
+// Call once to register the provider for the path keys defined above.
+void RegisterPathProvider();
+
+} // namespace chrome
+
+#endif // CHROME_COMMON_CHROME_PATHS_H__
diff --git a/chrome/common/chrome_paths_internal.h b/chrome/common/chrome_paths_internal.h
new file mode 100644
index 0000000..7d731e1
--- /dev/null
+++ b/chrome/common/chrome_paths_internal.h
@@ -0,0 +1,60 @@
+// Copyright (c) 2006-2008 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_COMMON_CHROME_PATHS_INTERNAL_H_
+#define CHROME_COMMON_CHROME_PATHS_INTERNAL_H_
+
+#include "build/build_config.h"
+#include "base/file_path.h"
+
+namespace chrome {
+
+// Get the path to the user's data directory, regardless of whether
+// DIR_USER_DATA has been overridden by a command-line option.
+bool GetDefaultUserDataDirectory(FilePath* result);
+
+// This returns the base directory in which Chrome Frame stores user profiles.
+// Note that this cannot be wrapped in a preprocessor define since
+// CF and Google Chrome want to share the same binaries.
+bool GetChromeFrameUserDataDirectory(FilePath* result);
+
+// Get the path to the user's documents directory.
+bool GetUserDocumentsDirectory(FilePath* result);
+
+#if defined (OS_WIN)
+// Gets the path to a safe default download directory for a user.
+bool GetUserDownloadsDirectorySafe(FilePath* result);
+#endif
+
+// Get the path to the user's downloads directory.
+bool GetUserDownloadsDirectory(FilePath* result);
+
+// The path to the user's desktop.
+bool GetUserDesktop(FilePath* result);
+
+#if defined(OS_MACOSX)
+// The "versioned directory" is a directory in the browser .app bundle. It
+// contains the bulk of the application, except for the things that the system
+// requires be located at spepcific locations. The versioned directory is
+// in the .app at Contents/Versions/w.x.y.z.
+FilePath GetVersionedDirectory();
+
+// This overrides the directory returned by |GetVersionedDirectory()|, to be
+// used when |GetVersionedDirectory()| can't automatically determine the proper
+// location. This is the case when the browser didn't load itself but by, e.g.,
+// the app mode loader. This should be called before |ChromeMain()|. This takes
+// ownership of the object |path| and the caller must not delete it.
+void SetOverrideVersionedDirectory(const FilePath* path);
+
+// Most of the application is further contained within the framework. The
+// framework bundle is located within the versioned directory at a specific
+// path. The only components in the versioned directory not included in the
+// framework are things that also depend on the framework, such as the helper
+// app bundle.
+FilePath GetFrameworkBundlePath();
+#endif // OS_MACOSX
+
+} // namespace chrome
+
+#endif // CHROME_COMMON_CHROME_PATHS_INTERNAL_H_
diff --git a/chrome/common/chrome_paths_linux.cc b/chrome/common/chrome_paths_linux.cc
new file mode 100644
index 0000000..32a9925
--- /dev/null
+++ b/chrome/common/chrome_paths_linux.cc
@@ -0,0 +1,76 @@
+// Copyright (c) 2010 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/common/chrome_paths_internal.h"
+
+#include "base/env_var.h"
+#include "base/file_util.h"
+#include "base/scoped_ptr.h"
+#include "base/xdg_util.h"
+
+namespace chrome {
+
+// See http://standards.freedesktop.org/basedir-spec/basedir-spec-latest.html
+// for a spec on where config files go. The net effect for most
+// systems is we use ~/.config/chromium/ for Chromium and
+// ~/.config/google-chrome/ for official builds.
+// (This also helps us sidestep issues with other apps grabbing ~/.chromium .)
+bool GetDefaultUserDataDirectory(FilePath* result) {
+ scoped_ptr<base::EnvVarGetter> env(base::EnvVarGetter::Create());
+ FilePath config_dir(
+ base::GetXDGDirectory(env.get(), "XDG_CONFIG_HOME", ".config"));
+#if defined(GOOGLE_CHROME_BUILD)
+ *result = config_dir.Append("google-chrome");
+#else
+ *result = config_dir.Append("chromium");
+#endif
+ return true;
+}
+
+bool GetChromeFrameUserDataDirectory(FilePath* result) {
+ scoped_ptr<base::EnvVarGetter> env(base::EnvVarGetter::Create());
+ FilePath config_dir(
+ base::GetXDGDirectory(env.get(), "XDG_CONFIG_HOME", ".config"));
+#if defined(GOOGLE_CHROME_BUILD)
+ *result = config_dir.Append("google-chrome-frame");
+#else
+ *result = config_dir.Append("chrome-frame");
+#endif
+ return true;
+}
+
+bool GetUserDocumentsDirectory(FilePath* result) {
+ scoped_ptr<base::EnvVarGetter> env(base::EnvVarGetter::Create());
+ *result = base::GetXDGUserDirectory(env.get(), "DOCUMENTS", "Documents");
+ return true;
+}
+
+// We respect the user's preferred download location, unless it is
+// ~ or their desktop directory, in which case we default to ~/Downloads.
+bool GetUserDownloadsDirectory(FilePath* result) {
+ scoped_ptr<base::EnvVarGetter> env(base::EnvVarGetter::Create());
+ *result = base::GetXDGUserDirectory(env.get(), "DOWNLOAD", "Downloads");
+
+ FilePath home = file_util::GetHomeDir();
+ if (*result == home) {
+ *result = home.Append("Downloads");
+ return true;
+ }
+
+ FilePath desktop;
+ GetUserDesktop(&desktop);
+ if (*result == desktop) {
+ *result = home.Append("Downloads");
+ }
+
+ return true;
+}
+
+bool GetUserDesktop(FilePath* result) {
+ scoped_ptr<base::EnvVarGetter> env(base::EnvVarGetter::Create());
+ *result = base::GetXDGUserDirectory(env.get(), "DESKTOP", "Desktop");
+ return true;
+}
+
+} // namespace chrome
diff --git a/chrome/common/chrome_paths_mac.mm b/chrome/common/chrome_paths_mac.mm
new file mode 100644
index 0000000..c7db483
--- /dev/null
+++ b/chrome/common/chrome_paths_mac.mm
@@ -0,0 +1,108 @@
+// Copyright (c) 2006-2008 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/common/chrome_paths_internal.h"
+
+#import <Cocoa/Cocoa.h>
+
+#include "base/base_paths.h"
+#include "base/logging.h"
+#include "base/mac_util.h"
+#include "base/path_service.h"
+#include "chrome/common/chrome_constants.h"
+
+namespace {
+const FilePath* g_override_versioned_directory = NULL;
+} // namespace
+
+namespace chrome {
+
+bool GetDefaultUserDataDirectory(FilePath* result) {
+ bool success = false;
+ if (result && PathService::Get(base::DIR_APP_DATA, result)) {
+#if defined(GOOGLE_CHROME_BUILD)
+ *result = result->Append("Google").Append("Chrome");
+#else
+ *result = result->Append("Chromium");
+#endif
+ success = true;
+ }
+ return success;
+}
+
+bool GetChromeFrameUserDataDirectory(FilePath* result) {
+ bool success = false;
+ if (result && PathService::Get(base::DIR_APP_DATA, result)) {
+#if defined(GOOGLE_CHROME_BUILD)
+ *result = result->Append("Google").Append("Chrome Frame");
+#else
+ *result = result->Append("Chrome Frame");
+#endif
+ success = true;
+ }
+ return success;
+}
+
+bool GetUserDocumentsDirectory(FilePath* result) {
+ return mac_util::GetUserDirectory(NSDocumentDirectory, result);
+}
+
+bool GetUserDownloadsDirectory(FilePath* result) {
+ return mac_util::GetUserDirectory(NSDownloadsDirectory, result);
+}
+
+bool GetUserDesktop(FilePath* result) {
+ return mac_util::GetUserDirectory(NSDesktopDirectory, result);
+}
+
+FilePath GetVersionedDirectory() {
+ if (g_override_versioned_directory)
+ return *g_override_versioned_directory;
+
+ // Start out with the path to the running executable.
+ FilePath path;
+ PathService::Get(base::FILE_EXE, &path);
+
+ // One step up to MacOS, another to Contents.
+ path = path.DirName().DirName();
+ DCHECK_EQ(path.BaseName().value(), "Contents");
+
+ if (mac_util::IsBackgroundOnlyProcess()) {
+ // path identifies the helper .app's Contents directory in the browser
+ // .app's versioned directory. Go up two steps to get to the browser
+ // .app's versioned directory.
+ path = path.DirName().DirName();
+ DCHECK_EQ(path.BaseName().value(), kChromeVersion);
+ } else {
+ // Go into the versioned directory.
+ path = path.Append("Versions").Append(kChromeVersion);
+ }
+
+ return path;
+}
+
+void SetOverrideVersionedDirectory(const FilePath* path) {
+ if (path != g_override_versioned_directory) {
+ delete g_override_versioned_directory;
+ g_override_versioned_directory = path;
+ }
+}
+
+FilePath GetFrameworkBundlePath() {
+ // It's tempting to use +[NSBundle bundleWithIdentifier:], but it's really
+ // slow (about 30ms on 10.5 and 10.6), despite Apple's documentation stating
+ // that it may be more efficient than +bundleForClass:. +bundleForClass:
+ // itself takes 1-2ms. Getting an NSBundle from a path, on the other hand,
+ // essentially takes no time at all, at least when the bundle has already
+ // been loaded as it will have been in this case. The FilePath operations
+ // needed to compute the framework's path are also effectively free, so that
+ // is the approach that is used here. NSBundle is also documented as being
+ // not thread-safe, and thread safety may be a concern here.
+
+ // The framework bundle is at a known path and name from the browser .app's
+ // versioned directory.
+ return GetVersionedDirectory().Append(kFrameworkName);
+}
+
+} // namespace chrome
diff --git a/chrome/common/chrome_paths_win.cc b/chrome/common/chrome_paths_win.cc
new file mode 100644
index 0000000..4d7709d
--- /dev/null
+++ b/chrome/common/chrome_paths_win.cc
@@ -0,0 +1,94 @@
+// Copyright (c) 2006-2008 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/common/chrome_paths_internal.h"
+
+#include <windows.h>
+#include <knownfolders.h>
+#include <shellapi.h>
+#include <shlobj.h>
+#include <shobjidl.h>
+
+#include "app/win_util.h"
+#include "base/file_path.h"
+#include "base/path_service.h"
+#include "base/scoped_comptr_win.h"
+#include "chrome/common/chrome_constants.h"
+#include "chrome/installer/util/browser_distribution.h"
+
+namespace chrome {
+
+bool GetDefaultUserDataDirectory(FilePath* result) {
+ if (!PathService::Get(base::DIR_LOCAL_APP_DATA, result))
+ return false;
+ BrowserDistribution* dist = BrowserDistribution::GetDistribution();
+ *result = result->Append(dist->GetInstallSubDir());
+ *result = result->Append(chrome::kUserDataDirname);
+ return true;
+}
+
+bool GetChromeFrameUserDataDirectory(FilePath* result) {
+ if (!PathService::Get(base::DIR_LOCAL_APP_DATA, result))
+ return false;
+#if defined(GOOGLE_CHROME_BUILD)
+ *result = result->Append(FILE_PATH_LITERAL("Google"));
+#endif
+ *result = result->Append(L"Chrome Frame");
+ *result = result->Append(chrome::kUserDataDirname);
+ return true;
+}
+
+bool GetUserDocumentsDirectory(FilePath* result) {
+ wchar_t path_buf[MAX_PATH];
+ if (FAILED(SHGetFolderPath(NULL, CSIDL_MYDOCUMENTS, NULL,
+ SHGFP_TYPE_CURRENT, path_buf)))
+ return false;
+ *result = FilePath(path_buf);
+ return true;
+}
+
+// Return a default path for downloads that is safe.
+// We just use 'Downloads' under DIR_USER_DOCUMENTS. Localizing
+// 'downloads' is not a good idea because Chrome's UI language
+// can be changed.
+bool GetUserDownloadsDirectorySafe(FilePath* result) {
+ if (!GetUserDocumentsDirectory(result))
+ return false;
+
+ *result = result->Append(L"Downloads");
+ return true;
+}
+
+// On Vista and higher, use the downloads known folder. Since it can be
+// relocated to point to a "dangerous" folder, callers should validate that the
+// returned path is not dangerous before using it.
+bool GetUserDownloadsDirectory(FilePath* result) {
+ typedef HRESULT (WINAPI *GetKnownFolderPath)(
+ REFKNOWNFOLDERID, DWORD, HANDLE, PWSTR*);
+ GetKnownFolderPath f = reinterpret_cast<GetKnownFolderPath>(
+ GetProcAddress(GetModuleHandle(L"shell32.dll"), "SHGetKnownFolderPath"));
+ win_util::CoMemReleaser<wchar_t> path_buf;
+ if (f && SUCCEEDED(f(FOLDERID_Downloads, 0, NULL, &path_buf))) {
+ *result = FilePath(std::wstring(path_buf));
+ return true;
+ }
+ return GetUserDownloadsDirectorySafe(result);
+}
+
+bool GetUserDesktop(FilePath* result) {
+ // We need to go compute the value. It would be nice to support paths
+ // with names longer than MAX_PATH, but the system functions don't seem
+ // to be designed for it either, with the exception of GetTempPath
+ // (but other things will surely break if the temp path is too long,
+ // so we don't bother handling it.
+ wchar_t system_buffer[MAX_PATH];
+ system_buffer[0] = 0;
+ if (FAILED(SHGetFolderPath(NULL, CSIDL_DESKTOPDIRECTORY, NULL,
+ SHGFP_TYPE_CURRENT, system_buffer)))
+ return false;
+ *result = FilePath(system_buffer);
+ return true;
+}
+
+} // namespace chrome
diff --git a/chrome/common/chrome_plugin_api.h b/chrome/common/chrome_plugin_api.h
new file mode 100644
index 0000000..e5230cd
--- /dev/null
+++ b/chrome/common/chrome_plugin_api.h
@@ -0,0 +1,566 @@
+// Copyright (c) 2009 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.
+//
+// This header specifies the Chrome Plugin API. It is based heavily on NPAPI.
+// The key difference is that Chrome plugins can be loaded for the lifetime
+// of the browser, and are not tied to a specific web page.
+//
+// NOTE: This API is not final and may change or go away at any point.
+//
+// All strings in the API are UTF8-encoded unless otherwise noted.
+
+#ifndef CHROME_COMMON_CHROME_PLUGIN_API_H__
+#define CHROME_COMMON_CHROME_PLUGIN_API_H__
+
+#include "base/basictypes.h"
+
+#ifndef STDCALL
+#ifdef WIN32
+#define STDCALL __stdcall
+#else
+#define STDCALL
+#endif // WIN32
+#endif // STDCALL
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+// The current version of the API, used by the 'version' field of CPPluginFuncs
+// and CPBrowserFuncs.
+#define CP_MAJOR_VERSION 0
+#define CP_MINOR_VERSION 11
+#define CP_VERSION ((CP_MAJOR_VERSION << 8) | (CP_MINOR_VERSION))
+
+#define CP_GET_MAJOR_VERSION(version) ((version & 0xff00) >> 8)
+#define CP_GET_MINOR_VERSION(version) (version & 0x00ff)
+
+typedef unsigned char CPBool;
+
+// Chrome plugins can be loaded into different process types.
+typedef enum {
+ CP_PROCESS_BROWSER = 0,
+ CP_PROCESS_PLUGIN,
+ CP_PROCESS_RENDERER,
+} CPProcessType;
+
+// Return codes. Error values are negative.
+typedef enum {
+ // No error
+ CPERR_SUCCESS = 0,
+
+ // (network) An asynchronous IO operation is not complete
+ CPERR_IO_PENDING = -1,
+
+ // Generic failure
+ CPERR_FAILURE = -2,
+
+ // The API versions used by plugin and host are incompatible
+ CPERR_INVALID_VERSION = -3,
+
+ // The operation was cancelled
+ CPERR_CANCELLED = -4,
+
+ // An invalid parameter was passed
+ CPERR_INVALID_PARAMETER = -5,
+} CPError;
+
+// Types of response info metadata to query using CPP_GetResponseInfo.
+typedef enum {
+ // HTTP status code.
+ CPRESPONSEINFO_HTTP_STATUS = 0,
+
+ // Raw headers from the server, including the status line. Headers should
+ // be delimited by "\0", and end with "\0\0" (a blank line).
+ CPRESPONSEINFO_HTTP_RAW_HEADERS = 1,
+} CPResponseInfoType;
+
+// An identifier for the plugin used by the browser.
+typedef struct _CPID_t {
+ int unused;
+} CPID_t;
+typedef struct _CPID_t* CPID;
+
+// An identifier that encapsulates the browsing context needed by various APIs.
+// This includes information about what tab a request was made from, and what
+// profile is active. Note that this ID is global to all processes, so it can
+// be passed from one process to another. The value 0 is reserved for an
+// undefined context.
+typedef uint32 CPBrowsingContext;
+
+// Types of context info to query using CPB_GetBrowsingContextInfo.
+typedef enum {
+ // The data directory for the profile associated with this context as a
+ // pointer to a null-terminated string. The plugin can save persistent data
+ // to this directory. The returned pointer should be freed using CPB_Free.
+ CPBROWSINGCONTEXT_DATA_DIR_PTR = 0,
+
+ // The locale language code used for the browser UI. The returned pointer
+ // should be freed using CPB_Free.
+ CPBROWSINGCONTEXT_UI_LOCALE_PTR = 1,
+} CPBrowsingContextInfoType;
+
+// A network request object.
+typedef struct _CPRequest {
+ void* pdata; // plugin private data
+ const char* url; // the URL being requested
+ const char* method; // the request method as an uppercase string (ex: "GET")
+ CPBrowsingContext context; // context in which this request was made
+} CPRequest;
+
+typedef enum {
+ CPREQUESTLOAD_NORMAL = 0,
+
+ // This is "normal reload", meaning an if-none-match/if-modified-since query
+ CPREQUESTLOAD_VALIDATE_CACHE = 1 << 0,
+
+ // This is "shift-reload", meaning a "pragma: no-cache" end-to-end fetch
+ CPREQUESTLOAD_BYPASS_CACHE = 1 << 1,
+
+ // This is a back/forward style navigation where the cached content should
+ // be preferred over any protocol specific cache validation.
+ CPREQUESTLOAD_PREFERRING_CACHE = 1 << 2,
+
+ // This is a navigation that will fail if it cannot serve the requested
+ // resource from the cache (or some equivalent local store).
+ CPREQUESTLOAD_ONLY_FROM_CACHE = 1 << 3,
+
+ // This is a navigation that will not use the cache at all. It does not
+ // impact the HTTP request headers.
+ CPREQUESTLOAD_DISABLE_CACHE = 1 << 4,
+
+ // This navigation should not be intercepted by plugins.
+ CPREQUESTLOAD_DISABLE_INTERCEPT = 1 << 5,
+
+ // This request should be loaded synchronously. What this means is that
+ // CPR_StartRequest and CPR_Read will never return CPERR_IO_PENDING - they
+ // will block until a response is available, and return success or failure.
+ CPREQUESTLOAD_SYNCHRONOUS = 1 << 20,
+} CPRequestLoadFlags;
+
+//
+// Functions provided by plugin to host.
+//
+
+// Called when the browser is unloading the plugin.
+typedef CPError (STDCALL *CPP_ShutdownFunc)(void);
+
+// Returns true if the plugin is interested in handling this request.
+typedef CPBool (STDCALL *CPP_ShouldInterceptRequestFunc)(CPRequest* request);
+
+// Called when an HTML dialog was closed. json_retval is the JSON string
+// containing the return value sent back by the dialog (using Chrome's
+// JavaScript DOM bindings).
+typedef void (STDCALL *CPP_HtmlDialogClosedFunc)(
+ void* plugin_context, const char* json_retval);
+
+// Asks the plugin to handle the given command. 'command_data' is command-
+// specific data used for some builtin commands: see gears_api.h for
+// possible types. It is only valid for the duration of this call.
+typedef CPError (STDCALL *CPP_HandleCommandFunc)(
+ CPBrowsingContext context, int command, void* command_data);
+
+//
+// Functions provided by host to plugin.
+//
+
+// Asks the host to handle the given command. 'command_data' is
+// command-specific data used for some builtin commands: see gears_api.h for
+// possible types. It is only valid for the duration of this call.
+typedef CPError (STDCALL *CPB_HandleCommandFunc)(
+ CPID id, CPBrowsingContext context, int command, void* command_data);
+
+// Asks the browser to enable/disable request interception for this plugin for
+// the given schemes. 'schemes' is an array of strings containing the scheme
+// names the plugin wishes to handle; case is ignored. If 'schemes' is NULL or
+// empty, request interception is disabled for this plugin. Multiple calls to
+// this function will add to the existing set of enabled schemes. The browser
+// should call the plugin's CPP_ShouldInterceptRequestFunc for any network
+// requests it makes that match a given scheme. The browser may choose not to
+// allow the plugin to intercept certain protocols.
+typedef void (STDCALL *CPB_EnableRequestInterceptFunc)(
+ CPID id, const char** schemes, uint32 num_schemes);
+
+// Asks the browser to create a request object for the given method/url.
+// Returns CPERR_SUCCESS and puts the new object into the 'request' field on
+// success, or an error code on failure. The plugin must call CPR_EndRequest
+// to clean up the request object when it is done with it.
+typedef CPError (STDCALL *CPB_CreateRequestFunc)(
+ CPID id, CPBrowsingContext context, const char* method, const char* url,
+ CPRequest** request);
+
+// Queries the browser's cookie store for cookies set for the given URL.
+// Sets 'cookies' to an allocated string containing the cookies as
+// semicolon-delimited "name=value" pairs on success, NULL on failure.
+// The memory should be freed using CPB_Free when done.
+typedef CPError (STDCALL *CPB_GetCookiesFunc)(
+ CPID id, CPBrowsingContext context, const char* url, char** cookies);
+
+// Allocates memory for the given size using the browser's allocator. Call
+// CPB_Free when done.
+typedef void* (STDCALL *CPB_AllocFunc)(uint32 size);
+
+// Frees a pointer allocated by CPB_Alloc.
+typedef void (STDCALL *CPB_FreeFunc)(void* memory);
+
+
+// Sets a flag that influences when the plugin process created to host
+// the plugin is shutdown. Generally, the plugin process is terminated
+// when no more plugin instances exist, this is the default behavior.
+// If keep_alive is non-zero, the process will not be terminated when
+// the instance count goes to zero. Note: a non-zero keep_alive value
+// does not prevent the plugin process from being terminated upon
+// overall browser shutdown.
+typedef void (STDCALL *CPB_SetKeepProcessAliveFunc)(CPID id,
+ CPBool keep_alive);
+
+// Asks the browser to show an HTML dialog to the user. The dialog contents
+// should be loaded from the given URL. The 'json_arguments' is a JSON string
+// that the dialog can fetch using Chrome's JavaScript DOM bindings. This call
+// will block until the dialog is closed. On success, 'json_retval' will
+// contain the JSON string sent back by the dialog (using Chrome's JavaScript
+// DOM bindings), and CPERR_SUCCESS is returned. 'json_retval' should be freed
+// using CPB_Free when done.
+typedef CPError (STDCALL *CPB_ShowHtmlDialogModalFunc)(
+ CPID id, CPBrowsingContext context, const char* url, int width, int height,
+ const char* json_arguments, char** json_retval);
+
+// Similar to CPB_ShowHtmlDialogModalFunc, but does not block. When the dialog
+// is closed, CPP_HtmlDialogClosed is called with the JSON return value and the
+// given 'plugin_context', which may be used by the plugin to associate other
+// data with the dialog.
+typedef CPError (STDCALL *CPB_ShowHtmlDialogFunc)(
+ CPID id, CPBrowsingContext context, const char* url, int width, int height,
+ const char* json_arguments, void* plugin_context);
+
+// Get the browsing context associated with the given NPAPI instance.
+typedef CPBrowsingContext (STDCALL *CPB_GetBrowsingContextFromNPPFunc)(
+ struct _NPP* npp);
+
+// Queries for some meta data associated with the given browsing context. See
+// CPBrowsingContextInfoType for possible queries. If buf_size is too small to
+// contain the entire data, the return value will indicate the size required.
+// Otherwise, the return value is a CPError or CPERR_SUCCESS.
+typedef int (STDCALL *CPB_GetBrowsingContextInfoFunc)(
+ CPID id, CPBrowsingContext context, CPBrowsingContextInfoType type,
+ void* buf, uint32 buf_size);
+
+// Given an URL string, returns the string of command-line arguments that should
+// be passed to start the browser at the given URL. 'arguments' should be freed
+// using CPB_Free when done.
+typedef CPError (STDCALL *CPB_GetCommandLineArgumentsFunc)(
+ CPID id, CPBrowsingContext context, const char* url, char** arguments);
+
+// Asks the browser to let the plugin handle the given UI command. When the
+// command is invoked, the browser will call CPP_HandleCommand. 'command'
+// should be an integer identifier. Currently only builtin commands are
+// supported, but in the future we may want to let plugins add custom menu
+// commands with their own descriptions.
+typedef CPError (STDCALL *CPB_AddUICommandFunc)(CPID id, int command);
+
+//
+// Functions related to making network requests.
+// Both the host and plugin will implement their own versions of these.
+//
+
+// Starts the request. Returns CPERR_SUCCESS if the request could be started
+// immediately, at which point the response info is available to be read.
+// Returns CPERR_IO_PENDING if an asynchronous operation was started, and the
+// caller should wait for CPRR_StartCompleted to be called before reading the
+// response info. Returns an error code on failure.
+typedef CPError (STDCALL *CPR_StartRequestFunc)(CPRequest* request);
+
+// Stops or cancels the request. The caller should not access the request
+// object after this call. If an asynchronous IO operation is pending, the
+// operation is aborted and the caller will not receive a callback for it.
+typedef void (STDCALL *CPR_EndRequestFunc)(CPRequest* request, CPError reason);
+
+// Sets the additional request headers to append to the standard headers that
+// would normally be made with this request. Headers should be \r\n-delimited,
+// with no terminating \r\n. Extra headers are not checked against the standard
+// headers for duplicates. Must be called before CPRR_StartCompletedFunc.
+// Plugins should avoid setting the following headers: User-Agent,
+// Content-Length.
+typedef void (STDCALL *CPR_SetExtraRequestHeadersFunc)(CPRequest* request,
+ const char* headers);
+
+// Sets the load flags for this request. 'flags' is a bitwise-OR of
+// CPRequestLoadFlags. Must be called before CPRR_StartCompletedFunc.
+typedef void (STDCALL *CPR_SetRequestLoadFlagsFunc)(CPRequest* request,
+ uint32 flags);
+
+// Appends binary data to the request body of a POST or PUT request. The caller
+// should set the "Content-Type" header to the appropriate mime type using
+// CPR_SetExtraRequestHeadersFunc. This can be called multiple times to append
+// a sequence of data segments to upload. Must be called before
+// CPR_StartRequestFunc.
+typedef void (STDCALL *CPR_AppendDataToUploadFunc)(
+ CPRequest* request, const char* bytes, int bytes_len);
+
+// Appends the contents of a file to the request body of a POST or PUT request.
+// 'offset' and 'length' can be used to append a subset of the file. Pass zero
+// for 'length' and 'offset' to upload the entire file. 'offset'
+// indicates where the data to upload begins in the file. 'length' indicates
+// how much of the file to upload. A 'length' of zero is interpretted as to
+// end-of-file. If 'length' and 'offset' indicate a range beyond end of file,
+// the amount sent is clipped at eof.
+// See CPR_AppendDataToUploadFunc for additional usage information.
+// (added in v0.4)
+typedef CPError (STDCALL *CPR_AppendFileToUploadFunc)(
+ CPRequest* request, const char* filepath, uint64 offset, uint64 length);
+
+// Queries for some response meta data. See CPResponseInfoType for possible
+// queries. If buf_size is too small to contain the entire data, the return
+// value will indicate the size required. Otherwise, the return value is a
+// CPError or CPERR_SUCCESS.
+typedef int (STDCALL *CPR_GetResponseInfoFunc)(
+ CPRequest* request, CPResponseInfoType type,
+ void* buf, uint32 buf_size);
+
+// Attempts to read a request's response data. The number of bytes read is
+// returned; 0 indicates an EOF. CPERR_IO_PENDING is returned if an
+// asynchronous operation was started, and CPRR_ReadCompletedFunc will be called
+// when it completes; 'buf' must be available until the operation completes.
+// Returns an error code on failure.
+typedef int (STDCALL *CPR_ReadFunc)(
+ CPRequest* request, void* buf, uint32 buf_size);
+
+//
+// Functions related to serving network requests.
+// Both the host and plugin will implement their own versions of these.
+//
+
+// Called upon a server-initiated redirect. The request will still hold the
+// original URL, and 'new_url' will be the redirect destination.
+typedef void (STDCALL *CPRR_ReceivedRedirectFunc)(CPRequest* request,
+ const char* new_url);
+
+// Called when an asynchronous CPR_StartRequest call has completed, once all
+// redirects are followed. On success, 'result' holds CPERR_SUCCESS and the
+// response info is available to be read via CPR_GetResponseInfo. On error,
+// 'result' holds the error code.
+typedef void (STDCALL *CPRR_StartCompletedFunc)(CPRequest* request,
+ CPError result);
+
+// Called when an asynchronous CPR_Read call has completed. On success,
+// 'bytes_read' will hold the number of bytes read into the buffer that was
+// passed to CPR_Read; 0 indicates an EOF, and the request object will be
+// destroyed after the call completes. On failure, 'bytes_read' holds the error
+// code.
+typedef void (STDCALL *CPRR_ReadCompletedFunc)(CPRequest* request,
+ int bytes_read);
+
+// Called as upload progress is being made for async POST requests.
+// (added in v0.5)
+typedef void (STDCALL *CPRR_UploadProgressFunc)(CPRequest* request,
+ uint64 position,
+ uint64 size);
+
+//
+// Functions to support the sending and receipt of messages between processes.
+//
+
+// Returns true if the plugin process is running
+typedef CPBool (STDCALL *CPB_IsPluginProcessRunningFunc)(CPID id);
+
+// Returns the type of the current process.
+typedef CPProcessType (STDCALL *CPB_GetProcessTypeFunc)(CPID id);
+
+// Asks the browser to send raw data to the other process hosting an instance of
+// this plugin. If needed, the plugin process will be started prior to sending
+// the message.
+typedef CPError (STDCALL *CPB_SendMessageFunc)(CPID id,
+ const void *data,
+ uint32 data_len);
+
+// Asks the browser to send raw data to the other process hosting an instance of
+// this plugin. This function only works from the plugin or renderer process.
+// This function blocks until the message is processed. The memory should be
+// freed using CPB_Free when done.
+typedef CPError (STDCALL *CPB_SendSyncMessageFunc)(CPID id,
+ const void *data,
+ uint32 data_len,
+ void **retval,
+ uint32 *retval_len);
+
+// This function asynchronously calls the provided function on the plugin
+// thread. user_data is passed as the argument to the function.
+typedef CPError (STDCALL *CPB_PluginThreadAsyncCallFunc)(CPID id,
+ void (*func)(void *),
+ void *user_data);
+
+// This function creates an open file dialog. The process is granted access
+// to any files that are selected. |multiple_files| determines if more than
+// one file can be selected.
+typedef CPError (STDCALL *CPB_OpenFileDialogFunc)(CPID id,
+ CPBrowsingContext context,
+ bool multiple_files,
+ const char *title,
+ const char *filter,
+ void *user_data);
+
+// Informs the plugin of raw data having been sent from another process.
+typedef void (STDCALL *CPP_OnMessageFunc)(void *data, uint32 data_len);
+
+// Informs the plugin of raw data having been sent from another process.
+typedef void (STDCALL *CPP_OnSyncMessageFunc)(void *data, uint32 data_len,
+ void **retval,
+ uint32 *retval_len);
+
+// Informs the plugin that the file dialog has completed, and contains the
+// results.
+typedef void (STDCALL *CPP_OnFileDialogResultFunc)(void *data,
+ const char **files,
+ uint32 files_len);
+
+// Asks the browser to verify that NPObject* 'event' is the current drag event
+// the browser is dispatching, and extract drag data from the event if so. On
+// success, returns the drag 'identity' (an up-counter that the browser chrome
+// increases each time a user drag enters a renderer tab), the drag 'event_id'
+// and the 'drag_type' being a utf8 encoded string with values "Files", "Text"
+// or "URL". If 'add_data' is true, also return the 'drag_data', again a utf8
+// encoded string with the data for the drag type. For drag type "Files", the
+// data is a backspace delimited list of file paths.
+//
+// The call fails with a CPError if 'event' is an invalid drag event, and sets
+// the 'identity' and 'event_id' to 0. Note: on success, non-NULL 'drag_type'
+// and 'drag_data' should be freed with CPB_Free() when done.
+typedef CPError (STDCALL *CPB_GetDragDataFunc)(
+ CPID id, CPBrowsingContext context, struct NPObject* event, bool add_data,
+ int32* identity, int32* event_id, char** drag_type, char** drag_data);
+
+// Asks the browser to verify that NPObject* 'event' is the current drag event
+// the browser is dispatching and show the requested drop 'effect' if so. The
+// browser displays drop effects during dragenter and dragover events, to give
+// user visible feedback (with a drag cursor, typically) to indicate whether a
+// subsequent drop event will succeed or not. The implementation supports the
+// so-called "copy" and "none" effects. When 'effect' is non-zero, the "copy"
+// effect is shown. Otherwise, the "none" effect is shown, which prevents the
+// subsequent drop event from succeeding. Returns CPError on failure, meaning
+// the 'event' is an invalid drag event.
+//
+// Note: 'effect' is int to allow for new effects in future. For example, the
+// HTML5-defined drop effects "move" and "link".
+typedef CPError (STDCALL *CPB_SetDropEffectFunc)(
+ CPID id, CPBrowsingContext context, struct NPObject* event, int effect);
+
+// For drag type "Files", the drag data returned by CPB_GetDragDataFunc() is a
+// backspace delimited list of file paths. Use this routine to pass that data
+// to the browser process to verify that the renderer has permission to access
+// the files. Returns CPERR_SUCCESS if access is allowed.
+typedef CPError (STDCALL *CPB_AllowFileDropFunc)(
+ CPID id, CPBrowsingContext context, const char* file_drag_data);
+
+// Function table for issuing requests using via the other side's network stack.
+// For the plugin, this functions deal with issuing requests through the
+// browser. For the browser, these functions deal with allowing the plugin to
+// intercept requests.
+typedef struct _CPRequestFuncs {
+ uint16 size;
+ CPR_SetExtraRequestHeadersFunc set_extra_request_headers;
+ CPR_SetRequestLoadFlagsFunc set_request_load_flags;
+ CPR_AppendDataToUploadFunc append_data_to_upload;
+ CPR_StartRequestFunc start_request;
+ CPR_EndRequestFunc end_request;
+ CPR_GetResponseInfoFunc get_response_info;
+ CPR_ReadFunc read;
+ CPR_AppendFileToUploadFunc append_file_to_upload;
+} CPRequestFuncs;
+
+// Function table for handling requests issued by the other side. For the
+// plugin, these deal with serving requests that the plugin has intercepted. For
+// the browser, these deal with serving requests that the plugin has issued
+// through us.
+typedef struct _CPResponseFuncs {
+ uint16 size;
+ CPRR_ReceivedRedirectFunc received_redirect;
+ CPRR_StartCompletedFunc start_completed;
+ CPRR_ReadCompletedFunc read_completed;
+ CPRR_UploadProgressFunc upload_progress;
+} CPResponseFuncs;
+
+// Function table of CPP functions (functions provided by plugin to host). This
+// structure is filled in by the plugin in the CP_Initialize call, except for
+// the 'size' field, which is set by the browser. The version fields should be
+// set to those that the plugin was compiled using.
+typedef struct _CPPluginFuncs {
+ uint16 size;
+ uint16 version;
+ CPRequestFuncs* request_funcs;
+ CPResponseFuncs* response_funcs;
+ CPP_ShutdownFunc shutdown;
+ CPP_ShouldInterceptRequestFunc should_intercept_request;
+ CPP_OnMessageFunc on_message;
+ CPP_HtmlDialogClosedFunc html_dialog_closed;
+ CPP_HandleCommandFunc handle_command;
+ CPP_OnSyncMessageFunc on_sync_message;
+ CPP_OnFileDialogResultFunc on_file_dialog_result;
+} CPPluginFuncs;
+
+// Function table CPB functions (functions provided by host to plugin).
+// This structure is filled in by the browser and provided to the plugin. The
+// plugin will likely want to save a copy of this structure to make calls
+// back to the browser.
+typedef struct _CPBrowserFuncs {
+ uint16 size;
+ uint16 version;
+ CPRequestFuncs* request_funcs;
+ CPResponseFuncs* response_funcs;
+ CPB_EnableRequestInterceptFunc enable_request_intercept;
+ CPB_CreateRequestFunc create_request;
+ CPB_GetCookiesFunc get_cookies;
+ CPB_AllocFunc alloc;
+ CPB_FreeFunc free;
+ CPB_SetKeepProcessAliveFunc set_keep_process_alive;
+ CPB_ShowHtmlDialogModalFunc show_html_dialog_modal;
+ CPB_ShowHtmlDialogFunc show_html_dialog;
+ CPB_IsPluginProcessRunningFunc is_plugin_process_running;
+ CPB_GetProcessTypeFunc get_process_type;
+ CPB_SendMessageFunc send_message;
+ CPB_GetBrowsingContextFromNPPFunc get_browsing_context_from_npp;
+ CPB_GetBrowsingContextInfoFunc get_browsing_context_info;
+ CPB_GetCommandLineArgumentsFunc get_command_line_arguments;
+ CPB_AddUICommandFunc add_ui_command;
+ CPB_HandleCommandFunc handle_command;
+ CPB_SendSyncMessageFunc send_sync_message;
+ CPB_PluginThreadAsyncCallFunc plugin_thread_async_call;
+ CPB_OpenFileDialogFunc open_file_dialog;
+ CPB_GetDragDataFunc get_drag_data;
+ CPB_SetDropEffectFunc set_drop_effect;
+ CPB_AllowFileDropFunc allow_file_drop;
+} CPBrowserFuncs;
+
+
+//
+// DLL exports
+//
+
+// This export is optional.
+// Prior to calling CP_Initialize, the browser may negotiate with the plugin
+// regarding which version of the CPAPI to utilize. 'min_version' is the
+// lowest version of the interface supported by the browser, 'max_version' is
+// the highest supported version. The plugin can specify which version within
+// the range should be used. This version will be reflected in the version field
+// of the CPBrowserFuncs struct passed to CP_Initialize. If this function
+// returns an error code, CP_Initialize will not be called. If function is not
+// exported by the chrome plugin module, CP_Initiailize will be called with
+// a version of the host's choosing.
+typedef CPError (STDCALL *CP_VersionNegotiateFunc)(
+ uint16 min_version, uint16 max_version, uint16 *selected_version);
+
+// 'bfuncs' are the browser functions provided to the plugin. 'id' is the
+// plugin identifier that the plugin should use when calling browser functions.
+// The plugin should initialize 'pfuncs' with pointers to its own functions,
+// or return an error code.
+// All functions and entry points should be called on the same thread. The
+// plugin should not attempt to call a browser function from a thread other
+// than the one CP_InitializeFunc is called from.
+typedef CPError (STDCALL *CP_InitializeFunc)(
+ CPID id, const CPBrowserFuncs* bfuncs, CPPluginFuncs* pfuncs);
+
+#ifdef __cplusplus
+} // extern "C"
+#endif
+
+#endif // CHROME_COMMON_CHROME_PLUGIN_API_H_
diff --git a/chrome/common/chrome_plugin_lib.cc b/chrome/common/chrome_plugin_lib.cc
new file mode 100644
index 0000000..daf6bb7
--- /dev/null
+++ b/chrome/common/chrome_plugin_lib.cc
@@ -0,0 +1,290 @@
+// Copyright (c) 2006-2008 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/common/chrome_plugin_lib.h"
+
+#include "base/command_line.h"
+#include "base/hash_tables.h"
+#include "base/histogram.h"
+#include "base/message_loop.h"
+#include "base/path_service.h"
+#include "base/perftimer.h"
+#include "base/thread.h"
+#if defined(OS_WIN)
+#include "base/registry.h"
+#endif
+#include "base/string_util.h"
+#include "chrome/common/chrome_counters.h"
+#include "chrome/common/chrome_switches.h"
+#include "chrome/common/notification_service.h"
+#include "chrome/common/chrome_paths.h"
+#include "webkit/glue/plugins/plugin_list.h"
+
+using base::TimeDelta;
+
+// TODO(port): revisit when plugins happier
+#if defined(OS_WIN)
+const TCHAR ChromePluginLib::kRegistryChromePlugins[] =
+ _T("Software\\Google\\Chrome\\Plugins");
+static const TCHAR kRegistryLoadOnStartup[] = _T("LoadOnStartup");
+static const TCHAR kRegistryPath[] = _T("Path");
+#endif
+
+typedef base::hash_map<FilePath, scoped_refptr<ChromePluginLib> >
+ PluginMap;
+
+// A map of all the instantiated plugins.
+static PluginMap* g_loaded_libs;
+
+// The thread plugins are loaded and used in, lazily initialized upon
+// the first creation call.
+static PlatformThreadId g_plugin_thread_id = 0;
+static MessageLoop* g_plugin_thread_loop = NULL;
+
+static bool IsSingleProcessMode() {
+ // We don't support ChromePlugins in single-process mode.
+ return CommandLine::ForCurrentProcess()->HasSwitch(switches::kSingleProcess);
+}
+
+// static
+bool ChromePluginLib::IsInitialized() {
+ return (g_loaded_libs != NULL);
+}
+
+// static
+ChromePluginLib* ChromePluginLib::Create(const FilePath& filename,
+ const CPBrowserFuncs* bfuncs) {
+ // Keep a map of loaded plugins to ensure we only load each library once.
+ if (!g_loaded_libs) {
+ g_loaded_libs = new PluginMap();
+ g_plugin_thread_id = PlatformThread::CurrentId();
+ g_plugin_thread_loop = MessageLoop::current();
+ }
+ DCHECK(IsPluginThread());
+
+ PluginMap::const_iterator iter = g_loaded_libs->find(filename);
+ if (iter != g_loaded_libs->end())
+ return iter->second;
+
+ scoped_refptr<ChromePluginLib> plugin(new ChromePluginLib(filename));
+ if (!plugin->CP_Initialize(bfuncs))
+ return NULL;
+
+ (*g_loaded_libs)[filename] = plugin;
+ return plugin;
+}
+
+// static
+ChromePluginLib* ChromePluginLib::Find(const FilePath& filename) {
+ if (g_loaded_libs) {
+ PluginMap::const_iterator iter = g_loaded_libs->find(filename);
+ if (iter != g_loaded_libs->end())
+ return iter->second;
+ }
+ return NULL;
+}
+
+// static
+void ChromePluginLib::Destroy(const FilePath& filename) {
+ DCHECK(g_loaded_libs);
+ PluginMap::iterator iter = g_loaded_libs->find(filename);
+ if (iter != g_loaded_libs->end()) {
+ iter->second->Unload();
+ g_loaded_libs->erase(iter);
+ }
+}
+
+// static
+bool ChromePluginLib::IsPluginThread() {
+ return PlatformThread::CurrentId() == g_plugin_thread_id;
+}
+
+// static
+MessageLoop* ChromePluginLib::GetPluginThreadLoop() {
+ return g_plugin_thread_loop;
+}
+
+// static
+void ChromePluginLib::RegisterPluginsWithNPAPI() {
+ // We don't support ChromePlugins in single-process mode.
+ if (IsSingleProcessMode())
+ return;
+
+ FilePath path;
+ // Register Gears, if available.
+ if (PathService::Get(chrome::FILE_GEARS_PLUGIN, &path))
+ NPAPI::PluginList::Singleton()->AddExtraPluginPath(path);
+}
+
+static void LogPluginLoadTime(const TimeDelta &time) {
+ UMA_HISTOGRAM_TIMES("Gears.LoadTime", time);
+}
+
+// static
+void ChromePluginLib::LoadChromePlugins(const CPBrowserFuncs* bfuncs) {
+ static bool loaded = false;
+ if (loaded)
+ return;
+ loaded = true;
+
+ // We don't support ChromePlugins in single-process mode.
+ if (IsSingleProcessMode())
+ return;
+
+ FilePath path;
+ if (!PathService::Get(chrome::FILE_GEARS_PLUGIN, &path))
+ return;
+
+ PerfTimer timer;
+ ChromePluginLib::Create(path, bfuncs);
+ LogPluginLoadTime(timer.Elapsed());
+
+ // TODO(mpcomplete): disabled loading of plugins from the registry until we
+ // phase out registry keys from the gears installer.
+#if 0
+ for (RegistryKeyIterator iter(HKEY_CURRENT_USER, kRegistryChromePlugins);
+ iter.Valid(); ++iter) {
+ // Use the registry to gather plugin across the file system.
+ std::wstring reg_path = kRegistryChromePlugins;
+ reg_path.append(L"\\");
+ reg_path.append(iter.Name());
+ RegKey key(HKEY_CURRENT_USER, reg_path.c_str());
+
+ DWORD is_persistent;
+ if (key.ReadValueDW(kRegistryLoadOnStartup, &is_persistent) &&
+ is_persistent) {
+ std::wstring path;
+ if (key.ReadValue(kRegistryPath, &path)) {
+ ChromePluginLib::Create(path, bfuncs);
+ }
+ }
+ }
+#endif
+}
+
+// static
+void ChromePluginLib::UnloadAllPlugins() {
+ if (g_loaded_libs) {
+ PluginMap::iterator it;
+ for (PluginMap::iterator it = g_loaded_libs->begin();
+ it != g_loaded_libs->end(); ++it) {
+ it->second->Unload();
+ }
+ delete g_loaded_libs;
+ g_loaded_libs = NULL;
+ }
+}
+
+const CPPluginFuncs& ChromePluginLib::functions() const {
+ DCHECK(initialized_);
+ DCHECK(IsPluginThread());
+ return plugin_funcs_;
+}
+
+ChromePluginLib::ChromePluginLib(const FilePath& filename)
+ : filename_(filename),
+#if defined(OS_WIN)
+ module_(0),
+#endif
+ initialized_(false),
+ CP_VersionNegotiate_(NULL),
+ CP_Initialize_(NULL) {
+ memset((void*)&plugin_funcs_, 0, sizeof(plugin_funcs_));
+}
+
+ChromePluginLib::~ChromePluginLib() {
+}
+
+bool ChromePluginLib::CP_Initialize(const CPBrowserFuncs* bfuncs) {
+ LOG(INFO) << "ChromePluginLib::CP_Initialize(" << filename_.value() <<
+ "): initialized=" << initialized_;
+ if (initialized_)
+ return true;
+
+ if (!Load())
+ return false;
+
+ if (CP_VersionNegotiate_) {
+ uint16 selected_version = 0;
+ CPError rv = CP_VersionNegotiate_(CP_VERSION, CP_VERSION,
+ &selected_version);
+ if ( (rv != CPERR_SUCCESS) || (selected_version != CP_VERSION))
+ return false;
+ }
+
+ plugin_funcs_.size = sizeof(plugin_funcs_);
+ CPError rv = CP_Initialize_(cpid(), bfuncs, &plugin_funcs_);
+ initialized_ = (rv == CPERR_SUCCESS) &&
+ (CP_GET_MAJOR_VERSION(plugin_funcs_.version) == CP_MAJOR_VERSION) &&
+ (CP_GET_MINOR_VERSION(plugin_funcs_.version) <= CP_MINOR_VERSION);
+ LOG(INFO) << "ChromePluginLib::CP_Initialize(" << filename_.value() <<
+ "): initialized=" << initialized_ <<
+ "): result=" << rv;
+
+ return initialized_;
+}
+
+void ChromePluginLib::CP_Shutdown() {
+ DCHECK(initialized_);
+ functions().shutdown();
+ initialized_ = false;
+ memset((void*)&plugin_funcs_, 0, sizeof(plugin_funcs_));
+}
+
+int ChromePluginLib::CP_Test(void* param) {
+ DCHECK(initialized_);
+ if (!CP_Test_)
+ return -1;
+ return CP_Test_(param);
+}
+
+bool ChromePluginLib::Load() {
+#if !defined(OS_WIN)
+ // Mac and Linux won't implement Gears.
+ return false;
+#else
+ DCHECK(module_ == 0);
+
+ module_ = LoadLibrary(filename_.value().c_str());
+ if (module_ == 0)
+ return false;
+
+ // required initialization function
+ CP_Initialize_ = reinterpret_cast<CP_InitializeFunc>
+ (GetProcAddress(module_, "CP_Initialize"));
+
+ if (!CP_Initialize_) {
+ FreeLibrary(module_);
+ module_ = 0;
+ return false;
+ }
+
+ // optional version negotiation function
+ CP_VersionNegotiate_ = reinterpret_cast<CP_VersionNegotiateFunc>
+ (GetProcAddress(module_, "CP_VersionNegotiate"));
+
+ // optional test function
+ CP_Test_ = reinterpret_cast<CP_TestFunc>
+ (GetProcAddress(module_, "CP_Test"));
+
+ return true;
+#endif
+}
+
+void ChromePluginLib::Unload() {
+ NotificationService::current()->Notify(
+ NotificationType::CHROME_PLUGIN_UNLOADED,
+ Source<ChromePluginLib>(this),
+ NotificationService::NoDetails());
+
+ if (initialized_)
+ CP_Shutdown();
+
+#if defined(OS_WIN)
+ if (module_) {
+ FreeLibrary(module_);
+ module_ = 0;
+ }
+#endif
+}
diff --git a/chrome/common/chrome_plugin_lib.h b/chrome/common/chrome_plugin_lib.h
new file mode 100644
index 0000000..5027cfc
--- /dev/null
+++ b/chrome/common/chrome_plugin_lib.h
@@ -0,0 +1,106 @@
+// Copyright (c) 2010 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_COMMON_CHROME_PLUGIN_LIB_H_
+#define CHROME_COMMON_CHROME_PLUGIN_LIB_H_
+
+#include <string>
+
+#include "base/basictypes.h"
+#include "base/file_path.h"
+#include "base/ref_counted.h"
+#include "chrome/common/chrome_plugin_api.h"
+
+class MessageLoop;
+
+// A ChromePluginLib is a single Chrome Plugin Library.
+// This class is used in the browser process (IO thread), and the plugin process
+// (plugin thread). It should not be accessed on other threads, because it
+// issues a NOTIFY_CHROME_PLUGIN_UNLOADED notification.
+class ChromePluginLib : public base::RefCounted<ChromePluginLib> {
+ public:
+ static bool IsInitialized();
+ static ChromePluginLib* Create(const FilePath& filename,
+ const CPBrowserFuncs* bfuncs);
+ static ChromePluginLib* Find(const FilePath& filename);
+ static void Destroy(const FilePath& filename);
+ static bool IsPluginThread();
+ static MessageLoop* GetPluginThreadLoop();
+
+ static ChromePluginLib* FromCPID(CPID id) {
+ return reinterpret_cast<ChromePluginLib*>(id);
+ }
+
+ // Adds Chrome plugins to the NPAPI plugin list.
+ static void RegisterPluginsWithNPAPI();
+
+ // Loads all the plugins that are marked as "LoadOnStartup" in the
+ // registry. This should only be called in the browser process.
+ static void LoadChromePlugins(const CPBrowserFuncs* bfuncs);
+
+ // Unloads all the loaded plugins and cleans up the plugin map.
+ static void UnloadAllPlugins();
+
+ // Returns true if the plugin is currently loaded.
+ bool is_loaded() const { return initialized_; }
+
+ // Get the Plugin's function pointer table.
+ const CPPluginFuncs& functions() const;
+
+ CPID cpid() { return reinterpret_cast<CPID>(this); }
+
+ const FilePath& filename() { return filename_; }
+
+ // Plugin API functions
+
+ // Method to call a test function in the plugin, used for unit tests.
+ int CP_Test(void* param);
+
+#if defined(OS_WIN)
+ // The registry path to search for Chrome Plugins/
+ static const TCHAR kRegistryChromePlugins[];
+#endif // defined(OS_WIN)
+
+ private:
+ friend class base::RefCounted<ChromePluginLib>;
+
+ explicit ChromePluginLib(const FilePath& filename);
+ ~ChromePluginLib();
+
+ // Method to initialize a Plugin.
+ // Initialize can be safely called multiple times.
+ bool CP_Initialize(const CPBrowserFuncs* bfuncs);
+
+ // Method to shutdown a Plugin.
+ void CP_Shutdown();
+
+ // Attempts to load the plugin.
+ // Returns true if it is a legitimate plugin, false otherwise
+ bool Load();
+
+ // Unloads the plugin.
+ void Unload();
+
+ FilePath filename_; // the path to the plugin
+#if defined(OS_WIN)
+ // TODO(port): Remove ifdefs when we have portable replacement for HMODULE.
+ HMODULE module_; // the opened plugin handle
+#endif // defined(OS_WIN)
+ bool initialized_; // is the plugin initialized
+
+ // Exported symbols from the plugin, looked up by name.
+ CP_VersionNegotiateFunc CP_VersionNegotiate_;
+ CP_InitializeFunc CP_Initialize_;
+
+ // Additional function pointers provided by the plugin.
+ CPPluginFuncs plugin_funcs_;
+
+ // Used for unit tests.
+ typedef int (STDCALL *CP_TestFunc)(void*);
+ CP_TestFunc CP_Test_;
+
+ DISALLOW_COPY_AND_ASSIGN(ChromePluginLib);
+};
+
+#endif // CHROME_COMMON_CHROME_PLUGIN_LIB_H_
diff --git a/chrome/common/chrome_plugin_util.cc b/chrome/common/chrome_plugin_util.cc
new file mode 100644
index 0000000..08be12b
--- /dev/null
+++ b/chrome/common/chrome_plugin_util.cc
@@ -0,0 +1,182 @@
+// Copyright (c) 2010 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/common/chrome_plugin_util.h"
+
+#include <algorithm>
+
+#include "base/command_line.h"
+#include "base/file_util.h"
+#include "base/message_loop.h"
+#include "base/utf_string_conversions.h"
+#include "chrome/common/chrome_plugin_lib.h"
+#include "chrome/common/chrome_switches.h"
+#include "chrome/common/notification_service.h"
+#include "net/base/load_flags.h"
+#include "net/http/http_response_headers.h"
+
+//
+// ScopableCPRequest
+//
+
+ScopableCPRequest::ScopableCPRequest(const char* u, const char* m,
+ CPBrowsingContext c) {
+ pdata = NULL;
+ data = NULL;
+#if defined(OS_WIN)
+ url = _strdup(u);
+ method = _strdup(m);
+#else
+ url = strdup(u);
+ method = strdup(m);
+#endif
+ context = c;
+}
+
+ScopableCPRequest::~ScopableCPRequest() {
+ pdata = NULL;
+ data = NULL;
+ free(const_cast<char*>(url));
+ free(const_cast<char*>(method));
+}
+
+//
+// PluginHelper
+//
+
+// static
+void PluginHelper::DestroyAllHelpersForPlugin(ChromePluginLib* plugin) {
+ NotificationService::current()->Notify(
+ NotificationType::CHROME_PLUGIN_UNLOADED,
+ Source<ChromePluginLib>(plugin),
+ NotificationService::NoDetails());
+}
+
+PluginHelper::PluginHelper(ChromePluginLib* plugin) : plugin_(plugin) {
+ DCHECK(CalledOnValidThread());
+ registrar_.Add(this, NotificationType::CHROME_PLUGIN_UNLOADED,
+ Source<ChromePluginLib>(plugin_));
+}
+
+PluginHelper::~PluginHelper() {
+ DCHECK(CalledOnValidThread());
+}
+
+void PluginHelper::Observe(NotificationType type,
+ const NotificationSource& source,
+ const NotificationDetails& details) {
+ DCHECK(CalledOnValidThread());
+ DCHECK(type == NotificationType::CHROME_PLUGIN_UNLOADED);
+ DCHECK(plugin_ == Source<ChromePluginLib>(source).ptr());
+
+ delete this;
+}
+
+//
+// PluginResponseUtils
+//
+
+uint32 PluginResponseUtils::CPLoadFlagsToNetFlags(uint32 flags) {
+ uint32 net_flags = 0;
+#define HANDLE_FLAG(name) \
+ if (flags & CPREQUEST##name) \
+ net_flags |= net::name
+
+ HANDLE_FLAG(LOAD_VALIDATE_CACHE);
+ HANDLE_FLAG(LOAD_BYPASS_CACHE);
+ HANDLE_FLAG(LOAD_PREFERRING_CACHE);
+ HANDLE_FLAG(LOAD_ONLY_FROM_CACHE);
+ HANDLE_FLAG(LOAD_DISABLE_CACHE);
+ HANDLE_FLAG(LOAD_DISABLE_INTERCEPT);
+
+ net_flags |= net::LOAD_ENABLE_UPLOAD_PROGRESS;
+
+ return net_flags;
+}
+
+int PluginResponseUtils::GetResponseInfo(
+ const net::HttpResponseHeaders* response_headers,
+ CPResponseInfoType type, void* buf, size_t buf_size) {
+ if (!response_headers)
+ return CPERR_FAILURE;
+
+ switch (type) {
+ case CPRESPONSEINFO_HTTP_STATUS:
+ if (buf && buf_size) {
+ int status = response_headers->response_code();
+ memcpy(buf, &status, std::min(buf_size, sizeof(status)));
+ }
+ break;
+ case CPRESPONSEINFO_HTTP_RAW_HEADERS: {
+ const std::string& headers = response_headers->raw_headers();
+ if (buf_size < headers.size()+1)
+ return static_cast<int>(headers.size()+1);
+ if (buf)
+ memcpy(buf, headers.c_str(), headers.size()+1);
+ break;
+ }
+ default:
+ return CPERR_INVALID_VERSION;
+ }
+
+ return CPERR_SUCCESS;
+}
+
+CPError CPB_GetCommandLineArgumentsCommon(const char* url,
+ std::string* arguments) {
+ const CommandLine cmd = *CommandLine::ForCurrentProcess();
+ std::wstring arguments_w;
+
+ // Use the same UserDataDir for new launches that we currently have set.
+ FilePath user_data_dir = cmd.GetSwitchValuePath(switches::kUserDataDir);
+ if (!user_data_dir.empty()) {
+ // Make sure user_data_dir is an absolute path.
+ if (file_util::AbsolutePath(&user_data_dir) &&
+ file_util::PathExists(user_data_dir)) {
+ // TODO(evanm): use CommandLine APIs instead of this.
+ arguments_w += std::wstring(L"--") + ASCIIToWide(switches::kUserDataDir) +
+ L"=\"" + user_data_dir.ToWStringHack() + L"\" ";
+ }
+ }
+
+#if defined (OS_CHROMEOS)
+ std::wstring profile = cmd.GetSwitchValue(switches::kProfile);
+ if (!profile.empty()) {
+ arguments_w += std::wstring(L"--") + ASCIIToWide(switches::kProfile) +
+ L"=\"" + profile + L"\" ";
+ }
+#endif
+
+ // Use '--app=url' instead of just 'url' to launch the browser with minimal
+ // chrome.
+ // Note: Do not change this flag! Old Gears shortcuts will break if you do!
+ std::string url_string(url);
+ ReplaceSubstringsAfterOffset(&url_string, 0, "\\", "%5C");
+ ReplaceSubstringsAfterOffset(&url_string, 0, "\"", "%22");
+ ReplaceSubstringsAfterOffset(&url_string, 0, ";", "%3B");
+ ReplaceSubstringsAfterOffset(&url_string, 0, "$", "%24");
+#if defined(OS_WIN) // Windows shortcuts can't escape % so we use \x instead.
+ ReplaceSubstringsAfterOffset(&url_string, 0, "%", "\\x");
+#endif
+ std::wstring url_w = UTF8ToWide(url_string);
+ // TODO(evanm): use CommandLine APIs instead of this.
+ arguments_w += std::wstring(L"--") + ASCIIToWide(switches::kApp) +
+ L"=\"" + url_w + L"\"";
+
+ *arguments = WideToUTF8(arguments_w);
+
+ return CPERR_SUCCESS;
+}
+
+//
+// Host functions shared by browser and plugin processes
+//
+
+void* STDCALL CPB_Alloc(uint32 size) {
+ return malloc(size);
+}
+
+void STDCALL CPB_Free(void* memory) {
+ free(memory);
+}
diff --git a/chrome/common/chrome_plugin_util.h b/chrome/common/chrome_plugin_util.h
new file mode 100644
index 0000000..7714a53
--- /dev/null
+++ b/chrome/common/chrome_plugin_util.h
@@ -0,0 +1,87 @@
+// Copyright (c) 2006-2008 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_COMMON_CHROME_PLUGIN_UTIL_H_
+#define CHROME_COMMON_CHROME_PLUGIN_UTIL_H_
+
+#include <string>
+
+#include "base/basictypes.h"
+#include "base/non_thread_safe.h"
+#include "base/ref_counted.h"
+#include "chrome/common/chrome_plugin_api.h"
+#include "chrome/common/notification_registrar.h"
+
+class ChromePluginLib;
+class MessageLoop;
+namespace net {
+class HttpResponseHeaders;
+}
+
+// A helper struct to ensure the CPRequest data is cleaned up when done.
+// This class is reused for requests made by the browser (and intercepted by the
+// plugin) as well as those made by the plugin.
+struct ScopableCPRequest : public CPRequest {
+ template<class T>
+ static T GetData(CPRequest* request) {
+ return static_cast<T>(static_cast<ScopableCPRequest*>(request)->data);
+ }
+
+ ScopableCPRequest(const char* url, const char* method,
+ CPBrowsingContext context);
+ ~ScopableCPRequest();
+
+ void* data;
+};
+
+// This is a base class for plugin-related objects that need to go away when
+// the plugin unloads. This object also verifies that it is created and
+// destroyed on the same thread.
+class PluginHelper : public NotificationObserver, public NonThreadSafe {
+ public:
+ static void DestroyAllHelpersForPlugin(ChromePluginLib* plugin);
+
+ explicit PluginHelper(ChromePluginLib* plugin);
+ virtual ~PluginHelper();
+
+ // NotificationObserver
+ virtual void Observe(NotificationType type,
+ const NotificationSource& source,
+ const NotificationDetails& details);
+
+ protected:
+ NotificationRegistrar registrar_;
+
+ scoped_refptr<ChromePluginLib> plugin_;
+
+ DISALLOW_COPY_AND_ASSIGN(PluginHelper);
+};
+
+// A class of utility functions for dealing with request responses.
+class PluginResponseUtils {
+ public:
+ // Helper to convert request load flags from the plugin API to the net API
+ // versions.
+ static uint32 CPLoadFlagsToNetFlags(uint32 flags);
+
+ // Common implementation of a CPR_GetResponseInfo call.
+ static int GetResponseInfo(
+ const net::HttpResponseHeaders* response_headers,
+ CPResponseInfoType type, void* buf, size_t buf_size);
+};
+
+// Helper to allocate a string using the given CPB_Alloc function.
+inline char* CPB_StringDup(CPB_AllocFunc alloc, const std::string& str) {
+ char* cstr = static_cast<char*>(alloc(static_cast<uint32>(str.length() + 1)));
+ memcpy(cstr, str.c_str(), str.length() + 1); // Include null terminator.
+ return cstr;
+}
+
+CPError CPB_GetCommandLineArgumentsCommon(const char* url,
+ std::string* arguments);
+
+void* STDCALL CPB_Alloc(uint32 size);
+void STDCALL CPB_Free(void* memory);
+
+#endif // CHROME_COMMON_CHROME_PLUGIN_UTIL_H_
diff --git a/chrome/common/chrome_switches.cc b/chrome/common/chrome_switches.cc
new file mode 100644
index 0000000..3c4255a
--- /dev/null
+++ b/chrome/common/chrome_switches.cc
@@ -0,0 +1,1129 @@
+// Copyright (c) 2010 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/common/chrome_switches.h"
+
+#include "base/base_switches.h"
+#include "base/command_line.h"
+
+namespace switches {
+
+// -----------------------------------------------------------------------------
+// Can't find the switch you are looking for? try looking in
+// base/base_switches.cc instead.
+// -----------------------------------------------------------------------------
+
+// Activate (make foreground) myself on launch. Helpful when Chrome
+// is launched on the command line (e.g. by Selenium). Only needed on Mac.
+const char kActivateOnLaunch[] = "activate-on-launch";
+
+// By default, file:// URIs cannot read other file:// URIs. This is an
+// override for developers who need the old behavior for testing.
+const char kAllowFileAccessFromFiles[] = "allow-file-access-from-files";
+
+// Allows debugging of sandboxed processes (see zygote_main_linux.cc).
+const char kAllowSandboxDebugging[] = "allow-sandbox-debugging";
+
+// Allows injecting extensions and user scripts on the extensions
+// gallery site. Normally prevented for security reasons, but can be
+// useful for automation testing of the gallery.
+const char kAllowScriptingGallery[] = "allow-scripting-gallery";
+
+// Enable web inspector for all windows, even if they're part of the browser.
+// Allows us to use our dev tools to debug browser windows itself.
+const char kAlwaysEnableDevTools[] = "always-enable-dev-tools";
+
+// Specifies that the associated value should be launched in "application" mode.
+const char kApp[] = "app";
+
+// Specifies that the extension-app with the specified id should be launched
+// according to its configuration.
+const char kAppId[] = "app-id";
+
+// Lacks meaning with out kApp. Causes the specified app to be launched in an
+// panel window.
+const char kAppLaunchAsPanel[] = "app-launch-as-panel";
+
+// Makes the app launcher popup when a new tab is created.
+const char kAppsPanel[] = "apps-panel";
+
+// The URL to use for the gallery link in the app launcher.
+const char kAppsGalleryURL[] = "apps-gallery-url";
+
+// Disable throbber for extension apps.
+const char kAppsNoThrob[] = "apps-no-throb";
+
+// Whether to display the "Debug" link for app launch behavior.
+const char kAppsDebug[] = "apps-debug";
+
+// Authentication white list for servers
+const char kAuthServerWhitelist[] = "auth-server-whitelist";
+
+// The value of this switch tells the app to listen for and broadcast
+// automation-related messages on IPC channel with the given ID.
+const char kAutomationClientChannelID[] = "automation-channel";
+
+// Causes the browser process to throw an assertion on startup.
+const char kBrowserAssertTest[] = "assert-test";
+
+// Causes the browser process to crash on startup.
+const char kBrowserCrashTest[] = "crash-test";
+
+// Path to the exe to run for the renderer and plugin subprocesses.
+const char kBrowserSubprocessPath[] = "browser-subprocess-path";
+
+// Run Chrome in Chrome Frame mode. This means that Chrome expects to be run
+// as a dependent process of the Chrome Frame plugin.
+const char kChromeFrame[] = "chrome-frame";
+
+// The unique id to be used for this cloud print proxy instance.
+const char kCloudPrintProxyId[] = "cloud-print-proxy-id";
+
+// The URL of the cloud print service to use, overrides any value
+// stored in preferences, and the default. Only used if the cloud
+// print service has been enabled (see enable-cloud-print).
+const char kCloudPrintServiceURL[] = "cloud-print-service";
+
+// The Country we should use. This is normally obtained from the operating
+// system during first run and cached in the preferences afterwards. This is a
+// string value, the 2 letter code from ISO 3166-1.
+const char kCountry[] = "country";
+
+// Enables support to debug printing subsystem.
+const char kDebugPrint[] = "debug-print";
+
+// Triggers a pletora of diagnostic modes.
+const char kDiagnostics[] = "diagnostics";
+
+// Disables the alternate window station for the renderer.
+const char kDisableAltWinstation[] = "disable-winsta";
+
+// Disable the ApplicationCache.
+const char kDisableApplicationCache[] = "disable-application-cache";
+
+// Replaces the audio IPC layer for <audio> and <video> with a mock audio
+// device, useful when using remote desktop or machines without sound cards.
+// This is temporary until we fix the underlying problem.
+//
+// TODO(scherkus): remove --disable-audio when we have a proper fallback
+// mechanism.
+const char kDisableAudio[] = "disable-audio";
+
+// Disable CNAME lookup of the host when generating the Kerberos SPN for a
+// Negotiate challenge. See HttpAuthHandlerNegotiate::CreateSPN
+// for more background.
+const char kDisableAuthNegotiateCnameLookup[] =
+ "disable-auth-negotiate-cname-lookup";
+
+// Disable limits on the number of backing stores. Can prevent blinking for
+// users with many windows/tabs and lots of memory.
+const char kDisableBackingStoreLimit[] = "disable-backing-store-limit";
+
+// Disable support for cached byte-ranges.
+const char kDisableByteRangeSupport[] = "disable-byte-range-support";
+
+// Disables the custom JumpList on Windows 7.
+const char kDisableCustomJumpList[] = "disable-custom-jumplist";
+
+// Disables HTML5 DB support.
+const char kDisableDatabases[] = "disable-databases";
+
+// Disables desktop notifications (default enabled on windows).
+const char kDisableDesktopNotifications[] = "disable-desktop-notifications";
+
+// Browser flag to disable the web inspector for all renderers.
+const char kDisableDevTools[] = "disable-dev-tools";
+
+// Disable extensions.
+const char kDisableExtensions[] = "disable-extensions";
+
+// Disable checking for user opt-in for extensions that want to inject script
+// into file URLs (ie, always allow it). This is used during automated testing.
+const char kDisableExtensionsFileAccessCheck[] =
+ "disable-extensions-file-access-check";
+
+// Suppresses support for the Geolocation javascript API.
+const char kDisableGeolocation[] = "disable-geolocation";
+
+// Suppresses hang monitor dialogs in renderer processes.
+const char kDisableHangMonitor[] = "disable-hang-monitor";
+
+// Disable the internal Flash Player.
+const char kDisableInternalFlash[] = "disable-internal-flash";
+
+// Don't resolve hostnames to IPv6 addresses. This can be used when debugging
+// issues relating to IPv6, but shouldn't otherwise be needed. Be sure to
+// file bugs if something isn't working properly in the presence of IPv6.
+// This flag can be overidden by the "enable-ipv6" flag.
+const char kDisableIPv6[] = "disable-ipv6";
+
+// Don't execute JavaScript (browser JS like the new tab page still runs).
+const char kDisableJavaScript[] = "disable-javascript";
+
+// Prevent Java from running.
+const char kDisableJava[] = "disable-java";
+
+// Disable LocalStorage.
+const char kDisableLocalStorage[] = "disable-local-storage";
+
+// Force logging to be disabled. Logging is enabled by default in debug
+// builds.
+const char kDisableLogging[] = "disable-logging";
+
+// Whether we should prevent the new tab page from showing the first run
+// notification.
+const char kDisableNewTabFirstRun[] = "disable-new-tab-first-run";
+
+// Prevent plugins from running.
+const char kDisablePlugins[] = "disable-plugins";
+
+// Disable pop-up blocking.
+const char kDisablePopupBlocking[] = "disable-popup-blocking";
+
+// Normally when the user attempts to navigate to a page that was the result of
+// a post we prompt to make sure they want to. This switch may be used to
+// disable that check. This switch is used during automated testing.
+const char kDisablePromptOnRepost[] = "disable-prompt-on-repost";
+
+// Disable remote web font support. SVG font should always work whether
+// this option is specified or not.
+const char kDisableRemoteFonts[] = "disable-remote-fonts";
+
+// Turns off the accessibility in the renderer.
+const char kDisableRendererAccessibility[] = "disable-renderer-accessibility";
+
+// Disable session storage.
+const char kDisableSessionStorage[] = "disable-session-storage";
+
+// Enable shared workers. Functionality not yet complete.
+const char kDisableSharedWorkers[] = "disable-shared-workers";
+
+// Disable site-specific tailoring to compatibility issues in WebKit.
+const char kDisableSiteSpecificQuirks[] = "disable-site-specific-quirks";
+
+// Disable syncing browser data to a Google Account.
+const char kDisableSync[] = "disable-sync";
+
+// Disable syncing of autofill.
+const char kDisableSyncAutofill[] = "disable-sync-autofill";
+
+// Disable syncing of bookmarks.
+const char kDisableSyncBookmarks[] = "disable-sync-bookmarks";
+
+// Disable syncing of extensions.
+const char kDisableSyncExtensions[] = "disable-sync-extensions";
+
+// Disable syncing of passwords.
+const char kDisableSyncPasswords[] = "disable-sync-passwords";
+
+// Disable syncing of preferences.
+const char kDisableSyncPreferences[] = "disable-sync-preferences";
+
+// Disable syncing of themes.
+const char kDisableSyncThemes[] = "disable-sync-themes";
+
+// Disable syncing of typed urls.
+const char kDisableSyncTypedUrls[] = "disable-sync-typed-urls";
+
+// TabCloseableStateWatcher disallows closing of tabs and browsers under certain
+// situations on ChromeOS. Some tests expect tabs or browsers to close, so we
+// need a switch to disable the watcher.
+const char kDisableTabCloseableStateWatcher[] =
+ "disable-tab-closeable-state-watcher";
+
+// Enables the backend service for web resources, used in the new tab page for
+// loading tips and recommendations from a JSON feed.
+const char kDisableWebResources[] = "disable-web-resources";
+
+// Don't enforce the same-origin policy. (Used by people testing their sites.)
+const char kDisableWebSecurity[] = "disable-web-security";
+
+// Disable Web Sockets support.
+const char kDisableWebSockets[] = "disable-web-sockets";
+
+// Use a specific disk cache location, rather than one derived from the
+// UserDatadir.
+const char kDiskCacheDir[] = "disk-cache-dir";
+
+// Forces the maximum disk space to be used by the disk cache, in bytes.
+const char kDiskCacheSize[] = "disk-cache-size";
+
+const char kDnsLogDetails[] = "dns-log-details";
+
+// Disables prefetching of DNS information.
+const char kDnsPrefetchDisable[] = "dns-prefetch-disable";
+
+// Specifies if the dom_automation_controller_ needs to be bound in the
+// renderer. This binding happens on per-frame basis and hence can potentially
+// be a performance bottleneck. One should only enable it when automating
+// dom based tests.
+const char kDomAutomationController[] = "dom-automation";
+
+// Dump any accumualted histograms to the log when browser terminates (requires
+// logging to be enabled to really do anything). Used by developers and test
+// scripts.
+const char kDumpHistogramsOnExit[] = "dump-histograms-on-exit";
+
+// Enable gpu-accelerated compositing.
+const char kEnableAcceleratedCompositing[] = "enable-accelerated-compositing";
+
+// Enables AeroPeek for each tab. (This switch only works on Windows 7).
+const char kEnableAeroPeekTabs[] = "enable-aero-peek-tabs";
+
+// Enable experimental extension apps.
+const char kEnableApps[] = "enable-apps";
+
+// Enable the inclusion of non-standard ports when generating the Kerberos SPN
+// in response to a Negotiate challenge. See HttpAuthHandlerNegotiate::CreateSPN
+// for more background.
+const char kEnableAuthNegotiatePort[] = "enable-auth-negotiate-port";
+
+// Enables the benchmarking extensions.
+const char kEnableBenchmarking[] = "enable-benchmarking";
+
+// This applies only when the process type is "service". Enables the
+// Chromoting Host Process within the service process.
+const char kEnableChromoting[] = "enable-chromoting";
+
+// This applies only when the process type is "service". Enables the
+// Cloud Print Proxy component within the service process.
+const char kEnableCloudPrintProxy[] = "enable-cloud-print-proxy";
+
+// Enables the Cloud Print dialog hosting code.
+const char kEnableCloudPrint[] = "enable-cloud-print";
+
+// Enables extension APIs that are in development.
+const char kEnableExperimentalExtensionApis[] =
+ "enable-experimental-extension-apis";
+
+// Enable experimental WebGL support.
+const char kEnableExperimentalWebGL[] = "enable-webgl";
+
+// Enable experimental timeline API.
+const char kEnableExtensionTimelineApi[] = "enable-extension-timeline-api";
+
+// Enable extension toolstrips (deprecated API - will be removed).
+const char kEnableExtensionToolstrips[] = "enable-extension-toolstrips";
+
+// Enable the fastback page cache.
+const char kEnableFastback[] = "enable-fastback";
+
+// By default, cookies are not allowed on file://. They are needed for
+// testing, for example page cycler and layout tests. See bug 1157243.
+const char kEnableFileCookies[] = "enable-file-cookies";
+
+// Enable the Indexed Database API.
+const char kEnableIndexedDatabase[] = "enable-indexed-database";
+
+// Use the InMemoryURLIndex to back the HistoryURLProvider for autocomplete
+// results. If not set, defaults to using the InMemoryDatabase.
+const char kEnableInMemoryURLIndex[] = "enable-in-memory-url-index";
+
+// Enable IPv6 support, even if probes suggest that it may not be fully
+// supported. Some probes may require internet connections, and this flag will
+// allow support independent of application testing.
+// This flag overrides "disable-ipv6" which appears elswhere in this file.
+const char kEnableIPv6[] = "enable-ipv6";
+
+// Enable the GLSL translator.
+const char kEnableGLSLTranslator[] = "enable-glsl-translator";
+
+// Enable the GPU plugin and Pepper 3D rendering.
+const char kEnableGPUPlugin[] = "enable-gpu-plugin";
+
+// Enable experimental GPU rendering for backing store and video.
+const char kEnableGPURendering[] = "enable-gpu-rendering";
+
+// Force logging to be enabled. Logging is disabled by default in release
+// builds.
+const char kEnableLogging[] = "enable-logging";
+
+// Allows reporting memory info (JS heap size) to page.
+const char kEnableMemoryInfo[] = "enable-memory-info";
+
+// On Windows, converts the page to the currently-installed monitor profile.
+// This does NOT enable color management for images. The source is still
+// assumed to be sRGB.
+const char kEnableMonitorProfile[] = "enable-monitor-profile";
+
+// Runs the Native Client inside the renderer process and enables GPU plugin
+// (internally adds kInternalNaCl and lEnableGpuPlugin to the command line).
+const char kEnableNaCl[] = "enable-nacl";
+
+// Enable Native Web Worker support.
+const char kEnableNativeWebWorkers[] = "enable-native-web-workers";
+
+// Enable speculative TCP/IP preconnection.
+const char kEnablePreconnect[] = "enable-preconnect";
+
+// Enable caching of pre-parsed JS script data. See http://crbug.com/32407.
+const char kEnablePreparsedJsCaching[] = "enable-preparsed-js-caching";
+
+// Enable print preview (work in progress).
+const char kEnablePrintPreview[] = "enable-print-preview";
+
+// Enable the IsSearchProviderInstalled and InstallSearchProvider with an extra
+// parameter to indicate if the provider should be the default.
+const char kEnableSearchProviderApiV2[] = "enable-search-provider-api-v2";
+
+// Enables StatsTable, logging statistics to a global named shared memory table.
+const char kEnableStatsTable[] = "enable-stats-table";
+
+// Enable syncing browser data to a Google Account.
+const char kEnableSync[] = "enable-sync";
+
+// Enable syncing browser autofill.
+const char kEnableSyncAutofill[] = "enable-sync-autofill";
+
+// Enable syncing browser bookmarks.
+const char kEnableSyncBookmarks[] = "enable-sync-bookmarks";
+
+// Enable syncing browser extensions.
+const char kEnableSyncExtensions[] = "enable-sync-extensions";
+
+// Enable syncing browser passwords.
+const char kEnableSyncPasswords[] = "enable-sync-passwords";
+
+// Enable syncing browser preferences.
+const char kEnableSyncPreferences[] = "enable-sync-preferences";
+
+// Enable syncing browser themes.
+const char kEnableSyncThemes[] = "enable-sync-themes";
+
+// Enable syncing browser typed urls.
+const char kEnableSyncTypedUrls[] = "enable-sync-typed-urls";
+
+// Enable tabbed options, ie: dom-ui version of options window.
+const char kEnableTabbedOptions[] = "enable-tabbed-options";
+
+// Whether or not the touch events API is exposed.
+const char kEnableTouch[] = "enable-touch";
+
+// Enables the option to show tabs as a vertical stack down the side of the
+// browser window.
+const char kEnableVerticalTabs[] = "enable-vertical-tabs";
+
+// Enables support for fullscreen video. Current implementation is
+// incomplete and this flag is used for development and testing.
+const char kEnableVideoFullscreen[] = "enable-video-fullscreen";
+
+// Enables video layering where video is rendered as a separate layer outside
+// of the backing store.
+const char kEnableVideoLayering[] = "enable-video-layering";
+
+// Enables video logging where video elements log playback performance data to
+// the debug log.
+const char kEnableVideoLogging[] = "enable-video-logging";
+
+// Spawn threads to watch for excessive delays in specified message loops.
+// User should set breakpoints on Alarm() to examine problematic thread.
+// Usage: -enable-watchdog=[ui][io]
+// Order of the listed sub-arguments does not matter.
+const char kEnableWatchdog[] = "enable-watchdog";
+
+// Disable WebKit's XSSAuditor. The XSSAuditor mitigates reflective XSS.
+const char kEnableXSSAuditor[] = "enable-xss-auditor";
+
+// Enables the experimental Negotiate authentication protocol.
+const char kExperimentalEnableNegotiateAuth[] =
+ "experimental-enable-negotiate-auth";
+
+// Enables experimental features for Spellchecker. Right now, the first
+// experimental feature is auto spell correct, which corrects words which are
+// misppelled by typing the word with two consecutive letters swapped. The
+// features that will be added next are:
+// 1 - Allow multiple spellcheckers to work simultaneously.
+// 2 - Allow automatic detection of spell check language.
+// TODO(sidchat): Implement the above fetaures to work under this flag.
+const char kExperimentalSpellcheckerFeatures[] =
+ "experimental-spellchecker-features";
+
+// Explicitly allow additional ports using a comma separated list of port
+// numbers.
+const char kExplicitlyAllowedPorts[] = "explicitly-allowed-ports";
+
+// Causes the process to run as an extension subprocess.
+const char kExtensionProcess[] = "extension";
+
+// Frequency in seconds for Extensions auto-update.
+const char kExtensionsUpdateFrequency[] = "extensions-update-frequency";
+
+// The file descriptor limit is set to the value of this switch, subject to the
+// OS hard limits. Useful for testing that file descriptor exhaustion is handled
+// gracefully.
+const char kFileDescriptorLimit[] = "file-descriptor-limit";
+
+// Display the First Run experience when the browser is started, regardless of
+// whether or not it's actually the first run.
+const char kFirstRun[] = "first-run";
+
+// Some field tests may rendomized in the browser, and the randomly selected
+// outcome needs to be propogated to the renderer. For instance, this is used
+// to modify histograms recorded in the renderer, or to get the renderer to
+// also set of its state (initialize, or not initialize components) to match the
+// experiment(s).
+// The argument is a string-ized list of experiment names, and the associated
+// value that was randomly selected. In the recent implementetaion, the
+// persistent representation generated by field_trial.cc and later decoded, is a
+// list of name and value pairs, separated by slashes. See field trial.cc for
+// current details.
+const char kForceFieldTestNameAndValue[] = "force-fieldtest";
+
+// Extra command line options for launching the GPU process (normally used
+// for debugging). Use like renderer-cmd-prefix.
+const char kGpuLauncher[] = "gpu-launcher";
+
+// Makes this process a GPU sub-process.
+const char kGpuProcess[] = "gpu-process";
+
+// Causes the GPU process to display a dialog on launch.
+const char kGpuStartupDialog[] = "gpu-startup-dialog";
+
+// These flags show the man page on Linux. They are equivalent to each
+// other.
+const char kHelp[] = "help";
+const char kHelpShort[] = "h";
+
+// Make Windows happy by allowing it to show "Enable access to this program"
+// checkbox in Add/Remove Programs->Set Program Access and Defaults. This
+// only shows an error box because the only way to hide Chrome is by
+// uninstalling it.
+const char kHideIcons[] = "hide-icons";
+
+// The value of this switch specifies which page will be displayed
+// in newly-opened tabs. We need this for testing purposes so
+// that the UI tests don't depend on what comes up for http://google.com.
+const char kHomePage[] = "homepage";
+
+// Comma separated list of rules that control how hostnames are mapped.
+//
+// For example:
+// "MAP * 127.0.0.1" --> Forces all hostnames to be mapped to 127.0.0.1
+// "MAP *.google.com proxy" --> Forces all google.com subdomains to be
+// resolved to "proxy".
+// "MAP test.com [::1]:77 --> Forces "test.com" to resolve to IPv6 loopback.
+// Will also force the port of the resulting
+// socket address to be 77.
+// "MAP * baz, EXCLUDE www.google.com" --> Remaps everything to "baz",
+// except for "www.google.com".
+//
+// These mappings apply to the endpoint host in a URLRequest (the TCP connect
+// and host resolver in a direct connection, and the CONNECT in an http proxy
+// connection, and the endpoint host in a SOCKS proxy connection).
+const char kHostRules[] = "host-rules";
+
+// The maximum number of concurrent host resolve requests (i.e. DNS) to allow.
+const char kHostResolverParallelism[] = "host-resolver-parallelism";
+
+// These mappings only apply to the host resolver.
+const char kHostResolverRules[] = "host-resolver-rules";
+
+// Perform importing from another browser. The value associated with this
+// setting encodes the target browser and what items to import.
+const char kImport[] = "import";
+
+// Perform bookmark importing from an HTML file. The value associated with this
+// setting encodes the file path. It may be used jointly with kImport.
+const char kImportFromFile[] = "import-from-file";
+
+// Runs plugins inside the renderer process
+const char kInProcessPlugins[] = "in-process-plugins";
+
+// Runs WebGL inside the renderer process.
+const char kInProcessWebGL[] = "in-process-webgl";
+
+// Causes the browser to launch directly in incognito mode.
+const char kIncognito[] = "incognito";
+
+// Back up the profile.
+const char kInstallerTestBackup[] = "backup";
+
+// Control the build under test.
+const char kInstallerTestBuild[] = "build";
+
+// Uninstall before running the tests.
+const char kInstallerTestClean[] = "clean";
+
+// Force the installer tests to run, regardless of the current platform.
+const char kInstallerTestForce[] = "force";
+
+// Runs the Native Client inside the renderer process.
+const char kInternalNaCl[] = "internal-nacl";
+
+// Runs a trusted Pepper plugin inside the renderer process.
+const char kInternalPepper[] = "internal-pepper";
+
+// The following flags allow users who can reproduce crbug/35198
+// to enable extra logging and behaviors. They will be removed once
+// the issue is fixed.
+const char kIssue35198CrxDirBrowser[] = "issue35198-crxdir-browser";
+const char kIssue35198ExtraLogging[] = "issue35198-logging";
+const char kIssue35198Permission[] = "issue35198-permission";
+
+// Specifies the flags passed to JS engine
+const char kJavaScriptFlags[] = "js-flags";
+
+// Used for testing - keeps browser alive after last browser window closes.
+const char kKeepAliveForTest[] = "keep-alive-for-test";
+
+// Load an extension from the specified directory.
+const char kLoadExtension[] = "load-extension";
+
+// Load an NPAPI plugin from the specified path.
+const char kLoadPlugin[] = "load-plugin";
+
+// Load NPAPI plugins from the specified directory.
+const char kExtraPluginDir[] = "extra-plugin-dir";
+
+// Will filter log messages to show only the messages that are prefixed
+// with the specified value. See also kEnableLogging and kLoggingLevel.
+const char kLogFilterPrefix[] = "log-filter-prefix";
+
+// Make plugin processes log their sent and received messages to LOG(INFO).
+const char kLogPluginMessages[] = "log-plugin-messages";
+
+// Sets the minimum log level. Valid values are from 0 to 3:
+// INFO = 0, WARNING = 1, LOG_ERROR = 2, LOG_FATAL = 3.
+const char kLoggingLevel[] = "log-level";
+
+// Make Chrome default browser
+const char kMakeDefaultBrowser[] = "make-default-browser";
+
+// Forces the maximum disk space to be used by the media cache, in bytes.
+const char kMediaCacheSize[] = "media-cache-size";
+
+// Enable dynamic loading of the Memory Profiler DLL, which will trace
+// all memory allocations during the run.
+const char kMemoryProfiling[] = "memory-profile";
+
+// Enable histograming of tasks served by MessageLoop. See about:histograms/Loop
+// for results, which show frequency of messages on each thread, including APC
+// count, object signalling count, etc.
+const char kMessageLoopHistogrammer[] = "message-loop-histogrammer";
+
+// Enables the recording of metrics reports but disables reporting. In
+// contrast to kDisableMetrics, this executes all the code that a normal client
+// would use for reporting, except the report is dropped rather than sent to
+// the server. This is useful for finding issues in the metrics code during UI
+// and performance tests.
+const char kMetricsRecordingOnly[] = "metrics-recording-only";
+
+// Causes the process to run as a NativeClient broker
+// (used for launching NaCl loader processes on 64-bit Windows).
+const char kNaClBrokerProcess[] = "nacl-broker";
+
+// Causes the process to run as a NativeClient loader.
+const char kNaClLoaderProcess[] = "nacl-loader";
+
+// Causes the Native Client process to display a dialog on launch.
+const char kNaClStartupDialog[] = "nacl-startup-dialog";
+
+// Disables the default browser check. Useful for UI/browser tests where we
+// want to avoid having the default browser info-bar displayed.
+const char kNoDefaultBrowserCheck[] = "no-default-browser-check";
+
+// Don't record/playback events when using record & playback.
+const char kNoEvents[] = "no-events";
+
+// Bypass the First Run experience when the browser is started, regardless of
+// whether or not it's actually the first run. Overrides kFirstRun in case
+// you're for some reason tempted to pass them both.
+const char kNoFirstRun[] = "no-first-run";
+
+// Support a separate switch that enables the v8 playback extension.
+// The extension causes javascript calls to Date.now() and Math.random()
+// to return consistent values, such that subsequent loads of the same
+// page will result in consistent js-generated data and XHR requests.
+// Pages may still be able to generate inconsistent data from plugins.
+const char kNoJsRandomness[] = "no-js-randomness";
+
+// Don't send HTTP-Referer headers.
+const char kNoReferrers[] = "no-referrers";
+
+// Don't use a proxy server, always make direct connections. Overrides any
+// other proxy server flags that are passed.
+const char kNoProxyServer[] = "no-proxy-server";
+
+// Runs the renderer outside the sandbox.
+const char kNoSandbox[] = "no-sandbox";
+
+// Specifies the maximum number of threads to use for running the Proxy
+// Autoconfig (PAC) script.
+const char kNumPacThreads[] = "num-pac-threads";
+
+// Launch URL in new browser window.
+const char kOpenInNewWindow[] = "new-window";
+
+// Package an extension to a .crx installable file from a given directory.
+const char kPackExtension[] = "pack-extension";
+
+// Optional PEM private key is to use in signing packaged .crx.
+const char kPackExtensionKey[] = "pack-extension-key";
+
+// Specifies the path to the user data folder for the parent profile.
+const char kParentProfile[] = "parent-profile";
+
+// Read previously recorded data from the cache. Only cached data is read.
+// See kRecordMode.
+const char kPlaybackMode[] = "playback-mode";
+
+// Specifies the plugin data directory, which is where plugins (Gears
+// specifically) will store its state.
+const char kPluginDataDir[] = "plugin-data-dir";
+
+// Specifies a command that should be used to launch the plugin process. Useful
+// for running the plugin process through purify or quantify. Ex:
+// --plugin-launcher="path\to\purify /Run=yes"
+const char kPluginLauncher[] = "plugin-launcher";
+
+// Tells the plugin process the path of the plugin to load
+const char kPluginPath[] = "plugin-path";
+
+// Causes the process to run as a plugin subprocess.
+const char kPluginProcess[] = "plugin";
+
+// Causes the plugin process to display a dialog on launch.
+const char kPluginStartupDialog[] = "plugin-startup-dialog";
+
+// Enable TCP/IP preconnection, and DNS preresolution, even if a proxy might
+// possibly be used for connections.
+const char kPreconnectDespiteProxy[] = "preconnect-despite-proxy";
+
+// Establishes a channel to the GPU process asynchronously and (re)launches it
+// if necessary when a renderer process starts.
+const char kPrelaunchGpuProcess[] = "prelaunch-gpu-process";
+
+// Prints the pages on the screen.
+const char kPrint[] = "print";
+
+// Runs a single process for each site (i.e., group of pages from the same
+// registered domain) the user visits. We default to using a renderer process
+// for each site instance (i.e., group of pages from the same registered
+// domain with script connections to each other).
+const char kProcessPerSite[] = "process-per-site";
+
+// Runs each set of script-connected tabs (i.e., a BrowsingInstance) in its own
+// renderer process. We default to using a renderer process for each
+// site instance (i.e., group of pages from the same registered domain with
+// script connections to each other).
+const char kProcessPerTab[] = "process-per-tab";
+
+// Output the product version information and quit. Used as an internal api to
+// detect the installed version of Chrome on Linux.
+const char kProductVersion[] = "product-version";
+
+// Causes the process to run as a profile import subprocess.
+const char kProfileImportProcess[] = "profile-import";
+
+// Force proxy auto-detection.
+const char kProxyAutoDetect[] = "proxy-auto-detect";
+
+// Specify a list of hosts for whom we bypass proxy settings and use direct
+// connections. Ignored if --proxy-auto-detect or --no-proxy-server are
+// also specified.
+// This is a comma separated list of bypass rules. See:
+// "net/proxy/proxy_bypass_rules.h" for the format of these rules.
+const char kProxyBypassList[] = "proxy-bypass-list";
+
+// Use the pac script at the given URL
+const char kProxyPacUrl[] = "proxy-pac-url";
+
+// Use a specified proxy server, overrides system settings. This switch only
+// affects HTTP and HTTPS requests.
+const char kProxyServer[] = "proxy-server";
+
+// Adds a "Purge memory" button to the Task Manager, which tries to dump as
+// much memory as possible. This is mostly useful for testing how well the
+// MemoryPurger functionality works.
+//
+// NOTE: This is only implemented for Views.
+const char kPurgeMemoryButton[] = "purge-memory-button";
+
+// Chrome supports a playback and record mode. Record mode saves *everything*
+// to the cache. Playback mode reads data exclusively from the cache. This
+// allows us to record a session into the cache and then replay it at will.
+// See also kPlaybackMode.
+const char kRecordMode[] = "record-mode";
+
+// Register pepper plugins that should be loaded into the renderer.
+const char kRegisterPepperPlugins[] = "register-pepper-plugins";
+
+// Enable remote debug over HTTP on the specified port.
+const char kRemoteDebuggingPort[] = "remote-debugging-port";
+
+// Enable remote debug / automation shell on the specified port.
+const char kRemoteShellPort[] = "remote-shell-port";
+
+// Causes the renderer process to throw an assertion on launch.
+const char kRendererAssertTest[] = "renderer-assert-test";
+
+#if !defined(OFFICIAL_BUILD)
+// Causes the renderer process to throw an assertion on launch.
+const char kRendererCheckFalseTest[] = "renderer-check-false-test";
+#endif
+
+// On POSIX only: the contents of this flag are prepended to the renderer
+// command line. Useful values might be "valgrind" or "xterm -e gdb --args".
+const char kRendererCmdPrefix[] = "renderer-cmd-prefix";
+
+// Causes the renderer process to crash on launch.
+const char kRendererCrashTest[] = "renderer-crash-test";
+
+// Causes the process to run as renderer instead of as browser.
+const char kRendererProcess[] = "renderer";
+
+// Causes the renderer process to display a dialog on launch.
+const char kRendererStartupDialog[] = "renderer-startup-dialog";
+
+// Causes the URLs of BackgroundContents to be remembered and re-launched when
+// the browser restarts.
+const char kRestoreBackgroundContents[] = "restore-background-contents";
+
+// Indicates the last session should be restored on startup. This overrides
+// the preferences value and is primarily intended for testing. The value of
+// this switch is the number of tabs to wait until loaded before
+// 'load completed' is sent to the ui_test.
+const char kRestoreLastSession[] = "restore-last-session";
+
+// Runs the plugin processes inside the sandbox.
+const char kSafePlugins[] = "safe-plugins";
+
+// URL prefix used by safebrowsing to fetch hash, download data and
+// report malware.
+const char kSbInfoURLPrefix[] = "safebrowsing-info-url-prefix";
+// URL prefix used by safebrowsing to get MAC key.
+const char kSbMacKeyURLPrefix[] = "safebrowsing-mackey-url-prefix";
+// If present, safebrowsing only performs update when
+// SafeBrowsingProtocolManager::ForceScheduleNextUpdate() is explicitly called.
+// This is used for testing only.
+const char kSbDisableAutoUpdate[] = "safebrowsing-disable-auto-update";
+
+// Enable support for SDCH filtering (dictionary based expansion of content).
+// Optional argument is *the* only domain name that will have SDCH suppport.
+// Default is "-enable-sdch" to advertise SDCH on all domains.
+// Sample usage with argument: "-enable-sdch=.google.com"
+// SDCH is currently only supported server-side for searches on google.com.
+const char kSdchFilter[] = "enable-sdch";
+
+// Enables the showing of an info-bar instructing user they can search directly
+// from the omnibox.
+const char kSearchInOmniboxHint[] = "search-in-omnibox-hint";
+
+// Causes the process to run as a service process.
+const char kServiceProcess[] = "service";
+
+// The LSID of the account to use for the service process.
+const char kServiceAccountLsid[] = "service-account-lsid";
+
+// See kHideIcons.
+const char kShowIcons[] = "show-icons";
+
+// Renders a border around composited Render Layers to help debug and study
+// layer compositing.
+const char kShowCompositedLayerBorders[] = "show-composited-layer-borders";
+
+// Visibly render a border around paint rects in the web page to help debug
+// and study painting behavior.
+const char kShowPaintRects[] = "show-paint-rects";
+
+// Whether to show the link to the Google Privacy Dashboard on the Sync options
+// panel.
+const char kShowPrivacyDashboardLink[] = "show-privacy-dashboard-link";
+
+// Change the DCHECKS to dump memory and continue instead of displaying error
+// dialog. This is valid only in Release mode when --enable-dcheck is
+// specified.
+const char kSilentDumpOnDCHECK[] = "silent-dump-on-dcheck";
+
+// Replaces the buffered data source for <audio> and <video> with a simplified
+// resource loader that downloads the entire resource into memory.
+//
+// TODO(scherkus): remove --simple-data-source when our media resource loading
+// is cleaned up and playback testing completed.
+const char kSimpleDataSource[] = "simple-data-source";
+
+// Runs the renderer and plugins in the same process as the browser
+const char kSingleProcess[] = "single-process";
+
+// Start the browser maximized, regardless of any previous settings.
+const char kStartMaximized[] = "start-maximized";
+
+// Control Sync XMPP client settings.
+const char kSyncAllowPlain[] = "allow-plain";
+
+// Control Sync XMPP client settings.
+const char kSyncDisableTls[] = "disable-tls";
+
+// Email used for sync.
+const char kSyncEmail[] = "email";
+
+// Use the SyncerThread implementation that matches up with the old pthread
+// impl semantics, but using Chrome synchronization primitives. The only
+// difference between this and the default is that we now have no timeout on
+// Stop(). Should only use if you experience problems with the default.
+const char kSyncerThreadTimedStop[] = "syncer-thread-timed-stop";
+
+// Override the default notification method for sync.
+const char kSyncNotificationMethod[] = "sync-notification-method";
+
+// Password used for sync.
+const char kSyncPassword[] = "password";
+
+// Port used for sync.
+const char kSyncPort[] = "port";
+
+// Server used for sync.
+const char kSyncServer[] = "server";
+
+// Override the default server used for profile sync.
+const char kSyncServiceURL[] = "sync-url";
+
+// Use the (new, untested) Chrome-socket-based buzz::AsyncSocket
+// implementation for notifications.
+const char kSyncUseChromeAsyncSocket[] = "sync-use-chrome-async-socket";
+
+// Control Sync XMPP client settings.
+const char kSyncUseSslTcp[] = "use-ssl-tcp";
+
+// Control Sync XMPP client settings.
+const char kSyncUseCacheInvalidation[] = "use-cache-invalidation";
+
+// Pass the name of the current running automated test to Chrome.
+const char kTestName[] = "test-name";
+
+// Runs the security test for the renderer sandbox.
+const char kTestSandbox[] = "test-sandbox";
+
+// Runs the security test for the NaCl loader sandbox.
+const char kTestNaClSandbox[] = "test-nacl-sandbox";
+
+// Pass the type of the current test harness ("browser" or "ui")
+const char kTestType[] = "test-type";
+
+// The value of this switch tells the app to listen for and broadcast
+// testing-related messages on IPC channel with the given ID.
+const char kTestingChannelID[] = "testing-channel";
+
+// Enables using TopSites instead of ThumbnailDatabase (and
+// ThumbnailStore) for getting thumbnails for the new tab page.
+const char kTopSites[] = "top-sites";
+
+// Excludes these plugins from the plugin sandbox.
+// This is a comma-separated list of plugin library names.
+const char kTrustedPlugins[] = "trusted-plugins";
+
+// Experimental. Shows a dialog asking the user to try chrome. This flag
+// is to be used only by the upgrade process.
+const char kTryChromeAgain[] = "try-chrome-again";
+
+// Runs un-installation steps that were done by chrome first-run.
+const char kUninstall[] = "uninstall";
+
+// Use Spdy for the transport protocol instead of HTTP.
+// This is a temporary testing flag.
+const char kUseSpdy[] = "use-spdy";
+
+// These two flags are used to force http and https requests to fixed ports.
+const char kFixedHttpPort[] = "testing-fixed-http-port";
+const char kFixedHttpsPort[] = "testing-fixed-https-port";
+
+// Ignore certificate related errors.
+const char kIgnoreCertificateErrors[] = "ignore-certificate-errors";
+
+// Set the maximum SPDY sessions per domain.
+const char kMaxSpdySessionsPerDomain[] = "max-spdy-sessions-per-domain";
+
+// Use the low fragmentation heap for the CRT.
+const char kUseLowFragHeapCrt[] = "use-lf-heap";
+
+// A string used to override the default user agent with a custom one.
+const char kUserAgent[] = "user-agent";
+
+// Specifies the user data directory, which is where the browser will look
+// for all of its state.
+const char kUserDataDir[] = "user-data-dir";
+
+// directory to locate user scripts in as an over-ride of the default
+const char kUserScriptsDir[] = "user-scripts-dir";
+
+// On POSIX only: the contents of this flag are prepended to the utility
+// process command line. Useful values might be "valgrind" or "xterm -e gdb
+// --args".
+const char kUtilityCmdPrefix[] = "utility-cmd-prefix";
+
+// Causes the process to run as a utility subprocess.
+const char kUtilityProcess[] = "utility";
+
+// The utility process is sandboxed, with access to one directory. This flag
+// specifies the directory that can be accessed.
+const char kUtilityProcessAllowedDir[] = "utility-allowed-dir";
+
+// Print version information and quit.
+const char kVersion[] = "version";
+
+// Will add kWaitForDebugger to every child processes. If a value is passed, it
+// will be used as a filter to determine if the child process should have the
+// kWaitForDebugger flag passed on or not.
+const char kWaitForDebuggerChildren[] = "wait-for-debugger-children";
+
+// Causes the worker process allocation to use as many processes as cores.
+const char kWebWorkerProcessPerCore[] = "web-worker-process-per-core";
+
+// Causes workers to run together in one process, depending on their domains.
+// Note this is duplicated in webworkerclient_impl.cc
+const char kWebWorkerShareProcesses[] = "web-worker-share-processes";
+
+// Use WinHTTP to fetch and evaluate PAC scripts. Otherwise the default is
+// to use Chromium's network stack to fetch, and V8 to evaluate.
+const char kWinHttpProxyResolver[] = "winhttp-proxy-resolver";
+
+// Causes the process to run as a worker subprocess.
+const char kWorkerProcess[] = "worker";
+
+// The prefix used when starting the zygote process. (i.e. 'gdb --args')
+const char kZygoteCmdPrefix[] = "zygote-cmd-prefix";
+
+// Causes the process to run as a renderer zygote.
+const char kZygoteProcess[] = "zygote";
+
+#if defined(OS_CHROMEOS)
+// Enable the redirection of viewable document requests to the Google
+// Document Viewer.
+const char kEnableGView[] = "enable-gview";
+
+// Should we show the image based login?
+const char kEnableLoginImages[] = "enable-login-images";
+
+// Enable Chrome-as-a-login-manager behavior.
+const char kLoginManager[] = "login-manager";
+// Allows to override the first login screen. The value should be the name
+// of the first login screen to show (see
+// chrome/browser/chromeos/login/login_wizard_view.cc for actual names).
+// Ignored if kLoginManager is not specified.
+// TODO(avayvod): Remove when the switch is no longer needed for testing.
+const char kLoginScreen[] = "login-screen";
+// Allows control over the initial login screen size. Pass width,height.
+const char kLoginScreenSize[] = "login-screen-size";
+
+// Attempts to load libcros and validate it, then exits. A nonzero return code
+// means the library could not be loaded correctly.
+const char kTestLoadLibcros[] = "test-load-libcros";
+
+// TODO(davemoore) Delete this once chromeos has started using
+// login-profile as its arg.
+const char kProfile[] = "profile";
+
+// Specifies the profile to use once a chromeos user is logged in.
+const char kLoginProfile[] = "login-profile";
+
+// Specifies the user which is already logged in.
+const char kLoginUser[] = "login-user";
+
+// Use the frame layout used in chromeos.
+const char kChromeosFrame[] = "chromeos-frame";
+
+// Set logging output to the given file.
+const char kChromeosLogToFile[] = "logtofile";
+
+// Specify startup customization manifest.
+// TODO(denisromanov): delete this when not needed for testing.
+const char kStartupManifest[] = "startup-manifest";
+
+// Specify services customization manifest.
+// TODO(denisromanov): delete this when not needed for testing.
+const char kServicesManifest[] = "services-manifest";
+
+#endif
+
+#if defined(OS_LINUX)
+// Specify the amount the trackpad should scroll by.
+const char kScrollPixels[] = "scroll-pixels";
+#endif
+
+#if defined(OS_MACOSX) || defined(OS_WIN)
+// Use the system SSL library (Secure Transport on Mac, SChannel on Windows)
+// instead of NSS for SSL.
+const char kUseSystemSSL[] = "use-system-ssl";
+#endif
+
+#if defined(OS_POSIX)
+// Bypass the error dialog when the profile lock couldn't be attained.
+// A flag, generated internally by Chrome for renderer and other helper process
+// command lines on Linux and Mac. It tells the helper process to enable crash
+// dumping and reporting, because helpers cannot access the profile or other
+// files needed to make this decision.
+// If passed to the browser, it'll be passed on to all the helper processes
+// as well, thereby force-enabling the crash reporter.
+const char kEnableCrashReporter[] = "enable-crash-reporter";
+
+// This switch is used during automated testing.
+const char kNoProcessSingletonDialog[] = "no-process-singleton-dialog";
+
+#if !defined(OS_MACOSX)
+// Specifies which password store to use (detect, default, gnome, kwallet).
+const char kPasswordStore[] = "password-store";
+#endif
+#endif
+
+#if defined(OS_MACOSX)
+// Cause the OS X sandbox write to syslog every time an access to a resource
+// is denied by the sandbox.
+const char kEnableSandboxLogging[] = "enable-sandbox-logging";
+
+// Temporary flag to prevent Flash from negotiating the Core Animation drawing
+// model. This will be removed once the last issues have been resolved.
+const char kDisableFlashCoreAnimation[] = "disable-flash-core-animation";
+#else
+// Enable Kiosk mode.
+const char kKioskMode[] = "kiosk";
+#endif
+
+#ifndef NDEBUG
+// Debug only switch to specify which gears plugin dll to load.
+const char kGearsPluginPathOverride[] = "gears-plugin-path";
+
+// Makes sure any sync login attempt will fail with an error. (Only
+// used for testing.)
+const char kInvalidateSyncLogin[] = "invalidate-sync-login";
+
+// Makes sure any sync xmpp login attempt will fail with an error. (Only
+// used for testing.)
+const char kInvalidateSyncXmppLogin[] = "invalidate-sync-xmpp-login";
+
+// Debug only switch to specify which websocket live experiment host to be used.
+// If host is specified, it also makes initial delay shorter (5 min to 5 sec)
+// to make it faster to test websocket live experiment code.
+const char kWebSocketLiveExperimentHost[] = "websocket-live-experiment-host";
+#endif
+
+// USE_SECCOMP_SANDBOX controls whether the seccomp sandbox is opt-in or -out.
+// TODO(evan): unify all of these once we turn the seccomp sandbox always
+// on. Also remove the #include of command_line.h above.
+#if defined(USE_SECCOMP_SANDBOX)
+// Disable the seccomp sandbox (Linux only)
+const char kDisableSeccompSandbox[] = "disable-seccomp-sandbox";
+#else
+// Enable the seccomp sandbox (Linux only)
+const char kEnableSeccompSandbox[] = "enable-seccomp-sandbox";
+#endif
+
+bool SeccompSandboxEnabled() {
+#if defined(USE_SECCOMP_SANDBOX)
+ return !CommandLine::ForCurrentProcess()->HasSwitch(
+ switches::kDisableSeccompSandbox);
+#else
+ return CommandLine::ForCurrentProcess()->HasSwitch(
+ switches::kEnableSeccompSandbox);
+#endif
+}
+
+// -----------------------------------------------------------------------------
+// DO NOT ADD YOUR CRAP TO THE BOTTOM OF THIS FILE.
+//
+// You were going to just dump your switches here, weren't you? Instead,
+// please put them in alphabetical order above, or in order inside the
+// appropriate ifdef at the bottom. The order should match the header.
+// -----------------------------------------------------------------------------
+
+} // namespace switches
diff --git a/chrome/common/chrome_switches.h b/chrome/common/chrome_switches.h
new file mode 100644
index 0000000..70a8268
--- /dev/null
+++ b/chrome/common/chrome_switches.h
@@ -0,0 +1,354 @@
+// Copyright (c) 2010 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.
+
+// Defines all the command-line switches used by Chrome.
+
+#ifndef CHROME_COMMON_CHROME_SWITCHES_H_
+#define CHROME_COMMON_CHROME_SWITCHES_H_
+
+#include "build/build_config.h"
+#include "base/base_switches.h"
+
+namespace switches {
+
+// -----------------------------------------------------------------------------
+// Can't find the switch you are looking for? Try looking in
+// base/base_switches.cc instead.
+// -----------------------------------------------------------------------------
+
+// All switches in alphabetical order. The switches should be documented
+// alongside the definition of their values in the .cc file.
+extern const char kActivateOnLaunch[];
+extern const char kAllowFileAccessFromFiles[];
+extern const char kAllowSandboxDebugging[];
+extern const char kAllowScriptingGallery[];
+extern const char kAlwaysEnableDevTools[];
+extern const char kApp[];
+extern const char kAppId[];
+extern const char kAppLaunchAsPanel[];
+extern const char kAppsDebug[];
+extern const char kAppsPanel[];
+extern const char kAppsGalleryURL[];
+extern const char kAppsNoThrob[];
+extern const char kAuthServerWhitelist[];
+extern const char kAutomationClientChannelID[];
+extern const char kBrowserAssertTest[];
+extern const char kBrowserCrashTest[];
+extern const char kBrowserSubprocessPath[];
+extern const char kChromeFrame[];
+extern const char kCloudPrintProxyId[];
+extern const char kCloudPrintServiceURL[];
+extern const char kCountry[];
+extern const char kDebugPrint[];
+extern const char kDiagnostics[];
+extern const char kDisableAltWinstation[];
+extern const char kDisableApplicationCache[];
+extern const char kDisableAudio[];
+extern const char kDisableAuthNegotiateCnameLookup[];
+extern const char kDisableBackingStoreLimit[];
+extern const char kDisableByteRangeSupport[];
+extern const char kDisableCustomJumpList[];
+extern const char kDisableDatabases[];
+extern const char kDisableDesktopNotifications[];
+extern const char kDisableDevTools[];
+extern const char kDisableExtensions[];
+extern const char kDisableExtensionsFileAccessCheck[];
+extern const char kDisableGeolocation[];
+extern const char kDisableHangMonitor[];
+extern const char kDisableInternalFlash[];
+extern const char kDisableIPv6[];
+extern const char kDisableJavaScript[];
+extern const char kDisableJava[];
+extern const char kDisableLocalStorage[];
+extern const char kDisableLogging[];
+extern const char kDisableNewTabFirstRun[];
+extern const char kDisablePlugins[];
+extern const char kDisablePopupBlocking[];
+extern const char kDisablePromptOnRepost[];
+extern const char kDisableRemoteFonts[];
+extern const char kDisableRendererAccessibility[];
+extern const char kDisableSessionStorage[];
+extern const char kDisableSharedWorkers[];
+extern const char kDisableSiteSpecificQuirks[];
+extern const char kDisableSync[];
+extern const char kDisableSyncAutofill[];
+extern const char kDisableSyncBookmarks[];
+extern const char kDisableSyncExtensions[];
+extern const char kDisableSyncPasswords[];
+extern const char kDisableSyncPreferences[];
+extern const char kDisableSyncThemes[];
+extern const char kDisableSyncTypedUrls[];
+extern const char kDisableTabCloseableStateWatcher[];
+extern const char kDisableWebResources[];
+extern const char kDisableWebSecurity[];
+extern const char kDisableWebSockets[];
+extern const char kDiskCacheDir[];
+extern const char kDiskCacheSize[];
+extern const char kDnsLogDetails[];
+extern const char kDnsPrefetchDisable[];
+extern const char kDomAutomationController[];
+extern const char kDumpHistogramsOnExit[];
+extern const char kEnableAcceleratedCompositing[];
+extern const char kEnableAeroPeekTabs[];
+extern const char kEnableApps[];
+extern const char kEnableAuthNegotiatePort[];
+extern const char kEnableBenchmarking[];
+extern const char kEnableChromoting[];
+extern const char kEnableCloudPrintProxy[];
+extern const char kEnableCloudPrint[];
+extern const char kEnableExperimentalExtensionApis[];
+extern const char kEnableExperimentalWebGL[];
+extern const char kEnableExtensionTimelineApi[];
+extern const char kEnableExtensionToolstrips[];
+extern const char kEnableFastback[];
+extern const char kEnableFileCookies[];
+extern const char kEnableGLSLTranslator[];
+extern const char kEnableGPUPlugin[];
+extern const char kEnableGPURendering[];
+extern const char kEnableIndexedDatabase[];
+extern const char kEnableInMemoryURLIndex[];
+extern const char kEnableIPv6[];
+extern const char kEnableLogging[];
+extern const char kEnableMemoryInfo[];
+extern const char kEnableMonitorProfile[];
+extern const char kEnableNaCl[];
+extern const char kEnableNativeWebWorkers[];
+extern const char kEnablePreparsedJsCaching[];
+extern const char kEnablePreconnect[];
+extern const char kEnablePrintPreview[];
+extern const char kEnableSearchProviderApiV2[];
+extern const char kEnableStatsTable[];
+extern const char kEnableSync[];
+extern const char kEnableSyncAutofill[];
+extern const char kEnableSyncBookmarks[];
+extern const char kEnableSyncExtensions[];
+extern const char kEnableSyncPasswords[];
+extern const char kEnableSyncPreferences[];
+extern const char kEnableSyncThemes[];
+extern const char kEnableSyncTypedUrls[];
+extern const char kEnableTabbedOptions[];
+extern const char kEnableTouch[];
+extern const char kEnableVerticalTabs[];
+extern const char kEnableVideoFullscreen[];
+extern const char kEnableVideoLayering[];
+extern const char kEnableVideoLogging[];
+extern const char kEnableWatchdog[];
+extern const char kEnableXSSAuditor[];
+// Experimental features.
+extern const char kExperimentalEnableNegotiateAuth[];
+extern const char kExperimentalSpellcheckerFeatures[];
+// End experimental features.
+extern const char kExplicitlyAllowedPorts[];
+extern const char kExtensionProcess[];
+extern const char kExtensionsUpdateFrequency[];
+extern const char kFileDescriptorLimit[];
+extern const char kFirstRun[];
+extern const char kForceFieldTestNameAndValue[];
+extern const char kGpuLauncher[];
+extern const char kGpuProcess[];
+extern const char kGpuStartupDialog[];
+extern const char kHelp[];
+extern const char kHelpShort[];
+extern const char kHideIcons[];
+extern const char kHomePage[];
+extern const char kHostRules[];
+extern const char kHostResolverParallelism[];
+extern const char kHostResolverRules[];
+extern const char kImport[];
+extern const char kImportFromFile[];
+extern const char kInProcessPlugins[];
+extern const char kInProcessWebGL[];
+extern const char kIncognito[];
+extern const char kInstallerTestBackup[];
+extern const char kInstallerTestBuild[];
+extern const char kInstallerTestClean[];
+extern const char kInstallerTestForce[];
+extern const char kInternalNaCl[];
+extern const char kInternalPepper[];
+extern const char kIssue35198CrxDirBrowser[];
+extern const char kIssue35198ExtraLogging[];
+extern const char kIssue35198Permission[];
+extern const char kJavaScriptFlags[];
+extern const char kKeepAliveForTest[];
+extern const char kLoadExtension[];
+extern const char kLoadPlugin[];
+extern const char kExtraPluginDir[];
+extern const char kLogFilterPrefix[];
+extern const char kLogPluginMessages[];
+extern const char kLoggingLevel[];
+extern const char kMakeDefaultBrowser[];
+extern const char kMediaCacheSize[];
+extern const char kMemoryProfiling[];
+extern const char kMessageLoopHistogrammer[];
+extern const char kMetricsRecordingOnly[];
+extern const char kNaClBrokerProcess[];
+extern const char kNaClLoaderProcess[];
+extern const char kNaClStartupDialog[];
+extern const char kNoDefaultBrowserCheck[];
+extern const char kNoEvents[];
+extern const char kNoFirstRun[];
+extern const char kNoJsRandomness[];
+extern const char kNoProxyServer[];
+extern const char kNoReferrers[];
+extern const char kNoSandbox[];
+extern const char kNumPacThreads[];
+extern const char kOpenInNewWindow[];
+extern const char kPackExtension[];
+extern const char kPackExtensionKey[];
+extern const char kParentProfile[];
+extern const char kPlaybackMode[];
+extern const char kPluginDataDir[];
+extern const char kPluginLauncher[];
+extern const char kPluginPath[];
+extern const char kPluginProcess[];
+extern const char kPluginStartupDialog[];
+extern const char kPreconnectDespiteProxy[];
+extern const char kPrelaunchGpuProcess[];
+extern const char kPrint[];
+extern const char kProcessPerSite[];
+extern const char kProcessPerTab[];
+extern const char kProductVersion[];
+extern const char kProfileImportProcess[];
+extern const char kProxyAutoDetect[];
+extern const char kProxyBypassList[];
+extern const char kProxyPacUrl[];
+extern const char kProxyServer[];
+extern const char kPurgeMemoryButton[];
+extern const char kRecordMode[];
+extern const char kRegisterPepperPlugins[];
+extern const char kRemoteDebuggingPort[];
+extern const char kRemoteShellPort[];
+extern const char kRendererAssertTest[];
+extern const char kRendererCmdPrefix[];
+extern const char kRendererCrashTest[];
+extern const char kRendererProcess[];
+extern const char kRendererStartupDialog[];
+extern const char kRestoreBackgroundContents[];
+extern const char kRestoreLastSession[];
+extern const char kSafePlugins[];
+extern const char kSbInfoURLPrefix[];
+extern const char kSbMacKeyURLPrefix[];
+extern const char kSbDisableAutoUpdate[];
+extern const char kSdchFilter[];
+extern const char kSearchInOmniboxHint[];
+extern const char kServiceProcess[];
+extern const char kServiceAccountLsid[];
+extern const char kShowCompositedLayerBorders[];
+extern const char kShowIcons[];
+extern const char kShowPaintRects[];
+extern const char kShowPrivacyDashboardLink[];
+extern const char kSilentDumpOnDCHECK[];
+extern const char kSimpleDataSource[];
+extern const char kSingleProcess[];
+extern const char kStartMaximized[];
+extern const char kSyncAllowPlain[];
+extern const char kSyncDisableTls[];
+extern const char kSyncEmail[];
+extern const char kSyncerThreadTimedStop[];
+extern const char kSyncNotificationMethod[];
+extern const char kSyncPassword[];
+extern const char kSyncPort[];
+extern const char kSyncServer[];
+extern const char kSyncServiceURL[];
+extern const char kSyncUseChromeAsyncSocket[];
+extern const char kSyncUseSslTcp[];
+extern const char kSyncUseCacheInvalidation[];
+extern const char kTestNaClSandbox[];
+extern const char kTestName[];
+extern const char kTestSandbox[];
+extern const char kTestType[];
+extern const char kTestingChannelID[];
+extern const char kTopSites[];
+extern const char kTrustedPlugins[];
+extern const char kTryChromeAgain[];
+extern const char kUninstall[];
+extern const char kUseSpdy[];
+extern const char kFixedHttpPort[];
+extern const char kFixedHttpsPort[];
+extern const char kIgnoreCertificateErrors[];
+extern const char kMaxSpdySessionsPerDomain[];
+extern const char kUseLowFragHeapCrt[];
+extern const char kUserAgent[];
+extern const char kUserDataDir[];
+extern const char kUserScriptsDir[];
+extern const char kUtilityCmdPrefix[];
+extern const char kUtilityProcess[];
+extern const char kUtilityProcessAllowedDir[];
+extern const char kVersion[];
+extern const char kWaitForDebuggerChildren[];
+extern const char kWebWorkerProcessPerCore[];
+extern const char kWebWorkerShareProcesses[];
+extern const char kWinHttpProxyResolver[];
+extern const char kWorkerProcess[];
+extern const char kZygoteCmdPrefix[];
+extern const char kZygoteProcess[];
+
+#if defined(OS_CHROMEOS)
+extern const char kEnableGView[];
+extern const char kEnableLoginImages[];
+extern const char kLoginManager[];
+// TODO(avayvod): Remove this flag when it's unnecessary for testing
+// purposes.
+extern const char kLoginScreen[];
+extern const char kLoginScreenSize[];
+extern const char kTestLoadLibcros[];
+extern const char kProfile[];
+extern const char kLoginProfile[];
+extern const char kLoginUser[];
+extern const char kChromeosFrame[];
+extern const char kChromeosLogToFile[];
+// TODO(denisromanov): Remove this flag when it is not needed for testing.
+extern const char kStartupManifest[];
+// TODO(denisromanov): Remove this flag when it is not needed for testing, too.
+extern const char kServicesManifest[];
+#endif
+
+#if defined(OS_LINUX)
+extern const char kScrollPixels[];
+#endif
+
+#if defined(OS_MACOSX) || defined(OS_WIN)
+extern const char kUseSystemSSL[];
+#endif
+
+#if defined(OS_POSIX)
+extern const char kEnableCrashReporter[];
+extern const char kNoProcessSingletonDialog[];
+#if !defined(OS_MACOSX)
+extern const char kPasswordStore[];
+#endif
+#endif
+
+#if defined(OS_MACOSX)
+extern const char kDisableFlashCoreAnimation[];
+extern const char kEnableSandboxLogging[];
+#else
+extern const char kKioskMode[];
+#endif
+
+#ifndef NDEBUG
+extern const char kGearsPluginPathOverride[];
+extern const char kInvalidateSyncLogin[];
+extern const char kInvalidateSyncXmppLogin[];
+extern const char kWebSocketLiveExperimentHost[];
+#endif
+
+#if !defined(OFFICIAL_BUILD)
+extern const char kRendererCheckFalseTest[];
+#endif
+
+#if defined(USE_SECCOMP_SANDBOX)
+extern const char kDisableSeccompSandbox[];
+#else
+extern const char kEnableSeccompSandbox[];
+#endif
+// Return true if the switches indicate the seccomp sandbox is enabled.
+bool SeccompSandboxEnabled();
+
+// DON'T ADD RANDOM STUFF HERE. Put it in the main section above in
+// alphabetical order, or in one of the ifdefs (also in order in each section).
+
+} // namespace switches
+
+#endif // CHROME_COMMON_CHROME_SWITCHES_H_
diff --git a/chrome/common/chrome_version_info.cc b/chrome/common/chrome_version_info.cc
new file mode 100644
index 0000000..1b1d479
--- /dev/null
+++ b/chrome/common/chrome_version_info.cc
@@ -0,0 +1,52 @@
+// Copyright (c) 2010 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/common/chrome_version_info.h"
+
+#include "base/basictypes.h"
+#include "base/file_version_info.h"
+#include "build/build_config.h"
+
+#if defined(OS_POSIX) && !defined(OS_MACOSX)
+#include "chrome/common/chrome_version_info_posix.h"
+
+// Posix files don't have per-file version information, so we get chrome
+// version information from chrome_version_info_posix.h, a generated header.
+class ChromeVersionInfoPosix : public FileVersionInfo {
+ public:
+ ChromeVersionInfoPosix() {}
+
+ virtual std::wstring company_name() { return COMPANY_NAME; }
+ virtual std::wstring company_short_name() { return COMPANY_SHORT_NAME; }
+ virtual std::wstring product_name() { return PRODUCT_NAME; }
+ virtual std::wstring product_short_name() { return PRODUCT_SHORT_NAME; }
+ virtual std::wstring internal_name() { return INTERNAL_NAME; }
+ virtual std::wstring product_version() { return PRODUCT_VERSION; }
+ virtual std::wstring private_build() { return PRIVATE_BUILD; }
+ virtual std::wstring special_build() { return SPECIAL_BUILD; }
+ virtual std::wstring comments() { return COMMENTS; }
+ virtual std::wstring original_filename() { return ORIGINAL_FILENAME; }
+ virtual std::wstring file_description() { return FILE_DESCRIPTION; }
+ virtual std::wstring file_version() { return FILE_VERSION; }
+ virtual std::wstring legal_copyright() { return LEGAL_COPYRIGHT; }
+ virtual std::wstring legal_trademarks() { return LEGAL_TRADEMARKS; }
+ virtual std::wstring last_change() { return LAST_CHANGE; }
+ virtual bool is_official_build() { return OFFICIAL_BUILD; }
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(ChromeVersionInfoPosix);
+};
+#endif
+
+namespace chrome {
+
+FileVersionInfo* GetChromeVersionInfo() {
+#if defined(OS_WIN) || defined(OS_MACOSX)
+ return FileVersionInfo::CreateFileVersionInfoForCurrentModule();
+#elif defined(OS_POSIX)
+ return new ChromeVersionInfoPosix();
+#endif
+}
+
+} // namespace chrome
diff --git a/chrome/common/chrome_version_info.h b/chrome/common/chrome_version_info.h
new file mode 100644
index 0000000..e3bfad7
--- /dev/null
+++ b/chrome/common/chrome_version_info.h
@@ -0,0 +1,18 @@
+// Copyright (c) 2010 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_COMMON_CHROME_VERSION_INFO_H_
+#define CHROME_COMMON_CHROME_VERSION_INFO_H_
+
+class FileVersionInfo;
+
+namespace chrome {
+
+// Creates a FileVersionInfo for the app, Chrome. Returns NULL in case of
+// error. The returned object should be deleted when you are done with it.
+FileVersionInfo* GetChromeVersionInfo();
+
+} // namespace chrome
+
+#endif // CHROME_COMMON_CHROME_VERSION_INFO_H_
diff --git a/chrome/common/chrome_version_info_posix.h.version b/chrome/common/chrome_version_info_posix.h.version
new file mode 100644
index 0000000..56a8fea
--- /dev/null
+++ b/chrome/common/chrome_version_info_posix.h.version
@@ -0,0 +1,26 @@
+// Copyright (c) 2010 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_COMMON_CHROME_VERSION_INFO_POSIX_H_
+#define CHROME_COMMON_CHROME_VERSION_INFO_POSIX_H_
+
+#define COMPANY_NAME L"@COMPANY_FULLNAME@"
+#define FILE_DESCRIPTION L"@PRODUCT_FULLNAME@"
+#define FILE_VERSION L"@MAJOR@.@MINOR@.@BUILD@.@PATCH@"
+#define LEGAL_COPYRIGHT L"@COPYRIGHT@"
+#define PRODUCT_NAME L"@PRODUCT_FULLNAME@"
+#define PRODUCT_VERSION L"@MAJOR@.@MINOR@.@BUILD@.@PATCH@"
+#define COMPANY_SHORT_NAME L"@COMPANY_SHORTNAME@"
+#define PRODUCT_SHORT_NAME L"@PRODUCT_SHORTNAME@"
+#define LAST_CHANGE L"@LASTCHANGE@"
+#define OFFICIAL_BUILD @OFFICIAL_BUILD@
+// TODO(mmoss) Do these have values for Linux?
+#define INTERNAL_NAME L""
+#define ORIGINAL_FILENAME L""
+#define PRIVATE_BUILD L""
+#define SPECIAL_BUILD L""
+#define COMMENTS L""
+#define LEGAL_TRADEMARKS L""
+
+#endif // CHROME_COMMON_CHROME_VERSION_INFO_POSIX_H_
diff --git a/chrome/common/common.sb b/chrome/common/common.sb
new file mode 100644
index 0000000..71c73cf
--- /dev/null
+++ b/chrome/common/common.sb
@@ -0,0 +1,33 @@
+;;
+;; Copyright (c) 2010 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.
+;;
+; This configuration file isn't used on it's own, but instead implicity included
+; at the start of all other sandbox configuration files in Chrome.
+(version 1)
+(deny default)
+
+; Support for programmatically enabling verbose debugging.
+;ENABLE_LOGGING (debug deny)
+
+; Allow sending signals to self - http://crbug.com/20370
+(allow signal (target self))
+
+; Needed for full-page-zoomed controls - http://crbug.com/11325
+(allow sysctl-read)
+
+; Each line is marked with the System version that needs it.
+; This profile is tested with the following system versions:
+; 10.5.6, 10.6
+
+; Allow following symlinks
+(allow file-read-metadata) ; 10.5.6
+
+; Loading System Libraries.
+(allow file-read-data (regex #"^/System/Library/Frameworks($|/)")) ; 10.5.6
+(allow file-read-data (regex #"^/System/Library/PrivateFrameworks($|/)")) ; 10.5.6
+(allow file-read-data (regex #"^/System/Library/CoreServices($|/)")) ; 10.5.6
+
+; Needed for IPC on 10.6
+;10.6_ONLY (allow ipc-posix-shm) \ No newline at end of file
diff --git a/chrome/common/common.vsprops b/chrome/common/common.vsprops
new file mode 100644
index 0000000..a834391
--- /dev/null
+++ b/chrome/common/common.vsprops
@@ -0,0 +1,8 @@
+<?xml version="1.0" encoding="Windows-1252"?>
+<VisualStudioPropertySheet
+ ProjectType="Visual C++"
+ Version="8.00"
+ Name="common (chrome)"
+ InheritedPropertySheets="$(SolutionDir)..\build\common.vsprops;$(SolutionDir)..\third_party\icu\build\using_icu.vsprops;$(SolutionDir)..\third_party\zlib\using_zlib.vsprops;$(SolutionDir)..\third_party\libpng\using_libpng.vsprops;$(SolutionDir)..\skia\using_skia.vsprops;$(SolutionDir)..\tools\grit\build\using_generated_resources.vsprops;$(SolutionDir)..\third_party\libxml\build\using_libxml.vsprops;$(SolutionDir)..\third_party\npapi\using_npapi.vsprops;$(SolutionDir)..\chrome\third_party\wtl\using_wtl.vsprops;$(SolutionDir)\common\extra_defines.vsprops"
+ >
+</VisualStudioPropertySheet>
diff --git a/chrome/common/common_glue.cc b/chrome/common/common_glue.cc
new file mode 100644
index 0000000..95417ab
--- /dev/null
+++ b/chrome/common/common_glue.cc
@@ -0,0 +1,49 @@
+// Copyright (c) 2006-2008 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 "app/app_switches.h"
+#include "app/l10n_util.h"
+#include "base/command_line.h"
+#include "base/path_service.h"
+#include "base/string16.h"
+#include "base/utf_string_conversions.h"
+#include "build/build_config.h"
+#include "chrome/common/chrome_paths.h"
+#include "chrome/common/chrome_switches.h"
+#include "chrome/plugin/npobject_util.h"
+#include "googleurl/src/url_util.h"
+#include "webkit/glue/webkit_glue.h"
+
+namespace webkit_glue {
+
+bool GetExeDirectory(FilePath* path) {
+ return PathService::Get(base::DIR_EXE, path);
+}
+
+bool GetApplicationDirectory(FilePath* path) {
+ return PathService::Get(chrome::DIR_APP, path);
+}
+
+bool IsPluginRunningInRendererProcess() {
+ return !IsPluginProcess();
+}
+
+std::wstring GetWebKitLocale() {
+ // The browser process should have passed the locale to the renderer via the
+ // --lang command line flag. In single process mode, this will return the
+ // wrong value. TODO(tc): Fix this for single process mode.
+ const CommandLine& parsed_command_line = *CommandLine::ForCurrentProcess();
+ const std::wstring& lang =
+ parsed_command_line.GetSwitchValue(switches::kLang);
+ DCHECK(!lang.empty() ||
+ (!parsed_command_line.HasSwitch(switches::kRendererProcess) &&
+ !parsed_command_line.HasSwitch(switches::kPluginProcess)));
+ return lang;
+}
+
+string16 GetLocalizedString(int message_id) {
+ return WideToUTF16(l10n_util::GetString(message_id));
+}
+
+} // namespace webkit_glue
diff --git a/chrome/common/common_param_traits.cc b/chrome/common/common_param_traits.cc
new file mode 100644
index 0000000..e655435
--- /dev/null
+++ b/chrome/common/common_param_traits.cc
@@ -0,0 +1,458 @@
+// Copyright (c) 2010 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/common/common_param_traits.h"
+
+#include "chrome/common/chrome_constants.h"
+#include "chrome/common/content_settings.h"
+#include "chrome/common/thumbnail_score.h"
+#include "gfx/rect.h"
+#include "googleurl/src/gurl.h"
+#include "printing/native_metafile.h"
+#include "printing/page_range.h"
+
+#ifndef EXCLUDE_SKIA_DEPENDENCIES
+#include "third_party/skia/include/core/SkBitmap.h"
+#endif
+#include "webkit/glue/dom_operations.h"
+#include "webkit/glue/password_form.h"
+
+namespace IPC {
+
+#ifndef EXCLUDE_SKIA_DEPENDENCIES
+
+namespace {
+
+struct SkBitmap_Data {
+ // The configuration for the bitmap (bits per pixel, etc).
+ SkBitmap::Config fConfig;
+
+ // The width of the bitmap in pixels.
+ uint32 fWidth;
+
+ // The height of the bitmap in pixels.
+ uint32 fHeight;
+
+ void InitSkBitmapDataForTransfer(const SkBitmap& bitmap) {
+ fConfig = bitmap.config();
+ fWidth = bitmap.width();
+ fHeight = bitmap.height();
+ }
+
+ // Returns whether |bitmap| successfully initialized.
+ bool InitSkBitmapFromData(SkBitmap* bitmap, const char* pixels,
+ size_t total_pixels) const {
+ if (total_pixels) {
+ bitmap->setConfig(fConfig, fWidth, fHeight, 0);
+ if (!bitmap->allocPixels())
+ return false;
+ if (total_pixels != bitmap->getSize())
+ return false;
+ memcpy(bitmap->getPixels(), pixels, total_pixels);
+ }
+ return true;
+ }
+};
+
+} // namespace
+
+
+void ParamTraits<SkBitmap>::Write(Message* m, const SkBitmap& p) {
+ size_t fixed_size = sizeof(SkBitmap_Data);
+ SkBitmap_Data bmp_data;
+ bmp_data.InitSkBitmapDataForTransfer(p);
+ m->WriteData(reinterpret_cast<const char*>(&bmp_data),
+ static_cast<int>(fixed_size));
+ size_t pixel_size = p.getSize();
+ SkAutoLockPixels p_lock(p);
+ m->WriteData(reinterpret_cast<const char*>(p.getPixels()),
+ static_cast<int>(pixel_size));
+}
+
+bool ParamTraits<SkBitmap>::Read(const Message* m, void** iter, SkBitmap* r) {
+ const char* fixed_data;
+ int fixed_data_size = 0;
+ if (!m->ReadData(iter, &fixed_data, &fixed_data_size) ||
+ (fixed_data_size <= 0)) {
+ NOTREACHED();
+ return false;
+ }
+ if (fixed_data_size != sizeof(SkBitmap_Data))
+ return false; // Message is malformed.
+
+ const char* variable_data;
+ int variable_data_size = 0;
+ if (!m->ReadData(iter, &variable_data, &variable_data_size) ||
+ (variable_data_size < 0)) {
+ NOTREACHED();
+ return false;
+ }
+ const SkBitmap_Data* bmp_data =
+ reinterpret_cast<const SkBitmap_Data*>(fixed_data);
+ return bmp_data->InitSkBitmapFromData(r, variable_data, variable_data_size);
+}
+
+void ParamTraits<SkBitmap>::Log(const SkBitmap& p, std::wstring* l) {
+ l->append(StringPrintf(L"<SkBitmap>"));
+}
+
+#endif // EXCLUDE_SKIA_DEPENDENCIES
+
+void ParamTraits<GURL>::Write(Message* m, const GURL& p) {
+ m->WriteString(p.possibly_invalid_spec());
+ // TODO(brettw) bug 684583: Add encoding for query params.
+}
+
+bool ParamTraits<GURL>::Read(const Message* m, void** iter, GURL* p) {
+ std::string s;
+ if (!m->ReadString(iter, &s) || s.length() > chrome::kMaxURLChars) {
+ *p = GURL();
+ return false;
+ }
+ *p = GURL(s);
+ return true;
+}
+
+void ParamTraits<GURL>::Log(const GURL& p, std::wstring* l) {
+ l->append(UTF8ToWide(p.spec()));
+}
+
+void ParamTraits<gfx::Point>::Write(Message* m, const gfx::Point& p) {
+ m->WriteInt(p.x());
+ m->WriteInt(p.y());
+}
+
+bool ParamTraits<gfx::Point>::Read(const Message* m, void** iter,
+ gfx::Point* r) {
+ int x, y;
+ if (!m->ReadInt(iter, &x) ||
+ !m->ReadInt(iter, &y))
+ return false;
+ r->set_x(x);
+ r->set_y(y);
+ return true;
+}
+
+void ParamTraits<gfx::Point>::Log(const gfx::Point& p, std::wstring* l) {
+ l->append(StringPrintf(L"(%d, %d)", p.x(), p.y()));
+}
+
+
+void ParamTraits<gfx::Rect>::Write(Message* m, const gfx::Rect& p) {
+ m->WriteInt(p.x());
+ m->WriteInt(p.y());
+ m->WriteInt(p.width());
+ m->WriteInt(p.height());
+}
+
+bool ParamTraits<gfx::Rect>::Read(const Message* m, void** iter, gfx::Rect* r) {
+ int x, y, w, h;
+ if (!m->ReadInt(iter, &x) ||
+ !m->ReadInt(iter, &y) ||
+ !m->ReadInt(iter, &w) ||
+ !m->ReadInt(iter, &h))
+ return false;
+ r->set_x(x);
+ r->set_y(y);
+ r->set_width(w);
+ r->set_height(h);
+ return true;
+}
+
+void ParamTraits<gfx::Rect>::Log(const gfx::Rect& p, std::wstring* l) {
+ l->append(StringPrintf(L"(%d, %d, %d, %d)", p.x(), p.y(),
+ p.width(), p.height()));
+}
+
+
+void ParamTraits<gfx::Size>::Write(Message* m, const gfx::Size& p) {
+ m->WriteInt(p.width());
+ m->WriteInt(p.height());
+}
+
+bool ParamTraits<gfx::Size>::Read(const Message* m, void** iter, gfx::Size* r) {
+ int w, h;
+ if (!m->ReadInt(iter, &w) ||
+ !m->ReadInt(iter, &h))
+ return false;
+ r->set_width(w);
+ r->set_height(h);
+ return true;
+}
+
+void ParamTraits<gfx::Size>::Log(const gfx::Size& p, std::wstring* l) {
+ l->append(StringPrintf(L"(%d, %d)", p.width(), p.height()));
+}
+
+void ParamTraits<ContentSetting>::Write(Message* m, const param_type& p) {
+ WriteParam(m, static_cast<int>(p));
+}
+
+bool ParamTraits<ContentSetting>::Read(const Message* m, void** iter,
+ param_type* r) {
+ int value;
+ if (!ReadParam(m, iter, &value))
+ return false;
+ if (value < 0 || value >= static_cast<int>(CONTENT_SETTING_NUM_SETTINGS))
+ return false;
+ *r = static_cast<param_type>(value);
+ return true;
+}
+
+void ParamTraits<ContentSetting>::Log(const param_type& p, std::wstring* l) {
+ LogParam(static_cast<int>(p), l);
+}
+
+void ParamTraits<ContentSettings>::Write(
+ Message* m, const ContentSettings& settings) {
+ for (size_t i = 0; i < arraysize(settings.settings); ++i)
+ WriteParam(m, settings.settings[i]);
+}
+
+bool ParamTraits<ContentSettings>::Read(
+ const Message* m, void** iter, ContentSettings* r) {
+ for (size_t i = 0; i < arraysize(r->settings); ++i) {
+ if (!ReadParam(m, iter, &r->settings[i]))
+ return false;
+ }
+ return true;
+}
+
+void ParamTraits<ContentSettings>::Log(
+ const ContentSettings& p, std::wstring* l) {
+ l->append(StringPrintf(L"<ContentSettings>"));
+}
+
+void ParamTraits<webkit_glue::WebApplicationInfo>::Write(
+ Message* m, const webkit_glue::WebApplicationInfo& p) {
+ WriteParam(m, p.title);
+ WriteParam(m, p.description);
+ WriteParam(m, p.app_url);
+ WriteParam(m, p.icons.size());
+ for (size_t i = 0; i < p.icons.size(); ++i) {
+ WriteParam(m, p.icons[i].url);
+ WriteParam(m, p.icons[i].width);
+ WriteParam(m, p.icons[i].height);
+ }
+}
+
+bool ParamTraits<webkit_glue::WebApplicationInfo>::Read(
+ const Message* m, void** iter, webkit_glue::WebApplicationInfo* r) {
+ size_t icon_count;
+ bool result =
+ ReadParam(m, iter, &r->title) &&
+ ReadParam(m, iter, &r->description) &&
+ ReadParam(m, iter, &r->app_url) &&
+ ReadParam(m, iter, &icon_count);
+ if (!result)
+ return false;
+ for (size_t i = 0; i < icon_count; ++i) {
+ param_type::IconInfo icon_info;
+ result =
+ ReadParam(m, iter, &icon_info.url) &&
+ ReadParam(m, iter, &icon_info.width) &&
+ ReadParam(m, iter, &icon_info.height);
+ if (!result)
+ return false;
+ r->icons.push_back(icon_info);
+ }
+ return true;
+}
+
+void ParamTraits<webkit_glue::WebApplicationInfo>::Log(
+ const webkit_glue::WebApplicationInfo& p, std::wstring* l) {
+ l->append(L"<WebApplicationInfo>");
+}
+
+void ParamTraits<URLRequestStatus>::Write(Message* m, const param_type& p) {
+ WriteParam(m, static_cast<int>(p.status()));
+ WriteParam(m, p.os_error());
+}
+
+bool ParamTraits<URLRequestStatus>::Read(const Message* m, void** iter,
+ param_type* r) {
+ int status, os_error;
+ if (!ReadParam(m, iter, &status) ||
+ !ReadParam(m, iter, &os_error))
+ return false;
+ r->set_status(static_cast<URLRequestStatus::Status>(status));
+ r->set_os_error(os_error);
+ return true;
+}
+
+void ParamTraits<URLRequestStatus>::Log(const param_type& p, std::wstring* l) {
+ std::wstring status;
+ switch (p.status()) {
+ case URLRequestStatus::SUCCESS:
+ status = L"SUCCESS";
+ break;
+ case URLRequestStatus::IO_PENDING:
+ status = L"IO_PENDING ";
+ break;
+ case URLRequestStatus::HANDLED_EXTERNALLY:
+ status = L"HANDLED_EXTERNALLY";
+ break;
+ case URLRequestStatus::CANCELED:
+ status = L"CANCELED";
+ break;
+ case URLRequestStatus::FAILED:
+ status = L"FAILED";
+ break;
+ default:
+ status = L"UNKNOWN";
+ break;
+ }
+ if (p.status() == URLRequestStatus::FAILED)
+ l->append(L"(");
+
+ LogParam(status, l);
+
+ if (p.status() == URLRequestStatus::FAILED) {
+ l->append(L", ");
+ LogParam(p.os_error(), l);
+ l->append(L")");
+ }
+}
+
+void ParamTraits<ThumbnailScore>::Write(Message* m, const param_type& p) {
+ IPC::ParamTraits<double>::Write(m, p.boring_score);
+ IPC::ParamTraits<bool>::Write(m, p.good_clipping);
+ IPC::ParamTraits<bool>::Write(m, p.at_top);
+ IPC::ParamTraits<base::Time>::Write(m, p.time_at_snapshot);
+}
+
+bool ParamTraits<ThumbnailScore>::Read(const Message* m, void** iter,
+ param_type* r) {
+ double boring_score;
+ bool good_clipping, at_top;
+ base::Time time_at_snapshot;
+ if (!IPC::ParamTraits<double>::Read(m, iter, &boring_score) ||
+ !IPC::ParamTraits<bool>::Read(m, iter, &good_clipping) ||
+ !IPC::ParamTraits<bool>::Read(m, iter, &at_top) ||
+ !IPC::ParamTraits<base::Time>::Read(m, iter, &time_at_snapshot))
+ return false;
+
+ r->boring_score = boring_score;
+ r->good_clipping = good_clipping;
+ r->at_top = at_top;
+ r->time_at_snapshot = time_at_snapshot;
+ return true;
+}
+
+void ParamTraits<ThumbnailScore>::Log(const param_type& p, std::wstring* l) {
+ l->append(StringPrintf(L"(%f, %d, %d)",
+ p.boring_score, p.good_clipping, p.at_top));
+}
+
+void ParamTraits<Geoposition::ErrorCode>::Write(
+ Message* m, const Geoposition::ErrorCode& p) {
+ int error_code = p;
+ WriteParam(m, error_code);
+}
+
+bool ParamTraits<Geoposition::ErrorCode>::Read(
+ const Message* m, void** iter, Geoposition::ErrorCode* p) {
+ int error_code_param = 0;
+ bool ret = ReadParam(m, iter, &error_code_param);
+ *p = static_cast<Geoposition::ErrorCode>(error_code_param);
+ return ret;
+}
+
+void ParamTraits<Geoposition::ErrorCode>::Log(
+ const Geoposition::ErrorCode& p, std::wstring* l) {
+ int error_code = p;
+ l->append(StringPrintf(L"<Geoposition::ErrorCode>%d", error_code));
+}
+
+void ParamTraits<Geoposition>::Write(Message* m, const Geoposition& p) {
+ WriteParam(m, p.latitude);
+ WriteParam(m, p.longitude);
+ WriteParam(m, p.accuracy);
+ WriteParam(m, p.altitude);
+ WriteParam(m, p.altitude_accuracy);
+ WriteParam(m, p.speed);
+ WriteParam(m, p.heading);
+ WriteParam(m, p.timestamp);
+ WriteParam(m, p.error_code);
+ WriteParam(m, p.error_message);
+}
+
+bool ParamTraits<Geoposition>::Read(
+ const Message* m, void** iter, Geoposition* p) {
+ bool ret = ReadParam(m, iter, &p->latitude);
+ ret = ret && ReadParam(m, iter, &p->longitude);
+ ret = ret && ReadParam(m, iter, &p->accuracy);
+ ret = ret && ReadParam(m, iter, &p->altitude);
+ ret = ret && ReadParam(m, iter, &p->altitude_accuracy);
+ ret = ret && ReadParam(m, iter, &p->speed);
+ ret = ret && ReadParam(m, iter, &p->heading);
+ ret = ret && ReadParam(m, iter, &p->timestamp);
+ ret = ret && ReadParam(m, iter, &p->error_code);
+ ret = ret && ReadParam(m, iter, &p->error_message);
+ return ret;
+}
+
+void ParamTraits<Geoposition>::Log(const Geoposition& p, std::wstring* l) {
+ l->append(
+ StringPrintf(
+ L"<Geoposition>"
+ L"%.6f %.6f %.6f %.6f "
+ L"%.6f %.6f %.6f ",
+ p.latitude, p.longitude, p.accuracy, p.altitude,
+ p.altitude_accuracy, p.speed, p.heading));
+ LogParam(p.timestamp, l);
+ l->append(L" ");
+ l->append(UTF8ToWide(p.error_message));
+ LogParam(p.error_code, l);
+}
+
+void ParamTraits<printing::PageRange>::Write(Message* m, const param_type& p) {
+ WriteParam(m, p.from);
+ WriteParam(m, p.to);
+}
+
+bool ParamTraits<printing::PageRange>::Read(
+ const Message* m, void** iter, param_type* p) {
+ return ReadParam(m, iter, &p->from) &&
+ ReadParam(m, iter, &p->to);
+}
+
+void ParamTraits<printing::PageRange>::Log(
+ const param_type& p, std::wstring* l) {
+ l->append(L"(");
+ LogParam(p.to, l);
+ l->append(L", ");
+ LogParam(p.from, l);
+ l->append(L")");
+}
+
+void ParamTraits<printing::NativeMetafile>::Write(
+ Message* m, const param_type& p) {
+ std::vector<uint8> buffer;
+ uint32 size = p.GetDataSize();
+ if (size) {
+ buffer.resize(size);
+ p.GetData(&buffer.front(), size);
+ }
+ WriteParam(m, buffer);
+}
+
+bool ParamTraits<printing::NativeMetafile>::Read(
+ const Message* m, void** iter, param_type* p) {
+ std::vector<uint8> buffer;
+#if defined(OS_WIN)
+ return ReadParam(m, iter, &buffer) &&
+ p->CreateFromData(&buffer.front(), static_cast<uint32>(buffer.size()));
+#else // defined(OS_WIN)
+ return ReadParam(m, iter, &buffer) &&
+ p->Init(&buffer.front(), static_cast<uint32>(buffer.size()));
+#endif // defined(OS_WIN)
+}
+
+void ParamTraits<printing::NativeMetafile>::Log(
+ const param_type& p, std::wstring* l) {
+ l->append(StringPrintf(L"<printing::NativeMetafile>"));
+}
+
+} // namespace IPC
diff --git a/chrome/common/common_param_traits.h b/chrome/common/common_param_traits.h
new file mode 100644
index 0000000..b4ec78e
--- /dev/null
+++ b/chrome/common/common_param_traits.h
@@ -0,0 +1,428 @@
+// Copyright (c) 2010 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.
+
+// This file is used to define IPC::ParamTraits<> specializations for a number
+// of types so that they can be serialized over IPC. IPC::ParamTraits<>
+// specializations for basic types (like int and std::string) and types in the
+// 'base' project can be found in ipc/ipc_message_utils.h. This file contains
+// specializations for types that are shared by more than one child process.
+
+#ifndef CHROME_COMMON_COMMON_PARAM_TRAITS_H_
+#define CHROME_COMMON_COMMON_PARAM_TRAITS_H_
+
+#include <vector>
+
+#include "app/surface/transport_dib.h"
+#include "chrome/common/content_settings.h"
+#include "chrome/common/geoposition.h"
+#include "chrome/common/page_zoom.h"
+#include "gfx/native_widget_types.h"
+#include "ipc/ipc_message_utils.h"
+#include "net/base/upload_data.h"
+#include "net/url_request/url_request_status.h"
+#include "printing/native_metafile.h"
+#include "webkit/glue/password_form.h"
+#include "webkit/glue/webcursor.h"
+#include "webkit/glue/window_open_disposition.h"
+
+// Forward declarations.
+class GURL;
+class SkBitmap;
+class DictionaryValue;
+class ListValue;
+struct ThumbnailScore;
+class URLRequestStatus;
+
+namespace gfx {
+class Point;
+class Rect;
+class Size;
+} // namespace gfx
+
+namespace printing {
+struct PageRange;
+} // namespace printing
+
+namespace webkit_glue {
+struct PasswordForm;
+struct WebApplicationInfo;
+} // namespace webkit_glue
+
+namespace IPC {
+
+template <>
+struct ParamTraits<SkBitmap> {
+ typedef SkBitmap param_type;
+ static void Write(Message* m, const param_type& p);
+
+ // Note: This function expects parameter |r| to be of type &SkBitmap since
+ // r->SetConfig() and r->SetPixels() are called.
+ static bool Read(const Message* m, void** iter, param_type* r);
+
+ static void Log(const param_type& p, std::wstring* l);
+};
+
+
+template <>
+struct ParamTraits<GURL> {
+ typedef GURL param_type;
+ static void Write(Message* m, const param_type& p);
+ static bool Read(const Message* m, void** iter, param_type* p);
+ static void Log(const param_type& p, std::wstring* l);
+};
+
+
+template <>
+struct ParamTraits<gfx::Point> {
+ typedef gfx::Point param_type;
+ static void Write(Message* m, const param_type& p);
+ static bool Read(const Message* m, void** iter, param_type* r);
+ static void Log(const param_type& p, std::wstring* l);
+};
+
+template <>
+struct ParamTraits<gfx::Rect> {
+ typedef gfx::Rect param_type;
+ static void Write(Message* m, const param_type& p);
+ static bool Read(const Message* m, void** iter, param_type* r);
+ static void Log(const param_type& p, std::wstring* l);
+};
+
+template <>
+struct ParamTraits<gfx::Size> {
+ typedef gfx::Size param_type;
+ static void Write(Message* m, const param_type& p);
+ static bool Read(const Message* m, void** iter, param_type* r);
+ static void Log(const param_type& p, std::wstring* l);
+};
+
+template <>
+struct ParamTraits<ContentSetting> {
+ typedef ContentSetting param_type;
+ static void Write(Message* m, const param_type& p);
+ static bool Read(const Message* m, void** iter, param_type* r);
+ static void Log(const param_type& p, std::wstring* l);
+};
+
+template <>
+struct ParamTraits<ContentSettingsType> {
+ typedef ContentSettingsType param_type;
+ static void Write(Message* m, const param_type& p) {
+ WriteParam(m, static_cast<int>(p));
+ }
+ static bool Read(const Message* m, void** iter, param_type* r) {
+ int value;
+ if (!ReadParam(m, iter, &value))
+ return false;
+ if (value < 0 || value >= static_cast<int>(CONTENT_SETTINGS_NUM_TYPES))
+ return false;
+ *r = static_cast<param_type>(value);
+ return true;
+ }
+ static void Log(const param_type& p, std::wstring* l) {
+ LogParam(static_cast<int>(p), l);
+ }
+};
+
+template <>
+struct ParamTraits<ContentSettings> {
+ typedef ContentSettings param_type;
+ static void Write(Message* m, const param_type& p);
+ static bool Read(const Message* m, void** iter, param_type* r);
+ static void Log(const param_type& p, std::wstring* l);
+};
+
+template <>
+struct ParamTraits<gfx::NativeWindow> {
+ typedef gfx::NativeWindow param_type;
+ static void Write(Message* m, const param_type& p) {
+#if defined(OS_WIN)
+ // HWNDs are always 32 bits on Windows, even on 64 bit systems.
+ m->WriteUInt32(reinterpret_cast<uint32>(p));
+#else
+ m->WriteData(reinterpret_cast<const char*>(&p), sizeof(p));
+#endif
+ }
+ static bool Read(const Message* m, void** iter, param_type* r) {
+#if defined(OS_WIN)
+ return m->ReadUInt32(iter, reinterpret_cast<uint32*>(r));
+#else
+ const char *data;
+ int data_size = 0;
+ bool result = m->ReadData(iter, &data, &data_size);
+ if (result && data_size == sizeof(gfx::NativeWindow)) {
+ memcpy(r, data, sizeof(gfx::NativeWindow));
+ } else {
+ result = false;
+ NOTREACHED();
+ }
+ return result;
+#endif
+ }
+ static void Log(const param_type& p, std::wstring* l) {
+ l->append(L"<gfx::NativeWindow>");
+ }
+};
+
+template <>
+struct ParamTraits<PageZoom::Function> {
+ typedef PageZoom::Function param_type;
+ static void Write(Message* m, const param_type& p) {
+ WriteParam(m, static_cast<int>(p));
+ }
+ static bool Read(const Message* m, void** iter, param_type* r) {
+ int value;
+ if (!ReadParam(m, iter, &value))
+ return false;
+ *r = static_cast<param_type>(value);
+ return true;
+ }
+ static void Log(const param_type& p, std::wstring* l) {
+ LogParam(static_cast<int>(p), l);
+ }
+};
+
+
+template <>
+struct ParamTraits<WindowOpenDisposition> {
+ typedef WindowOpenDisposition param_type;
+ static void Write(Message* m, const param_type& p) {
+ WriteParam(m, static_cast<int>(p));
+ }
+ static bool Read(const Message* m, void** iter, param_type* r) {
+ int value;
+ if (!ReadParam(m, iter, &value))
+ return false;
+ *r = static_cast<param_type>(value);
+ return true;
+ }
+ static void Log(const param_type& p, std::wstring* l) {
+ LogParam(static_cast<int>(p), l);
+ }
+};
+
+
+template <>
+struct ParamTraits<WebCursor> {
+ typedef WebCursor param_type;
+ static void Write(Message* m, const param_type& p) {
+ p.Serialize(m);
+ }
+ static bool Read(const Message* m, void** iter, param_type* r) {
+ return r->Deserialize(m, iter);
+ }
+ static void Log(const param_type& p, std::wstring* l) {
+ l->append(L"<WebCursor>");
+ }
+};
+
+
+template <>
+struct ParamTraits<webkit_glue::WebApplicationInfo> {
+ typedef webkit_glue::WebApplicationInfo param_type;
+ static void Write(Message* m, const param_type& p);
+ static bool Read(const Message* m, void** iter, param_type* r);
+ static void Log(const param_type& p, std::wstring* l);
+};
+
+
+#if defined(OS_WIN)
+template<>
+struct ParamTraits<TransportDIB::Id> {
+ typedef TransportDIB::Id param_type;
+ static void Write(Message* m, const param_type& p) {
+ WriteParam(m, p.handle);
+ WriteParam(m, p.sequence_num);
+ }
+ static bool Read(const Message* m, void** iter, param_type* r) {
+ return (ReadParam(m, iter, &r->handle) &&
+ ReadParam(m, iter, &r->sequence_num));
+ }
+ static void Log(const param_type& p, std::wstring* l) {
+ l->append(L"TransportDIB(");
+ LogParam(p.handle, l);
+ l->append(L", ");
+ LogParam(p.sequence_num, l);
+ l->append(L")");
+ }
+};
+#endif
+
+// Traits for URLRequestStatus
+template <>
+struct ParamTraits<URLRequestStatus> {
+ typedef URLRequestStatus param_type;
+ static void Write(Message* m, const param_type& p);
+ static bool Read(const Message* m, void** iter, param_type* r);
+ static void Log(const param_type& p, std::wstring* l);
+};
+
+
+// Traits for net::UploadData::Element.
+template <>
+struct ParamTraits<net::UploadData::Element> {
+ typedef net::UploadData::Element param_type;
+ static void Write(Message* m, const param_type& p) {
+ WriteParam(m, static_cast<int>(p.type()));
+ if (p.type() == net::UploadData::TYPE_BYTES) {
+ m->WriteData(&p.bytes()[0], static_cast<int>(p.bytes().size()));
+ } else {
+ WriteParam(m, p.file_path());
+ WriteParam(m, p.file_range_offset());
+ WriteParam(m, p.file_range_length());
+ WriteParam(m, p.expected_file_modification_time());
+ }
+ }
+ static bool Read(const Message* m, void** iter, param_type* r) {
+ int type;
+ if (!ReadParam(m, iter, &type))
+ return false;
+ if (type == net::UploadData::TYPE_BYTES) {
+ const char* data;
+ int len;
+ if (!m->ReadData(iter, &data, &len))
+ return false;
+ r->SetToBytes(data, len);
+ } else {
+ DCHECK(type == net::UploadData::TYPE_FILE);
+ FilePath file_path;
+ uint64 offset, length;
+ base::Time expected_modification_time;
+ if (!ReadParam(m, iter, &file_path))
+ return false;
+ if (!ReadParam(m, iter, &offset))
+ return false;
+ if (!ReadParam(m, iter, &length))
+ return false;
+ if (!ReadParam(m, iter, &expected_modification_time))
+ return false;
+ r->SetToFilePathRange(file_path, offset, length,
+ expected_modification_time);
+ }
+ return true;
+ }
+ static void Log(const param_type& p, std::wstring* l) {
+ l->append(L"<net::UploadData::Element>");
+ }
+};
+
+// Traits for net::UploadData.
+template <>
+struct ParamTraits<scoped_refptr<net::UploadData> > {
+ typedef scoped_refptr<net::UploadData> param_type;
+ static void Write(Message* m, const param_type& p) {
+ WriteParam(m, p.get() != NULL);
+ if (p) {
+ WriteParam(m, *p->elements());
+ WriteParam(m, p->identifier());
+ }
+ }
+ static bool Read(const Message* m, void** iter, param_type* r) {
+ bool has_object;
+ if (!ReadParam(m, iter, &has_object))
+ return false;
+ if (!has_object)
+ return true;
+ std::vector<net::UploadData::Element> elements;
+ if (!ReadParam(m, iter, &elements))
+ return false;
+ int64 identifier;
+ if (!ReadParam(m, iter, &identifier))
+ return false;
+ *r = new net::UploadData;
+ (*r)->swap_elements(&elements);
+ (*r)->set_identifier(identifier);
+ return true;
+ }
+ static void Log(const param_type& p, std::wstring* l) {
+ l->append(L"<net::UploadData>");
+ }
+};
+
+template<>
+struct ParamTraits<ThumbnailScore> {
+ typedef ThumbnailScore param_type;
+ static void Write(Message* m, const param_type& p);
+ static bool Read(const Message* m, void** iter, param_type* r);
+ static void Log(const param_type& p, std::wstring* l);
+};
+
+template <>
+struct ParamTraits<Geoposition> {
+ typedef Geoposition param_type;
+ static void Write(Message* m, const param_type& p);
+ static bool Read(const Message* m, void** iter, param_type* p);
+ static void Log(const param_type& p, std::wstring* l);
+};
+
+template <>
+struct ParamTraits<Geoposition::ErrorCode> {
+ typedef Geoposition::ErrorCode param_type;
+ static void Write(Message* m, const param_type& p);
+ static bool Read(const Message* m, void** iter, param_type* p);
+ static void Log(const param_type& p, std::wstring* l);
+};
+
+template <>
+struct ParamTraits<webkit_glue::PasswordForm> {
+ typedef webkit_glue::PasswordForm param_type;
+ static void Write(Message* m, const param_type& p) {
+ WriteParam(m, p.signon_realm);
+ WriteParam(m, p.origin);
+ WriteParam(m, p.action);
+ WriteParam(m, p.submit_element);
+ WriteParam(m, p.username_element);
+ WriteParam(m, p.username_value);
+ WriteParam(m, p.password_element);
+ WriteParam(m, p.password_value);
+ WriteParam(m, p.old_password_element);
+ WriteParam(m, p.old_password_value);
+ WriteParam(m, p.ssl_valid);
+ WriteParam(m, p.preferred);
+ WriteParam(m, p.blacklisted_by_user);
+ }
+ static bool Read(const Message* m, void** iter, param_type* p) {
+ return
+ ReadParam(m, iter, &p->signon_realm) &&
+ ReadParam(m, iter, &p->origin) &&
+ ReadParam(m, iter, &p->action) &&
+ ReadParam(m, iter, &p->submit_element) &&
+ ReadParam(m, iter, &p->username_element) &&
+ ReadParam(m, iter, &p->username_value) &&
+ ReadParam(m, iter, &p->password_element) &&
+ ReadParam(m, iter, &p->password_value) &&
+ ReadParam(m, iter, &p->old_password_element) &&
+ ReadParam(m, iter, &p->old_password_value) &&
+ ReadParam(m, iter, &p->ssl_valid) &&
+ ReadParam(m, iter, &p->preferred) &&
+ ReadParam(m, iter, &p->blacklisted_by_user);
+ }
+ static void Log(const param_type& p, std::wstring* l) {
+ l->append(L"<PasswordForm>");
+ }
+};
+
+template <>
+struct ParamTraits<printing::PageRange> {
+ typedef printing::PageRange param_type;
+ static void Write(Message* m, const param_type& p);
+
+ static bool Read(const Message* m, void** iter, param_type* r);
+
+ static void Log(const param_type& p, std::wstring* l);
+};
+
+template <>
+struct ParamTraits<printing::NativeMetafile> {
+ typedef printing::NativeMetafile param_type;
+ static void Write(Message* m, const param_type& p);
+
+ static bool Read(const Message* m, void** iter, param_type* r);
+
+ static void Log(const param_type& p, std::wstring* l);
+};
+
+} // namespace IPC
+
+#endif // CHROME_COMMON_COMMON_PARAM_TRAITS_H_
diff --git a/chrome/common/common_param_traits_unittest.cc b/chrome/common/common_param_traits_unittest.cc
new file mode 100644
index 0000000..032f471
--- /dev/null
+++ b/chrome/common/common_param_traits_unittest.cc
@@ -0,0 +1,279 @@
+// Copyright (c) 2006-2008 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 <string.h>
+#include <utility>
+
+#include "base/scoped_ptr.h"
+#include "base/values.h"
+#include "chrome/common/common_param_traits.h"
+#include "gfx/rect.h"
+#include "googleurl/src/gurl.h"
+#include "ipc/ipc_message.h"
+#include "ipc/ipc_message_utils.h"
+#include "printing/native_metafile.h"
+#include "printing/page_range.h"
+#include "testing/gtest/include/gtest/gtest.h"
+#include "third_party/skia/include/core/SkBitmap.h"
+
+#ifndef NDEBUG
+namespace {
+void IgnoreAssertHandler(const std::string& str) {
+}
+} // namespace
+
+#endif // NDEBUG
+
+// Tests that serialize/deserialize correctly understand each other
+TEST(IPCMessageTest, Serialize) {
+ const char* serialize_cases[] = {
+ "http://www.google.com/",
+ "http://user:pass@host.com:888/foo;bar?baz#nop",
+ "#inva://idurl/",
+ };
+
+ for (size_t i = 0; i < arraysize(serialize_cases); i++) {
+ GURL input(serialize_cases[i]);
+ IPC::Message msg(1, 2, IPC::Message::PRIORITY_NORMAL);
+ IPC::ParamTraits<GURL>::Write(&msg, input);
+
+ GURL output;
+ void* iter = NULL;
+ EXPECT_TRUE(IPC::ParamTraits<GURL>::Read(&msg, &iter, &output));
+
+ // We want to test each component individually to make sure its range was
+ // correctly serialized and deserialized, not just the spec.
+ EXPECT_EQ(input.possibly_invalid_spec(), output.possibly_invalid_spec());
+ EXPECT_EQ(input.is_valid(), output.is_valid());
+ EXPECT_EQ(input.scheme(), output.scheme());
+ EXPECT_EQ(input.username(), output.username());
+ EXPECT_EQ(input.password(), output.password());
+ EXPECT_EQ(input.host(), output.host());
+ EXPECT_EQ(input.port(), output.port());
+ EXPECT_EQ(input.path(), output.path());
+ EXPECT_EQ(input.query(), output.query());
+ EXPECT_EQ(input.ref(), output.ref());
+ }
+
+ // Also test the corrupt case.
+ IPC::Message msg(1, 2, IPC::Message::PRIORITY_NORMAL);
+ msg.WriteInt(99);
+ GURL output;
+ void* iter = NULL;
+ EXPECT_FALSE(IPC::ParamTraits<GURL>::Read(&msg, &iter, &output));
+}
+
+// Tests std::pair serialization
+TEST(IPCMessageTest, Pair) {
+ typedef std::pair<std::string, std::string> TestPair;
+
+ TestPair input("foo", "bar");
+ IPC::Message msg(1, 2, IPC::Message::PRIORITY_NORMAL);
+ IPC::ParamTraits<TestPair>::Write(&msg, input);
+
+ TestPair output;
+ void* iter = NULL;
+ EXPECT_TRUE(IPC::ParamTraits<TestPair>::Read(&msg, &iter, &output));
+ EXPECT_EQ(output.first, "foo");
+ EXPECT_EQ(output.second, "bar");
+
+}
+
+// Tests bitmap serialization.
+TEST(IPCMessageTest, Bitmap) {
+ SkBitmap bitmap;
+
+ bitmap.setConfig(SkBitmap::kARGB_8888_Config, 10, 5);
+ bitmap.allocPixels();
+ memset(bitmap.getPixels(), 'A', bitmap.getSize());
+
+ IPC::Message msg(1, 2, IPC::Message::PRIORITY_NORMAL);
+ IPC::ParamTraits<SkBitmap>::Write(&msg, bitmap);
+
+ SkBitmap output;
+ void* iter = NULL;
+ EXPECT_TRUE(IPC::ParamTraits<SkBitmap>::Read(&msg, &iter, &output));
+
+ EXPECT_EQ(bitmap.config(), output.config());
+ EXPECT_EQ(bitmap.width(), output.width());
+ EXPECT_EQ(bitmap.height(), output.height());
+ EXPECT_EQ(bitmap.rowBytes(), output.rowBytes());
+ EXPECT_EQ(bitmap.getSize(), output.getSize());
+ EXPECT_EQ(memcmp(bitmap.getPixels(), output.getPixels(), bitmap.getSize()),
+ 0);
+
+ // Also test the corrupt case.
+ IPC::Message bad_msg(1, 2, IPC::Message::PRIORITY_NORMAL);
+ // Copy the first message block over to |bad_msg|.
+ const char* fixed_data;
+ int fixed_data_size;
+ iter = NULL;
+ msg.ReadData(&iter, &fixed_data, &fixed_data_size);
+ bad_msg.WriteData(fixed_data, fixed_data_size);
+ // Add some bogus pixel data.
+ const size_t bogus_pixels_size = bitmap.getSize() * 2;
+ scoped_array<char> bogus_pixels(new char[bogus_pixels_size]);
+ memset(bogus_pixels.get(), 'B', bogus_pixels_size);
+ bad_msg.WriteData(bogus_pixels.get(), bogus_pixels_size);
+ // Make sure we don't read out the bitmap!
+ SkBitmap bad_output;
+ iter = NULL;
+ EXPECT_FALSE(IPC::ParamTraits<SkBitmap>::Read(&bad_msg, &iter, &bad_output));
+}
+
+TEST(IPCMessageTest, ListValue) {
+ ListValue input;
+ input.Set(0, Value::CreateRealValue(42.42));
+ input.Set(1, Value::CreateStringValue("forty"));
+ input.Set(2, Value::CreateNullValue());
+
+ IPC::Message msg(1, 2, IPC::Message::PRIORITY_NORMAL);
+ IPC::WriteParam(&msg, input);
+
+ ListValue output;
+ void* iter = NULL;
+ EXPECT_TRUE(IPC::ReadParam(&msg, &iter, &output));
+
+ EXPECT_TRUE(input.Equals(&output));
+
+ // Also test the corrupt case.
+ IPC::Message bad_msg(1, 2, IPC::Message::PRIORITY_NORMAL);
+ bad_msg.WriteInt(99);
+ iter = NULL;
+ EXPECT_FALSE(IPC::ReadParam(&bad_msg, &iter, &output));
+}
+
+TEST(IPCMessageTest, DictionaryValue) {
+ DictionaryValue input;
+ input.Set(L"null", Value::CreateNullValue());
+ input.Set(L"bool", Value::CreateBooleanValue(true));
+ input.Set(L"int", Value::CreateIntegerValue(42));
+
+ scoped_ptr<DictionaryValue> subdict(new DictionaryValue());
+ subdict->Set(L"str", Value::CreateStringValue("forty two"));
+ subdict->Set(L"bool", Value::CreateBooleanValue(false));
+
+ scoped_ptr<ListValue> sublist(new ListValue());
+ sublist->Set(0, Value::CreateRealValue(42.42));
+ sublist->Set(1, Value::CreateStringValue("forty"));
+ sublist->Set(2, Value::CreateStringValue("two"));
+ subdict->Set(L"list", sublist.release());
+
+ input.Set(L"dict", subdict.release());
+
+ IPC::Message msg(1, 2, IPC::Message::PRIORITY_NORMAL);
+ IPC::WriteParam(&msg, input);
+
+ DictionaryValue output;
+ void* iter = NULL;
+ EXPECT_TRUE(IPC::ReadParam(&msg, &iter, &output));
+
+ EXPECT_TRUE(input.Equals(&output));
+
+ // Also test the corrupt case.
+ IPC::Message bad_msg(1, 2, IPC::Message::PRIORITY_NORMAL);
+ bad_msg.WriteInt(99);
+ iter = NULL;
+ EXPECT_FALSE(IPC::ReadParam(&bad_msg, &iter, &output));
+}
+
+TEST(IPCMessageTest, Geoposition) {
+ Geoposition input;
+ input.latitude = 0.1;
+ input.longitude = 51.3;
+ input.accuracy = 13.7;
+ input.altitude = 42.24;
+ input.altitude_accuracy = 9.3;
+ input.speed = 55;
+ input.heading = 120;
+ input.timestamp = base::Time::FromInternalValue(1977);
+ input.error_code = Geoposition::ERROR_CODE_POSITION_UNAVAILABLE;
+ input.error_message = "unittest error message for geoposition";
+
+ IPC::Message msg(1, 2, IPC::Message::PRIORITY_NORMAL);
+ IPC::WriteParam(&msg, input);
+
+ Geoposition output;
+ void* iter = NULL;
+ EXPECT_TRUE(IPC::ReadParam(&msg, &iter, &output));
+ EXPECT_EQ(input.altitude, output.altitude);
+ EXPECT_EQ(input.altitude_accuracy, output.altitude_accuracy);
+ EXPECT_EQ(input.latitude, output.latitude);
+ EXPECT_EQ(input.longitude, output.longitude);
+ EXPECT_EQ(input.accuracy, output.accuracy);
+ EXPECT_EQ(input.heading, output.heading);
+ EXPECT_EQ(input.speed, output.speed);
+ EXPECT_EQ(input.error_code, output.error_code);
+ EXPECT_EQ(input.error_message, output.error_message);
+
+ std::wstring log_message;
+ IPC::LogParam(output, &log_message);
+ EXPECT_STREQ(L"<Geoposition>"
+ L"0.100000 51.300000 13.700000 42.240000 "
+ L"9.300000 55.000000 120.000000 "
+ L"1977 unittest error message for geoposition"
+ L"<Geoposition::ErrorCode>2",
+ log_message.c_str());
+}
+
+// Tests printing::PageRange serialization
+TEST(IPCMessageTest, PageRange) {
+ printing::PageRange input;
+ input.from = 2;
+ input.to = 45;
+ IPC::Message msg(1, 2, IPC::Message::PRIORITY_NORMAL);
+ IPC::ParamTraits<printing::PageRange>::Write(&msg, input);
+
+ printing::PageRange output;
+ void* iter = NULL;
+ EXPECT_TRUE(IPC::ParamTraits<printing::PageRange>::Read(
+ &msg, &iter, &output));
+ EXPECT_TRUE(input == output);
+}
+
+// Tests printing::NativeMetafile serialization.
+TEST(IPCMessageTest, Metafile) {
+ // TODO(sanjeevr): Make this test meaningful for non-Windows platforms. We
+ // need to initialize the metafile using alternate means on the other OSes.
+#if defined(OS_WIN)
+ printing::NativeMetafile metafile;
+ RECT test_rect = {0, 0, 100, 100};
+ // Create a metsfile using the screen DC as a reference.
+ metafile.CreateDc(NULL, NULL);
+ metafile.CloseDc();
+
+ IPC::Message msg(1, 2, IPC::Message::PRIORITY_NORMAL);
+ IPC::ParamTraits<printing::NativeMetafile>::Write(&msg, metafile);
+
+ printing::NativeMetafile output;
+ void* iter = NULL;
+ EXPECT_TRUE(IPC::ParamTraits<printing::NativeMetafile>::Read(
+ &msg, &iter, &output));
+
+ EXPECT_EQ(metafile.GetDataSize(), output.GetDataSize());
+ EXPECT_EQ(metafile.GetBounds(), output.GetBounds());
+ EXPECT_EQ(::GetDeviceCaps(metafile.hdc(), LOGPIXELSX),
+ ::GetDeviceCaps(output.hdc(), LOGPIXELSX));
+
+ // Also test the corrupt case.
+ IPC::Message bad_msg(1, 2, IPC::Message::PRIORITY_NORMAL);
+ // Write some bogus metafile data.
+ const size_t bogus_data_size = metafile.GetDataSize() * 2;
+ scoped_array<char> bogus_data(new char[bogus_data_size]);
+ memset(bogus_data.get(), 'B', bogus_data_size);
+ bad_msg.WriteData(bogus_data.get(), bogus_data_size);
+ // Make sure we don't read out the metafile!
+ printing::NativeMetafile bad_output;
+ iter = NULL;
+ // The Emf code on Windows DCHECKs if it cannot create the metafile.
+#ifndef NDEBUG
+ logging::SetLogAssertHandler(IgnoreAssertHandler);
+#endif // NDEBUG
+ EXPECT_FALSE(IPC::ParamTraits<printing::NativeMetafile>::Read(
+ &bad_msg, &iter, &bad_output));
+#else // defined(OS_WIN)
+ NOTIMPLEMENTED();
+#endif // defined(OS_WIN)
+}
+
diff --git a/chrome/common/common_resources.grd b/chrome/common/common_resources.grd
new file mode 100644
index 0000000..ea1b784
--- /dev/null
+++ b/chrome/common/common_resources.grd
@@ -0,0 +1,17 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<grit latest_public_release="0" current_release="1">
+ <outputs>
+ <output filename="grit/common_resources.h" type="rc_header">
+ <emit emit_type='prepend'></emit>
+ </output>
+ <output filename="common_resources.pak" type="data_package" />
+ <output filename="common_resources.rc" type="rc_all" />
+ </outputs>
+ <release seq="1">
+ <includes>
+ <include name="IDR_EXTENSION_API_JSON" file="extensions\api\extension_api.json" type="BINDATA" />
+ <include name="IDR_I18N_TEMPLATE_JS" file="..\browser\resources\shared\js\i18n_template.js" type="BINDATA" />
+ <include name="IDR_JSTEMPLATE_JS" file="..\third_party\jstemplate\jstemplate_compiled.js" type="BINDATA" />
+ </includes>
+ </release>
+</grit>
diff --git a/chrome/common/content_settings.cc b/chrome/common/content_settings.cc
new file mode 100644
index 0000000..89eaa59
--- /dev/null
+++ b/chrome/common/content_settings.cc
@@ -0,0 +1,11 @@
+// Copyright (c) 2010 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/common/content_settings.h"
+
+ContentSetting IntToContentSetting(int content_setting) {
+ return ((content_setting < 0) ||
+ (content_setting >= CONTENT_SETTING_NUM_SETTINGS)) ?
+ CONTENT_SETTING_DEFAULT : static_cast<ContentSetting>(content_setting);
+}
diff --git a/chrome/common/content_settings.h b/chrome/common/content_settings.h
new file mode 100644
index 0000000..10fdcb5
--- /dev/null
+++ b/chrome/common/content_settings.h
@@ -0,0 +1,40 @@
+// Copyright (c) 2010 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_COMMON_CONTENT_SETTINGS_H_
+#define CHROME_COMMON_CONTENT_SETTINGS_H_
+
+#include "chrome/common/content_settings_types.h"
+
+// Different settings that can be assigned for a particular content type. We
+// give the user the ability to set these on a global and per-host basis.
+enum ContentSetting {
+ CONTENT_SETTING_DEFAULT = 0,
+ CONTENT_SETTING_ALLOW,
+ CONTENT_SETTING_BLOCK,
+ CONTENT_SETTING_ASK,
+ CONTENT_SETTING_SESSION_ONLY,
+ CONTENT_SETTING_NUM_SETTINGS
+};
+
+// Range-checked conversion of an int to a ContentSetting, for use when reading
+// prefs off disk.
+ContentSetting IntToContentSetting(int content_setting);
+
+// Aggregates the permissions for the different content types.
+struct ContentSettings {
+ ContentSettings() {
+ for (int i = 0; i < CONTENT_SETTINGS_NUM_TYPES; ++i)
+ settings[i] = CONTENT_SETTING_DEFAULT;
+ }
+
+ explicit ContentSettings(ContentSetting default_setting) {
+ for (int i = 0; i < CONTENT_SETTINGS_NUM_TYPES; ++i)
+ settings[i] = default_setting;
+ }
+
+ ContentSetting settings[CONTENT_SETTINGS_NUM_TYPES];
+};
+
+#endif // CHROME_COMMON_CONTENT_SETTINGS_H_
diff --git a/chrome/common/content_settings_helper.cc b/chrome/common/content_settings_helper.cc
new file mode 100644
index 0000000..315b5e4
--- /dev/null
+++ b/chrome/common/content_settings_helper.cc
@@ -0,0 +1,22 @@
+// Copyright (c) 2010 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/common/content_settings_helper.h"
+
+#include "base/utf_string_conversions.h"
+#include "base/string_piece.h"
+#include "chrome/common/url_constants.h"
+#include "googleurl/src/gurl.h"
+
+namespace content_settings_helper {
+
+std::wstring OriginToWString(const GURL& origin) {
+ std::string port_component((origin.IntPort() != url_parse::PORT_UNSPECIFIED) ?
+ ":" + origin.port() : "");
+ std::string scheme_component(!origin.SchemeIs(chrome::kHttpScheme) ?
+ origin.scheme() + chrome::kStandardSchemeSeparator : "");
+ return UTF8ToWide(scheme_component + origin.host() + port_component);
+}
+
+} // namespace content_settings_helper
diff --git a/chrome/common/content_settings_helper.h b/chrome/common/content_settings_helper.h
new file mode 100644
index 0000000..0aa2947
--- /dev/null
+++ b/chrome/common/content_settings_helper.h
@@ -0,0 +1,20 @@
+// Copyright (c) 2010 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_COMMON_CONTENT_SETTINGS_HELPER_H_
+#define CHROME_COMMON_CONTENT_SETTINGS_HELPER_H_
+
+#include <string>
+
+class GURL;
+
+namespace content_settings_helper {
+
+// Return simplified string representing origin. If origin is using http or
+// the standard port, those parts are not included in the output.
+std::wstring OriginToWString(const GURL& origin);
+
+} // namespace content_settings_helper
+
+#endif // CHROME_COMMON_CONTENT_SETTINGS_HELPER_H_
diff --git a/chrome/common/content_settings_helper_unittest.cc b/chrome/common/content_settings_helper_unittest.cc
new file mode 100644
index 0000000..d46eda6
--- /dev/null
+++ b/chrome/common/content_settings_helper_unittest.cc
@@ -0,0 +1,42 @@
+// Copyright (c) 2010 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/common/content_settings_helper.h"
+
+#include "googleurl/src/gurl.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+TEST(ContentSettingsHelperTest, OriginToWString) {
+ // Urls with "http":
+ const GURL kUrl0("http://www.foo.com/bar");
+ const GURL kUrl1("http://foo.com/bar");
+
+ const GURL kUrl2("http://www.foo.com:81/bar");
+ const GURL kUrl3("http://foo.com:81/bar");
+
+ // Urls with "https":
+ const GURL kUrl4("https://www.foo.com/bar");
+ const GURL kUrl5("https://foo.com/bar");
+
+ const GURL kUrl6("https://www.foo.com:81/bar");
+ const GURL kUrl7("https://foo.com:81/bar");
+
+ // Now check the first group of urls with just "http":
+ EXPECT_EQ(L"www.foo.com", content_settings_helper::OriginToWString(kUrl0));
+ EXPECT_EQ(L"foo.com", content_settings_helper::OriginToWString(kUrl1));
+
+ EXPECT_EQ(L"www.foo.com:81", content_settings_helper::OriginToWString(kUrl2));
+ EXPECT_EQ(L"foo.com:81", content_settings_helper::OriginToWString(kUrl3));
+
+ // Now check the second group of urls with "https":
+ EXPECT_EQ(L"https://www.foo.com",
+ content_settings_helper::OriginToWString(kUrl4));
+ EXPECT_EQ(L"https://foo.com",
+ content_settings_helper::OriginToWString(kUrl5));
+
+ EXPECT_EQ(L"https://www.foo.com:81",
+ content_settings_helper::OriginToWString(kUrl6));
+ EXPECT_EQ(L"https://foo.com:81",
+ content_settings_helper::OriginToWString(kUrl7));
+}
diff --git a/chrome/common/content_settings_types.h b/chrome/common/content_settings_types.h
new file mode 100644
index 0000000..2e2a563
--- /dev/null
+++ b/chrome/common/content_settings_types.h
@@ -0,0 +1,24 @@
+// Copyright (c) 2010 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_COMMON_CONTENT_SETTINGS_TYPES_H_
+#define CHROME_COMMON_CONTENT_SETTINGS_TYPES_H_
+
+// A particular type of content to care about. We give the user various types
+// of controls over each of these.
+enum ContentSettingsType {
+ // "DEFAULT" is only used as an argument to the Content Settings Window
+ // opener; there it means "whatever was last shown".
+ CONTENT_SETTINGS_TYPE_DEFAULT = -1,
+ CONTENT_SETTINGS_TYPE_COOKIES = 0,
+ CONTENT_SETTINGS_TYPE_IMAGES,
+ CONTENT_SETTINGS_TYPE_JAVASCRIPT,
+ CONTENT_SETTINGS_TYPE_PLUGINS,
+ CONTENT_SETTINGS_TYPE_POPUPS,
+ CONTENT_SETTINGS_TYPE_GEOLOCATION,
+ CONTENT_SETTINGS_TYPE_NOTIFICATIONS,
+ CONTENT_SETTINGS_NUM_TYPES
+};
+
+#endif // CHROME_COMMON_CONTENT_SETTINGS_TYPES_H_
diff --git a/chrome/common/css_colors.h b/chrome/common/css_colors.h
new file mode 100644
index 0000000..d952e98
--- /dev/null
+++ b/chrome/common/css_colors.h
@@ -0,0 +1,25 @@
+// Copyright (c) 2009 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_COMMON_CSS_COLORS_H_
+#define CHROME_COMMON_CSS_COLORS_H_
+
+#include <utility>
+
+#include "base/basictypes.h"
+#include "third_party/WebKit/WebKit/chromium/public/WebColor.h"
+#include "third_party/WebKit/WebKit/chromium/public/WebColorName.h"
+
+// Functionality related to sending the values of CSS colors to the renderer.
+class CSSColors {
+ public:
+ typedef WebKit::WebColorName CSSColorName;
+ typedef std::pair<CSSColorName, WebKit::WebColor> CSSColorMapping;
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(CSSColors);
+};
+
+#endif // CHROME_COMMON_CSS_COLORS_H_
+
diff --git a/chrome/common/database_util.cc b/chrome/common/database_util.cc
new file mode 100644
index 0000000..c62e5fa
--- /dev/null
+++ b/chrome/common/database_util.cc
@@ -0,0 +1,53 @@
+// Copyright (c) 2010 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/common/database_util.h"
+
+#include "chrome/common/child_thread.h"
+#include "chrome/common/render_messages.h"
+#include "ipc/ipc_sync_message_filter.h"
+#include "third_party/sqlite/preprocessed/sqlite3.h"
+#include "third_party/WebKit/WebKit/chromium/public/WebString.h"
+
+using WebKit::WebKitClient;
+using WebKit::WebString;
+
+WebKitClient::FileHandle DatabaseUtil::databaseOpenFile(
+ const WebString& vfs_file_name, int desired_flags) {
+ IPC::PlatformFileForTransit file_handle =
+ IPC::InvalidPlatformFileForTransit();
+
+ scoped_refptr<IPC::SyncMessageFilter> filter =
+ ChildThread::current()->sync_message_filter();
+ filter->Send(new ViewHostMsg_DatabaseOpenFile(
+ vfs_file_name, desired_flags, &file_handle));
+
+ return IPC::PlatformFileForTransitToPlatformFile(file_handle);
+}
+
+int DatabaseUtil::databaseDeleteFile(
+ const WebString& vfs_file_name, bool sync_dir) {
+ int rv = SQLITE_IOERR_DELETE;
+ scoped_refptr<IPC::SyncMessageFilter> filter =
+ ChildThread::current()->sync_message_filter();
+ filter->Send(new ViewHostMsg_DatabaseDeleteFile(
+ vfs_file_name, sync_dir, &rv));
+ return rv;
+}
+
+long DatabaseUtil::databaseGetFileAttributes(const WebString& vfs_file_name) {
+ int32 rv = -1;
+ scoped_refptr<IPC::SyncMessageFilter> filter =
+ ChildThread::current()->sync_message_filter();
+ filter->Send(new ViewHostMsg_DatabaseGetFileAttributes(vfs_file_name, &rv));
+ return rv;
+}
+
+long long DatabaseUtil::databaseGetFileSize(const WebString& vfs_file_name) {
+ int64 rv = 0LL;
+ scoped_refptr<IPC::SyncMessageFilter> filter =
+ ChildThread::current()->sync_message_filter();
+ filter->Send(new ViewHostMsg_DatabaseGetFileSize(vfs_file_name, &rv));
+ return rv;
+}
diff --git a/chrome/common/database_util.h b/chrome/common/database_util.h
new file mode 100644
index 0000000..9c263af
--- /dev/null
+++ b/chrome/common/database_util.h
@@ -0,0 +1,22 @@
+// Copyright (c) 2010 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_COMMON_DATABASE_UTIL_H_
+#define CHROME_COMMON_DATABASE_UTIL_H_
+
+#include "webkit/glue/webkitclient_impl.h"
+
+// A class of utility functions used by RendererWebKitClientImpl and
+// WorkerWebKitClientImpl to handle database file accesses.
+class DatabaseUtil {
+ public:
+ static WebKit::WebKitClient::FileHandle databaseOpenFile(
+ const WebKit::WebString& vfs_file_name, int desired_flags);
+ static int databaseDeleteFile(const WebKit::WebString& vfs_file_name,
+ bool sync_dir);
+ static long databaseGetFileAttributes(const WebKit::WebString& vfs_file_name);
+ static long long databaseGetFileSize(const WebKit::WebString& vfs_file_name);
+};
+
+#endif // CHROME_COMMON_DATABASE_UTIL_H_
diff --git a/chrome/common/db_message_filter.cc b/chrome/common/db_message_filter.cc
new file mode 100644
index 0000000..8e3bbc6
--- /dev/null
+++ b/chrome/common/db_message_filter.cc
@@ -0,0 +1,37 @@
+// Copyright (c) 2010 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/common/db_message_filter.h"
+
+#include "chrome/common/render_messages.h"
+#include "third_party/WebKit/WebKit/chromium/public/WebDatabase.h"
+
+DBMessageFilter::DBMessageFilter() {
+}
+
+bool DBMessageFilter::OnMessageReceived(const IPC::Message& message) {
+ bool handled = true;
+ IPC_BEGIN_MESSAGE_MAP(DBMessageFilter, message)
+ IPC_MESSAGE_HANDLER(ViewMsg_DatabaseUpdateSize, OnDatabaseUpdateSize)
+ IPC_MESSAGE_HANDLER(ViewMsg_DatabaseCloseImmediately,
+ OnDatabaseCloseImmediately)
+ IPC_MESSAGE_UNHANDLED(handled = false)
+ IPC_END_MESSAGE_MAP()
+ return handled;
+}
+
+void DBMessageFilter::OnDatabaseUpdateSize(const string16& origin_identifier,
+ const string16& database_name,
+ int64 database_size,
+ int64 space_available) {
+ WebKit::WebDatabase::updateDatabaseSize(
+ origin_identifier, database_name, database_size, space_available);
+}
+
+void DBMessageFilter::OnDatabaseCloseImmediately(
+ const string16& origin_identifier,
+ const string16& database_name) {
+ WebKit::WebDatabase::closeDatabaseImmediately(
+ origin_identifier, database_name);
+}
diff --git a/chrome/common/db_message_filter.h b/chrome/common/db_message_filter.h
new file mode 100644
index 0000000..1cb07d8
--- /dev/null
+++ b/chrome/common/db_message_filter.h
@@ -0,0 +1,27 @@
+// Copyright (c) 2010 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_COMMON_DB_MESSAGE_FILTER_H_
+#define CHROME_COMMON_DB_MESSAGE_FILTER_H_
+
+#include "ipc/ipc_channel_proxy.h"
+
+// Receives database messages from the browser process and processes them on the
+// IO thread.
+class DBMessageFilter : public IPC::ChannelProxy::MessageFilter {
+ public:
+ DBMessageFilter();
+
+ private:
+ virtual bool OnMessageReceived(const IPC::Message& message);
+
+ void OnDatabaseUpdateSize(const string16& origin_identifier,
+ const string16& database_name,
+ int64 database_size,
+ int64 space_available);
+ void OnDatabaseCloseImmediately(const string16& origin_identifier,
+ const string16& database_name);
+};
+
+#endif // CHROME_COMMON_DB_MESSAGE_FILTER_H_
diff --git a/chrome/common/debug_flags.cc b/chrome/common/debug_flags.cc
new file mode 100644
index 0000000..dd2eaee
--- /dev/null
+++ b/chrome/common/debug_flags.cc
@@ -0,0 +1,50 @@
+// Copyright (c) 2006-2008 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/common/debug_flags.h"
+
+#include "base/base_switches.h"
+#include "base/command_line.h"
+#include "base/utf_string_conversions.h"
+#include "chrome/common/chrome_switches.h"
+#include "ipc/ipc_switches.h"
+
+bool DebugFlags::ProcessDebugFlags(CommandLine* command_line,
+ ChildProcessInfo::ProcessType type,
+ bool is_in_sandbox) {
+ bool should_help_child = false;
+ const CommandLine& current_cmd_line = *CommandLine::ForCurrentProcess();
+ if (current_cmd_line.HasSwitch(switches::kDebugChildren)) {
+ // Look to pass-on the kDebugOnStart flag.
+ std::string value = current_cmd_line.GetSwitchValueASCII(
+ switches::kDebugChildren);
+ if (value.empty() ||
+ (type == ChildProcessInfo::WORKER_PROCESS &&
+ value == switches::kWorkerProcess) ||
+ (type == ChildProcessInfo::RENDER_PROCESS &&
+ value == switches::kRendererProcess) ||
+ (type == ChildProcessInfo::PLUGIN_PROCESS &&
+ value == switches::kPluginProcess)) {
+ command_line->AppendSwitch(switches::kDebugOnStart);
+ should_help_child = true;
+ }
+ command_line->AppendSwitchWithValue(switches::kDebugChildren, value);
+ } else if (current_cmd_line.HasSwitch(switches::kWaitForDebuggerChildren)) {
+ // Look to pass-on the kWaitForDebugger flag.
+ std::string value = current_cmd_line.GetSwitchValueASCII(
+ switches::kWaitForDebuggerChildren);
+ if (value.empty() ||
+ (type == ChildProcessInfo::WORKER_PROCESS &&
+ value == switches::kWorkerProcess) ||
+ (type == ChildProcessInfo::RENDER_PROCESS &&
+ value == switches::kRendererProcess) ||
+ (type == ChildProcessInfo::PLUGIN_PROCESS &&
+ value == switches::kPluginProcess)) {
+ command_line->AppendSwitch(switches::kWaitForDebugger);
+ }
+ command_line->AppendSwitchWithValue(switches::kWaitForDebuggerChildren,
+ value);
+ }
+ return should_help_child;
+}
diff --git a/chrome/common/debug_flags.h b/chrome/common/debug_flags.h
new file mode 100644
index 0000000..231d2ca
--- /dev/null
+++ b/chrome/common/debug_flags.h
@@ -0,0 +1,28 @@
+// Copyright (c) 2006-2008 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_COMMON_DEBUG_FLAGS_H__
+#define CHROME_COMMON_DEBUG_FLAGS_H__
+
+#include "chrome/common/child_process_info.h"
+
+class CommandLine;
+
+class DebugFlags {
+ public:
+
+ // Updates the command line arguments with debug-related flags. If
+ // debug flags have been used with this process, they will be
+ // filtered and added to command_line as needed. is_in_sandbox must
+ // be true if the child process will be in a sandbox.
+ //
+ // Returns true if the caller should "help" the child process by
+ // calling the JIT debugger on it. It may only happen if
+ // is_in_sandbox is true.
+ static bool ProcessDebugFlags(CommandLine* command_line,
+ ChildProcessInfo::ProcessType type,
+ bool is_in_sandbox);
+};
+
+#endif // CHROME_COMMON_DEBUG_FLAGS_H__
diff --git a/chrome/common/default_plugin.cc b/chrome/common/default_plugin.cc
new file mode 100644
index 0000000..bba738b
--- /dev/null
+++ b/chrome/common/default_plugin.cc
@@ -0,0 +1,33 @@
+// Copyright (c) 2010 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/common/default_plugin.h"
+
+#include "chrome/default_plugin/plugin_main.h"
+#include "webkit/glue/plugins/plugin_list.h"
+
+namespace chrome {
+
+void RegisterInternalDefaultPlugin() {
+ const NPAPI::PluginVersionInfo default_plugin = {
+ FilePath(kDefaultPluginLibraryName),
+ L"Default Plug-in",
+ L"Provides functionality for installing third-party plug-ins",
+ L"1",
+ L"*",
+ L"",
+ L"",
+ {
+#if !defined(OS_POSIX) || defined(OS_MACOSX)
+ default_plugin::NP_GetEntryPoints,
+#endif
+ default_plugin::NP_Initialize,
+ default_plugin::NP_Shutdown
+ }
+ };
+
+ NPAPI::PluginList::Singleton()->RegisterInternalPlugin(default_plugin);
+}
+
+} // namespace chrome
diff --git a/chrome/common/default_plugin.h b/chrome/common/default_plugin.h
new file mode 100644
index 0000000..e3394e8
--- /dev/null
+++ b/chrome/common/default_plugin.h
@@ -0,0 +1,15 @@
+// Copyright (c) 2010 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_COMMON_DEFAULT_PLUGIN_H_
+#define CHROME_COMMON_DEFAULT_PLUGIN_H_
+
+namespace chrome {
+
+// Register the default plugin as an internal plugin in the PluginList.
+void RegisterInternalDefaultPlugin();
+
+} // namespace chrome
+
+#endif // CHROME_COMMON_DEFAULT_PLUGIN_H_
diff --git a/chrome/common/deprecated/event_sys-inl.h b/chrome/common/deprecated/event_sys-inl.h
new file mode 100644
index 0000000..62fa350
--- /dev/null
+++ b/chrome/common/deprecated/event_sys-inl.h
@@ -0,0 +1,341 @@
+// Copyright (c) 2009 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_COMMON_DEPRECATED_EVENT_SYS_INL_H_
+#define CHROME_COMMON_DEPRECATED_EVENT_SYS_INL_H_
+
+#include <map>
+
+#include "base/atomicops.h"
+#include "base/basictypes.h"
+#include "base/condition_variable.h"
+#include "base/lock.h"
+#include "base/logging.h"
+#include "base/message_loop.h"
+#include "base/port.h"
+#include "chrome/common/deprecated/event_sys.h"
+
+// How to use Channels:
+
+// 0. Assume Bob is the name of the class from which you want to broadcast
+// events.
+// 1. Choose an EventType. This could be an Enum or something more complicated.
+// 2. Create an EventTraits class for your EventType. It must have
+// two members:
+//
+// typedef x EventType;
+// static bool IsChannelShutdownEvent(const EventType& event);
+//
+// 3. Add an EventChannel<MyEventTraits>* instance and event_channel() const;
+// accessor to Bob.
+// Delete the channel ordinarily in Bob's destructor, or whenever you want.
+// 4. To broadcast events, call bob->event_channel()->NotifyListeners(event).
+// 5. Only call NotifyListeners from a single thread at a time.
+
+// How to use Listeners/Hookups:
+
+// 0. Assume you want a class called Lisa to listen to events from Bob.
+// 1. Create an event handler method in Lisa. Its single argument should be of
+// your event type.
+// 2. Add a EventListenerHookup* hookup_ member to Lisa.
+// 3. Initialize the hookup by calling:
+//
+// hookup_ = NewEventListenerHookup(bob->event_channel(),
+// this,
+// &Lisa::HandleEvent);
+//
+// 4. Delete hookup_ in Lisa's destructor, or anytime sooner to stop receiving
+// events.
+
+// An Event Channel is a source, or broadcaster of events. Listeners subscribe
+// by calling the AddListener() method. The owner of the channel calls the
+// NotifyListeners() method.
+//
+// Don't inherit from this class. Just make an event_channel member and an
+// event_channel() accessor.
+
+// No reason why CallbackWaiters has to be templatized.
+class CallbackWaiters {
+ public:
+ CallbackWaiters() : waiter_count_(0),
+ callback_done_(false),
+ condvar_(&mutex_) {
+ }
+ ~CallbackWaiters() {
+ DCHECK_EQ(0, waiter_count_);
+ }
+ void WaitForCallbackToComplete(Lock* listeners_mutex) {
+ {
+ AutoLock lock(mutex_);
+ waiter_count_ += 1;
+ listeners_mutex->Release();
+ while (!callback_done_)
+ condvar_.Wait();
+ waiter_count_ -= 1;
+ if (0 != waiter_count_)
+ return;
+ }
+ delete this;
+ }
+
+ void Signal() {
+ AutoLock lock(mutex_);
+ callback_done_ = true;
+ condvar_.Broadcast();
+ }
+
+ protected:
+ int waiter_count_;
+ bool callback_done_;
+ Lock mutex_;
+ ConditionVariable condvar_;
+};
+
+template <typename EventTraitsType, typename NotifyLock,
+ typename ScopedNotifyLocker>
+class EventChannel {
+ public:
+ typedef EventTraitsType EventTraits;
+ typedef typename EventTraits::EventType EventType;
+ typedef EventListener<EventType> Listener;
+
+ protected:
+ typedef std::map<Listener*, bool> Listeners;
+
+ public:
+ // The shutdown event gets send in the EventChannel's destructor.
+ explicit EventChannel(const EventType& shutdown_event)
+ : current_listener_callback_(NULL),
+ callback_waiters_(NULL),
+ shutdown_event_(shutdown_event) {
+ }
+
+ ~EventChannel() {
+ // Tell all the listeners that the channel is being deleted.
+ NotifyListeners(shutdown_event_);
+
+ // Make sure all the listeners have been disconnected. Otherwise, they
+ // will try to call RemoveListener() at a later date.
+#if defined(DEBUG)
+ AutoLock lock(listeners_mutex_);
+ for (typename Listeners::iterator i = listeners_.begin();
+ i != listeners_.end(); ++i) {
+ DCHECK(i->second) << "Listener not disconnected";
+ }
+#endif
+ }
+
+ // Never call this twice for the same listener.
+ //
+ // Thread safe.
+ void AddListener(Listener* listener) {
+ AutoLock lock(listeners_mutex_);
+ typename Listeners::iterator found = listeners_.find(listener);
+ if (found == listeners_.end()) {
+ listeners_.insert(std::make_pair(listener,
+ false)); // Not dead yet.
+ } else {
+ DCHECK(found->second) << "Attempted to add the same listener twice.";
+ found->second = false; // Not dead yet.
+ }
+ }
+
+ // If listener's callback is currently executing, this method waits until the
+ // callback completes before returning.
+ //
+ // Thread safe.
+ void RemoveListener(Listener* listener) {
+ bool wait = false;
+ listeners_mutex_.Acquire();
+ typename Listeners::iterator found = listeners_.find(listener);
+ if (found != listeners_.end()) {
+ found->second = true; // Mark as dead.
+ wait = (found->first == current_listener_callback_ &&
+ (MessageLoop::current() != current_listener_callback_message_loop_));
+ }
+ if (!wait) {
+ listeners_mutex_.Release();
+ return;
+ }
+ if (NULL == callback_waiters_)
+ callback_waiters_ = new CallbackWaiters;
+ callback_waiters_->WaitForCallbackToComplete(&listeners_mutex_);
+ }
+
+ // Blocks until all listeners have been notified.
+ //
+ // NOT thread safe. Must only be called by one thread at a time.
+ void NotifyListeners(const EventType& event) {
+ ScopedNotifyLocker lock_notify(notify_lock_);
+ listeners_mutex_.Acquire();
+ DCHECK(NULL == current_listener_callback_);
+ current_listener_callback_message_loop_ = MessageLoop::current();
+ typename Listeners::iterator i = listeners_.begin();
+ while (i != listeners_.end()) {
+ if (i->second) { // Clean out dead listeners
+ listeners_.erase(i++);
+ continue;
+ }
+ current_listener_callback_ = i->first;
+ listeners_mutex_.Release();
+
+ i->first->HandleEvent(event);
+
+ listeners_mutex_.Acquire();
+ current_listener_callback_ = NULL;
+ if (NULL != callback_waiters_) {
+ callback_waiters_->Signal();
+ callback_waiters_ = NULL;
+ }
+
+ ++i;
+ }
+ listeners_mutex_.Release();
+ }
+
+ // A map iterator remains valid until the element it points to gets removed
+ // from the map, so a map is perfect for our needs.
+ //
+ // Map value is a bool, true means the Listener is dead.
+ Listeners listeners_;
+ // NULL means no callback is currently being called.
+ Listener* current_listener_callback_;
+ // Only valid when current_listener is not NULL.
+ // The thread on which the callback is executing.
+ MessageLoop* current_listener_callback_message_loop_;
+ // Win32 Event that is usually NULL. Only created when another thread calls
+ // Remove while in callback. Owned and closed by the thread calling Remove().
+ CallbackWaiters* callback_waiters_;
+
+ Lock listeners_mutex_; // Protects all members above.
+ const EventType shutdown_event_;
+ NotifyLock notify_lock_;
+
+ DISALLOW_COPY_AND_ASSIGN(EventChannel);
+};
+
+// An EventListenerHookup hooks up a method in your class to an EventChannel.
+// Deleting the hookup disconnects from the EventChannel.
+//
+// Contains complexity of inheriting from Listener class and managing lifetimes.
+//
+// Create using NewEventListenerHookup() to avoid explicit template arguments.
+class EventListenerHookup {
+ public:
+ virtual ~EventListenerHookup() { }
+};
+
+template <typename EventChannel, typename EventTraits,
+ class Derived>
+class EventListenerHookupImpl : public EventListenerHookup,
+public EventListener<typename EventTraits::EventType> {
+ public:
+ explicit EventListenerHookupImpl(EventChannel* channel)
+ : channel_(channel), deleted_(NULL) {
+ channel->AddListener(this);
+ connected_ = true;
+ }
+
+ ~EventListenerHookupImpl() {
+ if (NULL != deleted_)
+ *deleted_ = true;
+ if (connected_)
+ channel_->RemoveListener(this);
+ }
+
+ typedef typename EventTraits::EventType EventType;
+ virtual void HandleEvent(const EventType& event) {
+ DCHECK(connected_);
+ bool deleted = false;
+ deleted_ = &deleted;
+ static_cast<Derived*>(this)->Callback(event);
+ if (deleted) // The callback (legally) deleted this.
+ return; // The only safe thing to do.
+ deleted_ = NULL;
+ if (EventTraits::IsChannelShutdownEvent(event)) {
+ channel_->RemoveListener(this);
+ connected_ = false;
+ }
+ }
+
+ protected:
+ EventChannel* const channel_;
+ bool connected_;
+ bool* deleted_; // Allows the handler to delete the hookup.
+};
+
+// SimpleHookup just passes the event to the callback message.
+template <typename EventChannel, typename EventTraits,
+ typename CallbackObject, typename CallbackMethod>
+class SimpleHookup
+ : public EventListenerHookupImpl<EventChannel, EventTraits,
+ SimpleHookup<EventChannel,
+ EventTraits,
+ CallbackObject,
+ CallbackMethod> > {
+ public:
+ SimpleHookup(EventChannel* channel, CallbackObject* cbobject,
+ CallbackMethod cbmethod)
+ : EventListenerHookupImpl<EventChannel, EventTraits,
+ SimpleHookup>(channel), cbobject_(cbobject),
+ cbmethod_(cbmethod) { }
+
+ typedef typename EventTraits::EventType EventType;
+ void Callback(const EventType& event) {
+ (cbobject_->*cbmethod_)(event);
+ }
+ CallbackObject* const cbobject_;
+ CallbackMethod const cbmethod_;
+};
+
+// ArgHookup also passes an additional arg to the callback method.
+template <typename EventChannel, typename EventTraits,
+ typename CallbackObject, typename CallbackMethod,
+ typename CallbackArg0>
+class ArgHookup
+ : public EventListenerHookupImpl<EventChannel, EventTraits,
+ ArgHookup<EventChannel, EventTraits,
+ CallbackObject,
+ CallbackMethod,
+ CallbackArg0> > {
+ public:
+ ArgHookup(EventChannel* channel, CallbackObject* cbobject,
+ CallbackMethod cbmethod, CallbackArg0 arg0)
+ : EventListenerHookupImpl<EventChannel, EventTraits,
+ ArgHookup>(channel), cbobject_(cbobject),
+ cbmethod_(cbmethod), arg0_(arg0) { }
+
+ typedef typename EventTraits::EventType EventType;
+ void Callback(const EventType& event) {
+ (cbobject_->*cbmethod_)(arg0_, event);
+ }
+ CallbackObject* const cbobject_;
+ CallbackMethod const cbmethod_;
+ CallbackArg0 const arg0_;
+};
+
+
+template <typename EventChannel, typename CallbackObject,
+ typename CallbackMethod>
+EventListenerHookup* NewEventListenerHookup(EventChannel* channel,
+ CallbackObject* cbobject,
+ CallbackMethod cbmethod) {
+ return new SimpleHookup<EventChannel,
+ typename EventChannel::EventTraits,
+ CallbackObject, CallbackMethod>(channel, cbobject, cbmethod);
+}
+
+template <typename EventChannel, typename CallbackObject,
+ typename CallbackMethod, typename CallbackArg0>
+EventListenerHookup* NewEventListenerHookup(EventChannel* channel,
+ CallbackObject* cbobject,
+ CallbackMethod cbmethod,
+ CallbackArg0 arg0) {
+ return new ArgHookup<EventChannel,
+ typename EventChannel::EventTraits,
+ CallbackObject, CallbackMethod, CallbackArg0>(channel, cbobject,
+ cbmethod, arg0);
+}
+
+#endif // CHROME_COMMON_DEPRECATED_EVENT_SYS_INL_H_
diff --git a/chrome/common/deprecated/event_sys.h b/chrome/common/deprecated/event_sys.h
new file mode 100644
index 0000000..bec8144
--- /dev/null
+++ b/chrome/common/deprecated/event_sys.h
@@ -0,0 +1,45 @@
+// Copyright (c) 2009 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_COMMON_DEPRECATED_EVENT_SYS_H_
+#define CHROME_COMMON_DEPRECATED_EVENT_SYS_H_
+
+// TODO: This class should be removed or moved to Notifier code.
+// See Bug 42450 (http://code.google.com/p/chromium/issues/detail?id=42450).
+
+class AutoLock;
+class Lock;
+
+// An abstract base class for listening to events.
+//
+// Don't inherit from this class yourself. Using NewEventListenerHookup() is
+// much easier.
+template <typename EventType>
+class EventListener {
+ public:
+ virtual void HandleEvent(const EventType& event) = 0;
+};
+
+// See the -inl.h for details about the following.
+
+template <typename EventTraits, typename NotifyLock = Lock,
+ typename ScopedNotifyLocker = AutoLock>
+class EventChannel;
+
+class EventListenerHookup;
+
+template <typename EventChannel, typename CallbackObject,
+ typename CallbackMethod>
+EventListenerHookup* NewEventListenerHookup(EventChannel* channel,
+ CallbackObject* cbobject,
+ CallbackMethod cbmethod);
+
+template <typename EventChannel, typename CallbackObject,
+ typename CallbackMethod, typename CallbackArg0>
+EventListenerHookup* NewEventListenerHookup(EventChannel* channel,
+ CallbackObject* cbobject,
+ CallbackMethod cbmethod,
+ CallbackArg0 arg0);
+
+#endif // CHROME_COMMON_DEPRECATED_EVENT_SYS_H_
diff --git a/chrome/common/deprecated/event_sys_unittest.cc b/chrome/common/deprecated/event_sys_unittest.cc
new file mode 100644
index 0000000..c70d3f7
--- /dev/null
+++ b/chrome/common/deprecated/event_sys_unittest.cc
@@ -0,0 +1,271 @@
+// Copyright (c) 2009 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 <iosfwd>
+#include <sstream>
+#include <string>
+#include <vector>
+
+#include "base/basictypes.h"
+#include "base/logging.h"
+#include "base/message_loop.h"
+#include "base/platform_thread.h"
+#include "base/port.h"
+#include "build/build_config.h"
+#include "chrome/common/deprecated/event_sys-inl.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+using std::endl;
+using std::ostream;
+using std::string;
+using std::stringstream;
+using std::vector;
+
+namespace {
+
+class Pair;
+
+struct TestEvent {
+ Pair* source;
+ enum {
+ A_CHANGED, B_CHANGED, PAIR_BEING_DELETED,
+ } what_happened;
+ int old_value;
+};
+
+struct TestEventTraits {
+ typedef TestEvent EventType;
+ static bool IsChannelShutdownEvent(const TestEvent& event) {
+ return TestEvent::PAIR_BEING_DELETED == event.what_happened;
+ }
+};
+
+class Pair {
+ public:
+ typedef EventChannel<TestEventTraits> Channel;
+ explicit Pair(const string& name) : name_(name), a_(0), b_(0) {
+ TestEvent shutdown = { this, TestEvent::PAIR_BEING_DELETED, 0 };
+ event_channel_ = new Channel(shutdown);
+ }
+ ~Pair() {
+ delete event_channel_;
+ }
+ void set_a(int n) {
+ TestEvent event = { this, TestEvent::A_CHANGED, a_ };
+ a_ = n;
+ event_channel_->NotifyListeners(event);
+ }
+ void set_b(int n) {
+ TestEvent event = { this, TestEvent::B_CHANGED, b_ };
+ b_ = n;
+ event_channel_->NotifyListeners(event);
+ }
+ int a() const { return a_; }
+ int b() const { return b_; }
+ const string& name() { return name_; }
+ Channel* event_channel() const { return event_channel_; }
+
+ protected:
+ const string name_;
+ int a_;
+ int b_;
+ Channel* event_channel_;
+};
+
+class EventLogger {
+ public:
+ explicit EventLogger(ostream& out) : out_(out) { }
+ ~EventLogger() {
+ for (Hookups::iterator i = hookups_.begin(); i != hookups_.end(); ++i)
+ delete *i;
+ }
+
+ void Hookup(const string name, Pair::Channel* channel) {
+ hookups_.push_back(NewEventListenerHookup(channel, this,
+ &EventLogger::HandlePairEvent,
+ name));
+ }
+
+ void HandlePairEvent(const string& name, const TestEvent& event) {
+ const char* what_changed = NULL;
+ int new_value = 0;
+ Hookups::iterator dead;
+ switch (event.what_happened) {
+ case TestEvent::A_CHANGED:
+ what_changed = "A";
+ new_value = event.source->a();
+ break;
+ case TestEvent::B_CHANGED:
+ what_changed = "B";
+ new_value = event.source->b();
+ break;
+ case TestEvent::PAIR_BEING_DELETED:
+ out_ << name << " heard " << event.source->name() << " being deleted."
+ << endl;
+ return;
+ default:
+ FAIL() << "Bad event.what_happened: " << event.what_happened;
+ break;
+ }
+ out_ << name << " heard " << event.source->name() << "'s " << what_changed
+ << " change from "
+ << event.old_value << " to " << new_value << endl;
+ }
+
+ typedef vector<EventListenerHookup*> Hookups;
+ Hookups hookups_;
+ ostream& out_;
+};
+
+const char golden_result[] = "Larry heard Sally's B change from 0 to 2\n"
+"Larry heard Sally's A change from 1 to 3\n"
+"Lewis heard Sam's B change from 0 to 5\n"
+"Larry heard Sally's A change from 3 to 6\n"
+"Larry heard Sally being deleted.\n";
+
+TEST(EventSys, Basic) {
+ Pair sally("Sally"), sam("Sam");
+ sally.set_a(1);
+ stringstream log;
+ EventLogger logger(log);
+ logger.Hookup("Larry", sally.event_channel());
+ sally.set_b(2);
+ sally.set_a(3);
+ sam.set_a(4);
+ logger.Hookup("Lewis", sam.event_channel());
+ sam.set_b(5);
+ sally.set_a(6);
+ // Test that disconnect within callback doesn't deadlock.
+ TestEvent event = {&sally, TestEvent::PAIR_BEING_DELETED, 0 };
+ sally.event_channel()->NotifyListeners(event);
+ sally.set_a(7);
+ ASSERT_EQ(log.str(), golden_result);
+}
+
+
+// This goes pretty far beyond the normal use pattern, so don't use
+// ThreadTester as an example of what to do.
+class ThreadTester : public EventListener<TestEvent>,
+ public PlatformThread::Delegate {
+ public:
+ explicit ThreadTester(Pair* pair)
+ : pair_(pair), remove_event_(&remove_event_mutex_),
+ remove_event_bool_(false), completed_(false) {
+ pair_->event_channel()->AddListener(this);
+ }
+ ~ThreadTester() {
+ pair_->event_channel()->RemoveListener(this);
+ for (size_t i = 0; i < threads_.size(); i++) {
+ PlatformThread::Join(threads_[i].thread);
+ }
+ }
+
+ struct ThreadInfo {
+ PlatformThreadHandle thread;
+ };
+
+ struct ThreadArgs {
+ ConditionVariable* thread_running_cond;
+ Lock* thread_running_mutex;
+ bool thread_running;
+ };
+
+ void Go() {
+ Lock thread_running_mutex;
+ ConditionVariable thread_running_cond(&thread_running_mutex);
+ ThreadArgs args;
+ ThreadInfo info;
+ args.thread_running_cond = &(thread_running_cond);
+ args.thread_running_mutex = &(thread_running_mutex);
+ args.thread_running = false;
+ args_ = args;
+ ASSERT_TRUE(PlatformThread::Create(0, this, &info.thread));
+ thread_running_mutex.Acquire();
+ while ((args_.thread_running) == false) {
+ thread_running_cond.Wait();
+ }
+ thread_running_mutex.Release();
+ threads_.push_back(info);
+ }
+
+ // PlatformThread::Delegate methods.
+ virtual void ThreadMain() {
+ // Make sure each thread gets a current MessageLoop in TLS.
+ // This test should use chrome threads for testing, but I'll leave it like
+ // this for the moment since it requires a big chunk of rewriting and I
+ // want the test passing while I checkpoint my CL. Technically speaking,
+ // there should be no functional difference.
+ MessageLoop message_loop;
+ args_.thread_running_mutex->Acquire();
+ args_.thread_running = true;
+ args_.thread_running_cond->Signal();
+ args_.thread_running_mutex->Release();
+
+ remove_event_mutex_.Acquire();
+ while (remove_event_bool_ == false) {
+ remove_event_.Wait();
+ }
+ remove_event_mutex_.Release();
+
+ // Normally, you'd just delete the hookup. This is very bad style, but
+ // necessary for the test.
+ pair_->event_channel()->RemoveListener(this);
+
+ completed_mutex_.Acquire();
+ completed_ = true;
+ completed_mutex_.Release();
+ }
+
+ void HandleEvent(const TestEvent& event) {
+ remove_event_mutex_.Acquire();
+ remove_event_bool_ = true;
+ remove_event_.Broadcast();
+ remove_event_mutex_.Release();
+
+ PlatformThread::YieldCurrentThread();
+
+ completed_mutex_.Acquire();
+ if (completed_)
+ FAIL() << "A test thread exited too early.";
+ completed_mutex_.Release();
+ }
+
+ Pair* pair_;
+ ConditionVariable remove_event_;
+ Lock remove_event_mutex_;
+ bool remove_event_bool_;
+ Lock completed_mutex_;
+ bool completed_;
+ vector<ThreadInfo> threads_;
+ ThreadArgs args_;
+};
+
+TEST(EventSys, Multithreaded) {
+ Pair sally("Sally");
+ ThreadTester a(&sally);
+ for (int i = 0; i < 3; ++i)
+ a.Go();
+ sally.set_b(99);
+}
+
+class HookupDeleter {
+ public:
+ void HandleEvent(const TestEvent& event) {
+ delete hookup_;
+ hookup_ = NULL;
+ }
+ EventListenerHookup* hookup_;
+};
+
+TEST(EventSys, InHandlerDeletion) {
+ Pair sally("Sally");
+ HookupDeleter deleter;
+ deleter.hookup_ = NewEventListenerHookup(sally.event_channel(),
+ &deleter,
+ &HookupDeleter::HandleEvent);
+ sally.set_a(1);
+ ASSERT_TRUE(NULL == deleter.hookup_);
+}
+
+} // namespace
diff --git a/chrome/common/desktop_notifications/active_notification_tracker.cc b/chrome/common/desktop_notifications/active_notification_tracker.cc
new file mode 100644
index 0000000..9822711
--- /dev/null
+++ b/chrome/common/desktop_notifications/active_notification_tracker.cc
@@ -0,0 +1,70 @@
+// Copyright (c) 2009 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/common/desktop_notifications/active_notification_tracker.h"
+
+#include "base/message_loop.h"
+#include "base/scoped_ptr.h"
+#include "third_party/WebKit/WebKit/chromium/public/WebNotification.h"
+#include "third_party/WebKit/WebKit/chromium/public/WebNotificationPermissionCallback.h"
+
+using WebKit::WebNotification;
+using WebKit::WebNotificationPermissionCallback;
+
+bool ActiveNotificationTracker::GetId(
+ const WebNotification& notification, int& id) {
+ ReverseTable::iterator iter = reverse_notification_table_.find(notification);
+ if (iter == reverse_notification_table_.end())
+ return false;
+ id = iter->second;
+ return true;
+}
+
+bool ActiveNotificationTracker::GetNotification(
+ int id, WebNotification* notification) {
+ WebNotification* lookup = notification_table_.Lookup(id);
+ if (!lookup)
+ return false;
+
+ *notification = *lookup;
+ return true;
+}
+
+int ActiveNotificationTracker::RegisterNotification(
+ const WebKit::WebNotification& proxy) {
+ WebNotification* notification = new WebNotification(proxy);
+ int id = notification_table_.Add(notification);
+ reverse_notification_table_[proxy] = id;
+ return id;
+}
+
+void ActiveNotificationTracker::UnregisterNotification(int id) {
+ // We want to free the notification after removing it from the table.
+ scoped_ptr<WebNotification> notification(notification_table_.Lookup(id));
+ notification_table_.Remove(id);
+ DCHECK(notification.get());
+ if (notification.get())
+ reverse_notification_table_.erase(*notification);
+}
+
+void ActiveNotificationTracker::Clear() {
+ while (!reverse_notification_table_.empty()) {
+ ReverseTable::iterator iter = reverse_notification_table_.begin();
+ UnregisterNotification((*iter).second);
+ }
+}
+
+WebNotificationPermissionCallback* ActiveNotificationTracker::GetCallback(
+ int id) {
+ return callback_table_.Lookup(id);
+}
+
+int ActiveNotificationTracker::RegisterPermissionRequest(
+ WebNotificationPermissionCallback* callback) {
+ return callback_table_.Add(callback);
+}
+
+void ActiveNotificationTracker::OnPermissionRequestComplete(int id) {
+ callback_table_.Remove(id);
+}
diff --git a/chrome/common/desktop_notifications/active_notification_tracker.h b/chrome/common/desktop_notifications/active_notification_tracker.h
new file mode 100644
index 0000000..1676f32
--- /dev/null
+++ b/chrome/common/desktop_notifications/active_notification_tracker.h
@@ -0,0 +1,52 @@
+// Copyright (c) 2009 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_COMMON_DESKTOP_NOTIFICATIONS_ACTIVE_NOTIFICATION_TRACKER_H_
+#define CHROME_COMMON_DESKTOP_NOTIFICATIONS_ACTIVE_NOTIFICATION_TRACKER_H_
+
+#include <map>
+
+#include "base/basictypes.h"
+#include "base/id_map.h"
+#include "base/hash_tables.h"
+#include "third_party/WebKit/WebKit/chromium/public/WebNotification.h"
+
+namespace WebKit {
+class WebNotificationPermissionCallback;
+}
+
+// This class manages the set of active Notification objects in either
+// a render or worker process. This class should be accessed only on
+// the main thread.
+class ActiveNotificationTracker {
+ public:
+ ActiveNotificationTracker() {}
+
+ // Methods for tracking active notification objects.
+ int RegisterNotification(const WebKit::WebNotification& notification);
+ void UnregisterNotification(int id);
+ bool GetId(const WebKit::WebNotification& notification, int& id);
+ bool GetNotification(int id, WebKit::WebNotification* notification);
+
+ // Methods for tracking active permission requests.
+ int RegisterPermissionRequest(
+ WebKit::WebNotificationPermissionCallback* callback);
+ void OnPermissionRequestComplete(int id);
+ WebKit::WebNotificationPermissionCallback* GetCallback(int id);
+
+ // Clears out all active notifications. Useful on page navigation.
+ void Clear();
+
+ private:
+ typedef std::map<WebKit::WebNotification, int> ReverseTable;
+
+ // Tracking maps for active notifications and permission requests.
+ IDMap<WebKit::WebNotification> notification_table_;
+ ReverseTable reverse_notification_table_;
+ IDMap<WebKit::WebNotificationPermissionCallback> callback_table_;
+
+ DISALLOW_COPY_AND_ASSIGN(ActiveNotificationTracker);
+};
+
+#endif // CHROME_COMMON_DESKTOP_NOTIFICATIONS_ACTIVE_NOTIFICATION_TRACKER_H_
diff --git a/chrome/common/desktop_notifications/active_notification_tracker_unittest.cc b/chrome/common/desktop_notifications/active_notification_tracker_unittest.cc
new file mode 100644
index 0000000..b741d35
--- /dev/null
+++ b/chrome/common/desktop_notifications/active_notification_tracker_unittest.cc
@@ -0,0 +1,25 @@
+// Copyright (c) 2010 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/common/desktop_notifications/active_notification_tracker.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+TEST(ActiveNotificationTrackerTest, TestLookupAndClear) {
+ ActiveNotificationTracker tracker;
+
+ WebKit::WebNotification notification1;
+ int id1 = tracker.RegisterNotification(notification1);
+
+ WebKit::WebNotification notification2;
+ int id2 = tracker.RegisterNotification(notification2);
+
+ WebKit::WebNotification result;
+ tracker.GetNotification(id1, &result);
+ EXPECT_TRUE(result == notification1);
+
+ tracker.GetNotification(id2, &result);
+ EXPECT_TRUE(result == notification2);
+
+ tracker.Clear();
+}
diff --git a/chrome/common/devtools_messages.h b/chrome/common/devtools_messages.h
new file mode 100644
index 0000000..a46d72b
--- /dev/null
+++ b/chrome/common/devtools_messages.h
@@ -0,0 +1,38 @@
+// Copyright (c) 2009 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_COMMON_DEVTOOLS_MESSAGES_H_
+#define CHROME_COMMON_DEVTOOLS_MESSAGES_H_
+
+#include "ipc/ipc_message_utils.h"
+#include "webkit/glue/devtools_message_data.h"
+
+namespace IPC {
+
+// Traits for DevToolsMessageData structure to pack/unpack.
+template <>
+struct ParamTraits<DevToolsMessageData> {
+ typedef DevToolsMessageData param_type;
+ static void Write(Message* m, const param_type& p) {
+ WriteParam(m, p.class_name);
+ WriteParam(m, p.method_name);
+ WriteParam(m, p.arguments);
+ }
+ static bool Read(const Message* m, void** iter, param_type* p) {
+ return
+ ReadParam(m, iter, &p->class_name) &&
+ ReadParam(m, iter, &p->method_name) &&
+ ReadParam(m, iter, &p->arguments);
+ }
+ static void Log(const param_type& p, std::wstring* l) {
+ l->append(L"<DevToolsMessageData>");
+ }
+};
+
+} // namespace IPC
+
+#define MESSAGES_INTERNAL_FILE "chrome/common/devtools_messages_internal.h"
+#include "ipc/ipc_message_macros.h"
+
+#endif // CHROME_COMMON_DEVTOOLS_MESSAGES_H_
diff --git a/chrome/common/devtools_messages_internal.h b/chrome/common/devtools_messages_internal.h
new file mode 100644
index 0000000..dcc8eee
--- /dev/null
+++ b/chrome/common/devtools_messages_internal.h
@@ -0,0 +1,96 @@
+// Copyright (c) 2009 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.
+
+// This header is meant to be included in multiple passes, hence no traditional
+// header guard.
+// See ipc_message_macros.h for explanation of the macros and passes.
+
+// Developer tools consist of the following parts:
+//
+// DevToolsAgent lives in the renderer of an inspected page and provides access
+// to the pages resources, DOM, v8 etc. by means of IPC messages.
+//
+// DevToolsClient is a thin delegate that lives in the tools front-end
+// renderer and converts IPC messages to frontend method calls and allows the
+// frontend to send messages to the DevToolsAgent.
+//
+// All the messages are routed through browser process. There is a
+// DevToolsManager living in the browser process that is responsible for
+// routing logistics. It is also capable of sending direct messages to the
+// agent rather than forwarding messages between agents and clients only.
+//
+// Chain of communication between the components may be described by the
+// following diagram:
+// ----------------------------
+// | (tools frontend |
+// | renderer process) |
+// | | --------------------
+// |tools <--> DevToolsClient+<-- IPC -->+ (browser process) |
+// |frontend | | |
+// ---------------------------- ---------+----------
+// ^
+// |
+// IPC
+// |
+// v
+// --------------------------+--------
+// | inspected page <--> DevToolsAgent |
+// | |
+// | (inspected page renderer process) |
+// -----------------------------------
+//
+// This file describes developer tools message types.
+
+#include "ipc/ipc_message_macros.h"
+#include "webkit/glue/devtools_message_data.h"
+
+// These are messages sent from DevToolsAgent to DevToolsClient through the
+// browser.
+IPC_BEGIN_MESSAGES(DevToolsClient)
+
+ // Sends glue-level Rpc message to the client.
+ IPC_MESSAGE_CONTROL1(DevToolsClientMsg_RpcMessage,
+ DevToolsMessageData /* message data */)
+
+IPC_END_MESSAGES(DevToolsClient)
+
+
+//-----------------------------------------------------------------------------
+// These are messages sent from DevToolsClient to DevToolsAgent through the
+// browser.
+IPC_BEGIN_MESSAGES(DevToolsAgent)
+
+ // Tells agent that there is a client host connected to it.
+ IPC_MESSAGE_CONTROL1(DevToolsAgentMsg_Attach,
+ std::vector<std::string> /* runtime_features */)
+
+ // Tells agent that there is no longer a client host connected to it.
+ IPC_MESSAGE_CONTROL0(DevToolsAgentMsg_Detach)
+
+ // Sends glue-level Rpc message to the agent.
+ IPC_MESSAGE_CONTROL1(DevToolsAgentMsg_RpcMessage,
+ DevToolsMessageData /* message data */)
+
+ // Send debugger command to the debugger agent. Debugger commands should
+ // be handled on IO thread(while all other devtools messages are handled in
+ // the render thread) to allow executing the commands when v8 is on a
+ // breakpoint.
+ IPC_MESSAGE_CONTROL1(DevToolsAgentMsg_DebuggerCommand,
+ std::string /* command */)
+
+ // This command is sent to debugger when user wants to pause script execution
+ // immediately. This message should be processed on the IO thread so that it
+ // can have effect even if the Renderer thread is busy with JavaScript
+ // execution.
+ IPC_MESSAGE_CONTROL0(DevToolsAgentMsg_DebuggerPauseScript)
+
+ // Inspect element with the given coordinates.
+ IPC_MESSAGE_CONTROL2(DevToolsAgentMsg_InspectElement,
+ int /* x */,
+ int /* y */)
+
+ // Enables/disables the apu agent.
+ IPC_MESSAGE_CONTROL1(DevToolsAgentMsg_SetApuAgentEnabled, bool /* enabled */)
+
+IPC_END_MESSAGES(DevToolsAgent)
diff --git a/chrome/common/dom_storage_common.h b/chrome/common/dom_storage_common.h
new file mode 100644
index 0000000..96fc508
--- /dev/null
+++ b/chrome/common/dom_storage_common.h
@@ -0,0 +1,16 @@
+// Copyright (c) 2009 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_COMMON_DOM_STORAGE_COMMON_H_
+#define CHROME_COMMON_DOM_STORAGE_COMMON_H_
+
+const int64 kLocalStorageNamespaceId = 0;
+const int64 kInvalidSessionStorageNamespaceId = kLocalStorageNamespaceId;
+
+enum DOMStorageType {
+ DOM_STORAGE_LOCAL = 0,
+ DOM_STORAGE_SESSION
+};
+
+#endif // CHROME_COMMON_DOM_STORAGE_COMMON_H_
diff --git a/chrome/common/edit_command.h b/chrome/common/edit_command.h
new file mode 100644
index 0000000..4fc373e
--- /dev/null
+++ b/chrome/common/edit_command.h
@@ -0,0 +1,24 @@
+// Copyright (c) 2009 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_COMMON_EDIT_COMMAND_H_
+#define CHROME_COMMON_EDIT_COMMAND_H_
+
+#include <string>
+#include <vector>
+
+// Types related to sending edit commands to the renderer.
+struct EditCommand {
+ EditCommand() { }
+ EditCommand(const std::string& n, const std::string& v)
+ : name(n), value(v) {
+ }
+
+ std::string name;
+ std::string value;
+};
+
+typedef std::vector<EditCommand> EditCommands;
+
+#endif // CHROME_COMMON_EDIT_COMMAND_H_
diff --git a/chrome/common/env_vars.cc b/chrome/common/env_vars.cc
new file mode 100644
index 0000000..dc2648c
--- /dev/null
+++ b/chrome/common/env_vars.cc
@@ -0,0 +1,40 @@
+// Copyright (c) 2010 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/common/env_vars.h"
+
+namespace env_vars {
+
+// We call running in unattended mode (for automated testing) "headless".
+// This mode can be enabled using this variable or by the kNoErrorDialogs
+// switch.
+const char kHeadless[] = "CHROME_HEADLESS";
+
+// The name of the log file.
+const char kLogFileName[] = "CHROME_LOG_FILE";
+
+// If this environment variable is set, Chrome on Windows will log
+// to Event Tracing for Windows.
+const char kEtwLogging[] = "CHROME_ETW_LOGGING";
+
+// CHROME_CRASHED exists if a previous instance of chrome has crashed. This
+// triggers the 'restart chrome' dialog. CHROME_RESTART contains the strings
+// that are needed to show the dialog.
+const char kShowRestart[] = "CHROME_CRASHED";
+const char kRestartInfo[] = "CHROME_RESTART";
+
+// The strings RIGHT_TO_LEFT and LEFT_TO_RIGHT indicate the locale direction.
+// For example, for Hebrew and Arabic locales, we use RIGHT_TO_LEFT so that the
+// dialog is displayed using the right orientation.
+const char kRtlLocale[] = "RIGHT_TO_LEFT";
+const char kLtrLocale[] = "LEFT_TO_RIGHT";
+
+// If the out-of-process breakpad could not be installed, we set this variable
+// according to the process.
+const char kNoOOBreakpad[] = "NO_OO_BREAKPAD";
+
+// Number of times to run a given startup_tests unit test.
+const char kStartupTestsNumCycles[] = "STARTUP_TESTS_NUMCYCLES";
+
+} // namespace env_vars
diff --git a/chrome/common/env_vars.h b/chrome/common/env_vars.h
new file mode 100644
index 0000000..1c5bc5d
--- /dev/null
+++ b/chrome/common/env_vars.h
@@ -0,0 +1,24 @@
+// Copyright (c) 2010 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.
+
+// Defines all the environment variables used by Chrome.
+
+#ifndef CHROME_COMMON_ENV_VARS_H__
+#define CHROME_COMMON_ENV_VARS_H__
+
+namespace env_vars {
+
+extern const char kHeadless[];
+extern const char kLogFileName[];
+extern const char kEtwLogging[];
+extern const char kShowRestart[];
+extern const char kRestartInfo[];
+extern const char kRtlLocale[];
+extern const char kLtrLocale[];
+extern const char kNoOOBreakpad[];
+extern const char kStartupTestsNumCycles[];
+
+} // namespace env_vars
+
+#endif // CHROME_COMMON_ENV_VARS_H__
diff --git a/chrome/common/extra_defines.vsprops b/chrome/common/extra_defines.vsprops
new file mode 100644
index 0000000..963972f
--- /dev/null
+++ b/chrome/common/extra_defines.vsprops
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="Windows-1252"?>
+<VisualStudioPropertySheet
+ ProjectType="Visual C++"
+ Version="8.00"
+ Name="extra"
+ >
+</VisualStudioPropertySheet>
diff --git a/chrome/common/font_descriptor_mac.h b/chrome/common/font_descriptor_mac.h
new file mode 100644
index 0000000..25ae9db
--- /dev/null
+++ b/chrome/common/font_descriptor_mac.h
@@ -0,0 +1,32 @@
+// Copyright (c) 2010 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_COMMON_FONT_DESCRIPTOR_MAC_H_
+#define CHROME_COMMON_FONT_DESCRIPTOR_MAC_H_
+
+#include "base/string16.h"
+
+#ifdef __OBJC__
+@class NSFont;
+#else
+class NSFont;
+#endif
+
+// Container to allow serializing an NSFont over IPC.
+struct FontDescriptor {
+ explicit FontDescriptor(NSFont* font);
+
+ FontDescriptor() : font_point_size(0) {}
+
+ // Return an autoreleased NSFont corresponding to the font description.
+ NSFont* nsFont() const;
+
+ // Name of the font.
+ string16 font_name;
+
+ // Size in points.
+ float font_point_size;
+};
+
+#endif // CHROME_COMMON_FONT_DESCRIPTOR_MAC_H_
diff --git a/chrome/common/font_descriptor_mac.mm b/chrome/common/font_descriptor_mac.mm
new file mode 100644
index 0000000..485c215
--- /dev/null
+++ b/chrome/common/font_descriptor_mac.mm
@@ -0,0 +1,20 @@
+// Copyright (c) 2010 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/common/font_descriptor_mac.h"
+
+#include <Cocoa/Cocoa.h>
+
+#include "base/sys_string_conversions.h"
+
+FontDescriptor::FontDescriptor(NSFont* font) {
+ font_name = base::SysNSStringToUTF16([font fontName]);
+ font_point_size = [font pointSize];
+}
+
+NSFont* FontDescriptor::nsFont() const {
+ NSString* font_name_ns = base::SysUTF16ToNSString(font_name);
+ NSFont* font = [NSFont fontWithName:font_name_ns size:font_point_size];
+ return font;
+}
diff --git a/chrome/common/font_descriptor_mac_unittest.mm b/chrome/common/font_descriptor_mac_unittest.mm
new file mode 100644
index 0000000..442e8e2
--- /dev/null
+++ b/chrome/common/font_descriptor_mac_unittest.mm
@@ -0,0 +1,91 @@
+// Copyright (c) 2010 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/common/font_descriptor_mac.h"
+
+#include <Cocoa/Cocoa.h>
+
+#include "base/logging.h"
+#include "testing/gtest/include/gtest/gtest.h"
+#include "testing/platform_test.h"
+
+namespace {
+
+class FontSerializationTest : public PlatformTest {};
+
+
+// Compare 2 fonts, make sure they point at the same font definition and have
+// the same style. Only Bold & Italic style attributes are tested since those
+// are the only ones we care about at the moment.
+bool CompareFonts(NSFont* font1, NSFont* font2) {
+ ATSFontRef id1 = CTFontGetPlatformFont(reinterpret_cast<CTFontRef>(font1), 0);
+ ATSFontRef id2 = CTFontGetPlatformFont(reinterpret_cast<CTFontRef>(font2), 0);
+
+ if (id1 != id2) {
+ LOG(ERROR) << "ATSFontRefs for "
+ << [[font1 fontName] UTF8String]
+ << " and "
+ << [[font2 fontName] UTF8String]
+ << " are different";
+ return false;
+ }
+
+ CGFloat size1 = [font1 pointSize];
+ CGFloat size2 = [font2 pointSize];
+ if (size1 != size2) {
+ LOG(ERROR) << "font sizes for "
+ << [[font1 fontName] UTF8String] << " (" << size1 << ")"
+ << "and"
+ << [[font2 fontName] UTF8String] << " (" << size2 << ")"
+ << " are different";
+ return false;
+ }
+
+ NSFontTraitMask traits1 = [[NSFontManager sharedFontManager]
+ traitsOfFont:font1];
+ NSFontTraitMask traits2 = [[NSFontManager sharedFontManager]
+ traitsOfFont:font2];
+
+ bool is_bold1 = traits1 & NSBoldFontMask;
+ bool is_bold2 = traits2 & NSBoldFontMask;
+ bool is_italic1 = traits1 & NSItalicFontMask;
+ bool is_italic2 = traits2 & NSItalicFontMask;
+
+ if (is_bold1 != is_bold2 || is_italic1 != is_italic2) {
+ LOG(ERROR) << "Style information for "
+ << [[font1 fontName] UTF8String]
+ << " and "
+ << [[font2 fontName] UTF8String]
+ << " are different";
+ return false;
+ }
+
+ return true;
+}
+
+// Verify that serialization and deserialization of fonts with various styles
+// is performed correctly by FontDescriptor.
+TEST_F(FontSerializationTest, StyledFonts) {
+ NSFont* plain_font = [NSFont systemFontOfSize:12.0];
+ ASSERT_TRUE(plain_font != nil);
+ FontDescriptor desc_plain(plain_font);
+ EXPECT_TRUE(CompareFonts(plain_font, desc_plain.nsFont()));
+
+ NSFont* bold_font = [NSFont boldSystemFontOfSize:30.0];
+ ASSERT_TRUE(bold_font != nil);
+ FontDescriptor desc_bold(bold_font);
+ EXPECT_TRUE(CompareFonts(bold_font, desc_bold.nsFont()));
+
+ NSFont* italic_bold_font =
+ [[NSFontManager sharedFontManager]
+ fontWithFamily:@"Courier"
+ traits:(NSBoldFontMask | NSItalicFontMask)
+ weight:5
+ size:18.0];
+ ASSERT_TRUE(italic_bold_font != nil);
+ FontDescriptor desc_italic_bold(italic_bold_font);
+ EXPECT_TRUE(CompareFonts(italic_bold_font, desc_italic_bold.nsFont()));
+}
+
+} // namsepace
diff --git a/chrome/common/font_loader_mac.h b/chrome/common/font_loader_mac.h
new file mode 100644
index 0000000..2ec42bc
--- /dev/null
+++ b/chrome/common/font_loader_mac.h
@@ -0,0 +1,55 @@
+// Copyright (c) 2010 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_COMMON_FONT_LOADER_MAC_H_
+#define CHROME_COMMON_FONT_LOADER_MAC_H_
+
+#include <ApplicationServices/ApplicationServices.h>
+
+#include "base/shared_memory.h"
+#include "base/string16.h"
+
+#ifdef __OBJC__
+@class NSFont;
+#else
+class NSFont;
+#endif
+
+// Provides functionality to transmit fonts over IPC.
+//
+// Note about font formats: .dfont (datafork suitcase) fonts are currently not
+// supported by this code since ATSFontActivateFromMemory() can't handle them
+// directly.
+
+class FontLoader {
+ public:
+ // Load a font specified by |font_to_encode| into a shared memory buffer
+ // suitable for sending over IPC.
+ //
+ // On return:
+ // returns true on success, false on failure.
+ // |font_data| - shared memory buffer containing the raw data for the font
+ // file.
+ // |font_data_size| - size of data contained in |font_data|.
+ static bool LoadFontIntoBuffer(NSFont* font_to_encode,
+ base::SharedMemory* font_data,
+ uint32* font_data_size);
+
+ // Given a shared memory buffer containing the raw data for a font file, load
+ // the font and return a container ref.
+ //
+ // |data| - A shared memory handle pointing to the raw data from a font file.
+ // |data_size| - Size of |data|.
+ //
+ // On return:
+ // returns true on success, false on failure.
+ // |font_container| - A font container corresponding to the designated font.
+ // The caller is responsible for releasing this value via ATSFontDeactivate()
+ // when done
+ static bool ATSFontContainerFromBuffer(base::SharedMemoryHandle font_data,
+ uint32 font_data_size,
+ ATSFontContainerRef* font_container);
+};
+
+#endif // CHROME_COMMON_FONT_LOADER_MAC_H_
diff --git a/chrome/common/font_loader_mac.mm b/chrome/common/font_loader_mac.mm
new file mode 100644
index 0000000..849ae87
--- /dev/null
+++ b/chrome/common/font_loader_mac.mm
@@ -0,0 +1,116 @@
+// Copyright (c) 2010 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/common/font_loader_mac.h"
+
+#import <Cocoa/Cocoa.h>
+
+#include "base/basictypes.h"
+#include "base/file_path.h"
+#include "base/file_util.h"
+#include "base/logging.h"
+#include "base/mac_util.h"
+#include "base/scoped_cftyperef.h"
+#include "base/sys_string_conversions.h"
+
+// static
+bool FontLoader::LoadFontIntoBuffer(NSFont* font_to_encode,
+ base::SharedMemory* font_data,
+ uint32* font_data_size) {
+ CHECK(font_data && font_data_size);
+ *font_data_size = 0;
+
+ // Used only for logging.
+ std::string font_name([[font_to_encode fontName] UTF8String]);
+
+ // Load appropriate NSFont.
+ if (!font_to_encode) {
+ LOG(ERROR) << "Failed to load font " << font_name;
+ return false;
+ }
+
+ // NSFont -> ATSFontRef.
+ ATSFontRef ats_font =
+ CTFontGetPlatformFont(reinterpret_cast<CTFontRef>(font_to_encode), NULL);
+ if (!ats_font) {
+ LOG(ERROR) << "Conversion to ATSFontRef failed for " << font_name;
+ return false;
+ }
+
+ // ATSFontRef -> File path.
+ // Warning: Calling this function on a font activated from memory will result
+ // in failure with a -50 - paramErr. This may occur if
+ // CreateCGFontFromBuffer() is called in the same process as this function
+ // e.g. when writing a unit test that exercises these two functions together.
+ // If said unit test were to load a system font and activate it from memory
+ // it becomes impossible for the system to the find the original file ref
+ // since the font now lives in memory as far as it's concerned.
+ FSRef font_fsref;
+ if (ATSFontGetFileReference(ats_font, &font_fsref) != noErr) {
+ LOG(ERROR) << "Failed to find font file for " << font_name;
+ return false;
+ }
+ FilePath font_path = FilePath(mac_util::PathFromFSRef(font_fsref));
+
+ // Load file into shared memory buffer.
+ int64 font_file_size_64 = -1;
+ if (!file_util::GetFileSize(font_path, &font_file_size_64)) {
+ LOG(ERROR) << "Couldn't get font file size for " << font_path.value();
+ return false;
+ }
+
+ if (font_file_size_64 <= 0 || font_file_size_64 >= kint32max) {
+ LOG(ERROR) << "Bad size for font file " << font_path.value();
+ return false;
+ }
+
+ int32 font_file_size_32 = static_cast<int32>(font_file_size_64);
+ if (!font_data->Create(L"", false, false, font_file_size_32)) {
+ LOG(ERROR) << "Failed to create shmem area for " << font_name;
+ return false;
+ }
+
+ if (!font_data->Map(font_file_size_32)) {
+ LOG(ERROR) << "Failed to map shmem area for " << font_name;
+ return false;
+ }
+
+ int32 amt_read = file_util::ReadFile(font_path,
+ reinterpret_cast<char*>(font_data->memory()),
+ font_file_size_32);
+ if (amt_read != font_file_size_32) {
+ LOG(ERROR) << "Failed to read font data for " << font_path.value();
+ return false;
+ }
+
+ *font_data_size = font_file_size_32;
+ return true;
+}
+
+// static
+bool FontLoader::ATSFontContainerFromBuffer(base::SharedMemoryHandle font_data,
+ uint32 font_data_size,
+ ATSFontContainerRef* font_container)
+{
+ CHECK(font_container);
+
+ using base::SharedMemory;
+ DCHECK(SharedMemory::IsHandleValid(font_data));
+ DCHECK_GT(font_data_size, 0U);
+
+ SharedMemory shm(font_data, true);
+ if (!shm.Map(font_data_size))
+ return false;
+
+ // A value of 3 means the font is private and can't be seen by anyone else.
+ // This is the value used by WebKit when activating remote fonts.
+ const ATSFontContext kFontContextPrivate = 3;
+ OSStatus err = ATSFontActivateFromMemory(shm.memory(), font_data_size,
+ kFontContextPrivate, kATSFontFormatUnspecified, NULL,
+ kATSOptionFlagsDefault, font_container);
+ if (err != noErr || !font_container)
+ return false;
+
+ return true;
+}
diff --git a/chrome/common/gears_api.h b/chrome/common/gears_api.h
new file mode 100644
index 0000000..9aba014
--- /dev/null
+++ b/chrome/common/gears_api.h
@@ -0,0 +1,97 @@
+// Copyright (c) 2006-2008 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.
+//
+// This header specifies extensions to the Chrome Plugin API to support Gears.
+
+#ifndef CHROME_COMMON_GEARS_API_H__
+#define CHROME_COMMON_GEARS_API_H__
+
+#include "chrome/common/chrome_plugin_api.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+// CommandIDs used when Chrome calls into Gears using CPP_HandleCommand.
+// Note: do not change the enum values. We want to preserve backwards
+// compatibility.
+typedef enum {
+ // Ask gears to show its settings dialog. Typical usage is for the plugin
+ // to display it using a call to CPB_ShowHtmlDialog. No command_data is
+ // provided.
+ GEARSPLUGINCOMMAND_SHOW_SETTINGS = 0,
+
+ // Ask gears to create a shortcut to a web page. command_data points
+ // to a GearsShortcutData struct.
+ GEARSPLUGINCOMMAND_CREATE_SHORTCUT = 1,
+
+ // Query gears for the list of installed shortcuts. command_data points
+ // to a GearsShortcutList struct.
+ GEARSPLUGINCOMMAND_GET_SHORTCUT_LIST = 2,
+} GearsPluginCommand;
+
+// CommandIDs used when Gears calls into Chrome using CPB_HandleCommand.
+// Note: do not change the enum values. We want to preserve backwards
+// compatibility.
+typedef enum {
+ // Tell chrome that the GEARSPLUGINCOMMAND_CREATE_SHORTCUT command is done,
+ // and the user has closed the dialog. command_data points to the same
+ // GearsShortcutData struct that was passed to the plugin command.
+ GEARSBROWSERCOMMAND_CREATE_SHORTCUT_DONE = 1,
+
+ // Notifies the browser of changes to the gears shortcuts database.
+ // command_data is null.
+ GEARSBROWSERCOMMAND_NOTIFY_SHORTCUTS_CHANGED = 3,
+} GearsBrowserCommand;
+
+// Note: currently only 16x16, 32x32, 48x48, and 128x128 icons are supported.
+typedef struct _GearsShortcutIcon {
+ const char* size; // unused
+ const char* url; // the URL of the icon, which should be a PNG image
+ int width; // width of the icon
+ int height; // height of the icon
+} GearsShortcutIcon;
+
+// Command data for GEARSPLUGINCOMMAND_CREATE_SHORTCUT.
+typedef struct _GearsShortcutData {
+ const char* name; // the shortcut's name (also used as the filename)
+ const char* url; // the URL that the shortcut should launch
+ const char* description; // an optional description
+ GearsShortcutIcon icons[4]; // list of icons to use for this shortcut
+} GearsShortcutData;
+
+// Command data for GEARSPLUGINCOMMAND_CREATE_SHORTCUT used in 0.6 and later.
+// This struct is backwards compatible with the first version.
+// http://b/viewIssue?id=1331408 - Chrome sanitizes 'name' for compatibility
+// with older versions of Gears that expect this. 'orig_name' is unsanitized,
+// which allows Gears to do its own validation.
+typedef struct _GearsShortcutData2 {
+ const char* name; // unused - for back compat with above struct
+ const char* url; // the URL that the shortcut should launch
+ const char* description; // an optional description
+ GearsShortcutIcon icons[4]; // list of icons to use for this shortcut
+ const char* orig_name; // the shortcut's unmodified filename (added in 0.6)
+} GearsShortcutData2;
+
+// Command data for GEARSPLUGINCOMMAND_GET_SHORTCUT_LIST.
+typedef struct _GearsShortcutList {
+ // Note: these are output params, set by Gears. There are no input params.
+ // Memory for these shortcuts, including the strings they hold, should be
+ // freed by the browser using CPB_Free.
+ GearsShortcutData* shortcuts; // array of installed shortcuts
+ uint32 num_shortcuts; // size of the array
+} GearsShortcutList;
+
+// Command data for GEARSBROWSERCOMMAND_CREATE_SHORTCUT_DONE
+typedef struct _GearsCreateShortcutResult {
+ GearsShortcutData2* shortcut; // pointer to struct passed to
+ // GEARSPLUGINCOMMAND_CREATE_SHORTCUT
+ CPError result; // CPERR_SUCCESS if shortcut was created, or error otherwise
+} GearsCreateShortcutResult;
+
+#ifdef __cplusplus
+} // extern "C"
+#endif
+
+#endif // CHROME_COMMON_GEARS_API_H_
diff --git a/chrome/common/geoposition.cc b/chrome/common/geoposition.cc
new file mode 100644
index 0000000..f8f087c
--- /dev/null
+++ b/chrome/common/geoposition.cc
@@ -0,0 +1,66 @@
+// Copyright (c) 2010 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/common/geoposition.h"
+
+namespace {
+// Sentinel values to mark invalid data. (WebKit carries companion is_valid
+// bools for this purpose; we may eventually follow that approach, but
+// sentinels worked OK in the gears code this is based on.)
+const double kBadLatitudeLongitude = 200;
+// Lowest point on land is at approximately -400 meters.
+const int kBadAltitude = -10000;
+const int kBadAccuracy = -1; // Accuracy must be non-negative.
+const int64 kBadTimestamp = kint64min;
+const int kBadHeading = -1; // Heading must be non-negative.
+const int kBadSpeed = -1;
+}
+
+Geoposition::Geoposition()
+ : latitude(kBadLatitudeLongitude),
+ longitude(kBadLatitudeLongitude),
+ altitude(kBadAltitude),
+ accuracy(kBadAccuracy),
+ altitude_accuracy(kBadAccuracy),
+ heading(kBadHeading),
+ speed(kBadSpeed),
+ error_code(ERROR_CODE_NONE) {
+}
+
+bool Geoposition::is_valid_latlong() const {
+ return latitude >= -90.0 && latitude <= 90.0 &&
+ longitude >= -180.0 && longitude <= 180.0;
+}
+
+bool Geoposition::is_valid_altitude() const {
+ return altitude > kBadAltitude;
+}
+
+bool Geoposition::is_valid_accuracy() const {
+ return accuracy >= 0.0;
+}
+
+bool Geoposition::is_valid_altitude_accuracy() const {
+ return altitude_accuracy >= 0.0;
+}
+
+bool Geoposition::is_valid_heading() const {
+ return heading >= 0 && heading <= 360;
+}
+
+bool Geoposition::is_valid_speed() const {
+ return speed >= 0;
+}
+
+bool Geoposition::is_valid_timestamp() const {
+ return !timestamp.is_null();
+}
+
+bool Geoposition::IsValidFix() const {
+ return is_valid_latlong() && is_valid_accuracy() && is_valid_timestamp();
+}
+
+bool Geoposition::IsInitialized() const {
+ return error_code != ERROR_CODE_NONE || IsValidFix();
+}
diff --git a/chrome/common/geoposition.h b/chrome/common/geoposition.h
new file mode 100644
index 0000000..f2db64c
--- /dev/null
+++ b/chrome/common/geoposition.h
@@ -0,0 +1,64 @@
+// Copyright (c) 2010 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.
+
+// This file declares the Position structure, which is used to represent a
+// position fix. Originally derived from
+// http://gears.googlecode.com/svn/trunk/gears/geolocation/geolocation.h
+
+#ifndef CHROME_COMMON_GEOPOSITION_H_
+#define CHROME_COMMON_GEOPOSITION_H_
+
+#include <string>
+#include "base/time.h"
+
+// The internal representation of a geo position. Some properties use different
+// types when passed to JavaScript.
+struct Geoposition {
+ public:
+ // Error codes for returning to JavaScript. These values are defined by the
+ // W3C spec. Note that Gears does not use all of these codes, but we need
+ // values for all of them to allow us to provide the constants on the error
+ // object.
+ enum ErrorCode {
+ ERROR_CODE_NONE = 0, // Chrome addition
+ ERROR_CODE_PERMISSION_DENIED = 1,
+ ERROR_CODE_POSITION_UNAVAILABLE = 2,
+ ERROR_CODE_TIMEOUT = 3,
+ };
+
+ Geoposition();
+
+ bool is_valid_latlong() const;
+ bool is_valid_altitude() const;
+ bool is_valid_accuracy() const;
+ bool is_valid_altitude_accuracy() const;
+ bool is_valid_heading() const;
+ bool is_valid_speed() const;
+ bool is_valid_timestamp() const;
+
+ // A valid fix has a valid latitude, longitude, accuracy and timestamp.
+ bool IsValidFix() const;
+
+ // A position is considered initialized if it has either a valid fix or
+ // an error code other than NONE.
+ bool IsInitialized() const;
+
+ // These properties correspond to the JavaScript Position object.
+ double latitude; // In degrees
+ double longitude; // In degrees
+ double altitude; // In metres
+ double accuracy; // In metres
+ double altitude_accuracy; // In metres
+ double heading; // In degrees clockwise relative to the true north
+ double speed; // In meters per second
+ // Timestamp for this position fix object taken from the host computer's
+ // system clock (i.e. from Time::Now(), not the source device's clock).
+ base::Time timestamp;
+
+ // These properties are returned to JavaScript as a PositionError object.
+ ErrorCode error_code;
+ std::string error_message; // Human-readable error message
+};
+
+#endif // CHROME_COMMON_GEOPOSITION_H_
diff --git a/chrome/common/googleurl_dummy.cc b/chrome/common/googleurl_dummy.cc
new file mode 100644
index 0000000..f55c263
--- /dev/null
+++ b/chrome/common/googleurl_dummy.cc
@@ -0,0 +1,18 @@
+// Copyright (c) 2010 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.
+
+namespace url_util {
+
+// A dummy version of the url_util function called by url_constants.cc for all
+// process types. For some processes, we don't want to link against googleurl.
+// rather than having complicated versions of that library (32 and 64 bit ones
+// on Windows) we just instead link this file in cases where googleurl isn't
+// otherwise necessary.
+void AddStandardScheme(const char* new_scheme) {
+}
+
+void LockStandardSchemes() {
+}
+
+} // namespace url_util
diff --git a/chrome/common/gpu_info.cc b/chrome/common/gpu_info.cc
new file mode 100644
index 0000000..b1add77
--- /dev/null
+++ b/chrome/common/gpu_info.cc
@@ -0,0 +1,41 @@
+// Copyright (c) 2006-2010 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/common/gpu_info.h"
+
+GPUInfo::GPUInfo()
+ : vendor_id_(0), device_id_(0), driver_version_(L""),
+ pixel_shader_version_(0), vertex_shader_version_(0) {
+}
+
+uint32 GPUInfo::vendor_id() const {
+ return vendor_id_;
+}
+
+uint32 GPUInfo::device_id() const {
+ return device_id_;
+}
+
+std::wstring GPUInfo::driver_version() const {
+ return driver_version_;
+}
+
+uint32 GPUInfo::pixel_shader_version() const {
+ return pixel_shader_version_;
+}
+
+uint32 GPUInfo::vertex_shader_version() const {
+ return vertex_shader_version_;
+}
+
+void GPUInfo::SetGraphicsInfo(uint32 vendor_id, uint32 device_id,
+ const std::wstring& driver_version,
+ uint32 pixel_shader_version,
+ uint32 vertex_shader_version) {
+ vendor_id_ = vendor_id;
+ device_id_ = device_id;
+ driver_version_ = driver_version;
+ pixel_shader_version_ = pixel_shader_version;
+ vertex_shader_version_ = vertex_shader_version;
+}
diff --git a/chrome/common/gpu_info.h b/chrome/common/gpu_info.h
new file mode 100644
index 0000000..65b5075
--- /dev/null
+++ b/chrome/common/gpu_info.h
@@ -0,0 +1,54 @@
+// Copyright (c) 2006-2010 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_COMMON_GPU_INFO_H__
+#define CHROME_COMMON_GPU_INFO_H__
+
+// Provides access to the GPU information for the system
+// on which chrome is currently running.
+
+#include <string>
+
+#include "base/basictypes.h"
+
+class GPUInfo {
+ public:
+ GPUInfo();
+ ~GPUInfo() {}
+
+ // Return the DWORD (uint32) representing the graphics card vendor id.
+ uint32 vendor_id() const;
+
+ // Return the DWORD (uint32) representing the graphics card device id.
+ // Device ids are unique to vendor, not to one another.
+ uint32 device_id() const;
+
+ // Return the version of the graphics driver currently installed.
+ // This will typically be something
+ std::wstring driver_version() const;
+
+ // Return the version of the pixel/fragment shader used by the gpu.
+ // This will typically be a number less than 10 so storing as a float
+ // should be okay.
+ uint32 pixel_shader_version() const;
+
+ // Return the version of the vertex shader used by the gpu.
+ // This will typically be a number less than 10 so storing as a float
+ // should be okay.
+ uint32 vertex_shader_version() const;
+
+ // Populate variables with passed in values
+ void SetGraphicsInfo(uint32 vendor_id, uint32 device_id,
+ const std::wstring& driver_version,
+ uint32 pixel_shader_version,
+ uint32 vertex_shader_version);
+ private:
+ uint32 vendor_id_;
+ uint32 device_id_;
+ std::wstring driver_version_;
+ uint32 pixel_shader_version_;
+ uint32 vertex_shader_version_;
+};
+
+#endif // CHROME_COMMON_GPU_INFO_H__
diff --git a/chrome/common/gpu_info_unittest.cc b/chrome/common/gpu_info_unittest.cc
new file mode 100644
index 0000000..4d469f6
--- /dev/null
+++ b/chrome/common/gpu_info_unittest.cc
@@ -0,0 +1,17 @@
+// Copyright (c) 2006-2010 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/logging.h"
+#include "chrome/common/gpu_info.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+// Test that an empty GPUInfo has valid members
+TEST(GPUInfoBasicTest, EmptyGPUInfo) {
+ GPUInfo gpu_info;
+ EXPECT_EQ(gpu_info.vendor_id(), 0u);
+ EXPECT_EQ(gpu_info.device_id(), 0u);
+ EXPECT_EQ(gpu_info.driver_version(), L"");
+ EXPECT_EQ(gpu_info.pixel_shader_version(), 0u);
+ EXPECT_EQ(gpu_info.vertex_shader_version(), 0u);
+}
diff --git a/chrome/common/gpu_messages.h b/chrome/common/gpu_messages.h
new file mode 100644
index 0000000..16f2860
--- /dev/null
+++ b/chrome/common/gpu_messages.h
@@ -0,0 +1,87 @@
+// Copyright (c) 2010 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_COMMON_GPU_MESSAGES_H_
+#define CHROME_COMMON_GPU_MESSAGES_H_
+
+#include <vector>
+
+#include "app/surface/transport_dib.h"
+#include "base/basictypes.h"
+#include "base/process.h"
+#include "chrome/common/common_param_traits.h"
+#include "chrome/common/gpu_info.h"
+#include "chrome/common/gpu_native_window_handle.h"
+#include "gfx/native_widget_types.h"
+#include "gfx/rect.h"
+#include "gfx/size.h"
+#include "gpu/command_buffer/common/command_buffer.h"
+
+namespace IPC {
+template <>
+struct ParamTraits<GPUInfo> {
+ typedef GPUInfo param_type;
+ static void Write(Message* m, const param_type& p) {
+ m->WriteUInt32(p.vendor_id());
+ m->WriteUInt32(p.device_id());
+ m->WriteWString(p.driver_version());
+ m->WriteUInt32(p.pixel_shader_version());
+ m->WriteUInt32(p.vertex_shader_version());
+ }
+ static bool Read(const Message* m, void** iter, param_type* p) {
+ uint32 vendor_id;
+ uint32 device_id;
+ std::wstring driver_version;
+ uint32 pixel_shader_version;
+ uint32 vertex_shader_version;
+ bool ret = m->ReadUInt32(iter, &vendor_id);
+ ret = ret && m->ReadUInt32(iter, &device_id);
+ ret = ret && m->ReadWString(iter, &driver_version);
+ ret = ret && m->ReadUInt32(iter, &pixel_shader_version);
+ ret = ret && m->ReadUInt32(iter, &vertex_shader_version);
+ p->SetGraphicsInfo(vendor_id, device_id, driver_version,
+ pixel_shader_version, vertex_shader_version);
+ return ret;
+ }
+ static void Log(const param_type& p, std::wstring* l) {
+ l->append(StringPrintf(L"<GPUInfo> %x %x %ls",
+ p.vendor_id(), p.device_id(), p.driver_version().c_str()));
+ }
+};
+
+template <>
+struct ParamTraits<gpu::CommandBuffer::State> {
+ typedef gpu::CommandBuffer::State param_type;
+ static void Write(Message* m, const param_type& p) {
+ m->WriteInt(p.num_entries);
+ m->WriteInt(p.get_offset);
+ m->WriteInt(p.put_offset);
+ m->WriteInt(p.token);
+ m->WriteInt(p.error);
+ }
+ static bool Read(const Message* m, void** iter, param_type* p) {
+ int32 temp;
+ if (m->ReadInt(iter, &p->num_entries) &&
+ m->ReadInt(iter, &p->get_offset) &&
+ m->ReadInt(iter, &p->put_offset) &&
+ m->ReadInt(iter, &p->token) &&
+ m->ReadInt(iter, &temp)) {
+ p->error = static_cast<gpu::error::Error>(temp);
+ return true;
+ } else {
+ return false;
+ }
+ }
+ static void Log(const param_type& p, std::wstring* l) {
+ l->append(L"<CommandBuffer::State>");
+ }
+};
+} // namespace IPC
+
+#define MESSAGES_INTERNAL_FILE \
+ "chrome/common/gpu_messages_internal.h"
+#include "ipc/ipc_message_macros.h"
+
+#endif // CHROME_COMMON_GPU_MESSAGES_H_
+
diff --git a/chrome/common/gpu_messages_internal.h b/chrome/common/gpu_messages_internal.h
new file mode 100644
index 0000000..fa9a83f
--- /dev/null
+++ b/chrome/common/gpu_messages_internal.h
@@ -0,0 +1,213 @@
+// Copyright (c) 2010 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.
+
+// This header is meant to be included in multiple passes, hence no traditional
+// header guard. It is included by backing_store_messages_internal.h
+// See ipc_message_macros.h for explanation of the macros and passes.
+
+// This file needs to be included again, even though we're actually included
+// from it via utility_messages.h.
+#include "base/shared_memory.h"
+#include "chrome/common/gpu_info.h"
+#include "gfx/size.h"
+#include "ipc/ipc_channel_handle.h"
+#include "ipc/ipc_message_macros.h"
+
+//------------------------------------------------------------------------------
+// GPU Messages
+// These are messages from the browser to the GPU process.
+IPC_BEGIN_MESSAGES(Gpu)
+
+ // Tells the GPU process to create a new channel for communication with a
+ // given renderer. The channel name is returned in a
+ // GpuHostMsg_ChannelEstablished message. The renderer ID is passed so that
+ // the GPU process reuses an existing channel to that process if it exists.
+ // This ID is a unique opaque identifier generated by the browser process.
+ IPC_MESSAGE_CONTROL1(GpuMsg_EstablishChannel,
+ int /* renderer_id */)
+
+ // Provides a synchronization point to guarantee that the processing of
+ // previous asynchronous messages (i.e., GpuMsg_EstablishChannel) has
+ // completed. (This message can't be synchronous because the
+ // GpuProcessHost uses an IPC::ChannelProxy, which sends all messages
+ // asynchronously.) Results in a GpuHostMsg_SynchronizeReply.
+ IPC_MESSAGE_CONTROL0(GpuMsg_Synchronize)
+
+ IPC_MESSAGE_CONTROL2(GpuMsg_NewRenderWidgetHostView,
+ GpuNativeWindowHandle, /* parent window */
+ int32 /* view_id */)
+
+ // Creates a new backing store.
+ IPC_MESSAGE_ROUTED2(GpuMsg_NewBackingStore,
+ int32, /* backing_store_routing_id */
+ gfx::Size /* size */)
+
+ // Creates a new video layer.
+ IPC_MESSAGE_ROUTED2(GpuMsg_NewVideoLayer,
+ int32, /* video_layer_routing_id */
+ gfx::Size /* size */)
+
+ // Updates the backing store with the given bitmap. The GPU process will send
+ // back a GpuHostMsg_PaintToBackingStore_ACK after the paint is complete to
+ // let the caller know the TransportDIB can be freed or reused.
+ IPC_MESSAGE_ROUTED4(GpuMsg_PaintToBackingStore,
+ base::ProcessId, /* process */
+ TransportDIB::Id, /* bitmap */
+ gfx::Rect, /* bitmap_rect */
+ std::vector<gfx::Rect>) /* copy_rects */
+
+
+ IPC_MESSAGE_ROUTED4(GpuMsg_ScrollBackingStore,
+ int, /* dx */
+ int, /* dy */
+ gfx::Rect, /* clip_rect */
+ gfx::Size) /* view_size */
+
+ // Tells the GPU process that the RenderWidgetHost has painted the window.
+ // Depending on the platform, the accelerated content may need to be painted
+ // over the top.
+ IPC_MESSAGE_ROUTED0(GpuMsg_WindowPainted)
+
+ // Updates the video layer with the given YUV data. The GPU process will send
+ // back a GpuHostMsg_PaintToVideoLayer_ACK after the paint is complete to
+ // let the caller know the TransportDIB can be freed or reused.
+ IPC_MESSAGE_ROUTED3(GpuMsg_PaintToVideoLayer,
+ base::ProcessId, /* process */
+ TransportDIB::Id, /* bitmap */
+ gfx::Rect) /* bitmap_rect */
+
+IPC_END_MESSAGES(Gpu)
+
+//------------------------------------------------------------------------------
+// GPU Host Messages
+// These are messages from the GPU process to the browser.
+IPC_BEGIN_MESSAGES(GpuHost)
+
+ // Sent in response to GpuMsg_PaintToBackingStore, see that for more.
+ IPC_MESSAGE_ROUTED0(GpuHostMsg_PaintToBackingStore_ACK)
+
+ // Sent in response to GpuMsg_PaintToVideoLayer, see that for more.
+ IPC_MESSAGE_ROUTED0(GpuHostMsg_PaintToVideoLayer_ACK)
+
+ // Response to a GpuHostMsg_EstablishChannel message.
+ IPC_MESSAGE_CONTROL2(GpuHostMsg_ChannelEstablished,
+ IPC::ChannelHandle, /* channel_handle */
+ GPUInfo /* GPU logging stats */)
+
+ // Response to a GpuMsg_Synchronize message.
+ IPC_MESSAGE_CONTROL0(GpuHostMsg_SynchronizeReply)
+
+#if defined(OS_LINUX)
+ // Get the XID for a view ID.
+ IPC_SYNC_MESSAGE_CONTROL1_1(GpuHostMsg_GetViewXID,
+ gfx::NativeViewId, /* view */
+ unsigned long /* xid */)
+#endif
+
+IPC_END_MESSAGES(GpuHost)
+
+//------------------------------------------------------------------------------
+// GPU Channel Messages
+// These are messages from a renderer process to the GPU process.
+IPC_BEGIN_MESSAGES(GpuChannel)
+
+ // Tells the GPU process to create a new command buffer that renders directly
+ // to a native view. A corresponding GpuCommandBufferStub is created.
+ IPC_SYNC_MESSAGE_CONTROL1_1(GpuChannelMsg_CreateViewCommandBuffer,
+ gfx::NativeViewId, /* view */
+ int32 /* route_id */)
+
+ // Tells the GPU process to create a new command buffer that renders to an
+ // offscreen frame buffer. If parent_route_id is not zero, the texture backing
+ // the frame buffer is mapped into the corresponding parent command buffer's
+ // namespace, with the name of parent_texture_id. This ID is in the parent's
+ // namespace.
+ IPC_SYNC_MESSAGE_CONTROL3_1(GpuChannelMsg_CreateOffscreenCommandBuffer,
+ int32, /* parent_route_id */
+ gfx::Size, /* size */
+ uint32, /* parent_texture_id */
+ int32 /* route_id */)
+
+ // The CommandBufferProxy sends this to the GpuCommandBufferStub in its
+ // destructor, so that the stub deletes the actual WebPluginDelegateImpl
+ // object that it's hosting.
+ // TODO(apatrick): Implement this.
+ IPC_MESSAGE_CONTROL1(GpuChannelMsg_DestroyCommandBuffer,
+ int32 /* instance_id */)
+
+IPC_END_MESSAGES(GpuChannel)
+
+//------------------------------------------------------------------------------
+// GPU Command Buffer Messages
+// These are messages from a renderer process to the GPU process relating to a
+// single OpenGL context.
+IPC_BEGIN_MESSAGES(GpuCommandBuffer)
+ // Initialize a command buffer with the given number of command entries.
+ // Returns the shared memory handle for the command buffer mapped to the
+ // calling process.
+ IPC_SYNC_MESSAGE_ROUTED1_1(GpuCommandBufferMsg_Initialize,
+ int32 /* size */,
+ base::SharedMemoryHandle /* ring_buffer */)
+
+ // Get the current state of the command buffer.
+ IPC_SYNC_MESSAGE_ROUTED0_1(GpuCommandBufferMsg_GetState,
+ gpu::CommandBuffer::State /* state */)
+
+ // Get the current state of the command buffer asynchronously. State is
+ // returned via UpdateState message.
+ IPC_MESSAGE_ROUTED0(GpuCommandBufferMsg_AsyncGetState)
+
+ // Synchronize the put and get offsets of both processes. Caller passes its
+ // current put offset. Current state (including get offset) is returned.
+ IPC_SYNC_MESSAGE_ROUTED1_1(GpuCommandBufferMsg_Flush,
+ int32 /* put_offset */,
+ gpu::CommandBuffer::State /* state */)
+
+ // Asynchronously synchronize the put and get offsets of both processes.
+ // Caller passes its current put offset. Current state (including get offset)
+ // is returned via an UpdateState message.
+ IPC_MESSAGE_ROUTED1(GpuCommandBufferMsg_AsyncFlush,
+ int32 /* put_offset */)
+
+ // Return the current state of the command buffer following a request via
+ // an AsyncGetState or AsyncFlush message.
+ IPC_MESSAGE_ROUTED1(GpuCommandBufferMsg_UpdateState,
+ gpu::CommandBuffer::State /* state */)
+
+ // Create a shared memory transfer buffer. Returns an id that can be used to
+ // identify the transfer buffer from a comment.
+ IPC_SYNC_MESSAGE_ROUTED1_1(GpuCommandBufferMsg_CreateTransferBuffer,
+ int32 /* size */,
+ int32 /* id */)
+
+ // Destroy a previously created transfer buffer.
+ IPC_SYNC_MESSAGE_ROUTED1_0(GpuCommandBufferMsg_DestroyTransferBuffer,
+ int32 /* id */)
+
+ // Get the shared memory handle for a transfer buffer mapped to the callers
+ // process.
+ IPC_SYNC_MESSAGE_ROUTED1_2(GpuCommandBufferMsg_GetTransferBuffer,
+ int32 /* id */,
+ base::SharedMemoryHandle /* transfer_buffer */,
+ uint32 /* size */)
+
+ // Send from command buffer stub to proxy when window is invalid and must be
+ // repainted.
+ IPC_MESSAGE_ROUTED0(GpuCommandBufferMsg_NotifyRepaint)
+
+ // Tells the GPU process to resize an offscreen frame buffer.
+ IPC_MESSAGE_ROUTED1(GpuCommandBufferMsg_ResizeOffscreenFrameBuffer,
+ gfx::Size /* size */)
+
+#if defined(OS_MACOSX)
+ // On Mac OS X the GPU plugin must be offscreen, because there is no
+ // true cross-process window hierarchy. For this reason we must send
+ // resize events explicitly to the command buffer stub so it can
+ // reallocate its backing store and send the new one back to the
+ // browser. This message is currently used only on 10.6 and later.
+ IPC_MESSAGE_ROUTED1(GpuCommandBufferMsg_SetWindowSize,
+ gfx::Size /* size */)
+#endif
+
+IPC_END_MESSAGES(GpuCommandBuffer)
diff --git a/chrome/common/gpu_messages_unittest.cc b/chrome/common/gpu_messages_unittest.cc
new file mode 100644
index 0000000..5215949
--- /dev/null
+++ b/chrome/common/gpu_messages_unittest.cc
@@ -0,0 +1,35 @@
+// Copyright (c) 2006-2010 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/logging.h"
+#include "base/scoped_ptr.h"
+#include "chrome/common/gpu_info.h"
+#include "chrome/common/gpu_messages.h"
+#include "ipc/ipc_message.h"
+#include "ipc/ipc_message_utils.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+// Test GPUInfo serialization
+TEST(GPUIPCMessageTest, GPUInfo) {
+ GPUInfo input;
+ // Test variables taken from Lenovo T61
+ input.SetGraphicsInfo(0x10de, 0x429, L"6.14.11.7715",
+ 0xffff0300, 0xfffe0300);
+
+ IPC::Message msg(1, 2, IPC::Message::PRIORITY_NORMAL);
+ IPC::WriteParam(&msg, input);
+
+ GPUInfo output;
+ void* iter = NULL;
+ EXPECT_TRUE(IPC::ReadParam(&msg, &iter, &output));
+ EXPECT_EQ(input.vendor_id(), output.vendor_id());
+ EXPECT_EQ(input.device_id(), output.device_id());
+ EXPECT_EQ(input.driver_version(), output.driver_version());
+ EXPECT_EQ(input.pixel_shader_version(), output.pixel_shader_version());
+ EXPECT_EQ(input.vertex_shader_version(), output.vertex_shader_version());
+
+ std::wstring log_message;
+ IPC::LogParam(output, &log_message);
+ EXPECT_STREQ(L"<GPUInfo> 10de 429 6.14.11.7715", log_message.c_str());
+}
diff --git a/chrome/common/gpu_native_window_handle.h b/chrome/common/gpu_native_window_handle.h
new file mode 100644
index 0000000..11e8cda
--- /dev/null
+++ b/chrome/common/gpu_native_window_handle.h
@@ -0,0 +1,41 @@
+// Copyright (c) 2010 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_COMMON_GPU_NATIVE_WINDOW_HANDLE_H_
+#define CHROME_COMMON_GPU_NATIVE_WINDOW_HANDLE_H_
+
+#include "build/build_config.h"
+
+// This file defines the window handle type used by the GPU process IPC layer.
+// This is different than gfx::NativeWindow[Id] since on X, this is an XID.
+// Normally, Chrome deals with either GTK window pointers, or magic window
+// IDs that the app generates. The GPU process needs to know the real XID.
+
+#if defined(OS_WIN)
+
+#include <windows.h>
+
+typedef HWND GpuNativeWindowHandle;
+
+#elif defined(OS_MACOSX)
+
+// The GPU process isn't supported on Mac yet. Defining this arbitrarily allows
+// us to not worry about the integration points not compiling.
+typedef int GpuNativeWindowHandle;
+
+#elif defined(USE_X11)
+
+// Forward declar XID ourselves to avoid pulling in all of the X headers, which
+// can cause compile problems for some parts of the project.
+typedef unsigned long XID;
+
+typedef XID GpuNativeWindowHandle;
+
+#else
+
+#error define GpuNativeWindowHandle
+
+#endif
+
+#endif // CHROME_COMMON_GPU_NATIVE_WINDOW_HANDLE_H_
diff --git a/chrome/common/gpu_plugin.cc b/chrome/common/gpu_plugin.cc
new file mode 100644
index 0000000..af009f9
--- /dev/null
+++ b/chrome/common/gpu_plugin.cc
@@ -0,0 +1,44 @@
+// Copyright (c) 2009 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/common/gpu_plugin.h"
+
+#include "base/command_line.h"
+#include "base/string_util.h"
+#include "chrome/common/chrome_switches.h"
+#include "gpu/gpu_plugin/gpu_plugin.h"
+#include "webkit/glue/plugins/plugin_list.h"
+
+#if defined(ENABLE_GPU)
+#include "webkit/glue/plugins/plugin_constants_win.h"
+#endif
+
+namespace chrome {
+
+void RegisterInternalGPUPlugin() {
+#if defined(ENABLE_GPU)
+ static const std::wstring kWideMimeType = ASCIIToWide(kGPUPluginMimeType);
+ static const NPAPI::PluginVersionInfo kGPUPluginInfo = {
+ FilePath(FILE_PATH_LITERAL("gpu-plugin")),
+ L"GPU Plug-in",
+ L"GPU Rendering Plug-in",
+ L"1",
+ kWideMimeType.c_str(),
+ L"",
+ L"",
+ {
+#if !defined(OS_POSIX) || defined(OS_MACOSX)
+ gpu_plugin::NP_GetEntryPoints,
+#endif
+ gpu_plugin::NP_Initialize,
+ gpu_plugin::NP_Shutdown
+ }
+ };
+
+ if (CommandLine::ForCurrentProcess()->HasSwitch(switches::kEnableGPUPlugin))
+ NPAPI::PluginList::Singleton()->RegisterInternalPlugin(kGPUPluginInfo);
+#endif // ENABLE_GPU
+}
+
+} // namespace chrome
diff --git a/chrome/common/gpu_plugin.h b/chrome/common/gpu_plugin.h
new file mode 100644
index 0000000..3fd609e
--- /dev/null
+++ b/chrome/common/gpu_plugin.h
@@ -0,0 +1,15 @@
+// Copyright (c) 2009 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_COMMON_GPU_PLUGIN_H_
+#define CHROME_COMMON_GPU_PLUGIN_H_
+
+namespace chrome {
+
+// Register the GPU plugin as an internal plugin in the PluginList.
+void RegisterInternalGPUPlugin();
+
+} // namespace chrome
+
+#endif // CHROME_COMMON_GPU_PLUGIN_H_
diff --git a/chrome/common/important_file_writer.cc b/chrome/common/important_file_writer.cc
new file mode 100644
index 0000000..3466958
--- /dev/null
+++ b/chrome/common/important_file_writer.cc
@@ -0,0 +1,150 @@
+// Copyright (c) 2010 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/common/important_file_writer.h"
+
+#include <stdio.h>
+
+#include <ostream>
+#include <string>
+
+#include "base/file_path.h"
+#include "base/file_util.h"
+#include "base/logging.h"
+#include "base/message_loop_proxy.h"
+#include "base/string_util.h"
+#include "base/task.h"
+#include "base/thread.h"
+#include "base/time.h"
+
+using base::TimeDelta;
+
+namespace {
+
+const int kDefaultCommitIntervalMs = 10000;
+
+class WriteToDiskTask : public Task {
+ public:
+ WriteToDiskTask(const FilePath& path, const std::string& data)
+ : path_(path),
+ data_(data) {
+ }
+
+ virtual void Run() {
+ // Write the data to a temp file then rename to avoid data loss if we crash
+ // while writing the file. Ensure that the temp file is on the same volume
+ // as target file, so it can be moved in one step, and that the temp file
+ // is securely created.
+ FilePath tmp_file_path;
+ FILE* tmp_file = file_util::CreateAndOpenTemporaryFileInDir(
+ path_.DirName(), &tmp_file_path);
+ if (!tmp_file) {
+ LogFailure("could not create temporary file");
+ return;
+ }
+
+ size_t bytes_written = fwrite(data_.data(), 1, data_.length(), tmp_file);
+ if (!file_util::CloseFile(tmp_file)) {
+ file_util::Delete(tmp_file_path, false);
+ LogFailure("failed to close temporary file");
+ return;
+ }
+ if (bytes_written < data_.length()) {
+ file_util::Delete(tmp_file_path, false);
+ LogFailure("error writing, bytes_written=" + UintToString(
+ static_cast<unsigned int>(bytes_written)));
+ return;
+ }
+
+ if (file_util::ReplaceFile(tmp_file_path, path_)) {
+ LogSuccess();
+ return;
+ }
+
+ file_util::Delete(tmp_file_path, false);
+ LogFailure("could not rename temporary file");
+ }
+
+ private:
+ void LogSuccess() {
+ LOG(INFO) << "successfully saved " << path_.value();
+ }
+
+ void LogFailure(const std::string& message) {
+ LOG(WARNING) << "failed to write " << path_.value()
+ << ": " << message;
+ }
+
+ const FilePath path_;
+ const std::string data_;
+
+ DISALLOW_COPY_AND_ASSIGN(WriteToDiskTask);
+};
+
+} // namespace
+
+ImportantFileWriter::ImportantFileWriter(
+ const FilePath& path, base::MessageLoopProxy* file_message_loop_proxy)
+ : path_(path),
+ file_message_loop_proxy_(file_message_loop_proxy),
+ serializer_(NULL),
+ commit_interval_(TimeDelta::FromMilliseconds(
+ kDefaultCommitIntervalMs)) {
+ DCHECK(CalledOnValidThread());
+ DCHECK(file_message_loop_proxy_.get());
+}
+
+ImportantFileWriter::~ImportantFileWriter() {
+ // We're usually a member variable of some other object, which also tends
+ // to be our serializer. It may not be safe to call back to the parent object
+ // being destructed.
+ DCHECK(!HasPendingWrite());
+}
+
+bool ImportantFileWriter::HasPendingWrite() const {
+ DCHECK(CalledOnValidThread());
+ return timer_.IsRunning();
+}
+
+void ImportantFileWriter::WriteNow(const std::string& data) {
+ DCHECK(CalledOnValidThread());
+
+ if (HasPendingWrite())
+ timer_.Stop();
+
+ // TODO(sanjeevr): Add a DCHECK for the return value of PostTask.
+ // (Some tests fail if we add the DCHECK and they need to be fixed first).
+ file_message_loop_proxy_->PostTask(FROM_HERE,
+ new WriteToDiskTask(path_, data));
+}
+
+void ImportantFileWriter::ScheduleWrite(DataSerializer* serializer) {
+ DCHECK(CalledOnValidThread());
+
+ DCHECK(serializer);
+ serializer_ = serializer;
+
+ if (!MessageLoop::current()) {
+ // Happens in unit tests.
+ DoScheduledWrite();
+ return;
+ }
+
+ if (!timer_.IsRunning()) {
+ timer_.Start(commit_interval_, this,
+ &ImportantFileWriter::DoScheduledWrite);
+ }
+}
+
+void ImportantFileWriter::DoScheduledWrite() {
+ DCHECK(serializer_);
+ std::string data;
+ if (serializer_->SerializeData(&data)) {
+ WriteNow(data);
+ } else {
+ LOG(WARNING) << "failed to serialize data to be saved in "
+ << path_.value();
+ }
+ serializer_ = NULL;
+}
diff --git a/chrome/common/important_file_writer.h b/chrome/common/important_file_writer.h
new file mode 100644
index 0000000..d4f57a0
--- /dev/null
+++ b/chrome/common/important_file_writer.h
@@ -0,0 +1,112 @@
+// Copyright (c) 2009 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_COMMON_IMPORTANT_FILE_WRITER_H_
+#define CHROME_COMMON_IMPORTANT_FILE_WRITER_H_
+
+#include <string>
+
+#include "base/basictypes.h"
+#include "base/file_path.h"
+#include "base/non_thread_safe.h"
+#include "base/ref_counted.h"
+#include "base/time.h"
+#include "base/timer.h"
+
+namespace base {
+class MessageLoopProxy;
+class Thread;
+}
+
+// Helper to ensure that a file won't be corrupted by the write (for example on
+// application crash). Consider a naive way to save an important file F:
+//
+// 1. Open F for writing, truncating it.
+// 2. Write new data to F.
+//
+// It's good when it works, but it gets very bad if step 2. doesn't complete.
+// It can be caused by a crash, a computer hang, or a weird I/O error. And you
+// end up with a broken file.
+//
+// To be safe, we don't start with writing directly to F. Instead, we write to
+// to a temporary file. Only after that write is successful, we rename the
+// temporary file to target filename.
+//
+// If you want to know more about this approach and ext3/ext4 fsync issues, see
+// http://valhenson.livejournal.com/37921.html
+class ImportantFileWriter : public NonThreadSafe {
+ public:
+ // Used by ScheduleSave to lazily provide the data to be saved. Allows us
+ // to also batch data serializations.
+ class DataSerializer {
+ public:
+ virtual ~DataSerializer() {}
+
+ // Should put serialized string in |data| and return true on successful
+ // serialization. Will be called on the same thread on which
+ // ImportantFileWriter has been created.
+ virtual bool SerializeData(std::string* data) = 0;
+ };
+
+ // Initialize the writer.
+ // |path| is the name of file to write.
+ // |file_message_loop_proxy| is the MessageLoopProxy for a thread on which
+ // file I/O can be done.
+ // All non-const methods, ctor and dtor must be called on the same thread.
+ ImportantFileWriter(const FilePath& path,
+ base::MessageLoopProxy* file_message_loop_proxy);
+
+ // You have to ensure that there are no pending writes at the moment
+ // of destruction.
+ ~ImportantFileWriter();
+
+ FilePath path() const { return path_; }
+
+ // Returns true if there is a scheduled write pending which has not yet
+ // been started.
+ bool HasPendingWrite() const;
+
+ // Save |data| to target filename. Does not block. If there is a pending write
+ // scheduled by ScheduleWrite, it is cancelled.
+ void WriteNow(const std::string& data);
+
+ // Schedule a save to target filename. Data will be serialized and saved
+ // to disk after the commit interval. If another ScheduleWrite is issued
+ // before that, only one serialization and write to disk will happen, and
+ // the most recent |serializer| will be used. This operation does not block.
+ // |serializer| should remain valid through the lifetime of
+ // ImportantFileWriter.
+ void ScheduleWrite(DataSerializer* serializer);
+
+ // Serialize data pending to be saved and execute write on backend thread.
+ void DoScheduledWrite();
+
+ base::TimeDelta commit_interval() const {
+ return commit_interval_;
+ }
+
+ void set_commit_interval(const base::TimeDelta& interval) {
+ commit_interval_ = interval;
+ }
+
+ private:
+ // Path being written to.
+ const FilePath path_;
+
+ // MessageLoopProxy for the thread on which file I/O can be done.
+ scoped_refptr<base::MessageLoopProxy> file_message_loop_proxy_;
+
+ // Timer used to schedule commit after ScheduleWrite.
+ base::OneShotTimer<ImportantFileWriter> timer_;
+
+ // Serializer which will provide the data to be saved.
+ DataSerializer* serializer_;
+
+ // Time delta after which scheduled data will be written to disk.
+ base::TimeDelta commit_interval_;
+
+ DISALLOW_COPY_AND_ASSIGN(ImportantFileWriter);
+};
+
+#endif // CHROME_COMMON_IMPORTANT_FILE_WRITER_H_
diff --git a/chrome/common/important_file_writer_unittest.cc b/chrome/common/important_file_writer_unittest.cc
new file mode 100644
index 0000000..3d44ae0
--- /dev/null
+++ b/chrome/common/important_file_writer_unittest.cc
@@ -0,0 +1,115 @@
+// Copyright (c) 2009 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/common/important_file_writer.h"
+
+#include "base/compiler_specific.h"
+#include "base/file_path.h"
+#include "base/file_util.h"
+#include "base/logging.h"
+#include "base/message_loop.h"
+#include "base/scoped_temp_dir.h"
+#include "base/thread.h"
+#include "base/time.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+namespace {
+
+std::string GetFileContent(const FilePath& path) {
+ std::string content;
+ if (!file_util::ReadFileToString(path, &content)) {
+ NOTREACHED();
+ }
+ return content;
+}
+
+class DataSerializer : public ImportantFileWriter::DataSerializer {
+ public:
+ explicit DataSerializer(const std::string& data) : data_(data) {
+ }
+
+ virtual bool SerializeData(std::string* output) {
+ output->assign(data_);
+ return true;
+ }
+
+ private:
+ const std::string data_;
+};
+
+} // namespace
+
+class ImportantFileWriterTest : public testing::Test {
+ public:
+ ImportantFileWriterTest() { }
+ virtual void SetUp() {
+ ASSERT_TRUE(temp_dir_.CreateUniqueTempDir());
+ file_ = temp_dir_.path().AppendASCII("test-file");
+ }
+
+ protected:
+ FilePath file_;
+ MessageLoop loop_;
+
+ private:
+ ScopedTempDir temp_dir_;
+};
+
+TEST_F(ImportantFileWriterTest, Basic) {
+ ImportantFileWriter writer(file_,
+ base::MessageLoopProxy::CreateForCurrentThread());
+ EXPECT_FALSE(file_util::PathExists(writer.path()));
+ writer.WriteNow("foo");
+ loop_.RunAllPending();
+
+ ASSERT_TRUE(file_util::PathExists(writer.path()));
+ EXPECT_EQ("foo", GetFileContent(writer.path()));
+}
+
+TEST_F(ImportantFileWriterTest, ScheduleWrite) {
+ ImportantFileWriter writer(file_,
+ base::MessageLoopProxy::CreateForCurrentThread());
+ writer.set_commit_interval(base::TimeDelta::FromMilliseconds(25));
+ EXPECT_FALSE(writer.HasPendingWrite());
+ DataSerializer serializer("foo");
+ writer.ScheduleWrite(&serializer);
+ EXPECT_TRUE(writer.HasPendingWrite());
+ MessageLoop::current()->PostDelayedTask(FROM_HERE,
+ new MessageLoop::QuitTask(), 100);
+ MessageLoop::current()->Run();
+ EXPECT_FALSE(writer.HasPendingWrite());
+ ASSERT_TRUE(file_util::PathExists(writer.path()));
+ EXPECT_EQ("foo", GetFileContent(writer.path()));
+}
+
+TEST_F(ImportantFileWriterTest, DoScheduledWrite) {
+ ImportantFileWriter writer(file_,
+ base::MessageLoopProxy::CreateForCurrentThread());
+ EXPECT_FALSE(writer.HasPendingWrite());
+ DataSerializer serializer("foo");
+ writer.ScheduleWrite(&serializer);
+ EXPECT_TRUE(writer.HasPendingWrite());
+ writer.DoScheduledWrite();
+ MessageLoop::current()->PostDelayedTask(FROM_HERE,
+ new MessageLoop::QuitTask(), 100);
+ MessageLoop::current()->Run();
+ EXPECT_FALSE(writer.HasPendingWrite());
+ ASSERT_TRUE(file_util::PathExists(writer.path()));
+ EXPECT_EQ("foo", GetFileContent(writer.path()));
+}
+
+TEST_F(ImportantFileWriterTest, BatchingWrites) {
+ ImportantFileWriter writer(file_,
+ base::MessageLoopProxy::CreateForCurrentThread());
+ writer.set_commit_interval(base::TimeDelta::FromMilliseconds(25));
+ DataSerializer foo("foo"), bar("bar"), baz("baz");
+ writer.ScheduleWrite(&foo);
+ writer.ScheduleWrite(&bar);
+ writer.ScheduleWrite(&baz);
+ MessageLoop::current()->PostDelayedTask(FROM_HERE,
+ new MessageLoop::QuitTask(), 100);
+ MessageLoop::current()->Run();
+ ASSERT_TRUE(file_util::PathExists(writer.path()));
+ EXPECT_EQ("baz", GetFileContent(writer.path()));
+}
diff --git a/chrome/common/indexed_db_key.cc b/chrome/common/indexed_db_key.cc
new file mode 100644
index 0000000..1c09ea2
--- /dev/null
+++ b/chrome/common/indexed_db_key.cc
@@ -0,0 +1,54 @@
+// Copyright (c) 2010 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/common/indexed_db_key.h"
+
+#include "base/logging.h"
+#include "third_party/WebKit/WebKit/chromium/public/WebString.h"
+
+using WebKit::WebIDBKey;
+
+IndexedDBKey::IndexedDBKey()
+ : type_(WebIDBKey::InvalidType) {
+}
+
+IndexedDBKey::IndexedDBKey(const WebIDBKey& key)
+ : type_(key.type()),
+ string_(key.type() == WebIDBKey::StringType
+ ? static_cast<string16>(key.string()) : string16()),
+ number_(key.type() == WebIDBKey::NumberType ? key.number() : 0) {
+}
+
+void IndexedDBKey::SetNull() {
+ type_ = WebIDBKey::NullType;
+}
+
+void IndexedDBKey::SetInvalid() {
+ type_ = WebIDBKey::InvalidType;
+}
+
+void IndexedDBKey::Set(const string16& string) {
+ type_ = WebIDBKey::StringType;
+ string_ = string;
+}
+
+void IndexedDBKey::Set(int32_t number) {
+ type_ = WebIDBKey::NumberType;
+ number_ = number;
+}
+
+IndexedDBKey::operator WebIDBKey() const {
+ switch (type_) {
+ case WebIDBKey::NullType:
+ return WebIDBKey::createNull();
+ case WebIDBKey::StringType:
+ return WebIDBKey(string_);
+ case WebIDBKey::NumberType:
+ return WebIDBKey(number_);
+ case WebIDBKey::InvalidType:
+ return WebIDBKey::createInvalid();
+ }
+ NOTREACHED();
+ return WebIDBKey::createInvalid();
+}
diff --git a/chrome/common/indexed_db_key.h b/chrome/common/indexed_db_key.h
new file mode 100644
index 0000000..13bfae3
--- /dev/null
+++ b/chrome/common/indexed_db_key.h
@@ -0,0 +1,34 @@
+// Copyright (c) 2010 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_COMMON_INDEXED_DB_KEY_H_
+#define CHROME_COMMON_INDEXED_DB_KEY_H_
+
+#include "base/basictypes.h"
+#include "base/string16.h"
+#include "third_party/WebKit/WebKit/chromium/public/WebIDBKey.h"
+
+class IndexedDBKey {
+ public:
+ IndexedDBKey(); // Defaults to WebKit::WebIDBKey::InvalidType.
+ explicit IndexedDBKey(const WebKit::WebIDBKey& key);
+
+ void SetNull();
+ void SetInvalid();
+ void Set(const string16& string);
+ void Set(int32_t number);
+
+ WebKit::WebIDBKey::Type type() const { return type_; }
+ const string16& string() const { return string_; }
+ int32_t number() const { return number_; }
+
+ operator WebKit::WebIDBKey() const;
+
+ private:
+ WebKit::WebIDBKey::Type type_;
+ string16 string_;
+ int32_t number_;
+};
+
+#endif // CHROME_COMMON_INDEXED_DB_KEY_H_
diff --git a/chrome/common/ipc_test_sink.cc b/chrome/common/ipc_test_sink.cc
new file mode 100644
index 0000000..04fd065
--- /dev/null
+++ b/chrome/common/ipc_test_sink.cc
@@ -0,0 +1,57 @@
+// Copyright (c) 2010 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/common/ipc_test_sink.h"
+
+namespace IPC {
+
+TestSink::TestSink() {
+}
+
+TestSink::~TestSink() {
+}
+
+bool TestSink::Send(IPC::Message* message) {
+ OnMessageReceived(*message);
+ delete message;
+ return true;
+}
+
+void TestSink::OnMessageReceived(const Message& msg) {
+ messages_.push_back(Message(msg));
+}
+
+void TestSink::ClearMessages() {
+ messages_.clear();
+}
+
+const Message* TestSink::GetMessageAt(size_t index) const {
+ if (index >= messages_.size())
+ return NULL;
+ return &messages_[index];
+}
+
+const Message* TestSink::GetFirstMessageMatching(uint32 id) const {
+ for (size_t i = 0; i < messages_.size(); i++) {
+ if (messages_[i].type() == id)
+ return &messages_[i];
+ }
+ return NULL;
+}
+
+const Message* TestSink::GetUniqueMessageMatching(uint32 id) const {
+ size_t found_index = 0;
+ size_t found_count = 0;
+ for (size_t i = 0; i < messages_.size(); i++) {
+ if (messages_[i].type() == id) {
+ found_count++;
+ found_index = i;
+ }
+ }
+ if (found_count != 1)
+ return NULL; // Didn't find a unique one.
+ return &messages_[found_index];
+}
+
+} // namespace IPC
diff --git a/chrome/common/ipc_test_sink.h b/chrome/common/ipc_test_sink.h
new file mode 100644
index 0000000..96e91c0
--- /dev/null
+++ b/chrome/common/ipc_test_sink.h
@@ -0,0 +1,89 @@
+// Copyright (c) 2010 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_COMMON_IPC_TEST_SINK_H_
+#define CHROME_COMMON_IPC_TEST_SINK_H_
+
+#include <utility>
+#include <vector>
+
+#include "base/basictypes.h"
+#include "ipc/ipc_channel.h"
+#include "ipc/ipc_message.h"
+
+namespace IPC {
+
+// This test sink provides a "sink" for IPC messages that are sent. It allows
+// the caller to query messages received in various different ways. It is
+// designed for tests for objects that use the IPC system.
+//
+// Typical usage:
+//
+// test_sink.ClearMessages();
+// do_something();
+//
+// // We should have gotten exactly one update state message.
+// EXPECT_TRUE(test_sink.GetUniqeMessageMatching(ViewHostMsg_Update::ID));
+// // ...and no start load messages.
+// EXPECT_FALSE(test_sink.GetFirstMessageMatching(ViewHostMsg_Start::ID));
+//
+// // Now inspect a message. This assumes a message that was declared like
+// // this: IPC_MESSAGE_ROUTED2(ViewMsg_Foo, bool, int)
+// IPC::Message* msg = test_sink.GetFirstMessageMatching(ViewMsg_Foo::ID));
+// ASSERT_TRUE(msg);
+// bool first_param;
+// int second_param;
+// ViewMsg_Foo::Read(msg, &first_param, &second_param);
+//
+// // Go on to the next phase of the test.
+// test_sink.ClearMessages();
+//
+// To hook up the sink, all you need to do is call OnMessageReceived when a
+// message is received.
+class TestSink : public IPC::Channel {
+ public:
+ TestSink();
+ ~TestSink();
+
+ // Interface in IPC::Channel. This copies the message to the sink and then
+ // deletes it.
+ virtual bool Send(IPC::Message* message);
+
+ // Used by the source of the messages to send the message to the sink. This
+ // will make a copy of the message and store it in the list.
+ void OnMessageReceived(const Message& msg);
+
+ // Returns the number of messages in the queue.
+ size_t message_count() const { return messages_.size(); }
+
+ // Clears the message queue of saved messages.
+ void ClearMessages();
+
+ // Returns the message at the given index in the queue. The index may be out
+ // of range, in which case the return value is NULL. The returned pointer will
+ // only be valid until another message is received or the list is cleared.
+ const Message* GetMessageAt(size_t index) const;
+
+ // Returns the first message with the given ID in the queue. If there is no
+ // message with the given ID, returns NULL. The returned pointer will only be
+ // valid until another message is received or the list is cleared.
+ const Message* GetFirstMessageMatching(uint32 id) const;
+
+ // Returns the message with the given ID in the queue. If there is no such
+ // message or there is more than one of that message, this will return NULL
+ // (with the expectation that you'll do an ASSERT_TRUE() on the result).
+ // The returned pointer will only be valid until another message is received
+ // or the list is cleared.
+ const Message* GetUniqueMessageMatching(uint32 id) const;
+
+ private:
+ // The actual list of received messages.
+ std::vector<Message> messages_;
+
+ DISALLOW_COPY_AND_ASSIGN(TestSink);
+};
+
+} // namespace IPC
+
+#endif // CHROME_COMMON_IPC_TEST_SINK_H_
diff --git a/chrome/common/json_pref_store.cc b/chrome/common/json_pref_store.cc
new file mode 100644
index 0000000..9acfcb2
--- /dev/null
+++ b/chrome/common/json_pref_store.cc
@@ -0,0 +1,130 @@
+// Copyright (c) 2010 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/common/json_pref_store.h"
+
+#include <algorithm>
+
+#include "base/file_util.h"
+#include "base/values.h"
+#include "chrome/common/json_value_serializer.h"
+
+namespace {
+
+// Some extensions we'll tack on to copies of the Preferences files.
+const FilePath::CharType* kBadExtension = FILE_PATH_LITERAL("bad");
+
+} // namespace
+
+JsonPrefStore::JsonPrefStore(const FilePath& filename,
+ base::MessageLoopProxy* file_message_loop_proxy)
+ : path_(filename),
+ prefs_(new DictionaryValue()),
+ read_only_(false),
+ writer_(filename, file_message_loop_proxy) {
+}
+
+JsonPrefStore::~JsonPrefStore() {
+ if (writer_.HasPendingWrite() && !read_only_)
+ writer_.DoScheduledWrite();
+}
+
+PrefStore::PrefReadError JsonPrefStore::ReadPrefs() {
+ JSONFileValueSerializer serializer(path_);
+
+ int error_code = 0;
+ std::string error_msg;
+ scoped_ptr<Value> value(serializer.Deserialize(&error_code, &error_msg));
+ if (!value.get()) {
+#if defined(GOOGLE_CHROME_BUILD)
+ // This log could be used for more detailed client-side error diagnosis,
+ // but since this triggers often with unit tests, we need to disable it
+ // in non-official builds.
+ PLOG(ERROR) << "Error reading Preferences: " << error_msg << " " <<
+ path_.value();
+#endif
+ PrefReadError error;
+ switch (error_code) {
+ case JSONFileValueSerializer::JSON_ACCESS_DENIED:
+ // If the file exists but is simply unreadable, put the file into a
+ // state where we don't try to save changes. Otherwise, we could
+ // clobber the existing prefs.
+ error = PREF_READ_ERROR_ACCESS_DENIED;
+ read_only_ = true;
+ break;
+ case JSONFileValueSerializer::JSON_CANNOT_READ_FILE:
+ error = PREF_READ_ERROR_FILE_OTHER;
+ read_only_ = true;
+ break;
+ case JSONFileValueSerializer::JSON_FILE_LOCKED:
+ error = PREF_READ_ERROR_FILE_LOCKED;
+ read_only_ = true;
+ break;
+ case JSONFileValueSerializer::JSON_NO_SUCH_FILE:
+ // If the file just doesn't exist, maybe this is first run. In any case
+ // there's no harm in writing out default prefs in this case.
+ error = PREF_READ_ERROR_NO_FILE;
+ break;
+ default:
+ error = PREF_READ_ERROR_JSON_PARSE;
+ // JSON errors indicate file corruption of some sort.
+ // Since the file is corrupt, move it to the side and continue with
+ // empty preferences. This will result in them losing their settings.
+ // We keep the old file for possible support and debugging assistance
+ // as well as to detect if they're seeing these errors repeatedly.
+ // TODO(erikkay) Instead, use the last known good file.
+ FilePath bad = path_.ReplaceExtension(kBadExtension);
+
+ // If they've ever had a parse error before, put them in another bucket.
+ // TODO(erikkay) if we keep this error checking for very long, we may
+ // want to differentiate between recent and long ago errors.
+ if (file_util::PathExists(bad))
+ error = PREF_READ_ERROR_JSON_REPEAT;
+ file_util::Move(path_, bad);
+ break;
+ }
+ return error;
+ }
+
+ // Preferences should always have a dictionary root.
+ if (!value->IsType(Value::TYPE_DICTIONARY)) {
+ // See comment for the default case above.
+ read_only_ = true;
+ return PREF_READ_ERROR_JSON_TYPE;
+ }
+
+ prefs_.reset(static_cast<DictionaryValue*>(value.release()));
+
+ return PREF_READ_ERROR_NONE;
+}
+
+bool JsonPrefStore::WritePrefs() {
+ std::string data;
+ if (!SerializeData(&data))
+ return false;
+
+ // Lie about our ability to save.
+ if (read_only_)
+ return true;
+
+ writer_.WriteNow(data);
+ return true;
+}
+
+void JsonPrefStore::ScheduleWritePrefs() {
+ if (read_only_)
+ return;
+
+ writer_.ScheduleWrite(this);
+}
+
+bool JsonPrefStore::SerializeData(std::string* output) {
+ // TODO(tc): Do we want to prune webkit preferences that match the default
+ // value?
+ JSONStringValueSerializer serializer(output);
+ serializer.set_pretty_print(true);
+ scoped_ptr<DictionaryValue> copy(prefs_->DeepCopyWithoutEmptyChildren());
+ return serializer.Serialize(*(copy.get()));
+}
+
diff --git a/chrome/common/json_pref_store.h b/chrome/common/json_pref_store.h
new file mode 100644
index 0000000..70f5dee
--- /dev/null
+++ b/chrome/common/json_pref_store.h
@@ -0,0 +1,56 @@
+// Copyright (c) 2010 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_COMMON_JSON_PREF_STORE_H_
+#define CHROME_COMMON_JSON_PREF_STORE_H_
+
+#include <string>
+
+#include "base/scoped_ptr.h"
+#include "chrome/common/pref_store.h"
+#include "chrome/common/important_file_writer.h"
+
+namespace base {
+class MessageLoopProxy;
+}
+
+class DictionaryValue;
+class FilePath;
+
+class JsonPrefStore : public PrefStore,
+ public ImportantFileWriter::DataSerializer {
+ public:
+ // |file_message_loop_proxy| is the MessageLoopProxy for a thread on which
+ // file I/O can be done.
+ JsonPrefStore(const FilePath& pref_filename,
+ base::MessageLoopProxy* file_message_loop_proxy);
+ virtual ~JsonPrefStore();
+
+ // PrefStore methods:
+ virtual bool ReadOnly() { return read_only_; }
+
+ virtual DictionaryValue* prefs() { return prefs_.get(); }
+
+ virtual PrefReadError ReadPrefs();
+
+ virtual bool WritePrefs();
+
+ virtual void ScheduleWritePrefs();
+
+ // ImportantFileWriter::DataSerializer methods:
+ virtual bool SerializeData(std::string* data);
+
+ private:
+ FilePath path_;
+
+ scoped_ptr<DictionaryValue> prefs_;
+
+ bool read_only_;
+
+ // Helper for safely writing pref data.
+ ImportantFileWriter writer_;
+};
+
+#endif // CHROME_COMMON_JSON_PREF_STORE_H_
+
diff --git a/chrome/common/json_pref_store_unittest.cc b/chrome/common/json_pref_store_unittest.cc
new file mode 100644
index 0000000..7d00030
--- /dev/null
+++ b/chrome/common/json_pref_store_unittest.cc
@@ -0,0 +1,150 @@
+// Copyright (c) 2010 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 "app/test/data/resource.h"
+#include "base/file_util.h"
+#include "base/message_loop.h"
+#include "base/message_loop_proxy.h"
+#include "base/path_service.h"
+#include "base/scoped_ptr.h"
+#include "base/string_util.h"
+#include "base/thread.h"
+#include "base/utf_string_conversions.h"
+#include "base/values.h"
+#include "chrome/common/json_pref_store.h"
+#include "chrome/common/chrome_paths.h"
+#include "chrome/common/pref_names.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+class JsonPrefStoreTest : public testing::Test {
+ protected:
+ virtual void SetUp() {
+ message_loop_proxy_ = base::MessageLoopProxy::CreateForCurrentThread();
+ // Name a subdirectory of the temp directory.
+ ASSERT_TRUE(PathService::Get(base::DIR_TEMP, &test_dir_));
+ test_dir_ = test_dir_.AppendASCII("JsonPrefStoreTest");
+
+ // Create a fresh, empty copy of this directory.
+ file_util::Delete(test_dir_, true);
+ file_util::CreateDirectory(test_dir_);
+
+ ASSERT_TRUE(PathService::Get(chrome::DIR_TEST_DATA, &data_dir_));
+ data_dir_ = data_dir_.AppendASCII("pref_service");
+ ASSERT_TRUE(file_util::PathExists(data_dir_));
+ }
+
+ virtual void TearDown() {
+ // Clean up test directory
+ ASSERT_TRUE(file_util::Delete(test_dir_, true));
+ ASSERT_FALSE(file_util::PathExists(test_dir_));
+ }
+
+ // the path to temporary directory used to contain the test operations
+ FilePath test_dir_;
+ // the path to the directory where the test data is stored
+ FilePath data_dir_;
+ // A message loop that we can use as the file thread message loop.
+ MessageLoop message_loop_;
+ scoped_refptr<base::MessageLoopProxy> message_loop_proxy_;
+};
+
+// Test fallback behavior for a nonexistent file.
+TEST_F(JsonPrefStoreTest, NonExistentFile) {
+ FilePath bogus_input_file = data_dir_.AppendASCII("read.txt");
+ ASSERT_FALSE(file_util::PathExists(bogus_input_file));
+ JsonPrefStore pref_store(bogus_input_file, message_loop_proxy_.get());
+ EXPECT_EQ(PrefStore::PREF_READ_ERROR_NO_FILE, pref_store.ReadPrefs());
+ EXPECT_FALSE(pref_store.ReadOnly());
+ EXPECT_TRUE(pref_store.prefs()->empty());
+}
+
+// Test fallback behavior for an invalid file.
+TEST_F(JsonPrefStoreTest, InvalidFile) {
+ FilePath invalid_file_original = data_dir_.AppendASCII("invalid.json");
+ FilePath invalid_file = test_dir_.AppendASCII("invalid.json");
+ ASSERT_TRUE(file_util::CopyFile(invalid_file_original, invalid_file));
+ JsonPrefStore pref_store(invalid_file, message_loop_proxy_.get());
+ EXPECT_EQ(PrefStore::PREF_READ_ERROR_JSON_PARSE, pref_store.ReadPrefs());
+ EXPECT_FALSE(pref_store.ReadOnly());
+ EXPECT_TRUE(pref_store.prefs()->empty());
+
+ // The file should have been moved aside.
+ EXPECT_FALSE(file_util::PathExists(invalid_file));
+ FilePath moved_aside = test_dir_.AppendASCII("invalid.bad");
+ EXPECT_TRUE(file_util::PathExists(moved_aside));
+ EXPECT_TRUE(file_util::TextContentsEqual(invalid_file_original,
+ moved_aside));
+}
+
+TEST_F(JsonPrefStoreTest, Basic) {
+ ASSERT_TRUE(file_util::CopyFile(data_dir_.AppendASCII("read.json"),
+ test_dir_.AppendASCII("write.json")));
+
+ // Test that the persistent value can be loaded.
+ FilePath input_file = test_dir_.AppendASCII("write.json");
+ ASSERT_TRUE(file_util::PathExists(input_file));
+ JsonPrefStore pref_store(input_file, message_loop_proxy_.get());
+ ASSERT_EQ(PrefStore::PREF_READ_ERROR_NONE, pref_store.ReadPrefs());
+ ASSERT_FALSE(pref_store.ReadOnly());
+ DictionaryValue* prefs = pref_store.prefs();
+
+ // The JSON file looks like this:
+ // {
+ // "homepage": "http://www.cnn.com",
+ // "some_directory": "/usr/local/",
+ // "tabs": {
+ // "new_windows_in_tabs": true,
+ // "max_tabs": 20
+ // }
+ // }
+
+ const wchar_t kNewWindowsInTabs[] = L"tabs.new_windows_in_tabs";
+ const wchar_t kMaxTabs[] = L"tabs.max_tabs";
+ const wchar_t kLongIntPref[] = L"long_int.pref";
+
+ std::wstring cnn(L"http://www.cnn.com");
+
+ std::wstring string_value;
+ EXPECT_TRUE(prefs->GetString(prefs::kHomePage, &string_value));
+ EXPECT_EQ(cnn, string_value);
+
+ const wchar_t kSomeDirectory[] = L"some_directory";
+
+ FilePath::StringType path;
+ EXPECT_TRUE(prefs->GetString(kSomeDirectory, &path));
+ EXPECT_EQ(FilePath::StringType(FILE_PATH_LITERAL("/usr/local/")), path);
+ FilePath some_path(FILE_PATH_LITERAL("/usr/sbin/"));
+ prefs->SetString(kSomeDirectory, some_path.value());
+ EXPECT_TRUE(prefs->GetString(kSomeDirectory, &path));
+ EXPECT_EQ(some_path.value(), path);
+
+ // Test reading some other data types from sub-dictionaries.
+ bool boolean;
+ EXPECT_TRUE(prefs->GetBoolean(kNewWindowsInTabs, &boolean));
+ EXPECT_TRUE(boolean);
+
+ prefs->SetBoolean(kNewWindowsInTabs, false);
+ EXPECT_TRUE(prefs->GetBoolean(kNewWindowsInTabs, &boolean));
+ EXPECT_FALSE(boolean);
+
+ int integer;
+ EXPECT_TRUE(prefs->GetInteger(kMaxTabs, &integer));
+ EXPECT_EQ(20, integer);
+ prefs->SetInteger(kMaxTabs, 10);
+ EXPECT_TRUE(prefs->GetInteger(kMaxTabs, &integer));
+ EXPECT_EQ(10, integer);
+
+ prefs->SetString(kLongIntPref, Int64ToWString(214748364842LL));
+ EXPECT_TRUE(prefs->GetString(kLongIntPref, &string_value));
+ EXPECT_EQ(214748364842LL, StringToInt64(WideToUTF16Hack(string_value)));
+
+ // Serialize and compare to expected output.
+ FilePath output_file = input_file;
+ FilePath golden_output_file = data_dir_.AppendASCII("write.golden.json");
+ ASSERT_TRUE(file_util::PathExists(golden_output_file));
+ ASSERT_TRUE(pref_store.WritePrefs());
+ MessageLoop::current()->RunAllPending();
+ EXPECT_TRUE(file_util::TextContentsEqual(golden_output_file, output_file));
+ ASSERT_TRUE(file_util::Delete(output_file, false));
+}
diff --git a/chrome/common/json_value_serializer.cc b/chrome/common/json_value_serializer.cc
new file mode 100644
index 0000000..df92afd
--- /dev/null
+++ b/chrome/common/json_value_serializer.cc
@@ -0,0 +1,108 @@
+// Copyright (c) 2006-2008 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/common/json_value_serializer.h"
+
+#include "base/file_util.h"
+#include "base/json/json_reader.h"
+#include "base/json/json_writer.h"
+#include "base/string_util.h"
+
+const char* JSONFileValueSerializer::kAccessDenied = "Access denied.";
+const char* JSONFileValueSerializer::kCannotReadFile = "Can't read file.";
+const char* JSONFileValueSerializer::kFileLocked = "File locked.";
+const char* JSONFileValueSerializer::kNoSuchFile = "File doesn't exist.";
+
+JSONStringValueSerializer::~JSONStringValueSerializer() {}
+
+bool JSONStringValueSerializer::Serialize(const Value& root) {
+ if (!json_string_ || initialized_with_const_string_)
+ return false;
+
+ base::JSONWriter::Write(&root, pretty_print_, json_string_);
+ return true;
+}
+
+Value* JSONStringValueSerializer::Deserialize(int* error_code,
+ std::string* error_str) {
+ if (!json_string_)
+ return NULL;
+
+ return base::JSONReader::ReadAndReturnError(*json_string_,
+ allow_trailing_comma_,
+ error_code,
+ error_str);
+}
+
+/******* File Serializer *******/
+
+bool JSONFileValueSerializer::Serialize(const Value& root) {
+ std::string json_string;
+ JSONStringValueSerializer serializer(&json_string);
+ serializer.set_pretty_print(true);
+ bool result = serializer.Serialize(root);
+ if (!result)
+ return false;
+
+ int data_size = static_cast<int>(json_string.size());
+ if (file_util::WriteFile(json_file_path_,
+ json_string.data(),
+ data_size) != data_size)
+ return false;
+
+ return true;
+}
+
+int JSONFileValueSerializer::ReadFileToString(std::string* json_string) {
+ DCHECK(json_string);
+ if (!file_util::ReadFileToString(json_file_path_, json_string)) {
+#if defined(OS_WIN)
+ int error = ::GetLastError();
+ if (error == ERROR_SHARING_VIOLATION || error == ERROR_LOCK_VIOLATION) {
+ return JSON_FILE_LOCKED;
+ } else if (error == ERROR_ACCESS_DENIED) {
+ return JSON_ACCESS_DENIED;
+ }
+#endif
+ if (!file_util::PathExists(json_file_path_))
+ return JSON_NO_SUCH_FILE;
+ else
+ return JSON_CANNOT_READ_FILE;
+ }
+ return JSON_NO_ERROR;
+}
+
+const char* JSONFileValueSerializer::GetErrorMessageForCode(int error_code) {
+ switch (error_code) {
+ case JSON_NO_ERROR:
+ return "";
+ case JSON_ACCESS_DENIED:
+ return kAccessDenied;
+ case JSON_CANNOT_READ_FILE:
+ return kCannotReadFile;
+ case JSON_FILE_LOCKED:
+ return kFileLocked;
+ case JSON_NO_SUCH_FILE:
+ return kNoSuchFile;
+ default:
+ NOTREACHED();
+ return "";
+ }
+}
+
+Value* JSONFileValueSerializer::Deserialize(int* error_code,
+ std::string* error_str) {
+ std::string json_string;
+ int error = ReadFileToString(&json_string);
+ if (error != JSON_NO_ERROR) {
+ if (error_code)
+ *error_code = error;
+ if (error_str)
+ *error_str = GetErrorMessageForCode(error);
+ return NULL;
+ }
+
+ JSONStringValueSerializer serializer(json_string);
+ return serializer.Deserialize(error_code, error_str);
+}
diff --git a/chrome/common/json_value_serializer.h b/chrome/common/json_value_serializer.h
new file mode 100644
index 0000000..7919cfe
--- /dev/null
+++ b/chrome/common/json_value_serializer.h
@@ -0,0 +1,127 @@
+// Copyright (c) 2009 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_COMMON_JSON_VALUE_SERIALIZER_H_
+#define CHROME_COMMON_JSON_VALUE_SERIALIZER_H_
+
+#include <string>
+
+#include "base/basictypes.h"
+#include "base/file_path.h"
+#include "base/values.h"
+
+class JSONStringValueSerializer : public ValueSerializer {
+ public:
+ // json_string is the string that will be source of the deserialization
+ // or the destination of the serialization. The caller of the constructor
+ // retains ownership of the string.
+ explicit JSONStringValueSerializer(std::string* json_string)
+ : json_string_(json_string),
+ initialized_with_const_string_(false),
+ pretty_print_(false),
+ allow_trailing_comma_(false) {
+ }
+
+ // This version allows initialization with a const string reference for
+ // deserialization only.
+ explicit JSONStringValueSerializer(const std::string& json_string)
+ : json_string_(&const_cast<std::string&>(json_string)),
+ initialized_with_const_string_(true),
+ pretty_print_(false),
+ allow_trailing_comma_(false) {
+ }
+
+ ~JSONStringValueSerializer();
+
+ // Attempt to serialize the data structure represented by Value into
+ // JSON. If the return value is true, the result will have been written
+ // into the string passed into the constructor.
+ bool Serialize(const Value& root);
+
+ // Attempt to deserialize the data structure encoded in the string passed
+ // in to the constructor into a structure of Value objects. If the return
+ // value is NULL, and if |error_code| is non-null, |error_code| will
+ // contain an integer error code (either JsonFileError or JsonParseError).
+ // If |error_message| is non-null, it will be filled in with a formatted
+ // error message including the location of the error if appropriate.
+ // The caller takes ownership of the returned value.
+ Value* Deserialize(int* error_code, std::string* error_message);
+
+ void set_pretty_print(bool new_value) { pretty_print_ = new_value; }
+ bool pretty_print() { return pretty_print_; }
+
+ void set_allow_trailing_comma(bool new_value) {
+ allow_trailing_comma_ = new_value;
+ }
+
+ private:
+ std::string* json_string_;
+ bool initialized_with_const_string_;
+ bool pretty_print_; // If true, serialization will span multiple lines.
+ // If true, deserialization will allow trailing commas.
+ bool allow_trailing_comma_;
+
+ DISALLOW_COPY_AND_ASSIGN(JSONStringValueSerializer);
+};
+
+class JSONFileValueSerializer : public ValueSerializer {
+ public:
+ // json_file_patch is the path of a file that will be source of the
+ // deserialization or the destination of the serialization.
+ // When deserializing, the file should exist, but when serializing, the
+ // serializer will attempt to create the file at the specified location.
+ explicit JSONFileValueSerializer(const FilePath& json_file_path)
+ : json_file_path_(json_file_path) {}
+
+ ~JSONFileValueSerializer() {}
+
+ // DO NOT USE except in unit tests to verify the file was written properly.
+ // We should never serialize directly to a file since this will block the
+ // thread. Instead, serialize to a string and write to the file you want on
+ // the file thread.
+ //
+ // Attempt to serialize the data structure represented by Value into
+ // JSON. If the return value is true, the result will have been written
+ // into the file whose name was passed into the constructor.
+ bool Serialize(const Value& root);
+
+ // Attempt to deserialize the data structure encoded in the file passed
+ // in to the constructor into a structure of Value objects. If the return
+ // value is NULL, and if |error_code| is non-null, |error_code| will
+ // contain an integer error code (either JsonFileError or JsonParseError).
+ // If |error_message| is non-null, it will be filled in with a formatted
+ // error message including the location of the error if appropriate.
+ // The caller takes ownership of the returned value.
+ Value* Deserialize(int* error_code, std::string* error_message);
+
+ // This enum is designed to safely overlap with JSONReader::JsonParseError.
+ enum JsonFileError {
+ JSON_NO_ERROR = 0,
+ JSON_ACCESS_DENIED = 1000,
+ JSON_CANNOT_READ_FILE,
+ JSON_FILE_LOCKED,
+ JSON_NO_SUCH_FILE
+ };
+
+ // File-specific error messages that can be returned.
+ static const char* kAccessDenied;
+ static const char* kCannotReadFile;
+ static const char* kFileLocked;
+ static const char* kNoSuchFile;
+
+ // Convert an error code into an error message. |error_code| is assumed to
+ // be a JsonFileError.
+ static const char* GetErrorMessageForCode(int error_code);
+
+ private:
+ FilePath json_file_path_;
+
+ // A wrapper for file_util::ReadFileToString which returns a non-zero
+ // JsonFileError if there were file errors.
+ int ReadFileToString(std::string* json_string);
+
+ DISALLOW_IMPLICIT_CONSTRUCTORS(JSONFileValueSerializer);
+};
+
+#endif // CHROME_COMMON_JSON_VALUE_SERIALIZER_H_
diff --git a/chrome/common/json_value_serializer_perftest.cc b/chrome/common/json_value_serializer_perftest.cc
new file mode 100644
index 0000000..504ddb2
--- /dev/null
+++ b/chrome/common/json_value_serializer_perftest.cc
@@ -0,0 +1,90 @@
+// Copyright (c) 2006-2008 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 <vector>
+
+#include "base/file_util.h"
+#include "base/path_service.h"
+#include "base/perftimer.h"
+#include "base/string_util.h"
+#include "base/values.h"
+#include "chrome/common/chrome_paths.h"
+#include "chrome/common/json_value_serializer.h"
+#include "chrome/common/logging_chrome.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+namespace {
+class JSONValueSerializerTests : public testing::Test {
+ protected:
+ virtual void SetUp() {
+ static const char* const kTestFilenames[] = {
+ "serializer_nested_test.js",
+ "serializer_test.js",
+ "serializer_test_nowhitespace.js",
+ };
+
+ // Load test cases
+ for (size_t i = 0; i < arraysize(kTestFilenames); ++i) {
+ FilePath filename;
+ EXPECT_TRUE(PathService::Get(chrome::DIR_TEST_DATA, &filename));
+ filename = filename.AppendASCII(kTestFilenames[i]);
+
+ std::string test_case;
+ EXPECT_TRUE(file_util::ReadFileToString(filename, &test_case));
+ test_cases_.push_back(test_case);
+ }
+ }
+
+ // Holds json strings to be tested.
+ std::vector<std::string> test_cases_;
+};
+
+} // namespace
+
+// Test deserialization of a json string into a Value object. We run the test
+// using 3 sample strings for both the current decoder and jsoncpp's decoder.
+TEST_F(JSONValueSerializerTests, Reading) {
+ printf("\n");
+ const int kIterations = 100000;
+
+ // Test chrome json implementation
+ PerfTimeLogger chrome_timer("chrome");
+ for (int i = 0; i < kIterations; ++i) {
+ for (size_t j = 0; j < test_cases_.size(); ++j) {
+ JSONStringValueSerializer reader(test_cases_[j]);
+ scoped_ptr<Value> root(reader.Deserialize(NULL, NULL));
+ ASSERT_TRUE(root.get());
+ }
+ }
+ chrome_timer.Done();
+}
+
+TEST_F(JSONValueSerializerTests, CompactWriting) {
+ printf("\n");
+ const int kIterations = 100000;
+ // Convert test cases to Value objects.
+ std::vector<Value*> test_cases;
+ for (size_t i = 0; i < test_cases_.size(); ++i) {
+ JSONStringValueSerializer reader(test_cases_[i]);
+ Value* root = reader.Deserialize(NULL, NULL);
+ ASSERT_TRUE(root);
+ test_cases.push_back(root);
+ }
+
+ PerfTimeLogger chrome_timer("chrome");
+ for (int i = 0; i < kIterations; ++i) {
+ for (size_t j = 0; j < test_cases.size(); ++j) {
+ std::string json;
+ JSONStringValueSerializer reader(&json);
+ ASSERT_TRUE(reader.Serialize(*test_cases[j]));
+ }
+ }
+ chrome_timer.Done();
+
+ // Clean up test cases.
+ for (size_t i = 0; i < test_cases.size(); ++i) {
+ delete test_cases[i];
+ test_cases[i] = NULL;
+ }
+}
diff --git a/chrome/common/json_value_serializer_unittest.cc b/chrome/common/json_value_serializer_unittest.cc
new file mode 100644
index 0000000..3f40dcc
--- /dev/null
+++ b/chrome/common/json_value_serializer_unittest.cc
@@ -0,0 +1,348 @@
+// Copyright (c) 2006-2008 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/file_util.h"
+#include "base/json/json_reader.h"
+#include "base/json/json_writer.h"
+#include "base/path_service.h"
+#include "base/string_util.h"
+#include "base/values.h"
+#include "chrome/common/chrome_paths.h"
+#include "chrome/common/json_value_serializer.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+TEST(JSONValueSerializerTest, Roundtrip) {
+ const std::string original_serialization =
+ "{\"bool\":true,\"int\":42,\"list\":[1,2],\"null\":null,\"real\":3.14}";
+ JSONStringValueSerializer serializer(original_serialization);
+ scoped_ptr<Value> root(serializer.Deserialize(NULL, NULL));
+ ASSERT_TRUE(root.get());
+ ASSERT_TRUE(root->IsType(Value::TYPE_DICTIONARY));
+
+ DictionaryValue* root_dict = static_cast<DictionaryValue*>(root.get());
+
+ Value* null_value = NULL;
+ ASSERT_TRUE(root_dict->Get(L"null", &null_value));
+ ASSERT_TRUE(null_value);
+ ASSERT_TRUE(null_value->IsType(Value::TYPE_NULL));
+
+ bool bool_value = false;
+ ASSERT_TRUE(root_dict->GetBoolean(L"bool", &bool_value));
+ ASSERT_TRUE(bool_value);
+
+ int int_value = 0;
+ ASSERT_TRUE(root_dict->GetInteger(L"int", &int_value));
+ ASSERT_EQ(42, int_value);
+
+ double real_value = 0.0;
+ ASSERT_TRUE(root_dict->GetReal(L"real", &real_value));
+ ASSERT_DOUBLE_EQ(3.14, real_value);
+
+ // We shouldn't be able to write using this serializer, since it was
+ // initialized with a const string.
+ ASSERT_FALSE(serializer.Serialize(*root_dict));
+
+ std::string test_serialization = "";
+ JSONStringValueSerializer mutable_serializer(&test_serialization);
+ ASSERT_TRUE(mutable_serializer.Serialize(*root_dict));
+ ASSERT_EQ(original_serialization, test_serialization);
+
+ mutable_serializer.set_pretty_print(true);
+ ASSERT_TRUE(mutable_serializer.Serialize(*root_dict));
+ // JSON output uses a different newline style on Windows than on other
+ // platforms.
+#if defined(OS_WIN)
+#define JSON_NEWLINE "\r\n"
+#else
+#define JSON_NEWLINE "\n"
+#endif
+ const std::string pretty_serialization =
+ "{" JSON_NEWLINE
+ " \"bool\": true," JSON_NEWLINE
+ " \"int\": 42," JSON_NEWLINE
+ " \"list\": [ 1, 2 ]," JSON_NEWLINE
+ " \"null\": null," JSON_NEWLINE
+ " \"real\": 3.14" JSON_NEWLINE
+ "}" JSON_NEWLINE;
+#undef JSON_NEWLINE
+ ASSERT_EQ(pretty_serialization, test_serialization);
+}
+
+TEST(JSONValueSerializerTest, StringEscape) {
+ std::wstring all_chars;
+ for (int i = 1; i < 256; ++i) {
+ all_chars += static_cast<wchar_t>(i);
+ }
+ // Generated in in Firefox using the following js (with an extra backslash for
+ // double quote):
+ // var s = '';
+ // for (var i = 1; i < 256; ++i) { s += String.fromCharCode(i); }
+ // uneval(s).replace(/\\/g, "\\\\");
+ std::string all_chars_expected =
+ "\\u0001\\u0002\\u0003\\u0004\\u0005\\u0006\\u0007\\b\\t\\n\\u000B\\f\\r"
+ "\\u000E\\u000F\\u0010\\u0011\\u0012\\u0013\\u0014\\u0015\\u0016\\u0017"
+ "\\u0018\\u0019\\u001A\\u001B\\u001C\\u001D\\u001E\\u001F !\\\""
+ "#$%&'()*+,-./0123456789:;\\u003C=\\u003E?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\"
+ "\\]^_`abcdefghijklmnopqrstuvwxyz{|}~\\u007F\\u0080\\u0081\\u0082\\u0083"
+ "\\u0084\\u0085\\u0086\\u0087\\u0088\\u0089\\u008A\\u008B\\u008C\\u008D"
+ "\\u008E\\u008F\\u0090\\u0091\\u0092\\u0093\\u0094\\u0095\\u0096\\u0097"
+ "\\u0098\\u0099\\u009A\\u009B\\u009C\\u009D\\u009E\\u009F\\u00A0\\u00A1"
+ "\\u00A2\\u00A3\\u00A4\\u00A5\\u00A6\\u00A7\\u00A8\\u00A9\\u00AA\\u00AB"
+ "\\u00AC\\u00AD\\u00AE\\u00AF\\u00B0\\u00B1\\u00B2\\u00B3\\u00B4\\u00B5"
+ "\\u00B6\\u00B7\\u00B8\\u00B9\\u00BA\\u00BB\\u00BC\\u00BD\\u00BE\\u00BF"
+ "\\u00C0\\u00C1\\u00C2\\u00C3\\u00C4\\u00C5\\u00C6\\u00C7\\u00C8\\u00C9"
+ "\\u00CA\\u00CB\\u00CC\\u00CD\\u00CE\\u00CF\\u00D0\\u00D1\\u00D2\\u00D3"
+ "\\u00D4\\u00D5\\u00D6\\u00D7\\u00D8\\u00D9\\u00DA\\u00DB\\u00DC\\u00DD"
+ "\\u00DE\\u00DF\\u00E0\\u00E1\\u00E2\\u00E3\\u00E4\\u00E5\\u00E6\\u00E7"
+ "\\u00E8\\u00E9\\u00EA\\u00EB\\u00EC\\u00ED\\u00EE\\u00EF\\u00F0\\u00F1"
+ "\\u00F2\\u00F3\\u00F4\\u00F5\\u00F6\\u00F7\\u00F8\\u00F9\\u00FA\\u00FB"
+ "\\u00FC\\u00FD\\u00FE\\u00FF";
+
+ std::string expected_output = "{\"all_chars\":\"" + all_chars_expected +
+ "\"}";
+ // Test JSONWriter interface
+ std::string output_js;
+ DictionaryValue valueRoot;
+ valueRoot.SetString(L"all_chars", all_chars);
+ base::JSONWriter::Write(&valueRoot, false, &output_js);
+ ASSERT_EQ(expected_output, output_js);
+
+ // Test JSONValueSerializer interface (uses JSONWriter).
+ JSONStringValueSerializer serializer(&output_js);
+ ASSERT_TRUE(serializer.Serialize(valueRoot));
+ ASSERT_EQ(expected_output, output_js);
+}
+
+TEST(JSONValueSerializerTest, UnicodeStrings) {
+ // unicode string json -> escaped ascii text
+ DictionaryValue root;
+ std::wstring test(L"\x7F51\x9875");
+ root.SetString(L"web", test);
+
+ std::string expected = "{\"web\":\"\\u7F51\\u9875\"}";
+
+ std::string actual;
+ JSONStringValueSerializer serializer(&actual);
+ ASSERT_TRUE(serializer.Serialize(root));
+ ASSERT_EQ(expected, actual);
+
+ // escaped ascii text -> json
+ JSONStringValueSerializer deserializer(expected);
+ scoped_ptr<Value> deserial_root(deserializer.Deserialize(NULL, NULL));
+ ASSERT_TRUE(deserial_root.get());
+ DictionaryValue* dict_root =
+ static_cast<DictionaryValue*>(deserial_root.get());
+ std::wstring web_value;
+ ASSERT_TRUE(dict_root->GetString(L"web", &web_value));
+ ASSERT_EQ(test, web_value);
+}
+
+TEST(JSONValueSerializerTest, HexStrings) {
+ // hex string json -> escaped ascii text
+ DictionaryValue root;
+ std::wstring test(L"\x01\x02");
+ root.SetString(L"test", test);
+
+ std::string expected = "{\"test\":\"\\u0001\\u0002\"}";
+
+ std::string actual;
+ JSONStringValueSerializer serializer(&actual);
+ ASSERT_TRUE(serializer.Serialize(root));
+ ASSERT_EQ(expected, actual);
+
+ // escaped ascii text -> json
+ JSONStringValueSerializer deserializer(expected);
+ scoped_ptr<Value> deserial_root(deserializer.Deserialize(NULL, NULL));
+ ASSERT_TRUE(deserial_root.get());
+ DictionaryValue* dict_root =
+ static_cast<DictionaryValue*>(deserial_root.get());
+ std::wstring test_value;
+ ASSERT_TRUE(dict_root->GetString(L"test", &test_value));
+ ASSERT_EQ(test, test_value);
+
+ // Test converting escaped regular chars
+ std::string escaped_chars = "{\"test\":\"\\u0067\\u006f\"}";
+ JSONStringValueSerializer deserializer2(escaped_chars);
+ deserial_root.reset(deserializer2.Deserialize(NULL, NULL));
+ ASSERT_TRUE(deserial_root.get());
+ dict_root = static_cast<DictionaryValue*>(deserial_root.get());
+ ASSERT_TRUE(dict_root->GetString(L"test", &test_value));
+ ASSERT_EQ(std::wstring(L"go"), test_value);
+}
+
+TEST(JSONValueSerializerTest, AllowTrailingComma) {
+ scoped_ptr<Value> root;
+ scoped_ptr<Value> root_expected;
+ std::string test_with_commas("{\"key\": [true,],}");
+ std::string test_no_commas("{\"key\": [true]}");
+
+ JSONStringValueSerializer serializer(test_with_commas);
+ serializer.set_allow_trailing_comma(true);
+ JSONStringValueSerializer serializer_expected(test_no_commas);
+ root.reset(serializer.Deserialize(NULL, NULL));
+ ASSERT_TRUE(root.get());
+ root_expected.reset(serializer_expected.Deserialize(NULL, NULL));
+ ASSERT_TRUE(root_expected.get());
+ ASSERT_TRUE(root->Equals(root_expected.get()));
+}
+
+namespace {
+
+void ValidateJsonList(const std::string& json) {
+ scoped_ptr<Value> root(base::JSONReader::Read(json, false));
+ ASSERT_TRUE(root.get() && root->IsType(Value::TYPE_LIST));
+ ListValue* list = static_cast<ListValue*>(root.get());
+ ASSERT_EQ(1U, list->GetSize());
+ Value* elt = NULL;
+ ASSERT_TRUE(list->Get(0, &elt));
+ int value = 0;
+ ASSERT_TRUE(elt && elt->GetAsInteger(&value));
+ ASSERT_EQ(1, value);
+}
+
+} // namespace
+
+TEST(JSONValueSerializerTest, JSONReaderComments) {
+ ValidateJsonList("[ // 2, 3, ignore me ] \n1 ]");
+ ValidateJsonList("[ /* 2, \n3, ignore me ]*/ \n1 ]");
+ ValidateJsonList("//header\n[ // 2, \n// 3, \n1 ]// footer");
+ ValidateJsonList("/*\n[ // 2, \n// 3, \n1 ]*/[1]");
+ ValidateJsonList("[ 1 /* one */ ] /* end */");
+ ValidateJsonList("[ 1 //// ,2\r\n ]");
+
+ scoped_ptr<Value> root;
+
+ // It's ok to have a comment in a string.
+ root.reset(base::JSONReader::Read("[\"// ok\\n /* foo */ \"]", false));
+ ASSERT_TRUE(root.get() && root->IsType(Value::TYPE_LIST));
+ ListValue* list = static_cast<ListValue*>(root.get());
+ ASSERT_EQ(1U, list->GetSize());
+ Value* elt = NULL;
+ ASSERT_TRUE(list->Get(0, &elt));
+ std::wstring value;
+ ASSERT_TRUE(elt && elt->GetAsString(&value));
+ ASSERT_EQ(L"// ok\n /* foo */ ", value);
+
+ // You can't nest comments.
+ root.reset(base::JSONReader::Read("/* /* inner */ outer */ [ 1 ]", false));
+ ASSERT_FALSE(root.get());
+
+ // Not a open comment token.
+ root.reset(base::JSONReader::Read("/ * * / [1]", false));
+ ASSERT_FALSE(root.get());
+}
+
+class JSONFileValueSerializerTest : public testing::Test {
+protected:
+ virtual void SetUp() {
+ // Name a subdirectory of the temp directory.
+ ASSERT_TRUE(PathService::Get(base::DIR_TEMP, &test_dir_));
+ test_dir_ =
+ test_dir_.Append(FILE_PATH_LITERAL("JSONFileValueSerializerTest"));
+
+ // Create a fresh, empty copy of this directory.
+ file_util::Delete(test_dir_, true);
+ file_util::CreateDirectory(test_dir_);
+ }
+ virtual void TearDown() {
+ // Clean up test directory
+ ASSERT_TRUE(file_util::Delete(test_dir_, false));
+ ASSERT_FALSE(file_util::PathExists(test_dir_));
+ }
+
+ // the path to temporary directory used to contain the test operations
+ FilePath test_dir_;
+};
+
+TEST_F(JSONFileValueSerializerTest, Roundtrip) {
+ FilePath original_file_path;
+ ASSERT_TRUE(
+ PathService::Get(chrome::DIR_TEST_DATA, &original_file_path));
+ original_file_path =
+ original_file_path.Append(FILE_PATH_LITERAL("serializer_test.js"));
+
+ ASSERT_TRUE(file_util::PathExists(original_file_path));
+
+ JSONFileValueSerializer deserializer(original_file_path);
+ scoped_ptr<Value> root;
+ root.reset(deserializer.Deserialize(NULL, NULL));
+
+ ASSERT_TRUE(root.get());
+ ASSERT_TRUE(root->IsType(Value::TYPE_DICTIONARY));
+
+ DictionaryValue* root_dict = static_cast<DictionaryValue*>(root.get());
+
+ Value* null_value = NULL;
+ ASSERT_TRUE(root_dict->Get(L"null", &null_value));
+ ASSERT_TRUE(null_value);
+ ASSERT_TRUE(null_value->IsType(Value::TYPE_NULL));
+
+ bool bool_value = false;
+ ASSERT_TRUE(root_dict->GetBoolean(L"bool", &bool_value));
+ ASSERT_TRUE(bool_value);
+
+ int int_value = 0;
+ ASSERT_TRUE(root_dict->GetInteger(L"int", &int_value));
+ ASSERT_EQ(42, int_value);
+
+ std::wstring string_value;
+ ASSERT_TRUE(root_dict->GetString(L"string", &string_value));
+ ASSERT_EQ(L"hello", string_value);
+
+ // Now try writing.
+ const FilePath written_file_path =
+ test_dir_.Append(FILE_PATH_LITERAL("test_output.js"));
+
+ ASSERT_FALSE(file_util::PathExists(written_file_path));
+ JSONFileValueSerializer serializer(written_file_path);
+ ASSERT_TRUE(serializer.Serialize(*root));
+ ASSERT_TRUE(file_util::PathExists(written_file_path));
+
+ // Now compare file contents.
+ EXPECT_TRUE(file_util::TextContentsEqual(original_file_path,
+ written_file_path));
+ EXPECT_TRUE(file_util::Delete(written_file_path, false));
+}
+
+TEST_F(JSONFileValueSerializerTest, RoundtripNested) {
+ FilePath original_file_path;
+ ASSERT_TRUE(
+ PathService::Get(chrome::DIR_TEST_DATA, &original_file_path));
+ original_file_path =
+ original_file_path.Append(FILE_PATH_LITERAL("serializer_nested_test.js"));
+
+ ASSERT_TRUE(file_util::PathExists(original_file_path));
+
+ JSONFileValueSerializer deserializer(original_file_path);
+ scoped_ptr<Value> root;
+ root.reset(deserializer.Deserialize(NULL, NULL));
+ ASSERT_TRUE(root.get());
+
+ // Now try writing.
+ FilePath written_file_path =
+ test_dir_.Append(FILE_PATH_LITERAL("test_output.js"));
+
+ ASSERT_FALSE(file_util::PathExists(written_file_path));
+ JSONFileValueSerializer serializer(written_file_path);
+ ASSERT_TRUE(serializer.Serialize(*root));
+ ASSERT_TRUE(file_util::PathExists(written_file_path));
+
+ // Now compare file contents.
+ EXPECT_TRUE(file_util::TextContentsEqual(original_file_path,
+ written_file_path));
+ EXPECT_TRUE(file_util::Delete(written_file_path, false));
+}
+
+TEST_F(JSONFileValueSerializerTest, NoWhitespace) {
+ FilePath source_file_path;
+ ASSERT_TRUE(PathService::Get(chrome::DIR_TEST_DATA, &source_file_path));
+ source_file_path = source_file_path.Append(
+ FILE_PATH_LITERAL("serializer_test_nowhitespace.js"));
+ ASSERT_TRUE(file_util::PathExists(source_file_path));
+ JSONFileValueSerializer serializer(source_file_path);
+ scoped_ptr<Value> root;
+ root.reset(serializer.Deserialize(NULL, NULL));
+ ASSERT_TRUE(root.get());
+}
diff --git a/chrome/common/jstemplate_builder.cc b/chrome/common/jstemplate_builder.cc
new file mode 100644
index 0000000..628edd7
--- /dev/null
+++ b/chrome/common/jstemplate_builder.cc
@@ -0,0 +1,116 @@
+// Copyright (c) 2006-2008 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.
+
+// A helper function for using JsTemplate. See jstemplate_builder.h for more
+// info.
+
+#include "chrome/common/jstemplate_builder.h"
+
+#include "app/resource_bundle.h"
+#include "base/logging.h"
+#include "base/string_util.h"
+#include "chrome/common/json_value_serializer.h"
+
+#include "grit/common_resources.h"
+
+namespace jstemplate_builder {
+
+std::string GetTemplateHtml(const base::StringPiece& html_template,
+ const DictionaryValue* json,
+ const base::StringPiece& template_id) {
+ std::string output(html_template.data(), html_template.size());
+ AppendJsonHtml(json, &output);
+ AppendJsTemplateSourceHtml(&output);
+ AppendJsTemplateProcessHtml(template_id, &output);
+ return output;
+}
+
+std::string GetI18nTemplateHtml(const base::StringPiece& html_template,
+ const DictionaryValue* json) {
+ std::string output(html_template.data(), html_template.size());
+ AppendJsonHtml(json, &output);
+ AppendI18nTemplateSourceHtml(&output);
+ AppendI18nTemplateProcessHtml(&output);
+ return output;
+}
+
+std::string GetTemplatesHtml(const base::StringPiece& html_template,
+ const DictionaryValue* json,
+ const base::StringPiece& template_id) {
+ std::string output(html_template.data(), html_template.size());
+ AppendI18nTemplateSourceHtml(&output);
+ AppendJsTemplateSourceHtml(&output);
+ AppendJsonHtml(json, &output);
+ AppendI18nTemplateProcessHtml(&output);
+ AppendJsTemplateProcessHtml(template_id, &output);
+ return output;
+}
+
+void AppendJsonHtml(const DictionaryValue* json, std::string* output) {
+ // Convert the template data to a json string.
+ DCHECK(json) << "must include json data structure";
+
+ std::string jstext;
+ JSONStringValueSerializer serializer(&jstext);
+ serializer.Serialize(*json);
+ // </ confuses the HTML parser because it could be a </script> tag. So we
+ // replace </ with <\/. The extra \ will be ignored by the JS engine.
+ ReplaceSubstringsAfterOffset(&jstext, 0, "</", "<\\/");
+
+ output->append("<script>");
+ output->append("var templateData = ");
+ output->append(jstext);
+ output->append(";");
+ output->append("</script>");
+}
+
+void AppendJsTemplateSourceHtml(std::string* output) {
+ // fetch and cache the pointer of the jstemplate resource source text.
+ static const base::StringPiece jstemplate_src(
+ ResourceBundle::GetSharedInstance().GetRawDataResource(
+ IDR_JSTEMPLATE_JS));
+
+ if (jstemplate_src.empty()) {
+ NOTREACHED() << "Unable to get jstemplate src";
+ return;
+ }
+
+ output->append("<script>");
+ output->append(jstemplate_src.data(), jstemplate_src.size());
+ output->append("</script>");
+}
+
+void AppendJsTemplateProcessHtml(const base::StringPiece& template_id,
+ std::string* output) {
+ output->append("<script>");
+ output->append("var tp = document.getElementById('");
+ output->append(template_id.data(), template_id.size());
+ output->append("');");
+ output->append("jstProcess(new JsEvalContext(templateData), tp);");
+ output->append("</script>");
+}
+
+void AppendI18nTemplateSourceHtml(std::string* output) {
+ // fetch and cache the pointer of the jstemplate resource source text.
+ static const base::StringPiece i18n_template_src(
+ ResourceBundle::GetSharedInstance().GetRawDataResource(
+ IDR_I18N_TEMPLATE_JS));
+
+ if (i18n_template_src.empty()) {
+ NOTREACHED() << "Unable to get i18n template src";
+ return;
+ }
+
+ output->append("<script>");
+ output->append(i18n_template_src.data(), i18n_template_src.size());
+ output->append("</script>");
+}
+
+void AppendI18nTemplateProcessHtml(std::string* output) {
+ output->append("<script>");
+ output->append("i18nTemplate.process(document, templateData);");
+ output->append("</script>");
+}
+
+} // namespace jstemplate_builder
diff --git a/chrome/common/jstemplate_builder.h b/chrome/common/jstemplate_builder.h
new file mode 100644
index 0000000..ac8285f
--- /dev/null
+++ b/chrome/common/jstemplate_builder.h
@@ -0,0 +1,69 @@
+// Copyright (c) 2006-2008 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.
+
+// This provides some helper methods for building and rendering an
+// internal html page. The flow is as follows:
+// - instantiate a builder given a webframe that we're going to render content
+// into
+// - load the template html and load the jstemplate javascript into the frame
+// - given a json data object, run the jstemplate javascript which fills in
+// template values
+
+#ifndef CHROME_COMMON_JSTEMPLATE_BUILDER_H_
+#define CHROME_COMMON_JSTEMPLATE_BUILDER_H_
+
+#include <string>
+
+class DictionaryValue;
+namespace base {
+class StringPiece;
+}
+
+namespace jstemplate_builder {
+
+// A helper function that generates a string of HTML to be loaded. The
+// string includes the HTML and the javascript code necessary to generate the
+// full page with support for JsTemplates.
+std::string GetTemplateHtml(const base::StringPiece& html_template,
+ const DictionaryValue* json,
+ const base::StringPiece& template_id);
+
+// A helper function that generates a string of HTML to be loaded. The
+// string includes the HTML and the javascript code necessary to generate the
+// full page with support for i18n Templates.
+std::string GetI18nTemplateHtml(const base::StringPiece& html_template,
+ const DictionaryValue* json);
+
+// A helper function that generates a string of HTML to be loaded. The
+// string includes the HTML and the javascript code necessary to generate the
+// full page with support for both i18n Templates and JsTemplates.
+std::string GetTemplatesHtml(const base::StringPiece& html_template,
+ const DictionaryValue* json,
+ const base::StringPiece& template_id);
+
+// The following functions build up the different parts that the above
+// templates use.
+
+// Appends a script tag with a variable name |templateData| that has the JSON
+// assigned to it.
+void AppendJsonHtml(const DictionaryValue* json, std::string* output);
+
+// Appends the source for JsTemplates in a script tag.
+void AppendJsTemplateSourceHtml(std::string* output);
+
+// Appends the code that processes the JsTemplate with the JSON. You should
+// call AppendJsTemplateSourceHtml and AppendJsonHtml before calling this.
+void AppendJsTemplateProcessHtml(const base::StringPiece& template_id,
+ std::string* output);
+
+// Appends the source for i18n Templates in a script tag.
+void AppendI18nTemplateSourceHtml(std::string* output);
+
+// Appends the code that processes the i18n Template with the JSON. You
+// should call AppendJsTemplateSourceHtml and AppendJsonHtml before calling
+// this.
+void AppendI18nTemplateProcessHtml(std::string* output);
+
+} // namespace jstemplate_builder
+#endif // CHROME_COMMON_JSTEMPLATE_BUILDER_H_
diff --git a/chrome/common/libxml_utils.cc b/chrome/common/libxml_utils.cc
new file mode 100644
index 0000000..f06df72
--- /dev/null
+++ b/chrome/common/libxml_utils.cc
@@ -0,0 +1,143 @@
+// Copyright (c) 2009 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/common/libxml_utils.h"
+
+#include "base/compiler_specific.h"
+#include "base/logging.h"
+#include "base/string_util.h"
+
+#include "libxml/xmlreader.h"
+
+std::string XmlStringToStdString(const xmlChar* xmlstring) {
+ // xmlChar*s are UTF-8, so this cast is safe.
+ if (xmlstring)
+ return std::string(reinterpret_cast<const char*>(xmlstring));
+ else
+ return "";
+}
+
+XmlReader::XmlReader()
+ : reader_(NULL),
+ ALLOW_THIS_IN_INITIALIZER_LIST(
+ error_func_(this, &XmlReader::GenericErrorCallback)) {
+}
+
+XmlReader::~XmlReader() {
+ if (reader_)
+ xmlFreeTextReader(reader_);
+}
+
+// static
+void XmlReader::GenericErrorCallback(void* context, const char* msg, ...) {
+ va_list args;
+ va_start(args, msg);
+
+ XmlReader* reader = static_cast<XmlReader*>(context);
+ reader->errors_.append(StringPrintV(msg, args));
+ va_end(args);
+}
+
+bool XmlReader::Load(const std::string& input) {
+ const int kParseOptions = XML_PARSE_RECOVER | // recover on errors
+ XML_PARSE_NONET; // forbid network access
+ // TODO(evanm): Verify it's OK to pass NULL for the URL and encoding.
+ // The libxml code allows for these, but it's unclear what effect is has.
+ reader_ = xmlReaderForMemory(input.data(), static_cast<int>(input.size()),
+ NULL, NULL, kParseOptions);
+ return reader_ != NULL;
+}
+
+bool XmlReader::LoadFile(const std::string& file_path) {
+
+ const int kParseOptions = XML_PARSE_RECOVER | // recover on errors
+ XML_PARSE_NONET; // forbid network access
+ reader_ = xmlReaderForFile(file_path.c_str(), NULL, kParseOptions);
+ return reader_ != NULL;
+}
+
+bool XmlReader::NodeAttribute(const char* name, std::string* out) {
+ xmlChar* value = xmlTextReaderGetAttribute(reader_, BAD_CAST name);
+ if (!value)
+ return false;
+ *out = XmlStringToStdString(value);
+ xmlFree(value);
+ return true;
+}
+
+bool XmlReader::ReadElementContent(std::string* content) {
+ DCHECK(NodeType() == XML_READER_TYPE_ELEMENT);
+ const int start_depth = Depth();
+
+ if (xmlTextReaderIsEmptyElement(reader_)) {
+ // Empty tag. We succesfully read the content, but it's
+ // empty.
+ *content = "";
+ // Advance past this empty tag.
+ if (!Read())
+ return false;
+ return true;
+ }
+
+ // Advance past opening element tag.
+ if (!Read())
+ return false;
+
+ // Read the content. We read up until we hit a closing tag at the
+ // same level as our starting point.
+ while (NodeType() != XML_READER_TYPE_END_ELEMENT || Depth() != start_depth) {
+ *content += XmlStringToStdString(xmlTextReaderConstValue(reader_));
+ if (!Read())
+ return false;
+ }
+
+ // Advance past ending element tag.
+ DCHECK_EQ(NodeType(), XML_READER_TYPE_END_ELEMENT);
+ if (!Read())
+ return false;
+
+ return true;
+}
+
+bool XmlReader::SkipToElement() {
+ do {
+ switch (NodeType()) {
+ case XML_READER_TYPE_ELEMENT:
+ return true;
+ case XML_READER_TYPE_END_ELEMENT:
+ return false;
+ default:
+ // Skip all other node types.
+ continue;
+ }
+ } while (Read());
+ return false;
+}
+
+
+// XmlWriter functions
+
+XmlWriter::XmlWriter()
+ : writer_(NULL),
+ buffer_(NULL) {}
+
+XmlWriter::~XmlWriter() {
+ if (writer_)
+ xmlFreeTextWriter(writer_);
+ if (buffer_)
+ xmlBufferFree(buffer_);
+}
+
+void XmlWriter::StartWriting() {
+ buffer_ = xmlBufferCreate();
+ writer_ = xmlNewTextWriterMemory(buffer_, 0);
+ xmlTextWriterSetIndent(writer_, 1);
+ xmlTextWriterStartDocument(writer_, NULL, NULL, NULL);
+}
+
+void XmlWriter::StopWriting() {
+ xmlTextWriterEndDocument(writer_);
+ xmlFreeTextWriter(writer_);
+ writer_ = NULL;
+}
diff --git a/chrome/common/libxml_utils.h b/chrome/common/libxml_utils.h
new file mode 100644
index 0000000..1484139
--- /dev/null
+++ b/chrome/common/libxml_utils.h
@@ -0,0 +1,182 @@
+// Copyright (c) 2006-2008 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_COMMON_LIBXML_UTILS_H__
+#define CHROME_COMMON_LIBXML_UTILS_H__
+
+#include <string>
+
+#include "libxml/xmlreader.h"
+#include "libxml/xmlwriter.h"
+
+// Converts a libxml xmlChar* into a UTF-8 std::string.
+// NULL inputs produce an empty string.
+std::string XmlStringToStdString(const xmlChar* xmlstring);
+
+// libxml uses a global error function pointer for reporting errors.
+// A ScopedXmlErrorFunc object lets you change the global error pointer
+// for the duration of the object's lifetime.
+class ScopedXmlErrorFunc {
+ public:
+ ScopedXmlErrorFunc(void* context, xmlGenericErrorFunc func) {
+ old_error_func_ = xmlGenericError;
+ old_error_context_ = xmlGenericErrorContext;
+ xmlSetGenericErrorFunc(context, func);
+ }
+ ~ScopedXmlErrorFunc() {
+ xmlSetGenericErrorFunc(old_error_context_, old_error_func_);
+ }
+
+ private:
+ xmlGenericErrorFunc old_error_func_;
+ void* old_error_context_;
+};
+
+// XmlReader is a wrapper class around libxml's xmlReader,
+// providing a simplified C++ API.
+class XmlReader {
+ public:
+ XmlReader();
+ ~XmlReader();
+
+ // Load a document into the reader from memory. |input| must be UTF-8 and
+ // exist for the lifetime of this object. Returns false on error.
+ // TODO(evanm): handle encodings other than UTF-8?
+ bool Load(const std::string& input);
+
+ // Load a document into the reader from a file. Returns false on error.
+ bool LoadFile(const std::string& file_path);
+
+ // Wrappers around libxml functions -----------------------------------------
+
+ // Read() advances to the next node. Returns false on EOF or error.
+ bool Read() { return xmlTextReaderRead(reader_) == 1; }
+
+ // Next(), when pointing at an opening tag, advances to the node after
+ // the matching closing tag. Returns false on EOF or error.
+ bool Next() { return xmlTextReaderNext(reader_) == 1; }
+
+ // Return the depth in the tree of the current node.
+ int Depth() { return xmlTextReaderDepth(reader_); }
+
+ // Returns the "local" name of the current node.
+ // For a tag like <foo:bar>, this is the string "foo:bar".
+ std::string NodeName() {
+ return XmlStringToStdString(xmlTextReaderConstLocalName(reader_));
+ }
+
+ // When pointing at a tag, retrieves the value of an attribute.
+ // Returns false on failure.
+ // E.g. for <foo bar:baz="a">, NodeAttribute("bar:baz", &value)
+ // returns true and |value| is set to "a".
+ bool NodeAttribute(const char* name, std::string* value);
+
+ // Helper functions not provided by libxml ----------------------------------
+
+ // Return the string content within an element.
+ // "<foo>bar</foo>" is a sequence of three nodes:
+ // (1) open tag, (2) text, (3) close tag.
+ // With the reader currently at (1), this returns the text of (2),
+ // and advances past (3).
+ // Returns false on error.
+ bool ReadElementContent(std::string* content);
+
+ // Skip to the next opening tag, returning false if we reach a closing
+ // tag or EOF first.
+ // If currently on an opening tag, doesn't advance at all.
+ bool SkipToElement();
+
+ // Returns the errors reported by libxml, if any.
+ // (libxml normally just dumps these errors to stderr.)
+ const std::string& errors() const { return errors_; }
+
+ private:
+ // A callback for libxml to report errors.
+ static void GenericErrorCallback(void* context, const char* msg, ...);
+
+ // Returns the libxml node type of the current node.
+ int NodeType() { return xmlTextReaderNodeType(reader_); }
+
+ // The underlying libxml xmlTextReader.
+ xmlTextReaderPtr reader_;
+
+ // error_func_ is used to reassign libxml's global error function
+ // to report errors into |errors_| for the lifetime of this object.
+ ScopedXmlErrorFunc error_func_;
+ std::string errors_;
+};
+
+// XmlWriter is a wrapper class around libxml's xmlWriter,
+// providing a simplified C++ API.
+// StartWriting must be called before other methods, and StopWriting
+// must be called before GetWrittenString() will return results.
+class XmlWriter {
+ public:
+ XmlWriter();
+ ~XmlWriter();
+
+ // Allocates the xmlTextWriter and an xmlBuffer and starts an XML document.
+ // This must be called before any other functions. By default, indenting is
+ // set to true.
+ void StartWriting();
+
+ // Ends the XML document and frees the xmlTextWriter.
+ // This must be called before GetWrittenString() is called.
+ void StopWriting();
+ // Wrappers around libxml functions -----------------------------------------
+
+ // All following elements will be indented to match their depth.
+ void StartIndenting() { xmlTextWriterSetIndent(writer_, 1); }
+
+ // All follow elements will not be indented.
+ void StopIndenting() { xmlTextWriterSetIndent(writer_, 0); }
+
+ // Start an element with the given name. All future elements added will be
+ // children of this element, until it is ended. Returns false on error.
+ bool StartElement(const std::string& element_name) {
+ return xmlTextWriterStartElement(writer_,
+ BAD_CAST element_name.c_str()) >= 0;
+ }
+
+ // Ends the current open element. Returns false on error.
+ bool EndElement() {
+ return xmlTextWriterEndElement(writer_) >= 0;
+ }
+
+ // Adds an attribute to the current open element. Returns false on error.
+ bool AddAttribute(const std::string& attribute_name,
+ const std::string& attribute_value) {
+ return xmlTextWriterWriteAttribute(writer_,
+ BAD_CAST attribute_name.c_str(),
+ BAD_CAST attribute_value.c_str()) >= 0;
+ }
+
+ // Adds a new element with name |element_name| and content |content|
+ // to the buffer. Example: <|element_name|>|content|</|element_name|>
+ // Returns false on errors.
+ bool WriteElement(const std::string& element_name,
+ const std::string& content) {
+ return xmlTextWriterWriteElement(writer_,
+ BAD_CAST element_name.c_str(),
+ BAD_CAST content.c_str()) >= 0;
+ }
+
+ // Helper functions not provided by xmlTextWriter ---------------------------
+
+ // Returns the string that has been written to the buffer.
+ std::string GetWrittenString() {
+ if (buffer_ == NULL)
+ return "";
+ return XmlStringToStdString(buffer_->content);
+ }
+
+ private:
+ // The underlying libxml xmlTextWriter.
+ xmlTextWriterPtr writer_;
+
+ // Stores the output.
+ xmlBufferPtr buffer_;
+};
+
+#endif // CHROME_COMMON_LIBXML_UTILS_H__
diff --git a/chrome/common/logging_chrome.cc b/chrome/common/logging_chrome.cc
new file mode 100644
index 0000000..c3bdb77
--- /dev/null
+++ b/chrome/common/logging_chrome.cc
@@ -0,0 +1,294 @@
+// Copyright (c) 2010 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 "build/build_config.h"
+
+// Need to include this before most other files because it defines
+// IPC_MESSAGE_LOG_ENABLED. We need to use it to define
+// IPC_MESSAGE_MACROS_LOG_ENABLED so render_messages.h will generate the
+// ViewMsgLog et al. functions.
+#include "ipc/ipc_message.h"
+
+// On Windows, the about:ipc dialog shows IPCs; on POSIX, we hook up a
+// logger in this file. (We implement about:ipc on Mac but implement
+// the loggers here anyway). We need to do this real early to be sure
+// IPC_MESSAGE_MACROS_LOG_ENABLED doesn't get undefined.
+#if defined(OS_POSIX) && defined(IPC_MESSAGE_LOG_ENABLED)
+#define IPC_MESSAGE_MACROS_LOG_ENABLED
+#include "chrome/common/devtools_messages.h"
+#include "chrome/common/plugin_messages.h"
+#include "chrome/common/render_messages.h"
+#include "chrome/common/worker_messages.h"
+#endif
+
+#if defined(OS_WIN)
+#include <windows.h>
+#endif
+
+#include <fstream>
+
+#include "chrome/common/logging_chrome.h"
+
+#include "base/command_line.h"
+#include "base/compiler_specific.h"
+#include "base/debug_util.h"
+#include "base/env_var.h"
+#include "base/file_path.h"
+#include "base/file_util.h"
+#include "base/logging.h"
+#include "base/path_service.h"
+#include "base/time.h"
+#include "base/utf_string_conversions.h"
+#include "chrome/common/chrome_paths.h"
+#include "chrome/common/chrome_switches.h"
+#include "chrome/common/env_vars.h"
+#include "ipc/ipc_logging.h"
+#if defined(OS_WIN)
+#include "base/logging_win.h"
+#include <initguid.h>
+#endif
+
+// When true, this means that error dialogs should not be shown.
+static bool dialogs_are_suppressed_ = false;
+
+// This should be true for exactly the period between the end of
+// InitChromeLogging() and the beginning of CleanupChromeLogging().
+static bool chrome_logging_initialized_ = false;
+
+#if defined(OS_WIN)
+// {7FE69228-633E-4f06-80C1-527FEA23E3A7}
+DEFINE_GUID(kChromeTraceProviderName,
+ 0x7fe69228, 0x633e, 0x4f06, 0x80, 0xc1, 0x52, 0x7f, 0xea, 0x23, 0xe3, 0xa7);
+#endif
+
+// Assertion handler for logging errors that occur when dialogs are
+// silenced. To record a new error, pass the log string associated
+// with that error in the str parameter.
+MSVC_DISABLE_OPTIMIZE();
+static void SilentRuntimeAssertHandler(const std::string& str) {
+ DebugUtil::BreakDebugger();
+}
+static void SilentRuntimeReportHandler(const std::string& str) {
+}
+MSVC_ENABLE_OPTIMIZE();
+
+// Suppresses error/assertion dialogs and enables the logging of
+// those errors into silenced_errors_.
+static void SuppressDialogs() {
+ if (dialogs_are_suppressed_)
+ return;
+
+ logging::SetLogAssertHandler(SilentRuntimeAssertHandler);
+ logging::SetLogReportHandler(SilentRuntimeReportHandler);
+
+#if defined(OS_WIN)
+ UINT new_flags = SEM_FAILCRITICALERRORS |
+ SEM_NOGPFAULTERRORBOX |
+ SEM_NOOPENFILEERRORBOX;
+
+ // Preserve existing error mode, as discussed at http://t/dmea
+ UINT existing_flags = SetErrorMode(new_flags);
+ SetErrorMode(existing_flags | new_flags);
+#endif
+
+ dialogs_are_suppressed_ = true;
+}
+
+namespace logging {
+
+LoggingDestination DetermineLogMode(const CommandLine& command_line) {
+ // only use OutputDebugString in debug mode
+#ifdef NDEBUG
+ bool enable_logging = false;
+ const char *kInvertLoggingSwitch = switches::kEnableLogging;
+ const logging::LoggingDestination kDefaultLoggingMode =
+ logging::LOG_ONLY_TO_FILE;
+#else
+ bool enable_logging = true;
+ const char *kInvertLoggingSwitch = switches::kDisableLogging;
+ const logging::LoggingDestination kDefaultLoggingMode =
+ logging::LOG_TO_BOTH_FILE_AND_SYSTEM_DEBUG_LOG;
+#endif
+
+ if (command_line.HasSwitch(kInvertLoggingSwitch))
+ enable_logging = !enable_logging;
+
+ logging::LoggingDestination log_mode;
+ if (enable_logging) {
+ // Let --enable-logging=stderr force only stderr, particularly useful for
+ // non-debug builds where otherwise you can't get logs to stderr at all.
+ if (command_line.GetSwitchValueASCII(switches::kEnableLogging) == "stderr")
+ log_mode = logging::LOG_ONLY_TO_SYSTEM_DEBUG_LOG;
+ else
+ log_mode = kDefaultLoggingMode;
+ } else {
+ log_mode = logging::LOG_NONE;
+ }
+ return log_mode;
+}
+
+#if defined(OS_CHROMEOS)
+void SetUpSymlink(const FilePath& symlink_path, const FilePath& new_log_path) {
+ // We don't care if the unlink fails; we're going to continue anyway.
+ if (unlink(symlink_path.value().c_str()) == -1)
+ PLOG(WARNING) << "Unable to unlink " << symlink_path.value();
+ if (symlink(new_log_path.value().c_str(),
+ symlink_path.value().c_str()) == -1) {
+ PLOG(ERROR) << "Unable to create symlink " << symlink_path.value()
+ << " pointing at " << new_log_path.value();
+ }
+}
+
+FilePath TimestampLog(const FilePath& new_log_file, base::Time timestamp) {
+ base::Time::Exploded time_deets;
+ timestamp.LocalExplode(&time_deets);
+ std::string suffix = StringPrintf("_%02d%02d%02d-%02d%02d%02d",
+ time_deets.year,
+ time_deets.month,
+ time_deets.day_of_month,
+ time_deets.hour,
+ time_deets.minute,
+ time_deets.second);
+ FilePath new_log_path = new_log_file.InsertBeforeExtension(suffix);
+ SetUpSymlink(new_log_file, new_log_path);
+
+ return new_log_path;
+}
+
+void RedirectChromeLogging(const FilePath& new_log_dir,
+ const CommandLine& command_line,
+ OldFileDeletionState delete_old_log_file) {
+ FilePath log_file_name = GetLogFileName().BaseName();
+ FilePath new_log_path =
+ TimestampLog(new_log_dir.Append(log_file_name), base::Time::Now());
+ InitLogging(new_log_path.value().c_str(),
+ DetermineLogMode(command_line),
+ logging::LOCK_LOG_FILE,
+ delete_old_log_file);
+}
+#endif
+
+void InitChromeLogging(const CommandLine& command_line,
+ OldFileDeletionState delete_old_log_file) {
+ DCHECK(!chrome_logging_initialized_) <<
+ "Attempted to initialize logging when it was already initialized.";
+
+#if defined(OS_POSIX) && defined(IPC_MESSAGE_LOG_ENABLED)
+ IPC::Logging::SetLoggerFunctions(g_log_function_mapping);
+#endif
+
+ FilePath log_path = GetLogFileName();
+#if defined(OS_CHROMEOS)
+ log_path = TimestampLog(log_path, base::Time::Now());
+#endif
+
+ logging::InitLogging(log_path.value().c_str(),
+ DetermineLogMode(command_line),
+ logging::LOCK_LOG_FILE,
+ delete_old_log_file);
+
+ // we want process and thread IDs because we have a lot of things running
+ logging::SetLogItems(true, true, false, true);
+
+ // We call running in unattended mode "headless", and allow
+ // headless mode to be configured either by the Environment
+ // Variable or by the Command Line Switch. This is for
+ // automated test purposes.
+ scoped_ptr<base::EnvVarGetter> env(base::EnvVarGetter::Create());
+ if (env->HasEnv(env_vars::kHeadless) ||
+ command_line.HasSwitch(switches::kNoErrorDialogs))
+ SuppressDialogs();
+
+ std::string log_filter_prefix =
+ command_line.GetSwitchValueASCII(switches::kLogFilterPrefix);
+ logging::SetLogFilterPrefix(log_filter_prefix.c_str());
+
+ // Use a minimum log level if the command line has one, otherwise set the
+ // default to LOG_WARNING.
+ std::string log_level = command_line.GetSwitchValueASCII(
+ switches::kLoggingLevel);
+ int level = 0;
+ if (StringToInt(log_level, &level)) {
+ if ((level >= 0) && (level < LOG_NUM_SEVERITIES))
+ logging::SetMinLogLevel(level);
+ } else {
+ logging::SetMinLogLevel(LOG_WARNING);
+ }
+
+#if defined(OS_WIN)
+ // Enable trace control and transport through event tracing for Windows.
+ if (env->HasEnv(env_vars::kEtwLogging))
+ logging::LogEventProvider::Initialize(kChromeTraceProviderName);
+#endif
+
+ chrome_logging_initialized_ = true;
+}
+
+// This is a no-op, but we'll keep it around in case
+// we need to do more cleanup in the future.
+void CleanupChromeLogging() {
+ DCHECK(chrome_logging_initialized_) <<
+ "Attempted to clean up logging when it wasn't initialized.";
+
+ CloseLogFile();
+
+ chrome_logging_initialized_ = false;
+}
+
+FilePath GetLogFileName() {
+ std::string filename;
+ scoped_ptr<base::EnvVarGetter> env(base::EnvVarGetter::Create());
+ if (env->GetEnv(env_vars::kLogFileName, &filename) && !filename.empty()) {
+#if defined(OS_WIN)
+ return FilePath(UTF8ToWide(filename).c_str());
+#elif defined(OS_POSIX)
+ return FilePath(filename.c_str());
+#endif
+ }
+
+ const FilePath log_filename(FILE_PATH_LITERAL("chrome_debug.log"));
+ FilePath log_path;
+
+ if (PathService::Get(chrome::DIR_LOGS, &log_path)) {
+ log_path = log_path.Append(log_filename);
+ return log_path;
+ } else {
+ // error with path service, just use some default file somewhere
+ return log_filename;
+ }
+}
+
+bool DialogsAreSuppressed() {
+ return dialogs_are_suppressed_;
+}
+
+size_t GetFatalAssertions(AssertionList* assertions) {
+ // In this function, we don't assume that assertions is non-null, so
+ // that if you just want an assertion count, you can pass in NULL.
+ if (assertions)
+ assertions->clear();
+ size_t assertion_count = 0;
+
+ std::ifstream log_file;
+ log_file.open(GetLogFileName().value().c_str());
+ if (!log_file.is_open())
+ return 0;
+
+ std::string utf8_line;
+ std::wstring wide_line;
+ while (!log_file.eof()) {
+ getline(log_file, utf8_line);
+ if (utf8_line.find(":FATAL:") != std::string::npos) {
+ wide_line = UTF8ToWide(utf8_line);
+ if (assertions)
+ assertions->push_back(wide_line);
+ ++assertion_count;
+ }
+ }
+ log_file.close();
+
+ return assertion_count;
+}
+
+} // namespace logging
diff --git a/chrome/common/logging_chrome.h b/chrome/common/logging_chrome.h
new file mode 100644
index 0000000..57c3906
--- /dev/null
+++ b/chrome/common/logging_chrome.h
@@ -0,0 +1,68 @@
+// Copyright (c) 2006-2008 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_COMMON_LOGGING_CHROME_H__
+#define CHROME_COMMON_LOGGING_CHROME_H__
+
+#include <string>
+#include <vector>
+
+#include "base/logging.h"
+
+class CommandLine;
+class FilePath;
+
+namespace base {
+class Time;
+}
+
+namespace logging {
+
+// Call to initialize logging for Chrome. This sets up the chrome-specific
+// logfile naming scheme and might do other things like log modules and
+// setting levels in the future.
+//
+// The main process might want to delete any old log files on startup by
+// setting delete_old_log_file, but the renderer processes should not, or
+// they will delete each others' logs.
+//
+// XXX
+// Setting suppress_error_dialogs to true disables any dialogs that would
+// normally appear for assertions and crashes, and makes any catchable
+// errors (namely assertions) available via GetSilencedErrorCount()
+// and GetSilencedError().
+void InitChromeLogging(const CommandLine& command_line,
+ OldFileDeletionState delete_old_log_file);
+
+#if defined(OS_CHROMEOS)
+void RedirectChromeLogging(const FilePath& new_log_dir,
+ const CommandLine& command_line,
+ OldFileDeletionState delete_old_log_file);
+#endif
+
+// Call when done using logging for Chrome.
+void CleanupChromeLogging();
+
+// Returns the fully-qualified name of the log file.
+FilePath GetLogFileName();
+
+// Returns true when error/assertion dialogs are to be shown,
+// false otherwise.
+bool DialogsAreSuppressed();
+
+typedef std::vector<std::wstring> AssertionList;
+
+// Gets the list of fatal assertions in the current log file, and
+// returns the number of fatal assertions. (If you don't care
+// about the actual list of assertions, you can pass in NULL.)
+// NOTE: Since this reads the log file to determine the assertions,
+// this operation is O(n) over the length of the log.
+// NOTE: This can fail if the file is locked for writing. However,
+// this is unlikely as this function is most useful after
+// the program writing the log has terminated.
+size_t GetFatalAssertions(AssertionList* assertions);
+
+} // namespace logging
+
+#endif // CHROME_COMMON_LOGGING_CHROME_H_
diff --git a/chrome/common/logging_chrome_uitest.cc b/chrome/common/logging_chrome_uitest.cc
new file mode 100644
index 0000000..f92525e
--- /dev/null
+++ b/chrome/common/logging_chrome_uitest.cc
@@ -0,0 +1,189 @@
+// Copyright (c) 2010 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 "build/build_config.h"
+
+#if defined(OS_WIN)
+#include <windows.h>
+#endif
+
+#include <string>
+
+#include "base/basictypes.h"
+#include "base/command_line.h"
+#include "base/env_var.h"
+#include "chrome/common/chrome_switches.h"
+#include "chrome/common/env_vars.h"
+#include "chrome/common/logging_chrome.h"
+#include "chrome/test/automation/browser_proxy.h"
+#include "chrome/test/ui/ui_test.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+class ChromeLoggingTest : public testing::Test {
+ public:
+ // Stores the current value of the log file name environment
+ // variable and sets the variable to new_value.
+ void SaveEnvironmentVariable(std::string new_value) {
+ scoped_ptr<base::EnvVarGetter> env(base::EnvVarGetter::Create());
+ if (!env->GetEnv(env_vars::kLogFileName, &environment_filename_))
+ environment_filename_ = "";
+
+ env->SetEnv(env_vars::kLogFileName, new_value);
+ }
+
+ // Restores the value of the log file nave environment variable
+ // previously saved by SaveEnvironmentVariable().
+ void RestoreEnvironmentVariable() {
+ scoped_ptr<base::EnvVarGetter> env(base::EnvVarGetter::Create());
+ env->SetEnv(env_vars::kLogFileName, environment_filename_);
+ }
+
+ private:
+ std::string environment_filename_; // Saves real environment value.
+};
+
+// Tests the log file name getter without an environment variable.
+TEST_F(ChromeLoggingTest, LogFileName) {
+ SaveEnvironmentVariable("");
+
+ FilePath filename = logging::GetLogFileName();
+ ASSERT_NE(FilePath::StringType::npos,
+ filename.value().find(FILE_PATH_LITERAL("chrome_debug.log")));
+
+ RestoreEnvironmentVariable();
+}
+
+// Tests the log file name getter with an environment variable.
+TEST_F(ChromeLoggingTest, EnvironmentLogFileName) {
+ SaveEnvironmentVariable("test value");
+
+ FilePath filename = logging::GetLogFileName();
+ ASSERT_EQ(FilePath(FILE_PATH_LITERAL("test value")).value(),
+ filename.value());
+
+ RestoreEnvironmentVariable();
+}
+
+#if defined(OS_LINUX) && (!defined(NDEBUG) || !defined(USE_LINUX_BREAKPAD))
+// On Linux in Debug mode, Chrome generates a SIGTRAP.
+// we do not catch SIGTRAPs, thus no crash dump.
+// This also does not work if Breakpad is disabled.
+#define EXPECTED_ASSERT_CRASHES 0
+#else
+#define EXPECTED_ASSERT_CRASHES 1
+#endif
+
+#if !defined(NDEBUG) // We don't have assertions in release builds.
+// Tests whether we correctly fail on browser assertions during tests.
+class AssertionTest : public UITest {
+ protected:
+ AssertionTest() : UITest() {
+ // Initial loads will never complete due to assertion.
+ wait_for_initial_loads_ = false;
+
+ // We're testing the renderer rather than the browser assertion here,
+ // because the browser assertion would flunk the test during SetUp()
+ // (since TAU wouldn't be able to find the browser window).
+ launch_arguments_.AppendSwitch(switches::kRendererAssertTest);
+ }
+};
+
+// Launch the app in assertion test mode, then close the app.
+#if defined(OS_WIN)
+// http://crbug.com/26715
+#define Assertion DISABLED_Assertion
+#elif defined(OS_MACOSX)
+// Crash service doesn't exist for the Mac yet: http://crbug.com/45243
+#define Assertion DISABLED_Assertion
+#endif
+TEST_F(AssertionTest, Assertion) {
+ if (UITest::in_process_renderer()) {
+ // in process mode doesn't do the crashing.
+ expected_errors_ = 0;
+ expected_crashes_ = 0;
+ } else {
+ expected_errors_ = 1;
+ expected_crashes_ = EXPECTED_ASSERT_CRASHES;
+ }
+}
+#endif // !defined(NDEBUG)
+
+#if !defined(OFFICIAL_BUILD)
+// Only works on Linux in Release mode with CHROME_HEADLESS=1
+class CheckFalseTest : public UITest {
+ protected:
+ CheckFalseTest() : UITest() {
+ // Initial loads will never complete due to assertion.
+ wait_for_initial_loads_ = false;
+
+ // We're testing the renderer rather than the browser assertion here,
+ // because the browser assertion would flunk the test during SetUp()
+ // (since TAU wouldn't be able to find the browser window).
+ launch_arguments_.AppendSwitch(switches::kRendererCheckFalseTest);
+ }
+};
+
+#if defined(OS_WIN)
+// http://crbug.com/38497
+#define CheckFails FLAKY_CheckFails
+#elif defined(OS_MACOSX)
+// Crash service doesn't exist for the Mac yet: http://crbug.com/45243
+#define CheckFails DISABLED_CheckFails
+#elif defined(OS_LINUX)
+// TODO(phajdan) Fix this - http://crbug.com/49838
+#define CheckFails FAILS_CheckFails
+#endif
+// Launch the app in assertion test mode, then close the app.
+TEST_F(CheckFalseTest, CheckFails) {
+ if (UITest::in_process_renderer()) {
+ // in process mode doesn't do the crashing.
+ expected_errors_ = 0;
+ expected_crashes_ = 0;
+ } else {
+ expected_errors_ = 1;
+ expected_crashes_ = EXPECTED_ASSERT_CRASHES;
+ }
+}
+#endif // !defined(OFFICIAL_BUILD)
+
+// Tests whether we correctly fail on browser crashes during UI Tests.
+class RendererCrashTest : public UITest {
+ protected:
+ RendererCrashTest() : UITest() {
+ // Initial loads will never complete due to crash.
+ wait_for_initial_loads_ = false;
+
+ launch_arguments_.AppendSwitch(switches::kRendererCrashTest);
+ }
+};
+
+#if defined(OS_LINUX) && !defined(USE_LINUX_BREAKPAD)
+// On Linux, do not expect a crash dump if Breakpad is disabled.
+#define EXPECTED_CRASH_CRASHES 0
+#else
+#define EXPECTED_CRASH_CRASHES 1
+#endif
+
+#if defined(OS_WIN)
+// http://crbug.com/32048
+#define Crash FLAKY_Crash
+#elif defined(OS_CHROMEOS)
+// http://crbug.com/43115
+#define Crash DISABLED_Crash
+#elif defined(OS_MACOSX)
+// Crash service doesn't exist for the Mac yet: http://crbug.com/45243
+#define Crash DISABLED_Crash
+#endif
+// Launch the app in renderer crash test mode, then close the app.
+TEST_F(RendererCrashTest, Crash) {
+ if (UITest::in_process_renderer()) {
+ // in process mode doesn't do the crashing.
+ expected_crashes_ = 0;
+ } else {
+ scoped_refptr<BrowserProxy> browser(automation()->GetBrowserWindow(0));
+ ASSERT_TRUE(browser.get());
+ ASSERT_TRUE(browser->WaitForTabCountToBecome(1, action_max_timeout_ms()));
+ expected_crashes_ = EXPECTED_CRASH_CRASHES;
+ }
+}
diff --git a/chrome/common/mach_message_source_mac.cc b/chrome/common/mach_message_source_mac.cc
new file mode 100644
index 0000000..1249d8a
--- /dev/null
+++ b/chrome/common/mach_message_source_mac.cc
@@ -0,0 +1,66 @@
+// Copyright (c) 2008 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/common/mach_message_source_mac.h"
+
+#include "base/logging.h"
+
+MachMessageSource::MachMessageSource(mach_port_t port,
+ MachPortListener* msg_listener,
+ bool* success) {
+ DCHECK(msg_listener);
+ DCHECK(success);
+ DCHECK(port != MACH_PORT_NULL);
+
+ CFMachPortContext port_context = {0};
+ port_context.info = msg_listener;
+
+ scoped_cftyperef<CFMachPortRef> cf_mach_port_ref(
+ CFMachPortCreateWithPort(kCFAllocatorDefault,
+ port,
+ MachMessageSource::OnReceiveMachMessage,
+ &port_context,
+ NULL));
+
+ if (cf_mach_port_ref.get() == NULL) {
+ LOG(WARNING) << "CFMachPortCreate failed";
+ *success = false;
+ return;
+ }
+
+ // Create a RL source.
+ machport_runloop_ref_.reset(
+ CFMachPortCreateRunLoopSource(kCFAllocatorDefault,
+ cf_mach_port_ref.get(),
+ 0));
+
+ if (machport_runloop_ref_.get() == NULL) {
+ LOG(WARNING) << "CFMachPortCreateRunLoopSource failed";
+ *success = false;
+ return;
+ }
+
+ CFRunLoopAddSource(CFRunLoopGetCurrent(),
+ machport_runloop_ref_.get(),
+ kCFRunLoopCommonModes);
+ *success = true;
+}
+
+MachMessageSource::~MachMessageSource() {
+ CFRunLoopRemoveSource(CFRunLoopGetCurrent(),
+ machport_runloop_ref_.get(),
+ kCFRunLoopCommonModes);
+}
+
+// static
+void MachMessageSource::OnReceiveMachMessage(CFMachPortRef port, void* msg,
+ CFIndex size, void* closure) {
+ MachPortListener *msg_listener = static_cast<MachPortListener*>(closure);
+ size_t msg_size = (size < 0) ? 0 : static_cast<size_t>(size);
+ DCHECK(msg && msg_size > 0); // this should never happen!
+
+ if (msg_listener && msg && msg_size > 0) {
+ msg_listener->OnMachMessageReceived(msg, msg_size);
+ }
+}
diff --git a/chrome/common/mach_message_source_mac.h b/chrome/common/mach_message_source_mac.h
new file mode 100644
index 0000000..f57539d
--- /dev/null
+++ b/chrome/common/mach_message_source_mac.h
@@ -0,0 +1,59 @@
+// Copyright (c) 2008 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_COMMON_MACH_MESSAGE_SOURCE_MAC_H_
+#define CHROME_COMMON_MACH_MESSAGE_SOURCE_MAC_H_
+
+#include <CoreServices/CoreServices.h>
+
+#include "base/scoped_cftyperef.h"
+
+// Handles registering and cleaning up after a CFRunloopSource for a Mach port.
+// Messages received on the port are piped through to a delegate.
+//
+// Example:
+// class MyListener : public MachMessageSource::MachPortListener {
+// public:
+// void OnMachMessageReceived(void* mach_msg, size_t size) {
+// printf("received message on Mach port\n");
+// }
+// };
+//
+// mach_port_t a_port = ...;
+// MyListener listener;
+// bool success = false;
+// MachMessageSource message_source(port, listener, &success);
+//
+// if (!success) {
+// exit(1); // Couldn't register mach runloop source.
+// }
+//
+// CFRunLoopRun(); // Process messages on runloop...
+class MachMessageSource {
+ public:
+ // Classes that want to listen on a Mach port can implement
+ // OnMachMessageReceived, |mach_msg| is a pointer to the raw message data and
+ // |size| is the buffer size;
+ class MachPortListener {
+ public:
+ virtual void OnMachMessageReceived(void* mach_msg, size_t size) = 0;
+ };
+
+ // |listener| is a week reference passed to CF, it needs to remain in
+ // existence till this object is destroeyd.
+ MachMessageSource(mach_port_t port,
+ MachPortListener* listener,
+ bool* success);
+ ~MachMessageSource();
+
+ private:
+ // Called by CF when a new message arrives on the Mach port.
+ static void OnReceiveMachMessage(CFMachPortRef port, void* msg, CFIndex size,
+ void* closure);
+
+ scoped_cftyperef<CFRunLoopSourceRef> machport_runloop_ref_;
+ DISALLOW_COPY_AND_ASSIGN(MachMessageSource);
+};
+
+#endif // CHROME_COMMON_MACH_MESSAGE_SOURCE_MAC_H_
diff --git a/chrome/common/main_function_params.h b/chrome/common/main_function_params.h
new file mode 100644
index 0000000..b224892
--- /dev/null
+++ b/chrome/common/main_function_params.h
@@ -0,0 +1,33 @@
+// Copyright (c) 2009 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.
+
+// Wrapper to the parameter list for the "main" entry points (browser, renderer,
+// plugin) to shield the call sites from the differences between platforms
+// (e.g., POSIX doesn't need to pass any sandbox information).
+
+#ifndef CHROME_COMMON_MAIN_FUNCTION_PARAMS_H_
+#define CHROME_COMMON_MAIN_FUNCTION_PARAMS_H_
+
+#include "base/command_line.h"
+#include "chrome/common/sandbox_init_wrapper.h"
+
+namespace base {
+class ScopedNSAutoreleasePool;
+};
+class Task;
+
+struct MainFunctionParams {
+ MainFunctionParams(const CommandLine& cl, const SandboxInitWrapper& sb,
+ base::ScopedNSAutoreleasePool* pool)
+ : command_line_(cl), sandbox_info_(sb), autorelease_pool_(pool),
+ ui_task(NULL) { }
+ const CommandLine& command_line_;
+ const SandboxInitWrapper& sandbox_info_;
+ base::ScopedNSAutoreleasePool* autorelease_pool_;
+ // Used by InProcessBrowserTest. If non-null BrowserMain schedules this
+ // task to run on the MessageLoop and BrowserInit is not invoked.
+ Task* ui_task;
+};
+
+#endif // CHROME_COMMON_MAIN_FUNCTION_PARAMS_H_
diff --git a/chrome/common/message_router.cc b/chrome/common/message_router.cc
new file mode 100644
index 0000000..b73f2d0
--- /dev/null
+++ b/chrome/common/message_router.cc
@@ -0,0 +1,46 @@
+// Copyright (c) 2006-2008 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/common/message_router.h"
+
+void MessageRouter::OnControlMessageReceived(const IPC::Message& msg) {
+ NOTREACHED() <<
+ "should override in subclass if you care about control messages";
+}
+
+bool MessageRouter::Send(IPC::Message* msg) {
+ NOTREACHED() <<
+ "should override in subclass if you care about sending messages";
+ return false;
+}
+
+void MessageRouter::AddRoute(int32 routing_id,
+ IPC::Channel::Listener* listener) {
+ routes_.AddWithID(listener, routing_id);
+}
+
+void MessageRouter::RemoveRoute(int32 routing_id) {
+ routes_.Remove(routing_id);
+}
+
+void MessageRouter::OnMessageReceived(const IPC::Message& msg) {
+ if (msg.routing_id() == MSG_ROUTING_CONTROL) {
+ OnControlMessageReceived(msg);
+ } else {
+ RouteMessage(msg);
+ }
+}
+
+bool MessageRouter::RouteMessage(const IPC::Message& msg) {
+ IPC::Channel::Listener* listener = ResolveRoute(msg.routing_id());
+ if (!listener)
+ return false;
+
+ listener->OnMessageReceived(msg);
+ return true;
+}
+
+IPC::Channel::Listener* MessageRouter::ResolveRoute(int32 routing_id) {
+ return routes_.Lookup(routing_id);
+}
diff --git a/chrome/common/message_router.h b/chrome/common/message_router.h
new file mode 100644
index 0000000..35d2a5d
--- /dev/null
+++ b/chrome/common/message_router.h
@@ -0,0 +1,62 @@
+// Copyright (c) 2006-2008 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_COMMON_MESSAGE_ROUTER_H__
+#define CHROME_COMMON_MESSAGE_ROUTER_H__
+
+#include "base/id_map.h"
+#include "ipc/ipc_channel.h"
+
+// The MessageRouter handles all incoming messages sent to it by routing them
+// to the correct listener. Routing is based on the Message's routing ID.
+// Since routing IDs are typically assigned asynchronously by the browser
+// process, the MessageRouter has the notion of pending IDs for listeners that
+// have not yet been assigned a routing ID.
+//
+// When a message arrives, the routing ID is used to index the set of routes to
+// find a listener. If a listener is found, then the message is passed to it.
+// Otherwise, the message is ignored if its routing ID is not equal to
+// MSG_ROUTING_CONTROL.
+//
+// The MessageRouter supports the IPC::Message::Sender interface for outgoing
+// messages, but does not define a meaningful implementation of it. The
+// subclass of MessageRouter is intended to provide that if appropriate.
+//
+// The MessageRouter can be used as a concrete class provided its Send method
+// is not called and it does not receive any control messages.
+
+class MessageRouter : public IPC::Channel::Listener,
+ public IPC::Message::Sender {
+ public:
+ MessageRouter() {}
+ virtual ~MessageRouter() {}
+
+ // Implemented by subclasses to handle control messages
+ virtual void OnControlMessageReceived(const IPC::Message& msg);
+
+ // IPC::Channel::Listener implementation:
+ virtual void OnMessageReceived(const IPC::Message& msg);
+
+ // Like OnMessageReceived, except it only handles routed messages. Returns
+ // true if the message was dispatched, or false if there was no listener for
+ // that route id.
+ virtual bool RouteMessage(const IPC::Message& msg);
+
+ // IPC::Message::Sender implementation:
+ virtual bool Send(IPC::Message* msg);
+
+ // Called to add/remove a listener for a particular message routing ID.
+ void AddRoute(int32 routing_id, IPC::Channel::Listener* listener);
+ void RemoveRoute(int32 routing_id);
+
+ IPC::Channel::Listener* ResolveRoute(int32 routing_id);
+
+ private:
+ // A list of all listeners with assigned routing IDs.
+ IDMap<IPC::Channel::Listener> routes_;
+
+ DISALLOW_COPY_AND_ASSIGN(MessageRouter);
+};
+
+#endif // CHROME_COMMON_MESSAGE_ROUTER_H__
diff --git a/chrome/common/metrics_helpers.cc b/chrome/common/metrics_helpers.cc
new file mode 100644
index 0000000..3bbaf3b
--- /dev/null
+++ b/chrome/common/metrics_helpers.cc
@@ -0,0 +1,516 @@
+// Copyright (c) 2009 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/common/metrics_helpers.h"
+
+#if defined(USE_SYSTEM_LIBBZ2)
+#include <bzlib.h>
+#else
+#include "third_party/bzip2/bzlib.h"
+#endif
+
+#include "base/base64.h"
+#include "base/time.h"
+#include "base/basictypes.h"
+#include "base/file_util.h"
+#include "base/md5.h"
+#include "base/perftimer.h"
+#include "base/scoped_ptr.h"
+#include "base/string_util.h"
+#include "base/sys_info.h"
+#include "base/utf_string_conversions.h"
+#include "base/third_party/nspr/prtime.h"
+#include "chrome/common/logging_chrome.h"
+#include "googleurl/src/gurl.h"
+#include "libxml/xmlwriter.h"
+
+#define OPEN_ELEMENT_FOR_SCOPE(name) ScopedElement scoped_element(this, name)
+
+using base::Time;
+using base::TimeDelta;
+
+// http://blogs.msdn.com/oldnewthing/archive/2004/10/25/247180.aspx
+#if defined(OS_WIN)
+extern "C" IMAGE_DOS_HEADER __ImageBase;
+#endif
+
+namespace {
+
+// libxml take xmlChar*, which is unsigned char*
+inline const unsigned char* UnsignedChar(const char* input) {
+ return reinterpret_cast<const unsigned char*>(input);
+}
+
+} // namespace
+
+class MetricsLogBase::XmlWrapper {
+ public:
+ XmlWrapper()
+ : doc_(NULL),
+ buffer_(NULL),
+ writer_(NULL) {
+ buffer_ = xmlBufferCreate();
+ DCHECK(buffer_);
+
+ #if defined(OS_CHROMEOS)
+ writer_ = xmlNewTextWriterDoc(&doc_, /* compression */ 0);
+ #else
+ writer_ = xmlNewTextWriterMemory(buffer_, /* compression */ 0);
+ #endif // OS_CHROMEOS
+ DCHECK(writer_);
+
+ int result = xmlTextWriterSetIndent(writer_, 2);
+ DCHECK_EQ(0, result);
+ }
+
+ ~XmlWrapper() {
+ FreeDocWriter();
+ if (buffer_) {
+ xmlBufferFree(buffer_);
+ buffer_ = NULL;
+ }
+ }
+
+ void FreeDocWriter() {
+ if (writer_) {
+ xmlFreeTextWriter(writer_);
+ writer_ = NULL;
+ }
+ if (doc_) {
+ xmlFreeDoc(doc_);
+ doc_ = NULL;
+ }
+ }
+
+ xmlDocPtr doc() const { return doc_; }
+ xmlTextWriterPtr writer() const { return writer_; }
+ xmlBufferPtr buffer() const { return buffer_; }
+
+ private:
+ xmlDocPtr doc_;
+ xmlBufferPtr buffer_;
+ xmlTextWriterPtr writer_;
+};
+
+// static
+std::string MetricsLogBase::version_extension_;
+
+MetricsLogBase::MetricsLogBase(const std::string& client_id, int session_id,
+ const std::string& version_string)
+ : start_time_(Time::Now()),
+ client_id_(client_id),
+ session_id_(IntToString(session_id)),
+ locked_(false),
+ xml_wrapper_(new XmlWrapper),
+ num_events_(0) {
+
+ StartElement("log");
+ WriteAttribute("clientid", client_id_);
+ WriteInt64Attribute("buildtime", GetBuildTime());
+ WriteAttribute("appversion", version_string);
+}
+
+MetricsLogBase::~MetricsLogBase() {
+ delete xml_wrapper_;
+}
+
+void MetricsLogBase::CloseLog() {
+ DCHECK(!locked_);
+ locked_ = true;
+
+ int result = xmlTextWriterEndDocument(xml_wrapper_->writer());
+ DCHECK_GE(result, 0);
+
+ result = xmlTextWriterFlush(xml_wrapper_->writer());
+ DCHECK_GE(result, 0);
+
+#if defined(OS_CHROMEOS)
+ xmlNodePtr root = xmlDocGetRootElement(xml_wrapper_->doc());
+ if (!hardware_class_.empty()) {
+ // The hardware class is determined after the first ongoing log is
+ // constructed, so this adds the root element's "hardwareclass"
+ // attribute when the log is closed instead.
+ xmlNewProp(root, UnsignedChar("hardwareclass"),
+ UnsignedChar(hardware_class_.c_str()));
+ }
+
+ // Flattens the XML tree into a character buffer.
+ PerfTimer dump_timer;
+ result = xmlNodeDump(xml_wrapper_->buffer(), xml_wrapper_->doc(),
+ root, /* level */ 0, /* format */ 1);
+ DCHECK_GE(result, 0);
+ UMA_HISTOGRAM_TIMES("UMA.XMLNodeDumpTime", dump_timer.Elapsed());
+
+ PerfTimer free_timer;
+ xml_wrapper_->FreeDocWriter();
+ UMA_HISTOGRAM_TIMES("UMA.XMLWriterDestructionTime", free_timer.Elapsed());
+#endif // OS_CHROMEOS
+}
+
+int MetricsLogBase::GetEncodedLogSize() {
+ DCHECK(locked_);
+ return xml_wrapper_->buffer()->use;
+}
+
+bool MetricsLogBase::GetEncodedLog(char* buffer, int buffer_size) {
+ DCHECK(locked_);
+ if (buffer_size < GetEncodedLogSize())
+ return false;
+
+ memcpy(buffer, xml_wrapper_->buffer()->content, GetEncodedLogSize());
+ return true;
+}
+
+std::string MetricsLogBase::GetEncodedLogString() {
+ DCHECK(locked_);
+ return std::string(reinterpret_cast<char*>(xml_wrapper_->buffer()->content));
+}
+
+int MetricsLogBase::GetElapsedSeconds() {
+ return static_cast<int>((Time::Now() - start_time_).InSeconds());
+}
+
+std::string MetricsLogBase::CreateHash(const std::string& value) {
+ MD5Context ctx;
+ MD5Init(&ctx);
+ MD5Update(&ctx, value.data(), value.length());
+
+ MD5Digest digest;
+ MD5Final(&digest, &ctx);
+
+ uint64 reverse_uint64;
+ // UMA only uses first 8 chars of hash. We use the above uint64 instead
+ // of a unsigned char[8] so that we don't run into strict aliasing issues
+ // in the LOG statement below when trying to interpret reverse as a uint64.
+ unsigned char* reverse = reinterpret_cast<unsigned char *>(&reverse_uint64);
+ DCHECK(arraysize(digest.a) >= sizeof(reverse_uint64));
+ for (size_t i = 0; i < sizeof(reverse_uint64); ++i)
+ reverse[i] = digest.a[sizeof(reverse_uint64) - i - 1];
+ // The following log is VERY helpful when folks add some named histogram into
+ // the code, but forgot to update the descriptive list of histograms. When
+ // that happens, all we get to see (server side) is a hash of the histogram
+ // name. We can then use this logging to find out what histogram name was
+ // being hashed to a given MD5 value by just running the version of Chromium
+ // in question with --enable-logging.
+ LOG(INFO) << "Metrics: Hash numeric [" << value << "]=["
+ << reverse_uint64 << "]";
+ return std::string(reinterpret_cast<char*>(digest.a), arraysize(digest.a));
+}
+
+std::string MetricsLogBase::CreateBase64Hash(const std::string& string) {
+ std::string encoded_digest;
+ if (base::Base64Encode(CreateHash(string), &encoded_digest)) {
+ DLOG(INFO) << "Metrics: Hash [" << encoded_digest << "]=[" << string << "]";
+ return encoded_digest;
+ }
+ return std::string();
+}
+
+void MetricsLogBase::RecordUserAction(const char* key) {
+ DCHECK(!locked_);
+
+ std::string command_hash = CreateBase64Hash(key);
+ if (command_hash.empty()) {
+ NOTREACHED() << "Unable generate encoded hash of command: " << key;
+ return;
+ }
+
+ OPEN_ELEMENT_FOR_SCOPE("uielement");
+ WriteAttribute("action", "command");
+ WriteAttribute("targetidhash", command_hash);
+
+ // TODO(jhughes): Properly track windows.
+ WriteIntAttribute("window", 0);
+ WriteCommonEventAttributes();
+
+ ++num_events_;
+}
+
+void MetricsLogBase::RecordLoadEvent(int window_id,
+ const GURL& url,
+ PageTransition::Type origin,
+ int session_index,
+ TimeDelta load_time) {
+ DCHECK(!locked_);
+
+ OPEN_ELEMENT_FOR_SCOPE("document");
+ WriteAttribute("action", "load");
+ WriteIntAttribute("docid", session_index);
+ WriteIntAttribute("window", window_id);
+ WriteAttribute("loadtime", Int64ToString(load_time.InMilliseconds()));
+
+ std::string origin_string;
+
+ switch (PageTransition::StripQualifier(origin)) {
+ // TODO(jhughes): Some of these mappings aren't right... we need to add
+ // some values to the server's enum.
+ case PageTransition::LINK:
+ case PageTransition::MANUAL_SUBFRAME:
+ origin_string = "link";
+ break;
+
+ case PageTransition::TYPED:
+ origin_string = "typed";
+ break;
+
+ case PageTransition::AUTO_BOOKMARK:
+ origin_string = "bookmark";
+ break;
+
+ case PageTransition::AUTO_SUBFRAME:
+ case PageTransition::RELOAD:
+ origin_string = "refresh";
+ break;
+
+ case PageTransition::GENERATED:
+ case PageTransition::KEYWORD:
+ origin_string = "global-history";
+ break;
+
+ case PageTransition::START_PAGE:
+ origin_string = "start-page";
+ break;
+
+ case PageTransition::FORM_SUBMIT:
+ origin_string = "form-submit";
+ break;
+
+ default:
+ NOTREACHED() << "Received an unknown page transition type: " <<
+ PageTransition::StripQualifier(origin);
+ }
+ if (!origin_string.empty())
+ WriteAttribute("origin", origin_string);
+
+ WriteCommonEventAttributes();
+
+ ++num_events_;
+}
+
+void MetricsLogBase::RecordWindowEvent(WindowEventType type,
+ int window_id,
+ int parent_id) {
+ DCHECK(!locked_);
+
+ OPEN_ELEMENT_FOR_SCOPE("window");
+ WriteAttribute("action", WindowEventTypeToString(type));
+ WriteAttribute("windowid", IntToString(window_id));
+ if (parent_id >= 0)
+ WriteAttribute("parent", IntToString(parent_id));
+ WriteCommonEventAttributes();
+
+ ++num_events_;
+}
+
+std::string MetricsLogBase::GetCurrentTimeString() {
+ return Uint64ToString(Time::Now().ToTimeT());
+}
+
+// These are the attributes that are common to every event.
+void MetricsLogBase::WriteCommonEventAttributes() {
+ WriteAttribute("session", session_id_);
+ WriteAttribute("time", GetCurrentTimeString());
+}
+
+void MetricsLogBase::WriteAttribute(const std::string& name,
+ const std::string& value) {
+ DCHECK(!locked_);
+ DCHECK(!name.empty());
+
+ int result = xmlTextWriterWriteAttribute(xml_wrapper_->writer(),
+ UnsignedChar(name.c_str()),
+ UnsignedChar(value.c_str()));
+ DCHECK_GE(result, 0);
+}
+
+void MetricsLogBase::WriteIntAttribute(const std::string& name, int value) {
+ WriteAttribute(name, IntToString(value));
+}
+
+void MetricsLogBase::WriteInt64Attribute(const std::string& name, int64 value) {
+ WriteAttribute(name, Int64ToString(value));
+}
+
+// static
+const char* MetricsLogBase::WindowEventTypeToString(WindowEventType type) {
+ switch (type) {
+ case WINDOW_CREATE: return "create";
+ case WINDOW_OPEN: return "open";
+ case WINDOW_CLOSE: return "close";
+ case WINDOW_DESTROY: return "destroy";
+
+ default:
+ NOTREACHED();
+ return "unknown"; // Can't return NULL as this is used in a required
+ // attribute.
+ }
+}
+
+void MetricsLogBase::StartElement(const char* name) {
+ DCHECK(!locked_);
+ DCHECK(name);
+
+ int result = xmlTextWriterStartElement(xml_wrapper_->writer(),
+ UnsignedChar(name));
+ DCHECK_GE(result, 0);
+}
+
+void MetricsLogBase::EndElement() {
+ DCHECK(!locked_);
+
+ int result = xmlTextWriterEndElement(xml_wrapper_->writer());
+ DCHECK_GE(result, 0);
+}
+
+// static
+int64 MetricsLogBase::GetBuildTime() {
+ static int64 integral_build_time = 0;
+ if (!integral_build_time) {
+ Time time;
+ const char* kDateTime = __DATE__ " " __TIME__ " GMT";
+ bool result = Time::FromString(ASCIIToWide(kDateTime).c_str(), &time);
+ DCHECK(result);
+ integral_build_time = static_cast<int64>(time.ToTimeT());
+ }
+ return integral_build_time;
+}
+
+// TODO(JAR): A The following should really be part of the histogram class.
+// Internal state is being needlessly exposed, and it would be hard to reuse
+// this code. If we moved this into the Histogram class, then we could use
+// the same infrastructure for logging StatsCounters, RatesCounters, etc.
+void MetricsLogBase::RecordHistogramDelta(
+ const Histogram& histogram,
+ const Histogram::SampleSet& snapshot) {
+ DCHECK(!locked_);
+ DCHECK_NE(0, snapshot.TotalCount());
+ snapshot.CheckSize(histogram);
+
+ // We will ignore the MAX_INT/infinite value in the last element of range[].
+
+ OPEN_ELEMENT_FOR_SCOPE("histogram");
+
+ WriteAttribute("name", CreateBase64Hash(histogram.histogram_name()));
+
+ WriteInt64Attribute("sum", snapshot.sum());
+ WriteInt64Attribute("sumsquares", snapshot.square_sum());
+
+ for (size_t i = 0; i < histogram.bucket_count(); i++) {
+ if (snapshot.counts(i)) {
+ OPEN_ELEMENT_FOR_SCOPE("histogrambucket");
+ WriteIntAttribute("min", histogram.ranges(i));
+ WriteIntAttribute("max", histogram.ranges(i + 1));
+ WriteIntAttribute("count", snapshot.counts(i));
+ }
+ }
+}
+
+
+// MetricsServiceBase
+MetricsServiceBase::MetricsServiceBase()
+ : pending_log_(NULL),
+ compressed_log_(),
+ current_log_(NULL),
+ logged_samples_() {
+}
+
+MetricsServiceBase::~MetricsServiceBase() {
+ if (pending_log_) {
+ delete pending_log_;
+ pending_log_ = NULL;
+ }
+ if (current_log_) {
+ delete current_log_;
+ current_log_ = NULL;
+ }
+}
+
+// This implementation is based on the Firefox MetricsService implementation.
+bool MetricsServiceBase::Bzip2Compress(const std::string& input,
+ std::string* output) {
+ bz_stream stream = {0};
+ // As long as our input is smaller than the bzip2 block size, we should get
+ // the best compression. For example, if your input was 250k, using a block
+ // size of 300k or 500k should result in the same compression ratio. Since
+ // our data should be under 100k, using the minimum block size of 100k should
+ // allocate less temporary memory, but result in the same compression ratio.
+ int result = BZ2_bzCompressInit(&stream,
+ 1, // 100k (min) block size
+ 0, // quiet
+ 0); // default "work factor"
+ if (result != BZ_OK) { // out of memory?
+ return false;
+ }
+
+ output->clear();
+
+ stream.next_in = const_cast<char*>(input.data());
+ stream.avail_in = static_cast<int>(input.size());
+ // NOTE: we don't need a BZ_RUN phase since our input buffer contains
+ // the entire input
+ do {
+ output->resize(output->size() + 1024);
+ stream.next_out = &((*output)[stream.total_out_lo32]);
+ stream.avail_out = static_cast<int>(output->size()) - stream.total_out_lo32;
+ result = BZ2_bzCompress(&stream, BZ_FINISH);
+ } while (result == BZ_FINISH_OK);
+ if (result != BZ_STREAM_END) // unknown failure?
+ return false;
+ result = BZ2_bzCompressEnd(&stream);
+ DCHECK(result == BZ_OK);
+
+ output->resize(stream.total_out_lo32);
+
+ return true;
+}
+
+void MetricsServiceBase::RecordCurrentHistograms() {
+ DCHECK(current_log_);
+
+ StatisticsRecorder::Histograms histograms;
+ StatisticsRecorder::GetHistograms(&histograms);
+ for (StatisticsRecorder::Histograms::const_iterator it = histograms.begin();
+ histograms.end() != it;
+ ++it) {
+ if ((*it)->flags() & Histogram::kUmaTargetedHistogramFlag)
+ RecordHistogram(**it);
+ }
+}
+
+void MetricsServiceBase::RecordHistogram(const Histogram& histogram) {
+ // Get up-to-date snapshot of sample stats.
+ Histogram::SampleSet snapshot;
+ histogram.SnapshotSample(&snapshot);
+
+ const std::string& histogram_name = histogram.histogram_name();
+
+ // Find the already sent stats, or create an empty set.
+ LoggedSampleMap::iterator it = logged_samples_.find(histogram_name);
+ Histogram::SampleSet* already_logged;
+ if (logged_samples_.end() == it) {
+ // Add new entry
+ already_logged = &logged_samples_[histogram.histogram_name()];
+ already_logged->Resize(histogram); // Complete initialization.
+ } else {
+ already_logged = &(it->second);
+ // Deduct any stats we've already logged from our snapshot.
+ snapshot.Subtract(*already_logged);
+ }
+
+ // Snapshot now contains only a delta to what we've already_logged.
+
+ if (snapshot.TotalCount() > 0) {
+ current_log_->RecordHistogramDelta(histogram, snapshot);
+ // Add new data into our running total.
+ already_logged->Add(snapshot);
+ }
+}
+
+void MetricsServiceBase::DiscardPendingLog() {
+ if (pending_log_) { // Shutdown might have deleted it!
+ delete pending_log_;
+ pending_log_ = NULL;
+ }
+ compressed_log_.clear();
+}
diff --git a/chrome/common/metrics_helpers.h b/chrome/common/metrics_helpers.h
new file mode 100644
index 0000000..8051273
--- /dev/null
+++ b/chrome/common/metrics_helpers.h
@@ -0,0 +1,223 @@
+// Copyright (c) 2010 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.
+
+// This file defines a set of user experience metrics data recorded by
+// the MetricsService. This is the unit of data that is sent to the server.
+
+#ifndef CHROME_COMMON_METRICS_HELPERS_H_
+#define CHROME_COMMON_METRICS_HELPERS_H_
+
+#include <map>
+#include <string>
+
+#include "base/basictypes.h"
+#include "base/histogram.h"
+#include "base/time.h"
+#include "chrome/common/page_transition_types.h"
+
+class GURL;
+class MetricsLog;
+
+// This class provides base functionality for logging metrics data.
+class MetricsLogBase {
+ public:
+ // Creates a new metrics log
+ // client_id is the identifier for this profile on this installation
+ // session_id is an integer that's incremented on each application launch
+ MetricsLogBase(const std::string& client_id, int session_id,
+ const std::string& version_string);
+ virtual ~MetricsLogBase();
+
+ // Records a user-initiated action.
+ void RecordUserAction(const char* key);
+
+ enum WindowEventType {
+ WINDOW_CREATE = 0,
+ WINDOW_OPEN,
+ WINDOW_CLOSE,
+ WINDOW_DESTROY
+ };
+
+ void RecordWindowEvent(WindowEventType type, int window_id, int parent_id);
+
+ // Records a page load.
+ // window_id - the index of the tab in which the load took place
+ // url - which URL was loaded
+ // origin - what kind of action initiated the load
+ // load_time - how long it took to load the page
+ void RecordLoadEvent(int window_id,
+ const GURL& url,
+ PageTransition::Type origin,
+ int session_index,
+ base::TimeDelta load_time);
+
+ // Record any changes in a given histogram for transmission.
+ void RecordHistogramDelta(const Histogram& histogram,
+ const Histogram::SampleSet& snapshot);
+
+ // Stop writing to this record and generate the encoded representation.
+ // None of the Record* methods can be called after this is called.
+ void CloseLog();
+
+ // These methods allow retrieval of the encoded representation of the
+ // record. They can only be called after CloseLog() has been called.
+ // GetEncodedLog returns false if buffer_size is less than
+ // GetEncodedLogSize();
+ int GetEncodedLogSize();
+ bool GetEncodedLog(char* buffer, int buffer_size);
+ // Returns an empty string on failure.
+ std::string GetEncodedLogString();
+
+ // Returns the amount of time in seconds that this log has been in use.
+ int GetElapsedSeconds();
+
+ int num_events() { return num_events_; }
+
+ void set_hardware_class(const std::string& hardware_class) {
+ hardware_class_ = hardware_class;
+ }
+
+ // Creates an MD5 hash of the given value, and returns hash as a byte
+ // buffer encoded as a std::string.
+ static std::string CreateHash(const std::string& value);
+
+ // Return a base64-encoded MD5 hash of the given string.
+ static std::string CreateBase64Hash(const std::string& string);
+
+ // Get the GMT buildtime for the current binary, expressed in seconds since
+ // Januray 1, 1970 GMT.
+ // The value is used to identify when a new build is run, so that previous
+ // reliability stats, from other builds, can be abandoned.
+ static int64 GetBuildTime();
+
+ // Use |extension| in all uploaded appversions in addition to the standard
+ // version string.
+ static void set_version_extension(const std::string& extension) {
+ version_extension_ = extension;
+ }
+
+ virtual MetricsLog* AsMetricsLog() {
+ return NULL;
+ }
+
+ protected:
+ class XmlWrapper;
+
+ // Returns a string containing the current time.
+ // Virtual so that it can be overridden for testing.
+ virtual std::string GetCurrentTimeString();
+ // Helper class that invokes StartElement from constructor, and EndElement
+ // from destructor.
+ //
+ // Use the macro OPEN_ELEMENT_FOR_SCOPE to help avoid usage problems.
+ class ScopedElement {
+ public:
+ ScopedElement(MetricsLogBase* log, const std::string& name) : log_(log) {
+ DCHECK(log);
+ log->StartElement(name.c_str());
+ }
+
+ ScopedElement(MetricsLogBase* log, const char* name) : log_(log) {
+ DCHECK(log);
+ log->StartElement(name);
+ }
+
+ ~ScopedElement() {
+ log_->EndElement();
+ }
+
+ private:
+ MetricsLogBase* log_;
+ };
+ friend class ScopedElement;
+
+ static const char* WindowEventTypeToString(WindowEventType type);
+
+ // Frees the resources allocated by the XML document writer: the
+ // main writer object as well as the XML tree structure, if
+ // applicable.
+ void FreeDocWriter();
+
+ // Convenience versions of xmlWriter functions
+ void StartElement(const char* name);
+ void EndElement();
+ void WriteAttribute(const std::string& name, const std::string& value);
+ void WriteIntAttribute(const std::string& name, int value);
+ void WriteInt64Attribute(const std::string& name, int64 value);
+
+ // Write the attributes that are common to every metrics event type.
+ void WriteCommonEventAttributes();
+
+ // An extension that is appended to the appversion in each log.
+ static std::string version_extension_;
+
+ base::Time start_time_;
+ base::Time end_time_;
+
+ std::string client_id_;
+ std::string session_id_;
+ std::string hardware_class_;
+
+ // locked_ is true when record has been packed up for sending, and should
+ // no longer be written to. It is only used for sanity checking and is
+ // not a real lock.
+ bool locked_;
+
+ // Isolated to limit the dependency on the XML library for our consumers.
+ XmlWrapper* xml_wrapper_;
+
+ int num_events_; // the number of events recorded in this log
+
+ DISALLOW_COPY_AND_ASSIGN(MetricsLogBase);
+};
+
+// This class provides base functionality for logging metrics data.
+// TODO(ananta)
+// Factor out more common code from chrome and chrome frame metrics service
+// into this class.
+class MetricsServiceBase {
+ protected:
+ MetricsServiceBase();
+ virtual ~MetricsServiceBase();
+
+ // Check to see if there is a log that needs to be, or is being, transmitted.
+ bool pending_log() const {
+ return pending_log_ || !compressed_log_.empty();
+ }
+
+ // Compress the report log in |input| using bzip2, store the result in
+ // |output|.
+ bool Bzip2Compress(const std::string& input, std::string* output);
+
+ // Discard |pending_log_|, and clear |compressed_log_|. Called after
+ // processing of this log is complete.
+ void DiscardPendingLog();
+
+ // Record complete list of histograms into the current log.
+ // Called when we close a log.
+ void RecordCurrentHistograms();
+
+ // Record a specific histogram .
+ void RecordHistogram(const Histogram& histogram);
+
+ // A log that we are currently transmiting, or about to try to transmit.
+ MetricsLogBase* pending_log_;
+
+ // An alternate form of |pending_log_|. We persistently save this version
+ // into prefs if we can't transmit it. As a result, sometimes all we have is
+ // the compressed text version.
+ std::string compressed_log_;
+
+ // The log that we are still appending to.
+ MetricsLogBase* current_log_;
+
+ // Maintain a map of histogram names to the sample stats we've sent.
+ typedef std::map<std::string, Histogram::SampleSet> LoggedSampleMap;
+
+ // For histograms, record what we've already logged (as a sample for each
+ // histogram) so that we can send only the delta with the next log.
+ LoggedSampleMap logged_samples_;
+};
+
+#endif // CHROME_COMMON_METRICS_HELPERS_H_
diff --git a/chrome/common/mru_cache.h b/chrome/common/mru_cache.h
new file mode 100644
index 0000000..b2643f8
--- /dev/null
+++ b/chrome/common/mru_cache.h
@@ -0,0 +1,252 @@
+// Copyright (c) 2009 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.
+
+// This file contains a template for a Most Recently Used cache that allows
+// constant-time access to items using a key, but easy identification of the
+// least-recently-used items for removal. Each key can only be associated with
+// one payload item at a time.
+//
+// The key object will be stored twice, so it should support efficient copying.
+//
+// NOTE: While all operations are O(1), this code is written for
+// legibility rather than optimality. If future profiling identifies this as
+// a bottleneck, there is room for smaller values of 1 in the O(1). :]
+
+#ifndef CHROME_COMMON_MRU_CACHE_H__
+#define CHROME_COMMON_MRU_CACHE_H__
+
+#include <list>
+#include <map>
+#include <utility>
+
+#include "base/basictypes.h"
+#include "base/logging.h"
+
+// MRUCacheBase ----------------------------------------------------------------
+
+// Base class for the MRU cache specializations defined below.
+// The deletor will get called on all payloads that are being removed or
+// replaced.
+template <class KeyType, class PayloadType, class DeletorType>
+class MRUCacheBase {
+ public:
+ // The payload of the list. This maintains a copy of the key so we can
+ // efficiently delete things given an element of the list.
+ typedef std::pair<KeyType, PayloadType> value_type;
+
+ private:
+ typedef std::list<value_type> PayloadList;
+ typedef std::map<KeyType, typename PayloadList::iterator> KeyIndex;
+
+ public:
+ typedef typename PayloadList::size_type size_type;
+
+ typedef typename PayloadList::iterator iterator;
+ typedef typename PayloadList::const_iterator const_iterator;
+ typedef typename PayloadList::reverse_iterator reverse_iterator;
+ typedef typename PayloadList::const_reverse_iterator const_reverse_iterator;
+
+ enum { NO_AUTO_EVICT = 0 };
+
+ // The max_size is the size at which the cache will prune its members to when
+ // a new item is inserted. If the caller wants to manager this itself (for
+ // example, maybe it has special work to do when something is evicted), it
+ // can pass NO_AUTO_EVICT to not restrict the cache size.
+ explicit MRUCacheBase(size_type max_size) : max_size_(max_size) {
+ }
+
+ virtual ~MRUCacheBase() {
+ iterator i = begin();
+ while (i != end())
+ i = Erase(i);
+ }
+
+ // Inserts a payload item with the given key. If an existing item has
+ // the same key, it is removed prior to insertion. An iterator indicating the
+ // inserted item will be returned (this will always be the front of the list).
+ //
+ // The payload will be copied. In the case of an OwningMRUCache, this function
+ // will take ownership of the pointer.
+ iterator Put(const KeyType& key, const PayloadType& payload) {
+ // Remove any existing payload with that key.
+ typename KeyIndex::iterator index_iter = index_.find(key);
+ if (index_iter != index_.end()) {
+ // Erase the reference to it. This will call the deletor on the removed
+ // element. The index reference will be replaced in the code below.
+ Erase(index_iter->second);
+ } else if (max_size_ != NO_AUTO_EVICT) {
+ // New item is being inserted which might make it larger than the maximum
+ // size: kick the oldest thing out if necessary.
+ ShrinkToSize(max_size_ - 1);
+ }
+
+ ordering_.push_front(value_type(key, payload));
+ index_[key] = ordering_.begin();
+ return ordering_.begin();
+ }
+
+ // Retrieves the contents of the given key, or end() if not found. This method
+ // has the side effect of moving the requested item to the front of the
+ // recency list.
+ //
+ // TODO(brettw) We may want a const version of this function in the future.
+ iterator Get(const KeyType& key) {
+ typename KeyIndex::iterator index_iter = index_.find(key);
+ if (index_iter == index_.end())
+ return end();
+ typename PayloadList::iterator iter = index_iter->second;
+
+ // Move the touched item to the front of the recency ordering.
+ ordering_.splice(ordering_.begin(), ordering_, iter);
+ return ordering_.begin();
+ }
+
+ // Retrieves the payload associated with a given key and returns it via
+ // result without affecting the ordering (unlike Get).
+ //
+ // TODO(brettw) We may want a const version of this function in the future.
+ iterator Peek(const KeyType& key) {
+ typename KeyIndex::const_iterator index_iter = index_.find(key);
+ if (index_iter == index_.end())
+ return end();
+ return index_iter->second;
+ }
+
+ // Erases the item referenced by the given iterator. An iterator to the item
+ // following it will be returned. The iterator must be valid.
+ iterator Erase(iterator pos) {
+ deletor_(pos->second);
+ index_.erase(pos->first);
+ return ordering_.erase(pos);
+ }
+
+ // MRUCache entries are often processed in reverse order, so we add this
+ // convenience function (not typically defined by STL containers).
+ reverse_iterator Erase(reverse_iterator pos) {
+ // We have to actually give it the incremented iterator to delete, since
+ // the forward iterator that base() returns is actually one past the item
+ // being iterated over.
+ return reverse_iterator(Erase((++pos).base()));
+ }
+
+ // Shrinks the cache so it only holds |new_size| items. If |new_size| is
+ // bigger or equal to the current number of items, this will do nothing.
+ void ShrinkToSize(size_type new_size) {
+ for (size_type i = size(); i > new_size; i--)
+ Erase(rbegin());
+ }
+
+ // Deletes everything from the cache.
+ void Clear() {
+ for (typename PayloadList::iterator i(ordering_.begin());
+ i != ordering_.end(); ++i)
+ deletor_(i->second);
+ index_.clear();
+ ordering_.clear();
+ }
+
+ // Returns the number of elements in the cache.
+ size_type size() const {
+ // We don't use ordering_.size() for the return value because
+ // (as a linked list) it can be O(n).
+ DCHECK(index_.size() == ordering_.size());
+ return index_.size();
+ }
+
+ // Allows iteration over the list. Forward iteration starts with the most
+ // recent item and works backwards.
+ //
+ // Note that since these iterators are actually iterators over a list, you
+ // can keep them as you insert or delete things (as long as you don't delete
+ // the one you are pointing to) and they will still be valid.
+ iterator begin() { return ordering_.begin(); }
+ const_iterator begin() const { ordering_.begin(); }
+ iterator end() { return ordering_.end(); }
+ const_iterator end() const { return ordering_.end(); }
+
+ reverse_iterator rbegin() { return ordering_.rbegin(); }
+ const_reverse_iterator rbegin() const { ordering_.rbegin(); }
+ reverse_iterator rend() { return ordering_.rend(); }
+ const_reverse_iterator rend() const { return ordering_.rend(); }
+
+ bool empty() const { return ordering_.empty(); }
+
+ private:
+ PayloadList ordering_;
+ KeyIndex index_;
+
+ size_type max_size_;
+
+ DeletorType deletor_;
+
+ DISALLOW_COPY_AND_ASSIGN(MRUCacheBase);
+};
+
+// MRUCache --------------------------------------------------------------------
+
+// A functor that does nothing. Used by the MRUCache.
+template<class PayloadType>
+class MRUCacheNullDeletor {
+ public:
+ void operator()(PayloadType& payload) {
+ }
+};
+
+// A container that does not do anything to free its data. Use this when storing
+// value types (as opposed to pointers) in the list.
+template <class KeyType, class PayloadType>
+class MRUCache : public MRUCacheBase<KeyType,
+ PayloadType,
+ MRUCacheNullDeletor<PayloadType> > {
+ private:
+ typedef MRUCacheBase<KeyType, PayloadType,
+ MRUCacheNullDeletor<PayloadType> > ParentType;
+
+ public:
+ // See MRUCacheBase, noting the possibility of using NO_AUTO_EVICT.
+ explicit MRUCache(typename ParentType::size_type max_size)
+ : ParentType(max_size) {
+ }
+ virtual ~MRUCache() {
+ }
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(MRUCache);
+};
+
+// OwningMRUCache --------------------------------------------------------------
+
+template<class PayloadType>
+class MRUCachePointerDeletor {
+ public:
+ void operator()(PayloadType& payload) {
+ delete payload;
+ }
+};
+
+// A cache that owns the payload type, which must be a non-const pointer type.
+// The pointers will be deleted when they are removed, replaced, or when the
+// cache is destroyed.
+template <class KeyType, class PayloadType>
+class OwningMRUCache
+ : public MRUCacheBase<KeyType,
+ PayloadType,
+ MRUCachePointerDeletor<PayloadType> > {
+ private:
+ typedef MRUCacheBase<KeyType, PayloadType,
+ MRUCachePointerDeletor<PayloadType> > ParentType;
+
+ public:
+ // See MRUCacheBase, noting the possibility of using NO_AUTO_EVICT.
+ explicit OwningMRUCache(typename ParentType::size_type max_size)
+ : ParentType(max_size) {
+ }
+ virtual ~OwningMRUCache() {
+ }
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(OwningMRUCache);
+};
+
+#endif // CHROME_COMMON_MRU_CACHE_H__
diff --git a/chrome/common/mru_cache_unittest.cc b/chrome/common/mru_cache_unittest.cc
new file mode 100644
index 0000000..7cfb7d8
--- /dev/null
+++ b/chrome/common/mru_cache_unittest.cc
@@ -0,0 +1,253 @@
+// Copyright (c) 2009 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 "chrome/common/mru_cache.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+namespace {
+
+int cached_item_live_count = 0;
+
+struct CachedItem {
+ CachedItem() : value(0) {
+ cached_item_live_count++;
+ }
+
+ explicit CachedItem(int new_value) : value(new_value) {
+ cached_item_live_count++;
+ }
+
+ explicit CachedItem(const CachedItem& other) : value(other.value) {
+ cached_item_live_count++;
+ }
+
+ ~CachedItem() {
+ cached_item_live_count--;
+ }
+
+ int value;
+};
+
+} // namespace
+
+TEST(MRUCacheTest, Basic) {
+ typedef MRUCache<int, CachedItem> Cache;
+ Cache cache(Cache::NO_AUTO_EVICT);
+
+ // Check failure conditions
+ {
+ CachedItem test_item;
+ EXPECT_TRUE(cache.Get(0) == cache.end());
+ EXPECT_TRUE(cache.Peek(0) == cache.end());
+ }
+
+ static const int kItem1Key = 5;
+ CachedItem item1(10);
+ Cache::iterator inserted_item = cache.Put(kItem1Key, item1);
+ EXPECT_EQ(1U, cache.size());
+
+ // Check that item1 was properly inserted.
+ {
+ Cache::iterator found = cache.Get(kItem1Key);
+ EXPECT_TRUE(inserted_item == cache.begin());
+ EXPECT_TRUE(found != cache.end());
+
+ found = cache.Peek(kItem1Key);
+ EXPECT_TRUE(found != cache.end());
+
+ EXPECT_EQ(kItem1Key, found->first);
+ EXPECT_EQ(item1.value, found->second.value);
+ }
+
+ static const int kItem2Key = 7;
+ CachedItem item2(12);
+ cache.Put(kItem2Key, item2);
+ EXPECT_EQ(2U, cache.size());
+
+ // Check that item1 is the oldest since item2 was added afterwards.
+ {
+ Cache::reverse_iterator oldest = cache.rbegin();
+ ASSERT_TRUE(oldest != cache.rend());
+ EXPECT_EQ(kItem1Key, oldest->first);
+ EXPECT_EQ(item1.value, oldest->second.value);
+ }
+
+ // Check that item1 is still accessible by key.
+ {
+ Cache::iterator test_item = cache.Get(kItem1Key);
+ ASSERT_TRUE(test_item != cache.end());
+ EXPECT_EQ(kItem1Key, test_item->first);
+ EXPECT_EQ(item1.value, test_item->second.value);
+ }
+
+ // Check that retrieving item1 pushed item2 to oldest.
+ {
+ Cache::reverse_iterator oldest = cache.rbegin();
+ ASSERT_TRUE(oldest != cache.rend());
+ EXPECT_EQ(kItem2Key, oldest->first);
+ EXPECT_EQ(item2.value, oldest->second.value);
+ }
+
+ // Remove the oldest item and check that item1 is now the only member.
+ {
+ Cache::reverse_iterator next = cache.Erase(cache.rbegin());
+
+ EXPECT_EQ(1U, cache.size());
+
+ EXPECT_TRUE(next == cache.rbegin());
+ EXPECT_EQ(kItem1Key, next->first);
+ EXPECT_EQ(item1.value, next->second.value);
+
+ cache.Erase(cache.begin());
+ EXPECT_EQ(0U, cache.size());
+ }
+
+ // Check that Clear() works properly.
+ cache.Put(kItem1Key, item1);
+ cache.Put(kItem2Key, item2);
+ EXPECT_EQ(2U, cache.size());
+ cache.Clear();
+ EXPECT_EQ(0U, cache.size());
+}
+
+TEST(MRUCacheTest, GetVsPeek) {
+ typedef MRUCache<int, CachedItem> Cache;
+ Cache cache(Cache::NO_AUTO_EVICT);
+
+ static const int kItem1Key = 1;
+ CachedItem item1(10);
+ cache.Put(kItem1Key, item1);
+
+ static const int kItem2Key = 2;
+ CachedItem item2(20);
+ cache.Put(kItem2Key, item2);
+
+ // This should do nothing since the size is bigger than the number of items.
+ cache.ShrinkToSize(100);
+
+ // Check that item1 starts out as oldest
+ {
+ Cache::reverse_iterator iter = cache.rbegin();
+ ASSERT_TRUE(iter != cache.rend());
+ EXPECT_EQ(kItem1Key, iter->first);
+ EXPECT_EQ(item1.value, iter->second.value);
+ }
+
+ // Check that Peek doesn't change ordering
+ {
+ Cache::iterator peekiter = cache.Peek(kItem1Key);
+ ASSERT_TRUE(peekiter != cache.end());
+
+ Cache::reverse_iterator iter = cache.rbegin();
+ ASSERT_TRUE(iter != cache.rend());
+ EXPECT_EQ(kItem1Key, iter->first);
+ EXPECT_EQ(item1.value, iter->second.value);
+ }
+}
+
+TEST(MRUCacheTest, KeyReplacement) {
+ typedef MRUCache<int, CachedItem> Cache;
+ Cache cache(Cache::NO_AUTO_EVICT);
+
+ static const int kItem1Key = 1;
+ CachedItem item1(10);
+ cache.Put(kItem1Key, item1);
+
+ static const int kItem2Key = 2;
+ CachedItem item2(20);
+ cache.Put(kItem2Key, item2);
+
+ static const int kItem3Key = 3;
+ CachedItem item3(30);
+ cache.Put(kItem3Key, item3);
+
+ static const int kItem4Key = 4;
+ CachedItem item4(40);
+ cache.Put(kItem4Key, item4);
+
+ CachedItem item5(50);
+ cache.Put(kItem3Key, item5);
+
+ EXPECT_EQ(4U, cache.size());
+ for (int i = 0; i < 3; ++i) {
+ Cache::reverse_iterator iter = cache.rbegin();
+ ASSERT_TRUE(iter != cache.rend());
+ }
+
+ // Make it so only the most important element is there.
+ cache.ShrinkToSize(1);
+
+ Cache::iterator iter = cache.begin();
+ EXPECT_EQ(kItem3Key, iter->first);
+ EXPECT_EQ(item5.value, iter->second.value);
+}
+
+// Make sure that the owning version release its pointers properly.
+TEST(MRUCacheTest, Owning) {
+ typedef OwningMRUCache<int, CachedItem*> Cache;
+ Cache cache(Cache::NO_AUTO_EVICT);
+
+ int initial_count = cached_item_live_count;
+
+ // First insert and item and then overwrite it.
+ static const int kItem1Key = 1;
+ cache.Put(kItem1Key, new CachedItem(20));
+ cache.Put(kItem1Key, new CachedItem(22));
+
+ // There should still be one item, and one extra live item.
+ Cache::iterator iter = cache.Get(kItem1Key);
+ EXPECT_EQ(1U, cache.size());
+ EXPECT_TRUE(iter != cache.end());
+ EXPECT_EQ(initial_count + 1, cached_item_live_count);
+
+ // Now remove it.
+ cache.Erase(cache.begin());
+ EXPECT_EQ(initial_count, cached_item_live_count);
+
+ // Now try another cache that goes out of scope to make sure its pointers
+ // go away.
+ {
+ Cache cache2(Cache::NO_AUTO_EVICT);
+ cache2.Put(1, new CachedItem(20));
+ cache2.Put(2, new CachedItem(20));
+ }
+
+ // There should be no objects leaked.
+ EXPECT_EQ(initial_count, cached_item_live_count);
+
+ // Check that Clear() also frees things correctly.
+ {
+ Cache cache2(Cache::NO_AUTO_EVICT);
+ cache2.Put(1, new CachedItem(20));
+ cache2.Put(2, new CachedItem(20));
+ EXPECT_EQ(initial_count + 2, cached_item_live_count);
+ cache2.Clear();
+ EXPECT_EQ(initial_count, cached_item_live_count);
+ }
+}
+
+TEST(MRUCacheTest, AutoEvict) {
+ typedef OwningMRUCache<int, CachedItem*> Cache;
+ static const Cache::size_type kMaxSize = 3;
+
+ int initial_count = cached_item_live_count;
+
+ {
+ Cache cache(kMaxSize);
+
+ static const int kItem1Key = 1, kItem2Key = 2, kItem3Key = 3, kItem4Key = 4;
+ cache.Put(kItem1Key, new CachedItem(20));
+ cache.Put(kItem2Key, new CachedItem(21));
+ cache.Put(kItem3Key, new CachedItem(22));
+ cache.Put(kItem4Key, new CachedItem(23));
+
+ // The cache should only have kMaxSize items in it even though we inserted
+ // more.
+ EXPECT_EQ(kMaxSize, cache.size());
+ }
+
+ // There should be no objects leaked.
+ EXPECT_EQ(initial_count, cached_item_live_count);
+}
diff --git a/chrome/common/nacl_cmd_line.cc b/chrome/common/nacl_cmd_line.cc
new file mode 100644
index 0000000..a54f196
--- /dev/null
+++ b/chrome/common/nacl_cmd_line.cc
@@ -0,0 +1,40 @@
+// Copyright (c) 2010 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/command_line.h"
+#include "chrome/common/chrome_constants.h"
+#include "chrome/common/chrome_switches.h"
+#include "chrome/common/logging_chrome.h"
+
+namespace nacl {
+ void CopyNaClCommandLineArguments(CommandLine* cmd_line) {
+ const CommandLine& browser_command_line = *CommandLine::ForCurrentProcess();
+ if (logging::DialogsAreSuppressed())
+ cmd_line->AppendSwitch(switches::kNoErrorDialogs);
+
+ // Propagate the following switches to the NaCl loader command line (along
+ // with any associated values) if present in the browser command line.
+ // TODO(gregoryd): check which flags of those below can be supported.
+ static const char* const switch_names[] = {
+ switches::kNoSandbox,
+ switches::kTestNaClSandbox,
+ switches::kDisableBreakpad,
+ switches::kFullMemoryCrashReport,
+ switches::kEnableLogging,
+ switches::kDisableLogging,
+ switches::kLoggingLevel,
+ switches::kEnableDCHECK,
+ switches::kSilentDumpOnDCHECK,
+ switches::kMemoryProfiling,
+ };
+
+ for (size_t i = 0; i < arraysize(switch_names); ++i) {
+ if (browser_command_line.HasSwitch(switch_names[i])) {
+ cmd_line->AppendSwitchWithValue(
+ switch_names[i],
+ browser_command_line.GetSwitchValueASCII(switch_names[i]));
+ }
+ }
+ }
+}
diff --git a/chrome/common/nacl_cmd_line.h b/chrome/common/nacl_cmd_line.h
new file mode 100644
index 0000000..1091e11
--- /dev/null
+++ b/chrome/common/nacl_cmd_line.h
@@ -0,0 +1,16 @@
+// Copyright (c) 2010 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_COMMON_NACL_CMD_LINE_H_
+#define CHROME_COMMON_NACL_CMD_LINE_H_
+
+#include "base/command_line.h"
+
+namespace nacl {
+ // Copy all the relevant arguments from the command line of the current
+ // process to cmd_line that will be used for launching the NaCl loader/broker.
+ void CopyNaClCommandLineArguments(CommandLine* cmd_line);
+}
+
+#endif // CHROME_COMMON_NACL_CMD_LINE_H_
diff --git a/chrome/common/nacl_messages.h b/chrome/common/nacl_messages.h
new file mode 100644
index 0000000..8d360dd
--- /dev/null
+++ b/chrome/common/nacl_messages.h
@@ -0,0 +1,19 @@
+// Copyright (c) 2009 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.
+
+// Defines messages between the browser and NaCl process.
+
+#ifndef CHROME_COMMON_NACL_MESSAGES_H_
+#define CHROME_COMMON_NACL_MESSAGES_H_
+
+#include <string>
+
+#include "base/basictypes.h"
+#include "ipc/ipc_message_utils.h"
+
+#define MESSAGES_INTERNAL_FILE "chrome/common/nacl_messages_internal.h"
+#include "ipc/ipc_message_macros.h"
+
+#endif // CHROME_COMMON_NACL_MESSAGES_H_
+
diff --git a/chrome/common/nacl_messages_internal.h b/chrome/common/nacl_messages_internal.h
new file mode 100644
index 0000000..abde832
--- /dev/null
+++ b/chrome/common/nacl_messages_internal.h
@@ -0,0 +1,30 @@
+// Copyright (c) 2009 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/common/nacl_types.h"
+#include "ipc/ipc_message_macros.h"
+
+//-----------------------------------------------------------------------------
+// NaClProcess messages
+// These are messages sent from the browser to the NaCl process.
+IPC_BEGIN_MESSAGES(NaClProcess)
+ // Tells the NaCl process to start.
+ IPC_MESSAGE_CONTROL2(NaClProcessMsg_Start,
+ int /* descriptor id */,
+ nacl::FileDescriptor /* handle value */)
+
+ // Tells the NaCl broker to launch a NaCl loader process.
+ IPC_MESSAGE_CONTROL1(NaClProcessMsg_LaunchLoaderThroughBroker,
+ std::wstring /* channel ID for the loader */)
+
+ // Notify the browser process that the loader was launched successfully.
+ IPC_MESSAGE_CONTROL2(NaClProcessMsg_LoaderLaunched,
+ std::wstring, /* channel ID for the loader */
+ base::ProcessHandle /* loader process handle */)
+
+ // Notify the broker that all loader processes have been terminated and it
+ // should shutdown.
+ IPC_MESSAGE_CONTROL0(NaClProcessMsg_StopBroker)
+IPC_END_MESSAGES(NaClProcess)
+
diff --git a/chrome/common/nacl_types.h b/chrome/common/nacl_types.h
new file mode 100644
index 0000000..5c5f5dc
--- /dev/null
+++ b/chrome/common/nacl_types.h
@@ -0,0 +1,29 @@
+// Copyright (c) 2009 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.
+
+// Handle passing definitions for NaCl
+#ifndef CHROME_COMMON_NACL_TYPES_H_
+#define CHROME_COMMON_NACL_TYPES_H_
+
+#if defined(OS_POSIX)
+#include "base/file_descriptor_posix.h"
+#endif
+
+// TODO(gregoryd): add a Windows definition for base::FileDescriptor
+namespace nacl {
+#if defined(OS_WIN)
+ // We assume that HANDLE always uses less than 32 bits
+ typedef int FileDescriptor;
+ inline HANDLE ToNativeHandle(const FileDescriptor& desc) {
+ return reinterpret_cast<HANDLE>(desc);
+ }
+#elif defined(OS_POSIX)
+ typedef base::FileDescriptor FileDescriptor;
+ inline int ToNativeHandle(const FileDescriptor& desc) {
+ return desc.fd;
+ }
+#endif
+}
+
+#endif // CHROME_COMMON_NACL_TYPES_H_
diff --git a/chrome/common/native_web_keyboard_event.h b/chrome/common/native_web_keyboard_event.h
new file mode 100644
index 0000000..381ad31
--- /dev/null
+++ b/chrome/common/native_web_keyboard_event.h
@@ -0,0 +1,63 @@
+// Copyright (c) 2009 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_COMMON_NATIVE_WEB_KEYBOARD_EVENT_H_
+#define CHROME_COMMON_NATIVE_WEB_KEYBOARD_EVENT_H_
+
+#include "base/basictypes.h"
+#include "third_party/WebKit/WebKit/chromium/public/WebInputEvent.h"
+
+#if defined(OS_WIN)
+#include <windows.h>
+#elif defined(OS_MACOSX)
+#ifdef __OBJC__
+@class NSEvent;
+#else
+class NSEvent;
+#endif // __OBJC__
+#elif defined(OS_POSIX)
+typedef struct _GdkEventKey GdkEventKey;
+#endif
+
+// Owns a platform specific event; used to pass own and pass event through
+// platform independent code.
+struct NativeWebKeyboardEvent : public WebKit::WebKeyboardEvent {
+ NativeWebKeyboardEvent();
+
+#if defined(OS_WIN)
+ NativeWebKeyboardEvent(HWND hwnd, UINT message, WPARAM wparam, LPARAM lparam);
+#elif defined(OS_MACOSX)
+ explicit NativeWebKeyboardEvent(NSEvent *event);
+ NativeWebKeyboardEvent(wchar_t character,
+ int state,
+ double time_stamp_seconds);
+#elif defined(OS_LINUX)
+ explicit NativeWebKeyboardEvent(const GdkEventKey* event);
+ NativeWebKeyboardEvent(wchar_t character,
+ int state,
+ double time_stamp_seconds);
+#endif
+
+ NativeWebKeyboardEvent(const NativeWebKeyboardEvent& event);
+ ~NativeWebKeyboardEvent();
+
+ NativeWebKeyboardEvent& operator=(const NativeWebKeyboardEvent& event);
+
+#if defined(OS_WIN)
+ MSG os_event;
+#elif defined(OS_MACOSX)
+ NSEvent* os_event;
+#elif defined(OS_LINUX)
+ GdkEventKey* os_event;
+#endif
+
+ // True if the browser should ignore this event if it's not handled by the
+ // renderer. This happens for RawKeyDown events that are created while IME is
+ // active and is necessary to prevent backspace from doing "history back" if
+ // it is hit in ime mode.
+ // Currently, it's only used by Linux and Mac ports.
+ bool skip_in_browser;
+};
+
+#endif // CHROME_COMMON_NATIVE_WEB_KEYBOARD_EVENT_H_
diff --git a/chrome/common/native_web_keyboard_event_linux.cc b/chrome/common/native_web_keyboard_event_linux.cc
new file mode 100644
index 0000000..571550e
--- /dev/null
+++ b/chrome/common/native_web_keyboard_event_linux.cc
@@ -0,0 +1,76 @@
+// Copyright (c) 2009 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/common/native_web_keyboard_event.h"
+
+#include <gdk/gdk.h>
+
+#include "third_party/WebKit/WebKit/chromium/public/gtk/WebInputEventFactory.h"
+
+using WebKit::WebInputEventFactory;
+
+namespace {
+
+void CopyEventTo(const GdkEventKey* in, GdkEventKey** out) {
+ if (in) {
+ *out = reinterpret_cast<GdkEventKey*>(
+ gdk_event_copy(
+ reinterpret_cast<GdkEvent*>(const_cast<GdkEventKey*>(in))));
+ } else {
+ *out = NULL;
+ }
+}
+
+void FreeEvent(GdkEventKey* event) {
+ if (event) {
+ gdk_event_free(reinterpret_cast<GdkEvent*>(event));
+ }
+}
+
+} // namespace
+
+
+NativeWebKeyboardEvent::NativeWebKeyboardEvent()
+ : os_event(NULL),
+ skip_in_browser(false) {
+}
+
+NativeWebKeyboardEvent::NativeWebKeyboardEvent(const GdkEventKey* native_event)
+ : WebKeyboardEvent(WebInputEventFactory::keyboardEvent(native_event)),
+ skip_in_browser(false) {
+ CopyEventTo(native_event, &os_event);
+}
+
+NativeWebKeyboardEvent::NativeWebKeyboardEvent(wchar_t character,
+ int state,
+ double time_stamp_seconds)
+ : WebKeyboardEvent(WebInputEventFactory::keyboardEvent(character,
+ state,
+ time_stamp_seconds)),
+ os_event(NULL),
+ skip_in_browser(false) {
+}
+
+NativeWebKeyboardEvent::NativeWebKeyboardEvent(
+ const NativeWebKeyboardEvent& other)
+ : WebKeyboardEvent(other),
+ skip_in_browser(other.skip_in_browser) {
+ CopyEventTo(other.os_event, &os_event);
+}
+
+NativeWebKeyboardEvent& NativeWebKeyboardEvent::operator=(
+ const NativeWebKeyboardEvent& other) {
+ WebKeyboardEvent::operator=(other);
+
+ FreeEvent(os_event);
+ CopyEventTo(other.os_event, &os_event);
+
+ skip_in_browser = other.skip_in_browser;
+
+ return *this;
+}
+
+NativeWebKeyboardEvent::~NativeWebKeyboardEvent() {
+ FreeEvent(os_event);
+}
diff --git a/chrome/common/native_web_keyboard_event_mac.mm b/chrome/common/native_web_keyboard_event_mac.mm
new file mode 100644
index 0000000..0c11033
--- /dev/null
+++ b/chrome/common/native_web_keyboard_event_mac.mm
@@ -0,0 +1,56 @@
+// Copyright (c) 2009 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/common/native_web_keyboard_event.h"
+
+#import <AppKit/AppKit.h>
+
+#include "third_party/WebKit/WebKit/chromium/public/mac/WebInputEventFactory.h"
+
+using WebKit::WebInputEventFactory;
+
+NativeWebKeyboardEvent::NativeWebKeyboardEvent()
+ : os_event(NULL),
+ skip_in_browser(false) {
+}
+
+NativeWebKeyboardEvent::NativeWebKeyboardEvent(NSEvent* event)
+ : WebKeyboardEvent(WebInputEventFactory::keyboardEvent(event)),
+ os_event([event retain]),
+ skip_in_browser(false) {
+}
+
+NativeWebKeyboardEvent::NativeWebKeyboardEvent(wchar_t character,
+ int modifiers,
+ double time_stamp_seconds)
+ : WebKeyboardEvent(WebInputEventFactory::keyboardEvent(character,
+ modifiers,
+ time_stamp_seconds)),
+ os_event(NULL),
+ skip_in_browser(false) {
+}
+
+NativeWebKeyboardEvent::NativeWebKeyboardEvent(
+ const NativeWebKeyboardEvent& other)
+ : WebKeyboardEvent(other),
+ os_event([other.os_event retain]),
+ skip_in_browser(other.skip_in_browser) {
+}
+
+NativeWebKeyboardEvent& NativeWebKeyboardEvent::operator=(
+ const NativeWebKeyboardEvent& other) {
+ WebKeyboardEvent::operator=(other);
+
+ NSObject* previous = os_event;
+ os_event = [other.os_event retain];
+ [previous release];
+
+ skip_in_browser = other.skip_in_browser;
+
+ return *this;
+}
+
+NativeWebKeyboardEvent::~NativeWebKeyboardEvent() {
+ [os_event release];
+}
diff --git a/chrome/common/native_web_keyboard_event_win.cc b/chrome/common/native_web_keyboard_event_win.cc
new file mode 100644
index 0000000..7608ec6
--- /dev/null
+++ b/chrome/common/native_web_keyboard_event_win.cc
@@ -0,0 +1,54 @@
+// Copyright (c) 2009 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/common/native_web_keyboard_event.h"
+
+#include "third_party/WebKit/WebKit/chromium/public/win/WebInputEventFactory.h"
+
+using WebKit::WebInputEventFactory;
+using WebKit::WebKeyboardEvent;
+
+NativeWebKeyboardEvent::NativeWebKeyboardEvent()
+ : skip_in_browser(false) {
+ memset(&os_event, 0, sizeof(os_event));
+}
+
+NativeWebKeyboardEvent::NativeWebKeyboardEvent(
+ HWND hwnd, UINT message, WPARAM wparam, LPARAM lparam)
+ : WebKeyboardEvent(
+ WebInputEventFactory::keyboardEvent(hwnd, message, wparam, lparam)),
+ skip_in_browser(false) {
+ os_event.hwnd = hwnd;
+ os_event.message = message;
+ os_event.wParam = wparam;
+ os_event.lParam = lparam;
+}
+
+NativeWebKeyboardEvent::NativeWebKeyboardEvent(
+ const NativeWebKeyboardEvent& other)
+ : WebKeyboardEvent(other),
+ skip_in_browser(other.skip_in_browser) {
+ os_event.hwnd = other.os_event.hwnd;
+ os_event.message = other.os_event.message;
+ os_event.wParam = other.os_event.wParam;
+ os_event.lParam = other.os_event.lParam;
+}
+
+NativeWebKeyboardEvent& NativeWebKeyboardEvent::operator=(
+ const NativeWebKeyboardEvent& other) {
+ WebKeyboardEvent::operator=(other);
+
+ os_event.hwnd = other.os_event.hwnd;
+ os_event.message = other.os_event.message;
+ os_event.wParam = other.os_event.wParam;
+ os_event.lParam = other.os_event.lParam;
+
+ skip_in_browser = other.skip_in_browser;
+
+ return *this;
+}
+
+NativeWebKeyboardEvent::~NativeWebKeyboardEvent() {
+ // Noop under windows
+}
diff --git a/chrome/common/native_window_notification_source.h b/chrome/common/native_window_notification_source.h
new file mode 100644
index 0000000..4cc75b8
--- /dev/null
+++ b/chrome/common/native_window_notification_source.h
@@ -0,0 +1,29 @@
+// Copyright (c) 2006-2008 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_COMMON_NATIVE_WINDOW_NOTIFICATION_SOURCE_H_
+#define CHROME_COMMON_NATIVE_WINDOW_NOTIFICATION_SOURCE_H_
+
+#include "chrome/common/notification_source.h"
+#include "gfx/native_widget_types.h"
+
+// Specialization of the Source class for native windows. On Windows, these are
+// HWNDs rather than pointers, and since the Source class expects a pointer
+// type, this is necessary. On Mac/Linux, these are pointers, so this is
+// unnecessary but harmless.
+template<>
+class Source<gfx::NativeWindow> : public NotificationSource {
+ public:
+ explicit Source(gfx::NativeWindow wnd) : NotificationSource(wnd) {}
+
+ explicit Source(const NotificationSource& other)
+ : NotificationSource(other) {}
+
+ gfx::NativeWindow operator->() const { return ptr(); }
+ gfx::NativeWindow ptr() const {
+ return static_cast<gfx::NativeWindow>(const_cast<void*>(ptr_));
+ }
+};
+
+#endif // CHROME_COMMON_NATIVE_WINDOW_NOTIFICATION_SOURCE_H_
diff --git a/chrome/common/navigation_gesture.h b/chrome/common/navigation_gesture.h
new file mode 100644
index 0000000..bb99497
--- /dev/null
+++ b/chrome/common/navigation_gesture.h
@@ -0,0 +1,22 @@
+// Copyright (c) 2006-2009 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_COMMON_NAVIGATION_GESTURE_H_
+#define CHROME_COMMON_NAVIGATION_GESTURE_H_
+
+enum NavigationGesture {
+ NavigationGestureUser, // User initiated navigation/load. This is not
+ // currently used due to the untrustworthy nature
+ // of userGestureHint (wasRunByUserGesture). See
+ // bug 1051891.
+ NavigationGestureAuto, // Non-user initiated navigation / load. For example
+ // onload or setTimeout triggered document.location
+ // changes, and form.submits. See bug 1046841 for
+ // some cases that should be treated this way but
+ // aren't yet.
+ NavigationGestureUnknown, // What we assign when userGestureHint returns true
+ // because we can't trust it.
+};
+
+#endif // CHROME_COMMON_NAVIGATION_GESTURE_H_
diff --git a/chrome/common/navigation_types.h b/chrome/common/navigation_types.h
new file mode 100644
index 0000000..c871201
--- /dev/null
+++ b/chrome/common/navigation_types.h
@@ -0,0 +1,66 @@
+// Copyright (c) 2006-2008 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_COMMON_NAVIGATION_TYPES_H_
+#define CHROME_COMMON_NAVIGATION_TYPES_H_
+
+#include "base/basictypes.h"
+
+// Indicates different types of navigations that can occur that we will handle
+// separately.
+class NavigationType {
+ public:
+ enum Type {
+ // Unknown type.
+ UNKNOWN,
+
+ // A new page was navigated in the main frame.
+ NEW_PAGE,
+
+ // Renavigating to an existing navigation entry. The entry is guaranteed to
+ // exist in the list, or else it would be a new page or IGNORE navigation.
+ EXISTING_PAGE,
+
+ // The same page has been reloaded as a result of the user requesting
+ // navigation to that same page (like pressing Enter in the URL bar). This
+ // is not the same as an in-page navigation because we'll actually have a
+ // pending entry for the load, which is then meaningless.
+ SAME_PAGE,
+
+ // In page navigations are when the reference fragment changes. This will
+ // be in the main frame only (we won't even get notified of in-page
+ // subframe navigations). It may be for any page, not necessarily the last
+ // committed one (for example, whey going back to a page with a ref).
+ IN_PAGE,
+
+ // A new subframe was manually navigated by the user. We will create a new
+ // NavigationEntry so they can go back to the previous subframe content
+ // using the back button.
+ NEW_SUBFRAME,
+
+ // A subframe in the page was automatically loaded or navigated to such that
+ // a new navigation entry should not be created. There are two cases:
+ // 1. Stuff like iframes containing ads that the page loads automatically.
+ // The user doesn't want to see these, so we just update the existing
+ // navigation entry.
+ // 2. Going back/forward to previous subframe navigations. We don't create
+ // a new entry here either, just update the last committed entry.
+ // These two cases are actually pretty different, they just happen to
+ // require almost the same code to handle.
+ AUTO_SUBFRAME,
+
+ // Nothing happened. This happens when we get information about a page we
+ // don't know anything about. It can also happen when an iframe in a popup
+ // navigated to about:blank is navigated. Nothing needs to be done.
+ NAV_IGNORE,
+ };
+
+ private:
+ // This class is for scoping only, so you shouldn't create an instance of it.
+ NavigationType() {}
+
+ DISALLOW_COPY_AND_ASSIGN(NavigationType);
+};
+
+#endif // CHROME_COMMON_NAVIGATION_TYPES_H_
diff --git a/chrome/common/net/gaia/gaia_auth_consumer.h b/chrome/common/net/gaia/gaia_auth_consumer.h
new file mode 100644
index 0000000..b7b215c
--- /dev/null
+++ b/chrome/common/net/gaia/gaia_auth_consumer.h
@@ -0,0 +1,73 @@
+// Copyright (c) 2010 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_COMMON_NET_GAIA_GAIA_AUTH_CONSUMER_H_
+#define CHROME_COMMON_NET_GAIA_GAIA_AUTH_CONSUMER_H_
+
+#include <string>
+
+// An interface that defines the callbacks for objects that
+// GaiaAuthenticator2 can return data to.
+class GaiaAuthConsumer {
+ public:
+ struct ClientLoginResult {
+ inline ClientLoginResult() {}
+ inline ClientLoginResult(const std::string& new_sid,
+ const std::string& new_lsid,
+ const std::string& new_token,
+ const std::string& new_data)
+ : sid(new_sid),
+ lsid(new_lsid),
+ token(new_token),
+ data(new_data) {}
+
+ inline bool operator==(const ClientLoginResult &b) const {
+ return sid == b.sid &&
+ lsid == b.lsid &&
+ token == b.token &&
+ data == b.data;
+ }
+
+ std::string sid;
+ std::string lsid;
+ std::string token;
+ // TODO(chron): Remove the data field later. Don't use it if possible.
+ std::string data; // Full contents of ClientLogin return.
+ };
+
+ enum GaiaAuthErrorCode {
+ NETWORK_ERROR,
+ REQUEST_CANCELED,
+ TWO_FACTOR, // Callers can treat this as a success.
+ PERMISSION_DENIED
+ };
+
+ struct GaiaAuthError {
+ inline bool operator==(const GaiaAuthError &b) const {
+ if (code != b.code) {
+ return false;
+ }
+ if (code == NETWORK_ERROR) {
+ return network_error == b.network_error;
+ }
+ return true;
+ }
+
+ GaiaAuthErrorCode code;
+ int network_error; // This field is only valid if NETWORK_ERROR occured.
+ std::string data; // TODO(chron): Remove this field. Should preparse data.
+ };
+
+ virtual ~GaiaAuthConsumer() {}
+
+ virtual void OnClientLoginSuccess(const ClientLoginResult& result) {}
+ virtual void OnClientLoginFailure(const GaiaAuthError& error) {}
+
+ virtual void OnIssueAuthTokenSuccess(const std::string& service,
+ const std::string& auth_token) {}
+ virtual void OnIssueAuthTokenFailure(const std::string& service,
+ const GaiaAuthError& error) {}
+};
+
+#endif // CHROME_COMMON_NET_GAIA_GAIA_AUTH_CONSUMER_H_
diff --git a/chrome/common/net/gaia/gaia_authenticator.cc b/chrome/common/net/gaia/gaia_authenticator.cc
new file mode 100644
index 0000000..f544e94
--- /dev/null
+++ b/chrome/common/net/gaia/gaia_authenticator.cc
@@ -0,0 +1,376 @@
+// Copyright (c) 2009 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/common/net/gaia/gaia_authenticator.h"
+
+#include <string>
+#include <utility>
+#include <vector>
+
+#include "base/basictypes.h"
+#include "base/port.h"
+#include "base/string_split.h"
+#include "chrome/common/deprecated/event_sys-inl.h"
+#include "chrome/common/net/http_return.h"
+#include "googleurl/src/gurl.h"
+#include "net/base/escape.h"
+
+using std::pair;
+using std::string;
+using std::vector;
+
+namespace gaia {
+
+static const char kGaiaV1IssueAuthTokenPath[] = "/accounts/IssueAuthToken";
+
+static const char kGetUserInfoPath[] = "/accounts/GetUserInfo";
+
+// Sole constructor with initializers for all fields.
+GaiaAuthenticator::GaiaAuthenticator(const string& user_agent,
+ const string& service_id,
+ const string& gaia_url)
+ : user_agent_(user_agent),
+ service_id_(service_id),
+ gaia_url_(gaia_url),
+ request_count_(0),
+ delay_(0),
+ next_allowed_auth_attempt_time_(0),
+ early_auth_attempt_count_(0),
+ message_loop_(NULL) {
+ GaiaAuthEvent done = { GaiaAuthEvent::GAIA_AUTHENTICATOR_DESTROYED, None,
+ this };
+ channel_ = new Channel(done);
+}
+
+GaiaAuthenticator::~GaiaAuthenticator() {
+ delete channel_;
+}
+
+// mutex_ must be entered before calling this function.
+GaiaAuthenticator::AuthParams GaiaAuthenticator::MakeParams(
+ const string& user_name,
+ const string& password,
+ const string& captcha_token,
+ const string& captcha_value) {
+ AuthParams params;
+ params.request_id = ++request_count_;
+ params.email = user_name;
+ params.password = password;
+ params.captcha_token = captcha_token;
+ params.captcha_value = captcha_value;
+ params.authenticator = this;
+ return params;
+}
+
+bool GaiaAuthenticator::Authenticate(const string& user_name,
+ const string& password,
+ const string& captcha_token,
+ const string& captcha_value) {
+ DCHECK_EQ(MessageLoop::current(), message_loop_);
+
+ AuthParams const params =
+ MakeParams(user_name, password, captcha_token, captcha_value);
+ return AuthenticateImpl(params);
+}
+
+bool GaiaAuthenticator::AuthenticateWithLsid(const string& lsid) {
+ auth_results_.lsid = lsid;
+ // We need to lookup the email associated with this LSID cookie in order to
+ // update |auth_results_| with the correct values.
+ if (LookupEmail(&auth_results_)) {
+ auth_results_.email = auth_results_.primary_email;
+ return IssueAuthToken(&auth_results_, service_id_);
+ }
+ return false;
+}
+
+bool GaiaAuthenticator::AuthenticateImpl(const AuthParams& params) {
+ DCHECK_EQ(MessageLoop::current(), message_loop_);
+ AuthResults results;
+ const bool succeeded = AuthenticateImpl(params, &results);
+ if (params.request_id == request_count_) {
+ auth_results_ = results;
+ GaiaAuthEvent event = { succeeded ? GaiaAuthEvent::GAIA_AUTH_SUCCEEDED
+ : GaiaAuthEvent::GAIA_AUTH_FAILED,
+ results.auth_error, this };
+ channel_->NotifyListeners(event);
+ }
+ return succeeded;
+}
+
+// This method makes an HTTP request to the Gaia server, and calls other
+// methods to help parse the response. If authentication succeeded, then
+// Gaia-issued cookies are available in the respective variables; if
+// authentication failed, then the exact error is available as an enum. If the
+// client wishes to save the credentials, the last parameter must be true.
+// If a subsequent request is made with fresh credentials, the saved credentials
+// are wiped out; any subsequent request to the zero-parameter overload of this
+// method preserves the saved credentials.
+bool GaiaAuthenticator::AuthenticateImpl(const AuthParams& params,
+ AuthResults* results) {
+ DCHECK_EQ(MessageLoop::current(), message_loop_);
+ results->auth_error = ConnectionUnavailable;
+ results->email = params.email.data();
+ results->password = params.password;
+
+ // The aim of this code is to start failing requests if due to a logic error
+ // in the program we're hammering GAIA.
+#if defined(OS_WIN)
+ __time32_t now = _time32(0);
+#else // defined(OS_WIN)
+ time_t now = time(0);
+#endif // defined(OS_WIN)
+
+ if (now > next_allowed_auth_attempt_time_) {
+ next_allowed_auth_attempt_time_ = now + 1;
+ // If we're more than 2 minutes past the allowed time we reset the early
+ // attempt count.
+ if (now - next_allowed_auth_attempt_time_ > 2 * 60) {
+ delay_ = 1;
+ early_auth_attempt_count_ = 0;
+ }
+ } else {
+ ++early_auth_attempt_count_;
+ // Allow 3 attempts, but then limit.
+ if (early_auth_attempt_count_ > 3) {
+ delay_ = GetBackoffDelaySeconds(delay_);
+ next_allowed_auth_attempt_time_ = now + delay_;
+ return false;
+ }
+ }
+
+ return PerformGaiaRequest(params, results);
+}
+
+bool GaiaAuthenticator::PerformGaiaRequest(const AuthParams& params,
+ AuthResults* results) {
+ DCHECK_EQ(MessageLoop::current(), message_loop_);
+ GURL gaia_auth_url(gaia_url_);
+
+ string post_body;
+ post_body += "Email=" + EscapeUrlEncodedData(params.email);
+ post_body += "&Passwd=" + EscapeUrlEncodedData(params.password);
+ post_body += "&source=" + EscapeUrlEncodedData(user_agent_);
+ post_body += "&service=" + service_id_;
+ if (!params.captcha_token.empty() && !params.captcha_value.empty()) {
+ post_body += "&logintoken=" + EscapeUrlEncodedData(params.captcha_token);
+ post_body += "&logincaptcha=" + EscapeUrlEncodedData(params.captcha_value);
+ }
+ post_body += "&PersistentCookie=true";
+ // We set it to GOOGLE (and not HOSTED or HOSTED_OR_GOOGLE) because we only
+ // allow consumer logins.
+ post_body += "&accountType=GOOGLE";
+
+ string message_text;
+ unsigned long server_response_code;
+ if (!Post(gaia_auth_url, post_body, &server_response_code, &message_text)) {
+ results->auth_error = ConnectionUnavailable;
+ return false;
+ }
+
+ // Parse reply in two different ways, depending on if request failed or
+ // succeeded.
+ if (RC_FORBIDDEN == server_response_code) {
+ ExtractAuthErrorFrom(message_text, results);
+ return false;
+ } else if (RC_REQUEST_OK == server_response_code) {
+ ExtractTokensFrom(message_text, results);
+ if (!IssueAuthToken(results, service_id_)) {
+ return false;
+ }
+
+ return LookupEmail(results);
+ } else {
+ results->auth_error = Unknown;
+ return false;
+ }
+}
+
+bool GaiaAuthenticator::LookupEmail(AuthResults* results) {
+ DCHECK_EQ(MessageLoop::current(), message_loop_);
+ // Use the provided Gaia server, but change the path to what V1 expects.
+ GURL url(gaia_url_); // Gaia server.
+ GURL::Replacements repl;
+ // Needs to stay in scope till GURL is out of scope.
+ string path(kGetUserInfoPath);
+ repl.SetPathStr(path);
+ url = url.ReplaceComponents(repl);
+
+ string post_body;
+ post_body += "LSID=";
+ post_body += EscapeUrlEncodedData(results->lsid);
+
+ unsigned long server_response_code;
+ string message_text;
+ if (!Post(url, post_body, &server_response_code, &message_text)) {
+ return false;
+ }
+
+ // Check if we received a valid AuthToken; if not, ignore it.
+ if (RC_FORBIDDEN == server_response_code) {
+ // Server says we're not authenticated.
+ ExtractAuthErrorFrom(message_text, results);
+ return false;
+ } else if (RC_REQUEST_OK == server_response_code) {
+ typedef vector<pair<string, string> > Tokens;
+ Tokens tokens;
+ base::SplitStringIntoKeyValuePairs(message_text, '=', '\n', &tokens);
+ for (Tokens::iterator i = tokens.begin(); i != tokens.end(); ++i) {
+ if ("accountType" == i->first) {
+ // We never authenticate an email as a hosted account.
+ DCHECK_EQ("GOOGLE", i->second);
+ } else if ("email" == i->first) {
+ results->primary_email = i->second;
+ }
+ }
+ return true;
+ }
+ return false;
+}
+
+// We need to call this explicitly when we need to obtain a long-lived session
+// token.
+bool GaiaAuthenticator::IssueAuthToken(AuthResults* results,
+ const string& service_id) {
+ DCHECK_EQ(MessageLoop::current(), message_loop_);
+ // Use the provided Gaia server, but change the path to what V1 expects.
+ GURL url(gaia_url_); // Gaia server.
+ GURL::Replacements repl;
+ // Needs to stay in scope till GURL is out of scope.
+ string path(kGaiaV1IssueAuthTokenPath);
+ repl.SetPathStr(path);
+ url = url.ReplaceComponents(repl);
+
+ string post_body;
+ post_body += "LSID=";
+ post_body += EscapeUrlEncodedData(results->lsid);
+ post_body += "&service=" + service_id;
+ post_body += "&Session=true";
+
+ unsigned long server_response_code;
+ string message_text;
+ if (!Post(url, post_body, &server_response_code, &message_text)) {
+ return false;
+ }
+
+ // Check if we received a valid AuthToken; if not, ignore it.
+ if (RC_FORBIDDEN == server_response_code) {
+ // Server says we're not authenticated.
+ ExtractAuthErrorFrom(message_text, results);
+ return false;
+ } else if (RC_REQUEST_OK == server_response_code) {
+ // Note that the format of message_text is different from what is returned
+ // in the first request, or to the sole request that is made to Gaia V2.
+ // Specifically, the entire string is the AuthToken, and looks like:
+ // "<token>" rather than "AuthToken=<token>". Thus, we need not use
+ // ExtractTokensFrom(...), but simply assign the token.
+ int last_index = message_text.length() - 1;
+ if ('\n' == message_text[last_index])
+ message_text.erase(last_index);
+ results->auth_token = message_text;
+ return true;
+ }
+ return false;
+}
+
+// Helper method that extracts tokens from a successful reply, and saves them
+// in the right fields.
+void GaiaAuthenticator::ExtractTokensFrom(const string& response,
+ AuthResults* results) {
+ vector<pair<string, string> > tokens;
+ base::SplitStringIntoKeyValuePairs(response, '=', '\n', &tokens);
+ for (vector<pair<string, string> >::iterator i = tokens.begin();
+ i != tokens.end(); ++i) {
+ if (i->first == "SID") {
+ results->sid = i->second;
+ } else if (i->first == "LSID") {
+ results->lsid = i->second;
+ } else if (i->first == "Auth") {
+ results->auth_token = i->second;
+ }
+ }
+}
+
+// Helper method that extracts tokens from a failure response, and saves them
+// in the right fields.
+void GaiaAuthenticator::ExtractAuthErrorFrom(const string& response,
+ AuthResults* results) {
+ vector<pair<string, string> > tokens;
+ base::SplitStringIntoKeyValuePairs(response, '=', '\n', &tokens);
+ for (vector<pair<string, string> >::iterator i = tokens.begin();
+ i != tokens.end(); ++i) {
+ if (i->first == "Error") {
+ results->error_msg = i->second;
+ } else if (i->first == "Url") {
+ results->auth_error_url = i->second;
+ } else if (i->first == "CaptchaToken") {
+ results->captcha_token = i->second;
+ } else if (i->first == "CaptchaUrl") {
+ results->captcha_url = i->second;
+ }
+ }
+
+ // Convert string error messages to enum values. Each case has two different
+ // strings; the first one is the most current and the second one is
+ // deprecated, but available.
+ const string& error_msg = results->error_msg;
+ if (error_msg == "BadAuthentication" || error_msg == "badauth") {
+ results->auth_error = BadAuthentication;
+ } else if (error_msg == "NotVerified" || error_msg == "nv") {
+ results->auth_error = NotVerified;
+ } else if (error_msg == "TermsNotAgreed" || error_msg == "tna") {
+ results->auth_error = TermsNotAgreed;
+ } else if (error_msg == "Unknown" || error_msg == "unknown") {
+ results->auth_error = Unknown;
+ } else if (error_msg == "AccountDeleted" || error_msg == "adel") {
+ results->auth_error = AccountDeleted;
+ } else if (error_msg == "AccountDisabled" || error_msg == "adis") {
+ results->auth_error = AccountDisabled;
+ } else if (error_msg == "CaptchaRequired" || error_msg == "cr") {
+ results->auth_error = CaptchaRequired;
+ } else if (error_msg == "ServiceUnavailable" || error_msg == "ire") {
+ results->auth_error = ServiceUnavailable;
+ }
+}
+
+// Reset all stored credentials, perhaps in preparation for letting a different
+// user sign in.
+void GaiaAuthenticator::ResetCredentials() {
+ DCHECK_EQ(MessageLoop::current(), message_loop_);
+ AuthResults blank;
+ auth_results_ = blank;
+}
+
+void GaiaAuthenticator::SetUsernamePassword(const string& username,
+ const string& password) {
+ DCHECK_EQ(MessageLoop::current(), message_loop_);
+ auth_results_.password = password;
+ auth_results_.email = username;
+}
+
+void GaiaAuthenticator::SetUsername(const string& username) {
+ DCHECK_EQ(MessageLoop::current(), message_loop_);
+ auth_results_.email = username;
+}
+
+void GaiaAuthenticator::RenewAuthToken(const string& auth_token) {
+ DCHECK_EQ(MessageLoop::current(), message_loop_);
+ DCHECK(!this->auth_token().empty());
+ auth_results_.auth_token = auth_token;
+}
+void GaiaAuthenticator::SetAuthToken(const string& auth_token) {
+ DCHECK_EQ(MessageLoop::current(), message_loop_);
+ auth_results_.auth_token = auth_token;
+}
+
+bool GaiaAuthenticator::Authenticate(const string& user_name,
+ const string& password) {
+ DCHECK_EQ(MessageLoop::current(), message_loop_);
+ const string empty;
+ return Authenticate(user_name, password, empty,
+ empty);
+}
+
+} // namepace gaia
+
diff --git a/chrome/common/net/gaia/gaia_authenticator.h b/chrome/common/net/gaia/gaia_authenticator.h
new file mode 100644
index 0000000..d34af2d
--- /dev/null
+++ b/chrome/common/net/gaia/gaia_authenticator.h
@@ -0,0 +1,302 @@
+// Copyright (c) 2009 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.
+//
+// Use this class to authenticate users with Gaia and access cookies sent
+// by the Gaia servers. This class cannot be used on its own becaue it relies
+// on a subclass to provide the virtual Post and GetBackoffDelaySeconds methods.
+//
+// Sample usage:
+// class ActualGaiaAuthenticator : public gaia::GaiaAuthenticator {
+// Provides actual implementation of Post and GetBackoffDelaySeconds.
+// };
+// ActualGaiaAuthenticator gaia_auth("User-Agent", SERVICE_NAME, kGaiaUrl);
+// if (gaia_auth.Authenticate("email", "passwd", SAVE_IN_MEMORY_ONLY,
+// true)) { // Synchronous
+// // Do something with: gaia_auth.auth_token(), or gaia_auth.sid(),
+// // or gaia_auth.lsid()
+// }
+//
+// Credentials can also be preserved for subsequent requests, though these are
+// saved in plain-text in memory, and not very secure on client systems. The
+// email address associated with the Gaia account can be read; the password is
+// write-only.
+
+// TODO(sanjeevr): This class has been moved here from the bookmarks sync code.
+// While it is a generic class that handles GAIA authentication, there are some
+// artifacts of the sync code which needs to be cleaned up.
+#ifndef CHROME_COMMON_NET_GAIA_GAIA_AUTHENTICATOR_H_
+#define CHROME_COMMON_NET_GAIA_GAIA_AUTHENTICATOR_H_
+
+#include <string>
+
+#include "base/basictypes.h"
+#include "base/message_loop.h"
+#include "chrome/common/deprecated/event_sys.h"
+#include "googleurl/src/gurl.h"
+#include "testing/gtest/include/gtest/gtest_prod.h" // For FRIEND_TEST
+
+namespace gaia {
+
+static const char kGaiaUrl[] =
+ "https://www.google.com:443/accounts/ClientLogin";
+
+// Error codes from Gaia. These will be set correctly for both Gaia V1
+// (/ClientAuth) and V2 (/ClientLogin)
+enum AuthenticationError {
+ None = 0,
+ BadAuthentication = 1,
+ NotVerified = 2,
+ TermsNotAgreed = 3,
+ Unknown = 4,
+ AccountDeleted = 5,
+ AccountDisabled = 6,
+ CaptchaRequired = 7,
+ ServiceUnavailable = 8,
+ // Errors generated by this class not Gaia.
+ CredentialsNotSet = 9,
+ ConnectionUnavailable = 10
+};
+
+class GaiaAuthenticator;
+
+struct GaiaAuthEvent {
+ enum {
+ GAIA_AUTH_FAILED,
+ GAIA_AUTH_SUCCEEDED,
+ GAIA_AUTHENTICATOR_DESTROYED
+ }
+ what_happened;
+ AuthenticationError error;
+ const GaiaAuthenticator* authenticator;
+
+ // Lets us use GaiaAuthEvent as its own traits type in hookups.
+ typedef GaiaAuthEvent EventType;
+ static inline bool IsChannelShutdownEvent(const GaiaAuthEvent& event) {
+ return event.what_happened == GAIA_AUTHENTICATOR_DESTROYED;
+ }
+};
+
+// GaiaAuthenticator can be used to pass user credentials to Gaia and obtain
+// cookies set by the Gaia servers.
+class GaiaAuthenticator {
+ FRIEND_TEST(GaiaAuthenticatorTest, TestNewlineAtEndOfAuthTokenRemoved);
+ public:
+
+ // Since GaiaAuthenticator can be used for any service, or by any client, you
+ // must include a user-agent and a service-id when creating one. The
+ // user_agent is a short string used for simple log analysis. gaia_url is used
+ // to choose the server to authenticate with (e.g.
+ // http://www.google.com/accounts/ClientLogin).
+ GaiaAuthenticator(const std::string& user_agent,
+ const std::string& service_id,
+ const std::string& gaia_url);
+
+ virtual ~GaiaAuthenticator();
+
+ // This object should only be invoked from the AuthWatcherThread message
+ // loop, which is injected here.
+ void set_message_loop(const MessageLoop* loop) {
+ message_loop_ = loop;
+ }
+
+ // Pass credentials to authenticate with, or use saved credentials via an
+ // overload. If authentication succeeds, you can retrieve the authentication
+ // token via the respective accessors. Returns a boolean indicating whether
+ // authentication succeeded or not.
+ bool Authenticate(const std::string& user_name, const std::string& password,
+ const std::string& captcha_token,
+ const std::string& captcha_value);
+
+ bool Authenticate(const std::string& user_name, const std::string& password);
+
+ // Pass the LSID to authenticate with. If the authentication succeeds, you can
+ // retrieve the authetication token via the respective accessors. Returns a
+ // boolean indicating whether authentication succeeded or not.
+ // Always returns a long lived token.
+ bool AuthenticateWithLsid(const std::string& lsid);
+
+ // Resets all stored cookies to their default values.
+ void ResetCredentials();
+
+ void SetUsernamePassword(const std::string& username,
+ const std::string& password);
+
+ void SetUsername(const std::string& username);
+
+ // Virtual for testing
+ virtual void RenewAuthToken(const std::string& auth_token);
+ void SetAuthToken(const std::string& auth_token);
+
+ struct AuthResults {
+ std::string email;
+ std::string password;
+
+ // Fields that store various cookies.
+ std::string sid;
+ std::string lsid;
+ std::string auth_token;
+
+ std::string primary_email;
+
+ // Fields for items returned when authentication fails.
+ std::string error_msg;
+ enum AuthenticationError auth_error;
+ std::string auth_error_url;
+ std::string captcha_token;
+ std::string captcha_url;
+
+ AuthResults() : auth_error(None) {}
+ };
+
+ protected:
+
+ struct AuthParams {
+ GaiaAuthenticator* authenticator;
+ uint32 request_id;
+ std::string email;
+ std::string password;
+ std::string captcha_token;
+ std::string captcha_value;
+ };
+
+ // mutex_ must be entered before calling this function.
+ AuthParams MakeParams(const std::string& user_name,
+ const std::string& password,
+ const std::string& captcha_token,
+ const std::string& captcha_value);
+
+ // The real Authenticate implementations.
+ bool AuthenticateImpl(const AuthParams& params);
+ bool AuthenticateImpl(const AuthParams& params, AuthResults* results);
+
+ // virtual for testing purposes.
+ virtual bool PerformGaiaRequest(const AuthParams& params,
+ AuthResults* results);
+ virtual bool Post(const GURL& url, const std::string& post_body,
+ unsigned long* response_code, std::string* response_body) {
+ return false;
+ }
+
+ // Caller should fill in results->LSID before calling. Result in
+ // results->primary_email.
+ virtual bool LookupEmail(AuthResults* results);
+
+ // Subclasses must override to provide a backoff delay. It is virtual instead
+ // of pure virtual for testing purposes.
+ // TODO(sanjeevr): This should be made pure virtual. But this class is
+ // currently directly being used in sync/engine/authenticator.cc, which is
+ // wrong.
+ virtual int GetBackoffDelaySeconds(int current_backoff_delay) {
+ NOTREACHED();
+ return current_backoff_delay;
+ }
+
+ public:
+ // Retrieve email.
+ inline std::string email() const {
+ DCHECK_EQ(MessageLoop::current(), message_loop_);
+ return auth_results_.email;
+ }
+
+ // Retrieve password.
+ inline std::string password() const {
+ DCHECK_EQ(MessageLoop::current(), message_loop_);
+ return auth_results_.password;
+ }
+
+ // Retrieve AuthToken, if previously authenticated; otherwise returns "".
+ inline std::string auth_token() const {
+ DCHECK_EQ(MessageLoop::current(), message_loop_);
+ return auth_results_.auth_token;
+ }
+
+ // Retrieve SID cookie. For details, see the Google Accounts documentation.
+ inline std::string sid() const {
+ DCHECK_EQ(MessageLoop::current(), message_loop_);
+ return auth_results_.sid;
+ }
+
+ // Retrieve LSID cookie. For details, see the Google Accounts documentation.
+ inline std::string lsid() const {
+ DCHECK_EQ(MessageLoop::current(), message_loop_);
+ return auth_results_.lsid;
+ }
+
+ // Get last authentication error.
+ inline enum AuthenticationError auth_error() const {
+ DCHECK_EQ(MessageLoop::current(), message_loop_);
+ return auth_results_.auth_error;
+ }
+
+ inline std::string auth_error_url() const {
+ DCHECK_EQ(MessageLoop::current(), message_loop_);
+ return auth_results_.auth_error_url;
+ }
+
+ inline std::string captcha_token() const {
+ DCHECK_EQ(MessageLoop::current(), message_loop_);
+ return auth_results_.captcha_token;
+ }
+
+ inline std::string captcha_url() const {
+ DCHECK_EQ(MessageLoop::current(), message_loop_);
+ return auth_results_.captcha_url;
+ }
+
+ inline AuthResults results() const {
+ DCHECK_EQ(MessageLoop::current(), message_loop_);
+ return auth_results_;
+ }
+
+ typedef EventChannel<GaiaAuthEvent, Lock> Channel;
+
+ inline Channel* channel() const {
+ return channel_;
+ }
+
+ private:
+ bool IssueAuthToken(AuthResults* results, const std::string& service_id);
+
+ // Helper method to parse response when authentication succeeds.
+ void ExtractTokensFrom(const std::string& response, AuthResults* results);
+ // Helper method to parse response when authentication fails.
+ void ExtractAuthErrorFrom(const std::string& response, AuthResults* results);
+
+ // Fields for the obvious data items.
+ const std::string user_agent_;
+ const std::string service_id_;
+ const std::string gaia_url_;
+
+ AuthResults auth_results_;
+
+ // When multiple async requests are running, only the one that started most
+ // recently updates the values.
+ //
+ // Note that even though this code was written to handle multiple requests
+ // simultaneously, the sync code issues auth requests one at a time.
+ uint32 request_count_;
+
+ Channel* channel_;
+
+ // Used to compute backoff time for next allowed authentication.
+ int delay_; // In seconds.
+ // On Windows, time_t is 64-bit by default. Even though we have defined the
+ // _USE_32BIT_TIME_T preprocessor flag, other libraries including this header
+ // may not have that preprocessor flag defined resulting in mismatched class
+ // sizes. So we explicitly define it as 32-bit on Windows.
+ // TODO(sanjeevr): Change this to to use base::Time
+#if defined(OS_WIN)
+ __time32_t next_allowed_auth_attempt_time_;
+#else // defined(OS_WIN)
+ time_t next_allowed_auth_attempt_time_;
+#endif // defined(OS_WIN)
+ int early_auth_attempt_count_;
+
+ // The message loop all our methods are invoked on.
+ const MessageLoop* message_loop_;
+};
+
+} // namespace gaia
+#endif // CHROME_COMMON_NET_GAIA_GAIA_AUTHENTICATOR_H_
+
diff --git a/chrome/common/net/gaia/gaia_authenticator2.cc b/chrome/common/net/gaia/gaia_authenticator2.cc
new file mode 100644
index 0000000..abc0efe
--- /dev/null
+++ b/chrome/common/net/gaia/gaia_authenticator2.cc
@@ -0,0 +1,292 @@
+// Copyright (c) 2010 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/common/net/gaia/gaia_authenticator2.h"
+
+#include <string>
+
+#include "base/string_split.h"
+#include "base/string_util.h"
+#include "chrome/common/net/gaia/gaia_auth_consumer.h"
+#include "chrome/common/net/http_return.h"
+#include "chrome/common/net/url_request_context_getter.h"
+#include "net/base/load_flags.h"
+#include "net/url_request/url_request_status.h"
+#include "third_party/libjingle/source/talk/base/urlencode.h"
+
+// TODO(chron): Add sourceless version of this formatter.
+// static
+const char GaiaAuthenticator2::kClientLoginFormat[] =
+ "Email=%s&"
+ "Passwd=%s&"
+ "PersistentCookie=%s&"
+ "accountType=%s&"
+ "source=%s&"
+ "service=%s";
+// static
+const char GaiaAuthenticator2::kClientLoginCaptchaFormat[] =
+ "Email=%s&"
+ "Passwd=%s&"
+ "PersistentCookie=%s&"
+ "accountType=%s&"
+ "source=%s&"
+ "service=%s&"
+ "logintoken=%s&"
+ "logincaptcha=%s";
+// static
+const char GaiaAuthenticator2::kIssueAuthTokenFormat[] =
+ "SID=%s&"
+ "LSID=%s&"
+ "service=%s&"
+ "Session=true";
+
+// static
+const char GaiaAuthenticator2::kCookiePersistence[] = "true";
+// static
+const char GaiaAuthenticator2::kAccountType[] = "HOSTED_OR_GOOGLE";
+// static
+const char GaiaAuthenticator2::kChromeOSSource[] = "chromeos";
+// static
+// Service name for Gaia Contacts API. API is used to get user's image.
+const char GaiaAuthenticator2::kContactsService[] = "cp";
+// static
+const char GaiaAuthenticator2::kSecondFactor[] = "Info=InvalidSecondFactor";
+
+// TODO(chron): These urls are also in auth_response_handler.h.
+// The URLs for different calls in the Google Accounts programmatic login API.
+const char GaiaAuthenticator2::kClientLoginUrl[] =
+ "https://www.google.com/accounts/ClientLogin";
+const char GaiaAuthenticator2::kIssueAuthTokenUrl[] =
+ "https://www.google.com/accounts/IssueAuthToken";
+
+GaiaAuthenticator2::GaiaAuthenticator2(GaiaAuthConsumer* consumer,
+ const std::string& source,
+ URLRequestContextGetter* getter)
+ : consumer_(consumer),
+ getter_(getter),
+ source_(source),
+ client_login_gurl_(kClientLoginUrl),
+ issue_auth_token_gurl_(kIssueAuthTokenUrl),
+ fetch_pending_(false) {}
+
+GaiaAuthenticator2::~GaiaAuthenticator2() {}
+
+bool GaiaAuthenticator2::HasPendingFetch() {
+ return fetch_pending_;
+}
+
+void GaiaAuthenticator2::CancelRequest() {
+ fetcher_.reset();
+ fetch_pending_ = false;
+}
+
+// static
+URLFetcher* GaiaAuthenticator2::CreateGaiaFetcher(
+ URLRequestContextGetter* getter,
+ const std::string& body,
+ const GURL& gaia_gurl,
+ URLFetcher::Delegate* delegate) {
+
+ URLFetcher* to_return =
+ URLFetcher::Create(0,
+ gaia_gurl,
+ URLFetcher::POST,
+ delegate);
+ to_return->set_request_context(getter);
+ to_return->set_load_flags(net::LOAD_DO_NOT_SEND_COOKIES);
+ to_return->set_upload_data("application/x-www-form-urlencoded", body);
+ return to_return;
+}
+
+// static
+std::string GaiaAuthenticator2::MakeClientLoginBody(
+ const std::string& username,
+ const std::string& password,
+ const std::string& source,
+ const char* service,
+ const std::string& login_token,
+ const std::string& login_captcha) {
+
+ if (login_token.empty() || login_captcha.empty()) {
+ return StringPrintf(kClientLoginFormat,
+ UrlEncodeString(username).c_str(),
+ UrlEncodeString(password).c_str(),
+ kCookiePersistence,
+ kAccountType,
+ source.c_str(),
+ service);
+ }
+
+ return StringPrintf(kClientLoginCaptchaFormat,
+ UrlEncodeString(username).c_str(),
+ UrlEncodeString(password).c_str(),
+ kCookiePersistence,
+ kAccountType,
+ source.c_str(),
+ service,
+ UrlEncodeString(login_token).c_str(),
+ UrlEncodeString(login_captcha).c_str());
+
+}
+
+// static
+std::string GaiaAuthenticator2::MakeIssueAuthTokenBody(
+ const std::string& sid,
+ const std::string& lsid,
+ const char* const service) {
+
+ return StringPrintf(kIssueAuthTokenFormat,
+ UrlEncodeString(sid).c_str(),
+ UrlEncodeString(lsid).c_str(),
+ service);
+}
+
+// Helper method that extracts tokens from a successful reply.
+// static
+void GaiaAuthenticator2::ParseClientLoginResponse(const std::string& data,
+ std::string* sid,
+ std::string* lsid,
+ std::string* token) {
+ using std::vector;
+ using std::pair;
+ using std::string;
+
+ vector<pair<string, string> > tokens;
+ base::SplitStringIntoKeyValuePairs(data, '=', '\n', &tokens);
+ for (vector<pair<string, string> >::iterator i = tokens.begin();
+ i != tokens.end(); ++i) {
+ if (i->first == "SID") {
+ sid->assign(i->second);
+ } else if (i->first == "LSID") {
+ lsid->assign(i->second);
+ } else if (i->first == "Auth") {
+ token->assign(i->second);
+ }
+ }
+}
+
+void GaiaAuthenticator2::StartClientLogin(const std::string& username,
+ const std::string& password,
+ const char* const service,
+ const std::string& login_token,
+ const std::string& login_captcha) {
+
+ DCHECK(!fetch_pending_) << "Tried to fetch two things at once!";
+
+ // This class is thread agnostic, so be sure to call this only on the
+ // same thread each time.
+ LOG(INFO) << "Starting new ClientLogin fetch for:" << username;
+
+ // Must outlive fetcher_.
+ request_body_ = MakeClientLoginBody(username,
+ password,
+ source_,
+ service,
+ login_token,
+ login_captcha);
+ fetcher_.reset(CreateGaiaFetcher(getter_,
+ request_body_,
+ client_login_gurl_,
+ this));
+ fetch_pending_ = true;
+ fetcher_->Start();
+}
+
+void GaiaAuthenticator2::StartIssueAuthToken(const std::string& sid,
+ const std::string& lsid,
+ const char* const service) {
+
+ DCHECK(!fetch_pending_) << "Tried to fetch two things at once!";
+
+ LOG(INFO) << "Starting IssueAuthToken for: " << service;
+ requested_service_ = service;
+ request_body_ = MakeIssueAuthTokenBody(sid, lsid, service);
+ fetcher_.reset(CreateGaiaFetcher(getter_,
+ request_body_,
+ issue_auth_token_gurl_,
+ this));
+ fetch_pending_ = true;
+ fetcher_->Start();
+}
+
+GaiaAuthConsumer::GaiaAuthError GaiaAuthenticator2::GenerateAuthError(
+ const std::string& data,
+ const URLRequestStatus& status) {
+
+ GaiaAuthConsumer::GaiaAuthError error;
+ error.data = data;
+
+ if (!status.is_success()) {
+ if (status.status() == URLRequestStatus::CANCELED) {
+ error.code = GaiaAuthConsumer::REQUEST_CANCELED;
+ } else {
+ error.code = GaiaAuthConsumer::NETWORK_ERROR;
+ error.network_error = status.os_error();
+ LOG(WARNING) << "Could not reach Google Accounts servers: errno "
+ << status.os_error();
+ }
+ } else {
+ if (IsSecondFactorSuccess(data)) {
+ error.code = GaiaAuthConsumer::TWO_FACTOR;
+ } else {
+ error.code = GaiaAuthConsumer::PERMISSION_DENIED;
+ }
+ }
+
+ return error;
+}
+
+void GaiaAuthenticator2::OnClientLoginFetched(const std::string& data,
+ const URLRequestStatus& status,
+ int response_code) {
+
+ if (status.is_success() && response_code == RC_REQUEST_OK) {
+ LOG(INFO) << "ClientLogin successful!";
+ std::string sid;
+ std::string lsid;
+ std::string token;
+ ParseClientLoginResponse(data, &sid, &lsid, &token);
+ consumer_->OnClientLoginSuccess(
+ GaiaAuthConsumer::ClientLoginResult(sid, lsid, token, data));
+ } else {
+ consumer_->OnClientLoginFailure(GenerateAuthError(data, status));
+ }
+}
+
+void GaiaAuthenticator2::OnIssueAuthTokenFetched(
+ const std::string& data,
+ const URLRequestStatus& status,
+ int response_code) {
+ if (status.is_success() && response_code == RC_REQUEST_OK) {
+ // Only the bare token is returned in the body of this Gaia call
+ // without any padding.
+ consumer_->OnIssueAuthTokenSuccess(requested_service_, data);
+ } else {
+ consumer_->OnIssueAuthTokenFailure(requested_service_,
+ GenerateAuthError(data, status));
+ }
+}
+
+void GaiaAuthenticator2::OnURLFetchComplete(const URLFetcher* source,
+ const GURL& url,
+ const URLRequestStatus& status,
+ int response_code,
+ const ResponseCookies& cookies,
+ const std::string& data) {
+ fetch_pending_ = false;
+ if (url == client_login_gurl_) {
+ OnClientLoginFetched(data, status, response_code);
+ } else if (url == issue_auth_token_gurl_) {
+ OnIssueAuthTokenFetched(data, status, response_code);
+ } else {
+ NOTREACHED();
+ }
+}
+
+// static
+bool GaiaAuthenticator2::IsSecondFactorSuccess(
+ const std::string& alleged_error) {
+ return alleged_error.find(kSecondFactor) !=
+ std::string::npos;
+}
diff --git a/chrome/common/net/gaia/gaia_authenticator2.h b/chrome/common/net/gaia/gaia_authenticator2.h
new file mode 100644
index 0000000..0e6c203
--- /dev/null
+++ b/chrome/common/net/gaia/gaia_authenticator2.h
@@ -0,0 +1,157 @@
+// Copyright (c) 2010 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_COMMON_NET_GAIA_GAIA_AUTHENTICATOR2_H_
+#define CHROME_COMMON_NET_GAIA_GAIA_AUTHENTICATOR2_H_
+
+#include <string>
+
+#include "base/gtest_prod_util.h"
+#include "base/scoped_ptr.h"
+#include "chrome/common/net/gaia/gaia_auth_consumer.h"
+#include "chrome/common/net/url_fetcher.h"
+#include "googleurl/src/gurl.h"
+
+// Authenticate a user against the Google Accounts ClientLogin API
+// with various capabilities and return results to a GaiaAuthConsumer.
+//
+// In the future, we will also issue auth tokens from this class.
+// This class should be used on a single thread, but it can be whichever thread
+// that you like.
+//
+// This class can handle one request at a time. To parallelize requests,
+// create multiple GaiaAuthenticator2's.
+
+class GaiaAuthenticator2Test;
+
+class GaiaAuthenticator2 : public URLFetcher::Delegate {
+ public:
+ // Constants to use in the ClientLogin request POST body.
+ static const char kChromeOSSource[];
+ static const char kContactsService[];
+
+ // The URLs for different calls in the Google Accounts programmatic login API.
+ static const char kClientLoginUrl[];
+ static const char kIssueAuthTokenUrl[];
+
+ // Magic string indicating that, while a second factor is still
+ // needed to complete authentication, the user provided the right password.
+ static const char kSecondFactor[];
+
+ // This will later be hidden behind an auth service which caches
+ // tokens.
+ GaiaAuthenticator2(GaiaAuthConsumer* consumer,
+ const std::string& source,
+ URLRequestContextGetter* getter);
+ virtual ~GaiaAuthenticator2();
+
+ // GaiaAuthConsumer will be called on the original thread
+ // after results come back. This class is thread agnostic.
+ // You can't make more than request at a time.
+ void StartClientLogin(const std::string& username,
+ const std::string& password,
+ const char* const service,
+ const std::string& login_token,
+ const std::string& login_captcha);
+
+ // GaiaAuthConsumer will be called on the original thread
+ // after results come back. This class is thread agnostic.
+ // You can't make more than one request at a time.
+ void StartIssueAuthToken(const std::string& sid,
+ const std::string& lsid,
+ const char* const service);
+
+ // Implementation of URLFetcher::Delegate
+ void OnURLFetchComplete(const URLFetcher* source,
+ const GURL& url,
+ const URLRequestStatus& status,
+ int response_code,
+ const ResponseCookies& cookies,
+ const std::string& data);
+
+ // StartClientLogin been called && results not back yet?
+ bool HasPendingFetch();
+
+ // Stop any URL fetches in progress.
+ void CancelRequest();
+
+ private:
+ // ClientLogin body constants that don't change
+ static const char kCookiePersistence[];
+ static const char kAccountType[];
+
+ // The format of the POST body for ClientLogin.
+ static const char kClientLoginFormat[];
+ // The format of said POST body when CAPTCHA token & answer are specified.
+ static const char kClientLoginCaptchaFormat[];
+ // The format of the POST body for IssueAuthToken.
+ static const char kIssueAuthTokenFormat[];
+
+ // Process the results of a ClientLogin fetch.
+ void OnClientLoginFetched(const std::string& data,
+ const URLRequestStatus& status,
+ int response_code);
+
+ void OnIssueAuthTokenFetched(const std::string& data,
+ const URLRequestStatus& status,
+ int response_code);
+
+ // Tokenize the results of a ClientLogin fetch.
+ static void ParseClientLoginResponse(const std::string& data,
+ std::string* sid,
+ std::string* lsid,
+ std::string* token);
+
+ // From a URLFetcher result, generate an appropriate GaiaAuthError.
+ // From the API documentation, both IssueAuthToken and ClientLogin have
+ // the same error returns.
+ static GaiaAuthConsumer::GaiaAuthError GenerateAuthError(
+ const std::string& data,
+ const URLRequestStatus& status);
+
+ // Is this a special case Gaia error for TwoFactor auth?
+ static bool IsSecondFactorSuccess(const std::string& alleged_error);
+
+ // Given parameters, create a ClientLogin request body.
+ static std::string MakeClientLoginBody(const std::string& username,
+ const std::string& password,
+ const std::string& source,
+ const char* const service,
+ const std::string& login_token,
+ const std::string& login_captcha);
+ // Supply the sid / lsid returned from ClientLogin in order to
+ // request a long lived auth token for a service.
+ static std::string MakeIssueAuthTokenBody(const std::string& sid,
+ const std::string& lsid,
+ const char* const service);
+
+ // Create a fetcher useable for making any Gaia request.
+ static URLFetcher* CreateGaiaFetcher(URLRequestContextGetter* getter,
+ const std::string& body,
+ const GURL& gaia_gurl_,
+ URLFetcher::Delegate* delegate);
+
+
+ // These fields are common to GaiaAuthenticator2, same every request
+ GaiaAuthConsumer* const consumer_;
+ URLRequestContextGetter* const getter_;
+ std::string source_;
+ const GURL client_login_gurl_;
+ const GURL issue_auth_token_gurl_;
+
+ // While a fetch is going on:
+ scoped_ptr<URLFetcher> fetcher_;
+ std::string request_body_;
+ std::string requested_service_; // Currently tracked for IssueAuthToken only
+ bool fetch_pending_;
+
+ friend class GaiaAuthenticator2Test;
+ FRIEND_TEST_ALL_PREFIXES(GaiaAuthenticator2Test, LoginNetFailure);
+ FRIEND_TEST_ALL_PREFIXES(GaiaAuthenticator2Test, CheckNormalErrorCode);
+ FRIEND_TEST_ALL_PREFIXES(GaiaAuthenticator2Test, CheckTwoFactorResponse);
+
+ DISALLOW_COPY_AND_ASSIGN(GaiaAuthenticator2);
+};
+
+#endif // CHROME_COMMON_NET_GAIA_GAIA_AUTHENTICATOR2_H_
diff --git a/chrome/common/net/gaia/gaia_authenticator2_unittest.cc b/chrome/common/net/gaia/gaia_authenticator2_unittest.cc
new file mode 100644
index 0000000..4e4dc82
--- /dev/null
+++ b/chrome/common/net/gaia/gaia_authenticator2_unittest.cc
@@ -0,0 +1,360 @@
+// Copyright (c) 2010 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.
+//
+// A complete set of unit tests for GaiaAuthenticator2.
+// Originally ported from GoogleAuthenticator tests.
+
+#include <string>
+
+#include "base/message_loop.h"
+#include "base/string_util.h"
+#include "chrome/common/net/gaia/gaia_auth_consumer.h"
+#include "chrome/common/net/gaia/gaia_authenticator2.h"
+#include "chrome/common/net/gaia/gaia_authenticator2_unittest.h"
+#include "chrome/common/net/http_return.h"
+#include "chrome/common/net/test_url_fetcher_factory.h"
+#include "chrome/common/net/url_fetcher.h"
+#include "chrome/test/testing_profile.h"
+#include "googleurl/src/gurl.h"
+#include "net/base/net_errors.h"
+#include "net/url_request/url_request_status.h"
+#include "testing/gmock/include/gmock/gmock.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+using ::testing::_;
+
+class GaiaAuthenticator2Test : public testing::Test {
+ public:
+ GaiaAuthenticator2Test()
+ : client_login_source_(GaiaAuthenticator2::kClientLoginUrl),
+ issue_auth_token_source_(GaiaAuthenticator2::kIssueAuthTokenUrl) {}
+
+ void RunParsingTest(const std::string& data,
+ const std::string& sid,
+ const std::string& lsid,
+ const std::string& token) {
+ std::string out_sid;
+ std::string out_lsid;
+ std::string out_token;
+
+ GaiaAuthenticator2::ParseClientLoginResponse(data,
+ &out_sid,
+ &out_lsid,
+ &out_token);
+ EXPECT_EQ(lsid, out_lsid);
+ EXPECT_EQ(sid, out_sid);
+ EXPECT_EQ(token, out_token);
+ }
+
+ ResponseCookies cookies_;
+ GURL client_login_source_;
+ GURL issue_auth_token_source_;
+ TestingProfile profile_;
+};
+
+class MockGaiaConsumer : public GaiaAuthConsumer {
+ public:
+ MockGaiaConsumer() {}
+ ~MockGaiaConsumer() {}
+
+ MOCK_METHOD1(OnClientLoginSuccess, void(const ClientLoginResult& result));
+ MOCK_METHOD2(OnIssueAuthTokenSuccess, void(const std::string& service,
+ const std::string& token));
+ MOCK_METHOD1(OnClientLoginFailure, void(const GaiaAuthError& error));
+ MOCK_METHOD2(OnIssueAuthTokenFailure, void(const std::string& service,
+ const GaiaAuthError& error));
+};
+
+TEST_F(GaiaAuthenticator2Test, ErrorComparator) {
+ GaiaAuthConsumer::GaiaAuthError expected_error;
+ expected_error.code = GaiaAuthConsumer::NETWORK_ERROR;
+ expected_error.network_error = -101;
+
+ GaiaAuthConsumer::GaiaAuthError matching_error;
+ matching_error.code = GaiaAuthConsumer::NETWORK_ERROR;
+ matching_error.network_error = -101;
+
+ EXPECT_TRUE(expected_error == matching_error);
+
+ expected_error.network_error = 6;
+
+ EXPECT_FALSE(expected_error == matching_error);
+
+ expected_error.code = GaiaAuthConsumer::PERMISSION_DENIED;
+ matching_error.code = GaiaAuthConsumer::PERMISSION_DENIED;
+
+ EXPECT_TRUE(expected_error == matching_error);
+}
+
+TEST_F(GaiaAuthenticator2Test, LoginNetFailure) {
+ int error_no = net::ERR_CONNECTION_RESET;
+ URLRequestStatus status(URLRequestStatus::FAILED, error_no);
+
+ GaiaAuthConsumer::GaiaAuthError expected_error;
+ expected_error.code = GaiaAuthConsumer::NETWORK_ERROR;
+ expected_error.network_error = error_no;
+
+ MockGaiaConsumer consumer;
+ EXPECT_CALL(consumer, OnClientLoginFailure(expected_error))
+ .Times(1);
+
+ GaiaAuthenticator2 auth(&consumer, std::string(),
+ profile_.GetRequestContext());
+
+ auth.OnURLFetchComplete(NULL,
+ client_login_source_,
+ status,
+ 0,
+ cookies_,
+ std::string());
+}
+
+TEST_F(GaiaAuthenticator2Test, TokenNetFailure) {
+ int error_no = net::ERR_CONNECTION_RESET;
+ URLRequestStatus status(URLRequestStatus::FAILED, error_no);
+
+ GaiaAuthConsumer::GaiaAuthError expected_error;
+ expected_error.code = GaiaAuthConsumer::NETWORK_ERROR;
+ expected_error.network_error = error_no;
+
+ MockGaiaConsumer consumer;
+ EXPECT_CALL(consumer, OnIssueAuthTokenFailure(_, expected_error))
+ .Times(1);
+
+ GaiaAuthenticator2 auth(&consumer, std::string(),
+ profile_.GetRequestContext());
+
+ auth.OnURLFetchComplete(NULL,
+ issue_auth_token_source_,
+ status,
+ 0,
+ cookies_,
+ std::string());
+}
+
+
+TEST_F(GaiaAuthenticator2Test, LoginDenied) {
+ std::string data("Error: NO!");
+ URLRequestStatus status(URLRequestStatus::SUCCESS, 0);
+
+ GaiaAuthConsumer::GaiaAuthError expected_error;
+ expected_error.code = GaiaAuthConsumer::PERMISSION_DENIED;
+
+ MockGaiaConsumer consumer;
+ EXPECT_CALL(consumer, OnClientLoginFailure(expected_error))
+ .Times(1);
+
+ GaiaAuthenticator2 auth(&consumer, std::string(),
+ profile_.GetRequestContext());
+ auth.OnURLFetchComplete(NULL,
+ client_login_source_,
+ status,
+ RC_FORBIDDEN,
+ cookies_,
+ data);
+}
+
+TEST_F(GaiaAuthenticator2Test, ParseRequest) {
+ RunParsingTest("SID=sid\nLSID=lsid\nAuth=auth\n", "sid", "lsid", "auth");
+ RunParsingTest("LSID=lsid\nSID=sid\nAuth=auth\n", "sid", "lsid", "auth");
+ RunParsingTest("SID=sid\nLSID=lsid\nAuth=auth", "sid", "lsid", "auth");
+ RunParsingTest("SID=sid\nAuth=auth\n", "sid", "", "auth");
+ RunParsingTest("LSID=lsid\nAuth=auth\n", "", "lsid", "auth");
+ RunParsingTest("\nAuth=auth\n", "", "", "auth");
+ RunParsingTest("SID=sid", "sid", "", "");
+}
+
+TEST_F(GaiaAuthenticator2Test, OnlineLogin) {
+ std::string data("SID=sid\nLSID=lsid\nAuth=auth\n");
+
+ GaiaAuthConsumer::ClientLoginResult result;
+ result.lsid = "lsid";
+ result.sid = "sid";
+ result.token = "auth";
+ result.data = data;
+
+ MockGaiaConsumer consumer;
+ EXPECT_CALL(consumer, OnClientLoginSuccess(result))
+ .Times(1);
+
+ GaiaAuthenticator2 auth(&consumer, std::string(),
+ profile_.GetRequestContext());
+ URLRequestStatus status(URLRequestStatus::SUCCESS, 0);
+ auth.OnURLFetchComplete(NULL,
+ client_login_source_,
+ status,
+ RC_REQUEST_OK,
+ cookies_,
+ data);
+}
+
+TEST_F(GaiaAuthenticator2Test, WorkingIssueAuthToken) {
+ MockGaiaConsumer consumer;
+ EXPECT_CALL(consumer, OnIssueAuthTokenSuccess(_, "token"))
+ .Times(1);
+
+ GaiaAuthenticator2 auth(&consumer, std::string(),
+ profile_.GetRequestContext());
+ URLRequestStatus status(URLRequestStatus::SUCCESS, 0);
+ auth.OnURLFetchComplete(NULL,
+ issue_auth_token_source_,
+ status,
+ RC_REQUEST_OK,
+ cookies_,
+ "token");
+}
+
+TEST_F(GaiaAuthenticator2Test, CheckTwoFactorResponse) {
+ std::string response =
+ StringPrintf("Error=BadAuthentication\n%s\n",
+ GaiaAuthenticator2::kSecondFactor);
+ EXPECT_TRUE(GaiaAuthenticator2::IsSecondFactorSuccess(response));
+}
+
+TEST_F(GaiaAuthenticator2Test, CheckNormalErrorCode) {
+ std::string response = "Error=BadAuthentication\n";
+ EXPECT_FALSE(GaiaAuthenticator2::IsSecondFactorSuccess(response));
+}
+
+TEST_F(GaiaAuthenticator2Test, TwoFactorLogin) {
+ std::string response =
+ StringPrintf("Error=BadAuthentication\n%s\n",
+ GaiaAuthenticator2::kSecondFactor);
+
+ GaiaAuthConsumer::GaiaAuthError error;
+ error.code = GaiaAuthConsumer::TWO_FACTOR;
+
+ MockGaiaConsumer consumer;
+ EXPECT_CALL(consumer, OnClientLoginFailure(error))
+ .Times(1);
+
+ GaiaAuthenticator2 auth(&consumer, std::string(),
+ profile_.GetRequestContext());
+ URLRequestStatus status(URLRequestStatus::SUCCESS, 0);
+ auth.OnURLFetchComplete(NULL,
+ client_login_source_,
+ status,
+ RC_FORBIDDEN,
+ cookies_,
+ response);
+}
+
+TEST_F(GaiaAuthenticator2Test, FullLogin) {
+ MockGaiaConsumer consumer;
+ EXPECT_CALL(consumer, OnClientLoginSuccess(_))
+ .Times(1);
+
+ TestingProfile profile;
+
+ MockFactory factory;
+ URLFetcher::set_factory(&factory);
+
+ GaiaAuthenticator2 auth(&consumer, std::string(),
+ profile_.GetRequestContext());
+ auth.StartClientLogin("username",
+ "password",
+ "service",
+ std::string(),
+ std::string());
+
+ URLFetcher::set_factory(NULL);
+}
+
+TEST_F(GaiaAuthenticator2Test, FullLoginFailure) {
+ MockGaiaConsumer consumer;
+ EXPECT_CALL(consumer, OnClientLoginFailure(_))
+ .Times(1);
+
+ TestingProfile profile;
+
+ MockFactory factory;
+ URLFetcher::set_factory(&factory);
+ factory.set_success(false);
+
+ GaiaAuthenticator2 auth(&consumer, std::string(),
+ profile_.GetRequestContext());
+ auth.StartClientLogin("username",
+ "password",
+ "service",
+ std::string(),
+ std::string());
+
+ URLFetcher::set_factory(NULL);
+}
+
+TEST_F(GaiaAuthenticator2Test, ClientFetchPending) {
+ MockGaiaConsumer consumer;
+ EXPECT_CALL(consumer, OnClientLoginSuccess(_))
+ .Times(1);
+
+ TestingProfile profile;
+ TestURLFetcherFactory factory;
+ URLFetcher::set_factory(&factory);
+
+ GaiaAuthenticator2 auth(&consumer, std::string(),
+ profile_.GetRequestContext());
+ auth.StartClientLogin("username",
+ "password",
+ "service",
+ std::string(),
+ std::string());
+
+ URLFetcher::set_factory(NULL);
+ EXPECT_TRUE(auth.HasPendingFetch());
+ auth.OnURLFetchComplete(NULL,
+ client_login_source_,
+ URLRequestStatus(URLRequestStatus::SUCCESS, 0),
+ RC_REQUEST_OK,
+ cookies_,
+ "SID=sid\nLSID=lsid\nAuth=auth\n");
+ EXPECT_FALSE(auth.HasPendingFetch());
+}
+
+TEST_F(GaiaAuthenticator2Test, FullTokenSuccess) {
+ MockGaiaConsumer consumer;
+ EXPECT_CALL(consumer, OnIssueAuthTokenSuccess("service", "token"))
+ .Times(1);
+
+ TestingProfile profile;
+ TestURLFetcherFactory factory;
+ URLFetcher::set_factory(&factory);
+
+ GaiaAuthenticator2 auth(&consumer, std::string(),
+ profile_.GetRequestContext());
+ auth.StartIssueAuthToken("sid", "lsid", "service");
+
+ URLFetcher::set_factory(NULL);
+ EXPECT_TRUE(auth.HasPendingFetch());
+ auth.OnURLFetchComplete(NULL,
+ issue_auth_token_source_,
+ URLRequestStatus(URLRequestStatus::SUCCESS, 0),
+ RC_REQUEST_OK,
+ cookies_,
+ "token");
+ EXPECT_FALSE(auth.HasPendingFetch());
+}
+
+TEST_F(GaiaAuthenticator2Test, FullTokenFailure) {
+ MockGaiaConsumer consumer;
+ EXPECT_CALL(consumer, OnIssueAuthTokenFailure("service", _))
+ .Times(1);
+
+ TestingProfile profile;
+ TestURLFetcherFactory factory;
+ URLFetcher::set_factory(&factory);
+
+ GaiaAuthenticator2 auth(&consumer, std::string(),
+ profile_.GetRequestContext());
+ auth.StartIssueAuthToken("sid", "lsid", "service");
+
+ URLFetcher::set_factory(NULL);
+ EXPECT_TRUE(auth.HasPendingFetch());
+ auth.OnURLFetchComplete(NULL,
+ issue_auth_token_source_,
+ URLRequestStatus(URLRequestStatus::SUCCESS, 0),
+ RC_FORBIDDEN,
+ cookies_,
+ "");
+ EXPECT_FALSE(auth.HasPendingFetch());
+}
diff --git a/chrome/common/net/gaia/gaia_authenticator2_unittest.h b/chrome/common/net/gaia/gaia_authenticator2_unittest.h
new file mode 100644
index 0000000..d392ee8
--- /dev/null
+++ b/chrome/common/net/gaia/gaia_authenticator2_unittest.h
@@ -0,0 +1,71 @@
+// Copyright (c) 2010 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.
+//
+// A collection of classes that are useful when testing things that use a
+// GaiaAuthenticator2.
+
+#ifndef CHROME_COMMON_NET_GAIA_GAIA_AUTHENTICATOR2_UNITTEST_H_
+#define CHROME_COMMON_NET_GAIA_GAIA_AUTHENTICATOR2_UNITTEST_H_
+
+#include "chrome/common/net/gaia/gaia_authenticator2.h"
+#include "chrome/common/net/url_fetcher.h"
+#include "chrome/common/net/http_return.h"
+#include "net/url_request/url_request_status.h"
+
+// Responds as though ClientLogin returned from the server.
+class MockFetcher : public URLFetcher {
+ public:
+ MockFetcher(bool success,
+ const GURL& url,
+ URLFetcher::RequestType request_type,
+ URLFetcher::Delegate* d)
+ : URLFetcher(url, request_type, d),
+ success_(success),
+ url_(url) {}
+ ~MockFetcher() {}
+ void Start() {
+ URLRequestStatus::Status code;
+ int http_code;
+ if (success_) {
+ http_code = RC_REQUEST_OK;
+ code = URLRequestStatus::SUCCESS;
+ } else {
+ http_code = RC_FORBIDDEN;
+ code = URLRequestStatus::FAILED;
+ }
+
+ URLRequestStatus status(code, 0);
+ delegate()->OnURLFetchComplete(NULL,
+ url_,
+ status,
+ http_code,
+ ResponseCookies(),
+ std::string());
+ }
+ private:
+ bool success_;
+ GURL url_;
+ DISALLOW_COPY_AND_ASSIGN(MockFetcher);
+};
+
+class MockFactory : public URLFetcher::Factory {
+ public:
+ MockFactory()
+ : success_(true) {}
+ ~MockFactory() {}
+ URLFetcher* CreateURLFetcher(int id,
+ const GURL& url,
+ URLFetcher::RequestType request_type,
+ URLFetcher::Delegate* d) {
+ return new MockFetcher(success_, url, request_type, d);
+ }
+ void set_success(bool success) {
+ success_ = success;
+ }
+ private:
+ bool success_;
+ DISALLOW_COPY_AND_ASSIGN(MockFactory);
+};
+
+#endif // CHROME_COMMON_NET_GAIA_GAIA_AUTHENTICATOR2_UNITTEST_H_
diff --git a/chrome/common/net/gaia/gaia_authenticator_unittest.cc b/chrome/common/net/gaia/gaia_authenticator_unittest.cc
new file mode 100644
index 0000000..25a92d0
--- /dev/null
+++ b/chrome/common/net/gaia/gaia_authenticator_unittest.cc
@@ -0,0 +1,49 @@
+// Copyright (c) 2009 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/common/net/gaia/gaia_authenticator.h"
+
+#include <string>
+
+#include "chrome/common/net/http_return.h"
+#include "googleurl/src/gurl.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+using std::string;
+
+namespace gaia {
+
+class GaiaAuthenticatorTest : public testing::Test { };
+
+class GaiaAuthMockForGaiaAuthenticator : public GaiaAuthenticator {
+ public:
+ GaiaAuthMockForGaiaAuthenticator()
+ : GaiaAuthenticator("useragent", "serviceid", "http://gaia_url") {}
+ ~GaiaAuthMockForGaiaAuthenticator() {}
+ protected:
+ bool Post(const GURL& url, const string& post_body,
+ unsigned long* response_code, string* response_body) {
+ *response_code = RC_REQUEST_OK;
+ response_body->assign("body\n");
+ return true;
+ }
+
+ int GetBackoffDelaySeconds(
+ int current_backoff_delay) {
+ // Dummy delay value.
+ return 5;
+ }
+};
+
+TEST(GaiaAuthenticatorTest, TestNewlineAtEndOfAuthTokenRemoved) {
+ GaiaAuthMockForGaiaAuthenticator mock_auth;
+ MessageLoop message_loop;
+ mock_auth.set_message_loop(&message_loop);
+ GaiaAuthenticator::AuthResults results;
+ EXPECT_TRUE(mock_auth.IssueAuthToken(&results, "sid"));
+ EXPECT_EQ(0, results.auth_token.compare("body"));
+}
+
+} // namespace gaia
+
diff --git a/chrome/common/net/http_return.h b/chrome/common/net/http_return.h
new file mode 100644
index 0000000..f47d1bb
--- /dev/null
+++ b/chrome/common/net/http_return.h
@@ -0,0 +1,17 @@
+// Copyright (c) 2009 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_COMMON_NET_HTTP_RETURN_H_
+#define CHROME_COMMON_NET_HTTP_RETURN_H_
+
+// TODO(sanjeevr): This has been moved from the sync library so it only
+// contains a few HTTP return codes. Add more HTTP return codes.
+enum HTTPReturnCode {
+ RC_REQUEST_OK = 200,
+ RC_UNAUTHORIZED = 401,
+ RC_FORBIDDEN = 403,
+};
+
+#endif // CHROME_COMMON_NET_HTTP_RETURN_H_
+
diff --git a/chrome/common/net/net_resource_provider.cc b/chrome/common/net/net_resource_provider.cc
new file mode 100644
index 0000000..6992470
--- /dev/null
+++ b/chrome/common/net/net_resource_provider.cc
@@ -0,0 +1,63 @@
+// Copyright (c) 2009 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/common/net/net_resource_provider.h"
+
+#include <string>
+
+#include "app/l10n_util.h"
+#include "app/resource_bundle.h"
+#include "base/string_piece.h"
+#include "base/values.h"
+#include "chrome/common/jstemplate_builder.h"
+#include "grit/chromium_strings.h"
+#include "grit/generated_resources.h"
+#include "grit/net_resources.h"
+
+namespace {
+
+// The net module doesn't have access to this HTML or the strings that need to
+// be localized. The Chrome locale will never change while we're running, so
+// it's safe to have a static string that we always return a pointer into.
+// This allows us to have the ResourceProvider return a pointer into the actual
+// resource (via a StringPiece), instead of always copying resources.
+struct LazyDirectoryListerCacher {
+ LazyDirectoryListerCacher() {
+ DictionaryValue value;
+ value.SetString(L"header",
+ l10n_util::GetString(IDS_DIRECTORY_LISTING_HEADER));
+ value.SetString(L"parentDirText",
+ l10n_util::GetString(IDS_DIRECTORY_LISTING_PARENT));
+ value.SetString(L"headerName",
+ l10n_util::GetString(IDS_DIRECTORY_LISTING_NAME));
+ value.SetString(L"headerSize",
+ l10n_util::GetString(IDS_DIRECTORY_LISTING_SIZE));
+ value.SetString(L"headerDateModified",
+ l10n_util::GetString(IDS_DIRECTORY_LISTING_DATE_MODIFIED));
+ value.SetString(L"listingParsingErrorBoxText",
+ l10n_util::GetStringF(IDS_DIRECTORY_LISTING_PARSING_ERROR_BOX_TEXT,
+ l10n_util::GetString(IDS_PRODUCT_NAME)));
+ html_data = jstemplate_builder::GetI18nTemplateHtml(
+ ResourceBundle::GetSharedInstance().GetRawDataResource(
+ IDR_DIR_HEADER_HTML),
+ &value);
+ }
+
+ std::string html_data;
+};
+
+} // namespace
+
+namespace chrome_common_net {
+
+base::StringPiece NetResourceProvider(int key) {
+ static LazyDirectoryListerCacher lazy_dir_lister;
+
+ if (IDR_DIR_HEADER_HTML == key)
+ return base::StringPiece(lazy_dir_lister.html_data);
+
+ return ResourceBundle::GetSharedInstance().GetRawDataResource(key);
+}
+
+} // namespace chrome_common_net
diff --git a/chrome/common/net/net_resource_provider.h b/chrome/common/net/net_resource_provider.h
new file mode 100644
index 0000000..4965adf
--- /dev/null
+++ b/chrome/common/net/net_resource_provider.h
@@ -0,0 +1,19 @@
+// Copyright (c) 2009 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_COMMON_NET_NET_RESOURCE_PROVIDER_H_
+#define CHROME_COMMON_NET_NET_RESOURCE_PROVIDER_H_
+
+namespace base {
+class StringPiece;
+}
+
+namespace chrome_common_net {
+
+// This is called indirectly by the network layer to access resources.
+base::StringPiece NetResourceProvider(int key);
+
+} // namespace chrome_common_net
+
+#endif // CHROME_COMMON_NET_NET_RESOURCE_PROVIDER_H_
diff --git a/chrome/common/net/predictor_common.h b/chrome/common/net/predictor_common.h
new file mode 100644
index 0000000..c1d995f
--- /dev/null
+++ b/chrome/common/net/predictor_common.h
@@ -0,0 +1,29 @@
+// Copyright (c) 2006-2008 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.
+
+// This file has shared types used across IPC between render_dns_master.cc
+// and dns_master.cc
+
+#ifndef CHROME_COMMON_NET_PREDICTOR_COMMON_H_
+#define CHROME_COMMON_NET_PREDICTOR_COMMON_H_
+
+#include <string>
+#include <vector>
+
+#include "googleurl/src/gurl.h"
+
+namespace chrome_common_net {
+
+// IPC messages are passed from the renderer to the browser in the form of
+// Namelist instances.
+// Each element of this vector is a hostname that needs to be looked up.
+// The hostnames should never be empty strings.
+typedef std::vector<std::string> NameList;
+// TODO(jar): We still need to switch to passing scheme/host/port in UrlList,
+// instead of NameList, from renderer (where content of pages are scanned for
+// links) to browser (where we perform predictive actions).
+typedef std::vector<GURL> UrlList;
+}
+
+#endif // CHROME_COMMON_NET_PREDICTOR_COMMON_H_
diff --git a/chrome/common/net/socket_stream.h b/chrome/common/net/socket_stream.h
new file mode 100644
index 0000000..6c1ad92
--- /dev/null
+++ b/chrome/common/net/socket_stream.h
@@ -0,0 +1,14 @@
+// Copyright (c) 2009 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_COMMON_NET_SOCKET_STREAM_H_
+#define CHROME_COMMON_NET_SOCKET_STREAM_H_
+
+namespace chrome_common_net {
+
+const int kNoSocketId = 0;
+
+} // namespace chrome_common_net
+
+#endif // CHROME_COMMON_NET_SOCKET_STREAM_H_
diff --git a/chrome/common/net/test_url_fetcher_factory.cc b/chrome/common/net/test_url_fetcher_factory.cc
new file mode 100644
index 0000000..6ab3a49
--- /dev/null
+++ b/chrome/common/net/test_url_fetcher_factory.cc
@@ -0,0 +1,27 @@
+// Copyright (c) 2009 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/common/net/test_url_fetcher_factory.h"
+
+TestURLFetcher::TestURLFetcher(const GURL& url,
+ URLFetcher::RequestType request_type,
+ URLFetcher::Delegate* d)
+ : URLFetcher(url, request_type, d),
+ original_url_(url) {
+}
+
+URLFetcher* TestURLFetcherFactory::CreateURLFetcher(
+ int id,
+ const GURL& url,
+ URLFetcher::RequestType request_type,
+ URLFetcher::Delegate* d) {
+ TestURLFetcher* fetcher = new TestURLFetcher(url, request_type, d);
+ fetchers_[id] = fetcher;
+ return fetcher;
+}
+
+TestURLFetcher* TestURLFetcherFactory::GetFetcherByID(int id) const {
+ Fetchers::const_iterator i = fetchers_.find(id);
+ return i == fetchers_.end() ? NULL : i->second;
+}
diff --git a/chrome/common/net/test_url_fetcher_factory.h b/chrome/common/net/test_url_fetcher_factory.h
new file mode 100644
index 0000000..2e4ea45
--- /dev/null
+++ b/chrome/common/net/test_url_fetcher_factory.h
@@ -0,0 +1,82 @@
+// Copyright (c) 2009 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_COMMON_NET_TEST_URL_FETCHER_FACTORY_H_
+#define CHROME_COMMON_NET_TEST_URL_FETCHER_FACTORY_H_
+
+#include <map>
+#include <string>
+
+#include "chrome/common/net/url_fetcher.h"
+#include "googleurl/src/gurl.h"
+
+// TestURLFetcher and TestURLFetcherFactory are used for testing consumers of
+// URLFetcher. TestURLFetcherFactory is a URLFetcher::Factory that creates
+// TestURLFetchers. TestURLFetcher::Start is overriden to do nothing. It is
+// expected that you'll grab the delegate from the TestURLFetcher and invoke
+// the callback method when appropriate. In this way it's easy to mock a
+// URLFetcher.
+// Typical usage:
+// // TestURLFetcher requires a MessageLoop:
+// MessageLoopForUI message_loop;
+// // Create and register factory.
+// TestURLFetcherFactory factory;
+// URLFetcher::set_factory(&factory);
+// // Do something that triggers creation of a URLFetcher.
+// TestURLFetcher* fetcher = factory.GetFetcherByID(expected_id);
+// DCHECK(fetcher);
+// // Notify delegate with whatever data you want.
+// fetcher->delegate()->OnURLFetchComplete(...);
+// // Make sure consumer of URLFetcher does the right thing.
+// ...
+// // Reset factory.
+// URLFetcher::set_factory(NULL);
+
+
+class TestURLFetcher : public URLFetcher {
+ public:
+ TestURLFetcher(const GURL& url, RequestType request_type, Delegate* d);
+
+ // Returns the delegate installed on the URLFetcher.
+ Delegate* delegate() const { return URLFetcher::delegate(); }
+
+ // Overriden to do nothing. It is assumed the caller will notify the delegate.
+ virtual void Start() {}
+
+ // URL we were created with. Because of how we're using URLFetcher url()
+ // always returns an empty URL. Chances are you'll want to use original_url()
+ // in your tests.
+ const GURL& original_url() const { return original_url_; }
+
+ // Returns the data uploaded on this URLFetcher.
+ const std::string& upload_data() const { return URLFetcher::upload_data(); }
+
+ private:
+ const GURL original_url_;
+
+ DISALLOW_COPY_AND_ASSIGN(TestURLFetcher);
+};
+
+// Simple URLFetcher::Factory method that creates TestURLFetchers. All fetchers
+// are registered in a map by the id passed to the create method.
+class TestURLFetcherFactory : public URLFetcher::Factory {
+ public:
+ TestURLFetcherFactory() {}
+
+ virtual URLFetcher* CreateURLFetcher(int id,
+ const GURL& url,
+ URLFetcher::RequestType request_type,
+ URLFetcher::Delegate* d);
+
+ TestURLFetcher* GetFetcherByID(int id) const;
+
+ private:
+ // Maps from id passed to create to the returned URLFetcher.
+ typedef std::map<int, TestURLFetcher*> Fetchers;
+ Fetchers fetchers_;
+
+ DISALLOW_COPY_AND_ASSIGN(TestURLFetcherFactory);
+};
+
+#endif // CHROME_COMMON_NET_TEST_URL_FETCHER_FACTORY_H_
diff --git a/chrome/common/net/url_fetcher.cc b/chrome/common/net/url_fetcher.cc
new file mode 100644
index 0000000..a74255b
--- /dev/null
+++ b/chrome/common/net/url_fetcher.cc
@@ -0,0 +1,377 @@
+// Copyright (c) 2009 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/common/net/url_fetcher.h"
+
+#include "base/compiler_specific.h"
+#include "base/message_loop_proxy.h"
+#include "base/string_util.h"
+#include "base/thread.h"
+#include "chrome/common/net/url_fetcher_protect.h"
+#include "chrome/common/net/url_request_context_getter.h"
+#include "googleurl/src/gurl.h"
+#include "net/base/load_flags.h"
+#include "net/base/io_buffer.h"
+#include "net/http/http_request_headers.h"
+#include "net/http/http_response_headers.h"
+#include "net/url_request/url_request.h"
+#include "net/url_request/url_request_context.h"
+
+static const int kBufferSize = 4096;
+
+bool URLFetcher::g_interception_enabled = false;
+
+class URLFetcher::Core
+ : public base::RefCountedThreadSafe<URLFetcher::Core>,
+ public MessageLoop::DestructionObserver,
+ public URLRequest::Delegate {
+ public:
+ // For POST requests, set |content_type| to the MIME type of the content
+ // and set |content| to the data to upload. |flags| are flags to apply to
+ // the load operation--these should be one or more of the LOAD_* flags
+ // defined in url_request.h.
+ Core(URLFetcher* fetcher,
+ const GURL& original_url,
+ RequestType request_type,
+ URLFetcher::Delegate* d);
+
+ // Starts the load. It's important that this not happen in the constructor
+ // because it causes the IO thread to begin AddRef()ing and Release()ing
+ // us. If our caller hasn't had time to fully construct us and take a
+ // reference, the IO thread could interrupt things, run a task, Release()
+ // us, and destroy us, leaving the caller with an already-destroyed object
+ // when construction finishes.
+ void Start();
+
+ // Stops any in-progress load and ensures no callback will happen. It is
+ // safe to call this multiple times.
+ void Stop();
+
+ // MessageLoop::DestructionObserver implementation. We are only registered as
+ // a DestructionObserver when |request_| exists.
+ virtual void WillDestroyCurrentMessageLoop();
+
+ // URLRequest::Delegate implementation.
+ virtual void OnResponseStarted(URLRequest* request);
+ virtual void OnReadCompleted(URLRequest* request, int bytes_read);
+
+ URLFetcher::Delegate* delegate() const { return delegate_; }
+
+ private:
+ friend class base::RefCountedThreadSafe<URLFetcher::Core>;
+
+ ~Core() {}
+
+ // Wrapper functions that allow us to ensure actions happen on the right
+ // thread.
+ void StartURLRequest();
+ void CancelURLRequest();
+ void OnCompletedURLRequest(const URLRequestStatus& status);
+
+ URLFetcher* fetcher_; // Corresponding fetcher object
+ GURL original_url_; // The URL we were asked to fetch
+ GURL url_; // The URL we eventually wound up at
+ RequestType request_type_; // What type of request is this?
+ URLFetcher::Delegate* delegate_; // Object to notify on completion
+ MessageLoop* delegate_loop_; // Message loop of the creating thread
+ scoped_refptr<base::MessageLoopProxy> io_message_loop_proxy_;
+ // The message loop proxy for the thread
+ // on which the request IO happens.
+ URLRequest* request_; // The actual request this wraps
+ int load_flags_; // Flags for the load operation
+ int response_code_; // HTTP status code for the request
+ std::string data_; // Results of the request
+ scoped_refptr<net::IOBuffer> buffer_;
+ // Read buffer
+ scoped_refptr<URLRequestContextGetter> request_context_getter_;
+ // Cookie/cache info for the request
+ ResponseCookies cookies_; // Response cookies
+ net::HttpRequestHeaders extra_request_headers_;
+ scoped_refptr<net::HttpResponseHeaders> response_headers_;
+
+ std::string upload_content_; // HTTP POST payload
+ std::string upload_content_type_; // MIME type of POST payload
+
+ // The overload protection entry for this URL. This is used to
+ // incrementally back off how rapidly we'll send requests to a particular
+ // URL, to avoid placing too much demand on the remote resource. We update
+ // this with the status of all requests as they return, and in turn use it
+ // to determine how long to wait before making another request.
+ URLFetcherProtectEntry* protect_entry_;
+ // |num_retries_| indicates how many times we've failed to successfully
+ // fetch this URL. Once this value exceeds the maximum number of retries
+ // specified by the protection manager, we'll give up.
+ int num_retries_;
+
+ // True if the URLFetcher has been cancelled.
+ bool was_cancelled_;
+
+ friend class URLFetcher;
+ DISALLOW_COPY_AND_ASSIGN(Core);
+};
+
+// static
+URLFetcher::Factory* URLFetcher::factory_ = NULL;
+
+URLFetcher::URLFetcher(const GURL& url,
+ RequestType request_type,
+ Delegate* d)
+ : ALLOW_THIS_IN_INITIALIZER_LIST(
+ core_(new Core(this, url, request_type, d))),
+ automatically_retry_on_5xx_(true) {
+}
+
+URLFetcher::~URLFetcher() {
+ core_->Stop();
+}
+
+// static
+URLFetcher* URLFetcher::Create(int id, const GURL& url,
+ RequestType request_type, Delegate* d) {
+ return factory_ ? factory_->CreateURLFetcher(id, url, request_type, d) :
+ new URLFetcher(url, request_type, d);
+}
+
+URLFetcher::Core::Core(URLFetcher* fetcher,
+ const GURL& original_url,
+ RequestType request_type,
+ URLFetcher::Delegate* d)
+ : fetcher_(fetcher),
+ original_url_(original_url),
+ request_type_(request_type),
+ delegate_(d),
+ delegate_loop_(MessageLoop::current()),
+ request_(NULL),
+ load_flags_(net::LOAD_NORMAL),
+ response_code_(-1),
+ buffer_(new net::IOBuffer(kBufferSize)),
+ protect_entry_(URLFetcherProtectManager::GetInstance()->Register(
+ original_url_.host())),
+ num_retries_(0),
+ was_cancelled_(false) {
+}
+
+void URLFetcher::Core::Start() {
+ DCHECK(delegate_loop_);
+ CHECK(request_context_getter_) << "We need an URLRequestContext!";
+ io_message_loop_proxy_ = request_context_getter_->GetIOMessageLoopProxy();
+ CHECK(io_message_loop_proxy_.get()) << "We need an IO message loop proxy";
+ io_message_loop_proxy_->PostDelayedTask(
+ FROM_HERE,
+ NewRunnableMethod(this, &Core::StartURLRequest),
+ protect_entry_->UpdateBackoff(URLFetcherProtectEntry::SEND));
+}
+
+void URLFetcher::Core::Stop() {
+ DCHECK_EQ(MessageLoop::current(), delegate_loop_);
+ delegate_ = NULL;
+ fetcher_ = NULL;
+ if (io_message_loop_proxy_.get()) {
+ io_message_loop_proxy_->PostTask(
+ FROM_HERE, NewRunnableMethod(this, &Core::CancelURLRequest));
+ }
+}
+
+void URLFetcher::Core::WillDestroyCurrentMessageLoop() {
+ CancelURLRequest();
+ // Don't bother to try and notify the delegate thread portion of this object,
+ // since if the IO thread is shutting down, everything is shutting down, and
+ // we just want to avoid leaks.
+}
+
+void URLFetcher::Core::OnResponseStarted(URLRequest* request) {
+ DCHECK(request == request_);
+ DCHECK(io_message_loop_proxy_->BelongsToCurrentThread());
+ if (request_->status().is_success()) {
+ response_code_ = request_->GetResponseCode();
+ response_headers_ = request_->response_headers();
+ }
+
+ int bytes_read = 0;
+ // Some servers may treat HEAD requests as GET requests. To free up the
+ // network connection as soon as possible, signal that the request has
+ // completed immediately, without trying to read any data back (all we care
+ // about is the response code and headers, which we already have).
+ if (request_->status().is_success() && (request_type_ != HEAD))
+ request_->Read(buffer_, kBufferSize, &bytes_read);
+ OnReadCompleted(request_, bytes_read);
+}
+
+void URLFetcher::Core::OnReadCompleted(URLRequest* request, int bytes_read) {
+ DCHECK(request == request_);
+ DCHECK(io_message_loop_proxy_->BelongsToCurrentThread());
+
+ url_ = request->url();
+
+ do {
+ if (!request_->status().is_success() || bytes_read <= 0)
+ break;
+ data_.append(buffer_->data(), bytes_read);
+ } while (request_->Read(buffer_, kBufferSize, &bytes_read));
+
+ if (request_->status().is_success())
+ request_->GetResponseCookies(&cookies_);
+
+ // See comments re: HEAD requests in OnResponseStarted().
+ if (!request_->status().is_io_pending() || (request_type_ == HEAD)) {
+ delegate_loop_->PostTask(FROM_HERE, NewRunnableMethod(
+ this, &Core::OnCompletedURLRequest, request_->status()));
+ delete request_;
+ request_ = NULL;
+ MessageLoop::current()->RemoveDestructionObserver(this);
+ }
+}
+
+void URLFetcher::Core::StartURLRequest() {
+ DCHECK(io_message_loop_proxy_->BelongsToCurrentThread());
+
+ if (was_cancelled_) {
+ // Since StartURLRequest() is posted as a *delayed* task, it may
+ // run after the URLFetcher was already stopped.
+ return;
+ }
+
+ CHECK(request_context_getter_);
+ DCHECK(!request_);
+
+ MessageLoop::current()->AddDestructionObserver(this);
+
+ request_ = new URLRequest(original_url_, this);
+ int flags = request_->load_flags() | load_flags_;
+ if (!g_interception_enabled) {
+ flags = flags | net::LOAD_DISABLE_INTERCEPT;
+ }
+ request_->set_load_flags(flags);
+ request_->set_context(request_context_getter_->GetURLRequestContext());
+
+ switch (request_type_) {
+ case GET:
+ break;
+
+ case POST:
+ DCHECK(!upload_content_.empty());
+ DCHECK(!upload_content_type_.empty());
+
+ request_->set_method("POST");
+ extra_request_headers_.SetHeader(net::HttpRequestHeaders::kContentType,
+ upload_content_type_);
+ request_->AppendBytesToUpload(upload_content_.data(),
+ static_cast<int>(upload_content_.size()));
+ break;
+
+ case HEAD:
+ request_->set_method("HEAD");
+ break;
+
+ default:
+ NOTREACHED();
+ }
+
+ if (!extra_request_headers_.IsEmpty())
+ request_->SetExtraRequestHeaders(extra_request_headers_);
+
+ request_->Start();
+}
+
+void URLFetcher::Core::CancelURLRequest() {
+ DCHECK(io_message_loop_proxy_->BelongsToCurrentThread());
+
+ if (request_) {
+ request_->Cancel();
+ delete request_;
+ request_ = NULL;
+ MessageLoop::current()->RemoveDestructionObserver(this);
+ }
+ // Release the reference to the request context. There could be multiple
+ // references to URLFetcher::Core at this point so it may take a while to
+ // delete the object, but we cannot delay the destruction of the request
+ // context.
+ request_context_getter_ = NULL;
+ was_cancelled_ = true;
+}
+
+void URLFetcher::Core::OnCompletedURLRequest(const URLRequestStatus& status) {
+ DCHECK(MessageLoop::current() == delegate_loop_);
+
+ // Checks the response from server.
+ if (response_code_ >= 500) {
+ // When encountering a server error, we will send the request again
+ // after backoff time.
+ int64 back_off_time =
+ protect_entry_->UpdateBackoff(URLFetcherProtectEntry::FAILURE);
+ if (delegate_) {
+ fetcher_->backoff_delay_ =
+ base::TimeDelta::FromMilliseconds(back_off_time);
+ }
+ ++num_retries_;
+ // Restarts the request if we still need to notify the delegate.
+ if (delegate_) {
+ if (fetcher_->automatically_retry_on_5xx_ &&
+ num_retries_ <= protect_entry_->max_retries()) {
+ io_message_loop_proxy_->PostDelayedTask(
+ FROM_HERE,
+ NewRunnableMethod(this, &Core::StartURLRequest), back_off_time);
+ } else {
+ delegate_->OnURLFetchComplete(fetcher_, url_, status, response_code_,
+ cookies_, data_);
+ }
+ }
+ } else {
+ protect_entry_->UpdateBackoff(URLFetcherProtectEntry::SUCCESS);
+ if (delegate_) {
+ fetcher_->backoff_delay_ = base::TimeDelta();
+ delegate_->OnURLFetchComplete(fetcher_, url_, status, response_code_,
+ cookies_, data_);
+ }
+ }
+}
+
+void URLFetcher::set_upload_data(const std::string& upload_content_type,
+ const std::string& upload_content) {
+ core_->upload_content_type_ = upload_content_type;
+ core_->upload_content_ = upload_content;
+}
+
+const std::string& URLFetcher::upload_data() const {
+ return core_->upload_content_;
+}
+
+void URLFetcher::set_load_flags(int load_flags) {
+ core_->load_flags_ = load_flags;
+}
+
+int URLFetcher::load_flags() const {
+ return core_->load_flags_;
+}
+
+void URLFetcher::set_extra_request_headers(
+ const std::string& extra_request_headers) {
+ core_->extra_request_headers_.Clear();
+ core_->extra_request_headers_.AddHeadersFromString(extra_request_headers);
+}
+
+void URLFetcher::set_request_context(
+ URLRequestContextGetter* request_context_getter) {
+ core_->request_context_getter_ = request_context_getter;
+}
+
+void URLFetcher::set_automatcally_retry_on_5xx(bool retry) {
+ automatically_retry_on_5xx_ = retry;
+}
+
+net::HttpResponseHeaders* URLFetcher::response_headers() const {
+ return core_->response_headers_;
+}
+
+void URLFetcher::Start() {
+ core_->Start();
+}
+
+const GURL& URLFetcher::url() const {
+ return core_->url_;
+}
+
+URLFetcher::Delegate* URLFetcher::delegate() const {
+ return core_->delegate();
+}
diff --git a/chrome/common/net/url_fetcher.h b/chrome/common/net/url_fetcher.h
new file mode 100644
index 0000000..9572478
--- /dev/null
+++ b/chrome/common/net/url_fetcher.h
@@ -0,0 +1,192 @@
+// Copyright (c) 2010 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.
+//
+// This file contains URLFetcher, a wrapper around URLRequest that handles
+// low-level details like thread safety, ref counting, and incremental buffer
+// reading. This is useful for callers who simply want to get the data from a
+// URL and don't care about all the nitty-gritty details.
+
+#ifndef CHROME_COMMON_NET_URL_FETCHER_H_
+#define CHROME_COMMON_NET_URL_FETCHER_H_
+
+#include <string>
+
+#include "base/message_loop.h"
+#include "base/ref_counted.h"
+#include "base/time.h"
+
+class GURL;
+typedef std::vector<std::string> ResponseCookies;
+class URLFetcher;
+class URLRequestContextGetter;
+class URLRequestStatus;
+
+namespace net {
+class HttpResponseHeaders;
+}
+
+// To use this class, create an instance with the desired URL and a pointer to
+// the object to be notified when the URL has been loaded:
+// URLFetcher* fetcher = new URLFetcher("http://www.google.com", this);
+//
+// Then, optionally set properties on this object, like the request context or
+// extra headers:
+// fetcher->SetExtraRequestHeaders("X-Foo: bar");
+//
+// Finally, start the request:
+// fetcher->Start();
+//
+// The object you supply as a delegate must inherit from URLFetcher::Delegate;
+// when the fetch is completed, OnURLFetchComplete() will be called with the
+// resulting status and (if applicable) HTTP response code. From that point
+// until the original URLFetcher instance is destroyed, you may examine the
+// provided status and data for the URL. (You should copy these objects if you
+// need them to live longer than the URLFetcher instance.) If the URLFetcher
+// instance is destroyed before the callback happens, the fetch will be
+// canceled and no callback will occur.
+//
+// You may create the URLFetcher instance on any thread; OnURLFetchComplete()
+// will be called back on the same thread you use to create the instance.
+//
+//
+// NOTE: By default URLFetcher requests are NOT intercepted, except when
+// interception is explicitly enabled in tests.
+
+class URLFetcher {
+ public:
+ enum RequestType {
+ GET,
+ POST,
+ HEAD,
+ };
+
+ class Delegate {
+ public:
+ // This will be called when the URL has been fetched, successfully or not.
+ // |response_code| is the HTTP response code (200, 404, etc.) if
+ // applicable. |url|, |status| and |data| are all valid until the
+ // URLFetcher instance is destroyed.
+ virtual void OnURLFetchComplete(const URLFetcher* source,
+ const GURL& url,
+ const URLRequestStatus& status,
+ int response_code,
+ const ResponseCookies& cookies,
+ const std::string& data) = 0;
+ };
+
+ // URLFetcher::Create uses the currently registered Factory to create the
+ // URLFetcher. Factory is intended for testing.
+ class Factory {
+ public:
+ virtual URLFetcher* CreateURLFetcher(int id,
+ const GURL& url,
+ RequestType request_type,
+ Delegate* d) = 0;
+ };
+
+ // |url| is the URL to send the request to.
+ // |request_type| is the type of request to make.
+ // |d| the object that will receive the callback on fetch completion.
+ URLFetcher(const GURL& url, RequestType request_type, Delegate* d);
+
+ virtual ~URLFetcher();
+
+ // Sets the factory used by the static method Create to create a URLFetcher.
+ // URLFetcher does not take ownership of |factory|. A value of NULL results
+ // in a URLFetcher being created directly.
+#if defined(UNIT_TEST)
+ static void set_factory(Factory* factory) { factory_ = factory; }
+#endif
+
+ // Normally interception is disabled for URLFetcher, but you can use this
+ // to enable it for tests. Also see the set_factory method for another way
+ // of testing code that uses an URLFetcher.
+ static void enable_interception_for_tests(bool enabled) {
+ g_interception_enabled = enabled;
+ }
+
+ // Creates a URLFetcher, ownership returns to the caller. If there is no
+ // Factory (the default) this creates and returns a new URLFetcher. See the
+ // constructor for a description of the args. |id| may be used during testing
+ // to identify who is creating the URLFetcher.
+ static URLFetcher* Create(int id, const GURL& url, RequestType request_type,
+ Delegate* d);
+
+ // Sets data only needed by POSTs. All callers making POST requests should
+ // call this before the request is started. |upload_content_type| is the MIME
+ // type of the content, while |upload_content| is the data to be sent (the
+ // Content-Length header value will be set to the length of this data).
+ void set_upload_data(const std::string& upload_content_type,
+ const std::string& upload_content);
+
+ // Set one or more load flags as defined in net/base/load_flags.h. Must be
+ // called before the request is started.
+ void set_load_flags(int load_flags);
+
+ // Returns the current load flags.
+ int load_flags() const;
+
+ // Set extra headers on the request. Must be called before the request
+ // is started.
+ void set_extra_request_headers(const std::string& extra_request_headers);
+
+ // Set the URLRequestContext on the request. Must be called before the
+ // request is started.
+ void set_request_context(URLRequestContextGetter* request_context_getter);
+
+ // If |retry| is false, 5xx responses will be propagated to the observer,
+ // if it is true URLFetcher will automatically re-execute the request,
+ // after backoff_delay() elapses. URLFetcher has it set to true by default.
+ void set_automatcally_retry_on_5xx(bool retry);
+
+ // Returns the back-off delay before the request will be retried,
+ // when a 5xx response was received.
+ base::TimeDelta backoff_delay() const { return backoff_delay_; }
+
+ // Sets the back-off delay, allowing to mock 5xx requests in unit-tests.
+#if defined(UNIT_TEST)
+ void set_backoff_delay(base::TimeDelta backoff_delay) {
+ backoff_delay_ = backoff_delay;
+ }
+#endif // defined(UNIT_TEST)
+
+ // Retrieve the response headers from the request. Must only be called after
+ // the OnURLFetchComplete callback has run.
+ virtual net::HttpResponseHeaders* response_headers() const;
+
+ // Start the request. After this is called, you may not change any other
+ // settings.
+ virtual void Start();
+
+ // Return the URL that this fetcher is processing.
+ const GURL& url() const;
+
+ protected:
+ // Returns the delegate.
+ Delegate* delegate() const;
+
+ // Used by tests.
+ const std::string& upload_data() const;
+
+ private:
+ class Core;
+
+ scoped_refptr<Core> core_;
+
+ static Factory* factory_;
+
+ // If |automatically_retry_on_5xx_| is false, 5xx responses will be
+ // propagated to the observer, if it is true URLFetcher will automatically
+ // re-execute the request, after the back-off delay has expired.
+ // true by default.
+ bool automatically_retry_on_5xx_;
+ // Back-off time delay. 0 by default.
+ base::TimeDelta backoff_delay_;
+
+ static bool g_interception_enabled;
+
+ DISALLOW_COPY_AND_ASSIGN(URLFetcher);
+};
+
+#endif // CHROME_COMMON_NET_URL_FETCHER_H_
diff --git a/chrome/common/net/url_fetcher_protect.cc b/chrome/common/net/url_fetcher_protect.cc
new file mode 100644
index 0000000..05c8e2e
--- /dev/null
+++ b/chrome/common/net/url_fetcher_protect.cc
@@ -0,0 +1,176 @@
+// Copyright (c) 2006-2008 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/common/net/url_fetcher_protect.h"
+
+#include "base/logging.h"
+
+// URLFetcherProtectEntry ----------------------------------------------------
+
+using base::TimeDelta;
+using base::TimeTicks;
+
+// Default parameters. Time is in milliseconds.
+// static
+const int URLFetcherProtectEntry::kDefaultSlidingWindowPeriod = 2000;
+
+const int URLFetcherProtectEntry::kDefaultMaxSendThreshold = 20;
+const int URLFetcherProtectEntry::kDefaultMaxRetries = 0;
+
+const int URLFetcherProtectEntry::kDefaultInitialTimeout = 100;
+const double URLFetcherProtectEntry::kDefaultMultiplier = 2.0;
+const int URLFetcherProtectEntry::kDefaultConstantFactor = 100;
+const int URLFetcherProtectEntry::kDefaultMaximumTimeout = 60000;
+
+
+URLFetcherProtectEntry::URLFetcherProtectEntry()
+ : sliding_window_period_(kDefaultSlidingWindowPeriod),
+ max_send_threshold_(kDefaultMaxSendThreshold),
+ max_retries_(kDefaultMaxRetries),
+ initial_timeout_(kDefaultInitialTimeout),
+ multiplier_(kDefaultMultiplier),
+ constant_factor_(kDefaultConstantFactor),
+ maximum_timeout_(kDefaultMaximumTimeout) {
+ ResetBackoff();
+}
+
+URLFetcherProtectEntry::URLFetcherProtectEntry(int sliding_window_period,
+ int max_send_threshold,
+ int max_retries,
+ int initial_timeout,
+ double multiplier,
+ int constant_factor,
+ int maximum_timeout)
+ : sliding_window_period_(sliding_window_period),
+ max_send_threshold_(max_send_threshold),
+ max_retries_(max_retries),
+ initial_timeout_(initial_timeout),
+ multiplier_(multiplier),
+ constant_factor_(constant_factor),
+ maximum_timeout_(maximum_timeout) {
+ ResetBackoff();
+}
+
+int64 URLFetcherProtectEntry::UpdateBackoff(EventType event_type) {
+ // request may be sent in different threads
+ AutoLock lock(lock_);
+
+ TimeDelta t;
+ switch (event_type) {
+ case SEND:
+ t = AntiOverload();
+ break;
+ case SUCCESS:
+ t = ResetBackoff();
+ break;
+ case FAILURE:
+ t = IncreaseBackoff();
+ break;
+ default:
+ NOTREACHED();
+ }
+
+ int64 wait = t.InMilliseconds();
+ DCHECK(wait >= 0);
+ return wait;
+}
+
+TimeDelta URLFetcherProtectEntry::AntiOverload() {
+ TimeDelta sw = TimeDelta::FromMilliseconds(sliding_window_period_);
+ TimeTicks now = TimeTicks::Now();
+ // Estimate when the next request will be sent.
+ release_time_ = now;
+ if (send_log_.size() > 0) {
+ release_time_ = std::max(release_time_, send_log_.back());
+ }
+ // Checks if there are too many send events in recent time.
+ if (send_log_.size() >= static_cast<unsigned>(max_send_threshold_)) {
+ release_time_ = std::max(release_time_, send_log_.front() + sw);
+ }
+ // Logs the new send event.
+ send_log_.push(release_time_);
+ // Drops the out-of-date events in the event list.
+ while (!send_log_.empty() &&
+ (send_log_.front() + sw <= send_log_.back())) {
+ send_log_.pop();
+ }
+ return release_time_ - now;
+}
+
+TimeDelta URLFetcherProtectEntry::ResetBackoff() {
+ timeout_period_ = initial_timeout_;
+ release_time_ = TimeTicks::Now();
+ return TimeDelta::FromMilliseconds(0);
+}
+
+TimeDelta URLFetcherProtectEntry::IncreaseBackoff() {
+ TimeTicks now = TimeTicks::Now();
+
+ release_time_ = std::max(release_time_, now) +
+ TimeDelta::FromMilliseconds(timeout_period_);
+
+ // Calculates the new backoff time.
+ timeout_period_ = static_cast<int>
+ (multiplier_ * timeout_period_ + constant_factor_);
+ if (maximum_timeout_ && timeout_period_ > maximum_timeout_)
+ timeout_period_ = maximum_timeout_;
+
+ return release_time_ - now;
+}
+
+// URLFetcherProtectManager --------------------------------------------------
+
+// static
+scoped_ptr<URLFetcherProtectManager> URLFetcherProtectManager::protect_manager_;
+Lock URLFetcherProtectManager::lock_;
+
+URLFetcherProtectManager::~URLFetcherProtectManager() {
+ // Deletes all entries
+ ProtectService::iterator i;
+ for (i = services_.begin(); i != services_.end(); ++i) {
+ if (i->second)
+ delete i->second;
+ }
+}
+
+// static
+URLFetcherProtectManager* URLFetcherProtectManager::GetInstance() {
+ AutoLock lock(lock_);
+
+ if (protect_manager_.get() == NULL) {
+ protect_manager_.reset(new URLFetcherProtectManager());
+ }
+ return protect_manager_.get();
+}
+
+URLFetcherProtectEntry* URLFetcherProtectManager::Register(
+ const std::string& id) {
+ AutoLock lock(lock_);
+
+ ProtectService::iterator i = services_.find(id);
+
+ if (i != services_.end()) {
+ // The entry exists.
+ return i->second;
+ }
+
+ // Creates a new entry.
+ URLFetcherProtectEntry* entry = new URLFetcherProtectEntry();
+ services_[id] = entry;
+ return entry;
+}
+
+URLFetcherProtectEntry* URLFetcherProtectManager::Register(
+ const std::string& id, URLFetcherProtectEntry* entry) {
+ AutoLock lock(lock_);
+
+ ProtectService::iterator i = services_.find(id);
+ if (i != services_.end()) {
+ // The entry exists.
+ delete i->second;
+ }
+
+ services_[id] = entry;
+ return entry;
+}
diff --git a/chrome/common/net/url_fetcher_protect.h b/chrome/common/net/url_fetcher_protect.h
new file mode 100644
index 0000000..0b9c624
--- /dev/null
+++ b/chrome/common/net/url_fetcher_protect.h
@@ -0,0 +1,146 @@
+// Copyright (c) 2006-2008 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.
+//
+// This file implements backoff in the suggest system so that we don't
+// DOS the Suggest servers when using URLFetcher.
+
+#ifndef CHROME_COMMON_NET_URL_FETCHER_PROTECT_H_
+#define CHROME_COMMON_NET_URL_FETCHER_PROTECT_H_
+
+#include <map>
+#include <queue>
+#include <string>
+
+#include "base/lock.h"
+#include "base/scoped_ptr.h"
+#include "base/time.h"
+
+
+// This class is used to manage one service's rate protection. It maintains
+// a queue of connection successes and failures and analyzes the requests
+// over some period of time, in order to deduce the backoff time of every
+// request.
+// The backoff algorithm consists of two parts. Firstly, avoid too many
+// send events in a sliding window. That will prevent traffic overload.
+// Secondly, exponential backoff is used when receiving an error message
+// from server. Exponential backoff period is calculated using the following
+// formula:
+//
+// initial backoff time (the first time to receive error)
+// backoff = k * current_backoff + c (the second, third, ... error)
+// maximum backoff time (when backoff > maximum backoff time)
+//
+// where |k| is the multiplier, and |c| is the constant factor.
+class URLFetcherProtectEntry {
+ public:
+ enum EventType {
+ SEND, // request will be sent out
+ SUCCESS, // successful response
+ FAILURE // no response or error
+ };
+
+ URLFetcherProtectEntry();
+ URLFetcherProtectEntry(int sliding_window_period, int max_send_threshold,
+ int max_retries, int initial_timeout,
+ double multiplier, int constant_factor,
+ int maximum_timeout);
+
+
+ virtual ~URLFetcherProtectEntry() { }
+
+ // When a connection event happens, log it to the queue, and recalculate
+ // the timeout period. It returns the backoff time, in milliseconds, that
+ // indicates to the sender how long should it wait before sending the request.
+ // If the request is allowed to be sent immediately, the backoff time is 0.
+ int64 UpdateBackoff(EventType event_type);
+
+ // Returns the max retries allowed.
+ int max_retries() const {
+ return max_retries_;
+ }
+
+ private:
+ // When a request comes, calculate the release time for it.
+ // Returns the backoff time before sending.
+ base::TimeDelta AntiOverload();
+ // Resets backoff when service is ok.
+ // Returns the backoff time before sending.
+ base::TimeDelta ResetBackoff();
+ // Calculates new backoff when encountering a failure.
+ // Returns the backoff time before sending.
+ base::TimeDelta IncreaseBackoff();
+
+ // Default parameters. Time is in milliseconds.
+ static const int kDefaultSlidingWindowPeriod;
+ static const int kDefaultMaxSendThreshold;
+ static const int kDefaultMaxRetries;
+ static const int kDefaultInitialTimeout;
+ static const double kDefaultMultiplier;
+ static const int kDefaultConstantFactor;
+ static const int kDefaultMaximumTimeout;
+
+ // time to consider events when checking backoff
+ int sliding_window_period_;
+
+ // maximum number of requests allowed in sliding window period
+ int max_send_threshold_;
+ // maximum retris allowed
+ int max_retries_;
+
+ // initial timeout on first failure
+ int initial_timeout_;
+ // factor by which to multiply on exponential backoff (e.g., 2.0)
+ double multiplier_;
+ // constant time term to add to each attempt
+ int constant_factor_;
+ // maximum amount of time between requests
+ int maximum_timeout_;
+
+ // current exponential backoff period
+ int timeout_period_;
+ // time that protection is scheduled to end
+ base::TimeTicks release_time_;
+
+ // Sets up a lock to ensure thread safe.
+ Lock lock_;
+
+ // A list of the recent send events. We ues them to decide whether
+ // there are too many requests sent in sliding window.
+ std::queue<base::TimeTicks> send_log_;
+
+ DISALLOW_COPY_AND_ASSIGN(URLFetcherProtectEntry);
+};
+
+
+// This singleton class is used to manage all protect entries.
+// Now we use the host name as service id.
+class URLFetcherProtectManager {
+ public:
+ ~URLFetcherProtectManager();
+
+ // Returns the global instance of this class.
+ static URLFetcherProtectManager* GetInstance();
+
+ // Registers a new entry in this service. If the entry already exists,
+ // just returns it. Ownership of the return object remains with the manager.
+ URLFetcherProtectEntry* Register(const std::string& id);
+ // Always registers the entry even when it exists; any existing entry for this
+ // id will be deleted and existing references to it will become invalid.
+ // Ownership of the return object remains with the manager.
+ URLFetcherProtectEntry* Register(const std::string& id,
+ URLFetcherProtectEntry* entry);
+
+ private:
+ URLFetcherProtectManager() { }
+
+ typedef std::map<const std::string, URLFetcherProtectEntry*> ProtectService;
+
+ static Lock lock_;
+ static scoped_ptr<URLFetcherProtectManager> protect_manager_;
+ ProtectService services_;
+
+ DISALLOW_COPY_AND_ASSIGN(URLFetcherProtectManager);
+};
+
+#endif // CHROME_COMMON_NET_URL_FETCHER_PROTECT_H_
diff --git a/chrome/common/net/url_fetcher_unittest.cc b/chrome/common/net/url_fetcher_unittest.cc
new file mode 100644
index 0000000..5e39c2a
--- /dev/null
+++ b/chrome/common/net/url_fetcher_unittest.cc
@@ -0,0 +1,613 @@
+// Copyright (c) 2006-2008 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_proxy.h"
+#include "base/thread.h"
+#include "base/waitable_event.h"
+#include "chrome/common/chrome_plugin_lib.h"
+#include "chrome/common/net/url_fetcher.h"
+#include "chrome/common/net/url_fetcher_protect.h"
+#include "chrome/common/net/url_request_context_getter.h"
+#include "net/http/http_response_headers.h"
+#include "net/test/test_server.h"
+#include "net/url_request/url_request_unittest.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+using base::Time;
+using base::TimeDelta;
+
+// TODO(eroman): Add a regression test for http://crbug.com/40505.
+
+namespace {
+
+const wchar_t kDocRoot[] = L"chrome/test/data";
+
+class TestURLRequestContextGetter : public URLRequestContextGetter {
+ public:
+ explicit TestURLRequestContextGetter(
+ base::MessageLoopProxy* io_message_loop_proxy)
+ : io_message_loop_proxy_(io_message_loop_proxy) {
+ }
+ virtual URLRequestContext* GetURLRequestContext() {
+ if (!context_)
+ context_ = new TestURLRequestContext();
+ return context_;
+ }
+ virtual scoped_refptr<base::MessageLoopProxy> GetIOMessageLoopProxy() {
+ return io_message_loop_proxy_;
+ }
+
+ protected:
+ scoped_refptr<base::MessageLoopProxy> io_message_loop_proxy_;
+
+ private:
+ ~TestURLRequestContextGetter() {}
+
+ scoped_refptr<URLRequestContext> context_;
+};
+
+class URLFetcherTest : public testing::Test, public URLFetcher::Delegate {
+ public:
+ URLFetcherTest() : fetcher_(NULL) { }
+
+ // Creates a URLFetcher, using the program's main thread to do IO.
+ virtual void CreateFetcher(const GURL& url);
+
+ // URLFetcher::Delegate
+ virtual void OnURLFetchComplete(const URLFetcher* source,
+ const GURL& url,
+ const URLRequestStatus& status,
+ int response_code,
+ const ResponseCookies& cookies,
+ const std::string& data);
+
+ scoped_refptr<base::MessageLoopProxy> io_message_loop_proxy() {
+ return io_message_loop_proxy_;
+ }
+
+ protected:
+ virtual void SetUp() {
+ testing::Test::SetUp();
+
+ io_message_loop_proxy_ = base::MessageLoopProxy::CreateForCurrentThread();
+
+ // Ensure that any plugin operations done by other tests are cleaned up.
+ ChromePluginLib::UnloadAllPlugins();
+ }
+
+ // URLFetcher is designed to run on the main UI thread, but in our tests
+ // we assume that the current thread is the IO thread where the URLFetcher
+ // dispatches its requests to. When we wish to simulate being used from
+ // a UI thread, we dispatch a worker thread to do so.
+ MessageLoopForIO io_loop_;
+ scoped_refptr<base::MessageLoopProxy> io_message_loop_proxy_;
+
+ URLFetcher* fetcher_;
+};
+
+// Version of URLFetcherTest that does a POST instead
+class URLFetcherPostTest : public URLFetcherTest {
+ public:
+ virtual void CreateFetcher(const GURL& url);
+
+ // URLFetcher::Delegate
+ virtual void OnURLFetchComplete(const URLFetcher* source,
+ const GURL& url,
+ const URLRequestStatus& status,
+ int response_code,
+ const ResponseCookies& cookies,
+ const std::string& data);
+};
+
+// Version of URLFetcherTest that tests headers.
+class URLFetcherHeadersTest : public URLFetcherTest {
+ public:
+ // URLFetcher::Delegate
+ virtual void OnURLFetchComplete(const URLFetcher* source,
+ const GURL& url,
+ const URLRequestStatus& status,
+ int response_code,
+ const ResponseCookies& cookies,
+ const std::string& data);
+};
+
+// Version of URLFetcherTest that tests overload protection.
+class URLFetcherProtectTest : public URLFetcherTest {
+ public:
+ virtual void CreateFetcher(const GURL& url);
+ // URLFetcher::Delegate
+ virtual void OnURLFetchComplete(const URLFetcher* source,
+ const GURL& url,
+ const URLRequestStatus& status,
+ int response_code,
+ const ResponseCookies& cookies,
+ const std::string& data);
+ private:
+ Time start_time_;
+};
+
+// Version of URLFetcherTest that tests overload protection, when responses
+// passed through.
+class URLFetcherProtectTestPassedThrough : public URLFetcherTest {
+ public:
+ virtual void CreateFetcher(const GURL& url);
+ // URLFetcher::Delegate
+ virtual void OnURLFetchComplete(const URLFetcher* source,
+ const GURL& url,
+ const URLRequestStatus& status,
+ int response_code,
+ const ResponseCookies& cookies,
+ const std::string& data);
+ private:
+ Time start_time_;
+};
+
+// Version of URLFetcherTest that tests bad HTTPS requests.
+class URLFetcherBadHTTPSTest : public URLFetcherTest {
+ public:
+ URLFetcherBadHTTPSTest();
+
+ // URLFetcher::Delegate
+ virtual void OnURLFetchComplete(const URLFetcher* source,
+ const GURL& url,
+ const URLRequestStatus& status,
+ int response_code,
+ const ResponseCookies& cookies,
+ const std::string& data);
+
+ private:
+ FilePath cert_dir_;
+};
+
+// Version of URLFetcherTest that tests request cancellation on shutdown.
+class URLFetcherCancelTest : public URLFetcherTest {
+ public:
+ virtual void CreateFetcher(const GURL& url);
+ // URLFetcher::Delegate
+ virtual void OnURLFetchComplete(const URLFetcher* source,
+ const GURL& url,
+ const URLRequestStatus& status,
+ int response_code,
+ const ResponseCookies& cookies,
+ const std::string& data);
+
+ void CancelRequest();
+};
+
+// Version of TestURLRequestContext that posts a Quit task to the IO
+// thread once it is deleted.
+class CancelTestURLRequestContext : public TestURLRequestContext {
+ virtual ~CancelTestURLRequestContext() {
+ // The d'tor should execute in the IO thread. Post the quit task to the
+ // current thread.
+ MessageLoop::current()->PostTask(FROM_HERE, new MessageLoop::QuitTask());
+ }
+};
+
+class CancelTestURLRequestContextGetter : public URLRequestContextGetter {
+ public:
+ explicit CancelTestURLRequestContextGetter(
+ base::MessageLoopProxy* io_message_loop_proxy)
+ : io_message_loop_proxy_(io_message_loop_proxy),
+ context_created_(false, false) {
+ }
+ virtual URLRequestContext* GetURLRequestContext() {
+ if (!context_) {
+ context_ = new CancelTestURLRequestContext();
+ context_created_.Signal();
+ }
+ return context_;
+ }
+ virtual scoped_refptr<base::MessageLoopProxy> GetIOMessageLoopProxy() {
+ return io_message_loop_proxy_;
+ }
+ void WaitForContextCreation() {
+ context_created_.Wait();
+ }
+
+ private:
+ ~CancelTestURLRequestContextGetter() {}
+
+ scoped_refptr<base::MessageLoopProxy> io_message_loop_proxy_;
+ base::WaitableEvent context_created_;
+ scoped_refptr<URLRequestContext> context_;
+};
+
+// Wrapper that lets us call CreateFetcher() on a thread of our choice. We
+// could make URLFetcherTest refcounted and use PostTask(FROM_HERE.. ) to call
+// CreateFetcher() directly, but the ownership of the URLFetcherTest is a bit
+// confusing in that case because GTest doesn't know about the refcounting.
+// It's less confusing to just do it this way.
+class FetcherWrapperTask : public Task {
+ public:
+ FetcherWrapperTask(URLFetcherTest* test, const GURL& url)
+ : test_(test), url_(url) { }
+ virtual void Run() {
+ test_->CreateFetcher(url_);
+ }
+
+ private:
+ URLFetcherTest* test_;
+ GURL url_;
+};
+
+void URLFetcherTest::CreateFetcher(const GURL& url) {
+ fetcher_ = new URLFetcher(url, URLFetcher::GET, this);
+ fetcher_->set_request_context(new TestURLRequestContextGetter(
+ io_message_loop_proxy()));
+ fetcher_->Start();
+}
+
+void URLFetcherTest::OnURLFetchComplete(const URLFetcher* source,
+ const GURL& url,
+ const URLRequestStatus& status,
+ int response_code,
+ const ResponseCookies& cookies,
+ const std::string& data) {
+ EXPECT_TRUE(status.is_success());
+ EXPECT_EQ(200, response_code); // HTTP OK
+ EXPECT_FALSE(data.empty());
+
+ delete fetcher_; // Have to delete this here and not in the destructor,
+ // because the destructor won't necessarily run on the
+ // same thread that CreateFetcher() did.
+
+ io_message_loop_proxy()->PostTask(FROM_HERE, new MessageLoop::QuitTask());
+ // If the current message loop is not the IO loop, it will be shut down when
+ // the main loop returns and this thread subsequently goes out of scope.
+}
+
+void URLFetcherPostTest::CreateFetcher(const GURL& url) {
+ fetcher_ = new URLFetcher(url, URLFetcher::POST, this);
+ fetcher_->set_request_context(new TestURLRequestContextGetter(
+ io_message_loop_proxy()));
+ fetcher_->set_upload_data("application/x-www-form-urlencoded",
+ "bobsyeruncle");
+ fetcher_->Start();
+}
+
+void URLFetcherPostTest::OnURLFetchComplete(const URLFetcher* source,
+ const GURL& url,
+ const URLRequestStatus& status,
+ int response_code,
+ const ResponseCookies& cookies,
+ const std::string& data) {
+ EXPECT_EQ(std::string("bobsyeruncle"), data);
+ URLFetcherTest::OnURLFetchComplete(source, url, status, response_code,
+ cookies, data);
+}
+
+void URLFetcherHeadersTest::OnURLFetchComplete(
+ const URLFetcher* source,
+ const GURL& url,
+ const URLRequestStatus& status,
+ int response_code,
+ const ResponseCookies& cookies,
+ const std::string& data) {
+ std::string header;
+ EXPECT_TRUE(source->response_headers()->GetNormalizedHeader("cache-control",
+ &header));
+ EXPECT_EQ("private", header);
+ URLFetcherTest::OnURLFetchComplete(source, url, status, response_code,
+ cookies, data);
+}
+
+void URLFetcherProtectTest::CreateFetcher(const GURL& url) {
+ fetcher_ = new URLFetcher(url, URLFetcher::GET, this);
+ fetcher_->set_request_context(new TestURLRequestContextGetter(
+ io_message_loop_proxy()));
+ start_time_ = Time::Now();
+ fetcher_->Start();
+}
+
+void URLFetcherProtectTest::OnURLFetchComplete(const URLFetcher* source,
+ const GURL& url,
+ const URLRequestStatus& status,
+ int response_code,
+ const ResponseCookies& cookies,
+ const std::string& data) {
+ const TimeDelta one_second = TimeDelta::FromMilliseconds(1000);
+ if (response_code >= 500) {
+ // Now running ServerUnavailable test.
+ // It takes more than 1 second to finish all 11 requests.
+ EXPECT_TRUE(Time::Now() - start_time_ >= one_second);
+ EXPECT_TRUE(status.is_success());
+ EXPECT_FALSE(data.empty());
+ delete fetcher_;
+ io_message_loop_proxy()->PostTask(FROM_HERE, new MessageLoop::QuitTask());
+ } else {
+ // Now running Overload test.
+ static int count = 0;
+ count++;
+ if (count < 20) {
+ fetcher_->Start();
+ } else {
+ // We have already sent 20 requests continuously. And we expect that
+ // it takes more than 1 second due to the overload pretection settings.
+ EXPECT_TRUE(Time::Now() - start_time_ >= one_second);
+ URLFetcherTest::OnURLFetchComplete(source, url, status, response_code,
+ cookies, data);
+ }
+ }
+}
+
+void URLFetcherProtectTestPassedThrough::CreateFetcher(const GURL& url) {
+ fetcher_ = new URLFetcher(url, URLFetcher::GET, this);
+ fetcher_->set_request_context(new TestURLRequestContextGetter(
+ io_message_loop_proxy()));
+ fetcher_->set_automatcally_retry_on_5xx(false);
+ start_time_ = Time::Now();
+ fetcher_->Start();
+}
+
+void URLFetcherProtectTestPassedThrough::OnURLFetchComplete(
+ const URLFetcher* source,
+ const GURL& url,
+ const URLRequestStatus& status,
+ int response_code,
+ const ResponseCookies& cookies,
+ const std::string& data) {
+ const TimeDelta one_minute = TimeDelta::FromMilliseconds(60000);
+ if (response_code >= 500) {
+ // Now running ServerUnavailable test.
+ // It should get here on the first attempt, so almost immediately and
+ // *not* to attempt to execute all 11 requests (2.5 minutes).
+ EXPECT_TRUE(Time::Now() - start_time_ < one_minute);
+ EXPECT_TRUE(status.is_success());
+ // Check that suggested back off time is bigger than 0.
+ EXPECT_GT(fetcher_->backoff_delay().InMicroseconds(), 0);
+ EXPECT_FALSE(data.empty());
+ delete fetcher_;
+ io_message_loop_proxy()->PostTask(FROM_HERE, new MessageLoop::QuitTask());
+ } else {
+ // We should not get here!
+ FAIL();
+ }
+}
+
+
+URLFetcherBadHTTPSTest::URLFetcherBadHTTPSTest() {
+ PathService::Get(base::DIR_SOURCE_ROOT, &cert_dir_);
+ cert_dir_ = cert_dir_.AppendASCII("chrome");
+ cert_dir_ = cert_dir_.AppendASCII("test");
+ cert_dir_ = cert_dir_.AppendASCII("data");
+ cert_dir_ = cert_dir_.AppendASCII("ssl");
+ cert_dir_ = cert_dir_.AppendASCII("certificates");
+}
+
+// The "server certificate expired" error should result in automatic
+// cancellation of the request by
+// URLRequest::Delegate::OnSSLCertificateError.
+void URLFetcherBadHTTPSTest::OnURLFetchComplete(
+ const URLFetcher* source,
+ const GURL& url,
+ const URLRequestStatus& status,
+ int response_code,
+ const ResponseCookies& cookies,
+ const std::string& data) {
+ // This part is different from URLFetcherTest::OnURLFetchComplete
+ // because this test expects the request to be cancelled.
+ EXPECT_EQ(URLRequestStatus::CANCELED, status.status());
+ EXPECT_EQ(net::ERR_ABORTED, status.os_error());
+ EXPECT_EQ(-1, response_code);
+ EXPECT_TRUE(cookies.empty());
+ EXPECT_TRUE(data.empty());
+
+ // The rest is the same as URLFetcherTest::OnURLFetchComplete.
+ delete fetcher_;
+ io_message_loop_proxy()->PostTask(FROM_HERE, new MessageLoop::QuitTask());
+}
+
+void URLFetcherCancelTest::CreateFetcher(const GURL& url) {
+ fetcher_ = new URLFetcher(url, URLFetcher::GET, this);
+ CancelTestURLRequestContextGetter* context_getter =
+ new CancelTestURLRequestContextGetter(io_message_loop_proxy());
+ fetcher_->set_request_context(context_getter);
+ fetcher_->Start();
+ // We need to wait for the creation of the URLRequestContext, since we
+ // rely on it being destroyed as a signal to end the test.
+ context_getter->WaitForContextCreation();
+ CancelRequest();
+}
+
+void URLFetcherCancelTest::OnURLFetchComplete(const URLFetcher* source,
+ const GURL& url,
+ const URLRequestStatus& status,
+ int response_code,
+ const ResponseCookies& cookies,
+ const std::string& data) {
+ // We should have cancelled the request before completion.
+ ADD_FAILURE();
+ delete fetcher_;
+ io_message_loop_proxy()->PostTask(FROM_HERE, new MessageLoop::QuitTask());
+}
+
+void URLFetcherCancelTest::CancelRequest() {
+ delete fetcher_;
+ // The URLFetcher's test context will post a Quit task once it is
+ // deleted. So if this test simply hangs, it means cancellation
+ // did not work.
+}
+
+TEST_F(URLFetcherTest, SameThreadsTest) {
+ // Create the fetcher on the main thread. Since IO will happen on the main
+ // thread, this will test URLFetcher's ability to do everything on one
+ // thread.
+ scoped_refptr<HTTPTestServer> server =
+ HTTPTestServer::CreateServer(kDocRoot, NULL);
+ ASSERT_TRUE(NULL != server.get());
+
+ CreateFetcher(GURL(server->TestServerPage("defaultresponse")));
+
+ MessageLoop::current()->Run();
+}
+
+TEST_F(URLFetcherTest, DifferentThreadsTest) {
+ scoped_refptr<HTTPTestServer> server =
+ HTTPTestServer::CreateServer(kDocRoot, NULL);
+ ASSERT_TRUE(NULL != server.get());
+ // Create a separate thread that will create the URLFetcher. The current
+ // (main) thread will do the IO, and when the fetch is complete it will
+ // terminate the main thread's message loop; then the other thread's
+ // message loop will be shut down automatically as the thread goes out of
+ // scope.
+ base::Thread t("URLFetcher test thread");
+ ASSERT_TRUE(t.Start());
+ t.message_loop()->PostTask(FROM_HERE, new FetcherWrapperTask(this,
+ GURL(server->TestServerPage("defaultresponse"))));
+
+ MessageLoop::current()->Run();
+}
+
+TEST_F(URLFetcherPostTest, Basic) {
+ scoped_refptr<HTTPTestServer> server =
+ HTTPTestServer::CreateServer(kDocRoot, NULL);
+ ASSERT_TRUE(NULL != server.get());
+ CreateFetcher(GURL(server->TestServerPage("echo")));
+ MessageLoop::current()->Run();
+}
+
+TEST_F(URLFetcherHeadersTest, Headers) {
+ scoped_refptr<HTTPTestServer> server =
+ HTTPTestServer::CreateServer(L"net/data/url_request_unittest", NULL);
+ ASSERT_TRUE(NULL != server.get());
+ CreateFetcher(GURL(server->TestServerPage("files/with-headers.html")));
+ MessageLoop::current()->Run();
+ // The actual tests are in the URLFetcherHeadersTest fixture.
+}
+
+TEST_F(URLFetcherProtectTest, Overload) {
+ scoped_refptr<HTTPTestServer> server =
+ HTTPTestServer::CreateServer(kDocRoot, NULL);
+ ASSERT_TRUE(NULL != server.get());
+ GURL url = GURL(server->TestServerPage("defaultresponse"));
+
+ // Registers an entry for test url. It only allows 3 requests to be sent
+ // in 200 milliseconds.
+ URLFetcherProtectManager* manager = URLFetcherProtectManager::GetInstance();
+ URLFetcherProtectEntry* entry =
+ new URLFetcherProtectEntry(200, 3, 11, 1, 2.0, 0, 256);
+ manager->Register(url.host(), entry);
+
+ CreateFetcher(url);
+
+ MessageLoop::current()->Run();
+}
+
+TEST_F(URLFetcherProtectTest, ServerUnavailable) {
+ scoped_refptr<HTTPTestServer> server =
+ HTTPTestServer::CreateServer(L"chrome/test/data", NULL);
+ ASSERT_TRUE(NULL != server.get());
+ GURL url = GURL(server->TestServerPage("files/server-unavailable.html"));
+
+ // Registers an entry for test url. The backoff time is calculated by:
+ // new_backoff = 2.0 * old_backoff + 0
+ // and maximum backoff time is 256 milliseconds.
+ // Maximum retries allowed is set to 11.
+ URLFetcherProtectManager* manager = URLFetcherProtectManager::GetInstance();
+ URLFetcherProtectEntry* entry =
+ new URLFetcherProtectEntry(200, 3, 11, 1, 2.0, 0, 256);
+ manager->Register(url.host(), entry);
+
+ CreateFetcher(url);
+
+ MessageLoop::current()->Run();
+}
+
+TEST_F(URLFetcherProtectTestPassedThrough, ServerUnavailablePropagateResponse) {
+ scoped_refptr<HTTPTestServer> server =
+ HTTPTestServer::CreateServer(L"chrome/test/data", NULL);
+ ASSERT_TRUE(NULL != server.get());
+ GURL url = GURL(server->TestServerPage("files/server-unavailable.html"));
+
+ // Registers an entry for test url. The backoff time is calculated by:
+ // new_backoff = 2.0 * old_backoff + 0
+ // and maximum backoff time is 256 milliseconds.
+ // Maximum retries allowed is set to 11.
+ URLFetcherProtectManager* manager = URLFetcherProtectManager::GetInstance();
+ // Total time if *not* for not doing automatic backoff would be 150s.
+ // In reality it should be "as soon as server responds".
+ URLFetcherProtectEntry* entry =
+ new URLFetcherProtectEntry(200, 3, 11, 100, 2.0, 0, 150000);
+ manager->Register(url.host(), entry);
+
+ CreateFetcher(url);
+
+ MessageLoop::current()->Run();
+}
+
+
+TEST_F(URLFetcherBadHTTPSTest, BadHTTPSTest) {
+ scoped_refptr<HTTPSTestServer> server =
+ HTTPSTestServer::CreateExpiredServer(kDocRoot);
+ ASSERT_TRUE(NULL != server.get());
+
+ CreateFetcher(GURL(server->TestServerPage("defaultresponse")));
+
+ MessageLoop::current()->Run();
+}
+
+TEST_F(URLFetcherCancelTest, ReleasesContext) {
+ scoped_refptr<HTTPTestServer> server =
+ HTTPTestServer::CreateServer(L"chrome/test/data", NULL);
+ ASSERT_TRUE(NULL != server.get());
+ GURL url = GURL(server->TestServerPage("files/server-unavailable.html"));
+
+ // Registers an entry for test url. The backoff time is calculated by:
+ // new_backoff = 2.0 * old_backoff + 0
+ // The initial backoff is 2 seconds and maximum backoff is 4 seconds.
+ // Maximum retries allowed is set to 2.
+ URLFetcherProtectManager* manager = URLFetcherProtectManager::GetInstance();
+ URLFetcherProtectEntry* entry =
+ new URLFetcherProtectEntry(200, 3, 2, 2000, 2.0, 0, 4000);
+ manager->Register(url.host(), entry);
+
+ // Create a separate thread that will create the URLFetcher. The current
+ // (main) thread will do the IO, and when the fetch is complete it will
+ // terminate the main thread's message loop; then the other thread's
+ // message loop will be shut down automatically as the thread goes out of
+ // scope.
+ base::Thread t("URLFetcher test thread");
+ ASSERT_TRUE(t.Start());
+ t.message_loop()->PostTask(FROM_HERE, new FetcherWrapperTask(this, url));
+
+ MessageLoop::current()->Run();
+}
+
+TEST_F(URLFetcherCancelTest, CancelWhileDelayedStartTaskPending) {
+ scoped_refptr<HTTPTestServer> server =
+ HTTPTestServer::CreateServer(L"chrome/test/data", NULL);
+ ASSERT_TRUE(NULL != server.get());
+ GURL url = GURL(server->TestServerPage("files/server-unavailable.html"));
+
+ // Register an entry for test url.
+ //
+ // Ideally we would mock URLFetcherProtectEntry to return XXX seconds
+ // in response to entry->UpdateBackoff(SEND).
+ //
+ // Unfortunately this function is time sensitive, so we fudge some numbers
+ // to make it at least somewhat likely to have a non-zero deferred
+ // delay when running.
+ //
+ // Using a sliding window of 2 seconds, and max of 1 request, under a fast
+ // run we expect to have a 4 second delay when posting the Start task.
+ URLFetcherProtectManager* manager = URLFetcherProtectManager::GetInstance();
+ URLFetcherProtectEntry* entry =
+ new URLFetcherProtectEntry(2000, 1, 2, 2000, 2.0, 0, 4000);
+ EXPECT_EQ(0, entry->UpdateBackoff(URLFetcherProtectEntry::SEND));
+ entry->UpdateBackoff(URLFetcherProtectEntry::SEND); // Returns about 2000.
+ manager->Register(url.host(), entry);
+
+ // The next request we try to send will be delayed by ~4 seconds.
+ // The slower the test runs, the less the delay will be (since it takes the
+ // time difference from now).
+
+ base::Thread t("URLFetcher test thread");
+ ASSERT_TRUE(t.Start());
+ t.message_loop()->PostTask(FROM_HERE, new FetcherWrapperTask(this, url));
+
+ MessageLoop::current()->Run();
+}
+
+} // namespace.
diff --git a/chrome/common/net/url_request_context_getter.cc b/chrome/common/net/url_request_context_getter.cc
new file mode 100644
index 0000000..e58b794
--- /dev/null
+++ b/chrome/common/net/url_request_context_getter.cc
@@ -0,0 +1,27 @@
+// Copyright (c) 2009 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_proxy.h"
+#include "chrome/common/net/url_request_context_getter.h"
+#include "net/url_request/url_request_context.h"
+
+net::CookieStore* URLRequestContextGetter::GetCookieStore() {
+ return GetURLRequestContext()->cookie_store();
+}
+
+void URLRequestContextGetter::OnDestruct() {
+ scoped_refptr<base::MessageLoopProxy> io_message_loop_proxy =
+ GetIOMessageLoopProxy();
+ DCHECK(io_message_loop_proxy);
+ if (io_message_loop_proxy) {
+ if (io_message_loop_proxy->BelongsToCurrentThread()) {
+ delete this;
+ } else {
+ io_message_loop_proxy->DeleteSoon(FROM_HERE, this);
+ }
+ }
+ // If no IO message loop proxy was available, we will just leak memory.
+ // This is also true if the IO thread is gone.
+}
+
diff --git a/chrome/common/net/url_request_context_getter.h b/chrome/common/net/url_request_context_getter.h
new file mode 100644
index 0000000..dcc77b3
--- /dev/null
+++ b/chrome/common/net/url_request_context_getter.h
@@ -0,0 +1,55 @@
+// Copyright (c) 2009 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_COMMON_NET_URL_REQUEST_CONTEXT_GETTER_H_
+#define CHROME_COMMON_NET_URL_REQUEST_CONTEXT_GETTER_H_
+
+#include "base/ref_counted.h"
+#include "base/task.h"
+
+namespace base {
+class MessageLoopProxy;
+}
+
+namespace net {
+class CookieStore;
+}
+
+class URLRequestContext;
+struct URLRequestContextGetterTraits;
+
+// Interface for retrieving an URLRequestContext.
+class URLRequestContextGetter
+ : public base::RefCountedThreadSafe<URLRequestContextGetter,
+ URLRequestContextGetterTraits> {
+ public:
+ virtual URLRequestContext* GetURLRequestContext() = 0;
+
+ // Defaults to GetURLRequestContext()->cookie_store(), but
+ // implementations can override it.
+ virtual net::CookieStore* GetCookieStore();
+ // Returns a MessageLoopProxy corresponding to the thread on which the
+ // request IO happens (the thread on which the returned URLRequestContext
+ // may be used).
+ virtual scoped_refptr<base::MessageLoopProxy> GetIOMessageLoopProxy() = 0;
+
+ protected:
+ friend class DeleteTask<URLRequestContextGetter>;
+ friend struct URLRequestContextGetterTraits;
+
+ virtual ~URLRequestContextGetter() {}
+ private:
+ // OnDestruct is meant to ensure deletion on the thread on which the request
+ // IO happens.
+ void OnDestruct();
+};
+
+struct URLRequestContextGetterTraits {
+ static void Destruct(URLRequestContextGetter* context_getter) {
+ context_getter->OnDestruct();
+ }
+};
+
+#endif // CHROME_COMMON_NET_URL_REQUEST_CONTEXT_GETTER_H_
+
diff --git a/chrome/common/net/url_request_intercept_job.cc b/chrome/common/net/url_request_intercept_job.cc
new file mode 100644
index 0000000..ed68fcd
--- /dev/null
+++ b/chrome/common/net/url_request_intercept_job.cc
@@ -0,0 +1,226 @@
+// Copyright (c) 2006-2008 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.
+//
+// This job type handles Chrome plugin network interception. When a plugin
+// wants to intercept a request, a job of this type is created. The intercept
+// job communicates with the plugin to retrieve the response headers and data.
+
+#include "chrome/common/net/url_request_intercept_job.h"
+
+#include "base/message_loop.h"
+#include "base/string_util.h"
+#include "chrome/common/chrome_plugin_lib.h"
+#include "chrome/common/notification_service.h"
+#include "net/base/io_buffer.h"
+#include "net/base/net_errors.h"
+#include "net/http/http_response_headers.h"
+#include "net/url_request/url_request.h"
+
+using base::Time;
+using base::TimeDelta;
+
+//
+// URLRequestInterceptJob
+//
+
+URLRequestInterceptJob::URLRequestInterceptJob(URLRequest* request,
+ ChromePluginLib* plugin,
+ ScopableCPRequest* cprequest)
+ : URLRequestJob(request),
+ cprequest_(cprequest),
+ plugin_(plugin),
+ read_buffer_(NULL) {
+ cprequest_->data = this; // see FromCPRequest().
+
+ registrar_.Add(this, NotificationType::CHROME_PLUGIN_UNLOADED,
+ Source<ChromePluginLib>(plugin_));
+}
+
+URLRequestInterceptJob::~URLRequestInterceptJob() {
+ if (plugin_) {
+ plugin_->functions().request_funcs->end_request(cprequest_.get(),
+ CPERR_SUCCESS);
+ }
+}
+
+void URLRequestInterceptJob::DetachPlugin() {
+ registrar_.RemoveAll();
+ plugin_ = NULL;
+}
+
+void URLRequestInterceptJob::Start() {
+ // Start reading asynchronously so that all error reporting and data
+ // callbacks happen as they would for network requests.
+ MessageLoop::current()->PostTask(FROM_HERE, NewRunnableMethod(
+ this, &URLRequestInterceptJob::StartAsync));
+}
+
+void URLRequestInterceptJob::Kill() {
+ if (plugin_) {
+ plugin_->functions().request_funcs->end_request(cprequest_.get(),
+ CPERR_CANCELLED);
+ DetachPlugin();
+ }
+ URLRequestJob::Kill();
+}
+
+bool URLRequestInterceptJob::ReadRawData(net::IOBuffer* dest, int dest_size,
+ int* bytes_read) {
+ DCHECK_NE(dest_size, 0);
+ DCHECK(bytes_read);
+
+ if (!plugin_)
+ return false;
+
+ int rv = plugin_->functions().request_funcs->read(cprequest_.get(),
+ dest->data(), dest_size);
+ if (rv >= 0) {
+ *bytes_read = rv;
+ return true;
+ }
+
+ if (rv == CPERR_IO_PENDING) {
+ read_buffer_ = dest;
+ read_buffer_size_ = dest_size;
+ SetStatus(URLRequestStatus(URLRequestStatus::IO_PENDING, 0));
+ } else {
+ // TODO(mpcomplete): better error code
+ NotifyDone(URLRequestStatus(URLRequestStatus::FAILED, net::ERR_FAILED));
+ }
+
+ return false;
+}
+
+bool URLRequestInterceptJob::GetMimeType(std::string* mime_type) const {
+ return request_->response_headers()->GetMimeType(mime_type);
+}
+
+bool URLRequestInterceptJob::GetCharset(std::string* charset) {
+ return request_->response_headers()->GetCharset(charset);
+}
+
+bool URLRequestInterceptJob::GetContentEncodings(
+ std::vector<Filter::FilterType>* encoding_types) {
+ DCHECK(encoding_types->empty());
+ if (!request_->response_headers())
+ return false;
+
+ std::string encoding_type;
+ void* iter = NULL;
+ while (request_->response_headers()->EnumerateHeader(
+ &iter, "Content-Encoding", &encoding_type)) {
+ encoding_types->push_back(Filter::ConvertEncodingToType(encoding_type));
+ }
+
+ // Even if encoding types are empty, there is a chance that we need to add
+ // some decoding, as some proxies strip encoding completely. In such cases,
+ // we may need to add (for example) SDCH filtering (when the context suggests
+ // it is appropriate).
+ Filter::FixupEncodingTypes(*this, encoding_types);
+ return !encoding_types->empty();
+}
+
+void URLRequestInterceptJob::GetResponseInfo(net::HttpResponseInfo* info) {
+ if (!plugin_)
+ return;
+
+ std::string raw_headers;
+ int size = plugin_->functions().request_funcs->get_response_info(
+ cprequest_.get(), CPRESPONSEINFO_HTTP_RAW_HEADERS, NULL, 0);
+ int rv = size < 0 ? size :
+ plugin_->functions().request_funcs->get_response_info(
+ cprequest_.get(), CPRESPONSEINFO_HTTP_RAW_HEADERS,
+ WriteInto(&raw_headers, size+1), size);
+ if (rv != CPERR_SUCCESS) {
+ // TODO(mpcomplete): what should we do here?
+ raw_headers = "HTTP/1.1 404 Not Found" + '\0';
+ }
+
+ info->headers = new net::HttpResponseHeaders(raw_headers);
+
+ if (request_->url().SchemeIsSecure()) {
+ // Make up a fake certificate for intercepted data since we don't have
+ // access to the real SSL info.
+ // TODO(mpcomplete): we should probably have the interception API transmit
+ // the SSL info, but the only consumer of this API (Gears) doesn't keep that
+ // around. We should change that.
+ const char* kCertIssuer = "Chrome Internal";
+ const int kLifetimeDays = 100;
+
+ DLOG(WARNING) << "Issuing a fake SSL certificate for interception of URL "
+ << request_->url();
+
+ info->ssl_info.cert =
+ new net::X509Certificate(request_->url().GetWithEmptyPath().spec(),
+ kCertIssuer,
+ Time::Now(),
+ Time::Now() +
+ TimeDelta::FromDays(kLifetimeDays));
+ info->ssl_info.cert_status = 0;
+ info->ssl_info.security_bits = 0;
+ }
+}
+
+int URLRequestInterceptJob::GetResponseCode() const {
+ if (!plugin_)
+ return -1;
+
+ int status = 200;
+ plugin_->functions().request_funcs->get_response_info(
+ cprequest_.get(), CPRESPONSEINFO_HTTP_STATUS, &status, sizeof(status));
+
+ return status;
+}
+
+bool URLRequestInterceptJob::IsRedirectResponse(GURL* location,
+ int* http_status_code) {
+ if (!request_->response_headers())
+ return false;
+
+ std::string value;
+ if (!request_->response_headers()->IsRedirect(&value))
+ return false;
+
+ *location = request_->url().Resolve(value);
+ *http_status_code = request_->response_headers()->response_code();
+ return true;
+}
+
+void URLRequestInterceptJob::StartAsync() {
+ // We may have been orphaned...
+ if (!request_ || !plugin_)
+ return;
+
+ int rv = plugin_->functions().request_funcs->start_request(cprequest_.get());
+ if (rv != CPERR_IO_PENDING)
+ OnStartCompleted(rv);
+}
+
+void URLRequestInterceptJob::OnStartCompleted(int result) {
+ if (result != CPERR_SUCCESS) {
+ NotifyDone(URLRequestStatus(URLRequestStatus::FAILED,
+ net::ERR_CONNECTION_FAILED));
+ return;
+ }
+
+ NotifyHeadersComplete();
+}
+
+void URLRequestInterceptJob::OnReadCompleted(int bytes_read) {
+ if (bytes_read < 0) {
+ NotifyDone(URLRequestStatus(URLRequestStatus::FAILED, net::ERR_FAILED));
+ return;
+ }
+
+ SetStatus(URLRequestStatus()); // clear the async flag
+ NotifyReadComplete(bytes_read);
+}
+
+void URLRequestInterceptJob::Observe(NotificationType type,
+ const NotificationSource& source,
+ const NotificationDetails& details) {
+ DCHECK(type == NotificationType::CHROME_PLUGIN_UNLOADED);
+ DCHECK(plugin_ == Source<ChromePluginLib>(source).ptr());
+ DetachPlugin();
+}
diff --git a/chrome/common/net/url_request_intercept_job.h b/chrome/common/net/url_request_intercept_job.h
new file mode 100644
index 0000000..3b7058b
--- /dev/null
+++ b/chrome/common/net/url_request_intercept_job.h
@@ -0,0 +1,67 @@
+// Copyright (c) 2006-2008 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_COMMON_NET_URL_REQUEST_INTERCEPT_JOB_H_
+#define CHROME_COMMON_NET_URL_REQUEST_INTERCEPT_JOB_H_
+
+#include <string>
+
+#include "base/scoped_ptr.h"
+#include "net/url_request/url_request_job.h"
+#include "chrome/common/chrome_plugin_api.h"
+#include "chrome/common/chrome_plugin_util.h"
+#include "chrome/common/notification_registrar.h"
+
+class ChromePluginLib;
+class URLRequest;
+
+// A request job that handles network requests intercepted by a Chrome plugin.
+class URLRequestInterceptJob
+ : public URLRequestJob, public NotificationObserver {
+ public:
+ static URLRequestInterceptJob* FromCPRequest(CPRequest* request) {
+ return ScopableCPRequest::GetData<URLRequestInterceptJob*>(request);
+ }
+
+ URLRequestInterceptJob(URLRequest* request, ChromePluginLib* plugin,
+ ScopableCPRequest* cprequest);
+ virtual ~URLRequestInterceptJob();
+
+ // Plugin callbacks.
+ void OnStartCompleted(int result);
+ void OnReadCompleted(int bytes_read);
+
+ // URLRequestJob
+ virtual void Start();
+ virtual void Kill();
+ virtual bool GetMimeType(std::string* mime_type) const;
+ virtual bool GetCharset(std::string* charset);
+ virtual void GetResponseInfo(net::HttpResponseInfo* info);
+ virtual int GetResponseCode() const;
+ virtual bool GetContentEncodings(
+ std::vector<Filter::FilterType>* encoding_types);
+ virtual bool IsRedirectResponse(GURL* location, int* http_status_code);
+
+ // NotificationObserver
+ virtual void Observe(NotificationType type,
+ const NotificationSource& source,
+ const NotificationDetails& details);
+
+ protected:
+ virtual bool ReadRawData(net::IOBuffer* buf, int buf_size, int* bytes_read);
+
+ private:
+ void StartAsync();
+ void DetachPlugin();
+
+ NotificationRegistrar registrar_;
+ scoped_ptr<ScopableCPRequest> cprequest_;
+ ChromePluginLib* plugin_;
+ net::IOBuffer* read_buffer_;
+ int read_buffer_size_;
+
+ DISALLOW_COPY_AND_ASSIGN(URLRequestInterceptJob);
+};
+
+#endif // CHROME_COMMON_NET_URL_REQUEST_INTERCEPT_JOB_H_
diff --git a/chrome/common/notification_details.cc b/chrome/common/notification_details.cc
new file mode 100644
index 0000000..4455faa
--- /dev/null
+++ b/chrome/common/notification_details.cc
@@ -0,0 +1,18 @@
+// Copyright (c) 2010 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/common/notification_details.h"
+
+NotificationDetails::NotificationDetails() : ptr_(NULL) {
+}
+
+NotificationDetails::NotificationDetails(const NotificationDetails& other)
+ : ptr_(other.ptr_) {
+}
+
+NotificationDetails::NotificationDetails(const void* ptr) : ptr_(ptr) {
+}
+
+NotificationDetails::~NotificationDetails() {
+}
diff --git a/chrome/common/notification_details.h b/chrome/common/notification_details.h
new file mode 100644
index 0000000..92c1906
--- /dev/null
+++ b/chrome/common/notification_details.h
@@ -0,0 +1,56 @@
+// Copyright (c) 2006-2008 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.
+
+// This file defines the type used to provide details for NotificationService
+// notifications.
+
+#ifndef CHROME_COMMON_NOTIFICATION_DETAILS_H__
+#define CHROME_COMMON_NOTIFICATION_DETAILS_H__
+
+#include "base/basictypes.h"
+
+// Do not declare a NotificationDetails directly--use either
+// "Details<detailsclassname>(detailsclasspointer)" or
+// NotificationService::NoDetails().
+class NotificationDetails {
+ public:
+ NotificationDetails();
+ NotificationDetails(const NotificationDetails& other);
+ ~NotificationDetails();
+
+ // NotificationDetails can be used as the index for a map; this method
+ // returns the pointer to the current details as an identifier, for use as a
+ // map index.
+ uintptr_t map_key() const { return reinterpret_cast<uintptr_t>(ptr_); }
+
+ bool operator!=(const NotificationDetails& other) const {
+ return ptr_ != other.ptr_;
+ }
+
+ bool operator==(const NotificationDetails& other) const {
+ return ptr_ == other.ptr_;
+ }
+
+ protected:
+ explicit NotificationDetails(const void* ptr);
+
+ // Declaring this const allows Details<T> to be used with both T = Foo and
+ // T = const Foo.
+ const void* ptr_;
+};
+
+template <class T>
+class Details : public NotificationDetails {
+ public:
+ // TODO(erg): Our code hard relies on implicit conversion
+ Details(T* ptr) : NotificationDetails(ptr) {} // NOLINT
+ Details(const NotificationDetails& other) // NOLINT
+ : NotificationDetails(other) {}
+
+ T* operator->() const { return ptr(); }
+ // The casts here allow this to compile with both T = Foo and T = const Foo.
+ T* ptr() const { return static_cast<T*>(const_cast<void*>(ptr_)); }
+};
+
+#endif // CHROME_COMMON_NOTIFICATION_DETAILS_H__
diff --git a/chrome/common/notification_observer.h b/chrome/common/notification_observer.h
new file mode 100644
index 0000000..8ad4d4a
--- /dev/null
+++ b/chrome/common/notification_observer.h
@@ -0,0 +1,24 @@
+// Copyright (c) 2009 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_COMMON_NOTIFICATION_OBSERVER_H_
+#define CHROME_COMMON_NOTIFICATION_OBSERVER_H_
+
+class NotificationDetails;
+class NotificationSource;
+class NotificationType;
+
+// This is the base class for notification observers. When a matching
+// notification is posted to the notification service, Observe is called.
+class NotificationObserver {
+ public:
+ NotificationObserver();
+ virtual ~NotificationObserver();
+
+ virtual void Observe(NotificationType type,
+ const NotificationSource& source,
+ const NotificationDetails& details) = 0;
+};
+
+#endif // CHROME_COMMON_NOTIFICATION_OBSERVER_H_
diff --git a/chrome/common/notification_observer_mock.h b/chrome/common/notification_observer_mock.h
new file mode 100644
index 0000000..9eeb665
--- /dev/null
+++ b/chrome/common/notification_observer_mock.h
@@ -0,0 +1,24 @@
+// Copyright (c) 2009 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_COMMON_NOTIFICATION_OBSERVER_MOCK_H_
+#define CHROME_COMMON_NOTIFICATION_OBSERVER_MOCK_H_
+
+#include "chrome/common/notification_details.h"
+#include "chrome/common/notification_observer.h"
+#include "chrome/common/notification_source.h"
+#include "chrome/common/notification_type.h"
+#include "testing/gmock/include/gmock/gmock.h"
+
+class NotificationObserverMock : public NotificationObserver {
+ public:
+ NotificationObserverMock() {}
+ virtual ~NotificationObserverMock() {}
+
+ MOCK_METHOD3(Observe, void(NotificationType type,
+ const NotificationSource& source,
+ const NotificationDetails& details));
+};
+
+#endif // CHROME_COMMON_NOTIFICATION_OBSERVER_MOCK_H_
diff --git a/chrome/common/notification_registrar.cc b/chrome/common/notification_registrar.cc
new file mode 100644
index 0000000..7ec5cda
--- /dev/null
+++ b/chrome/common/notification_registrar.cc
@@ -0,0 +1,108 @@
+// Copyright (c) 2010 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/common/notification_registrar.h"
+
+#include <algorithm>
+
+#include "base/logging.h"
+#include "chrome/common/notification_service.h"
+#include "base/platform_thread.h"
+
+namespace {
+
+void CheckCalledOnValidThread(PlatformThreadId thread_id) {
+ PlatformThreadId current_thread_id = PlatformThread::CurrentId();
+ CHECK(current_thread_id == thread_id) << "called on invalid thread: "
+ << thread_id << " vs. "
+ << current_thread_id;
+}
+
+} // namespace
+
+struct NotificationRegistrar::Record {
+ bool operator==(const Record& other) const;
+
+ NotificationObserver* observer;
+ NotificationType type;
+ NotificationSource source;
+ PlatformThreadId thread_id;
+};
+
+bool NotificationRegistrar::Record::operator==(const Record& other) const {
+ return observer == other.observer &&
+ type == other.type &&
+ source == other.source;
+ // thread_id is for debugging purpose and thus not compared here.
+}
+
+NotificationRegistrar::NotificationRegistrar() {
+}
+
+NotificationRegistrar::~NotificationRegistrar() {
+ RemoveAll();
+}
+
+void NotificationRegistrar::Add(NotificationObserver* observer,
+ NotificationType type,
+ const NotificationSource& source) {
+ Record record = { observer, type, source, PlatformThread::CurrentId() };
+
+ DCHECK(std::find(registered_.begin(), registered_.end(), record) ==
+ registered_.end()) << "Duplicate registration.";
+ registered_.push_back(record);
+
+ NotificationService::current()->AddObserver(observer, type, source);
+}
+
+void NotificationRegistrar::Remove(NotificationObserver* observer,
+ NotificationType type,
+ const NotificationSource& source) {
+ Record record = { observer, type, source };
+ RecordVector::iterator found = std::find(
+ registered_.begin(), registered_.end(), record);
+ if (found == registered_.end()) {
+ NOTREACHED() << "Trying to remove unregistered observer of type " <<
+ type.value << " from list of size " << registered_.size() << ".";
+ return;
+ }
+ CheckCalledOnValidThread(found->thread_id);
+
+ registered_.erase(found);
+
+ // This can be NULL if our owner outlives the NotificationService, e.g. if our
+ // owner is a Singleton.
+ NotificationService* service = NotificationService::current();
+ if (service)
+ service->RemoveObserver(observer, type, source);
+}
+
+void NotificationRegistrar::RemoveAll() {
+ // Early-exit if no registrations, to avoid calling
+ // NotificationService::current. If we've constructed an object with a
+ // NotificationRegistrar member, but haven't actually used the notification
+ // service, and we reach prgram exit, then calling current() below could try
+ // to initialize the service's lazy TLS pointer during exit, which throws
+ // wrenches at things.
+ if (registered_.empty())
+ return;
+
+
+ // This can be NULL if our owner outlives the NotificationService, e.g. if our
+ // owner is a Singleton.
+ NotificationService* service = NotificationService::current();
+ if (service) {
+ for (size_t i = 0; i < registered_.size(); i++) {
+ CheckCalledOnValidThread(registered_[i].thread_id);
+ service->RemoveObserver(registered_[i].observer,
+ registered_[i].type,
+ registered_[i].source);
+ }
+ }
+ registered_.clear();
+}
+
+bool NotificationRegistrar::IsEmpty() const {
+ return registered_.empty();
+}
diff --git a/chrome/common/notification_registrar.h b/chrome/common/notification_registrar.h
new file mode 100644
index 0000000..f8dd743
--- /dev/null
+++ b/chrome/common/notification_registrar.h
@@ -0,0 +1,56 @@
+// Copyright (c) 2010 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_COMMON_NOTIFICATION_REGISTRAR_H_
+#define CHROME_COMMON_NOTIFICATION_REGISTRAR_H_
+
+#include <vector>
+
+#include "base/basictypes.h"
+#include "chrome/common/notification_observer.h"
+
+// Aids in registering for notifications and ensures that all registered
+// notifications are unregistered when the class is destroyed.
+//
+// The intended use is that you make a NotificationRegistrar member in your
+// class and use it to register your notifications instead of going through the
+// notification service directly. It will automatically unregister them for
+// you.
+class NotificationRegistrar {
+ public:
+ // This class must not be derived from (we don't have a virtual destructor so
+ // it won't work). Instead, use it as a member in your class.
+ NotificationRegistrar();
+ ~NotificationRegistrar();
+
+ // Wrappers around NotificationService::[Add|Remove]Observer.
+ void Add(NotificationObserver* observer,
+ NotificationType type,
+ const NotificationSource& source);
+ void Remove(NotificationObserver* observer,
+ NotificationType type,
+ const NotificationSource& source);
+
+ // Unregisters all notifications.
+ void RemoveAll();
+
+ // Returns true if no notifications are registered.
+ bool IsEmpty() const;
+
+ private:
+ struct Record;
+
+ // We keep registered notifications in a simple vector. This means we'll do
+ // brute-force searches when removing them individually, but individual
+ // removal is uncommon, and there will typically only be a couple of
+ // notifications anyway.
+ typedef std::vector<Record> RecordVector;
+
+ // Lists all notifications we're currently registered for.
+ RecordVector registered_;
+
+ DISALLOW_COPY_AND_ASSIGN(NotificationRegistrar);
+};
+
+#endif // CHROME_COMMON_NOTIFICATION_REGISTRAR_H_
diff --git a/chrome/common/notification_service.cc b/chrome/common/notification_service.cc
new file mode 100644
index 0000000..e127ccf
--- /dev/null
+++ b/chrome/common/notification_service.cc
@@ -0,0 +1,152 @@
+// Copyright (c) 2006-2008 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/common/notification_service.h"
+
+#include "base/lazy_instance.h"
+#include "base/thread_local.h"
+
+static base::LazyInstance<base::ThreadLocalPointer<NotificationService> >
+ lazy_tls_ptr(base::LINKER_INITIALIZED);
+
+// static
+NotificationService* NotificationService::current() {
+ return lazy_tls_ptr.Pointer()->Get();
+}
+
+// static
+bool NotificationService::HasKey(const NotificationSourceMap& map,
+ const NotificationSource& source) {
+ return map.find(source.map_key()) != map.end();
+}
+
+NotificationService::NotificationService() {
+ DCHECK(current() == NULL);
+#ifndef NDEBUG
+ memset(observer_counts_, 0, sizeof(observer_counts_));
+#endif
+
+ lazy_tls_ptr.Pointer()->Set(this);
+}
+
+void NotificationService::AddObserver(NotificationObserver* observer,
+ NotificationType type,
+ const NotificationSource& source) {
+ DCHECK(type.value < NotificationType::NOTIFICATION_TYPE_COUNT);
+
+ // We have gotten some crashes where the observer pointer is NULL. The problem
+ // is that this happens when we actually execute a notification, so have no
+ // way of knowing who the bad observer was. We want to know when this happens
+ // in release mode so we know what code to blame the crash on (since this is
+ // guaranteed to crash later).
+ CHECK(observer);
+
+ NotificationObserverList* observer_list;
+ if (HasKey(observers_[type.value], source)) {
+ observer_list = observers_[type.value][source.map_key()];
+ } else {
+ observer_list = new NotificationObserverList;
+ observers_[type.value][source.map_key()] = observer_list;
+ }
+
+ observer_list->AddObserver(observer);
+#ifndef NDEBUG
+ ++observer_counts_[type.value];
+#endif
+}
+
+void NotificationService::RemoveObserver(NotificationObserver* observer,
+ NotificationType type,
+ const NotificationSource& source) {
+ DCHECK(type.value < NotificationType::NOTIFICATION_TYPE_COUNT);
+
+ // This is a very serious bug. An object is most likely being deleted on
+ // the wrong thread, and as a result another thread's NotificationService
+ // has its deleted pointer in its map. A garbge object will be called in the
+ // future.
+ // NOTE: when this check shows crashes, use ChromeThread::DeleteOnIOThread or
+ // other variants as the trait on the object.
+ CHECK(HasKey(observers_[type.value], source));
+
+ NotificationObserverList* observer_list =
+ observers_[type.value][source.map_key()];
+ if (observer_list) {
+ observer_list->RemoveObserver(observer);
+#ifndef NDEBUG
+ --observer_counts_[type.value];
+#endif
+ }
+
+ // TODO(jhughes): Remove observer list from map if empty?
+}
+
+void NotificationService::Notify(NotificationType type,
+ const NotificationSource& source,
+ const NotificationDetails& details) {
+ DCHECK(type.value > NotificationType::ALL) <<
+ "Allowed for observing, but not posting.";
+ DCHECK(type.value < NotificationType::NOTIFICATION_TYPE_COUNT);
+
+ // There's no particular reason for the order in which the different
+ // classes of observers get notified here.
+
+ // Notify observers of all types and all sources
+ if (HasKey(observers_[NotificationType::ALL], AllSources()) &&
+ source != AllSources()) {
+ FOR_EACH_OBSERVER(NotificationObserver,
+ *observers_[NotificationType::ALL][AllSources().map_key()],
+ Observe(type, source, details));
+ }
+
+ // Notify observers of all types and the given source
+ if (HasKey(observers_[NotificationType::ALL], source)) {
+ FOR_EACH_OBSERVER(NotificationObserver,
+ *observers_[NotificationType::ALL][source.map_key()],
+ Observe(type, source, details));
+ }
+
+ // Notify observers of the given type and all sources
+ if (HasKey(observers_[type.value], AllSources()) &&
+ source != AllSources()) {
+ FOR_EACH_OBSERVER(NotificationObserver,
+ *observers_[type.value][AllSources().map_key()],
+ Observe(type, source, details));
+ }
+
+ // Notify observers of the given type and the given source
+ if (HasKey(observers_[type.value], source)) {
+ FOR_EACH_OBSERVER(NotificationObserver,
+ *observers_[type.value][source.map_key()],
+ Observe(type, source, details));
+ }
+}
+
+
+NotificationService::~NotificationService() {
+ lazy_tls_ptr.Pointer()->Set(NULL);
+
+#ifndef NDEBUG
+ for (int i = 0; i < NotificationType::NOTIFICATION_TYPE_COUNT; i++) {
+ if (observer_counts_[i] > 0) {
+ // This may not be completely fixable -- see
+ // http://code.google.com/p/chromium/issues/detail?id=11010 .
+ // But any new leaks should be fixed.
+ LOG(INFO) << observer_counts_[i] << " notification observer(s) leaked"
+ << " of notification type " << i;
+ }
+ }
+#endif
+
+ for (int i = 0; i < NotificationType::NOTIFICATION_TYPE_COUNT; i++) {
+ NotificationSourceMap omap = observers_[i];
+ for (NotificationSourceMap::iterator it = omap.begin();
+ it != omap.end(); ++it) {
+ delete it->second;
+ }
+ }
+}
+
+NotificationObserver::NotificationObserver() {}
+
+NotificationObserver::~NotificationObserver() {}
diff --git a/chrome/common/notification_service.h b/chrome/common/notification_service.h
new file mode 100644
index 0000000..fefc09c
--- /dev/null
+++ b/chrome/common/notification_service.h
@@ -0,0 +1,108 @@
+// Copyright (c) 2006-2008 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.
+
+// This file describes a central switchboard for notifications that might
+// happen in various parts of the application, and allows users to register
+// observers for various classes of events that they're interested in.
+
+#ifndef CHROME_COMMON_NOTIFICATION_SERVICE_H_
+#define CHROME_COMMON_NOTIFICATION_SERVICE_H_
+
+#include <map>
+
+#include "base/observer_list.h"
+#include "chrome/common/notification_details.h"
+#include "chrome/common/notification_observer.h"
+#include "chrome/common/notification_source.h"
+#include "chrome/common/notification_type.h"
+
+class NotificationObserver;
+
+class NotificationService {
+ public:
+ // Returns the NotificationService object for the current thread, or NULL if
+ // none.
+ static NotificationService* current();
+
+ // Normally instantiated when the thread is created. Not all threads have
+ // a NotificationService. Only one instance should be created per thread.
+ NotificationService();
+ ~NotificationService();
+
+ // Synchronously posts a notification to all interested observers.
+ // Source is a reference to a NotificationSource object representing
+ // the object originating the notification (can be
+ // NotificationService::AllSources(), in which case
+ // only observers interested in all sources will be notified).
+ // Details is a reference to an object containing additional data about
+ // the notification. If no additional data is needed, NoDetails() is used.
+ // There is no particular order in which the observers will be notified.
+ void Notify(NotificationType type,
+ const NotificationSource& source,
+ const NotificationDetails& details);
+
+ // Returns a NotificationSource that represents all notification sources
+ // (for the purpose of registering an observer for events from all sources).
+ static Source<void> AllSources() { return Source<void>(NULL); }
+
+ // Returns a NotificationDetails object that represents a lack of details
+ // associated with a notification. (This is effectively a null pointer.)
+ static Details<void> NoDetails() { return Details<void>(NULL); }
+
+ private:
+ friend class NotificationRegistrar;
+
+ typedef ObserverList<NotificationObserver> NotificationObserverList;
+ typedef std::map<uintptr_t, NotificationObserverList*> NotificationSourceMap;
+
+ // Convenience function to determine whether a source has a
+ // NotificationObserverList in the given map;
+ static bool HasKey(const NotificationSourceMap& map,
+ const NotificationSource& source);
+
+ // NOTE: Rather than using this directly, you should use a
+ // NotificationRegistrar.
+ //
+ // Registers a NotificationObserver to be called whenever a matching
+ // notification is posted. Observer is a pointer to an object subclassing
+ // NotificationObserver to be notified when an event matching the other two
+ // parameters is posted to this service. Type is the type of events to
+ // be notified about (or NOTIFY_ALL to receive events of all types).
+ // Source is a NotificationSource object (created using
+ // "Source<classname>(pointer)"), if this observer only wants to
+ // receive events from that object, or NotificationService::AllSources()
+ // to receive events from all sources.
+ //
+ // A given observer can be registered only once for each combination of
+ // type and source. If the same object is registered more than once,
+ // it must be removed for each of those combinations of type and source later.
+ //
+ // The caller retains ownership of the object pointed to by observer.
+ void AddObserver(NotificationObserver* observer,
+ NotificationType type, const NotificationSource& source);
+
+ // NOTE: Rather than using this directly, you should use a
+ // NotificationRegistrar.
+ //
+ // Removes the object pointed to by observer from receiving notifications
+ // that match type and source. If no object matching the parameters is
+ // currently registered, this method is a no-op.
+ void RemoveObserver(NotificationObserver* observer,
+ NotificationType type, const NotificationSource& source);
+
+ // Keeps track of the observers for each type of notification.
+ // Until we get a prohibitively large number of notification types,
+ // a simple array is probably the fastest way to dispatch.
+ NotificationSourceMap observers_[NotificationType::NOTIFICATION_TYPE_COUNT];
+
+#ifndef NDEBUG
+ // Used to check to see that AddObserver and RemoveObserver calls are
+ // balanced.
+ int observer_counts_[NotificationType::NOTIFICATION_TYPE_COUNT];
+#endif
+
+ DISALLOW_COPY_AND_ASSIGN(NotificationService);
+};
+
+#endif // CHROME_COMMON_NOTIFICATION_SERVICE_H_
diff --git a/chrome/common/notification_service_unittest.cc b/chrome/common/notification_service_unittest.cc
new file mode 100644
index 0000000..d65f6e5
--- /dev/null
+++ b/chrome/common/notification_service_unittest.cc
@@ -0,0 +1,163 @@
+// Copyright (c) 2006-2008 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/common/notification_registrar.h"
+#include "chrome/common/notification_service.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+namespace {
+
+// Bogus class to act as a NotificationSource for the messages.
+class TestSource {};
+
+class TestObserver : public NotificationObserver {
+public:
+ TestObserver() : notification_count_(0) {}
+
+ int notification_count() { return notification_count_; }
+
+ void Observe(NotificationType type,
+ const NotificationSource& source,
+ const NotificationDetails& details) {
+ ++notification_count_;
+ }
+
+private:
+ int notification_count_;
+};
+
+} // namespace
+
+
+class NotificationServiceTest : public testing::Test {
+ protected:
+ NotificationRegistrar registrar_;
+};
+
+TEST_F(NotificationServiceTest, Basic) {
+ TestSource test_source;
+ TestSource other_source;
+
+ // Check the equality operators defined for NotificationSource
+ EXPECT_TRUE(
+ Source<TestSource>(&test_source) == Source<TestSource>(&test_source));
+ EXPECT_TRUE(
+ Source<TestSource>(&test_source) != Source<TestSource>(&other_source));
+
+ TestObserver all_types_all_sources;
+ TestObserver idle_all_sources;
+ TestObserver all_types_test_source;
+ TestObserver idle_test_source;
+
+ // Make sure it doesn't freak out when there are no observers.
+ NotificationService* service = NotificationService::current();
+ service->Notify(NotificationType::IDLE,
+ Source<TestSource>(&test_source),
+ NotificationService::NoDetails());
+
+ registrar_.Add(&all_types_all_sources, NotificationType::ALL,
+ NotificationService::AllSources());
+ registrar_.Add(&idle_all_sources, NotificationType::IDLE,
+ NotificationService::AllSources());
+ registrar_.Add(&all_types_test_source, NotificationType::ALL,
+ Source<TestSource>(&test_source));
+ registrar_.Add(&idle_test_source, NotificationType::IDLE,
+ Source<TestSource>(&test_source));
+
+ EXPECT_EQ(0, all_types_all_sources.notification_count());
+ EXPECT_EQ(0, idle_all_sources.notification_count());
+ EXPECT_EQ(0, all_types_test_source.notification_count());
+ EXPECT_EQ(0, idle_test_source.notification_count());
+
+ service->Notify(NotificationType::IDLE,
+ Source<TestSource>(&test_source),
+ NotificationService::NoDetails());
+
+ EXPECT_EQ(1, all_types_all_sources.notification_count());
+ EXPECT_EQ(1, idle_all_sources.notification_count());
+ EXPECT_EQ(1, all_types_test_source.notification_count());
+ EXPECT_EQ(1, idle_test_source.notification_count());
+
+ service->Notify(NotificationType::BUSY,
+ Source<TestSource>(&test_source),
+ NotificationService::NoDetails());
+
+ EXPECT_EQ(2, all_types_all_sources.notification_count());
+ EXPECT_EQ(1, idle_all_sources.notification_count());
+ EXPECT_EQ(2, all_types_test_source.notification_count());
+ EXPECT_EQ(1, idle_test_source.notification_count());
+
+ service->Notify(NotificationType::IDLE,
+ Source<TestSource>(&other_source),
+ NotificationService::NoDetails());
+
+ EXPECT_EQ(3, all_types_all_sources.notification_count());
+ EXPECT_EQ(2, idle_all_sources.notification_count());
+ EXPECT_EQ(2, all_types_test_source.notification_count());
+ EXPECT_EQ(1, idle_test_source.notification_count());
+
+ service->Notify(NotificationType::BUSY,
+ Source<TestSource>(&other_source),
+ NotificationService::NoDetails());
+
+ EXPECT_EQ(4, all_types_all_sources.notification_count());
+ EXPECT_EQ(2, idle_all_sources.notification_count());
+ EXPECT_EQ(2, all_types_test_source.notification_count());
+ EXPECT_EQ(1, idle_test_source.notification_count());
+
+ // Try send with NULL source.
+ service->Notify(NotificationType::IDLE,
+ NotificationService::AllSources(),
+ NotificationService::NoDetails());
+
+ EXPECT_EQ(5, all_types_all_sources.notification_count());
+ EXPECT_EQ(3, idle_all_sources.notification_count());
+ EXPECT_EQ(2, all_types_test_source.notification_count());
+ EXPECT_EQ(1, idle_test_source.notification_count());
+
+ registrar_.RemoveAll();
+
+ service->Notify(NotificationType::IDLE,
+ Source<TestSource>(&test_source),
+ NotificationService::NoDetails());
+
+ EXPECT_EQ(5, all_types_all_sources.notification_count());
+ EXPECT_EQ(3, idle_all_sources.notification_count());
+ EXPECT_EQ(2, all_types_test_source.notification_count());
+ EXPECT_EQ(1, idle_test_source.notification_count());
+}
+
+TEST_F(NotificationServiceTest, MultipleRegistration) {
+ TestSource test_source;
+
+ TestObserver idle_test_source;
+
+ NotificationService* service = NotificationService::current();
+
+ registrar_.Add(&idle_test_source, NotificationType::IDLE,
+ Source<TestSource>(&test_source));
+ registrar_.Add(&idle_test_source, NotificationType::ALL,
+ Source<TestSource>(&test_source));
+
+ service->Notify(NotificationType::IDLE,
+ Source<TestSource>(&test_source),
+ NotificationService::NoDetails());
+ EXPECT_EQ(2, idle_test_source.notification_count());
+
+ registrar_.Remove(&idle_test_source, NotificationType::IDLE,
+ Source<TestSource>(&test_source));
+
+ service->Notify(NotificationType::IDLE,
+ Source<TestSource>(&test_source),
+ NotificationService::NoDetails());
+ EXPECT_EQ(3, idle_test_source.notification_count());
+
+ registrar_.Remove(&idle_test_source, NotificationType::ALL,
+ Source<TestSource>(&test_source));
+
+ service->Notify(NotificationType::IDLE,
+ Source<TestSource>(&test_source),
+ NotificationService::NoDetails());
+ EXPECT_EQ(3, idle_test_source.notification_count());
+}
diff --git a/chrome/common/notification_source.cc b/chrome/common/notification_source.cc
new file mode 100644
index 0000000..e0f5ca0
--- /dev/null
+++ b/chrome/common/notification_source.cc
@@ -0,0 +1,17 @@
+// Copyright (c) 2010 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/common/notification_source.h"
+
+NotificationSource::NotificationSource(const NotificationSource& other)
+ : ptr_(other.ptr_) {
+}
+
+NotificationSource::NotificationSource(const void* ptr) : ptr_(ptr) {
+}
+
+NotificationSource::~NotificationSource() {
+}
+
+
diff --git a/chrome/common/notification_source.h b/chrome/common/notification_source.h
new file mode 100644
index 0000000..1813c2e
--- /dev/null
+++ b/chrome/common/notification_source.h
@@ -0,0 +1,54 @@
+// Copyright (c) 2006-2008 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.
+
+// This file defines the type used to provide sources for NotificationService
+// notifications.
+
+#ifndef CHROME_COMMON_NOTIFICATION_SOURCE_H__
+#define CHROME_COMMON_NOTIFICATION_SOURCE_H__
+
+#include "base/basictypes.h"
+
+// Do not declare a NotificationSource directly--use either
+// "Source<sourceclassname>(sourceclasspointer)" or
+// NotificationService::AllSources().
+class NotificationSource {
+ public:
+ NotificationSource(const NotificationSource& other);
+ ~NotificationSource();
+
+ // NotificationSource can be used as the index for a map; this method
+ // returns the pointer to the current source as an identifier, for use as a
+ // map index.
+ uintptr_t map_key() const { return reinterpret_cast<uintptr_t>(ptr_); }
+
+ bool operator!=(const NotificationSource& other) const {
+ return ptr_ != other.ptr_;
+ }
+ bool operator==(const NotificationSource& other) const {
+ return ptr_ == other.ptr_;
+ }
+
+ protected:
+ explicit NotificationSource(const void* ptr);
+
+ // Declaring this const allows Source<T> to be used with both T = Foo and
+ // T = const Foo.
+ const void* ptr_;
+};
+
+template <class T>
+class Source : public NotificationSource {
+ public:
+ // TODO(erg): Our code hard relies on implicit conversion
+ Source(T* ptr) : NotificationSource(ptr) {} // NOLINT
+ Source(const NotificationSource& other) // NOLINT
+ : NotificationSource(other) {}
+
+ T* operator->() const { return ptr(); }
+ // The casts here allow this to compile with both T = Foo and T = const Foo.
+ T* ptr() const { return static_cast<T*>(const_cast<void*>(ptr_)); }
+};
+
+#endif // CHROME_COMMON_NOTIFICATION_SOURCE_H__
diff --git a/chrome/common/notification_type.h b/chrome/common/notification_type.h
new file mode 100644
index 0000000..9f75bb4
--- /dev/null
+++ b/chrome/common/notification_type.h
@@ -0,0 +1,1114 @@
+// Copyright (c) 2010 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_COMMON_NOTIFICATION_TYPE_H_
+#define CHROME_COMMON_NOTIFICATION_TYPE_H_
+
+// This file describes various types used to describe and filter notifications
+// that pass through the NotificationService.
+//
+// It is written as an enum inside a class so that it can be forward declared.
+// You're not allowed to forward declare an enum, and we want to forward
+// declare this since it's required by NotificationObserver which is included
+// by a lot of header files.
+//
+// Since this class encapsulates an integral value, it should be passed by
+// value.
+class NotificationType {
+ public:
+ enum Type {
+ // General -----------------------------------------------------------------
+
+ // Special signal value to represent an interest in all notifications.
+ // Not valid when posting a notification.
+ ALL = 0,
+
+ // The app is done processing user actions, now is a good time to do
+ // some background work.
+ IDLE,
+
+ // Means that the app has just started doing something in response to a
+ // user action, and that background processes shouldn't run if avoidable.
+ BUSY,
+
+ // This is sent when the user does a gesture resulting in a noteworthy
+ // action taking place. This is typically used for logging. The source is
+ // the profile, and the details is a wstring identifying the action.
+ USER_ACTION,
+
+ // NavigationController ----------------------------------------------------
+
+ // A new pending navigation has been created. Pending entries are created
+ // when the user requests the navigation. We don't know if it will actually
+ // happen until it does (at this point, it will be "committed." Note that
+ // renderer- initiated navigations such as link clicks will never be
+ // pending.
+ //
+ // This notification is called after the pending entry is created, but
+ // before we actually try to navigate. The source will be the
+ // NavigationController that owns the pending entry, and there are no
+ // details.
+ NAV_ENTRY_PENDING,
+
+ // A new non-pending navigation entry has been created. This will
+ // correspond to one NavigationController entry being created (in the case
+ // of new navigations) or renavigated to (for back/forward navigations).
+ //
+ // The source will be the navigation controller doing the commit. The
+ // details will be NavigationController::LoadCommittedDetails.
+ NAV_ENTRY_COMMITTED,
+
+ // Indicates that the NavigationController given in the Source has
+ // decreased its back/forward list count by removing entries from either
+ // the front or back of its list. This is usually the result of going back
+ // and then doing a new navigation, meaning all the "forward" items are
+ // deleted.
+ //
+ // This normally happens as a result of a new navigation. It will be
+ // followed by a NAV_ENTRY_COMMITTED message for the new page that
+ // caused the pruning. It could also be a result of removing an item from
+ // the list to fix up after interstitials.
+ //
+ // The details are NavigationController::PrunedDetails.
+ NAV_LIST_PRUNED,
+
+ // Indicates that a NavigationEntry has changed. The source will be the
+ // NavigationController that owns the NavigationEntry. The details will be
+ // a NavigationController::EntryChangedDetails struct.
+ //
+ // This will NOT be sent on navigation, interested parties should also
+ // listen for NAV_ENTRY_COMMITTED to handle that case. This will be
+ // sent when the entry is updated outside of navigation (like when a new
+ // title comes).
+ NAV_ENTRY_CHANGED,
+
+ // Other load-related (not from NavigationController) ----------------------
+
+ // A content load is starting. The source will be a
+ // Source<NavigationController> corresponding to the tab in which the load
+ // is occurring. No details are expected for this notification.
+ LOAD_START,
+
+ // A content load has stopped. The source will be a
+ // Source<NavigationController> corresponding to the tab in which the load
+ // is occurring. Details in the form of a LoadNotificationDetails object
+ // are optional.
+ LOAD_STOP,
+
+ // A frame is staring a provisional load. The source is a
+ // Source<NavigationController> corresponding to the tab in which the load
+ // occurs. Details is a bool specifying if the load occurs in the main
+ // frame (or a sub-frame if false).
+ FRAME_PROVISIONAL_LOAD_START,
+
+ // Content was loaded from an in-memory cache. The source will be a
+ // Source<NavigationController> corresponding to the tab in which the load
+ // occurred. Details in the form of a LoadFromMemoryCacheDetails object
+ // are provided.
+ LOAD_FROM_MEMORY_CACHE,
+
+ // A provisional content load has failed with an error. The source will be
+ // a Source<NavigationController> corresponding to the tab in which the
+ // load occurred. Details in the form of a ProvisionalLoadDetails object
+ // are provided.
+ FAIL_PROVISIONAL_LOAD_WITH_ERROR,
+
+ // A response has been received for a resource request. The source will be
+ // a Source<NavigationController> corresponding to the tab in which the
+ // request was issued. Details in the form of a ResourceRequestDetails
+ // object are provided.
+ RESOURCE_RESPONSE_STARTED,
+
+ // A redirect was received while requesting a resource. The source will be
+ // a Source<NavigationController> corresponding to the tab in which the
+ // request was issued. Details in the form of a ResourceRedirectDetails
+ // are provided.
+ RESOURCE_RECEIVED_REDIRECT,
+
+ // SSL ---------------------------------------------------------------------
+
+ // Updating the SSL security indicators (the lock icon and such) proceeds
+ // in two phases:
+ //
+ // 1) The internal SSL state for a host or tab changes. When this happens,
+ // the SSLManager broadcasts an SSL_INTERNAL_STATE_CHANGED notification.
+ //
+ // 2) The SSLManager for each tab receives this notification and might or
+ // might not update the navigation entry for its tab, depending on
+ // whether the change in state affects that tab. If the SSLManager does
+ // change the navigation entry, then the SSLManager broadcasts an
+ // SSL_VISIBLE_STATE_CHANGED notification to the user interface can
+ // redraw properly.
+
+ // The SSL state of a page has changed in some visible way. For example,
+ // if an insecure resource is loaded on a secure page. Note that a
+ // toplevel load commit will also update the SSL state (since the
+ // NavigationEntry is new) and this message won't always be sent in that
+ // case. Listen to this notification if you need to refresh SSL-related UI
+ // elements.
+ //
+ // There is no source or details.
+ SSL_VISIBLE_STATE_CHANGED,
+
+ // The SSL state of the browser has changed in some internal way. For
+ // example, the user might have explicitly allowed some broken certificate
+ // or a secure origin might have included some insecure content. Listen to
+ // this notifiation if you need to keep track of our internal SSL state.
+ //
+ // The source will be the navigation controller associated with the state
+ // change. There are no details.
+ SSL_INTERNAL_STATE_CHANGED,
+
+ // Lets resource handlers and other interested observers know when the
+ // message filter is being deleted and can no longer be used. This will
+ // also get sent if the renderer crashes (and in that case, it'll be sent
+ // twice).
+ RESOURCE_MESSAGE_FILTER_SHUTDOWN,
+
+ // Lets interested observers know when a WorkerProcessHost is being deleted
+ // and can no longer be used.
+ WORKER_PROCESS_HOST_SHUTDOWN,
+
+ // Views -------------------------------------------------------------------
+
+ // Notification that a view was removed from a view hierarchy. The source
+ // is the view, the details is the parent view.
+ VIEW_REMOVED,
+
+ // Browser-window ----------------------------------------------------------
+
+ // This message is sent after a window has been opened. The source is a
+ // Source<Browser> containing the affected Browser. No details are
+ // expected.
+ BROWSER_OPENED,
+
+ // This message is sent soon after BROWSER_OPENED, and indicates that
+ // the Browser's |window_| is now non-NULL. The source is a Source<Browser>
+ // containing the affected Browser. No details are expected.
+ BROWSER_WINDOW_READY,
+
+ // This message is sent when a browser is closing. The source is a
+ // Source<Browser> containing the affected Browser. Details is a boolean
+ // that if true indicates that the application will be closed as a result of
+ // this browser window closure (i.e. this was the last opened browser
+ // window on win/linux). This is sent prior to BROWSER_CLOSED, and may be
+ // sent more than once for a particular browser.
+ BROWSER_CLOSING,
+
+ // This message is sent after a window has been closed. The source is a
+ // Source<Browser> containing the affected Browser. Details is a boolean
+ // that if true indicates that the last browser window has closed - this
+ // does not indicate that the application is exiting (observers should
+ // listen for APP_TERMINATING if they want to detect when the application
+ // will shut down). Note that the boolean pointed to by details is only
+ // valid for the duration of this call.
+ BROWSER_CLOSED,
+
+ // This message is sent when the last window considered to be an
+ // "application window" has been closed. Dependent/dialog/utility windows
+ // can use this as a way to know that they should also close. No source or
+ // details are passed.
+ ALL_APPWINDOWS_CLOSED,
+
+#if defined(OS_MACOSX)
+ // This message is sent when the application is made active (Mac OS X only
+ // at present). No source or details are passed.
+ APP_ACTIVATED,
+#endif
+
+ // This message is sent when the application is terminating (the last
+ // browser window has shutdown as part of an explicit user-initiated exit,
+ // or the user closed the last browser window on Windows/Linux and there are
+ // no BackgroundContents keeping the browser running). No source or details
+ // are passed.
+ APP_TERMINATING,
+
+#if defined(OS_MACOSX)
+ // This notification is sent when the app has no key window, such as when
+ // all windows are closed but the app is still active. No source or details
+ // are provided.
+ NO_KEY_WINDOW,
+#endif
+
+ // This is sent when the user has chosen to exit the app, but before any
+ // browsers have closed. This is only sent if the user chooses the exit menu
+ // item, not if Chrome exists by some other means (such as the user closing
+ // the last window). The source and details are unspecified.
+ APP_EXITING,
+
+ // Indicates that a top window has been closed. The source is the HWND
+ // that was closed, no details are expected.
+ WINDOW_CLOSED,
+
+ // Indicates that a devtools window is closing. The source is the Profile*
+ // and the details is the inspected RenderViewHost*.
+ DEVTOOLS_WINDOW_CLOSING,
+
+ // Sent when an info bubble has been created but not yet shown. The source
+ // is the InfoBubble.
+ INFO_BUBBLE_CREATED,
+
+ // Sent when the language (English, French...) for a page has been detected.
+ // The details Details<std::string> contain the ISO 639-1 language code and
+ // the source is Source<TabContents>.
+ TAB_LANGUAGE_DETERMINED,
+
+ // Sent when a page has been translated. The source is the tab for that page
+ // (Source<TabContents>) and the details are the language the page was
+ // originally in and the language it was translated to
+ // (std::pair<std::string, std::string>).
+ PAGE_TRANSLATED,
+
+ // Sent after the renderer returns a snapshot of tab contents.
+ // The source (Source<RenderViewHost>) is the RenderViewHost for which the
+ // snapshot was generated and the details (Details<const SkBitmap>) is the
+ // actual snapshot.
+ TAB_SNAPSHOT_TAKEN,
+
+ // Send after the code is run in specified tab.
+ TAB_CODE_EXECUTED,
+
+ // The user has changed the browser theme.
+ BROWSER_THEME_CHANGED,
+
+ // Sent when the renderer returns focus to the browser, as part of focus
+ // traversal. The source is the browser, there are no details.
+ FOCUS_RETURNED_TO_BROWSER,
+
+ // Application-modal dialogs -----------------------------------------------
+
+ // Sent after an application-modal dialog has been shown. The source
+ // is the dialog.
+ APP_MODAL_DIALOG_SHOWN,
+
+ // Sent after an application-modal dialog has been closed. The source
+ // is the dialog.
+ APP_MODAL_DIALOG_CLOSED,
+
+ // Tabs --------------------------------------------------------------------
+
+ // Sent when a tab is added to a TabContentsDelegate. The source is the
+ // TabContentsDelegate and the details is the TabContents.
+ TAB_ADDED,
+
+ // This notification is sent after a tab has been appended to the
+ // tab_strip. The source is a Source<NavigationController> with a pointer
+ // to controller for the added tab. There are no details.
+ TAB_PARENTED,
+
+ // This message is sent before a tab has been closed. The source is a
+ // Source<NavigationController> with a pointer to the controller for the
+ // closed tab. No details are expected.
+ //
+ // See also TAB_CLOSED.
+ TAB_CLOSING,
+
+ // Notification that a tab has been closed. The source is the
+ // NavigationController with no details.
+ TAB_CLOSED,
+
+ // This notification is sent when a render view host has connected to a
+ // renderer process. The source is a Source<TabContents> with a pointer to
+ // the TabContents. A TAB_CONTENTS_DISCONNECTED notification is
+ // guaranteed before the source pointer becomes junk. No details are
+ // expected.
+ TAB_CONTENTS_CONNECTED,
+
+ // This notification is sent when a TabContents swaps its render view host
+ // with another one, possibly changing processes. The source is a
+ // Source<TabContents> with a pointer to the TabContents. A
+ // TAB_CONTENTS_DISCONNECTED notification is guaranteed before the
+ // source pointer becomes junk. No details are expected.
+ TAB_CONTENTS_SWAPPED,
+
+ // This message is sent after a TabContents is disconnected from the
+ // renderer process. The source is a Source<TabContents> with a pointer to
+ // the TabContents (the pointer is usable). No details are expected.
+ TAB_CONTENTS_DISCONNECTED,
+
+ // This notification is sent after TabContents' title is updated. The source
+ // is a Source<TabContents> with a pointer to the TabContents. No details
+ // are expected.
+ TAB_CONTENTS_TITLE_UPDATED,
+
+ // This message is sent when a new InfoBar has been added to a TabContents.
+ // The source is a Source<TabContents> with a pointer to the TabContents
+ // the InfoBar was added to. The details is a Details<InfoBarDelegate> with
+ // a pointer to an object implementing the InfoBarDelegate interface for
+ // the InfoBar that was added.
+ TAB_CONTENTS_INFOBAR_ADDED,
+
+ // This message is sent when an InfoBar is about to be removed from a
+ // TabContents. The source is a Source<TabContents> with a pointer to the
+ // TabContents the InfoBar was removed from. The details is a
+ // Details<InfoBarDelegate> with a pointer to an object implementing the
+ // InfoBarDelegate interface for the InfoBar that was removed.
+ TAB_CONTENTS_INFOBAR_REMOVED,
+
+ // This message is sent when an InfoBar is replacing another infobar in a
+ // TabContents. The source is a Source<TabContents> with a pointer to the
+ // TabContents the InfoBar was removed from. The details is a
+ // Details<std::pair<InfoBarDelegate*, InfoBarDelegate*> > with a pointer
+ // to the old and new InfoBarDelegates, respectively.
+ TAB_CONTENTS_INFOBAR_REPLACED,
+
+ // This is sent when an externally hosted tab is created. The details
+ // contain the ExternalTabContainer that contains the tab
+ EXTERNAL_TAB_CREATED,
+
+ // This is sent when an externally hosted tab is closed. No details are
+ // expected.
+ EXTERNAL_TAB_CLOSED,
+
+ // Indicates that the new page tab has finished loading. This is used for
+ // performance testing to see how fast we can load it after startup, and is
+ // only called once for the lifetime of the browser. The source is unused.
+ // Details is an integer: the number of milliseconds elapsed between
+ // starting and finishing all painting.
+ INITIAL_NEW_TAB_UI_LOAD,
+
+ // Used to fire notifications about how long various events took to
+ // complete. E.g., this is used to get more fine grained timings from the
+ // new tab page. Details is a MetricEventDurationDetails.
+ METRIC_EVENT_DURATION,
+
+ // This notification is sent when a TabContents is being hidden, e.g. due
+ // to switching away from this tab. The source is a Source<TabContents>.
+ TAB_CONTENTS_HIDDEN,
+
+ // This notification is sent when a TabContents is being destroyed. Any
+ // object holding a reference to a TabContents can listen to that
+ // notification to properly reset the reference. The source is a
+ // Source<TabContents>.
+ TAB_CONTENTS_DESTROYED,
+
+ // This notification is sent when TabContents::SetAppExtension is invoked.
+ // The source is the TabContents SetAppExtension was invoked on.
+ TAB_CONTENTS_APPLICATION_EXTENSION_CHANGED,
+
+ // A RenderViewHost was created for a TabContents. The source is the
+ // associated TabContents, and the details is the RenderViewHost
+ // pointer.
+ RENDER_VIEW_HOST_CREATED_FOR_TAB,
+
+ // Stuff inside the tabs ---------------------------------------------------
+
+ // This message is sent after a constrained window has been closed. The
+ // source is a Source<ConstrainedWindow> with a pointer to the closed child
+ // window. (The pointer isn't usable, except for identification.) No
+ // details are expected.
+ CWINDOW_CLOSED,
+
+ // Indicates that a RenderProcessHost was created and its handle is now
+ // available. The source will be the RenderProcessHost that corresponds to
+ // the process.
+ RENDERER_PROCESS_CREATED,
+
+ // Indicates that a RenderProcessHost is destructing. The source will be the
+ // RenderProcessHost that corresponds to the process.
+ RENDERER_PROCESS_TERMINATED,
+
+ // Indicates that a render process was closed (meaning it exited, but the
+ // RenderProcessHost might be reused). The source will be the corresponding
+ // RenderProcessHost. The details will be a RendererClosedDetails struct.
+ // This may get sent along with RENDERER_PROCESS_TERMINATED.
+ RENDERER_PROCESS_CLOSED,
+
+ // Indicates that a render process has become unresponsive for a period of
+ // time. The source will be the RenderWidgetHost that corresponds to the
+ // hung view, and no details are expected.
+ RENDERER_PROCESS_HANG,
+
+ // This is sent to notify that the RenderViewHost displayed in a
+ // TabContents has changed. Source is the TabContents for which the change
+ // happened, details is the previous RenderViewHost (can be NULL when the
+ // first RenderViewHost is set).
+ RENDER_VIEW_HOST_CHANGED,
+
+ // Indicates that the render view host has received a new accessibility tree
+ // from the render view. The source is the RenderViewHost, the details
+ // are not used.
+ RENDER_VIEW_HOST_ACCESSIBILITY_TREE_UPDATED,
+
+ // This is sent when a RenderWidgetHost is being destroyed. The source is
+ // the RenderWidgetHost, the details are not used.
+ RENDER_WIDGET_HOST_DESTROYED,
+
+ // Sent from ~RenderViewHost. The source is the TabContents.
+ RENDER_VIEW_HOST_DELETED,
+
+ // Sent from RenderViewHost::ClosePage. The hosted RenderView has
+ // processed the onbeforeunload handler and is about to be sent a
+ // ViewMsg_ClosePage message to complete the tear-down process. The source
+ // is the RenderViewHost sending the message, and no details are provided.
+ // Note: This message is not sent in response to RenderView closure
+ // initiated by window.close().
+ RENDER_VIEW_HOST_WILL_CLOSE_RENDER_VIEW,
+
+ // Indicates a RenderWidgetHost has been hidden or restored. The source is
+ // the RWH whose visibility changed, the details is a bool set to true if
+ // the new state is "visible."
+ RENDER_WIDGET_VISIBILITY_CHANGED,
+
+ // Notification from TabContents that we have received a response from the
+ // renderer in response to a dom automation controller action.
+ DOM_OPERATION_RESPONSE,
+
+ // Sent when the bookmark bubble hides. The source is the profile, the
+ // details unused.
+ BOOKMARK_BUBBLE_HIDDEN,
+
+ // This notification is sent when the result of a find-in-page search is
+ // available with the browser process. The source is a Source<TabContents>
+ // with a pointer to the TabContents. Details encompass a
+ // FindNotificationDetail object that tells whether the match was found or
+ // not found.
+ FIND_RESULT_AVAILABLE,
+
+ // This is sent when the users preference for when the bookmark bar should
+ // be shown changes. The source is the profile, and the details are
+ // NoDetails.
+ BOOKMARK_BAR_VISIBILITY_PREF_CHANGED,
+
+ // This is sent when the user's preference (for when the extension shelf
+ // should be shown) changes. The source is the profile, and the details are
+ // NoDetails.
+ EXTENSION_SHELF_VISIBILITY_PREF_CHANGED,
+
+ // Sent just before the installation confirm dialog is shown. The source
+ // is the ExtensionInstallUI, the details are NoDetails.
+ EXTENSION_WILL_SHOW_CONFIRM_DIALOG,
+
+ // Used to monitor web cache usage by notifying whenever the
+ // CacheManagerHost observes new UsageStats. The source will be the
+ // RenderProcessHost that corresponds to the new statistics. Details are a
+ // UsageStats object sent by the renderer, and should be copied - ptr not
+ // guaranteed to be valid after the notification.
+ WEB_CACHE_STATS_OBSERVED,
+
+ // The focused element inside a page has changed. The source is the render
+ // view host for the page, there are no details.
+ FOCUS_CHANGED_IN_PAGE,
+
+ // BackgroundContents ------------------------------------------------------
+
+ // A new background contents was opened by script. The source is the parent
+ // profile and the details are BackgroundContentsOpenedDetails.
+ BACKGROUND_CONTENTS_OPENED,
+
+ // The background contents navigated to a new location. The source is the
+ // parent Profile, and the details are the BackgroundContents that was
+ // navigated.
+ BACKGROUND_CONTENTS_NAVIGATED,
+
+ // The background contents were closed by someone invoking window.close()
+ // or the parent application was uninstalled.
+ // The source is the parent profile, and the details are the
+ // BackgroundContents.
+ BACKGROUND_CONTENTS_CLOSED,
+
+ // The background contents is being deleted. The source is the
+ // parent Profile, and the details are the BackgroundContents being deleted.
+ BACKGROUND_CONTENTS_DELETED,
+
+ // Child Processes ---------------------------------------------------------
+
+ // This notification is sent when a child process host has connected to a
+ // child process. There is no usable source, since it is sent from an
+ // ephemeral task; register for AllSources() to receive this notification.
+ // The details are in a Details<ChildProcessInfo>.
+ CHILD_PROCESS_HOST_CONNECTED,
+
+ // This message is sent after a ChildProcessHost is disconnected from the
+ // child process. There is no usable source, since it is sent from an
+ // ephemeral task; register for AllSources() to receive this notification.
+ // The details are in a Details<ChildProcessInfo>.
+ CHILD_PROCESS_HOST_DISCONNECTED,
+
+ // This message is sent when a child process disappears unexpectedly.
+ // There is no usable source, since it is sent from an ephemeral task;
+ // register for AllSources() to receive this notification. The details are
+ // in a Details<ChildProcessInfo>.
+ CHILD_PROCESS_CRASHED,
+
+ // This message indicates that an instance of a particular child was
+ // created in a page. (If one page contains several regions rendered by
+ // the same child, this notification will occur once for each region
+ // during the page load.)
+ //
+ // There is no usable source, since it is sent from an ephemeral task;
+ // register for AllSources() to receive this notification. The details are
+ // in a Details<ChildProcessInfo>.
+ CHILD_INSTANCE_CREATED,
+
+ // This is sent when network interception is disabled for a plugin, or the
+ // plugin is unloaded. This should only be sent/received on the browser IO
+ // thread or the plugin thread. The source is the plugin that is disabling
+ // interception. No details are expected.
+ CHROME_PLUGIN_UNLOADED,
+
+ // This is sent when a login prompt is shown. The source is the
+ // Source<NavigationController> for the tab in which the prompt is shown.
+ // Details are a LoginNotificationDetails which provide the LoginHandler
+ // that should be given authentication.
+ AUTH_NEEDED,
+
+ // This is sent when authentication credentials have been supplied (either
+ // by the user or by an automation service), but before we've actually
+ // received another response from the server. The source is the
+ // Source<NavigationController> for the tab in which the prompt was shown.
+ // Details are an AuthSuppliedLoginNotificationDetails which provide the
+ // LoginHandler that should be given authentication as well as the supplied
+ // username and password.
+ AUTH_SUPPLIED,
+
+ // This is sent when an authentication request has been dismissed without
+ // supplying credentials (either by the user or by an automation service).
+ // The source is the Source<NavigationController> for the tab in which the
+ // prompt was shown. Details are a LoginNotificationDetails which provide
+ // the LoginHandler that should be cancelled.
+ AUTH_CANCELLED,
+
+ // Saved Pages -------------------------------------------------------------
+
+ // Sent when a SavePackage finishes successfully. The source is the
+ // SavePackage, and Details are a GURL containing address of downloaded
+ // page.
+ SAVE_PACKAGE_SUCCESSFULLY_FINISHED,
+
+ // History -----------------------------------------------------------------
+
+ // Sent when a history service is created on the main thread. This is sent
+ // after history is created, but before it has finished loading. Use
+ // HISTORY_LOADED is you need to know when loading has completed.
+ // The source is the profile that the history service belongs to, and the
+ // details is the pointer to the newly created HistoryService object.
+ HISTORY_CREATED,
+
+ // Sent when a history service has finished loading. The source is the
+ // profile that the history service belongs to, and the details is the
+ // HistoryService.
+ HISTORY_LOADED,
+
+ // Sent when a URL that has been typed has been added or modified. This is
+ // used by the in-memory URL database (used by autocomplete) to track
+ // changes to the main history system.
+ //
+ // The source is the profile owning the history service that changed, and
+ // the details is history::URLsModifiedDetails that lists the modified or
+ // added URLs.
+ HISTORY_TYPED_URLS_MODIFIED,
+
+ // Sent when the user visits a URL.
+ //
+ // The source is the profile owning the history service that changed, and
+ // the details is history::URLVisitedDetails.
+ HISTORY_URL_VISITED,
+
+ // Sent when one or more URLs are deleted.
+ //
+ // The source is the profile owning the history service that changed, and
+ // the details is history::URLsDeletedDetails that lists the deleted URLs.
+ HISTORY_URLS_DELETED,
+
+ // Sent by history when the favicon of a URL changes. The source is the
+ // profile, and the details is history::FavIconChangeDetails (see
+ // history_notifications.h).
+ FAVICON_CHANGED,
+
+ // Sent by history if there is a problem reading the profile. The details
+ // is an int that's one of the message IDs in the string table. The active
+ // browser window should notify the user of this error.
+ PROFILE_ERROR,
+
+ // Sent before a Profile is destroyed. The details are
+ // none and the source is a Profile*.
+ PROFILE_DESTROYED,
+
+ // Thumbnails---------------------------------------------------------------
+
+ // Sent by the ThumbnailGenerator whenever a render widget host
+ // updates its backing store. The source is the
+ // ThumbnailGenerator, and the details are the RenderWidgetHost
+ // that notified the ThumbnailGenerator that its backing store was
+ // updated.
+ THUMBNAIL_GENERATOR_SNAPSHOT_CHANGED,
+
+ // Bookmarks ---------------------------------------------------------------
+
+ // Sent when the starred state of a URL changes. A URL is starred if there
+ // is at least one bookmark for it. The source is a Profile and the details
+ // is history::URLsStarredDetails that contains the list of URLs and
+ // whether they were starred or unstarred.
+ URLS_STARRED,
+
+ // Sent when the bookmark bar model finishes loading. This source is the
+ // Profile, and the details aren't used.
+ BOOKMARK_MODEL_LOADED,
+
+ // Sent when SpellCheckHost has been reloaded. The source is the profile,
+ // the details are NoDetails.
+ SPELLCHECK_HOST_REINITIALIZED,
+
+ // Sent when a new word has been added to the custom dictionary. The source
+ // is the SpellCheckHost, the details are NoDetails.
+ SPELLCHECK_WORD_ADDED,
+
+ // Sent by the profile when the automatic spell correction setting has been
+ // toggled. It exists as a notification rather than just letting interested
+ // parties listen for the pref change because some objects may outlive the
+ // profile. Source is profile, details is NoDetails.
+ SPELLCHECK_AUTOSPELL_TOGGLED,
+
+ // Sent when the bookmark bubble is shown for a particular URL. The source
+ // is the profile, the details the URL.
+ BOOKMARK_BUBBLE_SHOWN,
+
+ // Non-history storage services --------------------------------------------
+
+ // Notification that the TemplateURLModel has finished loading from the
+ // database. The source is the TemplateURLModel, and the details are
+ // NoDetails.
+ TEMPLATE_URL_MODEL_LOADED,
+
+ // Notification triggered when a web application has been installed or
+ // uninstalled. Any application view should reload its data. The source is
+ // the profile. No details are provided.
+ WEB_APP_INSTALL_CHANGED,
+
+ // This is sent to a pref observer when a pref is changed. The source is the
+ // PrefService and the details a std::wstring of the changed path.
+ PREF_CHANGED,
+
+ // Sent when a default request context has been created, so calling
+ // Profile::GetDefaultRequestContext() will not return NULL. This is sent
+ // on the thread where Profile::GetRequestContext() is first called, which
+ // should be the UI thread.
+ DEFAULT_REQUEST_CONTEXT_AVAILABLE,
+
+ // Autocomplete ------------------------------------------------------------
+
+ // Sent by the autocomplete controller at least once per query, each time
+ // new matches are available, subject to rate-limiting/coalescing to reduce
+ // the number of updates. The details hold the AutocompleteResult that
+ // observers should use if they want to see the updated matches.
+ AUTOCOMPLETE_CONTROLLER_RESULT_UPDATED,
+
+ // Sent by the autocomplete controller immediately after synchronous matches
+ // become available, and thereafter at the same time that
+ // AUTOCOMPLETE_CONTROLLER_RESULT_UPDATED is sent. The details hold the
+ // AutocompleteResult that observers should use if they want to see the
+ // up-to-date matches.
+ AUTOCOMPLETE_CONTROLLER_DEFAULT_MATCH_UPDATED,
+
+ // This is sent when an item of the Omnibox popup is selected. The source
+ // is the profile.
+ OMNIBOX_OPENED_URL,
+
+ // Sent by the autocomplete edit when it is destroyed.
+ AUTOCOMPLETE_EDIT_DESTROYED,
+
+ // Sent when the main Google URL has been updated. Some services cache
+ // this value and need to update themselves when it changes. See
+ // google_util::GetGoogleURLAndUpdateIfNecessary().
+ GOOGLE_URL_UPDATED,
+
+ // Printing ----------------------------------------------------------------
+
+ // Notification from PrintJob that an event occured. It can be that a page
+ // finished printing or that the print job failed. Details is
+ // PrintJob::EventDetails.
+ PRINT_JOB_EVENT,
+
+ // Shutdown ----------------------------------------------------------------
+
+ // Sent on the browser IO thread when an URLRequestContext is released by
+ // its owning Profile. The source is a pointer to the URLRequestContext.
+ URL_REQUEST_CONTEXT_RELEASED,
+
+ // Sent when WM_ENDSESSION has been received, after the browsers have been
+ // closed but before browser process has been shutdown. The source/details
+ // are all source and no details.
+ SESSION_END,
+
+ // Personalization ---------------------------------------------------------
+
+ PERSONALIZATION,
+ PERSONALIZATION_CREATED,
+
+ // User Scripts ------------------------------------------------------------
+
+ // Sent when there are new user scripts available. The details are a
+ // pointer to SharedMemory containing the new scripts.
+ USER_SCRIPTS_UPDATED,
+
+ // User Style Sheet --------------------------------------------------------
+
+ // Sent when the user style sheet has changed.
+ USER_STYLE_SHEET_UPDATED,
+
+ // Extensions --------------------------------------------------------------
+
+ // Sent when the known installed extensions have all been loaded. In
+ // testing scenarios this can happen multiple times if extensions are
+ // unloaded and reloaded. The source is a Profile.
+ EXTENSIONS_READY,
+
+ // Sent when a new extension is loaded. The details are an Extension, and
+ // the source is a Profile.
+ EXTENSION_LOADED,
+
+ // Sent when attempting to load a new extension, but they are disabled. The
+ // details are an Extension*, and the source is a Profile*.
+ EXTENSION_UPDATE_DISABLED,
+
+ // Sent when an extension is about to be installed so we can (in the case of
+ // themes) alert the user with a loading dialog. The source is the download
+ // manager and the details are the download url.
+ EXTENSION_READY_FOR_INSTALL,
+
+ // Sent when an extension install turns out to not be a theme.
+ NO_THEME_DETECTED,
+
+ // Sent when a new theme is installed. The details are an Extension, and the
+ // source is a Profile.
+ THEME_INSTALLED,
+
+ // Sent when new extensions are installed. The details are an Extension, and
+ // the source is a Profile.
+ EXTENSION_INSTALLED,
+
+ // An error occured during extension install. The details are a string with
+ // details about why the install failed.
+ EXTENSION_INSTALL_ERROR,
+
+ // Sent when an extension is unloaded. This happens when an extension is
+ // uninstalled or disabled. The details are an Extension, and the source is
+ // a Profile.
+ //
+ // Note that when this notification is sent, ExtensionsService has already
+ // removed the extension from its internal state.
+ EXTENSION_UNLOADED,
+
+ // Same as above, but for a disabled extension.
+ EXTENSION_UNLOADED_DISABLED,
+
+ // Sent when an extension has updated its user scripts. The details are an
+ // Extension, and the source is a Profile.
+ EXTENSION_USER_SCRIPTS_UPDATED,
+
+ // Sent after a new ExtensionFunctionDispatcher is created. The details are
+ // an ExtensionFunctionDispatcher* and the source is a Profile*. This is
+ // similar in timing to EXTENSION_HOST_CREATED, but also fires when an
+ // extension view which is hosted in TabContents* is created.
+ EXTENSION_FUNCTION_DISPATCHER_CREATED,
+
+ // Sent before an ExtensionHost is destroyed. The details are
+ // an ExtensionFunctionDispatcher* and the source is a Profile*. This is
+ // similar in timing to EXTENSION_HOST_DESTROYED, but also fires when an
+ // extension view which is hosted in TabContents* is destroyed.
+ EXTENSION_FUNCTION_DISPATCHER_DESTROYED,
+
+ // Sent after a new ExtensionHost is created. The details are
+ // an ExtensionHost* and the source is an ExtensionProcessManager*.
+ EXTENSION_HOST_CREATED,
+
+ // Sent before an ExtensionHost is destroyed. The details are
+ // an ExtensionHost* and the source is a Profile*.
+ EXTENSION_HOST_DESTROYED,
+
+ // Sent by an ExtensionHost when it finished its initial page load.
+ // The details are an ExtensionHost* and the source is a Profile*.
+ EXTENSION_HOST_DID_STOP_LOADING,
+
+ // Sent by an ExtensionHost when its render view requests closing through
+ // window.close(). The details are an ExtensionHost* and the source is a
+ // Profile*.
+ EXTENSION_HOST_VIEW_SHOULD_CLOSE,
+
+ // Sent after an extension render process is created and fully functional.
+ // The details are an ExtensionHost*.
+ EXTENSION_PROCESS_CREATED,
+
+ // Sent when extension render process ends (whether it crashes or closes).
+ // The details are an ExtensionHost* and the source is a Profile*. Not sent
+ // during browser shutdown.
+ EXTENSION_PROCESS_TERMINATED,
+
+ // Sent when the contents or order of toolstrips in the shelf model change.
+ EXTENSION_SHELF_MODEL_CHANGED,
+
+ // Sent when a background page is ready so other components can load.
+ EXTENSION_BACKGROUND_PAGE_READY,
+
+ // Sent when a pop-up extension view is ready, so that notification may
+ // be sent to pending callbacks. Note that this notification is sent
+ // after all onload callbacks have been invoked in the main frame.
+ // The details is the ExtensionHost* hosted within the popup, and the source
+ // is a Profile*.
+ EXTENSION_POPUP_VIEW_READY,
+
+ // Sent when a browser action's state has changed. The source is the
+ // ExtensionAction* that changed. There are no details.
+ EXTENSION_BROWSER_ACTION_UPDATED,
+
+ // Sent when the count of page actions has changed. Note that some of them
+ // may not apply to the current page. The source is a LocationBar*. There
+ // are no details.
+ EXTENSION_PAGE_ACTION_COUNT_CHANGED,
+
+ // Sent when a page action's visibility has changed. The source is the
+ // ExtensionAction* that changed. The details are a TabContents*.
+ EXTENSION_PAGE_ACTION_VISIBILITY_CHANGED,
+
+ // Sent by an extension to notify the browser about the results of a unit
+ // test.
+ EXTENSION_TEST_PASSED,
+ EXTENSION_TEST_FAILED,
+
+ // Sent when an bookmarks extensions API function was successfully invoked.
+ // The source is the id of the extension that invoked the function, and the
+ // details are a pointer to the const BookmarksFunction in question.
+ EXTENSION_BOOKMARKS_API_INVOKED,
+
+ // Sent when an omnibox extension has sent back omnibox suggestions. The
+ // source is the profile, and the details are an ExtensionOmniboxSuggestions
+ // object.
+ EXTENSION_OMNIBOX_SUGGESTIONS_READY,
+
+ // Sent when the user accepts the input in an extension omnibox keyword
+ // session. The source is the profile.
+ EXTENSION_OMNIBOX_INPUT_ENTERED,
+
+ // Debugging ---------------------------------------------------------------
+
+ // TODO(mpcomplete): Sent to diagnose a bug. Remove when fixed.
+ // http://code.google.com/p/chromium/issues/detail?id=21201
+ EXTENSION_PORT_DELETED_DEBUG,
+
+ // Desktop Notifications ---------------------------------------------------
+
+ // This notification is sent when a balloon is connected to a renderer
+ // process to render the balloon contents. The source is a
+ // Source<BalloonHost> with a pointer to the the balloon. A
+ // NOTIFY_BALLOON_DISCONNECTED is guaranteed before the source pointer
+ // becomes junk. No details expected.
+ NOTIFY_BALLOON_CONNECTED,
+
+ // This message is sent after a balloon is disconnected from the renderer
+ // process. The source is a Source<BalloonHost> with a pointer to the
+ // balloon host (the pointer is usable). No details are expected.
+ NOTIFY_BALLOON_DISCONNECTED,
+
+ // Web Database Service ----------------------------------------------------
+
+ // This notification is sent whenever autofill entries are
+ // changed. The detail of this notification is a list of changes
+ // represented by a vector of AutofillChange. Each change
+ // includes a change type (add, update, or remove) as well as the
+ // key of the entry that was affected.
+ AUTOFILL_ENTRIES_CHANGED,
+
+ // Sent when an AutoFillProfile has been added/removed/updated in the
+ // WebDatabase. The detail is an AutofillProfileChange.
+ AUTOFILL_PROFILE_CHANGED,
+
+ // Sent when an Autofill CreditCard has been added/removed/updated in the
+ // WebDatabase. The detail is an AutofillCreditCardChange.
+ AUTOFILL_CREDIT_CARD_CHANGED,
+
+ // This notification is sent whenever the web database service has finished
+ // loading the web database. No details are expected.
+ WEB_DATABASE_LOADED,
+
+ // Purge Memory ------------------------------------------------------------
+
+ // Sent on the IO thread when the system should try to reduce the amount of
+ // memory in use, no source or details are passed. See memory_purger.h .cc.
+ PURGE_MEMORY,
+
+ // Upgrade notifications ---------------------------------------------------
+
+ // Sent when Chrome detects that it has been upgraded behind the scenes.
+ // NOTE: The detection mechanism is asynchronous, so this event may arrive
+ // quite some time after the upgrade actually happened. No details are
+ // expected.
+ UPGRADE_DETECTED,
+
+ // Sent when Chrome believes an update has been installed and available for
+ // long enough with the user shutting down to let it take effect. See
+ // upgrade_detector.cc for details on how long it waits. No details are
+ // expected.
+ UPGRADE_RECOMMENDED,
+
+ // Accessibility Notifications ---------------------------------------------
+
+ // Notification that a window in the browser UI (not the web content)
+ // was opened, for propagating to an accessibility extension.
+ // Details will be an AccessibilityWindowInfo.
+ ACCESSIBILITY_WINDOW_OPENED,
+
+ // Notification that a window in the browser UI was closed.
+ // Details will be an AccessibilityWindowInfo.
+ ACCESSIBILITY_WINDOW_CLOSED,
+
+ // Notification that a control in the browser UI was focused.
+ // Details will be an AccessibilityControlInfo.
+ ACCESSIBILITY_CONTROL_FOCUSED,
+
+ // Notification that a control in the browser UI had its action taken,
+ // like pressing a button or toggling a checkbox.
+ // Details will be an AccessibilityControlInfo.
+ ACCESSIBILITY_CONTROL_ACTION,
+
+ // Notification that text box in the browser UI had text change.
+ // Details will be an AccessibilityControlInfo.
+ ACCESSIBILITY_TEXT_CHANGED,
+
+ // Notification that a pop-down menu was opened, for propagating
+ // to an accessibility extension.
+ // Details will be an AccessibilityMenuInfo.
+ ACCESSIBILITY_MENU_OPENED,
+
+ // Notification that a pop-down menu was closed, for propagating
+ // to an accessibility extension.
+ // Details will be an AccessibilityMenuInfo.
+ ACCESSIBILITY_MENU_CLOSED,
+
+ // Content Settings --------------------------------------------------------
+
+ // Sent when content settings change. The source is a HostContentSettings
+ // object, the details are ContentSettingsNotificationsDetails.
+ CONTENT_SETTINGS_CHANGED,
+
+ // Sent when the collect cookies dialog is shown. The source is a
+ // TabSpecificContentSettings object, there are no details.
+ COLLECTED_COOKIES_SHOWN,
+
+ // Sync --------------------------------------------------------------------
+
+ // Sent when the sync backend has been paused.
+ SYNC_PAUSED,
+
+ // Sent when the sync backend has been resumed.
+ SYNC_RESUMED,
+
+ // The sync service has started the configuration process.
+ SYNC_CONFIGURE_START,
+
+ // The sync service is finished the configuration process.
+ SYNC_CONFIGURE_DONE,
+
+ // The session service has been saved. This notification type is only sent
+ // if there were new SessionService commands to save, and not for no-op save
+ // operations.
+ SESSION_SERVICE_SAVED,
+
+ // The syncer requires a passphrase to decrypt sensitive updates. This
+ // notification is sent when the first sensitive data type is setup by the
+ // user as well as anytime any the passphrase is changed in another synced
+ // client.
+ SYNC_PASSPHRASE_REQUIRED,
+
+ // Sent when the passphrase provided by the user is accepted. After this
+ // notification is sent, updates to sensitive nodes are encrypted using the
+ // accepted passphrase.
+ SYNC_PASSPHRASE_ACCEPTED,
+
+ // Cookies -----------------------------------------------------------------
+
+ // Sent when a cookie changes. The source is a Profile object, the details
+ // are a ChromeCookieDetails object.
+ COOKIE_CHANGED,
+
+ // Misc --------------------------------------------------------------------
+
+#if defined(OS_CHROMEOS)
+ // Sent when a chromium os user logs in.
+ LOGIN_USER_CHANGED,
+
+ // Sent when user image is updated.
+ LOGIN_USER_IMAGE_CHANGED,
+
+ // Sent when a chromium os user attempts to log in. The source is
+ // all and the details are AuthenticationNotificationDetails.
+ LOGIN_AUTHENTICATION,
+
+ // Sent when a panel state changed.
+ PANEL_STATE_CHANGED,
+
+ // Sent when the wizard's content view is destroyed. The source and details
+ // are not used.
+ WIZARD_CONTENT_VIEW_DESTROYED,
+
+ // Sent when the screen lock state has changed. The source is
+ // ScreenLocker and the details is a bool specifing that the
+ // screen is locked. When details is a false, the source object
+ // is being deleted, so the receiver shouldn't use the screen locker
+ // object.
+ SCREEN_LOCK_STATE_CHANGED,
+
+ // Sent when the network state has changed on UI thread.
+ // The source is AllSources and the details is NetworkStateDetails defined
+ // in chrome/browser/chromeos/network_state_notifier.h.
+ // TODO(oshima): Port this to all platforms.
+ NETWORK_STATE_CHANGED,
+#endif
+
+ // Sent before the repost form warning is brought up.
+ // The source is a NavigationController.
+ REPOST_WARNING_SHOWN,
+
+#if defined(TOOLKIT_VIEWS)
+ // Sent when a bookmark's context menu is shown. Used to notify
+ // tests that the context menu has been created and shown.
+ BOOKMARK_CONTEXT_MENU_SHOWN,
+#endif
+
+ // Sent when the zoom level changes. The source is the profile, details the
+ // host as a std::string (see HostZoomMap::GetZoomLevel for details on the
+ // host as it not always just the host).
+ ZOOM_LEVEL_CHANGED,
+
+ // Sent when the tab's closeable state has changed due to increase/decrease
+ // in number of tabs in browser or increase/decrease in number of browsers.
+ // Details<bool> contain the closeable flag while source is AllSources.
+ // This is only sent from ChromeOS's TabCloseableStateWatcher.
+ TAB_CLOSEABLE_STATE_CHANGED,
+
+ // Password Store ----------------------------------------------------------
+ // This notification is sent whenenever login entries stored in the password
+ // store are changed. The detail of this notification is a list of changes
+ // represented by a vector of PasswordStoreChange. Each change includes a
+ // change type (ADD, UPDATE, or REMOVE) as well as the
+ // |webkit_glue::PasswordForm|s that were affected.
+ LOGINS_CHANGED,
+
+ // Count (must be last) ----------------------------------------------------
+ // Used to determine the number of notification types. Not valid as
+ // a type parameter when registering for or posting notifications.
+ NOTIFICATION_TYPE_COUNT
+ };
+
+ // TODO(erg): Our notification system relies on implicit conversion.
+ NotificationType(Type v) : value(v) {} // NOLINT
+
+ bool operator==(NotificationType t) const { return value == t.value; }
+ bool operator!=(NotificationType t) const { return value != t.value; }
+
+ // Comparison to explicit enum values.
+ bool operator==(Type v) const { return value == v; }
+ bool operator!=(Type v) const { return value != v; }
+
+ Type value;
+};
+
+inline bool operator==(NotificationType::Type a, NotificationType b) {
+ return a == b.value;
+}
+inline bool operator!=(NotificationType::Type a, NotificationType b) {
+ return a != b.value;
+}
+
+#endif // CHROME_COMMON_NOTIFICATION_TYPE_H_
diff --git a/chrome/common/owned_widget_gtk.cc b/chrome/common/owned_widget_gtk.cc
new file mode 100644
index 0000000..f9b8bef
--- /dev/null
+++ b/chrome/common/owned_widget_gtk.cc
@@ -0,0 +1,38 @@
+// Copyright (c) 2009 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/common/owned_widget_gtk.h"
+
+#include <gtk/gtk.h>
+
+#include "base/logging.h"
+
+OwnedWidgetGtk::~OwnedWidgetGtk() {
+ DCHECK(!widget_) << "You must explicitly call OwnerWidgetGtk::Destroy().";
+}
+
+void OwnedWidgetGtk::Own(GtkWidget* widget) {
+ DCHECK(!widget_);
+ // We want to make sure that Own() was called properly, right after the
+ // widget was created. There should be a floating reference.
+ DCHECK(g_object_is_floating(widget));
+
+ // Sink the floating reference, we should now own this reference.
+ g_object_ref_sink(widget);
+ widget_ = widget;
+}
+
+void OwnedWidgetGtk::Destroy() {
+ if (!widget_)
+ return;
+
+ GtkWidget* widget = widget_;
+ widget_ = NULL;
+ gtk_widget_destroy(widget);
+
+ DCHECK(!g_object_is_floating(widget));
+ // NOTE: Assumes some implementation details about glib internals.
+ DCHECK_EQ(G_OBJECT(widget)->ref_count, 1U);
+ g_object_unref(widget);
+}
diff --git a/chrome/common/owned_widget_gtk.h b/chrome/common/owned_widget_gtk.h
new file mode 100644
index 0000000..72fadd5
--- /dev/null
+++ b/chrome/common/owned_widget_gtk.h
@@ -0,0 +1,89 @@
+// Copyright (c) 2009 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.
+
+// This class assists you in dealing with a specific situation when managing
+// ownership between a C++ object and a GTK widget. It is common to have a
+// C++ object which encapsulates a GtkWidget, and that widget is exposed from
+// the object for use outside of the class. In this situation, you commonly
+// want the GtkWidget's lifetime to match its C++ object's lifetime. Using an
+// OwnedWigetGtk will take ownership over the initial reference of the
+// GtkWidget, so that it is "owned" by the C++ object. Example usage:
+//
+// class FooViewGtk() {
+// public:
+// FooViewGtk() { }
+// ~FooViewGtk() { widget_.Destroy(); }
+// void Init() { vbox_.Own(gtk_vbox_new()); }
+// GtkWidget* widget() { return vbox_.get() }; // Host my widget!
+// private:
+// OwnedWidgetGtk vbox_;
+// };
+//
+// This design will ensure that the widget stays alive from the call to Own()
+// until the call to Destroy().
+//
+// - Details of the problem and OwnedWidgetGtk's solution:
+// In order to make passing ownership more convenient for newly created
+// widgets, GTK has a concept of a "floating" reference. All GtkObjects (and
+// thus GtkWidgets) inherit from GInitiallyUnowned. When they are created, the
+// object starts with a reference count of 1, but has its floating flag set.
+// When it is put into a container for the first time, that container will
+// "sink" the floating reference, and the count will still be 1. Now the
+// container owns the widget, and if we remove the widget from the container,
+// the widget is destroyed. This style of ownership often causes problems when
+// you have an object encapsulating the widget. If we just use a raw
+// GtkObject* with no specific ownership management, we push the widget's
+// ownership onto the user of the class. Now the C++ object can't depend on
+// the widget being valid, since it doesn't manage its lifetime. If the widget
+// was removed from a container, removing its only reference, it would be
+// destroyed (from the C++ object's perspective) unexpectantly destroyed. The
+// solution is fairly simple, make sure that the C++ object owns the widget,
+// and thus it is also responsible for destroying it. This boils down to:
+// GtkWidget* widget = gtk_widget_new();
+// g_object_ref_sink(widget); // Claim the initial floating reference.
+// ...
+// gtk_destroy_widget(widget); // Ask all code to destroy their references.
+// g_object_unref(widget); // Destroy the initial reference we had claimed.
+
+#ifndef CHROME_COMMON_OWNED_WIDGET_GTK_H_
+#define CHROME_COMMON_OWNED_WIDGET_GTK_H_
+
+#include "base/basictypes.h"
+
+typedef struct _GtkWidget GtkWidget;
+
+class OwnedWidgetGtk {
+ public:
+ // Create an instance that isn't managing any ownership.
+ OwnedWidgetGtk() : widget_(NULL) { }
+ // Create an instance that owns |widget|.
+ explicit OwnedWidgetGtk(GtkWidget* widget) : widget_(NULL) { Own(widget); }
+
+ ~OwnedWidgetGtk();
+
+ // Return the currently owned widget, or NULL if no widget is owned.
+ GtkWidget* get() const { return widget_; }
+ GtkWidget* operator->() const { return widget_; }
+
+ // Takes ownership of a widget, by taking the initial floating reference of
+ // the GtkWidget. It is expected that Own() is called right after the widget
+ // has been created, and before any other references to the widget might have
+ // been added. It is valid to never call Own(), in which case Destroy() will
+ // do nothing. If Own() has been called, you must explicitly call Destroy().
+ void Own(GtkWidget* widget);
+
+ // You must call Destroy() after you have called Own(). Calling Destroy()
+ // will call gtk_widget_destroy(), and drop our reference to the widget.
+ // After a call to Destroy(), you may call Own() again. NOTE: It is expected
+ // that after gtk_widget_destroy we will be holding the only reference left
+ // on the object. We assert this in debug mode to help catch any leaks.
+ void Destroy();
+
+ private:
+ GtkWidget* widget_;
+
+ DISALLOW_COPY_AND_ASSIGN(OwnedWidgetGtk);
+};
+
+#endif // CHROME_COMMON_OWNED_WIDGET_GTK_H_
diff --git a/chrome/common/page_transition_types.cc b/chrome/common/page_transition_types.cc
new file mode 100644
index 0000000..bf686f9
--- /dev/null
+++ b/chrome/common/page_transition_types.cc
@@ -0,0 +1,36 @@
+// Copyright (c) 2010 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/common/page_transition_types.h"
+
+#include "base/logging.h"
+
+// static
+PageTransition::Type PageTransition::FromInt(int32 type) {
+ if (!ValidType(type)) {
+ NOTREACHED() << "Invalid transition type " << type;
+
+ // Return a safe default so we don't have corrupt data in release mode.
+ return LINK;
+ }
+ return static_cast<Type>(type);
+}
+
+// static
+const char* PageTransition::CoreTransitionString(Type type) {
+ switch (type & PageTransition::CORE_MASK) {
+ case 0: return "link";
+ case 1: return "typed";
+ case 2: return "auto_bookmark";
+ case 3: return "auto_subframe";
+ case 4: return "manual_subframe";
+ case 5: return "generated";
+ case 6: return "start_page";
+ case 7: return "form_submit";
+ case 8: return "reload";
+ case 9: return "keyword";
+ case 10: return "keyword_generated";
+ }
+ return NULL;
+}
diff --git a/chrome/common/page_transition_types.h b/chrome/common/page_transition_types.h
new file mode 100644
index 0000000..592fc29
--- /dev/null
+++ b/chrome/common/page_transition_types.h
@@ -0,0 +1,161 @@
+// Copyright (c) 2010 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_COMMON_PAGE_TRANSITION_TYPES_H__
+#define CHROME_COMMON_PAGE_TRANSITION_TYPES_H__
+
+#include "base/basictypes.h"
+
+// This class is for scoping only.
+class PageTransition {
+ public:
+ // Types of transitions between pages. These are stored in the history
+ // database to separate visits, and are reported by the renderer for page
+ // navigations.
+ //
+ // WARNING: don't change these numbers. They are written directly into the
+ // history database, so future versions will need the same values to match
+ // the enums.
+ //
+ // A type is made of a core value and a set of qualifiers. A type has one
+ // core value and 0 or or more qualifiers.
+ enum {
+ // User got to this page by clicking a link on another page.
+ LINK = 0,
+
+ // User got this page by typing the URL in the URL bar. This should not be
+ // used for cases where the user selected a choice that didn't look at all
+ // like a URL; see GENERATED below.
+ //
+ // We also use this for other "explicit" navigation actions.
+ TYPED = 1,
+
+ // User got to this page through a suggestion in the UI, for example,
+ // through the destinations page.
+ AUTO_BOOKMARK = 2,
+
+ // This is a subframe navigation. This is any content that is automatically
+ // loaded in a non-toplevel frame. For example, if a page consists of
+ // several frames containing ads, those ad URLs will have this transition
+ // type. The user may not even realize the content in these pages is a
+ // separate frame, so may not care about the URL (see MANUAL below).
+ AUTO_SUBFRAME = 3,
+
+ // For subframe navigations that are explicitly requested by the user and
+ // generate new navigation entries in the back/forward list. These are
+ // probably more important than frames that were automatically loaded in
+ // the background because the user probably cares about the fact that this
+ // link was loaded.
+ MANUAL_SUBFRAME = 4,
+
+ // User got to this page by typing in the URL bar and selecting an entry
+ // that did not look like a URL. For example, a match might have the URL
+ // of a Google search result page, but appear like "Search Google for ...".
+ // These are not quite the same as TYPED navigations because the user
+ // didn't type or see the destination URL.
+ // See also KEYWORD.
+ GENERATED = 5,
+
+ // The page was specified in the command line or is the start page.
+ START_PAGE = 6,
+
+ // The user filled out values in a form and submitted it. NOTE that in
+ // some situations submitting a form does not result in this transition
+ // type. This can happen if the form uses script to submit the contents.
+ FORM_SUBMIT = 7,
+
+ // The user "reloaded" the page, either by hitting the reload button or by
+ // hitting enter in the address bar. NOTE: This is distinct from the
+ // concept of whether a particular load uses "reload semantics" (i.e.
+ // bypasses cached data). For this reason, lots of code needs to pass
+ // around the concept of whether a load should be treated as a "reload"
+ // separately from their tracking of this transition type, which is mainly
+ // used for proper scoring for consumers who care about how frequently a
+ // user typed/visited a particular URL.
+ //
+ // SessionRestore and undo tab close use this transition type too.
+ RELOAD = 8,
+
+ // The url was generated from a replaceable keyword other than the default
+ // search provider. If the user types a keyword (which also applies to
+ // tab-to-search) in the omnibox this qualifier is applied to the transition
+ // type of the generated url. TemplateURLModel then may generate an
+ // additional visit with a transition type of KEYWORD_GENERATED against the
+ // url 'http://' + keyword. For example, if you do a tab-to-search against
+ // wikipedia the generated url has a transition qualifer of KEYWORD, and
+ // TemplateURLModel generates a visit for 'wikipedia.org' with a transition
+ // type of KEYWORD_GENERATED.
+ KEYWORD = 9,
+
+ // Corresponds to a visit generated for a keyword. See description of
+ // KEYWORD for more details.
+ KEYWORD_GENERATED = 10,
+
+ // ADDING NEW CORE VALUE? Be sure to update the LAST_CORE and CORE_MASK
+ // values below. Also update CoreTransitionString().
+ LAST_CORE = KEYWORD_GENERATED,
+ CORE_MASK = 0xFF,
+
+ // Qualifiers
+ // Any of the core values above can be augmented by one or more qualifiers.
+ // These qualifiers further define the transition.
+
+ // The beginning of a navigation chain.
+ CHAIN_START = 0x10000000,
+
+ // The last transition in a redirect chain.
+ CHAIN_END = 0x20000000,
+
+ // Redirects caused by JavaScript or a meta refresh tag on the page.
+ CLIENT_REDIRECT = 0x40000000,
+
+ // Redirects sent from the server by HTTP headers. It might be nice to
+ // break this out into 2 types in the future, permanent or temporary, if we
+ // can get that information from WebKit.
+ SERVER_REDIRECT = 0x80000000,
+
+ // Used to test whether a transition involves a redirect.
+ IS_REDIRECT_MASK = 0xC0000000,
+
+ // General mask defining the bits used for the qualifiers.
+ QUALIFIER_MASK = 0xFFFFFF00
+ };
+
+ // The type used for the bitfield.
+ typedef unsigned int Type;
+
+ static bool ValidType(int32 type) {
+ Type t = StripQualifier(static_cast<Type>(type));
+ return (t <= LAST_CORE);
+ }
+
+ static Type FromInt(int32 type);
+
+ // Returns true if the given transition is a top-level frame transition, or
+ // false if the transition was for a subframe.
+ static bool IsMainFrame(Type type) {
+ int32 t = StripQualifier(type);
+ return (t != AUTO_SUBFRAME && t != MANUAL_SUBFRAME);
+ }
+
+ // Returns whether a transition involves a redirection
+ static bool IsRedirect(Type type) {
+ return (type & IS_REDIRECT_MASK) != 0;
+ }
+
+ // Simplifies the provided transition by removing any qualifier
+ static Type StripQualifier(Type type) {
+ return static_cast<Type>(type & ~QUALIFIER_MASK);
+ }
+
+ // Return the qualifier
+ static int32 GetQualifier(Type type) {
+ return type & QUALIFIER_MASK;
+ }
+
+ // Return a string version of the core type values.
+ static const char* CoreTransitionString(Type type);
+};
+
+#endif // CHROME_COMMON_PAGE_TRANSITION_TYPES_H__
diff --git a/chrome/common/page_zoom.h b/chrome/common/page_zoom.h
new file mode 100644
index 0000000..fa2f5bb
--- /dev/null
+++ b/chrome/common/page_zoom.h
@@ -0,0 +1,22 @@
+// Copyright (c) 2009 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_COMMON_PAGE_ZOOM_H_
+#define CHROME_COMMON_PAGE_ZOOM_H_
+
+class PageZoom {
+ public:
+ // This enum is the parameter to various text/page zoom commands so we know
+ // what the specific zoom command is.
+ enum Function {
+ ZOOM_OUT = -1,
+ RESET = 0,
+ ZOOM_IN = 1,
+ };
+
+ private:
+ DISALLOW_IMPLICIT_CONSTRUCTORS(PageZoom);
+};
+
+#endif // CHROME_COMMON_PAGE_ZOOM_H_
diff --git a/chrome/common/pepper_plugin_registry.cc b/chrome/common/pepper_plugin_registry.cc
new file mode 100644
index 0000000..2ed484e
--- /dev/null
+++ b/chrome/common/pepper_plugin_registry.cc
@@ -0,0 +1,163 @@
+// Copyright (c) 2010 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/common/pepper_plugin_registry.h"
+
+#include "base/command_line.h"
+#include "base/file_util.h"
+#include "base/path_service.h"
+#include "base/string_util.h"
+#include "base/utf_string_conversions.h"
+#include "chrome/common/chrome_paths.h"
+#include "chrome/common/chrome_switches.h"
+#include "remoting/client/plugin/pepper_entrypoints.h"
+
+// static
+PepperPluginRegistry* PepperPluginRegistry::GetInstance() {
+ static PepperPluginRegistry registry;
+ return &registry;
+}
+
+// static
+void PepperPluginRegistry::GetList(std::vector<PepperPluginInfo>* plugins) {
+ InternalPluginInfoList internal_plugin_info;
+ GetInternalPluginInfo(&internal_plugin_info);
+ for (InternalPluginInfoList::const_iterator it =
+ internal_plugin_info.begin();
+ it != internal_plugin_info.end();
+ ++it) {
+ plugins->push_back(*it);
+ }
+
+ GetPluginInfoFromSwitch(plugins);
+ GetExtraPlugins(plugins);
+}
+
+// static
+void PepperPluginRegistry::GetPluginInfoFromSwitch(
+ std::vector<PepperPluginInfo>* plugins) {
+ const std::wstring& value = CommandLine::ForCurrentProcess()->GetSwitchValue(
+ switches::kRegisterPepperPlugins);
+ if (value.empty())
+ return;
+
+ // FORMAT:
+ // command-line = <plugin-entry> + *( LWS + "," + LWS + <plugin-entry> )
+ // plugin-entry = <file-path> + ["#" + <name> + ["#" + <description>]] +
+ // *1( LWS + ";" + LWS + <mime-type> )
+
+ std::vector<std::wstring> modules;
+ SplitString(value, ',', &modules);
+ for (size_t i = 0; i < modules.size(); ++i) {
+ std::vector<std::wstring> parts;
+ SplitString(modules[i], ';', &parts);
+ if (parts.size() < 2) {
+ DLOG(ERROR) << "Required mime-type not found";
+ continue;
+ }
+
+ std::vector<std::wstring> name_parts;
+ SplitString(parts[0], '#', &name_parts);
+
+ PepperPluginInfo plugin;
+ plugin.path = FilePath::FromWStringHack(name_parts[0]);
+ if (name_parts.size() > 1)
+ plugin.name = WideToUTF8(name_parts[1]);
+ if (name_parts.size() > 2)
+ plugin.type_descriptions = WideToUTF8(name_parts[2]);
+ for (size_t j = 1; j < parts.size(); ++j)
+ plugin.mime_types.push_back(WideToASCII(parts[j]));
+
+ plugins->push_back(plugin);
+ }
+}
+
+// static
+void PepperPluginRegistry::GetExtraPlugins(
+ std::vector<PepperPluginInfo>* plugins) {
+ FilePath path;
+ if (PathService::Get(chrome::FILE_PDF_PLUGIN, &path) &&
+ file_util::PathExists(path)) {
+ PepperPluginInfo pdf;
+ pdf.path = path;
+ pdf.name = "Chrome PDF Viewer";
+ pdf.mime_types.push_back("application/pdf");
+ pdf.file_extensions = "pdf";
+ pdf.type_descriptions = "Portable Document Format";
+ plugins->push_back(pdf);
+ }
+}
+
+// static
+void PepperPluginRegistry::GetInternalPluginInfo(
+ InternalPluginInfoList* plugin_info) {
+ // Currently, to centralize the internal plugin registration logic, we
+ // hardcode the list of plugins, mimetypes, and registration information
+ // in this function. This is gross, but because the GetList() function is
+ // called from both the renderer and browser the other option is to force a
+ // special register function for each plugin to be called by both
+ // RendererMain() and BrowserMain(). This seemed like the better tradeoff.
+ //
+ // TODO(ajwong): Think up a better way to maintain the plugin registration
+ // information. Pehraps by construction of a singly linked list of
+ // plugin initializers that is built with static initializers?
+
+#if defined(ENABLE_REMOTING)
+ if (CommandLine::ForCurrentProcess()->HasSwitch(
+ switches::kEnableChromoting)) {
+ InternalPluginInfo info;
+ // Add the chromoting plugin.
+ info.path =
+ FilePath(FILE_PATH_LITERAL("internal-chromoting"));
+ info.mime_types.push_back("pepper-application/x-chromoting");
+ info.entry_points.get_interface = remoting::PPP_GetInterface;
+ info.entry_points.initialize_module = remoting::PPP_InitializeModule;
+ info.entry_points.shutdown_module = remoting::PPP_ShutdownModule;
+
+ plugin_info->push_back(info);
+ }
+#endif
+}
+
+pepper::PluginModule* PepperPluginRegistry::GetModule(
+ const FilePath& path) const {
+ ModuleMap::const_iterator it = modules_.find(path);
+ if (it == modules_.end())
+ return NULL;
+ return it->second;
+}
+
+PepperPluginRegistry::PepperPluginRegistry() {
+ InternalPluginInfoList internal_plugin_info;
+ GetInternalPluginInfo(&internal_plugin_info);
+ // Register modules for these suckers.
+ for (InternalPluginInfoList::const_iterator it =
+ internal_plugin_info.begin();
+ it != internal_plugin_info.end();
+ ++it) {
+ const FilePath& path = it->path;
+ ModuleHandle module =
+ pepper::PluginModule::CreateInternalModule(it->entry_points);
+ if (!module) {
+ DLOG(ERROR) << "Failed to load pepper module: " << path.value();
+ continue;
+ }
+ modules_[path] = module;
+ }
+
+ // Add the modules specified on the command line last so that they can
+ // override the internal plugins.
+ std::vector<PepperPluginInfo> plugins;
+ GetPluginInfoFromSwitch(&plugins);
+ GetExtraPlugins(&plugins);
+ for (size_t i = 0; i < plugins.size(); ++i) {
+ const FilePath& path = plugins[i].path;
+ ModuleHandle module = pepper::PluginModule::CreateModule(path);
+ if (!module) {
+ DLOG(ERROR) << "Failed to load pepper module: " << path.value();
+ continue;
+ }
+ modules_[path] = module;
+ }
+}
diff --git a/chrome/common/pepper_plugin_registry.h b/chrome/common/pepper_plugin_registry.h
new file mode 100644
index 0000000..a728381
--- /dev/null
+++ b/chrome/common/pepper_plugin_registry.h
@@ -0,0 +1,52 @@
+// Copyright (c) 2010 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_COMMON_PEPPER_PLUGIN_REGISTRY_H_
+#define CHROME_COMMON_PEPPER_PLUGIN_REGISTRY_H_
+
+#include <string>
+#include <map>
+#include <vector>
+
+#include "webkit/glue/plugins/pepper_plugin_module.h"
+
+struct PepperPluginInfo {
+ FilePath path; // Internal plugins are of the form "internal-[name]".
+ std::vector<std::string> mime_types;
+ std::string name;
+ std::string description;
+ std::string file_extensions;
+ std::string type_descriptions;
+};
+
+// This class holds references to all of the known pepper plugin modules.
+class PepperPluginRegistry {
+ public:
+ static PepperPluginRegistry* GetInstance();
+
+ // Returns the list of known pepper plugins. This method is static so that
+ // it can be used by the browser process, which has no need to load the
+ // pepper plugin modules.
+ static void GetList(std::vector<PepperPluginInfo>* plugins);
+
+ pepper::PluginModule* GetModule(const FilePath& path) const;
+
+ private:
+ static void GetPluginInfoFromSwitch(std::vector<PepperPluginInfo>* plugins);
+ static void GetExtraPlugins(std::vector<PepperPluginInfo>* plugins);
+
+ struct InternalPluginInfo : public PepperPluginInfo {
+ pepper::PluginModule::EntryPoints entry_points;
+ };
+ typedef std::vector<InternalPluginInfo> InternalPluginInfoList;
+ static void GetInternalPluginInfo(InternalPluginInfoList* plugin_info);
+
+ PepperPluginRegistry();
+
+ typedef scoped_refptr<pepper::PluginModule> ModuleHandle;
+ typedef std::map<FilePath, ModuleHandle> ModuleMap;
+ ModuleMap modules_;
+};
+
+#endif // CHROME_COMMON_PEPPER_PLUGIN_REGISTRY_H_
diff --git a/chrome/common/plugin_carbon_interpose_constants_mac.cc b/chrome/common/plugin_carbon_interpose_constants_mac.cc
new file mode 100644
index 0000000..d7f6f91
--- /dev/null
+++ b/chrome/common/plugin_carbon_interpose_constants_mac.cc
@@ -0,0 +1,17 @@
+// Copyright (c) 2009 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.
+
+#if !defined(__LP64__)
+
+#include "chrome/common/plugin_carbon_interpose_constants_mac.h"
+
+namespace plugin_interpose_strings {
+
+const char kDYLDInsertLibrariesKey[] = "DYLD_INSERT_LIBRARIES";
+const char kInterposeLibraryPath[] =
+ "@executable_path/libplugin_carbon_interpose.dylib";
+
+} // namespace plugin_interpose_strings
+
+#endif // !__LP64__
diff --git a/chrome/common/plugin_carbon_interpose_constants_mac.h b/chrome/common/plugin_carbon_interpose_constants_mac.h
new file mode 100644
index 0000000..321dd84
--- /dev/null
+++ b/chrome/common/plugin_carbon_interpose_constants_mac.h
@@ -0,0 +1,20 @@
+// Copyright (c) 2009 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_COMMON_PLUGIN_CARBON_INTERPOSE_CONSTANTS_MAC_H_
+#define CHROME_COMMON_PLUGIN_CARBON_INTERPOSE_CONSTANTS_MAC_H_
+
+#if !defined(__LP64__)
+
+// Strings used in setting up Carbon interposing for the plugin process.
+namespace plugin_interpose_strings {
+
+extern const char kDYLDInsertLibrariesKey[];
+extern const char kInterposeLibraryPath[];
+
+} // namespace plugin_interpose_strings
+
+#endif // !__LP64__
+
+#endif // CHROME_BROWSER_PLUGIN_CARBON_INTERPOSE_CONSTANTS_MAC_H_
diff --git a/chrome/common/plugin_group.cc b/chrome/common/plugin_group.cc
new file mode 100644
index 0000000..5df39b3
--- /dev/null
+++ b/chrome/common/plugin_group.cc
@@ -0,0 +1,343 @@
+// Copyright (c) 2010 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/common/plugin_group.h"
+
+#include "base/string_util.h"
+#include "base/utf_string_conversions.h"
+#include "base/values.h"
+#include "base/version.h"
+#include "webkit/glue/plugins/plugin_list.h"
+
+#if defined(OS_MACOSX)
+// Plugin Groups for Mac.
+// Plugins are listed here as soon as vulnerabilities and solutions
+// (new versions) are published.
+// TODO(panayiotis): Track Java as soon as it's supported on Chrome Mac.
+// TODO(panayiotis): Get the Real Player version on Mac, somehow.
+static const PluginGroupDefinition kGroupDefinitions[] = {
+ { "Quicktime", "QuickTime Plug-in", "", "", "7.6.6",
+ "http://www.apple.com/quicktime/download/" },
+ { "Flash", "Shockwave Flash", "", "", "10.1.53",
+ "http://get.adobe.com/flashplayer/" },
+ { "Silverlight 3", "Silverlight", "0", "4", "3.0.50106.0",
+ "http://go.microsoft.com/fwlink/?LinkID=185927" },
+ { "Silverlight 4", "Silverlight", "4", "5", "",
+ "http://go.microsoft.com/fwlink/?LinkID=185927" },
+ { "Flip4Mac", "Flip4Mac", "", "", "2.2.1",
+ "http://www.telestream.net/flip4mac-wmv/overview.htm" },
+ { "Shockwave", "Shockwave for Director", "", "", "11.5.7.609",
+ "http://www.adobe.com/shockwave/download/" }
+};
+
+#elif defined(OS_WIN)
+// TODO(panayiotis): We should group "RealJukebox NS Plugin" with the rest of
+// the RealPlayer files.
+static const PluginGroupDefinition kGroupDefinitions[] = {
+ { "Quicktime", "QuickTime Plug-in", "", "", "7.6.6",
+ "http://www.apple.com/quicktime/download/" },
+ { "Java 6", "Java", "", "6", "6.0.200",
+ "http://www.java.com/" },
+ { "Adobe Reader 9", "Adobe Acrobat", "9", "10", "9.3.3",
+ "http://get.adobe.com/reader/" },
+ { "Adobe Reader 8", "Adobe Acrobat", "0", "9", "8.2.3",
+ "http://get.adobe.com/reader/" },
+ { "Flash", "Shockwave Flash", "", "", "10.1.53",
+ "http://get.adobe.com/flashplayer/" },
+ { "Silverlight 3", "Silverlight", "0", "4", "3.0.50106.0",
+ "http://go.microsoft.com/fwlink/?LinkID=185927" },
+ { "Silverlight 4", "Silverlight", "4", "5", "",
+ "http://go.microsoft.com/fwlink/?LinkID=185927" },
+ { "Shockwave", "Shockwave for Director", "", "", "11.5.7.609",
+ "http://www.adobe.com/shockwave/download/" },
+ { "DivX Player", "DivX Web Player", "", "", "1.4.3.4",
+ "http://download.divx.com/divx/autoupdate/player/DivXWebPlayerInstaller.exe" },
+ // These are here for grouping, no vulnerabilies known.
+ { "Windows Media Player", "Windows Media Player", "", "", "", "" },
+ { "Microsoft Office", "Microsoft Office", "", "", "", "" },
+ // TODO(panayiotis): The vulnerable versions are
+ // (v >= 6.0.12.1040 && v <= 6.0.12.1663)
+ // || v == 6.0.12.1698 || v == 6.0.12.1741
+ { "RealPlayer", "RealPlayer", "", "", "",
+ "http://www.adobe.com/shockwave/download/" },
+};
+
+#else
+static const PluginGroupDefinition kGroupDefinitions[] = {};
+#endif
+
+/*static*/
+std::set<string16>* PluginGroup::policy_disabled_puglins_;
+
+/*static*/
+const PluginGroupDefinition* PluginGroup::GetPluginGroupDefinitions() {
+ return kGroupDefinitions;
+}
+
+/*static*/
+size_t PluginGroup::GetPluginGroupDefinitionsSize() {
+ // TODO(viettrungluu): |arraysize()| doesn't work with zero-size arrays.
+ return ARRAYSIZE_UNSAFE(kGroupDefinitions);
+}
+
+/*static*/
+void PluginGroup::SetPolicyDisabledPluginSet(const std::set<string16>& set) {
+ if (!policy_disabled_puglins_) {
+ policy_disabled_puglins_ = new std::set<string16>();
+ *policy_disabled_puglins_ = set;
+ }
+}
+
+/*static*/
+bool PluginGroup::IsPluginNameDisabledByPolicy(const string16& plugin_name) {
+ return policy_disabled_puglins_ &&
+ policy_disabled_puglins_->find(plugin_name) !=
+ policy_disabled_puglins_->end();
+}
+
+/*static*/
+bool PluginGroup::IsPluginPathDisabledByPolicy(const FilePath& plugin_path) {
+ std::vector<WebPluginInfo> plugins;
+ NPAPI::PluginList::Singleton()->GetPlugins(false, &plugins);
+ for (std::vector<WebPluginInfo>::const_iterator it = plugins.begin();
+ it != plugins.end();
+ ++it) {
+ if (FilePath::CompareEqualIgnoreCase(it->path.value(),
+ plugin_path.value()) && IsPluginNameDisabledByPolicy(it->name)) {
+ return true;
+ }
+ }
+ return false;
+}
+
+PluginGroup::PluginGroup(const string16& group_name,
+ const string16& name_matcher,
+ const std::string& version_range_low,
+ const std::string& version_range_high,
+ const std::string& min_version,
+ const std::string& update_url) {
+ group_name_ = group_name;
+ name_matcher_ = name_matcher;
+ version_range_low_str_ = version_range_low;
+ if (!version_range_low.empty()) {
+ version_range_low_.reset(
+ Version::GetVersionFromString(version_range_low));
+ }
+ version_range_high_str_ = version_range_high;
+ if (!version_range_high.empty()) {
+ version_range_high_.reset(
+ Version::GetVersionFromString(version_range_high));
+ }
+ min_version_str_ = min_version;
+ if (!min_version.empty()) {
+ min_version_.reset(Version::GetVersionFromString(min_version));
+ }
+ update_url_ = update_url;
+ enabled_ = false;
+ max_version_.reset(Version::GetVersionFromString("0"));
+}
+
+PluginGroup* PluginGroup::FromPluginGroupDefinition(
+ const PluginGroupDefinition& definition) {
+ return new PluginGroup(ASCIIToUTF16(definition.name),
+ ASCIIToUTF16(definition.name_matcher),
+ definition.version_matcher_low,
+ definition.version_matcher_high,
+ definition.min_version,
+ definition.update_url);
+}
+
+PluginGroup* PluginGroup::FromWebPluginInfo(const WebPluginInfo& wpi) {
+ // Create a matcher from the name of this plugin.
+ return new PluginGroup(wpi.name, wpi.name,
+ "", "", "", "");
+}
+
+PluginGroup* PluginGroup::FindHardcodedPluginGroup(const WebPluginInfo& info) {
+ static std::vector<linked_ptr<PluginGroup> >* hardcoded_plugin_groups = NULL;
+ if (!hardcoded_plugin_groups) {
+ std::vector<linked_ptr<PluginGroup> >* groups =
+ new std::vector<linked_ptr<PluginGroup> >();
+ const PluginGroupDefinition* definitions = GetPluginGroupDefinitions();
+ for (size_t i = 0; i < GetPluginGroupDefinitionsSize(); ++i) {
+ PluginGroup* definition_group = PluginGroup::FromPluginGroupDefinition(
+ definitions[i]);
+ groups->push_back(linked_ptr<PluginGroup>(definition_group));
+ }
+ hardcoded_plugin_groups = groups;
+ }
+
+ // See if this plugin matches any of the hardcoded groups.
+ PluginGroup* hardcoded_group = FindGroupMatchingPlugin(
+ *hardcoded_plugin_groups, info);
+ if (hardcoded_group) {
+ // Make a copy.
+ return hardcoded_group->Copy();
+ } else {
+ // Not found in our hardcoded list, create a new one.
+ return PluginGroup::FromWebPluginInfo(info);
+ }
+}
+
+PluginGroup* PluginGroup::FindGroupMatchingPlugin(
+ std::vector<linked_ptr<PluginGroup> >& plugin_groups,
+ const WebPluginInfo& plugin) {
+ for (std::vector<linked_ptr<PluginGroup> >::iterator it =
+ plugin_groups.begin();
+ it != plugin_groups.end();
+ ++it) {
+ if ((*it)->Match(plugin)) {
+ return it->get();
+ }
+ }
+ return NULL;
+}
+
+bool PluginGroup::Match(const WebPluginInfo& plugin) const {
+ if (name_matcher_.empty()) {
+ return false;
+ }
+
+ // Look for the name matcher anywhere in the plugin name.
+ if (plugin.name.find(name_matcher_) == string16::npos) {
+ return false;
+ }
+
+ if (version_range_low_.get() == NULL ||
+ version_range_high_.get() == NULL) {
+ return true;
+ }
+
+ // There's a version range, we must be in it.
+ scoped_ptr<Version> plugin_version(
+ Version::GetVersionFromString(UTF16ToWide(plugin.version)));
+ if (plugin_version.get() == NULL) {
+ // No version could be extracted, assume we don't match the range.
+ return false;
+ }
+
+ // We match if we are in the range: [low, high)
+ return (version_range_low_->CompareTo(*plugin_version) <= 0 &&
+ version_range_high_->CompareTo(*plugin_version) > 0);
+}
+
+void PluginGroup::AddPlugin(const WebPluginInfo& plugin, int position) {
+ web_plugin_infos_.push_back(plugin);
+ // The position of this plugin relative to the global list of plugins.
+ web_plugin_positions_.push_back(position);
+ description_ = plugin.desc;
+
+ // A group is enabled if any of the files are enabled.
+ if (plugin.enabled) {
+ enabled_ = true;
+ }
+
+ // update max_version_. Remove spaces and ')' from the version string,
+ // Replace any instances of 'r', ',' or '(' with a dot.
+ std::wstring version = UTF16ToWide(plugin.version);
+ RemoveChars(version, L") ", &version);
+ std::replace(version.begin(), version.end(), 'r', '.');
+ std::replace(version.begin(), version.end(), ',', '.');
+ std::replace(version.begin(), version.end(), '(', '.');
+
+ scoped_ptr<Version> plugin_version(
+ Version::GetVersionFromString(version));
+ if (plugin_version.get() != NULL) {
+ if (plugin_version->CompareTo(*(max_version_)) > 0) {
+ max_version_.reset(plugin_version.release());
+ }
+ }
+}
+
+DictionaryValue* PluginGroup::GetSummary() const {
+ DictionaryValue* result = new DictionaryValue();
+ result->SetStringFromUTF16(L"name", group_name_);
+ result->SetBoolean(L"enabled", enabled_);
+ return result;
+}
+
+DictionaryValue* PluginGroup::GetDataForUI() const {
+ DictionaryValue* result = new DictionaryValue();
+ result->SetStringFromUTF16(L"name", group_name_);
+ result->SetStringFromUTF16(L"description", description_);
+ result->SetString(L"version", max_version_->GetString());
+ result->SetString(L"update_url", update_url_);
+ result->SetBoolean(L"critical", IsVulnerable());
+
+ bool group_disabled_by_policy = IsPluginNameDisabledByPolicy(group_name_);
+ if (group_disabled_by_policy) {
+ result->SetString(L"enabledMode", L"disabledByPolicy");
+ } else {
+ result->SetString(L"enabledMode",
+ enabled_ ? L"enabled" : L"disabledByUser");
+ }
+
+ ListValue* plugin_files = new ListValue();
+ for (size_t i = 0; i < web_plugin_infos_.size(); ++i) {
+ const WebPluginInfo& web_plugin = web_plugin_infos_[i];
+ int priority = web_plugin_positions_[i];
+ DictionaryValue* plugin_file = new DictionaryValue();
+ plugin_file->SetStringFromUTF16(L"name", web_plugin.name);
+ plugin_file->SetStringFromUTF16(L"description", web_plugin.desc);
+ plugin_file->SetString(L"path", web_plugin.path.value());
+ plugin_file->SetStringFromUTF16(L"version", web_plugin.version);
+ bool plugin_disabled_by_policy = group_disabled_by_policy ||
+ IsPluginNameDisabledByPolicy(web_plugin.name);
+ if (plugin_disabled_by_policy) {
+ result->SetString(L"enabledMode", L"disabledByPolicy");
+ } else {
+ result->SetString(L"enabledMode",
+ web_plugin.enabled ? L"enabled" : L"disabledByUser");
+ }
+ plugin_file->SetInteger(L"priority", priority);
+
+ ListValue* mime_types = new ListValue();
+ for (std::vector<WebPluginMimeType>::const_iterator type_it =
+ web_plugin.mime_types.begin();
+ type_it != web_plugin.mime_types.end();
+ ++type_it) {
+ DictionaryValue* mime_type = new DictionaryValue();
+ mime_type->SetString(L"mimeType", type_it->mime_type);
+ mime_type->SetStringFromUTF16(L"description", type_it->description);
+
+ ListValue* file_extensions = new ListValue();
+ for (std::vector<std::string>::const_iterator ext_it =
+ type_it->file_extensions.begin();
+ ext_it != type_it->file_extensions.end();
+ ++ext_it) {
+ file_extensions->Append(new StringValue(*ext_it));
+ }
+ mime_type->Set(L"fileExtensions", file_extensions);
+
+ mime_types->Append(mime_type);
+ }
+ plugin_file->Set(L"mimeTypes", mime_types);
+
+ plugin_files->Append(plugin_file);
+ }
+ result->Set(L"plugin_files", plugin_files);
+
+ return result;
+}
+
+// Returns true if the latest version of this plugin group is vulnerable.
+bool PluginGroup::IsVulnerable() const {
+ if (min_version_.get() == NULL || max_version_->GetString() == "0") {
+ return false;
+ }
+ return max_version_->CompareTo(*min_version_) < 0;
+}
+
+void PluginGroup::Enable(bool enable) {
+ for (std::vector<WebPluginInfo>::const_iterator it =
+ web_plugin_infos_.begin();
+ it != web_plugin_infos_.end(); ++it) {
+ if (enable && !IsPluginNameDisabledByPolicy(it->name)) {
+ NPAPI::PluginList::Singleton()->EnablePlugin(FilePath(it->path));
+ } else {
+ NPAPI::PluginList::Singleton()->DisablePlugin(FilePath(it->path));
+ }
+ }
+}
+
diff --git a/chrome/common/plugin_group.h b/chrome/common/plugin_group.h
new file mode 100644
index 0000000..f9f6ce3
--- /dev/null
+++ b/chrome/common/plugin_group.h
@@ -0,0 +1,129 @@
+// Copyright (c) 2010 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_COMMON_PLUGIN_GROUP_H_
+#define CHROME_COMMON_PLUGIN_GROUP_H_
+
+#include <set>
+#include <vector>
+
+#include "base/linked_ptr.h"
+#include "base/scoped_ptr.h"
+#include "base/string16.h"
+#include "base/version.h"
+#include "webkit/glue/plugins/webplugininfo.h"
+
+class DictionaryValue;
+
+// Hard-coded definitions of plugin groups.
+struct PluginGroupDefinition {
+ const char* name; // Name of this group.
+ const char* name_matcher; // Substring matcher for the plugin name.
+ const char* version_matcher_low; // Matchers for the plugin version.
+ const char* version_matcher_high;
+ const char* min_version; // Minimum secure version.
+ const char* update_url; // Location of latest secure version.
+};
+
+
+// A PluginGroup contains at least one WebPluginInfo.
+// In addition, it knows if the plugin is critically vulnerable.
+class PluginGroup {
+ public:
+ // Creates a PluginGroup from a PluginGroupDefinition.
+ static PluginGroup* FromPluginGroupDefinition(
+ const PluginGroupDefinition& definition);
+
+ // Creates a PluginGroup from a WebPluginInfo -- when no hard-coded
+ // definition is found.
+ static PluginGroup* FromWebPluginInfo(const WebPluginInfo& wpi);
+
+ // Find a plugin group matching |info| in the list of hardcoded plugins.
+ static PluginGroup* FindHardcodedPluginGroup(const WebPluginInfo& info);
+
+ // Configures the set of plugin names that are disabled by policy.
+ static void SetPolicyDisabledPluginSet(const std::set<string16>& set);
+
+ // Tests to see if a plugin is on the blacklist using its name as
+ // the lookup key.
+ static bool IsPluginNameDisabledByPolicy(const string16& plugin_name);
+
+ // Tests to see if a plugin is on the blacklist using its path as
+ // the lookup key.
+ static bool IsPluginPathDisabledByPolicy(const FilePath& plugin_path);
+
+ // Find the PluginGroup matching a Plugin in a list of plugin groups. Returns
+ // NULL if no matching PluginGroup is found.
+ static PluginGroup* FindGroupMatchingPlugin(
+ std::vector<linked_ptr<PluginGroup> >& plugin_groups,
+ const WebPluginInfo& plugin);
+
+ // Creates a copy of this plugin group.
+ PluginGroup* Copy() {
+ return new PluginGroup(group_name_, name_matcher_, version_range_low_str_,
+ version_range_high_str_, min_version_str_,
+ update_url_);
+ }
+
+ // Returns true if the given plugin matches this group.
+ bool Match(const WebPluginInfo& plugin) const;
+
+ // Adds the given plugin to this group. Provide the position of the
+ // plugin as given by PluginList so we can display its priority.
+ void AddPlugin(const WebPluginInfo& plugin, int position);
+
+ // Enables/disables this group. This enables/disables all plugins in the
+ // group.
+ void Enable(bool enable);
+
+ // Returns this group's name
+ const string16 GetGroupName() const { return group_name_; }
+
+ // Returns a DictionaryValue with data to display in the UI.
+ DictionaryValue* GetDataForUI() const;
+
+ // Returns a DictionaryValue with data to save in the preferences.
+ DictionaryValue* GetSummary() const;
+
+ // Returns the update URL.
+ std::string GetUpdateURL() const { return update_url_; }
+
+ // Returns true if the latest plugin in this group has known
+ // security problems.
+ bool IsVulnerable() const;
+
+ private:
+ FRIEND_TEST_ALL_PREFIXES(PluginGroupTest, PluginGroupDefinition);
+
+ static const PluginGroupDefinition* GetPluginGroupDefinitions();
+ static size_t GetPluginGroupDefinitionsSize();
+
+ PluginGroup(const string16& group_name,
+ const string16& name_matcher,
+ const std::string& version_range_low,
+ const std::string& version_range_high,
+ const std::string& min_version,
+ const std::string& update_url);
+
+ static std::set<string16>* policy_disabled_puglins_;
+
+ string16 group_name_;
+ string16 name_matcher_;
+ std::string version_range_low_str_;
+ std::string version_range_high_str_;
+ scoped_ptr<Version> version_range_low_;
+ scoped_ptr<Version> version_range_high_;
+ string16 description_;
+ std::string update_url_;
+ bool enabled_;
+ std::string min_version_str_;
+ scoped_ptr<Version> min_version_;
+ scoped_ptr<Version> max_version_;
+ std::vector<WebPluginInfo> web_plugin_infos_;
+ std::vector<int> web_plugin_positions_;
+
+ DISALLOW_COPY_AND_ASSIGN(PluginGroup);
+};
+
+#endif // CHROME_COMMON_PLUGIN_GROUP_H_
diff --git a/chrome/common/plugin_group_unittest.cc b/chrome/common/plugin_group_unittest.cc
new file mode 100644
index 0000000..7def7c6
--- /dev/null
+++ b/chrome/common/plugin_group_unittest.cc
@@ -0,0 +1,113 @@
+// Copyright (c) 2010 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/common/plugin_group.h"
+
+#include <string>
+#include <vector>
+
+#include "base/scoped_ptr.h"
+#include "base/string_util.h"
+#include "base/values.h"
+#include "base/version.h"
+#include "testing/gtest/include/gtest/gtest.h"
+#include "webkit/glue/plugins/webplugininfo.h"
+
+static const PluginGroupDefinition kPluginDef = {
+ "MyPlugin", "MyPlugin", "", "", "3.0.44", "http://latest/" };
+static const PluginGroupDefinition kPluginDef3 = {
+ "MyPlugin 3", "MyPlugin", "0", "4", "3.0.44", "http://latest" };
+static const PluginGroupDefinition kPluginDef4 = {
+ "MyPlugin 4", "MyPlugin", "4", "5", "4.0.44", "http://latest" };
+static const PluginGroupDefinition kPluginDefNotVulnerable = {
+ "MyPlugin", "MyPlugin", "", "", "", "http://latest" };
+
+// name, path, version, desc, mime_types, enabled.
+static WebPluginInfo kPlugin2043 = {
+ ASCIIToUTF16("MyPlugin"), FilePath(), ASCIIToUTF16("2.0.43"), string16(),
+ std::vector<WebPluginMimeType>(), true };
+static WebPluginInfo kPlugin3043 = {
+ ASCIIToUTF16("MyPlugin"), FilePath(), ASCIIToUTF16("3.0.43"), string16(),
+ std::vector<WebPluginMimeType>(), true };
+static WebPluginInfo kPlugin3044 = {
+ ASCIIToUTF16("MyPlugin"), FilePath(), ASCIIToUTF16("3.0.44"), string16(),
+ std::vector<WebPluginMimeType>(), true };
+static WebPluginInfo kPlugin3045 = {
+ ASCIIToUTF16("MyPlugin"), FilePath(), ASCIIToUTF16("3.0.45"), string16(),
+ std::vector<WebPluginMimeType>(), true };
+static WebPluginInfo kPlugin4043 = {
+ ASCIIToUTF16("MyPlugin"), FilePath(), ASCIIToUTF16("4.0.43"), string16(),
+ std::vector<WebPluginMimeType>(), true };
+
+class PluginGroupTest : public testing::Test {
+};
+
+TEST(PluginGroupTest, PluginGroupMatch) {
+ scoped_ptr<PluginGroup> group(PluginGroup::FromPluginGroupDefinition(
+ kPluginDef3));
+ EXPECT_TRUE(group->Match(kPlugin3045));
+ group->AddPlugin(kPlugin3045, 0);
+ EXPECT_FALSE(group->IsVulnerable());
+}
+
+TEST(PluginGroupTest, PluginGroupMatchMultipleFiles) {
+ scoped_ptr<PluginGroup> group(PluginGroup::FromPluginGroupDefinition(
+ kPluginDef3));
+ EXPECT_TRUE(group->Match(kPlugin3043));
+ group->AddPlugin(kPlugin3043, 0);
+ EXPECT_TRUE(group->IsVulnerable());
+
+ EXPECT_TRUE(group->Match(kPlugin3045));
+ group->AddPlugin(kPlugin3045, 1);
+ EXPECT_FALSE(group->IsVulnerable());
+}
+
+TEST(PluginGroupTest, PluginGroupMatchCorrectVersion) {
+ scoped_ptr<PluginGroup> group(PluginGroup::FromPluginGroupDefinition(
+ kPluginDef3));
+ EXPECT_TRUE(group->Match(kPlugin2043));
+ EXPECT_TRUE(group->Match(kPlugin3043));
+ EXPECT_FALSE(group->Match(kPlugin4043));
+
+ group.reset(PluginGroup::FromPluginGroupDefinition(kPluginDef4));
+ EXPECT_FALSE(group->Match(kPlugin2043));
+ EXPECT_FALSE(group->Match(kPlugin3043));
+ EXPECT_TRUE(group->Match(kPlugin4043));
+}
+
+TEST(PluginGroupTest, PluginGroupDefinition) {
+ const PluginGroupDefinition* definitions =
+ PluginGroup::GetPluginGroupDefinitions();
+ for (size_t i = 0; i < PluginGroup::GetPluginGroupDefinitionsSize(); ++i) {
+ scoped_ptr<PluginGroup> def_group(
+ PluginGroup::FromPluginGroupDefinition(definitions[i]));
+ ASSERT_TRUE(def_group.get() != NULL);
+ EXPECT_FALSE(def_group->Match(kPlugin2043));
+ }
+}
+
+TEST(PluginGroupTest, VersionExtraction) {
+ // Some real-world plugin versions (spaces, commata, parentheses, 'r', oh my)
+ const char* versions[][2] = {
+ { "7.6.6 (1671)", "7.6.6.1671" }, // Quicktime
+ { "2, 0, 0, 254", "2.0.0.254" }, // DivX
+ { "3, 0, 0, 0", "3.0.0.0" }, // Picasa
+ { "1, 0, 0, 1", "1.0.0.1" }, // Earth
+ { "10,0,45,2", "10.0.45.2" }, // Flash
+ { "11.5.7r609", "11.5.7.609"} // Shockwave
+ };
+
+ for (size_t i = 0; i < arraysize(versions); i++) {
+ const WebPluginInfo plugin = {
+ ASCIIToUTF16("Blah Plugin"), FilePath(), ASCIIToUTF16(versions[i][0]),
+ string16(),std::vector<WebPluginMimeType>(), true };
+ scoped_ptr<PluginGroup> group(PluginGroup::FromWebPluginInfo(plugin));
+ EXPECT_TRUE(group->Match(plugin));
+ group->AddPlugin(plugin, 0);
+ scoped_ptr<DictionaryValue> data(group->GetDataForUI());
+ std::string version;
+ data->GetString(L"version", &version);
+ EXPECT_EQ(versions[i][1], version);
+ }
+}
diff --git a/chrome/common/plugin_messages.h b/chrome/common/plugin_messages.h
new file mode 100644
index 0000000..82116d8
--- /dev/null
+++ b/chrome/common/plugin_messages.h
@@ -0,0 +1,433 @@
+// Copyright (c) 2009 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.
+
+// Defines messages between the browser and plugin process, as well as between
+// the renderer and plugin process.
+//
+// See render_message* for information about the multi-pass include of headers.
+
+#ifndef CHROME_COMMON_PLUGIN_MESSAGES_H_
+#define CHROME_COMMON_PLUGIN_MESSAGES_H_
+
+#include <string>
+#include <vector>
+
+#include "base/basictypes.h"
+#include "chrome/common/common_param_traits.h"
+#include "chrome/common/webkit_param_traits.h"
+#include "gfx/native_widget_types.h"
+#include "gfx/rect.h"
+#include "googleurl/src/gurl.h"
+#include "ipc/ipc_message_utils.h"
+#include "third_party/npapi/bindings/npapi.h"
+#include "third_party/WebKit/WebKit/chromium/public/WebBindings.h"
+#include "third_party/WebKit/WebKit/chromium/public/WebInputEvent.h"
+#include "webkit/glue/npruntime_util.h"
+
+// Name prefix of the event handle when a message box is displayed.
+#define kMessageBoxEventPrefix L"message_box_active"
+
+// Structures for messages that have too many parameters to be put in a
+// predefined IPC message.
+
+struct PluginMsg_Init_Params {
+ gfx::NativeViewId containing_window;
+ GURL url;
+ GURL page_url;
+ std::vector<std::string> arg_names;
+ std::vector<std::string> arg_values;
+ bool load_manually;
+ int host_render_view_routing_id;
+#if defined(OS_MACOSX)
+ gfx::Rect containing_window_frame;
+ gfx::Rect containing_content_frame;
+ bool containing_window_has_focus;
+#endif
+};
+
+struct PluginHostMsg_URLRequest_Params {
+ std::string url;
+ std::string method;
+ std::string target;
+ std::vector<char> buffer;
+ int notify_id;
+ bool popups_allowed;
+};
+
+struct PluginMsg_DidReceiveResponseParams {
+ unsigned long id;
+ std::string mime_type;
+ std::string headers;
+ uint32 expected_length;
+ uint32 last_modified;
+ bool request_is_seekable;
+};
+
+struct NPIdentifier_Param {
+ NPIdentifier identifier;
+};
+
+enum NPVariant_ParamEnum {
+ NPVARIANT_PARAM_VOID,
+ NPVARIANT_PARAM_NULL,
+ NPVARIANT_PARAM_BOOL,
+ NPVARIANT_PARAM_INT,
+ NPVARIANT_PARAM_DOUBLE,
+ NPVARIANT_PARAM_STRING,
+ // Used when when the NPObject is running in the caller's process, so we
+ // create an NPObjectProxy in the other process.
+ NPVARIANT_PARAM_SENDER_OBJECT_ROUTING_ID,
+ // Used when the NPObject we're sending is running in the callee's process
+ // (i.e. we have an NPObjectProxy for it). In that case we want the callee
+ // to just use the raw pointer.
+ NPVARIANT_PARAM_RECEIVER_OBJECT_ROUTING_ID,
+};
+
+struct NPVariant_Param {
+ NPVariant_ParamEnum type;
+ bool bool_value;
+ int int_value;
+ double double_value;
+ std::string string_value;
+ int npobject_routing_id;
+};
+
+struct PluginMsg_UpdateGeometry_Param {
+ gfx::Rect window_rect;
+ gfx::Rect clip_rect;
+ TransportDIB::Handle windowless_buffer;
+ TransportDIB::Handle background_buffer;
+ bool transparent;
+
+#if defined(OS_MACOSX)
+ // This field contains a key that the plug-in process is expected to return
+ // to the renderer in its ACK message, unless the value is -1, in which case
+ // no ACK message is required. Other than the special -1 value, the values
+ // used in ack_key are opaque to the plug-in process.
+ int ack_key;
+#endif
+};
+
+
+namespace IPC {
+
+// Traits for PluginMsg_Init_Params structure to pack/unpack.
+template <>
+struct ParamTraits<PluginMsg_Init_Params> {
+ typedef PluginMsg_Init_Params param_type;
+ static void Write(Message* m, const param_type& p) {
+ WriteParam(m, p.containing_window);
+ WriteParam(m, p.url);
+ WriteParam(m, p.page_url);
+ DCHECK(p.arg_names.size() == p.arg_values.size());
+ WriteParam(m, p.arg_names);
+ WriteParam(m, p.arg_values);
+ WriteParam(m, p.load_manually);
+ WriteParam(m, p.host_render_view_routing_id);
+#if defined(OS_MACOSX)
+ WriteParam(m, p.containing_window_frame);
+ WriteParam(m, p.containing_content_frame);
+ WriteParam(m, p.containing_window_has_focus);
+#endif
+ }
+ static bool Read(const Message* m, void** iter, param_type* p) {
+ return ReadParam(m, iter, &p->containing_window) &&
+ ReadParam(m, iter, &p->url) &&
+ ReadParam(m, iter, &p->page_url) &&
+ ReadParam(m, iter, &p->arg_names) &&
+ ReadParam(m, iter, &p->arg_values) &&
+ ReadParam(m, iter, &p->load_manually) &&
+ ReadParam(m, iter, &p->host_render_view_routing_id)
+#if defined(OS_MACOSX)
+ &&
+ ReadParam(m, iter, &p->containing_window_frame) &&
+ ReadParam(m, iter, &p->containing_content_frame) &&
+ ReadParam(m, iter, &p->containing_window_has_focus)
+#endif
+ ;
+ }
+ static void Log(const param_type& p, std::wstring* l) {
+ l->append(L"(");
+ LogParam(p.containing_window, l);
+ l->append(L", ");
+ LogParam(p.url, l);
+ l->append(L", ");
+ LogParam(p.page_url, l);
+ l->append(L", ");
+ LogParam(p.arg_names, l);
+ l->append(L", ");
+ LogParam(p.arg_values, l);
+ l->append(L", ");
+ LogParam(p.load_manually, l);
+ l->append(L", ");
+ LogParam(p.host_render_view_routing_id, l);
+#if defined(OS_MACOSX)
+ l->append(L", ");
+ LogParam(p.containing_window_frame, l);
+ l->append(L", ");
+ LogParam(p.containing_content_frame, l);
+ l->append(L", ");
+ LogParam(p.containing_window_has_focus, l);
+#endif
+ l->append(L")");
+ }
+};
+
+template <>
+struct ParamTraits<PluginHostMsg_URLRequest_Params> {
+ typedef PluginHostMsg_URLRequest_Params param_type;
+ static void Write(Message* m, const param_type& p) {
+ WriteParam(m, p.url);
+ WriteParam(m, p.method);
+ WriteParam(m, p.target);
+ WriteParam(m, p.buffer);
+ WriteParam(m, p.notify_id);
+ WriteParam(m, p.popups_allowed);
+ }
+ static bool Read(const Message* m, void** iter, param_type* p) {
+ return
+ ReadParam(m, iter, &p->url) &&
+ ReadParam(m, iter, &p->method) &&
+ ReadParam(m, iter, &p->target) &&
+ ReadParam(m, iter, &p->buffer) &&
+ ReadParam(m, iter, &p->notify_id) &&
+ ReadParam(m, iter, &p->popups_allowed);
+ }
+ static void Log(const param_type& p, std::wstring* l) {
+ l->append(L"(");
+ LogParam(p.url, l);
+ l->append(L", ");
+ LogParam(p.method, l);
+ l->append(L", ");
+ LogParam(p.target, l);
+ l->append(L", ");
+ LogParam(p.buffer, l);
+ l->append(L", ");
+ LogParam(p.notify_id, l);
+ l->append(L", ");
+ LogParam(p.popups_allowed, l);
+ l->append(L")");
+ }
+};
+
+template <>
+struct ParamTraits<PluginMsg_DidReceiveResponseParams> {
+ typedef PluginMsg_DidReceiveResponseParams param_type;
+ static void Write(Message* m, const param_type& p) {
+ WriteParam(m, p.id);
+ WriteParam(m, p.mime_type);
+ WriteParam(m, p.headers);
+ WriteParam(m, p.expected_length);
+ WriteParam(m, p.last_modified);
+ WriteParam(m, p.request_is_seekable);
+ }
+ static bool Read(const Message* m, void** iter, param_type* r) {
+ return
+ ReadParam(m, iter, &r->id) &&
+ ReadParam(m, iter, &r->mime_type) &&
+ ReadParam(m, iter, &r->headers) &&
+ ReadParam(m, iter, &r->expected_length) &&
+ ReadParam(m, iter, &r->last_modified) &&
+ ReadParam(m, iter, &r->request_is_seekable);
+ }
+ static void Log(const param_type& p, std::wstring* l) {
+ l->append(L"(");
+ LogParam(p.id, l);
+ l->append(L", ");
+ LogParam(p.mime_type, l);
+ l->append(L", ");
+ LogParam(p.headers, l);
+ l->append(L", ");
+ LogParam(p.expected_length, l);
+ l->append(L", ");
+ LogParam(p.last_modified, l);
+ l->append(L", ");
+ LogParam(p.request_is_seekable, l);
+ l->append(L")");
+ }
+};
+
+typedef const WebKit::WebInputEvent* WebInputEventPointer;
+template <>
+struct ParamTraits<WebInputEventPointer> {
+ typedef WebInputEventPointer param_type;
+ static void Write(Message* m, const param_type& p) {
+ m->WriteData(reinterpret_cast<const char*>(p), p->size);
+ }
+ // Note: upon read, the event has the lifetime of the message.
+ static bool Read(const Message* m, void** iter, param_type* r) {
+ const char* data;
+ int data_length;
+ if (!m->ReadData(iter, &data, &data_length)) {
+ NOTREACHED();
+ return false;
+ }
+ if (data_length < static_cast<int>(sizeof(WebKit::WebInputEvent))) {
+ NOTREACHED();
+ return false;
+ }
+ param_type event = reinterpret_cast<param_type>(data);
+ // Check that the data size matches that of the event (we check the latter
+ // in the delegate).
+ if (data_length != static_cast<int>(event->size)) {
+ NOTREACHED();
+ return false;
+ }
+ *r = event;
+ return true;
+ }
+ static void Log(const param_type& p, std::wstring* l) {
+ l->append(L"(");
+ LogParam(p->size, l);
+ l->append(L", ");
+ LogParam(p->type, l);
+ l->append(L", ");
+ LogParam(p->timeStampSeconds, l);
+ l->append(L")");
+ }
+};
+
+template <>
+struct ParamTraits<NPIdentifier_Param> {
+ typedef NPIdentifier_Param param_type;
+ static void Write(Message* m, const param_type& p) {
+ webkit_glue::SerializeNPIdentifier(p.identifier, m);
+ }
+ static bool Read(const Message* m, void** iter, param_type* r) {
+ return webkit_glue::DeserializeNPIdentifier(*m, iter, &r->identifier);
+ }
+ static void Log(const param_type& p, std::wstring* l) {
+ if (WebKit::WebBindings::identifierIsString(p.identifier)) {
+ NPUTF8* str = WebKit::WebBindings::utf8FromIdentifier(p.identifier);
+ l->append(UTF8ToWide(str));
+ NPN_MemFree(str);
+ } else {
+ l->append(IntToWString(
+ WebKit::WebBindings::intFromIdentifier(p.identifier)));
+ }
+ }
+};
+
+template <>
+struct ParamTraits<NPVariant_Param> {
+ typedef NPVariant_Param param_type;
+ static void Write(Message* m, const param_type& p) {
+ WriteParam(m, static_cast<int>(p.type));
+ if (p.type == NPVARIANT_PARAM_BOOL) {
+ WriteParam(m, p.bool_value);
+ } else if (p.type == NPVARIANT_PARAM_INT) {
+ WriteParam(m, p.int_value);
+ } else if (p.type == NPVARIANT_PARAM_DOUBLE) {
+ WriteParam(m, p.double_value);
+ } else if (p.type == NPVARIANT_PARAM_STRING) {
+ WriteParam(m, p.string_value);
+ } else if (p.type == NPVARIANT_PARAM_SENDER_OBJECT_ROUTING_ID ||
+ p.type == NPVARIANT_PARAM_RECEIVER_OBJECT_ROUTING_ID) {
+ // This is the routing id used to connect NPObjectProxy in the other
+ // process with NPObjectStub in this process or to identify the raw
+ // npobject pointer to be used in the callee process.
+ WriteParam(m, p.npobject_routing_id);
+ } else {
+ DCHECK(p.type == NPVARIANT_PARAM_VOID || p.type == NPVARIANT_PARAM_NULL);
+ }
+ }
+ static bool Read(const Message* m, void** iter, param_type* r) {
+ int type;
+ if (!ReadParam(m, iter, &type))
+ return false;
+
+ bool result = false;
+ r->type = static_cast<NPVariant_ParamEnum>(type);
+ if (r->type == NPVARIANT_PARAM_BOOL) {
+ result = ReadParam(m, iter, &r->bool_value);
+ } else if (r->type == NPVARIANT_PARAM_INT) {
+ result = ReadParam(m, iter, &r->int_value);
+ } else if (r->type == NPVARIANT_PARAM_DOUBLE) {
+ result = ReadParam(m, iter, &r->double_value);
+ } else if (r->type == NPVARIANT_PARAM_STRING) {
+ result = ReadParam(m, iter, &r->string_value);
+ } else if (r->type == NPVARIANT_PARAM_SENDER_OBJECT_ROUTING_ID ||
+ r->type == NPVARIANT_PARAM_RECEIVER_OBJECT_ROUTING_ID) {
+ result = ReadParam(m, iter, &r->npobject_routing_id);
+ } else if ((r->type == NPVARIANT_PARAM_VOID) ||
+ (r->type == NPVARIANT_PARAM_NULL)) {
+ result = true;
+ } else {
+ NOTREACHED();
+ }
+
+ return result;
+ }
+ static void Log(const param_type& p, std::wstring* l) {
+ if (p.type == NPVARIANT_PARAM_BOOL) {
+ LogParam(p.bool_value, l);
+ } else if (p.type == NPVARIANT_PARAM_INT) {
+ LogParam(p.int_value, l);
+ } else if (p.type == NPVARIANT_PARAM_DOUBLE) {
+ LogParam(p.double_value, l);
+ } else if (p.type == NPVARIANT_PARAM_STRING) {
+ LogParam(p.string_value, l);
+ } else if (p.type == NPVARIANT_PARAM_SENDER_OBJECT_ROUTING_ID ||
+ p.type == NPVARIANT_PARAM_RECEIVER_OBJECT_ROUTING_ID) {
+ LogParam(p.npobject_routing_id, l);
+ }
+ }
+};
+
+// For windowless plugins, windowless_buffer
+// contains a buffer that the plugin draws into. background_buffer is used
+// for transparent windowless plugins, and holds the background of the plugin
+// rectangle.
+template <>
+struct ParamTraits<PluginMsg_UpdateGeometry_Param> {
+ typedef PluginMsg_UpdateGeometry_Param param_type;
+ static void Write(Message* m, const param_type& p) {
+ WriteParam(m, p.window_rect);
+ WriteParam(m, p.clip_rect);
+ WriteParam(m, p.windowless_buffer);
+ WriteParam(m, p.background_buffer);
+ WriteParam(m, p.transparent);
+#if defined(OS_MACOSX)
+ WriteParam(m, p.ack_key);
+#endif
+ }
+ static bool Read(const Message* m, void** iter, param_type* r) {
+ return
+ ReadParam(m, iter, &r->window_rect) &&
+ ReadParam(m, iter, &r->clip_rect) &&
+ ReadParam(m, iter, &r->windowless_buffer) &&
+ ReadParam(m, iter, &r->background_buffer) &&
+ ReadParam(m, iter, &r->transparent)
+#if defined(OS_MACOSX)
+ &&
+ ReadParam(m, iter, &r->ack_key)
+#endif
+ ;
+ }
+ static void Log(const param_type& p, std::wstring* l) {
+ l->append(L"(");
+ LogParam(p.window_rect, l);
+ l->append(L", ");
+ LogParam(p.clip_rect, l);
+ l->append(L", ");
+ LogParam(p.windowless_buffer, l);
+ l->append(L", ");
+ LogParam(p.background_buffer, l);
+ l->append(L", ");
+ LogParam(p.transparent, l);
+#if defined(OS_MACOSX)
+ l->append(L", ");
+ LogParam(p.ack_key, l);
+#endif
+ l->append(L")");
+ }
+};
+
+} // namespace IPC
+
+
+#define MESSAGES_INTERNAL_FILE "chrome/common/plugin_messages_internal.h"
+#include "ipc/ipc_message_macros.h"
+
+#endif // CHROME_COMMON_PLUGIN_MESSAGES_H_
diff --git a/chrome/common/plugin_messages_internal.h b/chrome/common/plugin_messages_internal.h
new file mode 100644
index 0000000..29388a4
--- /dev/null
+++ b/chrome/common/plugin_messages_internal.h
@@ -0,0 +1,514 @@
+// Copyright (c) 2009 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/shared_memory.h"
+#include "build/build_config.h"
+#include "gfx/native_widget_types.h"
+#include "ipc/ipc_message_macros.h"
+#include "webkit/glue/webcursor.h"
+
+#if defined(OS_POSIX)
+#include "base/file_descriptor_posix.h"
+#endif
+
+//-----------------------------------------------------------------------------
+// PluginProcess messages
+// These are messages sent from the browser to the plugin process.
+IPC_BEGIN_MESSAGES(PluginProcess)
+ // Tells the plugin process to create a new channel for communication with a
+ // given renderer. The channel name is returned in a
+ // PluginProcessHostMsg_ChannelCreated message. The renderer ID is passed so
+ // that the plugin process reuses an existing channel to that process if it
+ // exists. This ID is a unique opaque identifier generated by the browser
+ // process.
+ IPC_MESSAGE_CONTROL2(PluginProcessMsg_CreateChannel,
+ int /* renderer_id */,
+ bool /* off_the_record */)
+
+ // Allows a chrome plugin loaded in the browser process to send arbitrary
+ // data to an instance of the same plugin loaded in a plugin process.
+ IPC_MESSAGE_CONTROL1(PluginProcessMsg_PluginMessage,
+ std::vector<uint8> /* opaque data */)
+
+ // Tells the plugin process to notify every connected renderer of the pending
+ // shutdown, so we don't mistake it for a crash.
+ IPC_MESSAGE_CONTROL0(PluginProcessMsg_NotifyRenderersOfPendingShutdown)
+
+ // The following messages are used by all child processes, even though they
+ // are listed under PluginProcess. It seems overkill to define ChildProcess.
+ // Tells the child process it should stop.
+ IPC_MESSAGE_CONTROL0(PluginProcessMsg_AskBeforeShutdown)
+
+ // Sent in response to PluginProcessHostMsg_ShutdownRequest to tell the child
+ // process that it's safe to shutdown.
+ IPC_MESSAGE_CONTROL0(PluginProcessMsg_Shutdown)
+
+#if defined(IPC_MESSAGE_LOG_ENABLED)
+ // Tell the child process to begin or end IPC message logging.
+ // Like above, this is used by all ChildProcesses.
+ IPC_MESSAGE_CONTROL1(PluginProcessMsg_SetIPCLoggingEnabled,
+ bool /* on or off */)
+#endif
+
+IPC_END_MESSAGES(PluginProcess)
+
+
+//-----------------------------------------------------------------------------
+// PluginProcessHost messages
+// These are messages sent from the plugin process to the browser process.
+IPC_BEGIN_MESSAGES(PluginProcessHost)
+ // Response to a PluginProcessMsg_CreateChannel message.
+ IPC_MESSAGE_CONTROL1(PluginProcessHostMsg_ChannelCreated,
+ IPC::ChannelHandle /* channel_handle */)
+
+ IPC_SYNC_MESSAGE_CONTROL0_1(PluginProcessHostMsg_GetPluginFinderUrl,
+ std::string /* plugin finder URL */)
+
+ IPC_MESSAGE_CONTROL0(PluginProcessHostMsg_ShutdownRequest)
+
+ // Allows a chrome plugin loaded in a plugin process to send arbitrary
+ // data to an instance of the same plugin loaded in the browser process.
+ IPC_MESSAGE_CONTROL1(PluginProcessHostMsg_PluginMessage,
+ std::vector<uint8> /* opaque data */)
+
+ // Allows a chrome plugin loaded in a plugin process to send arbitrary
+ // data to an instance of the same plugin loaded in the browser process.
+ IPC_SYNC_MESSAGE_CONTROL1_1(PluginProcessHostMsg_PluginSyncMessage,
+ std::vector<uint8> /* opaque data */,
+ std::vector<uint8> /* opaque data response */)
+
+ // Used to get cookies for the given URL. The request_context is a
+ // CPBrowsingContext, but is passed as int32 to avoid compilation errors.
+ IPC_SYNC_MESSAGE_CONTROL2_1(PluginProcessHostMsg_GetCookies,
+ int32 /* request_context */,
+ GURL /* url */,
+ std::string /* cookies */)
+
+ // Used by the plugin process to verify that its renderer |renderer_id| has
+ // permission to access the given |files|.
+ IPC_SYNC_MESSAGE_CONTROL2_1(PluginProcessHostMsg_AccessFiles,
+ int /* renderer_id */,
+ std::vector<std::string> /* files */,
+ bool /* allowed */)
+
+ // Get the list of proxies to use for |url|, as a semicolon delimited list
+ // of "<TYPE> <HOST>:<PORT>" | "DIRECT". See also ViewHostMsg_ResolveProxy
+ // which does the same thing.
+ IPC_SYNC_MESSAGE_CONTROL1_2(PluginProcessHostMsg_ResolveProxy,
+ GURL /* url */,
+ int /* network error */,
+ std::string /* proxy list */)
+
+#if defined(OS_WIN)
+ // Creates a child window of the given parent window on the UI thread.
+ IPC_SYNC_MESSAGE_CONTROL1_1(PluginProcessHostMsg_CreateWindow,
+ HWND /* parent */,
+ HWND /* child */)
+
+ // Destroys the given window's parent on the UI thread.
+ IPC_MESSAGE_CONTROL2(PluginProcessHostMsg_PluginWindowDestroyed,
+ HWND /* window */,
+ HWND /* parent */)
+
+ IPC_MESSAGE_ROUTED3(PluginProcessHostMsg_DownloadUrl,
+ std::string /* URL */,
+ int /* process id */,
+ HWND /* caller window */)
+#endif
+
+#if defined(USE_X11)
+ // On X11, the mapping between NativeViewId and X window ids
+ // is known only to the browser. This message lets the plugin process
+ // ask about a NativeViewId that was provided by the renderer.
+ // It will get 0 back if it's a bogus input.
+ IPC_SYNC_MESSAGE_CONTROL1_1(PluginProcessHostMsg_MapNativeViewId,
+ gfx::NativeViewId /* input: native view id */,
+ gfx::PluginWindowHandle /* output: X window id */)
+#endif
+
+#if defined(OS_MACOSX)
+ // On Mac OS X, we need the browser to keep track of plugin windows so
+ // that it can add and remove them from stacking groups, hide and show the
+ // menu bar, etc. We pass the window rect for convenience so that the
+ // browser can easily tell if the window is fullscreen.
+
+ // Notifies the browser that the plugin has selected a window (i.e., brought
+ // it to the front and wants it to have keyboard focus).
+ IPC_MESSAGE_CONTROL3(PluginProcessHostMsg_PluginSelectWindow,
+ uint32 /* window ID */,
+ gfx::Rect /* window rect */,
+ bool /* modal */)
+
+ // Notifies the browser that the plugin has shown a window.
+ IPC_MESSAGE_CONTROL3(PluginProcessHostMsg_PluginShowWindow,
+ uint32 /* window ID */,
+ gfx::Rect /* window rect */,
+ bool /* modal */)
+
+ // Notifies the browser that the plugin has hidden a window.
+ IPC_MESSAGE_CONTROL2(PluginProcessHostMsg_PluginHideWindow,
+ uint32 /* window ID */,
+ gfx::Rect /* window rect */)
+
+ // Notifies the browser that a plugin instance has requested a cursor
+ // visibility change.
+ IPC_MESSAGE_CONTROL1(PluginProcessHostMsg_PluginSetCursorVisibility,
+ bool /* cursor visibility */)
+#endif
+
+IPC_END_MESSAGES(PluginProcessHost)
+
+
+//-----------------------------------------------------------------------------
+// Plugin messages
+// These are messages sent from the renderer process to the plugin process.
+IPC_BEGIN_MESSAGES(Plugin)
+ // Tells the plugin process to create a new plugin instance with the given
+ // id. A corresponding WebPluginDelegateStub is created which hosts the
+ // WebPluginDelegateImpl.
+ IPC_SYNC_MESSAGE_CONTROL1_1(PluginMsg_CreateInstance,
+ std::string /* mime_type */,
+ int /* instance_id */)
+
+ // The WebPluginDelegateProxy sends this to the WebPluginDelegateStub in its
+ // destructor, so that the stub deletes the actual WebPluginDelegateImpl
+ // object that it's hosting.
+ IPC_SYNC_MESSAGE_CONTROL1_0(PluginMsg_DestroyInstance,
+ int /* instance_id */)
+
+ IPC_SYNC_MESSAGE_CONTROL0_1(PluginMsg_GenerateRouteID,
+ int /* id */)
+
+ // The messages below all map to WebPluginDelegate methods.
+ IPC_SYNC_MESSAGE_ROUTED1_1(PluginMsg_Init,
+ PluginMsg_Init_Params,
+ bool /* result */)
+
+ // Used to synchronously request a paint for windowless plugins.
+ IPC_SYNC_MESSAGE_ROUTED1_0(PluginMsg_Paint,
+ gfx::Rect /* damaged_rect */)
+
+ // Sent by the renderer after it paints from its backing store so that the
+ // plugin knows it can send more invalidates.
+ IPC_MESSAGE_ROUTED0(PluginMsg_DidPaint)
+
+ IPC_SYNC_MESSAGE_ROUTED0_2(PluginMsg_Print,
+ base::SharedMemoryHandle /* shared_memory*/,
+ uint32 /* size */)
+
+ IPC_SYNC_MESSAGE_ROUTED0_1(PluginMsg_GetPluginScriptableObject,
+ int /* route_id */)
+
+ IPC_MESSAGE_ROUTED3(PluginMsg_DidFinishLoadWithReason,
+ GURL /* url */,
+ int /* reason */,
+ int /* notify_id */)
+
+ // Updates the plugin location.
+ IPC_MESSAGE_ROUTED1(PluginMsg_UpdateGeometry,
+ PluginMsg_UpdateGeometry_Param)
+
+ // A synchronous version of above.
+ IPC_SYNC_MESSAGE_ROUTED1_0(PluginMsg_UpdateGeometrySync,
+ PluginMsg_UpdateGeometry_Param)
+
+ IPC_SYNC_MESSAGE_ROUTED1_0(PluginMsg_SetFocus,
+ bool /* focused */)
+
+ IPC_SYNC_MESSAGE_ROUTED1_2(PluginMsg_HandleInputEvent,
+ IPC::WebInputEventPointer /* event */,
+ bool /* handled */,
+ WebCursor /* cursor type*/)
+
+#if defined(OS_MACOSX)
+ IPC_MESSAGE_ROUTED1(PluginMsg_SetWindowFocus,
+ bool /* has_focus */)
+
+ IPC_MESSAGE_ROUTED1(PluginMsg_SetContentAreaFocus,
+ bool /* has_focus */)
+
+ IPC_MESSAGE_ROUTED0(PluginMsg_ContainerHidden)
+
+ IPC_MESSAGE_ROUTED3(PluginMsg_ContainerShown,
+ gfx::Rect /* window_frame */,
+ gfx::Rect /* view_frame */,
+ bool /* has_focus */)
+
+ IPC_MESSAGE_ROUTED2(PluginMsg_WindowFrameChanged,
+ gfx::Rect /* window_frame */,
+ gfx::Rect /* view_frame */)
+#endif
+
+ IPC_SYNC_MESSAGE_ROUTED2_0(PluginMsg_WillSendRequest,
+ unsigned long /* id */,
+ GURL /* url */)
+
+ IPC_MESSAGE_ROUTED1(PluginMsg_DidReceiveResponse,
+ PluginMsg_DidReceiveResponseParams)
+
+ IPC_MESSAGE_ROUTED3(PluginMsg_DidReceiveData,
+ unsigned long /* id */,
+ std::vector<char> /* buffer */,
+ int /* data_offset */)
+
+ IPC_MESSAGE_ROUTED1(PluginMsg_DidFinishLoading,
+ unsigned long /* id */)
+
+ IPC_MESSAGE_ROUTED1(PluginMsg_DidFail,
+ unsigned long /* id */)
+
+ IPC_MESSAGE_ROUTED4(PluginMsg_SendJavaScriptStream,
+ GURL /* url */,
+ std::string /* result */,
+ bool /* success */,
+ int /* notify_id */)
+
+ IPC_MESSAGE_ROUTED2(PluginMsg_DidReceiveManualResponse,
+ GURL /* url */,
+ PluginMsg_DidReceiveResponseParams)
+
+ IPC_MESSAGE_ROUTED1(PluginMsg_DidReceiveManualData,
+ std::vector<char> /* buffer */)
+
+ IPC_MESSAGE_ROUTED0(PluginMsg_DidFinishManualLoading)
+
+ IPC_MESSAGE_ROUTED0(PluginMsg_DidManualLoadFail)
+
+ IPC_MESSAGE_ROUTED0(PluginMsg_InstallMissingPlugin)
+
+ IPC_MESSAGE_ROUTED3(PluginMsg_HandleURLRequestReply,
+ unsigned long /* resource_id */,
+ GURL /* url */,
+ int /* notify_id */)
+
+ IPC_MESSAGE_ROUTED2(PluginMsg_HTTPRangeRequestReply,
+ unsigned long /* resource_id */,
+ int /* range_request_id */)
+
+ IPC_SYNC_MESSAGE_ROUTED0_1(PluginMsg_CreateCommandBuffer,
+ int /* route_id */)
+
+ IPC_MESSAGE_ROUTED0(PluginMsg_DestroyCommandBuffer)
+
+ IPC_MESSAGE_CONTROL1(PluginMsg_SignalModalDialogEvent,
+ gfx::NativeViewId /* containing_window */)
+
+ IPC_MESSAGE_CONTROL1(PluginMsg_ResetModalDialogEvent,
+ gfx::NativeViewId /* containing_window */)
+
+#if defined(OS_MACOSX)
+ // This message, used only on 10.6 and later, transmits the "fake"
+ // window handle allocated by the browser on behalf of the renderer
+ // to the GPU plugin.
+ IPC_MESSAGE_ROUTED1(PluginMsg_SetFakeAcceleratedSurfaceWindowHandle,
+ gfx::PluginWindowHandle /* window */)
+#endif
+
+IPC_END_MESSAGES(Plugin)
+
+
+//-----------------------------------------------------------------------------
+// PluginHost messages
+// These are messages sent from the plugin process to the renderer process.
+// They all map to the corresponding WebPlugin methods.
+IPC_BEGIN_MESSAGES(PluginHost)
+ // Sends the plugin window information to the renderer.
+ // The window parameter is a handle to the window if the plugin is a windowed
+ // plugin. It is NULL for windowless plugins.
+ IPC_SYNC_MESSAGE_ROUTED1_0(PluginHostMsg_SetWindow,
+ gfx::PluginWindowHandle /* window */)
+
+#if defined(OS_WIN)
+ // The modal_loop_pump_messages_event parameter is an event handle which is
+ // passed in for windowless plugins and is used to indicate if messages
+ // are to be pumped in sync calls to the plugin process. Currently used
+ // in HandleEvent calls.
+ IPC_SYNC_MESSAGE_ROUTED1_0(PluginHostMsg_SetWindowlessPumpEvent,
+ HANDLE /* modal_loop_pump_messages_event */)
+#endif
+
+ IPC_MESSAGE_ROUTED1(PluginHostMsg_URLRequest,
+ PluginHostMsg_URLRequest_Params)
+
+ IPC_MESSAGE_ROUTED1(PluginHostMsg_CancelResource,
+ int /* id */)
+
+ IPC_MESSAGE_ROUTED1(PluginHostMsg_InvalidateRect,
+ gfx::Rect /* rect */)
+
+ IPC_SYNC_MESSAGE_ROUTED1_1(PluginHostMsg_GetWindowScriptNPObject,
+ int /* route id */,
+ bool /* success */)
+
+ IPC_SYNC_MESSAGE_ROUTED1_1(PluginHostMsg_GetPluginElement,
+ int /* route id */,
+ bool /* success */)
+
+ IPC_MESSAGE_ROUTED3(PluginHostMsg_SetCookie,
+ GURL /* url */,
+ GURL /* first_party_for_cookies */,
+ std::string /* cookie */)
+
+ IPC_SYNC_MESSAGE_ROUTED2_1(PluginHostMsg_GetCookies,
+ GURL /* url */,
+ GURL /* first_party_for_cookies */,
+ std::string /* cookies */)
+
+ // Asks the browser to show a modal HTML dialog. The dialog is passed the
+ // given arguments as a JSON string, and returns its result as a JSON string
+ // through json_retval.
+ IPC_SYNC_MESSAGE_ROUTED4_1(PluginHostMsg_ShowModalHTMLDialog,
+ GURL /* url */,
+ int /* width */,
+ int /* height */,
+ std::string /* json_arguments */,
+ std::string /* json_retval */)
+
+ IPC_SYNC_MESSAGE_ROUTED2_2(PluginHostMsg_GetDragData,
+ NPVariant_Param /* event */,
+ bool /* add_data */,
+ std::vector<NPVariant_Param> /* result_values */,
+ bool /* result_success */)
+
+ IPC_SYNC_MESSAGE_ROUTED2_1(PluginHostMsg_SetDropEffect,
+ NPVariant_Param /* event */,
+ int /* effect */,
+ bool /* result_success */)
+
+ IPC_MESSAGE_ROUTED1(PluginHostMsg_MissingPluginStatus,
+ int /* status */)
+
+ IPC_SYNC_MESSAGE_ROUTED0_1(PluginHostMsg_GetCPBrowsingContext,
+ uint32 /* context */)
+
+ IPC_MESSAGE_ROUTED0(PluginHostMsg_CancelDocumentLoad)
+
+ IPC_MESSAGE_ROUTED3(PluginHostMsg_InitiateHTTPRangeRequest,
+ std::string /* url */,
+ std::string /* range_info */,
+ int /* range_request_id */)
+
+ IPC_MESSAGE_ROUTED2(PluginHostMsg_DeferResourceLoading,
+ unsigned long /* resource_id */,
+ bool /* defer */)
+
+ IPC_SYNC_MESSAGE_CONTROL1_0(PluginHostMsg_SetException,
+ std::string /* message */)
+
+ IPC_MESSAGE_CONTROL0(PluginHostMsg_PluginShuttingDown)
+
+#if defined(OS_MACOSX)
+ IPC_MESSAGE_ROUTED1(PluginHostMsg_UpdateGeometry_ACK,
+ int /* ack_key */)
+
+ // This message, used in Mac OS X 10.5 and earlier, is sent from the plug-in
+ // process to the renderer process to indicate that the plug-in allocated a
+ // new TransportDIB that holds the GPU's rendered image. This information is
+ // then forwarded to the browser process via a similar message.
+ IPC_MESSAGE_ROUTED4(PluginHostMsg_AcceleratedSurfaceSetTransportDIB,
+ gfx::PluginWindowHandle /* window */,
+ int32 /* width */,
+ int32 /* height */,
+ TransportDIB::Handle /* handle to the TransportDIB */)
+
+ // Synthesize a fake window handle for the plug-in to identify the instance
+ // to the browser, allowing mapping to a surface for hardware accelleration
+ // of plug-in content. The browser generates the handle which is then set on
+ // the plug-in. |opaque| indicates whether the content should be treated as
+ // opaque.
+ IPC_MESSAGE_ROUTED1(PluginHostMsg_BindFakePluginWindowHandle,
+ bool /* opaque */)
+
+ // This message, used only on 10.6 and later, is sent from the plug-in process
+ // to the renderer process to indicate that the plugin allocated a new
+ // IOSurface object of the given width and height. This information is then
+ // forwarded on to the browser process.
+ //
+ // NOTE: the original intent was to pass a mach port as the IOSurface
+ // identifier but it looks like that will be a lot of work. For now we pass an
+ // ID from IOSurfaceGetID.
+ IPC_MESSAGE_ROUTED4(PluginHostMsg_AcceleratedSurfaceSetIOSurface,
+ gfx::PluginWindowHandle /* window */,
+ int32 /* width */,
+ int32 /* height */,
+ uint64 /* identifier for IOSurface */)
+
+
+ // On the Mac, shared memory can't be allocated in the sandbox, so
+ // the TransportDIB used by the plug-in for rendering has to be allocated
+ // and managed by the browser. This is a synchronous message, use with care.
+ IPC_SYNC_MESSAGE_ROUTED1_1(PluginHostMsg_AllocTransportDIB,
+ size_t /* requested memory size */,
+ TransportDIB::Handle /* output: DIB handle */)
+
+ // Since the browser keeps handles to the allocated transport DIBs, this
+ // message is sent to tell the browser that it may release them when the
+ // renderer is finished with them.
+ IPC_MESSAGE_ROUTED1(PluginHostMsg_FreeTransportDIB,
+ TransportDIB::Id /* DIB id */)
+
+ // This message notifies the renderer process (and from there the
+ // browser process) that the plug-in swapped the buffers associated
+ // with the given "window", which should cause the browser to redraw
+ // the various plug-ins' contents.
+ IPC_MESSAGE_ROUTED1(PluginHostMsg_AcceleratedSurfaceBuffersSwapped,
+ gfx::PluginWindowHandle /* window */)
+#endif
+
+IPC_END_MESSAGES(PluginHost)
+
+//-----------------------------------------------------------------------------
+// NPObject messages
+// These are messages used to marshall NPObjects. They are sent both from the
+// plugin to the renderer and from the renderer to the plugin.
+IPC_BEGIN_MESSAGES(NPObject)
+ IPC_SYNC_MESSAGE_ROUTED0_0(NPObjectMsg_Release)
+
+ IPC_SYNC_MESSAGE_ROUTED1_1(NPObjectMsg_HasMethod,
+ NPIdentifier_Param /* name */,
+ bool /* result */)
+
+ IPC_SYNC_MESSAGE_ROUTED3_2(NPObjectMsg_Invoke,
+ bool /* is_default */,
+ NPIdentifier_Param /* method */,
+ std::vector<NPVariant_Param> /* args */,
+ NPVariant_Param /* result_param */,
+ bool /* result */)
+
+ IPC_SYNC_MESSAGE_ROUTED1_1(NPObjectMsg_HasProperty,
+ NPIdentifier_Param /* name */,
+ bool /* result */)
+
+ IPC_SYNC_MESSAGE_ROUTED1_2(NPObjectMsg_GetProperty,
+ NPIdentifier_Param /* name */,
+ NPVariant_Param /* property */,
+ bool /* result */)
+
+ IPC_SYNC_MESSAGE_ROUTED2_1(NPObjectMsg_SetProperty,
+ NPIdentifier_Param /* name */,
+ NPVariant_Param /* property */,
+ bool /* result */)
+
+ IPC_SYNC_MESSAGE_ROUTED1_1(NPObjectMsg_RemoveProperty,
+ NPIdentifier_Param /* name */,
+ bool /* result */)
+
+ IPC_SYNC_MESSAGE_ROUTED0_0(NPObjectMsg_Invalidate)
+
+ IPC_SYNC_MESSAGE_ROUTED0_2(NPObjectMsg_Enumeration,
+ std::vector<NPIdentifier_Param> /* value */,
+ bool /* result */)
+
+ IPC_SYNC_MESSAGE_ROUTED1_2(NPObjectMsg_Construct,
+ std::vector<NPVariant_Param> /* args */,
+ NPVariant_Param /* result_param */,
+ bool /* result */)
+
+ IPC_SYNC_MESSAGE_ROUTED2_2(NPObjectMsg_Evaluate,
+ std::string /* script */,
+ bool /* popups_allowed */,
+ NPVariant_Param /* result_param */,
+ bool /* result */)
+
+IPC_END_MESSAGES(NPObject)
diff --git a/chrome/common/pref_names.cc b/chrome/common/pref_names.cc
new file mode 100644
index 0000000..e04994f
--- /dev/null
+++ b/chrome/common/pref_names.cc
@@ -0,0 +1,945 @@
+// Copyright (c) 2010 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/common/pref_names.h"
+
+namespace prefs {
+
+// *************** PROFILE PREFS ***************
+// These are attached to the user profile
+
+// A boolean specifying whether the New Tab page is the home page or not.
+const wchar_t kHomePageIsNewTabPage[] = L"homepage_is_newtabpage";
+
+// This is the URL of the page to load when opening new tabs.
+const wchar_t kHomePage[] = L"homepage";
+
+// Used to determine if the last session exited cleanly. Set to false when
+// first opened, and to true when closing. On startup if the value is false,
+// it means the profile didn't exit cleanly.
+const wchar_t kSessionExitedCleanly[] = L"profile.exited_cleanly";
+
+// An integer pref. Holds one of several values:
+// 0: (or empty) don't do anything special on startup.
+// 1: restore the last session.
+// 2: this was used to indicate a specific session should be restored. It is
+// no longer used, but saved to avoid conflict with old preferences.
+// 3: unused, previously indicated the user wants to restore a saved session.
+// 4: restore the URLs defined in kURLsToRestoreOnStartup.
+const wchar_t kRestoreOnStartup[] = L"session.restore_on_startup";
+
+// The URLs to restore on startup or when the home button is pressed. The URLs
+// are only restored on startup if kRestoreOnStartup is 4.
+const wchar_t kURLsToRestoreOnStartup[] =
+ L"session.urls_to_restore_on_startup";
+
+// The application locale.
+const wchar_t kApplicationLocale[] = L"intl.app_locale";
+
+// The default character encoding to assume for a web page in the
+// absence of MIME charset specification
+const wchar_t kDefaultCharset[] = L"intl.charset_default";
+
+// The value to use for Accept-Languages HTTP header when making an HTTP
+// request.
+const wchar_t kAcceptLanguages[] = L"intl.accept_languages";
+
+// The value to use for showing locale-dependent encoding list for different
+// locale, it's initialized from the corresponding string resource that is
+// stored in non-translatable part of the resource bundle.
+const wchar_t kStaticEncodings[] = L"intl.static_encodings";
+
+// OBSOLETE. The list of hostnames for which we whitelist popups (rather than
+// blocking).
+const wchar_t kPopupWhitelistedHosts[] = L"profile.popup_whitelisted_sites";
+
+// WebKit preferences.
+// A boolean flag to indicate whether WebKit standard font family is
+// serif or sans-serif. We don't have a UI for setting standard family.
+// Instead, we use this pref to map either serif or sans_serif to WebKit
+// standard font family. At the moment, we don't have a UI for this
+// flag, either.
+const wchar_t kWebKitStandardFontIsSerif[] =
+ L"webkit.webprefs.standard_font_is_serif";
+const wchar_t kWebKitFixedFontFamily[] = L"webkit.webprefs.fixed_font_family";
+const wchar_t kWebKitSerifFontFamily[] = L"webkit.webprefs.serif_font_family";
+const wchar_t kWebKitSansSerifFontFamily[] =
+ L"webkit.webprefs.sansserif_font_family";
+const wchar_t kWebKitCursiveFontFamily[] =
+ L"webkit.webprefs.cursive_font_family";
+const wchar_t kWebKitFantasyFontFamily[] =
+ L"webkit.webprefs.fantasy_font_family";
+const wchar_t kWebKitDefaultFontSize[] = L"webkit.webprefs.default_font_size";
+const wchar_t kWebKitDefaultFixedFontSize[] =
+ L"webkit.webprefs.default_fixed_font_size";
+const wchar_t kWebKitMinimumFontSize[] = L"webkit.webprefs.minimum_font_size";
+const wchar_t kWebKitMinimumLogicalFontSize[] =
+ L"webkit.webprefs.minimum_logical_font_size";
+const wchar_t kWebKitJavascriptEnabled[] =
+ L"webkit.webprefs.javascript_enabled";
+const wchar_t kWebKitWebSecurityEnabled[] =
+ L"webkit.webprefs.web_security_enabled";
+const wchar_t kWebKitJavascriptCanOpenWindowsAutomatically[] =
+ L"webkit.webprefs.javascript_can_open_windows_automatically";
+const wchar_t kWebKitLoadsImagesAutomatically[] =
+ L"webkit.webprefs.loads_images_automatically";
+const wchar_t kWebKitPluginsEnabled[] = L"webkit.webprefs.plugins_enabled";
+const wchar_t kWebKitDomPasteEnabled[] = L"webkit.webprefs.dom_paste_enabled";
+const wchar_t kWebKitShrinksStandaloneImagesToFit[] =
+ L"webkit.webprefs.shrinks_standalone_images_to_fit";
+const wchar_t kWebKitInspectorSettings[] =
+ L"webkit.webprefs.inspector_settings";
+const wchar_t kWebKitUsesUniversalDetector[] =
+ L"webkit.webprefs.uses_universal_detector";
+const wchar_t kWebKitTextAreasAreResizable[] =
+ L"webkit.webprefs.text_areas_are_resizable";
+const wchar_t kWebKitJavaEnabled[] =
+ L"webkit.webprefs.java_enabled";
+const wchar_t kWebkitTabsToLinks[] = L"webkit.webprefs.tabs_to_links";
+
+// Boolean which specifies whether the bookmark bar is visible on all tabs.
+const wchar_t kShowBookmarkBar[] = L"bookmark_bar.show_on_all_tabs";
+
+// Boolean that is true if the password manager is on (will record new
+// passwords and fill in known passwords).
+const wchar_t kPasswordManagerEnabled[] = L"profile.password_manager_enabled";
+
+// OBSOLETE. Boolean that is true if the form AutoFill is on (will record
+// values entered in text inputs in forms and shows them in a popup when user
+// type in a text input with the same name later on). This has been superseded
+// by kAutoFillEnabled.
+const wchar_t kFormAutofillEnabled[] = L"profile.form_autofill_enabled";
+
+// Boolean that is true when SafeBrowsing is enabled.
+const wchar_t kSafeBrowsingEnabled[] = L"safebrowsing.enabled";
+
+// Boolean that is true when Suggest support is enabled.
+const wchar_t kSearchSuggestEnabled[] = L"search.suggest_enabled";
+
+// OBSOLETE. Enum that specifies whether to enforce a third-party cookie
+// blocking policy. This has been superseded by kDefaultContentSettings +
+// kBlockThirdPartyCookies.
+// 0 - allow all cookies.
+// 1 - block third-party cookies
+// 2 - block all cookies
+const wchar_t kCookieBehavior[] = L"security.cookie_behavior";
+
+// The URL (as understood by TemplateURLRef) the default search provider uses
+// for searches.
+const wchar_t kDefaultSearchProviderSearchURL[] =
+ L"default_search_provider.search_url";
+
+// The URL (as understood by TemplateURLRef) the default search provider uses
+// for suggestions.
+const wchar_t kDefaultSearchProviderSuggestURL[] =
+ L"default_search_provider.suggest_url";
+
+// The name of the default search provider.
+const wchar_t kDefaultSearchProviderName[] = L"default_search_provider.name";
+
+// The id of the default search provider.
+const wchar_t kDefaultSearchProviderID[] = L"default_search_provider.id";
+
+// The prepopulate id of the default search provider.
+const wchar_t kDefaultSearchProviderPrepopulateID[] =
+ L"default_search_provider.prepopulate_id";
+
+// The dictionary key used when the default search providers are given
+// in the preferences file. Normally they are copied from the master
+// preferences file.
+const wchar_t kSearchProviderOverrides[] =
+ L"search_provider_overrides";
+// The format version for the dictionary above.
+const wchar_t kSearchProviderOverridesVersion[] =
+ L"search_provider_overrides_version";
+
+// Boolean which specifies whether we should ask the user if we should download
+// a file (true) or just download it automatically.
+const wchar_t kPromptForDownload[] = L"download.prompt_for_download";
+
+// A boolean pref set to true if we're using Link Doctor error pages.
+const wchar_t kAlternateErrorPagesEnabled[] = L"alternate_error_pages.enabled";
+
+// A boolean pref set to true if DNS pre-fetching is being done in browser.
+const wchar_t kDnsPrefetchingEnabled[] = L"dns_prefetching.enabled";
+
+// An adaptively identified list of domain names to be pre-fetched during the
+// next startup, based on what was actually needed during this startup.
+const wchar_t kDnsStartupPrefetchList[] = L"StartupDNSPrefetchList";
+
+// A list of host names used to fetch web pages, and their commonly used
+// sub-resource hostnames (and expected latency benefits from pre-resolving, or
+// preconnecting to, such sub-resource hostnames).
+// This list is adaptively grown and pruned.
+const wchar_t kDnsHostReferralList[] = L"HostReferralList";
+
+// Is the cookie prompt expanded?
+const wchar_t kCookiePromptExpanded[] = L"cookieprompt.expanded";
+
+#if defined(USE_NSS)
+// Prefs for SSLConfigServicePref. Currently, these are only present on
+// and used by NSS-using OSes.
+const wchar_t kCertRevocationCheckingEnabled[] = L"ssl.rev_checking.enabled";
+const wchar_t kSSL2Enabled[] = L"ssl.ssl2.enabled";
+const wchar_t kSSL3Enabled[] = L"ssl.ssl3.enabled";
+const wchar_t kTLS1Enabled[] = L"ssl.tls1.enabled";
+#endif
+
+#if defined(OS_CHROMEOS)
+// A boolean pref set to true if TapToClick is being done in browser.
+const wchar_t kTapToClickEnabled[] = L"settings.touchpad.enable_tap_to_click";
+
+// A boolean pref set to true if VertEdgeScroll is being done in browser.
+const wchar_t kVertEdgeScrollEnabled[] =
+ L"settings.touchpad.enable_vert_edge_scroll";
+
+// A integer pref for the touchpad speed factor.
+const wchar_t kTouchpadSpeedFactor[] = L"settings.touchpad.speed_factor";
+
+// A integer pref for the touchpad sensitivity.
+const wchar_t kTouchpadSensitivity[] = L"settings.touchpad.sensitivity";
+
+// A string pref set to the current input method.
+const wchar_t kLanguageCurrentInputMethod[] =
+ L"settings.language.current_input_method";
+
+// A string pref set to the previous input method.
+const wchar_t kLanguagePreviousInputMethod[] =
+ L"settings.language.previous_input_method";
+
+// A string pref (comma-separated list) set to the "next engine in menu"
+// hot-key lists.
+const wchar_t kLanguageHotkeyNextEngineInMenu[] =
+ L"settings.language.hotkey_next_engine_in_menu";
+
+// A string pref (comma-separated list) set to the "previous engine"
+// hot-key lists.
+const wchar_t kLanguageHotkeyPreviousEngine[] =
+ L"settings.language.hotkey_previous_engine";
+
+// A string pref (comma-separated list) set to the preferred language IDs
+// (ex. "en-US,fr,ko").
+const wchar_t kLanguagePreferredLanguages[] =
+ L"settings.language.preferred_languages";
+
+// A string pref (comma-separated list) set to the preloaded (active) input
+// method IDs (ex. "pinyin,mozc").
+const wchar_t kLanguagePreloadEngines[] = L"settings.language.preload_engines";
+
+// Boolean prefs for ibus-chewing Chinese input method.
+const wchar_t kLanguageChewingAutoShiftCur[] =
+ L"settings.language.chewing_auto_shift_cur";
+const wchar_t kLanguageChewingAddPhraseDirection[] =
+ L"settings.language.chewing_add_phrase_direction";
+const wchar_t kLanguageChewingEasySymbolInput[] =
+ L"settings.language.chewing_easy_symbol_input";
+const wchar_t kLanguageChewingEscCleanAllBuf[] =
+ L"settings.language.chewing_esc_clean_all_buf";
+const wchar_t kLanguageChewingForceLowercaseEnglish[] =
+ L"settings.language.chewing_force_lowercase_english";
+const wchar_t kLanguageChewingPlainZhuyin[] =
+ L"settings.language.chewing_plain_zhuyin";
+const wchar_t kLanguageChewingPhraseChoiceRearward[] =
+ L"settings.language.chewing_phrase_choice_rearward";
+const wchar_t kLanguageChewingSpaceAsSelection[] =
+ L"settings.language.chewing_space_as_selection";
+
+// Integer prefs for ibus-chewing Chinese input method.
+const wchar_t kLanguageChewingMaxChiSymbolLen[] =
+ L"settings.language.chewing_max_chi_symbol_len";
+const wchar_t kLanguageChewingCandPerPage[] =
+ L"settings.language.chewing_cand_per_page";
+
+// String prefs for ibus-chewing Chinese input method.
+const wchar_t kLanguageChewingKeyboardType[] =
+ L"settings.language.chewing_keyboard_type";
+const wchar_t kLanguageChewingSelKeys[] =
+ L"settings.language.chewing_sel_keys";
+
+const wchar_t kLanguageChewingHsuSelKeyType[] =
+ L"settings.language.chewing_hsu_sel_key_type";
+
+// A string pref which determines the keyboard layout for Hangul input method.
+const wchar_t kLanguageHangulKeyboard[] = L"settings.language.hangul_keyboard";
+const wchar_t kLanguageHangulHanjaKeys[] =
+ L"settings.language.hangul_hanja_keys";
+
+// A boolean prefs for ibus-pinyin Chinese input method.
+const wchar_t kLanguagePinyinCorrectPinyin[] =
+ L"settings.language.pinyin_correct_pinyin";
+const wchar_t kLanguagePinyinFuzzyPinyin[] =
+ L"settings.language.pinyin_fuzzy_pinyin";
+const wchar_t kLanguagePinyinShiftSelectCandidate[] =
+ L"settings.language.pinyin_shift_select_candidate";
+const wchar_t kLanguagePinyinMinusEqualPage[] =
+ L"settings.language.pinyin_minus_equal_page";
+const wchar_t kLanguagePinyinCommaPeriodPage[] =
+ L"settings.language.pinyin_comma_period_page";
+const wchar_t kLanguagePinyinAutoCommit[] =
+ L"settings.language.pinyin_auto_commit";
+const wchar_t kLanguagePinyinDoublePinyin[] =
+ L"settings.language.pinyin_double_pinyin";
+const wchar_t kLanguagePinyinInitChinese[] =
+ L"settings.language.pinyin_init_chinese";
+const wchar_t kLanguagePinyinInitFull[] =
+ L"settings.language.pinyin_init_full";
+const wchar_t kLanguagePinyinInitFullPunct[] =
+ L"settings.language.pinyin_init_full_punct";
+const wchar_t kLanguagePinyinInitSimplifiedChinese[] =
+ L"settings.language.pinyin_init_simplified_chinese";
+const wchar_t kLanguagePinyinTradCandidate[] =
+ L"settings.language.pinyin_trad_candidate";
+
+// A integer prefs for ibus-pinyin Chinese input method.
+const wchar_t kLanguagePinyinDoublePinyinSchema[] =
+ L"settings.language.pinyin_double_pinyin_schema";
+const wchar_t kLanguagePinyinLookupTablePageSize[] =
+ L"settings.language.pinyin_lookup_table_page_size";
+
+// A string prefs for ibus-mozc Japanese input method.
+// ibus-mozc converts the string values to protobuf enum values defined in
+// third_party/ibus-mozc/files/src/session/config.proto.
+const wchar_t kLanguageMozcPreeditMethod[] =
+ L"settings.language.mozc_preedit_method";
+const wchar_t kLanguageMozcSessionKeymap[] =
+ L"settings.language.mozc_sessoin_keymap";
+const wchar_t kLanguageMozcPunctuationMethod[] =
+ L"settings.language.mozc_punctuation_method";
+const wchar_t kLanguageMozcSymbolMethod[] =
+ L"settings.language.mozc_symbol_method";
+const wchar_t kLanguageMozcSpaceCharacterForm[] =
+ L"settings.language.mozc_space_character_form";
+const wchar_t kLanguageMozcHistoryLearningLevel[] =
+ L"settings.language.mozc_history_learning_level";
+const wchar_t kLanguageMozcSelectionShortcut[] =
+ L"settings.language.mozc_selection_shortcut";
+const wchar_t kLanguageMozcShiftKeyModeSwitch[] =
+ L"settings.language.mozc_shift_key_mode_switch";
+const wchar_t kLanguageMozcNumpadCharacterForm[] =
+ L"settings.language.mozc_numpad_character_form";
+const wchar_t kLanguageMozcIncognitoMode[] =
+ L"settings.language.mozc_incognito_mode";
+const wchar_t kLanguageMozcUseAutoImeTurnOff[] =
+ L"settings.language.mozc_use_auto_ime_turn_off";
+const wchar_t kLanguageMozcUseDateConversion[] =
+ L"settings.language.mozc_use_date_conversion";
+const wchar_t kLanguageMozcUseSingleKanjiConversion[] =
+ L"settings.language.mozc_use_single_kanji_conversion";
+const wchar_t kLanguageMozcUseSymbolConversion[] =
+ L"settings.language.mozc_use_symbol_conversion";
+const wchar_t kLanguageMozcUseNumberConversion[] =
+ L"settings.language.mozc_use_number_conversion";
+const wchar_t kLanguageMozcUseHistorySuggest[] =
+ L"settings.language.mozc_use_history_suggest";
+const wchar_t kLanguageMozcUseDictionarySuggest[] =
+ L"settings.language.mozc_use_dictionary_suggest";
+const wchar_t kLanguageMozcSuggestionsSize[] =
+ L"settings.language.mozc_suggestions_size";
+
+// A boolean pref which determines whether accessibility is enabled.
+const wchar_t kAccessibilityEnabled[] = L"settings.accessibility";
+
+// A boolean pref which turns on Advanced Filesystem
+// (USB support, SD card, etc).
+const wchar_t kLabsAdvancedFilesystemEnabled[] =
+ L"settings.labs.advanced_filesystem";
+
+// A boolean pref which turns on the mediaplayer.
+const wchar_t kLabsMediaplayerEnabled[] = L"settings.labs.mediaplayer";
+
+#endif // defined(OS_CHROMEOS)
+
+// The disabled messages in IPC logging.
+const wchar_t kIpcDisabledMessages[] = L"ipc_log_disabled_messages";
+
+// A boolean pref set to true if a Home button to open the Home pages should be
+// visible on the toolbar.
+const wchar_t kShowHomeButton[] = L"browser.show_home_button";
+
+// A boolean pref set to true if the Page and Options menu buttons should be
+// visible on the toolbar. This is only used for Mac where the default is to
+// have these menu in the main menubar, not as buttons on the toolbar.
+const wchar_t kShowPageOptionsButtons[] = L"browser.show_page_options_buttons";
+
+// A string value which saves short list of recently user selected encodings
+// separated with comma punctuation mark.
+const wchar_t kRecentlySelectedEncoding[] =
+ L"profile.recently_selected_encodings";
+
+// Clear Browsing Data dialog preferences.
+const wchar_t kDeleteBrowsingHistory[] = L"browser.clear_data.browsing_history";
+const wchar_t kDeleteDownloadHistory[] =
+ L"browser.clear_data.download_history";
+const wchar_t kDeleteCache[] = L"browser.clear_data.cache";
+const wchar_t kDeleteCookies[] = L"browser.clear_data.cookies";
+const wchar_t kDeletePasswords[] = L"browser.clear_data.passwords";
+const wchar_t kDeleteFormData[] = L"browser.clear_data.form_data";
+const wchar_t kDeleteTimePeriod[] = L"browser.clear_data.time_period";
+
+// Boolean pref to define the default values for using spellchecker.
+const wchar_t kEnableSpellCheck[] = L"browser.enable_spellchecking";
+
+// Boolean pref to define the default values for using auto spell correct.
+const wchar_t kEnableAutoSpellCorrect[] = L"browser.enable_autospellcorrect";
+
+// String pref to define the default values for print overlays.
+const wchar_t kPrintingPageHeaderLeft[] = L"printing.page.header.left";
+const wchar_t kPrintingPageHeaderCenter[] = L"printing.page.header.center";
+const wchar_t kPrintingPageHeaderRight[] = L"printing.page.header.right";
+const wchar_t kPrintingPageFooterLeft[] = L"printing.page.footer.left";
+const wchar_t kPrintingPageFooterCenter[] = L"printing.page.footer.center";
+const wchar_t kPrintingPageFooterRight[] = L"printing.page.footer.right";
+#if defined(TOOLKIT_USES_GTK)
+// GTK specific preference on whether we should match the system GTK theme.
+const wchar_t kUsesSystemTheme[] = L"extensions.theme.use_system";
+#endif
+const wchar_t kCurrentThemePackFilename[] = L"extensions.theme.pack";
+const wchar_t kCurrentThemeID[] = L"extensions.theme.id";
+const wchar_t kCurrentThemeImages[] = L"extensions.theme.images";
+const wchar_t kCurrentThemeColors[] = L"extensions.theme.colors";
+const wchar_t kCurrentThemeTints[] = L"extensions.theme.tints";
+const wchar_t kCurrentThemeDisplayProperties[] =
+ L"extensions.theme.properties";
+
+// Boolean pref which persists whether the extensions_ui is in developer mode
+// (showing developer packing tools and extensions details)
+const wchar_t kExtensionsUIDeveloperMode[] = L"extensions.ui.developer_mode";
+
+// Integer pref that tracks the number of browser actions visible in the browser
+// actions toolbar.
+const wchar_t kExtensionToolbarSize[] = L"extensions.toolbarsize";
+
+// Pref containing the directory for internal plugins as written to the plugins
+// list (below).
+const wchar_t kPluginsLastInternalDirectory[] =
+ L"plugins.last_internal_directory";
+
+// List pref containing information (dictionaries) on plugins.
+const wchar_t kPluginsPluginsList[] = L"plugins.plugins_list";
+
+// List pref containing names of plugins that are disabled by policy.
+const wchar_t kPluginsPluginsBlacklist[] = L"plugins.plugins_blacklist";
+
+// When first shipped, the pdf plugin will be disabled by default. When we
+// enable it by default, we'll want to do so only once.
+const wchar_t kPluginsEnabledInternalPDF[] = L"plugins.enabled_internal_pdf";
+
+// Boolean that indicates whether we should check if we are the default browser
+// on start-up.
+const wchar_t kCheckDefaultBrowser[] = L"browser.check_default_browser";
+
+#if defined(OS_MACOSX)
+// Boolean that indicates whether the application should show the info bar
+// asking the user to set up automatic updates when Keystone promotion is
+// required.
+const wchar_t kShowUpdatePromotionInfoBar[] =
+ L"browser.show_update_promotion_info_bar";
+#endif
+
+// Boolean that is false if we should show window manager decorations. If
+// true, we draw a custom chrome frame (thicker title bar and blue border).
+const wchar_t kUseCustomChromeFrame[] = L"browser.custom_chrome_frame";
+
+// Boolean that indicates whether the infobar explaining that search can be
+// done directly from the omnibox should be shown.
+const wchar_t kShowOmniboxSearchHint[] = L"browser.show_omnibox_search_hint";
+
+// Int which specifies how many times left to show a promotional message on the
+// NTP. This value decrements each time the NTP is shown for the first time
+// in a session.
+const wchar_t kNTPPromoViewsRemaining[] = L"browser.ntp.promo_remaining";
+
+// The list of origins which are allowed|denied to show desktop notifications.
+const wchar_t kDesktopNotificationDefaultContentSetting[] =
+ L"profile.notifications_default_content_setting";
+const wchar_t kDesktopNotificationAllowedOrigins[] =
+ L"profile.notification_allowed_sites";
+const wchar_t kDesktopNotificationDeniedOrigins[] =
+ L"profile.notification_denied_sites";
+
+// Dictionary of content settings applied to all hosts by default.
+const wchar_t kDefaultContentSettings[] = L"profile.default_content_settings";
+
+// OBSOLETE. Dictionary that maps hostnames to content related settings.
+// Default settings will be applied to hosts not in this pref.
+const wchar_t kPerHostContentSettings[] = L"profile.per_host_content_settings";
+
+// Version of the pattern format used to define content settings.
+const wchar_t kContentSettingsVersion[] =
+ L"profile.content_settings.pref_version";
+
+// Patterns for mapping hostnames to content related settings. Default settings
+// will be applied to hosts that don't match any of the patterns. Replaces
+// kPerHostContentSettings. The pattern format used is defined by
+// kContentSettingsVersion.
+const wchar_t kContentSettingsPatterns[] =
+ L"profile.content_settings.patterns";
+
+// Boolean that is true if we should unconditionally block third-party cookies,
+// regardless of other content settings.
+const wchar_t kBlockThirdPartyCookies[] = L"profile.block_third_party_cookies";
+
+// Boolean that is true when all locally stored site data (e.g. cookies, local
+// storage, etc..) should be deleted on exit.
+const wchar_t kClearSiteDataOnExit[] = L"profile.clear_site_data_on_exit";
+
+// Dictionary that maps hostnames to zoom levels. Hosts not in this pref will
+// be displayed at the default zoom level.
+const wchar_t kPerHostZoomLevels[] = L"profile.per_host_zoom_levels";
+
+// Boolean that is true if AutoFill is enabled and allowed to save profile data.
+const wchar_t kAutoFillEnabled[] = L"autofill.enabled";
+
+// Boolean that is true when auxiliary AutoFill profiles are enabled.
+// Currently applies to Address Book "me" card on Mac. False on Win and Linux.
+const wchar_t kAutoFillAuxiliaryProfilesEnabled[] =
+ L"autofill.auxiliary_profiles_enabled";
+
+// Position and size of the AutoFill dialog.
+const wchar_t kAutoFillDialogPlacement[] = L"autofill.dialog_placement";
+
+// Double that indicates positive (for matched forms) upload rate.
+const wchar_t kAutoFillPositiveUploadRate[] = L"autofill.positive_upload_rate";
+
+// Double that indicates negative (for not matched forms) upload rate.
+const wchar_t kAutoFillNegativeUploadRate[] = L"autofill.negative_upload_rate";
+
+// Boolean that is true when the tabstrip is to be laid out vertically down the
+// side of the browser window.
+const wchar_t kUseVerticalTabs[] = L"tabs.use_vertical_tabs";
+
+// Boolean that is true when the translate feature is enabled.
+const wchar_t kEnableTranslate[] = L"translate.enabled";
+
+const wchar_t kPinnedTabs[] = L"pinned_tabs";
+
+// Integer containing the default Geolocation content setting.
+const wchar_t kGeolocationDefaultContentSetting[] =
+ L"geolocation.default_content_setting";
+
+// Dictionary that maps [frame, toplevel] to their Geolocation content setting.
+const wchar_t kGeolocationContentSettings[] = L"geolocation.content_settings";
+
+// *************** LOCAL STATE ***************
+// These are attached to the machine/installation
+
+// The metrics client GUID and session ID.
+const wchar_t kMetricsClientID[] = L"user_experience_metrics.client_id";
+const wchar_t kMetricsSessionID[] = L"user_experience_metrics.session_id";
+
+// Date/time when the current metrics profile ID was created
+// (which hopefully corresponds to first run).
+const wchar_t kMetricsClientIDTimestamp[] =
+ L"user_experience_metrics.client_id_timestamp";
+
+// Boolean that specifies whether or not crash reporting and metrics reporting
+// are sent over the network for analysis.
+const wchar_t kMetricsReportingEnabled[] =
+ L"user_experience_metrics.reporting_enabled";
+
+// Array of strings that are each UMA logs that were supposed to be sent in the
+// first minute of a browser session. These logs include things like crash count
+// info, etc.
+const wchar_t kMetricsInitialLogs[] =
+ L"user_experience_metrics.initial_logs";
+
+// Array of strings that are each UMA logs that were not sent because the
+// browser terminated before these accumulated metrics could be sent. These
+// logs typically include histograms and memory reports, as well as ongoing
+// user activities.
+const wchar_t kMetricsOngoingLogs[] =
+ L"user_experience_metrics.ongoing_logs";
+
+// Where profile specific metrics are placed.
+const wchar_t kProfileMetrics[] = L"user_experience_metrics.profiles";
+
+// The metrics for a profile are stored as dictionary values under the
+// path kProfileMetrics. The individual metrics are placed under the path
+// kProfileMetrics.kProfilePrefix<hashed-profile-id>.
+const wchar_t kProfilePrefix[] = L"profile-";
+
+// True if the previous run of the program exited cleanly.
+const wchar_t kStabilityExitedCleanly[] =
+ L"user_experience_metrics.stability.exited_cleanly";
+
+// Version string of previous run, which is used to assure that stability
+// metrics reported under current version reflect stability of the same version.
+const wchar_t kStabilityStatsVersion[] =
+ L"user_experience_metrics.stability.stats_version";
+
+// Build time, in seconds since an epoch, which is used to assure that stability
+// metrics reported reflect stability of the same build.
+const wchar_t kStabilityStatsBuildTime[] =
+ L"user_experience_metrics.stability.stats_buildtime";
+
+// False if we received a session end and either we crashed during processing
+// the session end or ran out of time and windows terminated us.
+const wchar_t kStabilitySessionEndCompleted[] =
+ L"user_experience_metrics.stability.session_end_completed";
+
+// Number of times the application was launched since last report.
+const wchar_t kStabilityLaunchCount[] =
+ L"user_experience_metrics.stability.launch_count";
+
+// Number of times the application exited uncleanly since the last report.
+const wchar_t kStabilityCrashCount[] =
+ L"user_experience_metrics.stability.crash_count";
+
+// Number of times the session end did not complete.
+const wchar_t kStabilityIncompleteSessionEndCount[] =
+ L"user_experience_metrics.stability.incomplete_session_end_count";
+
+// Number of times a page load event occurred since the last report.
+const wchar_t kStabilityPageLoadCount[] =
+ L"user_experience_metrics.stability.page_load_count";
+
+// Number of times a renderer process crashed since the last report.
+const wchar_t kStabilityRendererCrashCount[] =
+ L"user_experience_metrics.stability.renderer_crash_count";
+
+// Number of times an extension renderer process crashed since the last report.
+const wchar_t kStabilityExtensionRendererCrashCount[] =
+ L"user_experience_metrics.stability.extension_renderer_crash_count";
+
+// Time when the app was last launched, in seconds since the epoch.
+const wchar_t kStabilityLaunchTimeSec[] =
+ L"user_experience_metrics.stability.launch_time_sec";
+
+// Time when the app was last known to be running, in seconds since
+// the epoch.
+const wchar_t kStabilityLastTimestampSec[] =
+ L"user_experience_metrics.stability.last_timestamp_sec";
+
+// This is the location of a list of dictionaries of plugin stability stats.
+const wchar_t kStabilityPluginStats[] =
+ L"user_experience_metrics.stability.plugin_stats2";
+
+// Number of times the renderer has become non-responsive since the last
+// report.
+const wchar_t kStabilityRendererHangCount[] =
+ L"user_experience_metrics.stability.renderer_hang_count";
+
+// Total number of child process crashes (other than renderer / extension
+// renderer ones, and plugin children, which are counted separately) since the
+// last report.
+const wchar_t kStabilityChildProcessCrashCount[] =
+ L"user_experience_metrics.stability.child_process_crash_count";
+
+// Number of times the browser has been able to register crash reporting.
+const wchar_t kStabilityBreakpadRegistrationSuccess[] =
+ L"user_experience_metrics.stability.breakpad_registration_ok";
+
+// Number of times the browser has failed to register crash reporting.
+const wchar_t kStabilityBreakpadRegistrationFail[] =
+ L"user_experience_metrics.stability.breakpad_registration_fail";
+
+// Number of times the browser has been run under a debugger.
+const wchar_t kStabilityDebuggerPresent[] =
+ L"user_experience_metrics.stability.debugger_present";
+
+// Number of times the browser has not been run under a debugger.
+const wchar_t kStabilityDebuggerNotPresent[] =
+ L"user_experience_metrics.stability.debugger_not_present";
+
+// The keys below are used for the dictionaries in the
+// kStabilityPluginStats list.
+const wchar_t kStabilityPluginName[] = L"name";
+const wchar_t kStabilityPluginLaunches[] = L"launches";
+const wchar_t kStabilityPluginInstances[] = L"instances";
+const wchar_t kStabilityPluginCrashes[] = L"crashes";
+
+// The keys below are strictly increasing counters over the lifetime of
+// a chrome installation. They are (optionally) sent up to the uninstall
+// survey in the event of uninstallation.
+const wchar_t kUninstallMetricsPageLoadCount[] =
+ L"uninstall_metrics.page_load_count";
+const wchar_t kUninstallLaunchCount[] = L"uninstall_metrics.launch_count";
+const wchar_t kUninstallMetricsInstallDate[] =
+ L"uninstall_metrics.installation_date2";
+const wchar_t kUninstallMetricsUptimeSec[] = L"uninstall_metrics.uptime_sec";
+const wchar_t kUninstallLastLaunchTimeSec[] =
+ L"uninstall_metrics.last_launch_time_sec";
+const wchar_t kUninstallLastObservedRunTimeSec[] =
+ L"uninstall_metrics.last_observed_running_time_sec";
+
+// A collection of position, size, and other data relating to the browser
+// window to restore on startup.
+const wchar_t kBrowserWindowPlacement[] = L"browser.window_placement";
+
+// A collection of position, size, and other data relating to the task
+// manager window to restore on startup.
+const wchar_t kTaskManagerWindowPlacement[] = L"task_manager.window_placement";
+
+// A collection of position, size, and other data relating to the page info
+// window to restore on startup.
+const wchar_t kPageInfoWindowPlacement[] = L"page_info.window_placement";
+
+// A collection of position, size, and other data relating to the keyword
+// editor window to restore on startup.
+const wchar_t kKeywordEditorWindowPlacement[] =
+ L"keyword_editor.window_placement";
+
+// A collection of position, size, and other data relating to the preferences
+// window to restore on startup.
+const wchar_t kPreferencesWindowPlacement[] = L"preferences.window_placement";
+
+// An integer specifying the total number of bytes to be used by the
+// renderer's in-memory cache of objects.
+const wchar_t kMemoryCacheSize[] = L"renderer.memory_cache.size";
+
+// String which specifies where to download files to by default.
+const wchar_t kDownloadDefaultDirectory[] = L"download.default_directory";
+
+// Boolean that records if the download directory was changed by an
+// upgrade a unsafe location to a safe location.
+const wchar_t kDownloadDirUpgraded[] = L"download.directory_upgrade";
+
+// String which specifies where to save html files to by default.
+const wchar_t kSaveFileDefaultDirectory[] = L"savefile.default_directory";
+
+// String which specifies the last directory that was chosen for uploading
+// or opening a file.
+extern const wchar_t kSelectFileLastDirectory[] = L"selectfile.last_directory";
+
+// Extensions which should be opened upon completion.
+const wchar_t kDownloadExtensionsToOpen[] = L"download.extensions_to_open";
+
+// Integer which specifies the frequency in milliseconds for detecting whether
+// plugin windows are hung.
+const wchar_t kHungPluginDetectFrequency[] =
+ L"browser.hung_plugin_detect_freq";
+
+// Integer which specifies the timeout value to be used for SendMessageTimeout
+// to detect a hung plugin window.
+const wchar_t kPluginMessageResponseTimeout[] =
+ L"browser.plugin_message_response_timeout";
+
+// String which represents the dictionary name for our spell-checker.
+const wchar_t kSpellCheckDictionary[] = L"spellcheck.dictionary";
+
+// Dictionary of schemes used by the external protocol handler.
+// The value is true if the scheme must be ignored.
+const wchar_t kExcludedSchemes[] = L"protocol_handler.excluded_schemes";
+
+// Keys used for MAC handling of SafeBrowsing requests.
+const wchar_t kSafeBrowsingClientKey[] = L"safe_browsing.client_key";
+const wchar_t kSafeBrowsingWrappedKey[] = L"safe_browsing.wrapped_key";
+
+// Integer that specifies the index of the tab the user was on when they
+// last visited the options window.
+const wchar_t kOptionsWindowLastTabIndex[] = L"options_window.last_tab_index";
+
+// Integer that specifies the index of the tab the user was on when they
+// last visited the content settings window.
+const wchar_t kContentSettingsWindowLastTabIndex[] =
+ L"content_settings_window.last_tab_index";
+
+// Integer that specifies the index of the tab the user was on when they
+// last visited the Certificate Manager window.
+const wchar_t kCertificateManagerWindowLastTabIndex[] =
+ L"certificate_manager_window.last_tab_index";
+
+// The mere fact that this pref is registered signals that we should show the
+// First Run Search Information bubble when the first browser window appears.
+// This preference is only registered by the first-run procedure.
+const wchar_t kShouldShowFirstRunBubble[] = L"show-first-run-bubble";
+
+// The mere fact that this pref is registered signals that we should show the
+// smaller OEM First Run Search Information bubble when the first
+// browser window appears.
+// This preference is only registered by the first-run procedure.
+const wchar_t kShouldUseOEMFirstRunBubble[] = L"show-OEM-first-run-bubble";
+
+// The mere fact that this pref is registered signals that we should show the
+// minimal First Run omnibox information bubble when the first
+// browser window appears.
+// This preference is only registered by the first-run procedure.
+const wchar_t kShouldUseMinimalFirstRunBubble[] =
+ L"show-minimal-first-run-bubble";
+
+// Signal that we should show the welcome page when we launch Chrome.
+const wchar_t kShouldShowWelcomePage[] = L"show-welcome-page";
+
+// String containing the last known Google URL. We re-detect this on startup in
+// most cases, and use it to send traffic to the correct Google host or with the
+// correct Google domain/country code for whatever location the user is in.
+const wchar_t kLastKnownGoogleURL[] = L"browser.last_known_google_url";
+
+// String containing the last known intranet redirect URL, if any. See
+// intranet_redirect_detector.h for more information.
+const wchar_t kLastKnownIntranetRedirectOrigin[] = L"";
+
+// Integer containing the system Country ID the first time we checked the
+// template URL prepopulate data. This is used to avoid adding a whole bunch of
+// new search engine choices if prepopulation runs when the user's Country ID
+// differs from their previous Country ID. This pref does not exist until
+// prepopulation has been run at least once.
+const wchar_t kCountryIDAtInstall[] = L"countryid_at_install";
+// OBSOLETE. Same as above, but uses the Windows-specific GeoID value instead.
+// Updated if found to the above key.
+const wchar_t kGeoIDAtInstall[] = L"geoid_at_install";
+
+// An enum value of how the browser was shut down (see browser_shutdown.h).
+const wchar_t kShutdownType[] = L"shutdown.type";
+// Number of processes that were open when the user shut down.
+const wchar_t kShutdownNumProcesses[] = L"shutdown.num_processes";
+// Number of processes that were shut down using the slow path.
+const wchar_t kShutdownNumProcessesSlow[] = L"shutdown.num_processes_slow";
+
+// Whether to restart the current Chrome session automatically as the last thing
+// before shutting everything down.
+const wchar_t kRestartLastSessionOnShutdown[] =
+ L"restart.last.session.on.shutdown";
+
+// Number of bookmarks/folders on the bookmark bar/other bookmark folder.
+const wchar_t kNumBookmarksOnBookmarkBar[] =
+ L"user_experience_metrics.num_bookmarks_on_bookmark_bar";
+const wchar_t kNumFoldersOnBookmarkBar[] =
+ L"user_experience_metrics.num_folders_on_bookmark_bar";
+const wchar_t kNumBookmarksInOtherBookmarkFolder[] =
+ L"user_experience_metrics.num_bookmarks_in_other_bookmark_folder";
+const wchar_t kNumFoldersInOtherBookmarkFolder[] =
+ L"user_experience_metrics.num_folders_in_other_bookmark_folder";
+
+// Number of keywords.
+const wchar_t kNumKeywords[] = L"user_experience_metrics.num_keywords";
+
+// Placeholder preference for disabling voice / video chat if it is ever added.
+// Currently, this does not change any behavior.
+const wchar_t kDisableVideoAndChat[] = L"disable_video_chat";
+
+// Whether Extensions are enabled.
+const wchar_t kDisableExtensions[] = L"extensions.disabled";
+
+// Boolean which specifies whether the Extension Shelf is visible on all tabs.
+const wchar_t kShowExtensionShelf[] = L"extensions.shelf.show_on_all_tabs";
+
+// Integer boolean representing the width (in pixels) of the container for
+// browser actions.
+const wchar_t kBrowserActionContainerWidth[] =
+ L"extensions.browseractions.container.width";
+
+// Time of the last, and next scheduled, extensions auto-update checks.
+const wchar_t kLastExtensionsUpdateCheck[] =
+ L"extensions.autoupdate.last_check";
+const wchar_t kNextExtensionsUpdateCheck[] =
+ L"extensions.autoupdate.next_check";
+// Version number of last blacklist check
+const wchar_t kExtensionBlacklistUpdateVersion[] =
+ L"extensions.blacklistupdate.version";
+
+// New Tab Page URLs that should not be shown as most visited thumbnails.
+const wchar_t kNTPMostVisitedURLsBlacklist[] = L"ntp.most_visited_blacklist";
+
+// The URLs that have been pinned to the Most Visited section of the New Tab
+// Page.
+const wchar_t kNTPMostVisitedPinnedURLs[] = L"ntp.pinned_urls";
+
+// Data downloaded from resource pages (JSON, RSS) to be displayed in the
+// recommendations portion of the NTP.
+const wchar_t kNTPTipsCache[] = L"ntp.tips_cache";
+
+// Last time of update of tips_cache.
+const wchar_t kNTPTipsCacheUpdate[] = L"ntp.tips_cache_update";
+
+// Last server used to fill tips_cache.
+const wchar_t kNTPTipsServer[] = L"ntp.tips_server";
+
+// Which sections should be visible on the new tab page
+// 1 - Show the most visited sites in a grid
+// 2 - Show the most visited sites as a list
+// 4 - Show the recent section
+// 8 - Show tips
+// 16 - show sync status
+const wchar_t kNTPShownSections[] = L"ntp.shown_sections";
+
+// This pref is used for migrating the prefs for the NTP
+const wchar_t kNTPPrefVersion[] = L"ntp.pref_version";
+
+// A boolean specifying whether dev tools window should be opened docked.
+const wchar_t kDevToolsOpenDocked[] = L"devtools.open_docked";
+
+// Integer location of the split bar in the browser view.
+const wchar_t kDevToolsSplitLocation[] = L"devtools.split_location";
+
+// 64-bit integer serialization of the base::Time when the last sync occurred.
+const wchar_t kSyncLastSyncedTime[] = L"sync.last_synced_time";
+
+// Boolean specifying whether the user finished setting up sync.
+const wchar_t kSyncHasSetupCompleted[] = L"sync.has_setup_completed";
+
+// Boolean specifying whether to automatically sync all data types (including
+// future ones, as they're added). If this is true, the following preferences
+// (kSyncBookmarks, kSyncPasswords, etc.) can all be ignored.
+const wchar_t kKeepEverythingSynced[] = L"sync.keep_everything_synced";
+
+// Booleans specifying whether the user has selected to sync the following
+// datatypes.
+const wchar_t kSyncBookmarks[] = L"sync.bookmarks";
+const wchar_t kSyncPasswords[] = L"sync.passwords";
+const wchar_t kSyncPreferences[] = L"sync.preferences";
+const wchar_t kSyncAutofill[] = L"sync.autofill";
+const wchar_t kSyncThemes[] = L"sync.themes";
+const wchar_t kSyncTypedUrls[] = L"sync.typed_urls";
+const wchar_t kSyncExtensions[] = L"sync.extensions";
+
+// Boolean used by enterprise configuration management in order to lock down
+// sync.
+const wchar_t kSyncManaged[] = L"sync.managed";
+
+// Create web application shortcut dialog preferences.
+const wchar_t kWebAppCreateOnDesktop[] = L"browser.web_app.create_on_desktop";
+const wchar_t kWebAppCreateInAppsMenu[] =
+ L"browser.web_app.create_in_apps_menu";
+const wchar_t kWebAppCreateInQuickLaunchBar[] =
+ L"browser.web_app.create_in_quick_launch_bar";
+
+// Dictionary that maps Geolocation network provider server URLs to
+// corresponding access token.
+const wchar_t kGeolocationAccessToken[] = L"geolocation.access_token";
+
+// Whether PasswordForms have been migrated from the WedDataService to the
+// LoginDatabase.
+const wchar_t kLoginDatabaseMigrated[] = L"login_database.migrated";
+
+// The root URL of the cloud print service.
+const wchar_t kCloudPrintServiceURL[] = L"cloud_print.service_url";
+
+// The list of BackgroundContents that should be loaded when the browser
+// launches.
+const wchar_t kRegisteredBackgroundContents[] =
+ L"background_contents.registered";
+
+// *************** SERVICE PREFS ***************
+// These are attached to the service process.
+
+// The unique id for this instance of the cloud print proxy.
+const wchar_t kCloudPrintProxyId[] = L"cloud_print.proxy_id";
+// The GAIA auth token for Cloud Print
+const wchar_t kCloudPrintAuthToken[] = L"cloud_print.auth_token";
+// The GAIA auth token used by Cloud Print to authenticate with the XMPP server
+// This should eventually go away because the above token should work for both.
+const wchar_t kCloudPrintXMPPAuthToken[] = L"cloud_print.xmpp_auth_token";
+// The email address of the account used to authenticate with the Cloud Print
+// server.
+extern const wchar_t kCloudPrintEmail[] = L"cloud_print.email";
+// Settings specific to underlying print system.
+extern const wchar_t kCloudPrintPrintSystemSettings[] =
+ L"cloud_print.print_system_settings";
+
+// Boolean to disable proxy altogether. If true, other proxy
+// preferences are ignored.
+const wchar_t kNoProxyServer[] = L"proxy.disabled";
+// Boolean specifying if proxy should be auto-detected.
+const wchar_t kProxyAutoDetect[] = L"proxy.auto_detect";
+// String specifying the proxy server. For a specification of the expected
+// syntax see net::ProxyConfig::ProxyRules::ParseFromString().
+const wchar_t kProxyServer[] = L"proxy.server";
+// URL to the proxy .pac file.
+const wchar_t kProxyPacUrl[] = L"proxy.pac_url";
+// String containing proxy bypass rules. For a specification of the
+// expected syntax see net::ProxyBypassRules::ParseFromString().
+const wchar_t kProxyBypassList[] = L"proxy.bypass_list";
+
+} // namespace prefs
diff --git a/chrome/common/pref_names.h b/chrome/common/pref_names.h
new file mode 100644
index 0000000..9897ec0
--- /dev/null
+++ b/chrome/common/pref_names.h
@@ -0,0 +1,353 @@
+// Copyright (c) 2010 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.
+
+// Constants for the names of various preferences, for easier changing.
+
+#ifndef CHROME_COMMON_PREF_NAMES_H_
+#define CHROME_COMMON_PREF_NAMES_H_
+
+#include "build/build_config.h"
+
+namespace prefs {
+
+// Profile prefs
+extern const wchar_t kHomePageIsNewTabPage[];
+extern const wchar_t kHomePage[];
+extern const wchar_t kSessionExitedCleanly[];
+extern const wchar_t kRestoreOnStartup[];
+extern const wchar_t kURLsToRestoreOnStartup[];
+extern const wchar_t kApplicationLocale[];
+extern const wchar_t kDefaultCharset[];
+extern const wchar_t kAcceptLanguages[];
+extern const wchar_t kStaticEncodings[];
+extern const wchar_t kPopupWhitelistedHosts[];
+extern const wchar_t kShowBookmarkBar[];
+extern const wchar_t kWebKitStandardFontIsSerif[];
+extern const wchar_t kWebKitFixedFontFamily[];
+extern const wchar_t kWebKitSerifFontFamily[];
+extern const wchar_t kWebKitSansSerifFontFamily[];
+extern const wchar_t kWebKitCursiveFontFamily[];
+extern const wchar_t kWebKitFantasyFontFamily[];
+extern const wchar_t kWebKitDefaultFontSize[];
+extern const wchar_t kWebKitDefaultFixedFontSize[];
+extern const wchar_t kWebKitMinimumFontSize[];
+extern const wchar_t kWebKitMinimumLogicalFontSize[];
+extern const wchar_t kWebKitJavascriptEnabled[];
+extern const wchar_t kWebKitWebSecurityEnabled[];
+extern const wchar_t kWebKitJavascriptCanOpenWindowsAutomatically[];
+extern const wchar_t kWebKitLoadsImagesAutomatically[];
+extern const wchar_t kWebKitPluginsEnabled[];
+extern const wchar_t kWebKitDomPasteEnabled[];
+extern const wchar_t kWebKitShrinksStandaloneImagesToFit[];
+extern const wchar_t kWebKitInspectorSettings[];
+extern const wchar_t kWebKitUsesUniversalDetector[];
+extern const wchar_t kWebKitTextAreasAreResizable[];
+extern const wchar_t kWebKitJavaEnabled[];
+extern const wchar_t kWebkitTabsToLinks[];
+extern const wchar_t kPasswordManagerEnabled[];
+extern const wchar_t kFormAutofillEnabled[]; // OBSOLETE
+extern const wchar_t kSafeBrowsingEnabled[];
+extern const wchar_t kSearchSuggestEnabled[];
+extern const wchar_t kCookieBehavior[]; // OBSOLETE
+extern const wchar_t kDefaultSearchProviderSearchURL[];
+extern const wchar_t kDefaultSearchProviderSuggestURL[];
+extern const wchar_t kDefaultSearchProviderName[];
+extern const wchar_t kDefaultSearchProviderID[];
+extern const wchar_t kDefaultSearchProviderPrepopulateID[];
+extern const wchar_t kSearchProviderOverrides[];
+extern const wchar_t kSearchProviderOverridesVersion[];
+extern const wchar_t kPromptForDownload[];
+extern const wchar_t kAlternateErrorPagesEnabled[];
+extern const wchar_t kDnsPrefetchingEnabled[];
+extern const wchar_t kDnsStartupPrefetchList[];
+extern const wchar_t kDnsHostReferralList[];
+extern const wchar_t kCookiePromptExpanded[];
+#if defined(USE_NSS)
+extern const wchar_t kCertRevocationCheckingEnabled[];
+extern const wchar_t kSSL2Enabled[];
+extern const wchar_t kSSL3Enabled[];
+extern const wchar_t kTLS1Enabled[];
+#endif
+#if defined(OS_CHROMEOS)
+extern const wchar_t kTapToClickEnabled[];
+extern const wchar_t kVertEdgeScrollEnabled[];
+extern const wchar_t kTouchpadSpeedFactor[];
+extern const wchar_t kTouchpadSensitivity[];
+extern const wchar_t kLanguageCurrentInputMethod[];
+extern const wchar_t kLanguagePreviousInputMethod[];
+extern const wchar_t kLanguageHotkeyNextEngineInMenu[];
+extern const wchar_t kLanguageHotkeyPreviousEngine[];
+extern const wchar_t kLanguagePreferredLanguages[];
+extern const wchar_t kLanguagePreloadEngines[];
+extern const wchar_t kLanguageChewingAutoShiftCur[];
+extern const wchar_t kLanguageChewingAddPhraseDirection[];
+extern const wchar_t kLanguageChewingEasySymbolInput[];
+extern const wchar_t kLanguageChewingEscCleanAllBuf[];
+extern const wchar_t kLanguageChewingForceLowercaseEnglish[];
+extern const wchar_t kLanguageChewingPlainZhuyin[];
+extern const wchar_t kLanguageChewingPhraseChoiceRearward[];
+extern const wchar_t kLanguageChewingSpaceAsSelection[];
+extern const wchar_t kLanguageChewingMaxChiSymbolLen[];
+extern const wchar_t kLanguageChewingCandPerPage[];
+extern const wchar_t kLanguageChewingKeyboardType[];
+extern const wchar_t kLanguageChewingSelKeys[];
+extern const wchar_t kLanguageChewingHsuSelKeyType[];
+extern const wchar_t kLanguageHangulKeyboard[];
+extern const wchar_t kLanguageHangulHanjaKeys[];
+extern const wchar_t kLanguagePinyinCorrectPinyin[];
+extern const wchar_t kLanguagePinyinFuzzyPinyin[];
+extern const wchar_t kLanguagePinyinLookupTablePageSize[];
+extern const wchar_t kLanguagePinyinShiftSelectCandidate[];
+extern const wchar_t kLanguagePinyinMinusEqualPage[];
+extern const wchar_t kLanguagePinyinCommaPeriodPage[];
+extern const wchar_t kLanguagePinyinAutoCommit[];
+extern const wchar_t kLanguagePinyinDoublePinyin[];
+extern const wchar_t kLanguagePinyinDoublePinyinSchema[];
+extern const wchar_t kLanguagePinyinInitChinese[];
+extern const wchar_t kLanguagePinyinInitFull[];
+extern const wchar_t kLanguagePinyinInitFullPunct[];
+extern const wchar_t kLanguagePinyinInitSimplifiedChinese[];
+extern const wchar_t kLanguagePinyinTradCandidate[];
+extern const wchar_t kLanguageMozcPreeditMethod[];
+extern const wchar_t kLanguageMozcSessionKeymap[];
+extern const wchar_t kLanguageMozcPunctuationMethod[];
+extern const wchar_t kLanguageMozcSymbolMethod[];
+extern const wchar_t kLanguageMozcSpaceCharacterForm[];
+extern const wchar_t kLanguageMozcHistoryLearningLevel[];
+extern const wchar_t kLanguageMozcSelectionShortcut[];
+extern const wchar_t kLanguageMozcShiftKeyModeSwitch[];
+extern const wchar_t kLanguageMozcNumpadCharacterForm[];
+extern const wchar_t kLanguageMozcIncognitoMode[];
+extern const wchar_t kLanguageMozcUseAutoImeTurnOff[];
+extern const wchar_t kLanguageMozcUseDateConversion[];
+extern const wchar_t kLanguageMozcUseSingleKanjiConversion[];
+extern const wchar_t kLanguageMozcUseSymbolConversion[];
+extern const wchar_t kLanguageMozcUseNumberConversion[];
+extern const wchar_t kLanguageMozcUseHistorySuggest[];
+extern const wchar_t kLanguageMozcUseDictionarySuggest[];
+extern const wchar_t kLanguageMozcSuggestionsSize[];
+extern const wchar_t kAccessibilityEnabled[];
+extern const wchar_t kLabsAdvancedFilesystemEnabled[];
+extern const wchar_t kLabsMediaplayerEnabled[];
+#endif
+extern const wchar_t kIpcDisabledMessages[];
+extern const wchar_t kShowHomeButton[];
+extern const wchar_t kShowPageOptionsButtons[];
+extern const wchar_t kRecentlySelectedEncoding[];
+extern const wchar_t kDeleteBrowsingHistory[];
+extern const wchar_t kDeleteDownloadHistory[];
+extern const wchar_t kDeleteCache[];
+extern const wchar_t kDeleteCookies[];
+extern const wchar_t kDeletePasswords[];
+extern const wchar_t kDeleteFormData[];
+extern const wchar_t kEnableSpellCheck[];
+extern const wchar_t kEnableAutoSpellCorrect[];
+extern const wchar_t kDeleteTimePeriod[];
+extern const wchar_t kPrintingPageHeaderLeft[];
+extern const wchar_t kPrintingPageHeaderCenter[];
+extern const wchar_t kPrintingPageHeaderRight[];
+extern const wchar_t kPrintingPageFooterLeft[];
+extern const wchar_t kPrintingPageFooterCenter[];
+extern const wchar_t kPrintingPageFooterRight[];
+#if defined(TOOLKIT_USES_GTK)
+extern const wchar_t kUsesSystemTheme[];
+#endif
+extern const wchar_t kCurrentThemePackFilename[];
+extern const wchar_t kCurrentThemeID[];
+extern const wchar_t kCurrentThemeImages[];
+extern const wchar_t kCurrentThemeColors[];
+extern const wchar_t kCurrentThemeTints[];
+extern const wchar_t kCurrentThemeDisplayProperties[];
+extern const wchar_t kExtensionsUIDeveloperMode[];
+extern const wchar_t kExtensionToolbarSize[];
+extern const wchar_t kPluginsLastInternalDirectory[];
+extern const wchar_t kPluginsPluginsList[];
+extern const wchar_t kPluginsPluginsBlacklist[];
+extern const wchar_t kPluginsEnabledInternalPDF[];
+extern const wchar_t kCheckDefaultBrowser[];
+#if defined(OS_MACOSX)
+extern const wchar_t kShowUpdatePromotionInfoBar[];
+#endif
+extern const wchar_t kUseCustomChromeFrame[];
+extern const wchar_t kShowOmniboxSearchHint[];
+extern const wchar_t kNTPPromoViewsRemaining[];
+extern const wchar_t kDesktopNotificationDefaultContentSetting[];
+extern const wchar_t kDesktopNotificationAllowedOrigins[];
+extern const wchar_t kDesktopNotificationDeniedOrigins[];
+extern const wchar_t kDefaultContentSettings[];
+extern const wchar_t kPerHostContentSettings[]; // OBSOLETE
+extern const wchar_t kContentSettingsVersion[];
+extern const wchar_t kContentSettingsPatterns[];
+extern const wchar_t kBlockThirdPartyCookies[];
+extern const wchar_t kClearSiteDataOnExit[];
+extern const wchar_t kPerHostZoomLevels[];
+extern const wchar_t kAutoFillEnabled[];
+extern const wchar_t kAutoFillAuxiliaryProfilesEnabled[];
+extern const wchar_t kAutoFillDialogPlacement[];
+extern const wchar_t kAutoFillPositiveUploadRate[];
+extern const wchar_t kAutoFillNegativeUploadRate[];
+
+extern const wchar_t kUseVerticalTabs[];
+extern const wchar_t kEnableTranslate[];
+extern const wchar_t kPinnedTabs[];
+
+// Local state
+extern const wchar_t kMetricsClientID[];
+extern const wchar_t kMetricsSessionID[];
+extern const wchar_t kMetricsClientIDTimestamp[];
+extern const wchar_t kMetricsReportingEnabled[];
+extern const wchar_t kMetricsInitialLogs[];
+extern const wchar_t kMetricsOngoingLogs[];
+
+extern const wchar_t kProfileMetrics[];
+extern const wchar_t kProfilePrefix[];
+
+extern const wchar_t kStabilityExitedCleanly[];
+extern const wchar_t kStabilityStatsVersion[];
+extern const wchar_t kStabilityStatsBuildTime[];
+extern const wchar_t kStabilitySessionEndCompleted[];
+extern const wchar_t kStabilityLaunchCount[];
+extern const wchar_t kStabilityCrashCount[];
+extern const wchar_t kStabilityIncompleteSessionEndCount[];
+extern const wchar_t kStabilityPageLoadCount[];
+extern const wchar_t kStabilityRendererCrashCount[];
+extern const wchar_t kStabilityExtensionRendererCrashCount[];
+extern const wchar_t kStabilityLaunchTimeSec[];
+extern const wchar_t kStabilityLastTimestampSec[];
+extern const wchar_t kStabilityRendererHangCount[];
+extern const wchar_t kStabilityChildProcessCrashCount[];
+
+extern const wchar_t kStabilityBreakpadRegistrationSuccess[];
+extern const wchar_t kStabilityBreakpadRegistrationFail[];
+extern const wchar_t kStabilityDebuggerPresent[];
+extern const wchar_t kStabilityDebuggerNotPresent[];
+
+extern const wchar_t kStabilityPluginStats[];
+extern const wchar_t kStabilityPluginName[];
+extern const wchar_t kStabilityPluginLaunches[];
+extern const wchar_t kStabilityPluginInstances[];
+extern const wchar_t kStabilityPluginCrashes[];
+
+extern const wchar_t kUninstallMetricsPageLoadCount[];
+extern const wchar_t kUninstallLaunchCount[];
+
+extern const wchar_t kUninstallMetricsInstallDate[];
+extern const wchar_t kUninstallMetricsUptimeSec[];
+extern const wchar_t kUninstallLastLaunchTimeSec[];
+extern const wchar_t kUninstallLastObservedRunTimeSec[];
+
+extern const wchar_t kBrowserWindowPlacement[];
+extern const wchar_t kTaskManagerWindowPlacement[];
+extern const wchar_t kPageInfoWindowPlacement[];
+extern const wchar_t kKeywordEditorWindowPlacement[];
+extern const wchar_t kPreferencesWindowPlacement[];
+extern const wchar_t kMemoryCacheSize[];
+
+extern const wchar_t kDownloadDefaultDirectory[];
+extern const wchar_t kDownloadExtensionsToOpen[];
+extern const wchar_t kDownloadDirUpgraded[];
+
+extern const wchar_t kSaveFileDefaultDirectory[];
+
+extern const wchar_t kSelectFileLastDirectory[];
+
+extern const wchar_t kHungPluginDetectFrequency[];
+extern const wchar_t kPluginMessageResponseTimeout[];
+
+extern const wchar_t kSpellCheckDictionary[];
+
+extern const wchar_t kExcludedSchemes[];
+
+extern const wchar_t kSafeBrowsingClientKey[];
+extern const wchar_t kSafeBrowsingWrappedKey[];
+
+extern const wchar_t kOptionsWindowLastTabIndex[];
+extern const wchar_t kContentSettingsWindowLastTabIndex[];
+extern const wchar_t kCertificateManagerWindowLastTabIndex[];
+extern const wchar_t kShouldShowFirstRunBubble[];
+extern const wchar_t kShouldUseOEMFirstRunBubble[];
+extern const wchar_t kShouldUseMinimalFirstRunBubble[];
+extern const wchar_t kShouldShowWelcomePage[];
+
+extern const wchar_t kLastKnownGoogleURL[];
+extern const wchar_t kLastKnownIntranetRedirectOrigin[];
+
+extern const wchar_t kCountryIDAtInstall[];
+extern const wchar_t kGeoIDAtInstall[]; // OBSOLETE
+
+extern const wchar_t kShutdownType[];
+extern const wchar_t kShutdownNumProcesses[];
+extern const wchar_t kShutdownNumProcessesSlow[];
+
+extern const wchar_t kRestartLastSessionOnShutdown[];
+
+extern const wchar_t kNumBookmarksOnBookmarkBar[];
+extern const wchar_t kNumFoldersOnBookmarkBar[];
+extern const wchar_t kNumBookmarksInOtherBookmarkFolder[];
+extern const wchar_t kNumFoldersInOtherBookmarkFolder[];
+
+extern const wchar_t kNumKeywords[];
+
+extern const wchar_t kDisableVideoAndChat[];
+
+extern const wchar_t kDisableExtensions[];
+extern const wchar_t kShowExtensionShelf[];
+extern const wchar_t kBrowserActionContainerWidth[];
+
+extern const wchar_t kLastExtensionsUpdateCheck[];
+extern const wchar_t kNextExtensionsUpdateCheck[];
+
+extern const wchar_t kExtensionBlacklistUpdateVersion[];
+
+extern const wchar_t kNTPMostVisitedURLsBlacklist[];
+extern const wchar_t kNTPMostVisitedPinnedURLs[];
+extern const wchar_t kNTPTipsCache[];
+extern const wchar_t kNTPTipsCacheUpdate[];
+extern const wchar_t kNTPTipsServer[];
+extern const wchar_t kNTPShownSections[];
+extern const wchar_t kNTPPrefVersion[];
+
+extern const wchar_t kDevToolsOpenDocked[];
+extern const wchar_t kDevToolsSplitLocation[];
+
+extern const wchar_t kSyncLastSyncedTime[];
+extern const wchar_t kSyncHasSetupCompleted[];
+extern const wchar_t kKeepEverythingSynced[];
+extern const wchar_t kSyncBookmarks[];
+extern const wchar_t kSyncPasswords[];
+extern const wchar_t kSyncPreferences[];
+extern const wchar_t kSyncAutofill[];
+extern const wchar_t kSyncThemes[];
+extern const wchar_t kSyncTypedUrls[];
+extern const wchar_t kSyncExtensions[];
+extern const wchar_t kSyncManaged[];
+
+extern const wchar_t kWebAppCreateOnDesktop[];
+extern const wchar_t kWebAppCreateInAppsMenu[];
+extern const wchar_t kWebAppCreateInQuickLaunchBar[];
+
+extern const wchar_t kGeolocationAccessToken[];
+extern const wchar_t kGeolocationDefaultContentSetting[];
+extern const wchar_t kGeolocationContentSettings[];
+
+extern const wchar_t kLoginDatabaseMigrated[];
+
+extern const wchar_t kCloudPrintServiceURL[];
+extern const wchar_t kCloudPrintProxyId[];
+extern const wchar_t kCloudPrintAuthToken[];
+extern const wchar_t kCloudPrintXMPPAuthToken[];
+extern const wchar_t kCloudPrintEmail[];
+extern const wchar_t kCloudPrintPrintSystemSettings[];
+
+extern const wchar_t kNoProxyServer[];
+extern const wchar_t kProxyAutoDetect[];
+extern const wchar_t kProxyServer[];
+extern const wchar_t kProxyPacUrl[];
+extern const wchar_t kProxyBypassList[];
+
+extern const wchar_t kRegisteredBackgroundContents[];
+
+} // namespace prefs
+
+#endif // CHROME_COMMON_PREF_NAMES_H_
diff --git a/chrome/common/pref_store.h b/chrome/common/pref_store.h
new file mode 100644
index 0000000..959c412
--- /dev/null
+++ b/chrome/common/pref_store.h
@@ -0,0 +1,49 @@
+// Copyright (c) 2010 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_COMMON_PREF_STORE_H_
+#define CHROME_COMMON_PREF_STORE_H_
+
+class DictionaryValue;
+
+// This is an abstract interface for reading and writing from/to a persistent
+// preference store, used by |PrefService|. An implementation using a JSON file
+// can be found in |JsonPrefStore|, while an implementation without any backing
+// store (currently used for testing) can be found in |DummyPrefStore|.
+class PrefStore {
+ public:
+ // Unique integer code for each type of error so we can report them
+ // distinctly in a histogram.
+ // NOTE: Don't change the order here as it will change the server's meaning
+ // of the histogram.
+ enum PrefReadError {
+ PREF_READ_ERROR_NONE = 0,
+ PREF_READ_ERROR_JSON_PARSE,
+ PREF_READ_ERROR_JSON_TYPE,
+ PREF_READ_ERROR_ACCESS_DENIED,
+ PREF_READ_ERROR_FILE_OTHER,
+ PREF_READ_ERROR_FILE_LOCKED,
+ PREF_READ_ERROR_NO_FILE,
+ PREF_READ_ERROR_JSON_REPEAT,
+ PREF_READ_ERROR_OTHER
+ };
+
+ virtual ~PrefStore() { }
+
+ // Whether the store is in a pseudo-read-only mode where changes are not
+ // actually persisted to disk. This happens in some cases when there are
+ // read errors during startup.
+ virtual bool ReadOnly() { return true; }
+
+ virtual DictionaryValue* prefs() = 0;
+
+ virtual PrefReadError ReadPrefs() = 0;
+
+ virtual bool WritePrefs() { return true; }
+
+ virtual void ScheduleWritePrefs() { }
+};
+
+#endif // CHROME_COMMON_PREF_STORE_H_
+
diff --git a/chrome/common/process_watcher.h b/chrome/common/process_watcher.h
new file mode 100644
index 0000000..f764c4f
--- /dev/null
+++ b/chrome/common/process_watcher.h
@@ -0,0 +1,44 @@
+// Copyright (c) 2006-2008 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_COMMON_PROCESS_WATCHER_H_
+#define CHROME_COMMON_PROCESS_WATCHER_H_
+
+#include "build/build_config.h"
+
+#include "base/basictypes.h"
+#include "base/process_util.h"
+
+class ProcessWatcher {
+ public:
+ // This method ensures that the specified process eventually terminates, and
+ // then it closes the given process handle.
+ //
+ // It assumes that the process has already been signalled to exit, and it
+ // begins by waiting a small amount of time for it to exit. If the process
+ // does not appear to have exited, then this function starts to become
+ // aggressive about ensuring that the process terminates.
+ //
+ // On Linux this method does not block the calling thread.
+ // On OS X this method may block for up to 2 seconds.
+ //
+ // NOTE: The process handle must have been opened with the PROCESS_TERMINATE
+ // and SYNCHRONIZE permissions.
+ //
+ static void EnsureProcessTerminated(base::ProcessHandle process_handle);
+
+#if defined(OS_POSIX) && !defined(OS_MACOSX)
+ // The nicer version of EnsureProcessTerminated() that is patient and will
+ // wait for |process_handle| to finish and then reap it.
+ static void EnsureProcessGetsReaped(base::ProcessHandle process_handle);
+#endif
+
+ private:
+ // Do not instantiate this class.
+ ProcessWatcher();
+
+ DISALLOW_COPY_AND_ASSIGN(ProcessWatcher);
+};
+
+#endif // CHROME_COMMON_PROCESS_WATCHER_H_
diff --git a/chrome/common/process_watcher_mac.cc b/chrome/common/process_watcher_mac.cc
new file mode 100644
index 0000000..2702fa7
--- /dev/null
+++ b/chrome/common/process_watcher_mac.cc
@@ -0,0 +1,170 @@
+// Copyright (c) 2009 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/common/process_watcher.h"
+
+#include <errno.h>
+#include <signal.h>
+#include <sys/event.h>
+#include <sys/types.h>
+#include <sys/wait.h>
+
+#include "base/eintr_wrapper.h"
+#include "base/file_util.h"
+#include "base/time.h"
+
+namespace {
+
+const int kWaitBeforeKillSeconds = 2;
+
+// Reap |child| process. This call blocks until completion.
+void BlockingReap(pid_t child) {
+ const pid_t result = HANDLE_EINTR(waitpid(child, NULL, 0));
+ if (result == -1) {
+ PLOG(ERROR) << "waitpid(" << child << ", NULL, 0)";
+ }
+}
+
+// Waits for |timeout| seconds for the given |child| to exit and reap it. If
+// the child doesn't exit within the time specified, kills it.
+//
+// This function takes two approaches: first, it tries to use kqueue to
+// observe when the process exits. kevent can monitor a kqueue with a
+// timeout, so this method is preferred to wait for a specified period of
+// time. Once the kqueue indicates the process has exited, waitpid will reap
+// the exited child. If the kqueue doesn't provide an exit event notification,
+// before the timeout expires, or if the kqueue fails or misbehaves, the
+// process will be mercilessly killed and reaped.
+//
+// A child process passed to this function may be in one of several states:
+// running, terminated and not yet reaped, and (apparently, and unfortunately)
+// terminated and already reaped. Normally, a process will at least have been
+// asked to exit before this function is called, but this is not required.
+// If a process is terminating and unreaped, there may be a window between the
+// time that kqueue will no longer recognize it and when it becomes an actual
+// zombie that a non-blocking (WNOHANG) waitpid can reap. This condition is
+// detected when kqueue indicates that the process is not running and a
+// non-blocking waitpid fails to reap the process but indicates that it is
+// still running. In this event, a blocking attempt to reap the process
+// collects the known-dying child, preventing zombies from congregating.
+//
+// In the event that the kqueue misbehaves entirely, as it might under a
+// EMFILE condition ("too many open files", or out of file descriptors), this
+// function will forcibly kill and reap the child without delay. This
+// eliminates another potential zombie vector. (If you're out of file
+// descriptors, you're probably deep into something else, but that doesn't
+// mean that zombies be allowed to kick you while you're down.)
+//
+// The fact that this function seemingly can be called to wait on a child
+// that's not only already terminated but already reaped is a bit of a
+// problem: a reaped child's pid can be reclaimed and may refer to a distinct
+// process in that case. The fact that this function can seemingly be called
+// to wait on a process that's not even a child is also a problem: kqueue will
+// work in that case, but waitpid won't, and killing a non-child might not be
+// the best approach.
+void WaitForChildToDie(pid_t child, int timeout) {
+ DCHECK(child > 0);
+ DCHECK(timeout > 0);
+
+ // DON'T ADD ANY EARLY RETURNS TO THIS FUNCTION without ensuring that
+ // |child| has been reaped. Specifically, even if a kqueue, kevent, or other
+ // call fails, this function should fall back to the last resort of trying
+ // to kill and reap the process. Not observing this rule will resurrect
+ // zombies.
+
+ int result;
+
+ int kq = HANDLE_EINTR(kqueue());
+ if (kq == -1) {
+ PLOG(ERROR) << "kqueue()";
+ } else {
+ file_util::ScopedFD auto_close_kq(&kq);
+
+ struct kevent change = {0};
+ EV_SET(&change, child, EVFILT_PROC, EV_ADD, NOTE_EXIT, 0, NULL);
+ result = HANDLE_EINTR(kevent(kq, &change, 1, NULL, 0, NULL));
+
+ if (result == -1) {
+ if (errno != ESRCH) {
+ PLOG(ERROR) << "kevent (setup " << child << ")";
+ } else {
+ // At this point, one of the following has occurred:
+ // 1. The process has died but has not yet been reaped.
+ // 2. The process has died and has already been reaped.
+ // 3. The process is in the process of dying. It's no longer
+ // kqueueable, but it may not be waitable yet either. Mark calls
+ // this case the "zombie death race".
+
+ result = HANDLE_EINTR(waitpid(child, NULL, WNOHANG));
+
+ if (result != 0) {
+ // A positive result indicates case 1. waitpid succeeded and reaped
+ // the child. A result of -1 indicates case 2. The child has already
+ // been reaped. In both of these cases, no further action is
+ // necessary.
+ return;
+ }
+
+ // |result| is 0, indicating case 3. The process will be waitable in
+ // short order. Fall back out of the kqueue code to kill it (for good
+ // measure) and reap it.
+ }
+ } else {
+ // Keep track of the elapsed time to be able to restart kevent if it's
+ // interrupted.
+ base::TimeDelta remaining_delta = base::TimeDelta::FromSeconds(timeout);
+ base::Time deadline = base::Time::Now() + remaining_delta;
+ result = -1;
+ struct kevent event = {0};
+ while (remaining_delta.InMilliseconds() > 0) {
+ const struct timespec remaining_timespec = remaining_delta.ToTimeSpec();
+ result = kevent(kq, NULL, 0, &event, 1, &remaining_timespec);
+ if (result == -1 && errno == EINTR) {
+ remaining_delta = deadline - base::Time::Now();
+ result = 0;
+ } else {
+ break;
+ }
+ }
+
+ if (result == -1) {
+ PLOG(ERROR) << "kevent (wait " << child << ")";
+ } else if (result > 1) {
+ LOG(ERROR) << "kevent (wait " << child << "): unexpected result "
+ << result;
+ } else if (result == 1) {
+ if ((event.fflags & NOTE_EXIT) &&
+ (event.ident == static_cast<uintptr_t>(child))) {
+ // The process is dead or dying. This won't block for long, if at
+ // all.
+ BlockingReap(child);
+ return;
+ } else {
+ LOG(ERROR) << "kevent (wait " << child
+ << "): unexpected event: fflags=" << event.fflags
+ << ", ident=" << event.ident;
+ }
+ }
+ }
+ }
+
+ // The child is still alive, or is very freshly dead. Be sure by sending it
+ // a signal. This is safe even if it's freshly dead, because it will be a
+ // zombie (or on the way to zombiedom) and kill will return 0 even if the
+ // signal is not delivered to a live process.
+ result = kill(child, SIGKILL);
+ if (result == -1) {
+ PLOG(ERROR) << "kill(" << child << ", SIGKILL)";
+ } else {
+ // The child is definitely on the way out now. BlockingReap won't need to
+ // wait for long, if at all.
+ BlockingReap(child);
+ }
+}
+
+} // namespace
+
+void ProcessWatcher::EnsureProcessTerminated(base::ProcessHandle process) {
+ WaitForChildToDie(process, kWaitBeforeKillSeconds);
+}
diff --git a/chrome/common/process_watcher_posix.cc b/chrome/common/process_watcher_posix.cc
new file mode 100644
index 0000000..4b13c32
--- /dev/null
+++ b/chrome/common/process_watcher_posix.cc
@@ -0,0 +1,105 @@
+// Copyright (c) 2009 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/common/process_watcher.h"
+
+#include <errno.h>
+#include <signal.h>
+#include <sys/types.h>
+#include <sys/wait.h>
+
+#include "base/eintr_wrapper.h"
+#include "base/logging.h"
+#include "base/platform_thread.h"
+
+// Return true if the given child is dead. This will also reap the process.
+// Doesn't block.
+static bool IsChildDead(pid_t child) {
+ const pid_t result = HANDLE_EINTR(waitpid(child, NULL, WNOHANG));
+ if (result == -1) {
+ PLOG(ERROR) << "waitpid(" << child << ")";
+ NOTREACHED();
+ } else if (result > 0) {
+ // The child has died.
+ return true;
+ }
+
+ return false;
+}
+
+// A thread class which waits for the given child to exit and reaps it.
+// If the child doesn't exit within a couple of seconds, kill it.
+class BackgroundReaper : public PlatformThread::Delegate {
+ public:
+ explicit BackgroundReaper(pid_t child, unsigned timeout)
+ : child_(child),
+ timeout_(timeout) {
+ }
+
+ void ThreadMain() {
+ WaitForChildToDie();
+ delete this;
+ }
+
+ void WaitForChildToDie() {
+ // Wait forever case.
+ if (timeout_ == 0) {
+ pid_t r = HANDLE_EINTR(waitpid(child_, NULL, 0));
+ if (r != child_) {
+ PLOG(ERROR) << "While waiting for " << child_
+ << " to terminate, we got the following result: " << r;
+ }
+ return;
+ }
+
+ // There's no good way to wait for a specific child to exit in a timed
+ // fashion. (No kqueue on Linux), so we just loop and sleep.
+
+ // Wait for 2 * timeout_ 500 milliseconds intervals.
+ for (unsigned i = 0; i < 2 * timeout_; ++i) {
+ PlatformThread::Sleep(500); // 0.5 seconds
+ if (IsChildDead(child_))
+ return;
+ }
+
+ if (kill(child_, SIGKILL) == 0) {
+ // SIGKILL is uncatchable. Since the signal was delivered, we can
+ // just wait for the process to die now in a blocking manner.
+ if (HANDLE_EINTR(waitpid(child_, NULL, 0)) < 0)
+ PLOG(WARNING) << "waitpid";
+ } else {
+ LOG(ERROR) << "While waiting for " << child_ << " to terminate we"
+ << " failed to deliver a SIGKILL signal (" << errno << ").";
+ }
+ }
+
+ private:
+ const pid_t child_;
+ // Number of seconds to wait, if 0 then wait forever and do not attempt to
+ // kill |child_|.
+ const unsigned timeout_;
+
+ DISALLOW_COPY_AND_ASSIGN(BackgroundReaper);
+};
+
+// static
+void ProcessWatcher::EnsureProcessTerminated(base::ProcessHandle process) {
+ // If the child is already dead, then there's nothing to do.
+ if (IsChildDead(process))
+ return;
+
+ const unsigned timeout = 2; // seconds
+ BackgroundReaper* reaper = new BackgroundReaper(process, timeout);
+ PlatformThread::CreateNonJoinable(0, reaper);
+}
+
+// static
+void ProcessWatcher::EnsureProcessGetsReaped(base::ProcessHandle process) {
+ // If the child is already dead, then there's nothing to do.
+ if (IsChildDead(process))
+ return;
+
+ BackgroundReaper* reaper = new BackgroundReaper(process, 0);
+ PlatformThread::CreateNonJoinable(0, reaper);
+}
diff --git a/chrome/common/process_watcher_unittest.cc b/chrome/common/process_watcher_unittest.cc
new file mode 100644
index 0000000..af4aaa2
--- /dev/null
+++ b/chrome/common/process_watcher_unittest.cc
@@ -0,0 +1,64 @@
+// Copyright (c) 2009 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/common/process_watcher.h"
+
+#if defined(OS_POSIX)
+#include <sys/wait.h>
+
+#include "base/eintr_wrapper.h"
+#include "base/multiprocess_test.h"
+#include "base/process_util.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+class ProcessWatcherTest : public MultiProcessTest {
+};
+
+namespace {
+
+bool IsProcessDead(base::ProcessHandle child) {
+ // waitpid() will actually reap the process which is exactly NOT what we
+ // want to test for. The good thing is that if it can't find the process
+ // we'll get a nice value for errno which we can test for.
+ const pid_t result = HANDLE_EINTR(waitpid(child, NULL, WNOHANG));
+ return result == -1 && errno == ECHILD;
+}
+
+} // namespace
+
+TEST_F(ProcessWatcherTest, DelayedTermination) {
+ base::ProcessHandle child_process =
+ SpawnChild(L"process_watcher_test_never_die");
+ ProcessWatcher::EnsureProcessTerminated(child_process);
+ base::WaitForSingleProcess(child_process, 5000);
+
+ // Check that process was really killed.
+ EXPECT_TRUE(IsProcessDead(child_process));
+ base::CloseProcessHandle(child_process);
+}
+
+MULTIPROCESS_TEST_MAIN(process_watcher_test_never_die) {
+ while (1) {
+ sleep(500);
+ }
+ return 0;
+}
+
+TEST_F(ProcessWatcherTest, ImmediateTermination) {
+ base::ProcessHandle child_process =
+ SpawnChild(L"process_watcher_test_die_immediately");
+ // Give it time to die.
+ sleep(2);
+ ProcessWatcher::EnsureProcessTerminated(child_process);
+
+ // Check that process was really killed.
+ EXPECT_TRUE(IsProcessDead(child_process));
+ base::CloseProcessHandle(child_process);
+}
+
+MULTIPROCESS_TEST_MAIN(process_watcher_test_die_immediately) {
+ return 0;
+}
+
+#endif // OS_POSIX
diff --git a/chrome/common/process_watcher_win.cc b/chrome/common/process_watcher_win.cc
new file mode 100644
index 0000000..ed99780
--- /dev/null
+++ b/chrome/common/process_watcher_win.cc
@@ -0,0 +1,95 @@
+// Copyright (c) 2010 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/common/process_watcher.h"
+
+#include "base/scoped_ptr.h"
+#include "base/env_var.h"
+#include "base/message_loop.h"
+#include "base/object_watcher.h"
+#include "chrome/common/env_vars.h"
+#include "chrome/common/result_codes.h"
+
+// Maximum amount of time (in milliseconds) to wait for the process to exit.
+static const int kWaitInterval = 2000;
+
+namespace {
+
+class TimerExpiredTask : public Task, public base::ObjectWatcher::Delegate {
+ public:
+ explicit TimerExpiredTask(base::ProcessHandle process) : process_(process) {
+ watcher_.StartWatching(process_, this);
+ }
+
+ virtual ~TimerExpiredTask() {
+ if (process_) {
+ KillProcess();
+ DCHECK(!process_) << "Make sure to close the handle.";
+ }
+ }
+
+ // Task ---------------------------------------------------------------------
+
+ virtual void Run() {
+ if (process_)
+ KillProcess();
+ }
+
+ // MessageLoop::Watcher -----------------------------------------------------
+
+ virtual void OnObjectSignaled(HANDLE object) {
+ // When we're called from KillProcess, the ObjectWatcher may still be
+ // watching. the process handle, so make sure it has stopped.
+ watcher_.StopWatching();
+
+ CloseHandle(process_);
+ process_ = NULL;
+ }
+
+ private:
+ void KillProcess() {
+ scoped_ptr<base::EnvVarGetter> env(base::EnvVarGetter::Create());
+ if (env->HasEnv(env_vars::kHeadless)) {
+ // If running the distributed tests, give the renderer a little time
+ // to figure out that the channel is shutdown and unwind.
+ if (WaitForSingleObject(process_, kWaitInterval) == WAIT_OBJECT_0) {
+ OnObjectSignaled(process_);
+ return;
+ }
+ }
+
+ // OK, time to get frisky. We don't actually care when the process
+ // terminates. We just care that it eventually terminates, and that's what
+ // TerminateProcess should do for us. Don't check for the result code since
+ // it fails quite often. This should be investigated eventually.
+ base::KillProcess(process_, ResultCodes::HUNG, false);
+
+ // Now, just cleanup as if the process exited normally.
+ OnObjectSignaled(process_);
+ }
+
+ // The process that we are watching.
+ base::ProcessHandle process_;
+
+ base::ObjectWatcher watcher_;
+
+ DISALLOW_COPY_AND_ASSIGN(TimerExpiredTask);
+};
+
+} // namespace
+
+// static
+void ProcessWatcher::EnsureProcessTerminated(base::ProcessHandle process) {
+ DCHECK(process != GetCurrentProcess());
+
+ // If already signaled, then we are done!
+ if (WaitForSingleObject(process, 0) == WAIT_OBJECT_0) {
+ CloseHandle(process);
+ return;
+ }
+
+ MessageLoop::current()->PostDelayedTask(FROM_HERE,
+ new TimerExpiredTask(process),
+ kWaitInterval);
+}
diff --git a/chrome/common/property_bag.cc b/chrome/common/property_bag.cc
new file mode 100644
index 0000000..dc25961
--- /dev/null
+++ b/chrome/common/property_bag.cc
@@ -0,0 +1,55 @@
+// Copyright (c) 2006-2008 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/common/property_bag.h"
+
+PropertyBag::PropertyBag() {
+}
+
+PropertyBag::PropertyBag(const PropertyBag& other) {
+ operator=(other);
+}
+
+PropertyBag::~PropertyBag() {
+}
+
+PropertyBag& PropertyBag::operator=(const PropertyBag& other) {
+ props_.clear();
+
+ // We need to make copies of each property using the virtual copy() method.
+ for (PropertyMap::const_iterator i = other.props_.begin();
+ i != other.props_.end(); ++i)
+ props_[i->first] = linked_ptr<Prop>(i->second->copy());
+ return *this;
+}
+
+void PropertyBag::SetProperty(PropID id, Prop* prop) {
+ props_[id] = linked_ptr<Prop>(prop);
+}
+
+PropertyBag::Prop* PropertyBag::GetProperty(PropID id) {
+ PropertyMap::const_iterator found = props_.find(id);
+ if (found == props_.end())
+ return NULL;
+ return found->second.get();
+}
+
+const PropertyBag::Prop* PropertyBag::GetProperty(PropID id) const {
+ PropertyMap::const_iterator found = props_.find(id);
+ if (found == props_.end())
+ return NULL;
+ return found->second.get();
+}
+
+void PropertyBag::DeleteProperty(PropID id) {
+ PropertyMap::iterator found = props_.find(id);
+ if (found == props_.end())
+ return; // Not found, nothing to do.
+ props_.erase(found);
+}
+
+PropertyAccessorBase::PropertyAccessorBase() {
+ static PropertyBag::PropID next_id = 1;
+ prop_id_ = next_id++;
+}
diff --git a/chrome/common/property_bag.h b/chrome/common/property_bag.h
new file mode 100644
index 0000000..778d0b9
--- /dev/null
+++ b/chrome/common/property_bag.h
@@ -0,0 +1,173 @@
+// Copyright (c) 2006-2008 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_COMMON_PROPERTY_BAG_H_
+#define CHROME_COMMON_PROPERTY_BAG_H_
+
+#include <map>
+
+#include "base/basictypes.h"
+#include "base/linked_ptr.h"
+
+class PropertyAccessorBase;
+
+// A property bag holds a generalized list of arbitrary metadata called
+// properties. Each property is a class type derived from PropertyBag::Prop
+// that can bet set and retrieved.
+//
+// The property bag is not read or written directly. Instead, callers go
+// through a PropertyAccessor. The Accessor generates the unique IDs that
+// identify different properties. The Accessor is templatized to also provide
+// typesafety to the callers.
+//
+// Example:
+// // Note: you don't want to use Singleton for your Accessor if you're using
+// // a simple type like int or string as the data, since it will enforce that
+// // there is only one singleton for that type, which will conflict. If
+// // you're putting in some struct that's unique to you, go ahead.
+// PropertyAccessor<int>* my_accessor() const {
+// static PropertyAccessor<int>* accessor = NULL;
+// if (!accessor) accessor = new PropertyAccessor<int>;
+// return accessor;
+// }
+//
+// void doit(SomeObjectThatImplementsPropertyBag* object) {
+// PropertyAccessor<int>* accessor = my_accessor();
+// int* property = accessor.GetProperty(object);
+// if (property)
+// ... use property ...
+//
+// accessor.SetProperty(object, 22);
+// }
+class PropertyBag {
+ public:
+ // The type that uniquely identifies a property type.
+ typedef int PropID;
+ enum { NULL_PROP_ID = -1 }; // Invalid property ID.
+
+ // Properties are all derived from this class. They must be deletable and
+ // copyable
+ class Prop {
+ public:
+ virtual ~Prop() {}
+
+ // Copies the property and returns a pointer to the new one. The caller is
+ // responsible for managing the lifetime.
+ virtual Prop* copy() = 0;
+ };
+
+ PropertyBag();
+ PropertyBag(const PropertyBag& other);
+ virtual ~PropertyBag();
+
+ PropertyBag& operator=(const PropertyBag& other);
+
+ private:
+ friend class PropertyAccessorBase;
+
+ typedef std::map<PropID, linked_ptr<Prop> > PropertyMap;
+
+ // Used by the PropertyAccessor to set the property with the given ID.
+ // Ownership of the given pointer will be transferred to us. Any existing
+ // property matching the given ID will be deleted.
+ void SetProperty(PropID id, Prop* prop);
+
+ // Used by the PropertyAccessor to retrieve the property with the given ID.
+ // The returned pointer will be NULL if there is no match. Ownership of the
+ // pointer will stay with the property bag.
+ Prop* GetProperty(PropID id);
+ const Prop* GetProperty(PropID id) const;
+
+ // Deletes the property with the given ID from the bag if it exists.
+ void DeleteProperty(PropID id);
+
+ PropertyMap props_;
+
+ // Copy and assign is explicitly allowed for this class.
+};
+
+// PropertyAccessorBase -------------------------------------------------------
+
+// Manages getting the unique IDs to identify a property. Callers should use
+// PropertyAccessor below instead.
+class PropertyAccessorBase {
+ public:
+ PropertyAccessorBase();
+ virtual ~PropertyAccessorBase() {}
+
+ // Removes our property, if any, from the given property bag.
+ void DeleteProperty(PropertyBag* bag) {
+ bag->DeleteProperty(prop_id_);
+ }
+
+ protected:
+ void SetPropertyInternal(PropertyBag* bag, PropertyBag::Prop* prop) {
+ bag->SetProperty(prop_id_, prop);
+ }
+ PropertyBag::Prop* GetPropertyInternal(PropertyBag* bag) {
+ return bag->GetProperty(prop_id_);
+ }
+ const PropertyBag::Prop* GetPropertyInternal(const PropertyBag* bag) const {
+ return bag->GetProperty(prop_id_);
+ }
+
+ private:
+ // Identifier for this property.
+ PropertyBag::PropID prop_id_;
+
+ DISALLOW_COPY_AND_ASSIGN(PropertyAccessorBase);
+};
+
+// PropertyAccessor -----------------------------------------------------------
+
+// Provides typesafe accessor functions for a property bag, and manages the
+// unique identifiers for properties via the PropertyAccessorBase.
+template<class T>
+class PropertyAccessor : public PropertyAccessorBase {
+ public:
+ PropertyAccessor() : PropertyAccessorBase() {}
+ virtual ~PropertyAccessor() {}
+
+ // Makes a copy of the |prop| object for storage.
+ void SetProperty(PropertyBag* bag, const T& prop) {
+ SetPropertyInternal(bag, new Container(prop));
+ }
+
+ // Returns our property in the given bag or NULL if there is no match. The
+ // returned pointer's ownership will stay with the property bag.
+ T* GetProperty(PropertyBag* bag) {
+ PropertyBag::Prop* prop = GetPropertyInternal(bag);
+ if (!prop)
+ return NULL;
+ return static_cast<Container*>(prop)->get();
+ }
+ const T* GetProperty(const PropertyBag* bag) const {
+ const PropertyBag::Prop* prop = GetPropertyInternal(bag);
+ if (!prop)
+ return NULL;
+ return static_cast<const Container*>(prop)->get();
+ }
+
+ // See also DeleteProperty on thn PropertyAccessorBase.
+
+ private:
+ class Container : public PropertyBag::Prop {
+ public:
+ explicit Container(const T& data) : data_(data) {}
+
+ T* get() { return &data_; }
+ const T* get() const { return &data_; }
+
+ private:
+ virtual Prop* copy() {
+ return new Container(data_);
+ }
+
+ T data_;
+ };
+
+ DISALLOW_COPY_AND_ASSIGN(PropertyAccessor);
+};
+
+#endif // CHROME_COMMON_PROPERTY_BAG_H_
diff --git a/chrome/common/property_bag_unittest.cc b/chrome/common/property_bag_unittest.cc
new file mode 100644
index 0000000..f63bbc2
--- /dev/null
+++ b/chrome/common/property_bag_unittest.cc
@@ -0,0 +1,62 @@
+// Copyright (c) 2009 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/common/property_bag.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+TEST(PropertyBagTest, AddQueryRemove) {
+ PropertyBag bag;
+ PropertyAccessor<int> adaptor;
+
+ // Should be no match initially.
+ EXPECT_TRUE(adaptor.GetProperty(&bag) == NULL);
+
+ // Add the value and make sure we get it back.
+ const int kFirstValue = 1;
+ adaptor.SetProperty(&bag, kFirstValue);
+ ASSERT_TRUE(adaptor.GetProperty(&bag));
+ EXPECT_EQ(kFirstValue, *adaptor.GetProperty(&bag));
+
+ // Set it to a new value.
+ const int kSecondValue = 2;
+ adaptor.SetProperty(&bag, kSecondValue);
+ ASSERT_TRUE(adaptor.GetProperty(&bag));
+ EXPECT_EQ(kSecondValue, *adaptor.GetProperty(&bag));
+
+ // Remove the value and make sure it's gone.
+ adaptor.DeleteProperty(&bag);
+ EXPECT_TRUE(adaptor.GetProperty(&bag) == NULL);
+}
+
+TEST(PropertyBagTest, Copy) {
+ PropertyAccessor<int> adaptor1;
+ PropertyAccessor<double> adaptor2;
+
+ // Create a bag with property type 1 in it.
+ PropertyBag copy;
+ adaptor1.SetProperty(&copy, 22);
+
+ const int kType1Value = 10;
+ const double kType2Value = 2.7;
+ {
+ // Create a bag with property types 1 and 2 in it.
+ PropertyBag initial;
+ adaptor1.SetProperty(&initial, kType1Value);
+ adaptor2.SetProperty(&initial, kType2Value);
+
+ // Assign to the original.
+ copy = initial;
+ }
+
+ // Verify the copy got the two properties.
+ ASSERT_TRUE(adaptor1.GetProperty(&copy));
+ ASSERT_TRUE(adaptor2.GetProperty(&copy));
+ EXPECT_EQ(kType1Value, *adaptor1.GetProperty(&copy));
+ EXPECT_EQ(kType2Value, *adaptor2.GetProperty(&copy));
+
+ // Clear it out, neither property should be left.
+ copy = PropertyBag();
+ EXPECT_TRUE(adaptor1.GetProperty(&copy) == NULL);
+ EXPECT_TRUE(adaptor2.GetProperty(&copy) == NULL);
+}
diff --git a/chrome/common/ref_counted_util.h b/chrome/common/ref_counted_util.h
new file mode 100644
index 0000000..b04580e
--- /dev/null
+++ b/chrome/common/ref_counted_util.h
@@ -0,0 +1,26 @@
+// Copyright (c) 2006-2008 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_COMMON_REF_COUNTED_UTIL_H__
+#define CHROME_COMMON_REF_COUNTED_UTIL_H__
+
+#include "base/ref_counted.h"
+#include <vector>
+
+// RefCountedVector is just a vector wrapped up with
+// RefCountedThreadSafe.
+template<class T>
+class RefCountedVector
+ : public base::RefCountedThreadSafe<RefCountedVector<T> > {
+ public:
+ RefCountedVector() {}
+ explicit RefCountedVector(const std::vector<T>& initializer)
+ : data(initializer) {}
+
+ std::vector<T> data;
+
+ DISALLOW_COPY_AND_ASSIGN(RefCountedVector<T>);
+};
+
+#endif // CHROME_COMMON_REF_COUNTED_UTIL_H__
diff --git a/chrome/common/render_messages.h b/chrome/common/render_messages.h
new file mode 100644
index 0000000..e1ec6b3
--- /dev/null
+++ b/chrome/common/render_messages.h
@@ -0,0 +1,3214 @@
+// Copyright (c) 2010 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_COMMON_RENDER_MESSAGES_H_
+#define CHROME_COMMON_RENDER_MESSAGES_H_
+
+#include <map>
+#include <string>
+#include <vector>
+
+#include "app/clipboard/clipboard.h"
+#include "app/surface/transport_dib.h"
+#include "base/basictypes.h"
+#include "base/platform_file.h"
+#include "base/ref_counted.h"
+#include "base/shared_memory.h"
+#include "base/string16.h"
+#include "chrome/common/common_param_traits.h"
+#include "chrome/common/css_colors.h"
+#include "chrome/common/dom_storage_common.h"
+#include "chrome/common/edit_command.h"
+#include "chrome/common/extensions/extension_extent.h"
+#include "chrome/common/extensions/url_pattern.h"
+#include "chrome/common/font_descriptor_mac.h"
+#include "chrome/common/indexed_db_key.h"
+#include "chrome/common/navigation_gesture.h"
+#include "chrome/common/page_transition_types.h"
+#include "chrome/common/renderer_preferences.h"
+#include "chrome/common/resource_response.h"
+#include "chrome/common/translate_errors.h"
+#include "chrome/common/view_types.h"
+#include "chrome/common/serialized_script_value.h"
+#include "chrome/common/webkit_param_traits.h"
+#include "chrome/common/window_container_type.h"
+#include "gfx/native_widget_types.h"
+#include "googleurl/src/gurl.h"
+#include "ipc/ipc_message_utils.h"
+#include "ipc/ipc_platform_file.h"
+#include "media/audio/audio_io.h"
+#include "net/base/upload_data.h"
+#include "net/http/http_response_headers.h"
+#include "third_party/WebKit/WebKit/chromium/public/WebStorageArea.h"
+#include "third_party/WebKit/WebKit/chromium/public/WebTextDirection.h"
+#include "webkit/appcache/appcache_interfaces.h"
+#include "webkit/glue/context_menu.h"
+#include "webkit/glue/form_data.h"
+#include "webkit/glue/form_field.h"
+#include "webkit/glue/password_form.h"
+#include "webkit/glue/password_form_dom_manager.h"
+#include "webkit/glue/plugins/webplugin.h"
+#include "webkit/glue/plugins/webplugininfo.h"
+#include "webkit/glue/resource_loader_bridge.h"
+#include "webkit/glue/webaccessibility.h"
+#include "webkit/glue/webcookie.h"
+#include "webkit/glue/webdropdata.h"
+#include "webkit/glue/webmenuitem.h"
+#include "webkit/glue/webpreferences.h"
+
+namespace base {
+class Time;
+}
+
+class SkBitmap;
+
+// Parameters structure for ViewMsg_Navigate, which has too many data
+// parameters to be reasonably put in a predefined IPC message.
+struct ViewMsg_Navigate_Params {
+ enum NavigationType {
+ // Reload the page.
+ RELOAD,
+
+ // Reload the page, ignoring any cache entries.
+ RELOAD_IGNORING_CACHE,
+
+ // The navigation is the result of session restore and should honor the
+ // page's cache policy while restoring form state. This is set to true if
+ // restoring a tab/session from the previous session and the previous
+ // session did not crash. If this is not set and the page was restored then
+ // the page's cache policy is ignored and we load from the cache.
+ RESTORE,
+
+ // Navigation type not categorized by the other types.
+ NORMAL
+ };
+
+ // The page_id for this navigation, or -1 if it is a new navigation. Back,
+ // Forward, and Reload navigations should have a valid page_id. If the load
+ // succeeds, then this page_id will be reflected in the resultant
+ // ViewHostMsg_FrameNavigate message.
+ int32 page_id;
+
+ // If page_id is -1, then pending_history_list_offset will also be -1.
+ // Otherwise, it contains the offset into the history list corresponding to
+ // the current navigation.
+ int pending_history_list_offset;
+
+ // Informs the RenderView of where its current page contents reside in
+ // session history and the total size of the session history list.
+ int current_history_list_offset;
+ int current_history_list_length;
+
+ // The URL to load.
+ GURL url;
+
+ // The URL to send in the "Referer" header field. Can be empty if there is
+ // no referrer.
+ GURL referrer;
+
+ // The type of transition.
+ PageTransition::Type transition;
+
+ // Opaque history state (received by ViewHostMsg_UpdateState).
+ std::string state;
+
+ // Type of navigation.
+ NavigationType navigation_type;
+
+ // The time the request was created
+ base::Time request_time;
+};
+
+// Current status of the audio output stream in the browser process. Browser
+// sends information about the current playback state and error to the
+// renderer process using this type.
+struct ViewMsg_AudioStreamState_Params {
+ enum State {
+ kPlaying,
+ kPaused,
+ kError
+ };
+
+ // Carries the current playback state.
+ State state;
+};
+
+// The user has completed a find-in-page; this type defines what actions the
+// renderer should take next.
+struct ViewMsg_StopFinding_Params {
+ enum Action {
+ kClearSelection,
+ kKeepSelection,
+ kActivateSelection
+ };
+
+ // The action that should be taken when the find is completed.
+ Action action;
+};
+
+// The install state of the search provider (not installed, installed, default).
+struct ViewHostMsg_GetSearchProviderInstallState_Params {
+ enum State {
+ // Equates to an access denied error.
+ DENIED = -1,
+
+ // DON'T CHANGE THE VALUES BELOW.
+ // All of the following values are manidated by the
+ // spec for window.external.IsSearchProviderInstalled.
+
+ // The search provider is not installed.
+ NOT_INSTALLED = 0,
+
+ // The search provider is in the user's set but is not
+ INSTALLED_BUT_NOT_DEFAULT = 1,
+
+ // The search provider is set as the user's default.
+ INSTALLED_AS_DEFAULT = 2
+ };
+ State state;
+
+ ViewHostMsg_GetSearchProviderInstallState_Params()
+ : state(DENIED) {
+ }
+
+ explicit ViewHostMsg_GetSearchProviderInstallState_Params(State s)
+ : state(s) {
+ }
+
+ static ViewHostMsg_GetSearchProviderInstallState_Params Denied() {
+ return ViewHostMsg_GetSearchProviderInstallState_Params(DENIED);
+ }
+
+ static ViewHostMsg_GetSearchProviderInstallState_Params NotInstalled() {
+ return ViewHostMsg_GetSearchProviderInstallState_Params(NOT_INSTALLED);
+ }
+
+ static ViewHostMsg_GetSearchProviderInstallState_Params
+ InstallButNotDefault() {
+ return ViewHostMsg_GetSearchProviderInstallState_Params(
+ INSTALLED_BUT_NOT_DEFAULT);
+ }
+
+ static ViewHostMsg_GetSearchProviderInstallState_Params InstalledAsDefault() {
+ return ViewHostMsg_GetSearchProviderInstallState_Params(
+ INSTALLED_AS_DEFAULT);
+ }
+};
+
+
+// Parameters structure for ViewHostMsg_FrameNavigate, which has too many data
+// parameters to be reasonably put in a predefined IPC message.
+struct ViewHostMsg_FrameNavigate_Params {
+ // Page ID of this navigation. The renderer creates a new unique page ID
+ // anytime a new session history entry is created. This means you'll get new
+ // page IDs for user actions, and the old page IDs will be reloaded when
+ // iframes are loaded automatically.
+ int32 page_id;
+
+ // URL of the page being loaded.
+ GURL url;
+
+ // URL of the referrer of this load. WebKit generates this based on the
+ // source of the event that caused the load.
+ GURL referrer;
+
+ // The type of transition.
+ PageTransition::Type transition;
+
+ // Lists the redirects that occurred on the way to the current page. This
+ // vector has the same format as reported by the WebDataSource in the glue,
+ // with the current page being the last one in the list (so even when
+ // there's no redirect, there will be one entry in the list.
+ std::vector<GURL> redirects;
+
+ // Set to false if we want to update the session history but not update
+ // the browser history. E.g., on unreachable urls.
+ bool should_update_history;
+
+ // See SearchableFormData for a description of these.
+ GURL searchable_form_url;
+ std::string searchable_form_encoding;
+
+ // See password_form.h.
+ webkit_glue::PasswordForm password_form;
+
+ // Information regarding the security of the connection (empty if the
+ // connection was not secure).
+ std::string security_info;
+
+ // The gesture that initiated this navigation.
+ NavigationGesture gesture;
+
+ // Contents MIME type of main frame.
+ std::string contents_mime_type;
+
+ // True if this was a post request.
+ bool is_post;
+
+ // Whether the content of the frame was replaced with some alternate content
+ // (this can happen if the resource was insecure).
+ bool is_content_filtered;
+
+ // The status code of the HTTP request.
+ int http_status_code;
+};
+
+// Values that may be OR'd together to form the 'flags' parameter of a
+// ViewHostMsg_UpdateRect_Params structure.
+struct ViewHostMsg_UpdateRect_Flags {
+ enum {
+ IS_RESIZE_ACK = 1 << 0,
+ IS_RESTORE_ACK = 1 << 1,
+ IS_REPAINT_ACK = 1 << 2,
+ };
+ static bool is_resize_ack(int flags) {
+ return (flags & IS_RESIZE_ACK) != 0;
+ }
+ static bool is_restore_ack(int flags) {
+ return (flags & IS_RESTORE_ACK) != 0;
+ }
+ static bool is_repaint_ack(int flags) {
+ return (flags & IS_REPAINT_ACK) != 0;
+ }
+};
+
+struct ViewHostMsg_UpdateRect_Params {
+ // The bitmap to be painted into the view at the locations specified by
+ // update_rects.
+ TransportDIB::Id bitmap;
+
+ // The position and size of the bitmap.
+ gfx::Rect bitmap_rect;
+
+ // The scroll offset. Only one of these can be non-zero, and if they are
+ // both zero, then it means there is no scrolling and the scroll_rect is
+ // ignored.
+ int dx;
+ int dy;
+
+ // The rectangular region to scroll.
+ gfx::Rect scroll_rect;
+
+ // The regions of the bitmap (in view coords) that contain updated pixels.
+ // In the case of scrolling, this includes the scroll damage rect.
+ std::vector<gfx::Rect> copy_rects;
+
+ // The size of the RenderView when this message was generated. This is
+ // included so the host knows how large the view is from the perspective of
+ // the renderer process. This is necessary in case a resize operation is in
+ // progress.
+ gfx::Size view_size;
+
+ // New window locations for plugin child windows.
+ std::vector<webkit_glue::WebPluginGeometry> plugin_window_moves;
+
+ // The following describes the various bits that may be set in flags:
+ //
+ // ViewHostMsg_UpdateRect_Flags::IS_RESIZE_ACK
+ // Indicates that this is a response to a ViewMsg_Resize message.
+ //
+ // ViewHostMsg_UpdateRect_Flags::IS_RESTORE_ACK
+ // Indicates that this is a response to a ViewMsg_WasRestored message.
+ //
+ // ViewHostMsg_UpdateRect_Flags::IS_REPAINT_ACK
+ // Indicates that this is a response to a ViewMsg_Repaint message.
+ //
+ // If flags is zero, then this message corresponds to an unsoliticed paint
+ // request by the render view. Any of the above bits may be set in flags,
+ // which would indicate that this paint message is an ACK for multiple
+ // request messages.
+ int flags;
+};
+
+// Information on closing a tab. This is used both for ViewMsg_ClosePage, and
+// the corresponding ViewHostMsg_ClosePage_ACK.
+struct ViewMsg_ClosePage_Params {
+ // The identifier of the RenderProcessHost for the currently closing view.
+ //
+ // These first two parameters are technically redundant since they are
+ // needed only when processing the ACK message, and the processor
+ // theoretically knows both the process and route ID. However, this is
+ // difficult to figure out with our current implementation, so this
+ // information is duplicate here.
+ int closing_process_id;
+
+ // The route identifier for the currently closing RenderView.
+ int closing_route_id;
+
+ // True when this close is for the first (closing) tab of a cross-site
+ // transition where we switch processes. False indicates the close is for the
+ // entire tab.
+ //
+ // When true, the new_* variables below must be filled in. Otherwise they must
+ // both be -1.
+ bool for_cross_site_transition;
+
+ // The identifier of the RenderProcessHost for the new view attempting to
+ // replace the closing one above. This must be valid when
+ // for_cross_site_transition is set, and must be -1 otherwise.
+ int new_render_process_host_id;
+
+ // The identifier of the *request* the new view made that is causing the
+ // cross-site transition. This is *not* a route_id, but the request that we
+ // will resume once the ACK from the closing view has been received. This
+ // must be valid when for_cross_site_transition is set, and must be -1
+ // otherwise.
+ int new_request_id;
+};
+
+// Parameters for a resource request.
+struct ViewHostMsg_Resource_Request {
+ // The request method: GET, POST, etc.
+ std::string method;
+
+ // The requested URL.
+ GURL url;
+
+ // Usually the URL of the document in the top-level window, which may be
+ // checked by the third-party cookie blocking policy. Leaving it empty may
+ // lead to undesired cookie blocking. Third-party cookie blocking can be
+ // bypassed by setting first_party_for_cookies = url, but this should ideally
+ // only be done if there really is no way to determine the correct value.
+ GURL first_party_for_cookies;
+
+ // The referrer to use (may be empty).
+ GURL referrer;
+
+ // The origin of the frame that is associated with this request. This is used
+ // to update our insecure content state.
+ std::string frame_origin;
+
+ // The origin of the main frame (top-level frame) that is associated with this
+ // request. This is used to update our insecure content state.
+ std::string main_frame_origin;
+
+ // Additional HTTP request headers.
+ std::string headers;
+
+ // URLRequest load flags (0 by default).
+ int load_flags;
+
+ // Unique ID of process that originated this request. For normal renderer
+ // requests, this will be the ID of the renderer. For plugin requests routed
+ // through the renderer, this will be the plugin's ID.
+ int origin_child_id;
+
+ // What this resource load is for (main frame, sub-frame, sub-resource,
+ // object).
+ ResourceType::Type resource_type;
+
+ // Used by plugin->browser requests to get the correct URLRequestContext.
+ uint32 request_context;
+
+ // Indicates which frame (or worker context) the request is being loaded into,
+ // or kNoHostId.
+ int appcache_host_id;
+
+ // Optional upload data (may be null).
+ scoped_refptr<net::UploadData> upload_data;
+
+ // The following two members are specified if the request is initiated by
+ // a plugin like Gears.
+
+ // Contains the id of the host renderer.
+ int host_renderer_id;
+
+ // Contains the id of the host render view.
+ int host_render_view_id;
+};
+
+// Parameters for a render request.
+struct ViewMsg_Print_Params {
+ // Physical size of the page, including non-printable margins,
+ // in pixels according to dpi.
+ gfx::Size page_size;
+
+ // In pixels according to dpi_x and dpi_y.
+ gfx::Size printable_size;
+
+ // The y-offset of the printable area, in pixels according to dpi.
+ int margin_top;
+
+ // The x-offset of the printable area, in pixels according to dpi.
+ int margin_left;
+
+ // Specifies dots per inch.
+ double dpi;
+
+ // Minimum shrink factor. See PrintSettings::min_shrink for more information.
+ double min_shrink;
+
+ // Maximum shrink factor. See PrintSettings::max_shrink for more information.
+ double max_shrink;
+
+ // Desired apparent dpi on paper.
+ int desired_dpi;
+
+ // Cookie for the document to ensure correctness.
+ int document_cookie;
+
+ // Should only print currently selected text.
+ bool selection_only;
+
+ // Warning: do not compare document_cookie.
+ bool Equals(const ViewMsg_Print_Params& rhs) const {
+ return page_size == rhs.page_size &&
+ printable_size == rhs.printable_size &&
+ margin_top == rhs.margin_top &&
+ margin_left == rhs.margin_left &&
+ dpi == rhs.dpi &&
+ min_shrink == rhs.min_shrink &&
+ max_shrink == rhs.max_shrink &&
+ desired_dpi == rhs.desired_dpi &&
+ selection_only == rhs.selection_only;
+ }
+
+ // Checking if the current params is empty. Just initialized after a memset.
+ bool IsEmpty() const {
+ return !document_cookie && !desired_dpi && !max_shrink && !min_shrink &&
+ !dpi && printable_size.IsEmpty() && !selection_only &&
+ page_size.IsEmpty() && !margin_top && !margin_left;
+ }
+};
+
+struct ViewMsg_PrintPage_Params {
+ // Parameters to render the page as a printed page. It must always be the same
+ // value for all the document.
+ ViewMsg_Print_Params params;
+
+ // The page number is the indicator of the square that should be rendered
+ // according to the layout specified in ViewMsg_Print_Params.
+ int page_number;
+};
+
+struct ViewMsg_PrintPages_Params {
+ // Parameters to render the page as a printed page. It must always be the same
+ // value for all the document.
+ ViewMsg_Print_Params params;
+
+ // If empty, this means a request to render all the printed pages.
+ std::vector<int> pages;
+};
+
+// Parameters to describe a rendered page.
+struct ViewHostMsg_DidPrintPage_Params {
+ // A shared memory handle to the EMF data. This data can be quite large so a
+ // memory map needs to be used.
+ base::SharedMemoryHandle metafile_data_handle;
+
+ // Size of the metafile data.
+ uint32 data_size;
+
+ // Cookie for the document to ensure correctness.
+ int document_cookie;
+
+ // Page number.
+ int page_number;
+
+ // Shrink factor used to render this page.
+ double actual_shrink;
+
+ // The size of the page the page author specified.
+ gfx::Size page_size;
+
+ // The printable area the page author specified.
+ gfx::Rect content_area;
+
+ // True if the page has visible overlays.
+ bool has_visible_overlays;
+};
+
+// Parameters for creating an audio output stream.
+struct ViewHostMsg_Audio_CreateStream_Params {
+ // Format request for the stream.
+ AudioManager::Format format;
+
+ // Number of channels.
+ int channels;
+
+ // Sampling rate (frequency) of the output stream.
+ int sample_rate;
+
+ // Number of bits per sample;
+ int bits_per_sample;
+
+ // Number of bytes per packet. Determines the maximum number of bytes
+ // transported for each audio packet request.
+ // A value of 0 means that the audio packet size is selected automatically
+ // by the browser process.
+ uint32 packet_size;
+};
+
+// This message is used for supporting popup menus on Mac OS X using native
+// Cocoa controls. The renderer sends us this message which we use to populate
+// the popup menu.
+struct ViewHostMsg_ShowPopup_Params {
+ // Position on the screen.
+ gfx::Rect bounds;
+
+ // The height of each item in the menu.
+ int item_height;
+
+ // The size of the font to use for those items.
+ double item_font_size;
+
+ // The currently selected (displayed) item in the menu.
+ int selected_item;
+
+ // The entire list of items in the popup menu.
+ std::vector<WebMenuItem> popup_items;
+
+ // Whether items should be right-aligned.
+ bool right_aligned;
+};
+
+// Parameters for the IPC message ViewHostMsg_ScriptedPrint
+struct ViewHostMsg_ScriptedPrint_Params {
+ int routing_id;
+ gfx::NativeViewId host_window_id;
+ int cookie;
+ int expected_pages_count;
+ bool has_selection;
+ bool use_overlays;
+};
+
+// Signals a storage event.
+struct ViewMsg_DOMStorageEvent_Params {
+ // The key that generated the storage event. Null if clear() was called.
+ NullableString16 key_;
+
+ // The old value of this key. Null on clear() or if it didn't have a value.
+ NullableString16 old_value_;
+
+ // The new value of this key. Null on removeItem() or clear().
+ NullableString16 new_value_;
+
+ // The origin this is associated with.
+ string16 origin_;
+
+ // The URL of the page that caused the storage event.
+ GURL url_;
+
+ // The storage type of this event.
+ DOMStorageType storage_type_;
+};
+
+// Used to open an indexed database.
+struct ViewHostMsg_IndexedDatabaseOpen_Params {
+ // The routing ID of the view initiating the open.
+ int32 routing_id_;
+
+ // The response should have this id.
+ int32 response_id_;
+
+ // The origin doing the initiating.
+ string16 origin_;
+
+ // The name of the database.
+ string16 name_;
+
+ // The description of the database.
+ string16 description_;
+};
+
+// Used to create an object store.
+struct ViewHostMsg_IDBDatabaseCreateObjectStore_Params {
+ // The response should have this id.
+ int32 response_id_;
+
+ // The name of the object store.
+ string16 name_;
+
+ // The keyPath of the object store.
+ NullableString16 key_path_;
+
+ // Whether the object store created should have a key generator.
+ bool auto_increment_;
+
+ // The database the object store belongs to.
+ int32 idb_database_id_;
+};
+
+// Used to create an index.
+struct ViewHostMsg_IDBObjectStoreCreateIndex_Params {
+ // The response should have this id.
+ int32 response_id_;
+
+ // The name of the index.
+ string16 name_;
+
+ // The keyPath of the index.
+ NullableString16 key_path_;
+
+ // Whether the index created has unique keys.
+ bool unique_;
+
+ // The object store the index belongs to.
+ int32 idb_object_store_id_;
+};
+
+// Allows an extension to execute code in a tab.
+struct ViewMsg_ExecuteCode_Params {
+ ViewMsg_ExecuteCode_Params() {}
+ ViewMsg_ExecuteCode_Params(int request_id, const std::string& extension_id,
+ const std::vector<URLPattern>& host_permissions,
+ bool is_javascript, const std::string& code,
+ bool all_frames)
+ : request_id(request_id), extension_id(extension_id),
+ host_permissions(host_permissions), is_javascript(is_javascript),
+ code(code), all_frames(all_frames) {
+ }
+
+ // The extension API request id, for responding.
+ int request_id;
+
+ // The ID of the requesting extension. To know which isolated world to
+ // execute the code inside of.
+ std::string extension_id;
+
+ // The host permissions of the requesting extension. So that we can check them
+ // right before injecting, to avoid any race conditions.
+ std::vector<URLPattern> host_permissions;
+
+ // Whether the code is JavaScript or CSS.
+ bool is_javascript;
+
+ // String of code to execute.
+ std::string code;
+
+ // Whether to inject into all frames, or only the root frame.
+ bool all_frames;
+};
+
+// Parameters for the message that creates a worker thread.
+struct ViewHostMsg_CreateWorker_Params {
+ // URL for the worker script.
+ GURL url;
+
+ // True if this is a SharedWorker, false if it is a dedicated Worker.
+ bool is_shared;
+
+ // Name for a SharedWorker, otherwise empty string.
+ string16 name;
+
+ // The ID of the parent document (unique within parent renderer).
+ unsigned long long document_id;
+
+ // RenderView routing id used to send messages back to the parent.
+ int render_view_route_id;
+
+ // The route ID to associate with the worker. If MSG_ROUTING_NONE is passed,
+ // a new unique ID is created and assigned to the worker.
+ int route_id;
+
+ // The ID of the parent's appcache host, only valid for dedicated workers.
+ int parent_appcache_host_id;
+
+ // The ID of the appcache the main shared worker script resource was loaded
+ // from, only valid for shared workers.
+ int64 script_resource_appcache_id;
+};
+
+// Parameters for the message that creates a desktop notification.
+struct ViewHostMsg_ShowNotification_Params {
+ // URL which is the origin that created this notification.
+ GURL origin;
+
+ // True if this is HTML
+ bool is_html;
+
+ // URL which contains the HTML contents (if is_html is true), otherwise empty.
+ GURL contents_url;
+
+ // Contents of the notification if is_html is false.
+ GURL icon_url;
+ string16 title;
+ string16 body;
+
+ // Directionality of the notification.
+ WebKit::WebTextDirection direction;
+
+ // ReplaceID if this notification should replace an existing one; may be
+ // empty if no replacement is called for.
+ string16 replace_id;
+
+ // Notification ID for sending events back for this notification.
+ int notification_id;
+};
+
+// Creates a new view via a control message since the view doesn't yet exist.
+struct ViewMsg_New_Params {
+ // The parent window's id.
+ gfx::NativeViewId parent_window;
+
+ // Renderer-wide preferences.
+ RendererPreferences renderer_preferences;
+
+ // Preferences for this view.
+ WebPreferences web_preferences;
+
+ // The ID of the view to be created.
+ int32 view_id;
+
+ // The session storage namespace ID this view should use.
+ int64 session_storage_namespace_id;
+
+ // The name of the frame associated with this view (or empty if none).
+ string16 frame_name;
+};
+
+struct ViewHostMsg_CreateWindow_Params {
+ // Routing ID of the view initiating the open.
+ int opener_id;
+
+ // True if this open request came in the context of a user gesture.
+ bool user_gesture;
+
+ // Type of window requested.
+ WindowContainerType window_container_type;
+
+ // The session storage namespace ID this view should use.
+ int64 session_storage_namespace_id;
+
+ // The name of the resulting frame that should be created (empty if none
+ // has been specified).
+ string16 frame_name;
+};
+
+struct ViewHostMsg_RunFileChooser_Params {
+ enum Mode {
+ // Requires that the file exists before allowing the user to pick it.
+ Open,
+
+ // Like Open, but allows picking multiple files to open.
+ OpenMultiple,
+
+ // Allows picking a nonexistent file, and prompts to overwrite if the file
+ // already exists.
+ Save,
+ };
+
+ Mode mode;
+
+ // Title to be used for the dialog. This may be empty for the default title,
+ // which will be either "Open" or "Save" depending on the mode.
+ string16 title;
+
+ // Default file name to select in the dialog.
+ FilePath default_file_name;
+};
+
+struct ViewMsg_ExtensionExtentInfo {
+ std::string extension_id;
+ ExtensionExtent web_extent;
+ ExtensionExtent browse_extent;
+};
+
+struct ViewMsg_ExtensionExtentsUpdated_Params {
+ // Describes the installed extension apps and the URLs they cover.
+ std::vector<ViewMsg_ExtensionExtentInfo> extension_apps;
+};
+
+// Values that may be OR'd together to form the 'flags' parameter of the
+// ViewMsg_EnablePreferredSizeChangedMode message.
+enum ViewHostMsg_EnablePreferredSizeChangedMode_Flags {
+ kPreferredSizeNothing,
+ kPreferredSizeWidth = 1 << 0,
+ // Requesting the height currently requires a polling loop in render_view.cc.
+ kPreferredSizeHeightThisIsSlow = 1 << 1,
+};
+
+namespace IPC {
+
+template <>
+struct ParamTraits<ResourceType::Type> {
+ typedef ResourceType::Type param_type;
+ static void Write(Message* m, const param_type& p) {
+ m->WriteInt(p);
+ }
+ static bool Read(const Message* m, void** iter, param_type* p) {
+ int type;
+ if (!m->ReadInt(iter, &type) || !ResourceType::ValidType(type))
+ return false;
+ *p = ResourceType::FromInt(type);
+ return true;
+ }
+ static void Log(const param_type& p, std::wstring* l) {
+ std::wstring type;
+ switch (p) {
+ case ResourceType::MAIN_FRAME:
+ type = L"MAIN_FRAME";
+ break;
+ case ResourceType::SUB_FRAME:
+ type = L"SUB_FRAME";
+ break;
+ case ResourceType::SUB_RESOURCE:
+ type = L"SUB_RESOURCE";
+ break;
+ case ResourceType::OBJECT:
+ type = L"OBJECT";
+ break;
+ case ResourceType::MEDIA:
+ type = L"MEDIA";
+ break;
+ default:
+ type = L"UNKNOWN";
+ break;
+ }
+
+ LogParam(type, l);
+ }
+};
+
+// Traits for ViewMsg_Navigate_Params structure to pack/unpack.
+template <>
+struct ParamTraits<ViewMsg_Navigate_Params> {
+ typedef ViewMsg_Navigate_Params param_type;
+ static void Write(Message* m, const param_type& p) {
+ WriteParam(m, p.page_id);
+ WriteParam(m, p.pending_history_list_offset);
+ WriteParam(m, p.current_history_list_offset);
+ WriteParam(m, p.current_history_list_length);
+ WriteParam(m, p.url);
+ WriteParam(m, p.referrer);
+ WriteParam(m, p.transition);
+ WriteParam(m, p.state);
+ WriteParam(m, p.navigation_type);
+ WriteParam(m, p.request_time);
+ }
+ static bool Read(const Message* m, void** iter, param_type* p) {
+ return
+ ReadParam(m, iter, &p->page_id) &&
+ ReadParam(m, iter, &p->pending_history_list_offset) &&
+ ReadParam(m, iter, &p->current_history_list_offset) &&
+ ReadParam(m, iter, &p->current_history_list_length) &&
+ ReadParam(m, iter, &p->url) &&
+ ReadParam(m, iter, &p->referrer) &&
+ ReadParam(m, iter, &p->transition) &&
+ ReadParam(m, iter, &p->state) &&
+ ReadParam(m, iter, &p->navigation_type) &&
+ ReadParam(m, iter, &p->request_time);
+ }
+ static void Log(const param_type& p, std::wstring* l) {
+ l->append(L"(");
+ LogParam(p.page_id, l);
+ l->append(L", ");
+ LogParam(p.url, l);
+ l->append(L", ");
+ LogParam(p.transition, l);
+ l->append(L", ");
+ LogParam(p.state, l);
+ l->append(L", ");
+ LogParam(p.navigation_type, l);
+ l->append(L", ");
+ LogParam(p.request_time, l);
+ l->append(L")");
+ }
+};
+
+template<>
+struct ParamTraits<ViewMsg_Navigate_Params::NavigationType> {
+ typedef ViewMsg_Navigate_Params::NavigationType param_type;
+ static void Write(Message* m, const param_type& p) {
+ m->WriteInt(p);
+ }
+ static bool Read(const Message* m, void** iter, param_type* p) {
+ int type;
+ if (!m->ReadInt(iter, &type))
+ return false;
+ *p = static_cast<ViewMsg_Navigate_Params::NavigationType>(type);
+ return true;
+ }
+ static void Log(const param_type& p, std::wstring* l) {
+ std::wstring event;
+ switch (p) {
+ case ViewMsg_Navigate_Params::RELOAD:
+ event = L"NavigationType_RELOAD";
+ break;
+
+ case ViewMsg_Navigate_Params::RELOAD_IGNORING_CACHE:
+ event = L"NavigationType_RELOAD_IGNORING_CACHE";
+ break;
+
+ case ViewMsg_Navigate_Params::RESTORE:
+ event = L"NavigationType_RESTORE";
+ break;
+
+ case ViewMsg_Navigate_Params::NORMAL:
+ event = L"NavigationType_NORMAL";
+ break;
+
+ default:
+ event = L"NavigationType_UNKNOWN";
+ break;
+ }
+ LogParam(event, l);
+ }
+};
+
+// Traits for FormField_Params structure to pack/unpack.
+template <>
+struct ParamTraits<webkit_glue::FormField> {
+ typedef webkit_glue::FormField param_type;
+ static void Write(Message* m, const param_type& p) {
+ WriteParam(m, p.label());
+ WriteParam(m, p.name());
+ WriteParam(m, p.value());
+ WriteParam(m, p.form_control_type());
+ WriteParam(m, p.size());
+ WriteParam(m, p.option_strings());
+ }
+ static bool Read(const Message* m, void** iter, param_type* p) {
+ string16 label, name, value, form_control_type;
+ int size = 0;
+ std::vector<string16> options;
+ bool result = ReadParam(m, iter, &label);
+ result = result && ReadParam(m, iter, &name);
+ result = result && ReadParam(m, iter, &value);
+ result = result && ReadParam(m, iter, &form_control_type);
+ result = result && ReadParam(m, iter, &size);
+ result = result && ReadParam(m, iter, &options);
+ if (!result)
+ return false;
+
+ p->set_label(label);
+ p->set_name(name);
+ p->set_value(value);
+ p->set_form_control_type(form_control_type);
+ p->set_size(size);
+ p->set_option_strings(options);
+ return true;
+ }
+ static void Log(const param_type& p, std::wstring* l) {
+ l->append(L"<FormField>");
+ }
+};
+
+// Traits for FontDescriptor structure to pack/unpack.
+template <>
+struct ParamTraits<FontDescriptor> {
+ typedef FontDescriptor param_type;
+ static void Write(Message* m, const param_type& p) {
+ WriteParam(m, p.font_name);
+ WriteParam(m, p.font_point_size);
+ }
+ static bool Read(const Message* m, void** iter, param_type* p) {
+ return(
+ ReadParam(m, iter, &p->font_name) &&
+ ReadParam(m, iter, &p->font_point_size));
+ }
+ static void Log(const param_type& p, std::wstring* l) {
+ l->append(L"<FontDescriptor>");
+ }
+};
+
+// Traits for ViewHostMsg_GetSearchProviderInstallState_Params structure to
+// pack/unpack.
+template <>
+struct ParamTraits<ViewHostMsg_GetSearchProviderInstallState_Params> {
+ typedef ViewHostMsg_GetSearchProviderInstallState_Params param_type;
+ static void Write(Message* m, const param_type& p) {
+ m->WriteInt(p.state);
+ }
+ static bool Read(const Message* m, void** iter, param_type* p) {
+ int type;
+ if (!m->ReadInt(iter, &type))
+ return false;
+ p->state = static_cast<param_type::State>(type);
+ return true;
+ }
+ static void Log(const param_type& p, std::wstring* l) {
+ std::wstring state;
+ switch (p.state) {
+ case ViewHostMsg_GetSearchProviderInstallState_Params::DENIED:
+ state = L"ViewHostMsg_GetSearchProviderInstallState_Params::DENIED";
+ break;
+ case ViewHostMsg_GetSearchProviderInstallState_Params::NOT_INSTALLED:
+ state =
+ L"ViewHostMsg_GetSearchProviderInstallState_Params::NOT_INSTALLED";
+ break;
+ case ViewHostMsg_GetSearchProviderInstallState_Params::
+ INSTALLED_BUT_NOT_DEFAULT:
+ state = L"ViewHostMsg_GetSearchProviderInstallState_Params::"
+ L"INSTALLED_BUT_NOT_DEFAULT";
+ break;
+ case ViewHostMsg_GetSearchProviderInstallState_Params::
+ INSTALLED_AS_DEFAULT:
+ state = L"ViewHostMsg_GetSearchProviderInstallState_Params::"
+ L"INSTALLED_AS_DEFAULT";
+ break;
+ default:
+ state = L"UNKNOWN";
+ break;
+ }
+ LogParam(state, l);
+ }
+};
+
+// Traits for ViewHostMsg_FrameNavigate_Params structure to pack/unpack.
+template <>
+struct ParamTraits<ViewHostMsg_FrameNavigate_Params> {
+ typedef ViewHostMsg_FrameNavigate_Params param_type;
+ static void Write(Message* m, const param_type& p) {
+ WriteParam(m, p.page_id);
+ WriteParam(m, p.url);
+ WriteParam(m, p.referrer);
+ WriteParam(m, p.transition);
+ WriteParam(m, p.redirects);
+ WriteParam(m, p.should_update_history);
+ WriteParam(m, p.searchable_form_url);
+ WriteParam(m, p.searchable_form_encoding);
+ WriteParam(m, p.password_form);
+ WriteParam(m, p.security_info);
+ WriteParam(m, p.gesture);
+ WriteParam(m, p.contents_mime_type);
+ WriteParam(m, p.is_post);
+ WriteParam(m, p.is_content_filtered);
+ WriteParam(m, p.http_status_code);
+ }
+ static bool Read(const Message* m, void** iter, param_type* p) {
+ return
+ ReadParam(m, iter, &p->page_id) &&
+ ReadParam(m, iter, &p->url) &&
+ ReadParam(m, iter, &p->referrer) &&
+ ReadParam(m, iter, &p->transition) &&
+ ReadParam(m, iter, &p->redirects) &&
+ ReadParam(m, iter, &p->should_update_history) &&
+ ReadParam(m, iter, &p->searchable_form_url) &&
+ ReadParam(m, iter, &p->searchable_form_encoding) &&
+ ReadParam(m, iter, &p->password_form) &&
+ ReadParam(m, iter, &p->security_info) &&
+ ReadParam(m, iter, &p->gesture) &&
+ ReadParam(m, iter, &p->contents_mime_type) &&
+ ReadParam(m, iter, &p->is_post) &&
+ ReadParam(m, iter, &p->is_content_filtered) &&
+ ReadParam(m, iter, &p->http_status_code);
+ }
+ static void Log(const param_type& p, std::wstring* l) {
+ l->append(L"(");
+ LogParam(p.page_id, l);
+ l->append(L", ");
+ LogParam(p.url, l);
+ l->append(L", ");
+ LogParam(p.referrer, l);
+ l->append(L", ");
+ LogParam(p.transition, l);
+ l->append(L", ");
+ LogParam(p.redirects, l);
+ l->append(L", ");
+ LogParam(p.should_update_history, l);
+ l->append(L", ");
+ LogParam(p.searchable_form_url, l);
+ l->append(L", ");
+ LogParam(p.searchable_form_encoding, l);
+ l->append(L", ");
+ LogParam(p.password_form, l);
+ l->append(L", ");
+ LogParam(p.security_info, l);
+ l->append(L", ");
+ LogParam(p.gesture, l);
+ l->append(L", ");
+ LogParam(p.contents_mime_type, l);
+ l->append(L", ");
+ LogParam(p.is_post, l);
+ l->append(L", ");
+ LogParam(p.is_content_filtered, l);
+ l->append(L", ");
+ LogParam(p.http_status_code, l);
+ l->append(L")");
+ }
+};
+
+template <>
+struct ParamTraits<ContextMenuParams> {
+ typedef ContextMenuParams param_type;
+ static void Write(Message* m, const param_type& p) {
+ WriteParam(m, p.media_type);
+ WriteParam(m, p.x);
+ WriteParam(m, p.y);
+ WriteParam(m, p.link_url);
+ WriteParam(m, p.unfiltered_link_url);
+ WriteParam(m, p.src_url);
+ WriteParam(m, p.is_image_blocked);
+ WriteParam(m, p.page_url);
+ WriteParam(m, p.frame_url);
+ WriteParam(m, p.media_flags);
+ WriteParam(m, p.selection_text);
+ WriteParam(m, p.misspelled_word);
+ WriteParam(m, p.dictionary_suggestions);
+ WriteParam(m, p.spellcheck_enabled);
+ WriteParam(m, p.is_editable);
+#if defined(OS_MACOSX)
+ WriteParam(m, p.writing_direction_default);
+ WriteParam(m, p.writing_direction_left_to_right);
+ WriteParam(m, p.writing_direction_right_to_left);
+#endif // OS_MACOSX
+ WriteParam(m, p.edit_flags);
+ WriteParam(m, p.security_info);
+ WriteParam(m, p.frame_charset);
+ WriteParam(m, p.custom_items);
+ }
+ static bool Read(const Message* m, void** iter, param_type* p) {
+ return
+ ReadParam(m, iter, &p->media_type) &&
+ ReadParam(m, iter, &p->x) &&
+ ReadParam(m, iter, &p->y) &&
+ ReadParam(m, iter, &p->link_url) &&
+ ReadParam(m, iter, &p->unfiltered_link_url) &&
+ ReadParam(m, iter, &p->src_url) &&
+ ReadParam(m, iter, &p->is_image_blocked) &&
+ ReadParam(m, iter, &p->page_url) &&
+ ReadParam(m, iter, &p->frame_url) &&
+ ReadParam(m, iter, &p->media_flags) &&
+ ReadParam(m, iter, &p->selection_text) &&
+ ReadParam(m, iter, &p->misspelled_word) &&
+ ReadParam(m, iter, &p->dictionary_suggestions) &&
+ ReadParam(m, iter, &p->spellcheck_enabled) &&
+ ReadParam(m, iter, &p->is_editable) &&
+#if defined(OS_MACOSX)
+ ReadParam(m, iter, &p->writing_direction_default) &&
+ ReadParam(m, iter, &p->writing_direction_left_to_right) &&
+ ReadParam(m, iter, &p->writing_direction_right_to_left) &&
+#endif // OS_MACOSX
+ ReadParam(m, iter, &p->edit_flags) &&
+ ReadParam(m, iter, &p->security_info) &&
+ ReadParam(m, iter, &p->frame_charset) &&
+ ReadParam(m, iter, &p->custom_items);
+ }
+ static void Log(const param_type& p, std::wstring* l) {
+ l->append(L"<ContextMenuParams>");
+ }
+};
+
+// Traits for ViewHostMsg_UpdateRect_Params structure to pack/unpack.
+template <>
+struct ParamTraits<ViewHostMsg_UpdateRect_Params> {
+ typedef ViewHostMsg_UpdateRect_Params param_type;
+ static void Write(Message* m, const param_type& p) {
+ WriteParam(m, p.bitmap);
+ WriteParam(m, p.bitmap_rect);
+ WriteParam(m, p.dx);
+ WriteParam(m, p.dy);
+ WriteParam(m, p.scroll_rect);
+ WriteParam(m, p.copy_rects);
+ WriteParam(m, p.view_size);
+ WriteParam(m, p.plugin_window_moves);
+ WriteParam(m, p.flags);
+ }
+ static bool Read(const Message* m, void** iter, param_type* p) {
+ return
+ ReadParam(m, iter, &p->bitmap) &&
+ ReadParam(m, iter, &p->bitmap_rect) &&
+ ReadParam(m, iter, &p->dx) &&
+ ReadParam(m, iter, &p->dy) &&
+ ReadParam(m, iter, &p->scroll_rect) &&
+ ReadParam(m, iter, &p->copy_rects) &&
+ ReadParam(m, iter, &p->view_size) &&
+ ReadParam(m, iter, &p->plugin_window_moves) &&
+ ReadParam(m, iter, &p->flags);
+ }
+ static void Log(const param_type& p, std::wstring* l) {
+ l->append(L"(");
+ LogParam(p.bitmap, l);
+ l->append(L", ");
+ LogParam(p.bitmap_rect, l);
+ l->append(L", ");
+ LogParam(p.dx, l);
+ l->append(L", ");
+ LogParam(p.dy, l);
+ l->append(L", ");
+ LogParam(p.scroll_rect, l);
+ l->append(L", ");
+ LogParam(p.copy_rects, l);
+ l->append(L", ");
+ LogParam(p.view_size, l);
+ l->append(L", ");
+ LogParam(p.plugin_window_moves, l);
+ l->append(L", ");
+ LogParam(p.flags, l);
+ l->append(L")");
+ }
+};
+
+template <>
+struct ParamTraits<webkit_glue::WebPluginGeometry> {
+ typedef webkit_glue::WebPluginGeometry param_type;
+ static void Write(Message* m, const param_type& p) {
+ WriteParam(m, p.window);
+ WriteParam(m, p.window_rect);
+ WriteParam(m, p.clip_rect);
+ WriteParam(m, p.cutout_rects);
+ WriteParam(m, p.rects_valid);
+ WriteParam(m, p.visible);
+ }
+ static bool Read(const Message* m, void** iter, param_type* p) {
+ return
+ ReadParam(m, iter, &p->window) &&
+ ReadParam(m, iter, &p->window_rect) &&
+ ReadParam(m, iter, &p->clip_rect) &&
+ ReadParam(m, iter, &p->cutout_rects) &&
+ ReadParam(m, iter, &p->rects_valid) &&
+ ReadParam(m, iter, &p->visible);
+ }
+ static void Log(const param_type& p, std::wstring* l) {
+ l->append(L"(");
+ LogParam(p.window, l);
+ l->append(L", ");
+ LogParam(p.window_rect, l);
+ l->append(L", ");
+ LogParam(p.clip_rect, l);
+ l->append(L", ");
+ LogParam(p.cutout_rects, l);
+ l->append(L", ");
+ LogParam(p.rects_valid, l);
+ l->append(L", ");
+ LogParam(p.visible, l);
+ l->append(L")");
+ }
+};
+
+// Traits for ViewMsg_GetPlugins_Reply structure to pack/unpack.
+template <>
+struct ParamTraits<WebPluginMimeType> {
+ typedef WebPluginMimeType param_type;
+ static void Write(Message* m, const param_type& p) {
+ WriteParam(m, p.mime_type);
+ WriteParam(m, p.file_extensions);
+ WriteParam(m, p.description);
+ }
+ static bool Read(const Message* m, void** iter, param_type* r) {
+ return
+ ReadParam(m, iter, &r->mime_type) &&
+ ReadParam(m, iter, &r->file_extensions) &&
+ ReadParam(m, iter, &r->description);
+ }
+ static void Log(const param_type& p, std::wstring* l) {
+ l->append(L"(");
+ LogParam(p.mime_type, l);
+ l->append(L", ");
+ LogParam(p.file_extensions, l);
+ l->append(L", ");
+ LogParam(p.description, l);
+ l->append(L")");
+ }
+};
+
+
+template <>
+struct ParamTraits<WebPluginInfo> {
+ typedef WebPluginInfo param_type;
+ static void Write(Message* m, const param_type& p) {
+ WriteParam(m, p.name);
+ WriteParam(m, p.path);
+ WriteParam(m, p.version);
+ WriteParam(m, p.desc);
+ WriteParam(m, p.mime_types);
+ }
+ static bool Read(const Message* m, void** iter, param_type* r) {
+ return
+ ReadParam(m, iter, &r->name) &&
+ ReadParam(m, iter, &r->path) &&
+ ReadParam(m, iter, &r->version) &&
+ ReadParam(m, iter, &r->desc) &&
+ ReadParam(m, iter, &r->mime_types);
+ }
+ static void Log(const param_type& p, std::wstring* l) {
+ l->append(L"(");
+ LogParam(p.name, l);
+ l->append(L", ");
+ l->append(L", ");
+ LogParam(p.path, l);
+ l->append(L", ");
+ LogParam(p.version, l);
+ l->append(L", ");
+ LogParam(p.desc, l);
+ l->append(L", ");
+ LogParam(p.mime_types, l);
+ l->append(L")");
+ }
+};
+
+// Traits for webkit_glue::PasswordFormDomManager::FillData.
+template <>
+struct ParamTraits<webkit_glue::PasswordFormFillData> {
+ typedef webkit_glue::PasswordFormFillData param_type;
+ static void Write(Message* m, const param_type& p) {
+ WriteParam(m, p.basic_data);
+ WriteParam(m, p.additional_logins);
+ WriteParam(m, p.wait_for_username);
+ }
+ static bool Read(const Message* m, void** iter, param_type* r) {
+ return
+ ReadParam(m, iter, &r->basic_data) &&
+ ReadParam(m, iter, &r->additional_logins) &&
+ ReadParam(m, iter, &r->wait_for_username);
+ }
+ static void Log(const param_type& p, std::wstring* l) {
+ l->append(L"<PasswordFormFillData>");
+ }
+};
+
+template<>
+struct ParamTraits<NavigationGesture> {
+ typedef NavigationGesture param_type;
+ static void Write(Message* m, const param_type& p) {
+ m->WriteInt(p);
+ }
+ static bool Read(const Message* m, void** iter, param_type* p) {
+ int type;
+ if (!m->ReadInt(iter, &type))
+ return false;
+ *p = static_cast<NavigationGesture>(type);
+ return true;
+ }
+ static void Log(const param_type& p, std::wstring* l) {
+ std::wstring event;
+ switch (p) {
+ case NavigationGestureUser:
+ event = L"GESTURE_USER";
+ break;
+ case NavigationGestureAuto:
+ event = L"GESTURE_AUTO";
+ break;
+ default:
+ event = L"GESTURE_UNKNOWN";
+ break;
+ }
+ LogParam(event, l);
+ }
+};
+
+// Traits for ViewMsg_Close_Params.
+template <>
+struct ParamTraits<ViewMsg_ClosePage_Params> {
+ typedef ViewMsg_ClosePage_Params param_type;
+ static void Write(Message* m, const param_type& p) {
+ WriteParam(m, p.closing_process_id);
+ WriteParam(m, p.closing_route_id);
+ WriteParam(m, p.for_cross_site_transition);
+ WriteParam(m, p.new_render_process_host_id);
+ WriteParam(m, p.new_request_id);
+ }
+
+ static bool Read(const Message* m, void** iter, param_type* r) {
+ return ReadParam(m, iter, &r->closing_process_id) &&
+ ReadParam(m, iter, &r->closing_route_id) &&
+ ReadParam(m, iter, &r->for_cross_site_transition) &&
+ ReadParam(m, iter, &r->new_render_process_host_id) &&
+ ReadParam(m, iter, &r->new_request_id);
+ }
+
+ static void Log(const param_type& p, std::wstring* l) {
+ l->append(L"(");
+ LogParam(p.closing_process_id, l);
+ l->append(L", ");
+ LogParam(p.closing_route_id, l);
+ l->append(L", ");
+ LogParam(p.for_cross_site_transition, l);
+ l->append(L", ");
+ LogParam(p.new_render_process_host_id, l);
+ l->append(L", ");
+ LogParam(p.new_request_id, l);
+ l->append(L")");
+ }
+};
+
+// Traits for ViewHostMsg_Resource_Request
+template <>
+struct ParamTraits<ViewHostMsg_Resource_Request> {
+ typedef ViewHostMsg_Resource_Request param_type;
+ static void Write(Message* m, const param_type& p) {
+ WriteParam(m, p.method);
+ WriteParam(m, p.url);
+ WriteParam(m, p.first_party_for_cookies);
+ WriteParam(m, p.referrer);
+ WriteParam(m, p.frame_origin);
+ WriteParam(m, p.main_frame_origin);
+ WriteParam(m, p.headers);
+ WriteParam(m, p.load_flags);
+ WriteParam(m, p.origin_child_id);
+ WriteParam(m, p.resource_type);
+ WriteParam(m, p.request_context);
+ WriteParam(m, p.appcache_host_id);
+ WriteParam(m, p.upload_data);
+ WriteParam(m, p.host_renderer_id);
+ WriteParam(m, p.host_render_view_id);
+ }
+ static bool Read(const Message* m, void** iter, param_type* r) {
+ return
+ ReadParam(m, iter, &r->method) &&
+ ReadParam(m, iter, &r->url) &&
+ ReadParam(m, iter, &r->first_party_for_cookies) &&
+ ReadParam(m, iter, &r->referrer) &&
+ ReadParam(m, iter, &r->frame_origin) &&
+ ReadParam(m, iter, &r->main_frame_origin) &&
+ ReadParam(m, iter, &r->headers) &&
+ ReadParam(m, iter, &r->load_flags) &&
+ ReadParam(m, iter, &r->origin_child_id) &&
+ ReadParam(m, iter, &r->resource_type) &&
+ ReadParam(m, iter, &r->request_context) &&
+ ReadParam(m, iter, &r->appcache_host_id) &&
+ ReadParam(m, iter, &r->upload_data) &&
+ ReadParam(m, iter, &r->host_renderer_id) &&
+ ReadParam(m, iter, &r->host_render_view_id);
+ }
+ static void Log(const param_type& p, std::wstring* l) {
+ l->append(L"(");
+ LogParam(p.method, l);
+ l->append(L", ");
+ LogParam(p.url, l);
+ l->append(L", ");
+ LogParam(p.referrer, l);
+ l->append(L", ");
+ LogParam(p.frame_origin, l);
+ l->append(L", ");
+ LogParam(p.main_frame_origin, l);
+ l->append(L", ");
+ LogParam(p.load_flags, l);
+ l->append(L", ");
+ LogParam(p.origin_child_id, l);
+ l->append(L", ");
+ LogParam(p.resource_type, l);
+ l->append(L", ");
+ LogParam(p.request_context, l);
+ l->append(L", ");
+ LogParam(p.appcache_host_id, l);
+ l->append(L", ");
+ LogParam(p.host_renderer_id, l);
+ l->append(L", ");
+ LogParam(p.host_render_view_id, l);
+ l->append(L")");
+ }
+};
+
+template <>
+struct ParamTraits<scoped_refptr<net::HttpResponseHeaders> > {
+ typedef scoped_refptr<net::HttpResponseHeaders> param_type;
+ static void Write(Message* m, const param_type& p) {
+ WriteParam(m, p.get() != NULL);
+ if (p) {
+ // Do not disclose Set-Cookie headers over IPC.
+ p->Persist(m, net::HttpResponseHeaders::PERSIST_SANS_COOKIES);
+ }
+ }
+ static bool Read(const Message* m, void** iter, param_type* r) {
+ bool has_object;
+ if (!ReadParam(m, iter, &has_object))
+ return false;
+ if (has_object)
+ *r = new net::HttpResponseHeaders(*m, iter);
+ return true;
+ }
+ static void Log(const param_type& p, std::wstring* l) {
+ l->append(L"<HttpResponseHeaders>");
+ }
+};
+
+// Traits for webkit_glue::ResourceLoaderBridge::LoadTimingInfo
+template <>
+struct ParamTraits<webkit_glue::ResourceLoaderBridge::LoadTimingInfo> {
+ typedef webkit_glue::ResourceLoaderBridge::LoadTimingInfo param_type;
+ static void Write(Message* m, const param_type& p) {
+ WriteParam(m, p.base_time.is_null());
+ if (p.base_time.is_null())
+ return;
+ WriteParam(m, p.base_time);
+ WriteParam(m, p.proxy_start);
+ WriteParam(m, p.proxy_end);
+ WriteParam(m, p.dns_start);
+ WriteParam(m, p.dns_end);
+ WriteParam(m, p.connect_start);
+ WriteParam(m, p.connect_end);
+ WriteParam(m, p.ssl_start);
+ WriteParam(m, p.ssl_end);
+ WriteParam(m, p.send_start);
+ WriteParam(m, p.send_end);
+ WriteParam(m, p.receive_headers_start);
+ WriteParam(m, p.receive_headers_end);
+ }
+ static bool Read(const Message* m, void** iter, param_type* r) {
+ bool is_null;
+ if (!ReadParam(m, iter, &is_null))
+ return false;
+ if (is_null)
+ return true;
+
+ return
+ ReadParam(m, iter, &r->base_time) &&
+ ReadParam(m, iter, &r->proxy_start) &&
+ ReadParam(m, iter, &r->proxy_end) &&
+ ReadParam(m, iter, &r->dns_start) &&
+ ReadParam(m, iter, &r->dns_end) &&
+ ReadParam(m, iter, &r->connect_start) &&
+ ReadParam(m, iter, &r->connect_end) &&
+ ReadParam(m, iter, &r->ssl_start) &&
+ ReadParam(m, iter, &r->ssl_end) &&
+ ReadParam(m, iter, &r->send_start) &&
+ ReadParam(m, iter, &r->send_end) &&
+ ReadParam(m, iter, &r->receive_headers_start) &&
+ ReadParam(m, iter, &r->receive_headers_end);
+ }
+ static void Log(const param_type& p, std::wstring* l) {
+ l->append(L"(");
+ LogParam(p.base_time, l);
+ l->append(L", ");
+ LogParam(p.proxy_start, l);
+ l->append(L", ");
+ LogParam(p.proxy_end, l);
+ l->append(L", ");
+ LogParam(p.dns_start, l);
+ l->append(L", ");
+ LogParam(p.dns_end, l);
+ l->append(L", ");
+ LogParam(p.connect_start, l);
+ l->append(L", ");
+ LogParam(p.connect_end, l);
+ l->append(L", ");
+ LogParam(p.ssl_start, l);
+ l->append(L", ");
+ LogParam(p.ssl_end, l);
+ l->append(L", ");
+ LogParam(p.send_start, l);
+ l->append(L", ");
+ LogParam(p.send_end, l);
+ l->append(L", ");
+ LogParam(p.receive_headers_start, l);
+ l->append(L", ");
+ LogParam(p.receive_headers_end, l);
+ l->append(L")");
+ }
+};
+
+// Traits for webkit_glue::ResourceLoaderBridge::ResponseInfo
+template <>
+struct ParamTraits<webkit_glue::ResourceLoaderBridge::ResponseInfo> {
+ typedef webkit_glue::ResourceLoaderBridge::ResponseInfo param_type;
+ static void Write(Message* m, const param_type& p) {
+ WriteParam(m, p.request_time);
+ WriteParam(m, p.response_time);
+ WriteParam(m, p.headers);
+ WriteParam(m, p.mime_type);
+ WriteParam(m, p.charset);
+ WriteParam(m, p.security_info);
+ WriteParam(m, p.content_length);
+ WriteParam(m, p.appcache_id);
+ WriteParam(m, p.appcache_manifest_url);
+ WriteParam(m, p.connection_id);
+ WriteParam(m, p.connection_reused);
+ WriteParam(m, p.load_timing);
+ WriteParam(m, p.was_fetched_via_spdy);
+ WriteParam(m, p.was_npn_negotiated);
+ WriteParam(m, p.was_alternate_protocol_available);
+ WriteParam(m, p.was_fetched_via_proxy);
+ }
+ static bool Read(const Message* m, void** iter, param_type* r) {
+ return
+ ReadParam(m, iter, &r->request_time) &&
+ ReadParam(m, iter, &r->response_time) &&
+ ReadParam(m, iter, &r->headers) &&
+ ReadParam(m, iter, &r->mime_type) &&
+ ReadParam(m, iter, &r->charset) &&
+ ReadParam(m, iter, &r->security_info) &&
+ ReadParam(m, iter, &r->content_length) &&
+ ReadParam(m, iter, &r->appcache_id) &&
+ ReadParam(m, iter, &r->appcache_manifest_url) &&
+ ReadParam(m, iter, &r->connection_id) &&
+ ReadParam(m, iter, &r->connection_reused) &&
+ ReadParam(m, iter, &r->load_timing) &&
+ ReadParam(m, iter, &r->was_fetched_via_spdy) &&
+ ReadParam(m, iter, &r->was_npn_negotiated) &&
+ ReadParam(m, iter, &r->was_alternate_protocol_available) &&
+ ReadParam(m, iter, &r->was_fetched_via_proxy);
+ }
+ static void Log(const param_type& p, std::wstring* l) {
+ l->append(L"(");
+ LogParam(p.request_time, l);
+ l->append(L", ");
+ LogParam(p.response_time, l);
+ l->append(L", ");
+ LogParam(p.headers, l);
+ l->append(L", ");
+ LogParam(p.mime_type, l);
+ l->append(L", ");
+ LogParam(p.charset, l);
+ l->append(L", ");
+ LogParam(p.security_info, l);
+ l->append(L", ");
+ LogParam(p.content_length, l);
+ l->append(L", ");
+ LogParam(p.appcache_id, l);
+ l->append(L", ");
+ LogParam(p.appcache_manifest_url, l);
+ l->append(L", ");
+ LogParam(p.connection_id, l);
+ l->append(L", ");
+ LogParam(p.connection_reused, l);
+ l->append(L", ");
+ LogParam(p.load_timing, l);
+ l->append(L", ");
+ LogParam(p.was_fetched_via_spdy, l);
+ l->append(L", ");
+ LogParam(p.was_npn_negotiated, l);
+ l->append(L", ");
+ LogParam(p.was_alternate_protocol_available, l);
+ l->append(L", ");
+ LogParam(p.was_fetched_via_proxy, l);
+ l->append(L")");
+ }
+};
+
+template <>
+struct ParamTraits<ResourceResponseHead> {
+ typedef ResourceResponseHead param_type;
+ static void Write(Message* m, const param_type& p) {
+ ParamTraits<webkit_glue::ResourceLoaderBridge::ResponseInfo>::Write(m, p);
+ WriteParam(m, p.status);
+ WriteParam(m, p.replace_extension_localization_templates);
+ }
+ static bool Read(const Message* m, void** iter, param_type* r) {
+ return ParamTraits<webkit_glue::ResourceLoaderBridge::ResponseInfo>::Read(
+ m, iter, r) &&
+ ReadParam(m, iter, &r->status) &&
+ ReadParam(m, iter, &r->replace_extension_localization_templates);
+ }
+ static void Log(const param_type& p, std::wstring* l) {
+ // log more?
+ ParamTraits<webkit_glue::ResourceLoaderBridge::ResponseInfo>::Log(p, l);
+ }
+};
+
+template <>
+struct ParamTraits<SyncLoadResult> {
+ typedef SyncLoadResult param_type;
+ static void Write(Message* m, const param_type& p) {
+ ParamTraits<ResourceResponseHead>::Write(m, p);
+ WriteParam(m, p.final_url);
+ WriteParam(m, p.data);
+ }
+ static bool Read(const Message* m, void** iter, param_type* r) {
+ return
+ ParamTraits<ResourceResponseHead>::Read(m, iter, r) &&
+ ReadParam(m, iter, &r->final_url) &&
+ ReadParam(m, iter, &r->data);
+ }
+ static void Log(const param_type& p, std::wstring* l) {
+ // log more?
+ ParamTraits<webkit_glue::ResourceLoaderBridge::ResponseInfo>::Log(p, l);
+ }
+};
+
+template <>
+struct ParamTraits<SerializedScriptValue> {
+ typedef SerializedScriptValue param_type;
+ static void Write(Message* m, const param_type& p) {
+ WriteParam(m, p.is_null());
+ WriteParam(m, p.is_invalid());
+ WriteParam(m, p.data());
+ }
+ static bool Read(const Message* m, void** iter, param_type* r) {
+ bool is_null;
+ bool is_invalid;
+ string16 data;
+ bool ok =
+ ReadParam(m, iter, &is_null) &&
+ ReadParam(m, iter, &is_invalid) &&
+ ReadParam(m, iter, &data);
+ if (!ok)
+ return false;
+ r->set_is_null(is_null);
+ r->set_is_invalid(is_invalid);
+ r->set_data(data);
+ return true;
+ }
+ static void Log(const param_type& p, std::wstring* l) {
+ l->append(L"<SerializedScriptValue>(");
+ LogParam(p.is_null(), l);
+ l->append(L", ");
+ LogParam(p.is_invalid(), l);
+ l->append(L", ");
+ LogParam(p.data(), l);
+ l->append(L")");
+ }
+};
+
+template <>
+struct ParamTraits<IndexedDBKey> {
+ typedef IndexedDBKey param_type;
+ static void Write(Message* m, const param_type& p) {
+ WriteParam(m, int(p.type()));
+ // TODO(jorlow): Technically, we only need to pack the type being used.
+ WriteParam(m, p.string());
+ WriteParam(m, p.number());
+ }
+ static bool Read(const Message* m, void** iter, param_type* r) {
+ int type;
+ string16 string;
+ int32 number;
+ bool ok =
+ ReadParam(m, iter, &type) &&
+ ReadParam(m, iter, &string) &&
+ ReadParam(m, iter, &number);
+ if (!ok)
+ return false;
+ switch (type) {
+ case WebKit::WebIDBKey::NullType:
+ r->SetNull();
+ return true;
+ case WebKit::WebIDBKey::StringType:
+ r->Set(string);
+ return true;
+ case WebKit::WebIDBKey::NumberType:
+ r->Set(number);
+ return true;
+ case WebKit::WebIDBKey::InvalidType:
+ r->SetInvalid();
+ return true;
+ }
+ NOTREACHED();
+ return false;
+ }
+ static void Log(const param_type& p, std::wstring* l) {
+ l->append(L"<IndexedDBKey>(");
+ LogParam(int(p.type()), l);
+ l->append(L", ");
+ LogParam(p.string(), l);
+ l->append(L", ");
+ LogParam(p.number(), l);
+ l->append(L")");
+ }
+};
+
+// Traits for FormData structure to pack/unpack.
+template <>
+struct ParamTraits<webkit_glue::FormData> {
+ typedef webkit_glue::FormData param_type;
+ static void Write(Message* m, const param_type& p) {
+ WriteParam(m, p.name);
+ WriteParam(m, p.method);
+ WriteParam(m, p.origin);
+ WriteParam(m, p.action);
+ WriteParam(m, p.fields);
+ }
+ static bool Read(const Message* m, void** iter, param_type* p) {
+ return
+ ReadParam(m, iter, &p->name) &&
+ ReadParam(m, iter, &p->method) &&
+ ReadParam(m, iter, &p->origin) &&
+ ReadParam(m, iter, &p->action) &&
+ ReadParam(m, iter, &p->fields);
+ }
+ static void Log(const param_type& p, std::wstring* l) {
+ l->append(L"<FormData>");
+ }
+};
+
+// Traits for ViewMsg_Print_Params
+template <>
+struct ParamTraits<ViewMsg_Print_Params> {
+ typedef ViewMsg_Print_Params param_type;
+ static void Write(Message* m, const param_type& p) {
+ WriteParam(m, p.page_size);
+ WriteParam(m, p.printable_size);
+ WriteParam(m, p.margin_top);
+ WriteParam(m, p.margin_left);
+ WriteParam(m, p.dpi);
+ WriteParam(m, p.min_shrink);
+ WriteParam(m, p.max_shrink);
+ WriteParam(m, p.desired_dpi);
+ WriteParam(m, p.document_cookie);
+ WriteParam(m, p.selection_only);
+ }
+ static bool Read(const Message* m, void** iter, param_type* p) {
+ return ReadParam(m, iter, &p->page_size) &&
+ ReadParam(m, iter, &p->printable_size) &&
+ ReadParam(m, iter, &p->margin_top) &&
+ ReadParam(m, iter, &p->margin_left) &&
+ ReadParam(m, iter, &p->dpi) &&
+ ReadParam(m, iter, &p->min_shrink) &&
+ ReadParam(m, iter, &p->max_shrink) &&
+ ReadParam(m, iter, &p->desired_dpi) &&
+ ReadParam(m, iter, &p->document_cookie) &&
+ ReadParam(m, iter, &p->selection_only);
+ }
+ static void Log(const param_type& p, std::wstring* l) {
+ l->append(L"<ViewMsg_Print_Params>");
+ }
+};
+
+// Traits for ViewMsg_PrintPage_Params
+template <>
+struct ParamTraits<ViewMsg_PrintPage_Params> {
+ typedef ViewMsg_PrintPage_Params param_type;
+ static void Write(Message* m, const param_type& p) {
+ WriteParam(m, p.params);
+ WriteParam(m, p.page_number);
+ }
+ static bool Read(const Message* m, void** iter, param_type* p) {
+ return ReadParam(m, iter, &p->params) &&
+ ReadParam(m, iter, &p->page_number);
+ }
+ static void Log(const param_type& p, std::wstring* l) {
+ l->append(L"<ViewMsg_PrintPage_Params>");
+ }
+};
+
+// Traits for ViewMsg_PrintPages_Params
+template <>
+struct ParamTraits<ViewMsg_PrintPages_Params> {
+ typedef ViewMsg_PrintPages_Params param_type;
+ static void Write(Message* m, const param_type& p) {
+ WriteParam(m, p.params);
+ WriteParam(m, p.pages);
+ }
+ static bool Read(const Message* m, void** iter, param_type* p) {
+ return ReadParam(m, iter, &p->params) &&
+ ReadParam(m, iter, &p->pages);
+ }
+ static void Log(const param_type& p, std::wstring* l) {
+ l->append(L"<ViewMsg_PrintPages_Params>");
+ }
+};
+
+// Traits for ViewHostMsg_DidPrintPage_Params
+template <>
+struct ParamTraits<ViewHostMsg_DidPrintPage_Params> {
+ typedef ViewHostMsg_DidPrintPage_Params param_type;
+ static void Write(Message* m, const param_type& p) {
+ WriteParam(m, p.metafile_data_handle);
+ WriteParam(m, p.data_size);
+ WriteParam(m, p.document_cookie);
+ WriteParam(m, p.page_number);
+ WriteParam(m, p.actual_shrink);
+ WriteParam(m, p.page_size);
+ WriteParam(m, p.content_area);
+ WriteParam(m, p.has_visible_overlays);
+ }
+ static bool Read(const Message* m, void** iter, param_type* p) {
+ return ReadParam(m, iter, &p->metafile_data_handle) &&
+ ReadParam(m, iter, &p->data_size) &&
+ ReadParam(m, iter, &p->document_cookie) &&
+ ReadParam(m, iter, &p->page_number) &&
+ ReadParam(m, iter, &p->actual_shrink) &&
+ ReadParam(m, iter, &p->page_size) &&
+ ReadParam(m, iter, &p->content_area) &&
+ ReadParam(m, iter, &p->has_visible_overlays);
+ }
+ static void Log(const param_type& p, std::wstring* l) {
+ l->append(L"<ViewHostMsg_DidPrintPage_Params>");
+ }
+};
+
+// Traits for reading/writing CSS Colors
+template <>
+struct ParamTraits<CSSColors::CSSColorName> {
+ typedef CSSColors::CSSColorName param_type;
+ static void Write(Message* m, const param_type& p) {
+ WriteParam(m, static_cast<int>(p));
+ }
+ static bool Read(const Message* m, void** iter, param_type* p) {
+ return ReadParam(m, iter, reinterpret_cast<int*>(p));
+ }
+ static void Log(const param_type& p, std::wstring* l) {
+ l->append(L"<CSSColorName>");
+ }
+};
+
+
+// Traits for RendererPreferences structure to pack/unpack.
+template <>
+struct ParamTraits<RendererPreferences> {
+ typedef RendererPreferences param_type;
+ static void Write(Message* m, const param_type& p) {
+ WriteParam(m, p.can_accept_load_drops);
+ WriteParam(m, p.should_antialias_text);
+ WriteParam(m, static_cast<int>(p.hinting));
+ WriteParam(m, static_cast<int>(p.subpixel_rendering));
+ WriteParam(m, p.focus_ring_color);
+ WriteParam(m, p.thumb_active_color);
+ WriteParam(m, p.thumb_inactive_color);
+ WriteParam(m, p.track_color);
+ WriteParam(m, p.active_selection_bg_color);
+ WriteParam(m, p.active_selection_fg_color);
+ WriteParam(m, p.inactive_selection_bg_color);
+ WriteParam(m, p.inactive_selection_fg_color);
+ WriteParam(m, p.browser_handles_top_level_requests);
+ WriteParam(m, p.caret_blink_interval);
+ }
+ static bool Read(const Message* m, void** iter, param_type* p) {
+ if (!ReadParam(m, iter, &p->can_accept_load_drops))
+ return false;
+ if (!ReadParam(m, iter, &p->should_antialias_text))
+ return false;
+
+ int hinting = 0;
+ if (!ReadParam(m, iter, &hinting))
+ return false;
+ p->hinting = static_cast<RendererPreferencesHintingEnum>(hinting);
+
+ int subpixel_rendering = 0;
+ if (!ReadParam(m, iter, &subpixel_rendering))
+ return false;
+ p->subpixel_rendering =
+ static_cast<RendererPreferencesSubpixelRenderingEnum>(
+ subpixel_rendering);
+
+ int focus_ring_color;
+ if (!ReadParam(m, iter, &focus_ring_color))
+ return false;
+ p->focus_ring_color = focus_ring_color;
+
+ int thumb_active_color, thumb_inactive_color, track_color;
+ int active_selection_bg_color, active_selection_fg_color;
+ int inactive_selection_bg_color, inactive_selection_fg_color;
+ if (!ReadParam(m, iter, &thumb_active_color) ||
+ !ReadParam(m, iter, &thumb_inactive_color) ||
+ !ReadParam(m, iter, &track_color) ||
+ !ReadParam(m, iter, &active_selection_bg_color) ||
+ !ReadParam(m, iter, &active_selection_fg_color) ||
+ !ReadParam(m, iter, &inactive_selection_bg_color) ||
+ !ReadParam(m, iter, &inactive_selection_fg_color))
+ return false;
+ p->thumb_active_color = thumb_active_color;
+ p->thumb_inactive_color = thumb_inactive_color;
+ p->track_color = track_color;
+ p->active_selection_bg_color = active_selection_bg_color;
+ p->active_selection_fg_color = active_selection_fg_color;
+ p->inactive_selection_bg_color = inactive_selection_bg_color;
+ p->inactive_selection_fg_color = inactive_selection_fg_color;
+
+ if (!ReadParam(m, iter, &p->browser_handles_top_level_requests))
+ return false;
+
+ if (!ReadParam(m, iter, &p->caret_blink_interval))
+ return false;
+
+ return true;
+ }
+ static void Log(const param_type& p, std::wstring* l) {
+ l->append(L"<RendererPreferences>");
+ }
+};
+
+// Traits for WebPreferences structure to pack/unpack.
+template <>
+struct ParamTraits<WebPreferences> {
+ typedef WebPreferences param_type;
+ static void Write(Message* m, const param_type& p) {
+ WriteParam(m, p.standard_font_family);
+ WriteParam(m, p.fixed_font_family);
+ WriteParam(m, p.serif_font_family);
+ WriteParam(m, p.sans_serif_font_family);
+ WriteParam(m, p.cursive_font_family);
+ WriteParam(m, p.fantasy_font_family);
+ WriteParam(m, p.default_font_size);
+ WriteParam(m, p.default_fixed_font_size);
+ WriteParam(m, p.minimum_font_size);
+ WriteParam(m, p.minimum_logical_font_size);
+ WriteParam(m, p.default_encoding);
+ WriteParam(m, p.javascript_enabled);
+ WriteParam(m, p.web_security_enabled);
+ WriteParam(m, p.javascript_can_open_windows_automatically);
+ WriteParam(m, p.loads_images_automatically);
+ WriteParam(m, p.plugins_enabled);
+ WriteParam(m, p.dom_paste_enabled);
+ WriteParam(m, p.developer_extras_enabled);
+ WriteParam(m, p.inspector_settings);
+ WriteParam(m, p.site_specific_quirks_enabled);
+ WriteParam(m, p.shrinks_standalone_images_to_fit);
+ WriteParam(m, p.uses_universal_detector);
+ WriteParam(m, p.text_areas_are_resizable);
+ WriteParam(m, p.java_enabled);
+ WriteParam(m, p.allow_scripts_to_close_windows);
+ WriteParam(m, p.uses_page_cache);
+ WriteParam(m, p.remote_fonts_enabled);
+ WriteParam(m, p.javascript_can_access_clipboard);
+ WriteParam(m, p.xss_auditor_enabled);
+ WriteParam(m, p.local_storage_enabled);
+ WriteParam(m, p.databases_enabled);
+ WriteParam(m, p.application_cache_enabled);
+ WriteParam(m, p.tabs_to_links);
+ WriteParam(m, p.user_style_sheet_enabled);
+ WriteParam(m, p.user_style_sheet_location);
+ WriteParam(m, p.author_and_user_styles_enabled);
+ WriteParam(m, p.allow_universal_access_from_file_urls);
+ WriteParam(m, p.allow_file_access_from_file_urls);
+ WriteParam(m, p.experimental_webgl_enabled);
+ WriteParam(m, p.show_composited_layer_borders);
+ WriteParam(m, p.accelerated_compositing_enabled);
+ WriteParam(m, p.memory_info_enabled);
+ }
+ static bool Read(const Message* m, void** iter, param_type* p) {
+ return
+ ReadParam(m, iter, &p->standard_font_family) &&
+ ReadParam(m, iter, &p->fixed_font_family) &&
+ ReadParam(m, iter, &p->serif_font_family) &&
+ ReadParam(m, iter, &p->sans_serif_font_family) &&
+ ReadParam(m, iter, &p->cursive_font_family) &&
+ ReadParam(m, iter, &p->fantasy_font_family) &&
+ ReadParam(m, iter, &p->default_font_size) &&
+ ReadParam(m, iter, &p->default_fixed_font_size) &&
+ ReadParam(m, iter, &p->minimum_font_size) &&
+ ReadParam(m, iter, &p->minimum_logical_font_size) &&
+ ReadParam(m, iter, &p->default_encoding) &&
+ ReadParam(m, iter, &p->javascript_enabled) &&
+ ReadParam(m, iter, &p->web_security_enabled) &&
+ ReadParam(m, iter, &p->javascript_can_open_windows_automatically) &&
+ ReadParam(m, iter, &p->loads_images_automatically) &&
+ ReadParam(m, iter, &p->plugins_enabled) &&
+ ReadParam(m, iter, &p->dom_paste_enabled) &&
+ ReadParam(m, iter, &p->developer_extras_enabled) &&
+ ReadParam(m, iter, &p->inspector_settings) &&
+ ReadParam(m, iter, &p->site_specific_quirks_enabled) &&
+ ReadParam(m, iter, &p->shrinks_standalone_images_to_fit) &&
+ ReadParam(m, iter, &p->uses_universal_detector) &&
+ ReadParam(m, iter, &p->text_areas_are_resizable) &&
+ ReadParam(m, iter, &p->java_enabled) &&
+ ReadParam(m, iter, &p->allow_scripts_to_close_windows) &&
+ ReadParam(m, iter, &p->uses_page_cache) &&
+ ReadParam(m, iter, &p->remote_fonts_enabled) &&
+ ReadParam(m, iter, &p->javascript_can_access_clipboard) &&
+ ReadParam(m, iter, &p->xss_auditor_enabled) &&
+ ReadParam(m, iter, &p->local_storage_enabled) &&
+ ReadParam(m, iter, &p->databases_enabled) &&
+ ReadParam(m, iter, &p->application_cache_enabled) &&
+ ReadParam(m, iter, &p->tabs_to_links) &&
+ ReadParam(m, iter, &p->user_style_sheet_enabled) &&
+ ReadParam(m, iter, &p->user_style_sheet_location) &&
+ ReadParam(m, iter, &p->author_and_user_styles_enabled) &&
+ ReadParam(m, iter, &p->allow_universal_access_from_file_urls) &&
+ ReadParam(m, iter, &p->allow_file_access_from_file_urls) &&
+ ReadParam(m, iter, &p->experimental_webgl_enabled) &&
+ ReadParam(m, iter, &p->show_composited_layer_borders) &&
+ ReadParam(m, iter, &p->accelerated_compositing_enabled) &&
+ ReadParam(m, iter, &p->memory_info_enabled);
+ }
+ static void Log(const param_type& p, std::wstring* l) {
+ l->append(L"<WebPreferences>");
+ }
+};
+
+// Traits for WebDropData
+template <>
+struct ParamTraits<WebDropData> {
+ typedef WebDropData param_type;
+ static void Write(Message* m, const param_type& p) {
+ WriteParam(m, p.identity);
+ WriteParam(m, p.url);
+ WriteParam(m, p.url_title);
+ WriteParam(m, p.download_metadata);
+ WriteParam(m, p.file_extension);
+ WriteParam(m, p.filenames);
+ WriteParam(m, p.plain_text);
+ WriteParam(m, p.text_html);
+ WriteParam(m, p.html_base_url);
+ WriteParam(m, p.file_description_filename);
+ WriteParam(m, p.file_contents);
+ }
+ static bool Read(const Message* m, void** iter, param_type* p) {
+ return
+ ReadParam(m, iter, &p->identity) &&
+ ReadParam(m, iter, &p->url) &&
+ ReadParam(m, iter, &p->url_title) &&
+ ReadParam(m, iter, &p->download_metadata) &&
+ ReadParam(m, iter, &p->file_extension) &&
+ ReadParam(m, iter, &p->filenames) &&
+ ReadParam(m, iter, &p->plain_text) &&
+ ReadParam(m, iter, &p->text_html) &&
+ ReadParam(m, iter, &p->html_base_url) &&
+ ReadParam(m, iter, &p->file_description_filename) &&
+ ReadParam(m, iter, &p->file_contents);
+ }
+ static void Log(const param_type& p, std::wstring* l) {
+ l->append(L"<WebDropData>");
+ }
+};
+
+// Traits for AudioManager::Format.
+template <>
+struct ParamTraits<AudioManager::Format> {
+ typedef AudioManager::Format param_type;
+ static void Write(Message* m, const param_type& p) {
+ m->WriteInt(p);
+ }
+ static bool Read(const Message* m, void** iter, param_type* p) {
+ int type;
+ if (!m->ReadInt(iter, &type))
+ return false;
+ *p = static_cast<AudioManager::Format>(type);
+ return true;
+ }
+ static void Log(const param_type& p, std::wstring* l) {
+ std::wstring format;
+ switch (p) {
+ case AudioManager::AUDIO_PCM_LINEAR:
+ format = L"AUDIO_PCM_LINEAR";
+ break;
+ case AudioManager::AUDIO_PCM_LOW_LATENCY:
+ format = L"AUDIO_PCM_LOW_LATENCY";
+ break;
+ case AudioManager::AUDIO_MOCK:
+ format = L"AUDIO_MOCK";
+ break;
+ default:
+ format = L"AUDIO_LAST_FORMAT";
+ break;
+ }
+ LogParam(format, l);
+ }
+};
+
+// Traits for ViewHostMsg_Audio_CreateStream_Params.
+template <>
+struct ParamTraits<ViewHostMsg_Audio_CreateStream_Params> {
+ typedef ViewHostMsg_Audio_CreateStream_Params param_type;
+ static void Write(Message* m, const param_type& p) {
+ WriteParam(m, p.format);
+ WriteParam(m, p.channels);
+ WriteParam(m, p.sample_rate);
+ WriteParam(m, p.bits_per_sample);
+ WriteParam(m, p.packet_size);
+ }
+ static bool Read(const Message* m, void** iter, param_type* p) {
+ return
+ ReadParam(m, iter, &p->format) &&
+ ReadParam(m, iter, &p->channels) &&
+ ReadParam(m, iter, &p->sample_rate) &&
+ ReadParam(m, iter, &p->bits_per_sample) &&
+ ReadParam(m, iter, &p->packet_size);
+ }
+ static void Log(const param_type& p, std::wstring* l) {
+ l->append(L"<ViewHostMsg_Audio_CreateStream_Params>(");
+ LogParam(p.format, l);
+ l->append(L", ");
+ LogParam(p.channels, l);
+ l->append(L", ");
+ LogParam(p.sample_rate, l);
+ l->append(L", ");
+ LogParam(p.bits_per_sample, l);
+ l->append(L", ");
+ LogParam(p.packet_size, l);
+ l->append(L")");
+ }
+};
+
+
+#if defined(OS_POSIX)
+
+// TODO(port): this shouldn't exist. However, the plugin stuff is really using
+// HWNDS (NativeView), and making Windows calls based on them. I've not figured
+// out the deal with plugins yet.
+template <>
+struct ParamTraits<gfx::NativeView> {
+ typedef gfx::NativeView param_type;
+ static void Write(Message* m, const param_type& p) {
+ NOTIMPLEMENTED();
+ }
+
+ static bool Read(const Message* m, void** iter, param_type* p) {
+ NOTIMPLEMENTED();
+ *p = NULL;
+ return true;
+ }
+
+ static void Log(const param_type& p, std::wstring* l) {
+ l->append(StringPrintf(L"<gfx::NativeView>"));
+ }
+};
+
+#endif // defined(OS_POSIX)
+
+template <>
+struct ParamTraits<ViewMsg_AudioStreamState_Params> {
+ typedef ViewMsg_AudioStreamState_Params param_type;
+ static void Write(Message* m, const param_type& p) {
+ m->WriteInt(p.state);
+ }
+ static bool Read(const Message* m, void** iter, param_type* p) {
+ int type;
+ if (!m->ReadInt(iter, &type))
+ return false;
+ p->state = static_cast<ViewMsg_AudioStreamState_Params::State>(type);
+ return true;
+ }
+ static void Log(const param_type& p, std::wstring* l) {
+ std::wstring state;
+ switch (p.state) {
+ case ViewMsg_AudioStreamState_Params::kPlaying:
+ state = L"ViewMsg_AudioStreamState_Params::kPlaying";
+ break;
+ case ViewMsg_AudioStreamState_Params::kPaused:
+ state = L"ViewMsg_AudioStreamState_Params::kPaused";
+ break;
+ case ViewMsg_AudioStreamState_Params::kError:
+ state = L"ViewMsg_AudioStreamState_Params::kError";
+ break;
+ default:
+ state = L"UNKNOWN";
+ break;
+ }
+ LogParam(state, l);
+ }
+};
+
+template <>
+struct ParamTraits<ViewMsg_StopFinding_Params> {
+ typedef ViewMsg_StopFinding_Params param_type;
+ static void Write(Message* m, const param_type& p) {
+ m->WriteInt(p.action);
+ }
+ static bool Read(const Message* m, void** iter, param_type* p) {
+ int type;
+ if (!m->ReadInt(iter, &type))
+ return false;
+ p->action = static_cast<ViewMsg_StopFinding_Params::Action>(type);
+ return true;
+ }
+ static void Log(const param_type& p, std::wstring* l) {
+ std::wstring action;
+ switch (p.action) {
+ case ViewMsg_StopFinding_Params::kClearSelection:
+ action = L"ViewMsg_StopFinding_Params::kClearSelection";
+ break;
+ case ViewMsg_StopFinding_Params::kKeepSelection:
+ action = L"ViewMsg_StopFinding_Params::kKeepSelection";
+ break;
+ case ViewMsg_StopFinding_Params::kActivateSelection:
+ action = L"ViewMsg_StopFinding_Params::kActivateSelection";
+ break;
+ default:
+ action = L"UNKNOWN";
+ break;
+ }
+ LogParam(action, l);
+ }
+};
+
+template <>
+struct ParamTraits<appcache::Status> {
+ typedef appcache::Status param_type;
+ static void Write(Message* m, const param_type& p) {
+ m->WriteInt(static_cast<int>(p));
+ }
+ static bool Read(const Message* m, void** iter, param_type* p) {
+ int type;
+ if (!m->ReadInt(iter, &type))
+ return false;
+ *p = static_cast<param_type>(type);
+ return true;
+ }
+ static void Log(const param_type& p, std::wstring* l) {
+ std::wstring state;
+ switch (p) {
+ case appcache::UNCACHED:
+ state = L"UNCACHED";
+ break;
+ case appcache::IDLE:
+ state = L"IDLE";
+ break;
+ case appcache::CHECKING:
+ state = L"CHECKING";
+ break;
+ case appcache::DOWNLOADING:
+ state = L"DOWNLOADING";
+ break;
+ case appcache::UPDATE_READY:
+ state = L"UPDATE_READY";
+ break;
+ case appcache::OBSOLETE:
+ state = L"OBSOLETE";
+ break;
+ default:
+ state = L"InvalidStatusValue";
+ break;
+ }
+
+ LogParam(state, l);
+ }
+};
+
+template <>
+struct ParamTraits<appcache::EventID> {
+ typedef appcache::EventID param_type;
+ static void Write(Message* m, const param_type& p) {
+ m->WriteInt(static_cast<int>(p));
+ }
+ static bool Read(const Message* m, void** iter, param_type* p) {
+ int type;
+ if (!m->ReadInt(iter, &type))
+ return false;
+ *p = static_cast<param_type>(type);
+ return true;
+ }
+ static void Log(const param_type& p, std::wstring* l) {
+ std::wstring state;
+ switch (p) {
+ case appcache::CHECKING_EVENT:
+ state = L"CHECKING_EVENT";
+ break;
+ case appcache::ERROR_EVENT:
+ state = L"ERROR_EVENT";
+ break;
+ case appcache::NO_UPDATE_EVENT:
+ state = L"NO_UPDATE_EVENT";
+ break;
+ case appcache::DOWNLOADING_EVENT:
+ state = L"DOWNLOADING_EVENT";
+ break;
+ case appcache::PROGRESS_EVENT:
+ state = L"PROGRESS_EVENT";
+ break;
+ case appcache::UPDATE_READY_EVENT:
+ state = L"UPDATE_READY_EVENT";
+ break;
+ case appcache::CACHED_EVENT:
+ state = L"CACHED_EVENT";
+ break;
+ case appcache::OBSOLETE_EVENT:
+ state = L"OBSOLETE_EVENT";
+ break;
+ default:
+ state = L"InvalidEventValue";
+ break;
+ }
+
+ LogParam(state, l);
+ }
+};
+
+template<>
+struct ParamTraits<WebMenuItem::Type> {
+ typedef WebMenuItem::Type param_type;
+ static void Write(Message* m, const param_type& p) {
+ m->WriteInt(p);
+ }
+ static bool Read(const Message* m, void** iter, param_type* p) {
+ int type;
+ if (!m->ReadInt(iter, &type))
+ return false;
+ *p = static_cast<WebMenuItem::Type>(type);
+ return true;
+ }
+ static void Log(const param_type& p, std::wstring* l) {
+ std::wstring type;
+ switch (p) {
+ case WebMenuItem::OPTION:
+ type = L"OPTION";
+ break;
+ case WebMenuItem::GROUP:
+ type = L"GROUP";
+ break;
+ case WebMenuItem::SEPARATOR:
+ type = L"SEPARATOR";
+ break;
+ default:
+ type = L"UNKNOWN";
+ break;
+ }
+ LogParam(type, l);
+ }
+};
+
+template<>
+struct ParamTraits<WebMenuItem> {
+ typedef WebMenuItem param_type;
+ static void Write(Message* m, const param_type& p) {
+ WriteParam(m, p.label);
+ WriteParam(m, p.type);
+ WriteParam(m, p.enabled);
+ WriteParam(m, p.checked);
+ WriteParam(m, p.action);
+ }
+ static bool Read(const Message* m, void** iter, param_type* p) {
+ return
+ ReadParam(m, iter, &p->label) &&
+ ReadParam(m, iter, &p->type) &&
+ ReadParam(m, iter, &p->enabled) &&
+ ReadParam(m, iter, &p->checked) &&
+ ReadParam(m, iter, &p->action);
+ }
+ static void Log(const param_type& p, std::wstring* l) {
+ l->append(L"(");
+ LogParam(p.label, l);
+ l->append(L", ");
+ LogParam(p.type, l);
+ l->append(L", ");
+ LogParam(p.enabled, l);
+ l->append(L", ");
+ LogParam(p.checked, l);
+ l->append(L", ");
+ LogParam(p.action, l);
+ l->append(L")");
+ }
+};
+
+// Traits for ViewHostMsg_ShowPopup_Params.
+template <>
+struct ParamTraits<ViewHostMsg_ShowPopup_Params> {
+ typedef ViewHostMsg_ShowPopup_Params param_type;
+ static void Write(Message* m, const param_type& p) {
+ WriteParam(m, p.bounds);
+ WriteParam(m, p.item_height);
+ WriteParam(m, p.item_font_size);
+ WriteParam(m, p.selected_item);
+ WriteParam(m, p.popup_items);
+ WriteParam(m, p.right_aligned);
+ }
+ static bool Read(const Message* m, void** iter, param_type* p) {
+ return
+ ReadParam(m, iter, &p->bounds) &&
+ ReadParam(m, iter, &p->item_height) &&
+ ReadParam(m, iter, &p->item_font_size) &&
+ ReadParam(m, iter, &p->selected_item) &&
+ ReadParam(m, iter, &p->popup_items) &&
+ ReadParam(m, iter, &p->right_aligned);
+ }
+ static void Log(const param_type& p, std::wstring* l) {
+ l->append(L"(");
+ LogParam(p.bounds, l);
+ l->append(L", ");
+ LogParam(p.item_height, l);
+ l->append(L", ");
+ LogParam(p.item_font_size, l);
+ l->append(L", ");
+ LogParam(p.selected_item, l);
+ l->append(L", ");
+ LogParam(p.popup_items, l);
+ l->append(L", ");
+ LogParam(p.right_aligned, l);
+ l->append(L")");
+ }
+};
+
+// Traits for ViewHostMsg_ScriptedPrint_Params.
+template <>
+struct ParamTraits<ViewHostMsg_ScriptedPrint_Params> {
+ typedef ViewHostMsg_ScriptedPrint_Params param_type;
+ static void Write(Message* m, const param_type& p) {
+ WriteParam(m, p.routing_id);
+ WriteParam(m, p.host_window_id);
+ WriteParam(m, p.cookie);
+ WriteParam(m, p.expected_pages_count);
+ WriteParam(m, p.has_selection);
+ WriteParam(m, p.use_overlays);
+ }
+ static bool Read(const Message* m, void** iter, param_type* p) {
+ return
+ ReadParam(m, iter, &p->routing_id) &&
+ ReadParam(m, iter, &p->host_window_id) &&
+ ReadParam(m, iter, &p->cookie) &&
+ ReadParam(m, iter, &p->expected_pages_count) &&
+ ReadParam(m, iter, &p->has_selection) &&
+ ReadParam(m, iter, &p->use_overlays);
+ }
+ static void Log(const param_type& p, std::wstring* l) {
+ l->append(L"(");
+ LogParam(p.routing_id, l);
+ l->append(L", ");
+ LogParam(p.host_window_id, l);
+ l->append(L", ");
+ LogParam(p.cookie, l);
+ l->append(L", ");
+ LogParam(p.expected_pages_count, l);
+ l->append(L", ");
+ LogParam(p.has_selection, l);
+ l->append(L",");
+ LogParam(p.use_overlays, l);
+ l->append(L")");
+ }
+};
+
+template <>
+struct SimilarTypeTraits<ViewType::Type> {
+ typedef int Type;
+};
+
+// Traits for URLPattern.
+template <>
+struct ParamTraits<URLPattern> {
+ typedef URLPattern param_type;
+ static void Write(Message* m, const param_type& p) {
+ WriteParam(m, p.valid_schemes());
+ WriteParam(m, p.GetAsString());
+ }
+ static bool Read(const Message* m, void** iter, param_type* p) {
+ int valid_schemes;
+ std::string spec;
+ if (!ReadParam(m, iter, &valid_schemes) ||
+ !ReadParam(m, iter, &spec))
+ return false;
+
+ p->set_valid_schemes(valid_schemes);
+ return p->Parse(spec);
+ }
+ static void Log(const param_type& p, std::wstring* l) {
+ LogParam(p.GetAsString(), l);
+ }
+};
+
+template <>
+struct ParamTraits<Clipboard::Buffer> {
+ typedef Clipboard::Buffer param_type;
+ static void Write(Message* m, const param_type& p) {
+ m->WriteInt(p);
+ }
+ static bool Read(const Message* m, void** iter, param_type* p) {
+ int buffer;
+ if (!m->ReadInt(iter, &buffer) || !Clipboard::IsValidBuffer(buffer))
+ return false;
+ *p = Clipboard::FromInt(buffer);
+ return true;
+ }
+ static void Log(const param_type& p, std::wstring* l) {
+ std::wstring type;
+ switch (p) {
+ case Clipboard::BUFFER_STANDARD:
+ type = L"BUFFER_STANDARD";
+ break;
+#if defined(USE_X11)
+ case Clipboard::BUFFER_SELECTION:
+ type = L"BUFFER_SELECTION";
+ break;
+#endif
+ case Clipboard::BUFFER_DRAG:
+ type = L"BUFFER_DRAG";
+ break;
+ default:
+ type = L"UNKNOWN";
+ break;
+ }
+
+ LogParam(type, l);
+ }
+};
+
+// Traits for EditCommand structure.
+template <>
+struct ParamTraits<EditCommand> {
+ typedef EditCommand param_type;
+ static void Write(Message* m, const param_type& p) {
+ WriteParam(m, p.name);
+ WriteParam(m, p.value);
+ }
+ static bool Read(const Message* m, void** iter, param_type* p) {
+ return ReadParam(m, iter, &p->name) && ReadParam(m, iter, &p->value);
+ }
+ static void Log(const param_type& p, std::wstring* l) {
+ l->append(L"(");
+ LogParam(p.name, l);
+ l->append(L":");
+ LogParam(p.value, l);
+ l->append(L")");
+ }
+};
+
+// Traits for DOMStorageType enum.
+template <>
+struct ParamTraits<DOMStorageType> {
+ typedef DOMStorageType param_type;
+ static void Write(Message* m, const param_type& p) {
+ m->WriteInt(p);
+ }
+ static bool Read(const Message* m, void** iter, param_type* p) {
+ int type;
+ if (!m->ReadInt(iter, &type))
+ return false;
+ *p = static_cast<param_type>(type);
+ return true;
+ }
+ static void Log(const param_type& p, std::wstring* l) {
+ std::wstring control;
+ switch (p) {
+ case DOM_STORAGE_LOCAL:
+ control = L"DOM_STORAGE_LOCAL";
+ break;
+ case DOM_STORAGE_SESSION:
+ control = L"DOM_STORAGE_SESSION";
+ break;
+ default:
+ NOTIMPLEMENTED();
+ control = L"UNKNOWN";
+ break;
+ }
+ LogParam(control, l);
+ }
+};
+
+// Traits for WebKit::WebStorageArea::Result enum.
+template <>
+struct ParamTraits<WebKit::WebStorageArea::Result> {
+ typedef WebKit::WebStorageArea::Result param_type;
+ static void Write(Message* m, const param_type& p) {
+ m->WriteInt(p);
+ }
+ static bool Read(const Message* m, void** iter, param_type* p) {
+ int type;
+ if (!m->ReadInt(iter, &type))
+ return false;
+ *p = static_cast<param_type>(type);
+ return true;
+ }
+ static void Log(const param_type& p, std::wstring* l) {
+ std::wstring control;
+ switch (p) {
+ case WebKit::WebStorageArea::ResultOK:
+ control = L"WebKit::WebStorageArea::ResultOK";
+ break;
+ case WebKit::WebStorageArea::ResultBlockedByQuota:
+ control = L"WebKit::WebStorageArea::ResultBlockedByQuota";
+ break;
+ case WebKit::WebStorageArea::ResultBlockedByPolicy:
+ control = L"WebKit::WebStorageArea::ResultBlockedByPolicy";
+ break;
+ default:
+ NOTIMPLEMENTED();
+ control = L"UNKNOWN";
+ break;
+ }
+ LogParam(control, l);
+ }
+};
+
+// Traits for ViewMsg_DOMStorageEvent_Params.
+template <>
+struct ParamTraits<ViewMsg_DOMStorageEvent_Params> {
+ typedef ViewMsg_DOMStorageEvent_Params param_type;
+ static void Write(Message* m, const param_type& p) {
+ WriteParam(m, p.key_);
+ WriteParam(m, p.old_value_);
+ WriteParam(m, p.new_value_);
+ WriteParam(m, p.origin_);
+ WriteParam(m, p.url_);
+ WriteParam(m, p.storage_type_);
+ }
+ static bool Read(const Message* m, void** iter, param_type* p) {
+ return
+ ReadParam(m, iter, &p->key_) &&
+ ReadParam(m, iter, &p->old_value_) &&
+ ReadParam(m, iter, &p->new_value_) &&
+ ReadParam(m, iter, &p->origin_) &&
+ ReadParam(m, iter, &p->url_) &&
+ ReadParam(m, iter, &p->storage_type_);
+ }
+ static void Log(const param_type& p, std::wstring* l) {
+ l->append(L"(");
+ LogParam(p.key_, l);
+ l->append(L", ");
+ LogParam(p.old_value_, l);
+ l->append(L", ");
+ LogParam(p.new_value_, l);
+ l->append(L", ");
+ LogParam(p.origin_, l);
+ l->append(L", ");
+ LogParam(p.url_, l);
+ l->append(L", ");
+ LogParam(p.storage_type_, l);
+ l->append(L")");
+ }
+};
+
+// Traits for ViewHostMsg_IndexedDatabaseOpen_Params.
+template <>
+struct ParamTraits<ViewHostMsg_IndexedDatabaseOpen_Params> {
+ typedef ViewHostMsg_IndexedDatabaseOpen_Params param_type;
+ static void Write(Message* m, const param_type& p) {
+ WriteParam(m, p.routing_id_);
+ WriteParam(m, p.response_id_);
+ WriteParam(m, p.origin_);
+ WriteParam(m, p.name_);
+ WriteParam(m, p.description_);
+ }
+ static bool Read(const Message* m, void** iter, param_type* p) {
+ return
+ ReadParam(m, iter, &p->routing_id_) &&
+ ReadParam(m, iter, &p->response_id_) &&
+ ReadParam(m, iter, &p->origin_) &&
+ ReadParam(m, iter, &p->name_) &&
+ ReadParam(m, iter, &p->description_);
+ }
+ static void Log(const param_type& p, std::wstring* l) {
+ l->append(L"(");
+ LogParam(p.routing_id_, l);
+ l->append(L", ");
+ LogParam(p.response_id_, l);
+ l->append(L", ");
+ LogParam(p.origin_, l);
+ l->append(L", ");
+ LogParam(p.name_, l);
+ l->append(L", ");
+ LogParam(p.description_, l);
+ l->append(L")");
+ }
+};
+
+// Traits for ViewHostMsg_IDBDatabaseCreateObjectStore_Params.
+template <>
+struct ParamTraits<ViewHostMsg_IDBDatabaseCreateObjectStore_Params> {
+ typedef ViewHostMsg_IDBDatabaseCreateObjectStore_Params param_type;
+ static void Write(Message* m, const param_type& p) {
+ WriteParam(m, p.response_id_);
+ WriteParam(m, p.name_);
+ WriteParam(m, p.key_path_);
+ WriteParam(m, p.auto_increment_);
+ WriteParam(m, p.idb_database_id_);
+ }
+ static bool Read(const Message* m, void** iter, param_type* p) {
+ return
+ ReadParam(m, iter, &p->response_id_) &&
+ ReadParam(m, iter, &p->name_) &&
+ ReadParam(m, iter, &p->key_path_) &&
+ ReadParam(m, iter, &p->auto_increment_) &&
+ ReadParam(m, iter, &p->idb_database_id_);
+ }
+ static void Log(const param_type& p, std::wstring* l) {
+ l->append(L"(");
+ LogParam(p.response_id_, l);
+ l->append(L", ");
+ LogParam(p.name_, l);
+ l->append(L", ");
+ LogParam(p.key_path_, l);
+ l->append(L", ");
+ LogParam(p.auto_increment_, l);
+ l->append(L", ");
+ LogParam(p.idb_database_id_, l);
+ l->append(L")");
+ }
+};
+
+// Traits for ViewHostMsg_IDBObjectStoreCreateIndex_Params.
+template <>
+struct ParamTraits<ViewHostMsg_IDBObjectStoreCreateIndex_Params> {
+ typedef ViewHostMsg_IDBObjectStoreCreateIndex_Params param_type;
+ static void Write(Message* m, const param_type& p) {
+ WriteParam(m, p.response_id_);
+ WriteParam(m, p.name_);
+ WriteParam(m, p.key_path_);
+ WriteParam(m, p.unique_);
+ WriteParam(m, p.idb_object_store_id_);
+ }
+ static bool Read(const Message* m, void** iter, param_type* p) {
+ return
+ ReadParam(m, iter, &p->response_id_) &&
+ ReadParam(m, iter, &p->name_) &&
+ ReadParam(m, iter, &p->key_path_) &&
+ ReadParam(m, iter, &p->unique_) &&
+ ReadParam(m, iter, &p->idb_object_store_id_);
+ }
+ static void Log(const param_type& p, std::wstring* l) {
+ l->append(L"(");
+ LogParam(p.response_id_, l);
+ l->append(L", ");
+ LogParam(p.name_, l);
+ l->append(L", ");
+ LogParam(p.key_path_, l);
+ l->append(L", ");
+ LogParam(p.unique_, l);
+ l->append(L", ");
+ LogParam(p.idb_object_store_id_, l);
+ l->append(L")");
+ }
+};
+
+// Traits for ViewHostMsg_CreateWorker_Params
+template <>
+struct ParamTraits<ViewHostMsg_CreateWorker_Params> {
+ typedef ViewHostMsg_CreateWorker_Params param_type;
+ static void Write(Message* m, const param_type& p) {
+ WriteParam(m, p.url);
+ WriteParam(m, p.is_shared);
+ WriteParam(m, p.name);
+ WriteParam(m, p.document_id);
+ WriteParam(m, p.render_view_route_id);
+ WriteParam(m, p.route_id);
+ WriteParam(m, p.parent_appcache_host_id);
+ WriteParam(m, p.script_resource_appcache_id);
+ }
+ static bool Read(const Message* m, void** iter, param_type* p) {
+ return
+ ReadParam(m, iter, &p->url) &&
+ ReadParam(m, iter, &p->is_shared) &&
+ ReadParam(m, iter, &p->name) &&
+ ReadParam(m, iter, &p->document_id) &&
+ ReadParam(m, iter, &p->render_view_route_id) &&
+ ReadParam(m, iter, &p->route_id) &&
+ ReadParam(m, iter, &p->parent_appcache_host_id) &&
+ ReadParam(m, iter, &p->script_resource_appcache_id);
+ }
+ static void Log(const param_type& p, std::wstring* l) {
+ l->append(L"(");
+ LogParam(p.url, l);
+ l->append(L", ");
+ LogParam(p.is_shared, l);
+ l->append(L", ");
+ LogParam(p.name, l);
+ l->append(L", ");
+ LogParam(p.document_id, l);
+ l->append(L", ");
+ LogParam(p.render_view_route_id, l);
+ l->append(L",");
+ LogParam(p.route_id, l);
+ l->append(L", ");
+ LogParam(p.parent_appcache_host_id, l);
+ l->append(L",");
+ LogParam(p.script_resource_appcache_id, l);
+ l->append(L")");
+ }
+};
+
+// Traits for ShowNotification_Params
+template <>
+struct ParamTraits<ViewHostMsg_ShowNotification_Params> {
+ typedef ViewHostMsg_ShowNotification_Params param_type;
+ static void Write(Message* m, const param_type& p) {
+ WriteParam(m, p.origin);
+ WriteParam(m, p.is_html);
+ WriteParam(m, p.contents_url);
+ WriteParam(m, p.icon_url);
+ WriteParam(m, p.title);
+ WriteParam(m, p.body);
+ WriteParam(m, p.direction);
+ WriteParam(m, p.replace_id);
+ WriteParam(m, p.notification_id);
+ }
+ static bool Read(const Message* m, void** iter, param_type* p) {
+ return
+ ReadParam(m, iter, &p->origin) &&
+ ReadParam(m, iter, &p->is_html) &&
+ ReadParam(m, iter, &p->contents_url) &&
+ ReadParam(m, iter, &p->icon_url) &&
+ ReadParam(m, iter, &p->title) &&
+ ReadParam(m, iter, &p->body) &&
+ ReadParam(m, iter, &p->direction) &&
+ ReadParam(m, iter, &p->replace_id) &&
+ ReadParam(m, iter, &p->notification_id);
+ }
+ static void Log(const param_type &p, std::wstring* l) {
+ l->append(L"(");
+ LogParam(p.origin, l);
+ l->append(L", ");
+ LogParam(p.is_html, l);
+ l->append(L", ");
+ LogParam(p.contents_url, l);
+ l->append(L", ");
+ LogParam(p.icon_url, l);
+ l->append(L", ");
+ LogParam(p.title, l);
+ l->append(L",");
+ LogParam(p.body, l);
+ l->append(L",");
+ LogParam(p.direction, l);
+ l->append(L",");
+ LogParam(p.replace_id, l);
+ l->append(L",");
+ LogParam(p.notification_id, l);
+ l->append(L")");
+ }
+};
+
+// Traits for WebCookie
+template <>
+struct ParamTraits<webkit_glue::WebCookie> {
+ typedef webkit_glue::WebCookie param_type;
+ static void Write(Message* m, const param_type& p) {
+ WriteParam(m, p.name);
+ WriteParam(m, p.value);
+ WriteParam(m, p.domain);
+ WriteParam(m, p.path);
+ WriteParam(m, p.expires);
+ WriteParam(m, p.http_only);
+ WriteParam(m, p.secure);
+ WriteParam(m, p.session);
+ }
+ static bool Read(const Message* m, void** iter, param_type* p) {
+ return
+ ReadParam(m, iter, &p->name) &&
+ ReadParam(m, iter, &p->value) &&
+ ReadParam(m, iter, &p->domain) &&
+ ReadParam(m, iter, &p->path) &&
+ ReadParam(m, iter, &p->expires) &&
+ ReadParam(m, iter, &p->http_only) &&
+ ReadParam(m, iter, &p->secure) &&
+ ReadParam(m, iter, &p->session);
+ }
+ static void Log(const param_type& p, std::wstring* l) {
+ l->append(L"<WebCookie>");
+ }
+};
+
+template<>
+struct ParamTraits<ViewMsg_ExecuteCode_Params> {
+ typedef ViewMsg_ExecuteCode_Params param_type;
+ static void Write(Message* m, const param_type& p) {
+ WriteParam(m, p.request_id);
+ WriteParam(m, p.extension_id);
+ WriteParam(m, p.host_permissions);
+ WriteParam(m, p.is_javascript);
+ WriteParam(m, p.code);
+ WriteParam(m, p.all_frames);
+ }
+ static bool Read(const Message* m, void** iter, param_type* p) {
+ return
+ ReadParam(m, iter, &p->request_id) &&
+ ReadParam(m, iter, &p->extension_id) &&
+ ReadParam(m, iter, &p->host_permissions) &&
+ ReadParam(m, iter, &p->is_javascript) &&
+ ReadParam(m, iter, &p->code) &&
+ ReadParam(m, iter, &p->all_frames);
+ }
+ static void Log(const param_type& p, std::wstring* l) {
+ l->append(L"<ViewMsg_ExecuteCode_Params>");
+ }
+};
+
+template<>
+struct ParamTraits<ViewMsg_New_Params> {
+ typedef ViewMsg_New_Params param_type;
+ static void Write(Message* m, const param_type& p) {
+ WriteParam(m, p.parent_window);
+ WriteParam(m, p.renderer_preferences);
+ WriteParam(m, p.web_preferences);
+ WriteParam(m, p.view_id);
+ WriteParam(m, p.session_storage_namespace_id);
+ WriteParam(m, p.frame_name);
+ }
+
+ static bool Read(const Message* m, void** iter, param_type* p) {
+ return
+ ReadParam(m, iter, &p->parent_window) &&
+ ReadParam(m, iter, &p->renderer_preferences) &&
+ ReadParam(m, iter, &p->web_preferences) &&
+ ReadParam(m, iter, &p->view_id) &&
+ ReadParam(m, iter, &p->session_storage_namespace_id) &&
+ ReadParam(m, iter, &p->frame_name);
+ }
+ static void Log(const param_type& p, std::wstring* l) {
+ l->append(L"(");
+ LogParam(p.parent_window, l);
+ l->append(L", ");
+ LogParam(p.renderer_preferences, l);
+ l->append(L", ");
+ LogParam(p.web_preferences, l);
+ l->append(L", ");
+ LogParam(p.view_id, l);
+ l->append(L", ");
+ LogParam(p.session_storage_namespace_id, l);
+ l->append(L", ");
+ LogParam(p.frame_name, l);
+ l->append(L")");
+ }
+};
+
+template <>
+struct SimilarTypeTraits<TranslateErrors::Type> {
+ typedef int Type;
+};
+
+template<>
+struct ParamTraits<ViewHostMsg_RunFileChooser_Params> {
+ typedef ViewHostMsg_RunFileChooser_Params param_type;
+ static void Write(Message* m, const param_type& p) {
+ WriteParam(m, static_cast<int>(p.mode));
+ WriteParam(m, p.title);
+ WriteParam(m, p.default_file_name);
+ }
+ static bool Read(const Message* m, void** iter, param_type* p) {
+ int mode;
+ if (!ReadParam(m, iter, &mode))
+ return false;
+ if (mode != param_type::Open &&
+ mode != param_type::OpenMultiple &&
+ mode != param_type::Save)
+ return false;
+ p->mode = static_cast<param_type::Mode>(mode);
+ return
+ ReadParam(m, iter, &p->title) &&
+ ReadParam(m, iter, &p->default_file_name);
+ };
+ static void Log(const param_type& p, std::wstring* l) {
+ switch (p.mode) {
+ case param_type::Open:
+ l->append(L"(Open, ");
+ break;
+ case param_type::OpenMultiple:
+ l->append(L"(OpenMultiple, ");
+ break;
+ case param_type::Save:
+ l->append(L"(Save, ");
+ break;
+ default:
+ l->append(L"(UNKNOWN, ");
+ }
+ LogParam(p.title, l);
+ l->append(L", ");
+ LogParam(p.default_file_name, l);
+ }
+};
+
+template<>
+struct ParamTraits<ViewHostMsg_CreateWindow_Params> {
+ typedef ViewHostMsg_CreateWindow_Params param_type;
+ static void Write(Message* m, const param_type& p) {
+ WriteParam(m, p.opener_id);
+ WriteParam(m, p.user_gesture);
+ WriteParam(m, p.window_container_type);
+ WriteParam(m, p.session_storage_namespace_id);
+ WriteParam(m, p.frame_name);
+ }
+ static bool Read(const Message* m, void** iter, param_type* p) {
+ return
+ ReadParam(m, iter, &p->opener_id) &&
+ ReadParam(m, iter, &p->user_gesture) &&
+ ReadParam(m, iter, &p->window_container_type) &&
+ ReadParam(m, iter, &p->session_storage_namespace_id) &&
+ ReadParam(m, iter, &p->frame_name);
+ }
+ static void Log(const param_type& p, std::wstring* l) {
+ l->append(L"(");
+ LogParam(p.opener_id, l);
+ l->append(L", ");
+ LogParam(p.user_gesture, l);
+ l->append(L", ");
+ LogParam(p.window_container_type, l);
+ l->append(L", ");
+ LogParam(p.session_storage_namespace_id, l);
+ l->append(L", ");
+ LogParam(p.frame_name, l);
+ l->append(L")");
+ }
+};
+
+template <>
+struct ParamTraits<ExtensionExtent> {
+ typedef ExtensionExtent param_type;
+ static void Write(Message* m, const param_type& p) {
+ WriteParam(m, p.patterns());
+ }
+ static bool Read(const Message* m, void** iter, param_type* p) {
+ std::vector<URLPattern> patterns;
+ bool success =
+ ReadParam(m, iter, &patterns);
+ if (!success)
+ return false;
+
+ for (size_t i = 0; i < patterns.size(); ++i)
+ p->AddPattern(patterns[i]);
+ return true;
+ }
+ static void Log(const param_type& p, std::wstring* l) {
+ LogParam(p.patterns(), l);
+ }
+};
+
+template <>
+struct ParamTraits<ViewMsg_ExtensionExtentInfo> {
+ typedef ViewMsg_ExtensionExtentInfo param_type;
+ static void Write(Message* m, const param_type& p) {
+ WriteParam(m, p.extension_id);
+ WriteParam(m, p.web_extent);
+ WriteParam(m, p.browse_extent);
+ }
+ static bool Read(const Message* m, void** iter, param_type* p) {
+ return ReadParam(m, iter, &p->extension_id) &&
+ ReadParam(m, iter, &p->web_extent) &&
+ ReadParam(m, iter, &p->browse_extent);
+ }
+ static void Log(const param_type& p, std::wstring* l) {
+ LogParam(p.extension_id, l);
+ }
+};
+
+template <>
+struct ParamTraits<ViewMsg_ExtensionExtentsUpdated_Params> {
+ typedef ViewMsg_ExtensionExtentsUpdated_Params param_type;
+ static void Write(Message* m, const param_type& p) {
+ WriteParam(m, p.extension_apps);
+ }
+ static bool Read(const Message* m, void** iter, param_type* p) {
+ return ReadParam(m, iter, &p->extension_apps);
+ }
+ static void Log(const param_type& p, std::wstring* l) {
+ LogParam(p.extension_apps, l);
+ }
+};
+
+template <>
+struct ParamTraits<WindowContainerType> {
+ typedef WindowContainerType param_type;
+ static void Write(Message* m, const param_type& p) {
+ int val = static_cast<int>(p);
+ WriteParam(m, val);
+ }
+ static bool Read(const Message* m, void** iter, param_type* p) {
+ int val = 0;
+ if (!ReadParam(m, iter, &val) ||
+ val < WINDOW_CONTAINER_TYPE_NORMAL ||
+ val >= WINDOW_CONTAINER_TYPE_MAX_VALUE)
+ return false;
+ *p = static_cast<param_type>(val);
+ return true;
+ }
+ static void Log(const param_type& p, std::wstring* l) {
+ LogParam(p, l);
+ }
+};
+
+template <>
+struct ParamTraits<webkit_glue::WebAccessibility> {
+ typedef webkit_glue::WebAccessibility param_type;
+ static void Write(Message* m, const param_type& p) {
+ WriteParam(m, p.id);
+ WriteParam(m, p.name);
+ WriteParam(m, p.value);
+ WriteParam(m, static_cast<int>(p.role));
+ WriteParam(m, static_cast<int>(p.state));
+ WriteParam(m, p.location);
+ WriteParam(m, p.attributes);
+ WriteParam(m, p.children);
+ }
+ static bool Read(const Message* m, void** iter, param_type* p) {
+ bool ret = ReadParam(m, iter, &p->id);
+ ret = ret && ReadParam(m, iter, &p->name);
+ ret = ret && ReadParam(m, iter, &p->value);
+ int role = -1;
+ ret = ret && ReadParam(m, iter, &role);
+ if (role >= webkit_glue::WebAccessibility::ROLE_NONE &&
+ role < webkit_glue::WebAccessibility::NUM_ROLES) {
+ p->role = static_cast<webkit_glue::WebAccessibility::Role>(role);
+ } else {
+ p->role = webkit_glue::WebAccessibility::ROLE_NONE;
+ }
+ int state = 0;
+ ret = ret && ReadParam(m, iter, &state);
+ p->state = static_cast<webkit_glue::WebAccessibility::State>(state);
+ ret = ret && ReadParam(m, iter, &p->location);
+ ret = ret && ReadParam(m, iter, &p->attributes);
+ ret = ret && ReadParam(m, iter, &p->children);
+ return ret;
+ }
+ static void Log(const param_type& p, std::wstring* l) {
+ l->append(L"(");
+ LogParam(p.id, l);
+ l->append(L", ");
+ LogParam(p.name, l);
+ l->append(L", ");
+ LogParam(p.value, l);
+ l->append(L", ");
+ LogParam(static_cast<int>(p.role), l);
+ l->append(L", ");
+ LogParam(static_cast<int>(p.state), l);
+ l->append(L", ");
+ LogParam(p.location, l);
+ l->append(L", ");
+ LogParam(p.attributes, l);
+ l->append(L", ");
+ LogParam(p.children, l);
+ l->append(L")");
+ }
+};
+
+} // namespace IPC
+
+#define MESSAGES_INTERNAL_FILE "chrome/common/render_messages_internal.h"
+#include "ipc/ipc_message_macros.h"
+
+#endif // CHROME_COMMON_RENDER_MESSAGES_H_
diff --git a/chrome/common/render_messages_internal.h b/chrome/common/render_messages_internal.h
new file mode 100644
index 0000000..2cedec8
--- /dev/null
+++ b/chrome/common/render_messages_internal.h
@@ -0,0 +1,2529 @@
+// Copyright (c) 2010 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.
+
+// This header is meant to be included in multiple passes, hence no traditional
+// header guard.
+// See ipc_message_macros.h for explanation of the macros and passes.
+
+#include <map>
+#include <string>
+#include <vector>
+
+#include "build/build_config.h"
+
+#include "base/file_path.h"
+#include "base/nullable_string16.h"
+#include "base/platform_file.h"
+#include "base/sync_socket.h"
+#include "base/time.h"
+#include "base/values.h"
+#include "chrome/common/content_settings.h"
+#include "chrome/common/extensions/update_manifest.h"
+#include "chrome/common/geoposition.h"
+#include "chrome/common/nacl_types.h"
+#include "chrome/common/notification_type.h"
+#include "chrome/common/page_zoom.h"
+#include "chrome/common/thumbnail_score.h"
+#include "chrome/common/translate_errors.h"
+#include "chrome/common/window_container_type.h"
+#include "gfx/rect.h"
+#include "ipc/ipc_channel_handle.h"
+#include "ipc/ipc_message.h"
+#include "ipc/ipc_message_macros.h"
+#include "third_party/skia/include/core/SkBitmap.h"
+#include "webkit/glue/dom_operations.h"
+#include "webkit/glue/form_field.h"
+#include "webkit/glue/webcursor.h"
+
+#if defined(OS_POSIX)
+#include "base/file_descriptor_posix.h"
+#endif
+
+#if defined(OS_MACOSX)
+#include "chrome/common/font_descriptor_mac.h"
+#endif
+
+// TODO(mpcomplete): rename ViewMsg and ViewHostMsg to something that makes
+// more sense with our current design.
+
+// IPC_MESSAGE macros choke on extra , in the std::map, when expanding. We need
+// to typedef it to avoid that.
+// Substitution map for l10n messages.
+typedef std::map<std::string, std::string> SubstitutionMap;
+
+//-----------------------------------------------------------------------------
+// RenderView messages
+// These are messages sent from the browser to the renderer process.
+
+IPC_BEGIN_MESSAGES(View)
+ // Used typically when recovering from a crash. The new rendering process
+ // sets its global "next page id" counter to the given value.
+ IPC_MESSAGE_CONTROL1(ViewMsg_SetNextPageID,
+ int32 /* next_page_id */)
+
+ // Sends System Colors corresponding to a set of CSS color keywords
+ // down the pipe.
+ // This message must be sent to the renderer immediately on launch
+ // before creating any new views.
+ // The message can also be sent during a renderer's lifetime if system colors
+ // are updated.
+ // TODO(jeremy): Possibly change IPC format once we have this all hooked up.
+ IPC_MESSAGE_ROUTED1(ViewMsg_SetCSSColors,
+ std::vector<CSSColors::CSSColorMapping>)
+
+ // Tells the renderer to create a new view.
+ // This message is slightly different, the view it takes (via
+ // ViewMsg_New_Params) is the view to create, the message itself is sent as a
+ // non-view control message.
+ IPC_MESSAGE_CONTROL1(ViewMsg_New,
+ ViewMsg_New_Params)
+
+ // Tells the renderer to set its maximum cache size to the supplied value
+ IPC_MESSAGE_CONTROL3(ViewMsg_SetCacheCapacities,
+ size_t /* min_dead_capacity */,
+ size_t /* max_dead_capacity */,
+ size_t /* capacity */)
+
+ // Reply in response to ViewHostMsg_ShowView or ViewHostMsg_ShowWidget.
+ // similar to the new command, but used when the renderer created a view
+ // first, and we need to update it
+ IPC_MESSAGE_ROUTED1(ViewMsg_CreatingNew_ACK,
+ gfx::NativeViewId /* parent_hwnd */)
+
+ // Sends updated preferences to the renderer.
+ IPC_MESSAGE_ROUTED1(ViewMsg_SetRendererPrefs,
+ RendererPreferences)
+
+ // Tells the renderer to perform the given action on the media player
+ // located at the given point.
+ IPC_MESSAGE_ROUTED2(ViewMsg_MediaPlayerActionAt,
+ gfx::Point, /* location */
+ WebKit::WebMediaPlayerAction)
+
+ // Tells the render view to close.
+ IPC_MESSAGE_ROUTED0(ViewMsg_Close)
+
+ // Tells the render view to change its size. A ViewHostMsg_PaintRect message
+ // is generated in response provided new_size is not empty and not equal to
+ // the view's current size. The generated ViewHostMsg_PaintRect message will
+ // have the IS_RESIZE_ACK flag set. It also receives the resizer rect so that
+ // we don't have to fetch it every time WebKit asks for it.
+ IPC_MESSAGE_ROUTED2(ViewMsg_Resize,
+ gfx::Size /* new_size */,
+ gfx::Rect /* resizer_rect */)
+
+ // Sent to inform the view that it was hidden. This allows it to reduce its
+ // resource utilization.
+ IPC_MESSAGE_ROUTED0(ViewMsg_WasHidden)
+
+ // Tells the render view that it is no longer hidden (see WasHidden), and the
+ // render view is expected to respond with a full repaint if needs_repainting
+ // is true. In that case, the generated ViewHostMsg_PaintRect message will
+ // have the IS_RESTORE_ACK flag set. If needs_repainting is false, then this
+ // message does not trigger a message in response.
+ IPC_MESSAGE_ROUTED1(ViewMsg_WasRestored,
+ bool /* needs_repainting */)
+
+ // Tells the render view to capture a thumbnail image of the page. The
+ // render view responds with a ViewHostMsg_Thumbnail.
+ IPC_MESSAGE_ROUTED0(ViewMsg_CaptureThumbnail)
+
+ // Tells the render view to capture a thumbnail image of the page. The
+ // render view responds with a ViewHostMsg_Snapshot.
+ IPC_MESSAGE_ROUTED0(ViewMsg_CaptureSnapshot)
+
+ // Tells the render view to switch the CSS to print media type, renders every
+ // requested pages and switch back the CSS to display media type.
+ IPC_MESSAGE_ROUTED0(ViewMsg_PrintPages)
+
+ // Tells the render view that printing is done so it can clean up.
+ IPC_MESSAGE_ROUTED2(ViewMsg_PrintingDone,
+ int /* document_cookie */,
+ bool /* success */)
+
+ // Tells the renderer to dump as much memory as it can, perhaps because we
+ // have memory pressure or the renderer is (or will be) paged out. This
+ // should only result in purging objects we can recalculate, e.g. caches or
+ // JS garbage, not in purging irreplaceable objects.
+ IPC_MESSAGE_CONTROL0(ViewMsg_PurgeMemory)
+
+ // Sent to render the view into the supplied transport DIB, resize
+ // the web widget to match the |page_size|, scale it by the
+ // appropriate scale to make it fit the |desired_size|, and return
+ // it. In response to this message, the host generates a
+ // ViewHostMsg_PaintAtSize_ACK message. Note that the DIB *must* be
+ // the right size to receive an RGBA image at the |desired_size|.
+ // |tag| is sent along with ViewHostMsg_PaintAtSize_ACK unmodified to
+ // identify the PaintAtSize message the ACK belongs to.
+ IPC_MESSAGE_ROUTED4(ViewMsg_PaintAtSize,
+ TransportDIB::Handle /* dib_handle */,
+ int /* tag */,
+ gfx::Size /* page_size */,
+ gfx::Size /* desired_size */)
+
+ // Tells the render view that a ViewHostMsg_UpdateRect message was processed.
+ // This signals the render view that it can send another UpdateRect message.
+ IPC_MESSAGE_ROUTED0(ViewMsg_UpdateRect_ACK)
+
+ // Replies to creating and updating videos.
+ IPC_MESSAGE_ROUTED1(ViewMsg_CreateVideo_ACK,
+ int32 /* video_id */)
+ IPC_MESSAGE_ROUTED1(ViewMsg_UpdateVideo_ACK,
+ int32 /* video_id */)
+
+ // Message payload includes:
+ // 1. A blob that should be cast to WebInputEvent
+ // 2. An optional boolean value indicating if a RawKeyDown event is associated
+ // to a keyboard shortcut of the browser.
+ IPC_MESSAGE_ROUTED0(ViewMsg_HandleInputEvent)
+
+ // This message notifies the renderer that the next key event is bound to one
+ // or more pre-defined edit commands. If the next key event is not handled
+ // by webkit, the specified edit commands shall be executed against current
+ // focused frame.
+ // Parameters
+ // * edit_commands (see chrome/common/edit_command_types.h)
+ // Contains one or more edit commands.
+ // See third_party/WebKit/WebCore/editing/EditorCommand.cpp for detailed
+ // definition of webkit edit commands.
+ //
+ // This message must be sent just before sending a key event.
+ IPC_MESSAGE_ROUTED1(ViewMsg_SetEditCommandsForNextKeyEvent,
+ EditCommands /* edit_commands */)
+
+ // Message payload is the name/value of a WebCore edit command to execute.
+ IPC_MESSAGE_ROUTED2(ViewMsg_ExecuteEditCommand,
+ std::string, /* name */
+ std::string /* value */)
+
+ IPC_MESSAGE_ROUTED0(ViewMsg_MouseCaptureLost)
+
+ // TODO(darin): figure out how this meshes with RestoreFocus
+ IPC_MESSAGE_ROUTED1(ViewMsg_SetFocus, bool /* enable */)
+
+ // Tells the renderer to focus the first (last if reverse is true) focusable
+ // node.
+ IPC_MESSAGE_ROUTED1(ViewMsg_SetInitialFocus, bool /* reverse */)
+
+ // Tells the renderer to perform the specified navigation, interrupting any
+ // existing navigation.
+ IPC_MESSAGE_ROUTED1(ViewMsg_Navigate, ViewMsg_Navigate_Params)
+
+ IPC_MESSAGE_ROUTED0(ViewMsg_Stop)
+
+ // Tells the renderer to reload the current focused frame
+ IPC_MESSAGE_ROUTED0(ViewMsg_ReloadFrame)
+
+ // This message notifies the renderer that the user has closed the FindInPage
+ // window (and what action to take regarding the selection).
+ IPC_MESSAGE_ROUTED1(ViewMsg_StopFinding,
+ ViewMsg_StopFinding_Params /* action */)
+
+ // These messages are typically generated from context menus and request the
+ // renderer to apply the specified operation to the current selection.
+ IPC_MESSAGE_ROUTED0(ViewMsg_Undo)
+ IPC_MESSAGE_ROUTED0(ViewMsg_Redo)
+ IPC_MESSAGE_ROUTED0(ViewMsg_Cut)
+ IPC_MESSAGE_ROUTED0(ViewMsg_Copy)
+#if defined(OS_MACOSX)
+ IPC_MESSAGE_ROUTED0(ViewMsg_CopyToFindPboard)
+#endif
+ IPC_MESSAGE_ROUTED0(ViewMsg_Paste)
+ // Replaces the selected region or a word around the cursor with the
+ // specified string.
+ IPC_MESSAGE_ROUTED1(ViewMsg_Replace, string16)
+ IPC_MESSAGE_ROUTED0(ViewMsg_ToggleSpellCheck)
+ IPC_MESSAGE_ROUTED0(ViewMsg_Delete)
+ IPC_MESSAGE_ROUTED0(ViewMsg_SelectAll)
+ IPC_MESSAGE_ROUTED1(ViewMsg_ToggleSpellPanel, bool)
+
+ // This message tells the renderer to advance to the next misspelling. It is
+ // sent when the user clicks the "Find Next" button on the spelling panel.
+ IPC_MESSAGE_ROUTED0(ViewMsg_AdvanceToNextMisspelling)
+
+ // Copies the image at location x, y to the clipboard (if there indeed is an
+ // image at that location).
+ IPC_MESSAGE_ROUTED2(ViewMsg_CopyImageAt,
+ int /* x */,
+ int /* y */)
+
+ // History system notification that the visited link database has been
+ // replaced. It has one SharedMemoryHandle argument consisting of the table
+ // handle. This handle is valid in the context of the renderer
+ IPC_MESSAGE_CONTROL1(ViewMsg_VisitedLink_NewTable, base::SharedMemoryHandle)
+
+ // History system notification that a link has been added and the link
+ // coloring state for the given hash must be re-calculated.
+ IPC_MESSAGE_CONTROL1(ViewMsg_VisitedLink_Add, std::vector<uint64>)
+
+ // History system notification that one or more history items have been
+ // deleted, which at this point means that all link coloring state must be
+ // re-calculated.
+ IPC_MESSAGE_CONTROL0(ViewMsg_VisitedLink_Reset)
+
+ // Notification that the user scripts have been updated. It has one
+ // SharedMemoryHandle argument consisting of the pickled script data. This
+ // handle is valid in the context of the renderer.
+ IPC_MESSAGE_CONTROL1(ViewMsg_UserScripts_UpdatedScripts,
+ base::SharedMemoryHandle)
+
+ // Sent when the user wants to search for a word on the page (find in page).
+ IPC_MESSAGE_ROUTED3(ViewMsg_Find,
+ int /* request_id */,
+ string16 /* search_text */,
+ WebKit::WebFindOptions)
+
+ // Send from the renderer to the browser to return the script running result.
+ IPC_MESSAGE_ROUTED2(ViewMsg_ExecuteCodeFinished,
+ int, /* request id */
+ bool /* whether the script ran successfully */)
+
+ // Sent when the headers are available for a resource request.
+ IPC_MESSAGE_ROUTED2(ViewMsg_Resource_ReceivedResponse,
+ int /* request_id */,
+ ResourceResponseHead)
+
+ // Sent when cached metadata from a resource request is ready.
+ IPC_MESSAGE_ROUTED2(ViewMsg_Resource_ReceivedCachedMetadata,
+ int /* request_id */,
+ std::vector<char> /* data */)
+
+ // Sent as download progress is being made, size of the resource may be
+ // unknown, in that case |size| is -1.
+ IPC_MESSAGE_ROUTED3(ViewMsg_Resource_DownloadProgress,
+ int /* request_id */,
+ int64 /* position */,
+ int64 /* size */)
+
+ // Sent as upload progress is being made.
+ IPC_MESSAGE_ROUTED3(ViewMsg_Resource_UploadProgress,
+ int /* request_id */,
+ int64 /* position */,
+ int64 /* size */)
+
+ // Sent when the request has been redirected. The receiver is expected to
+ // respond with either a FollowRedirect message (if the redirect is to be
+ // followed) or a CancelRequest message (if it should not be followed).
+ IPC_MESSAGE_ROUTED3(ViewMsg_Resource_ReceivedRedirect,
+ int /* request_id */,
+ GURL /* new_url */,
+ ResourceResponseHead)
+
+ // Sent when some data from a resource request is ready. The handle should
+ // already be mapped into the process that receives this message.
+ IPC_MESSAGE_ROUTED3(ViewMsg_Resource_DataReceived,
+ int /* request_id */,
+ base::SharedMemoryHandle /* data */,
+ int /* data_len */)
+
+ // Sent when the request has been completed.
+ IPC_MESSAGE_ROUTED3(ViewMsg_Resource_RequestComplete,
+ int /* request_id */,
+ URLRequestStatus /* status */,
+ std::string /* security info */)
+
+ // Sent when user prompting is required before a ViewHostMsg_GetCookies
+ // message can complete. This message indicates that the renderer should
+ // pump messages while waiting for cookies.
+ IPC_MESSAGE_CONTROL0(ViewMsg_SignalCookiePromptEvent)
+
+ // Request for the renderer to evaluate an xpath to a frame and execute a
+ // javascript: url in that frame's context. The message is completely
+ // asynchronous and no corresponding response message is sent back.
+ //
+ // frame_xpath contains the modified xpath notation to identify an inner
+ // subframe (starting from the root frame). It is a concatenation of
+ // number of smaller xpaths delimited by '\n'. Each chunk in the string can
+ // be evaluated to a frame in its parent-frame's context.
+ //
+ // Example: /html/body/iframe/\n/html/body/div/iframe/\n/frameset/frame[0]
+ // can be broken into 3 xpaths
+ // /html/body/iframe evaluates to an iframe within the root frame
+ // /html/body/div/iframe evaluates to an iframe within the level-1 iframe
+ // /frameset/frame[0] evaluates to first frame within the level-2 iframe
+ //
+ // jscript_url is the string containing the javascript: url to be executed
+ // in the target frame's context. The string should start with "javascript:"
+ // and continue with a valid JS text.
+ IPC_MESSAGE_ROUTED2(ViewMsg_ScriptEvalRequest,
+ std::wstring, /* frame_xpath */
+ std::wstring /* jscript_url */)
+
+ // Request for the renderer to evaluate an xpath to a frame and insert css
+ // into that frame's document. See ViewMsg_ScriptEvalRequest for details on
+ // allowed xpath expressions.
+ IPC_MESSAGE_ROUTED3(ViewMsg_CSSInsertRequest,
+ std::wstring, /* frame_xpath */
+ std::string, /* css string */
+ std::string /* element id */)
+
+ // Log a message to the console of the target frame
+ IPC_MESSAGE_ROUTED3(ViewMsg_AddMessageToConsole,
+ string16 /* frame_xpath */,
+ string16 /* message */,
+ WebKit::WebConsoleMessage::Level /* message_level */)
+
+ // RenderViewHostDelegate::RenderViewCreated method sends this message to a
+ // new renderer to notify it that it will host developer tools UI and should
+ // set up all neccessary bindings and create DevToolsClient instance that
+ // will handle communication with inspected page DevToolsAgent.
+ IPC_MESSAGE_ROUTED0(ViewMsg_SetupDevToolsClient)
+
+ // Change the zoom level for the current main frame. If the level actually
+ // changes, a ViewHostMsg_DidZoomURL message will be sent back to the browser
+ // telling it what url got zoomed and what its current zoom level is.
+ IPC_MESSAGE_ROUTED1(ViewMsg_Zoom,
+ PageZoom::Function /* function */)
+
+ // Set the zoom level for a particular url that the renderer is in the
+ // process of loading. This will be stored, to be used if the load commits
+ // and ignored otherwise.
+ IPC_MESSAGE_ROUTED2(ViewMsg_SetZoomLevelForLoadingURL,
+ GURL /* url */,
+ int /* zoom_level */)
+
+ // Set the zoom level for a particular url, so all render views
+ // displaying this url can update their zoom levels to match.
+ IPC_MESSAGE_CONTROL2(ViewMsg_SetZoomLevelForCurrentURL,
+ GURL /* url */,
+ int /* zoom_level */)
+
+ // Set the content settings for a particular url that the renderer is in the
+ // process of loading. This will be stored, to be used if the load commits
+ // and ignored otherwise.
+ IPC_MESSAGE_ROUTED2(ViewMsg_SetContentSettingsForLoadingURL,
+ GURL /* url */,
+ ContentSettings /* content_settings */)
+
+ // Set the content settings for a particular url, so all render views
+ // displaying this host url update their content settings to match.
+ IPC_MESSAGE_CONTROL2(ViewMsg_SetContentSettingsForCurrentURL,
+ GURL /* url */,
+ ContentSettings /* content_settings */)
+
+ // Change encoding of page in the renderer.
+ IPC_MESSAGE_ROUTED1(ViewMsg_SetPageEncoding,
+ std::string /*new encoding name*/)
+
+ // Reset encoding of page in the renderer back to default.
+ IPC_MESSAGE_ROUTED0(ViewMsg_ResetPageEncodingToDefault)
+
+ // Requests the renderer to reserve a range of page ids.
+ IPC_MESSAGE_ROUTED1(ViewMsg_ReservePageIDRange,
+ int /* size_of_range */)
+
+ // Fill a form with data and optionally submit it
+ IPC_MESSAGE_ROUTED1(ViewMsg_FormFill,
+ webkit_glue::FormData /* form */)
+
+ // Fill a password form and prepare field autocomplete for multiple
+ // matching logins.
+ IPC_MESSAGE_ROUTED1(ViewMsg_FillPasswordForm,
+ webkit_glue::PasswordFormFillData)
+
+ // D&d drop target messages.
+ IPC_MESSAGE_ROUTED4(ViewMsg_DragTargetDragEnter,
+ WebDropData /* drop_data */,
+ gfx::Point /* client_pt */,
+ gfx::Point /* screen_pt */,
+ WebKit::WebDragOperationsMask /* ops_allowed */)
+ IPC_MESSAGE_ROUTED3(ViewMsg_DragTargetDragOver,
+ gfx::Point /* client_pt */,
+ gfx::Point /* screen_pt */,
+ WebKit::WebDragOperationsMask /* ops_allowed */)
+ IPC_MESSAGE_ROUTED0(ViewMsg_DragTargetDragLeave)
+ IPC_MESSAGE_ROUTED2(ViewMsg_DragTargetDrop,
+ gfx::Point /* client_pt */,
+ gfx::Point /* screen_pt */)
+
+ // Notifies the renderer of updates in mouse position of an in-progress
+ // drag. if |ended| is true, then the user has ended the drag operation.
+ IPC_MESSAGE_ROUTED4(ViewMsg_DragSourceEndedOrMoved,
+ gfx::Point /* client_pt */,
+ gfx::Point /* screen_pt */,
+ bool /* ended */,
+ WebKit::WebDragOperation /* drag_operation */)
+
+ // Notifies the renderer that the system DoDragDrop call has ended.
+ IPC_MESSAGE_ROUTED0(ViewMsg_DragSourceSystemDragEnded)
+
+ // Used to tell a render view whether it should expose various bindings
+ // that allow JS content extended privileges. See BindingsPolicy for valid
+ // flag values.
+ IPC_MESSAGE_ROUTED1(ViewMsg_AllowBindings,
+ int /* enabled_bindings_flags */)
+
+ // Tell the renderer to add a property to the DOMUI binding object. This
+ // only works if we allowed DOMUI bindings.
+ IPC_MESSAGE_ROUTED2(ViewMsg_SetDOMUIProperty,
+ std::string /* property_name */,
+ std::string /* property_value_json */)
+
+ // This message starts/stop monitoring the input method status of the focused
+ // edit control of a renderer process.
+ // Parameters
+ // * is_active (bool)
+ // Indicates if an input method is active in the browser process.
+ // The possible actions when a renderer process receives this message are
+ // listed below:
+ // Value Action
+ // true Start sending IPC message ViewHostMsg_ImeUpdateTextInputState
+ // to notify the input method status of the focused edit control.
+ // false Stop sending IPC message ViewHostMsg_ImeUpdateTextInputState.
+ IPC_MESSAGE_ROUTED1(ViewMsg_SetInputMethodActive,
+ bool /* is_active */)
+
+ // This message sends a string being composed with an input method.
+ IPC_MESSAGE_ROUTED4(
+ ViewMsg_ImeSetComposition,
+ string16, /* text */
+ std::vector<WebKit::WebCompositionUnderline>, /* underlines */
+ int, /* selectiont_start */
+ int /* selection_end */)
+
+ // This message confirms an ongoing composition.
+ IPC_MESSAGE_ROUTED0(ViewMsg_ImeConfirmComposition)
+
+ // This passes a set of webkit preferences down to the renderer.
+ IPC_MESSAGE_ROUTED1(ViewMsg_UpdateWebPreferences, WebPreferences)
+
+ // Used to notify the render-view that the browser has received a reply for
+ // the Find operation and is interested in receiving the next one. This is
+ // used to prevent the renderer from spamming the browser process with
+ // results.
+ IPC_MESSAGE_ROUTED0(ViewMsg_FindReplyACK)
+
+ // Used to notify the render-view that we have received a target URL. Used
+ // to prevent target URLs spamming the browser.
+ IPC_MESSAGE_ROUTED0(ViewMsg_UpdateTargetURL_ACK)
+
+ // Sets the alternate error page URL (link doctor) for the renderer process.
+ IPC_MESSAGE_ROUTED1(ViewMsg_SetAltErrorPageURL, GURL)
+
+ // Install the first missing pluign.
+ IPC_MESSAGE_ROUTED0(ViewMsg_InstallMissingPlugin)
+
+ // Tells the renderer to empty its plugin list cache, optional reloading
+ // pages containing plugins.
+ IPC_MESSAGE_CONTROL1(ViewMsg_PurgePluginListCache,
+ bool /* reload_pages */)
+
+ IPC_MESSAGE_ROUTED1(ViewMsg_RunFileChooserResponse,
+ std::vector<FilePath> /* selected files */)
+
+ // Used to instruct the RenderView to go into "view source" mode.
+ IPC_MESSAGE_ROUTED0(ViewMsg_EnableViewSourceMode)
+
+ // Get all savable resource links from current webpage, include main
+ // frame and sub-frame.
+ IPC_MESSAGE_ROUTED1(ViewMsg_GetAllSavableResourceLinksForCurrentPage,
+ GURL /* url of page which is needed to save */)
+
+ // Get html data by serializing all frames of current page with lists
+ // which contain all resource links that have local copy.
+ IPC_MESSAGE_ROUTED3(ViewMsg_GetSerializedHtmlDataForCurrentPageWithLocalLinks,
+ std::vector<GURL> /* urls that have local copy */,
+ std::vector<FilePath> /* paths of local copy */,
+ FilePath /* local directory path */)
+
+ // Requests application info for the page. The renderer responds back with
+ // ViewHostMsg_DidGetApplicationInfo.
+ IPC_MESSAGE_ROUTED1(ViewMsg_GetApplicationInfo, int32 /*page_id*/)
+
+ // Requests the renderer to download the specified favicon image encode it as
+ // PNG and send the PNG data back ala ViewHostMsg_DidDownloadFavIcon.
+ IPC_MESSAGE_ROUTED3(ViewMsg_DownloadFavIcon,
+ int /* identifier for the request */,
+ GURL /* URL of the image */,
+ int /* Size of the image. Normally 0, but set if you have
+ a preferred image size to request, such as when
+ downloading the favicon */)
+
+ // When a renderer sends a ViewHostMsg_Focus to the browser process,
+ // the browser has the option of sending a ViewMsg_CantFocus back to
+ // the renderer.
+ IPC_MESSAGE_ROUTED0(ViewMsg_CantFocus)
+
+ // Instructs the renderer to invoke the frame's shouldClose method, which
+ // runs the onbeforeunload event handler. Expects the result to be returned
+ // via ViewHostMsg_ShouldClose.
+ IPC_MESSAGE_ROUTED0(ViewMsg_ShouldClose)
+
+ // Instructs the renderer to close the current page, including running the
+ // onunload event handler. See the struct in render_messages.h for more.
+ //
+ // Expects a ClosePage_ACK message when finished, where the parameters are
+ // echoed back.
+ IPC_MESSAGE_ROUTED1(ViewMsg_ClosePage,
+ ViewMsg_ClosePage_Params)
+
+ // Asks the renderer to send back stats on the WebCore cache broken down by
+ // resource types.
+ IPC_MESSAGE_CONTROL0(ViewMsg_GetCacheResourceStats)
+
+ // Asks the renderer to send back Histograms.
+ IPC_MESSAGE_CONTROL1(ViewMsg_GetRendererHistograms,
+ int /* sequence number of Renderer Histograms. */)
+
+#if defined(USE_TCMALLOC)
+ // Asks the renderer to send back tcmalloc stats.
+ IPC_MESSAGE_CONTROL0(ViewMsg_GetRendererTcmalloc)
+#endif
+
+ // Asks the renderer to send back V8 heap stats.
+ IPC_MESSAGE_CONTROL0(ViewMsg_GetV8HeapStats)
+
+ // Notifies the renderer about ui theme changes
+ IPC_MESSAGE_ROUTED0(ViewMsg_ThemeChanged)
+
+ // Notifies the renderer that a paint is to be generated for the rectangle
+ // passed in.
+ IPC_MESSAGE_ROUTED1(ViewMsg_Repaint,
+ gfx::Size /* The view size to be repainted */)
+
+ // Posts a message to the renderer.
+ IPC_MESSAGE_ROUTED3(ViewMsg_HandleMessageFromExternalHost,
+ std::string /* The message */,
+ std::string /* The origin */,
+ std::string /* The target*/)
+
+ // Sent to the renderer when a popup window should no longer count against
+ // the current popup count (either because it's not a popup or because it was
+ // a generated by a user action or because a constrained popup got turned
+ // into a full window).
+ IPC_MESSAGE_ROUTED0(ViewMsg_DisassociateFromPopupCount)
+
+ // The browser sends this to a renderer process in response to a
+ // ViewHostMsg_EstablishGpuChannel message.
+ IPC_MESSAGE_CONTROL1(ViewMsg_GpuChannelEstablished,
+ IPC::ChannelHandle /* handle to channel */)
+
+ // Notifies the renderer of the appcache that has been selected for a
+ // a particular host. This is sent in reply to AppCacheMsg_SelectCache.
+ IPC_MESSAGE_CONTROL3(AppCacheMsg_CacheSelected,
+ int /* host_id */,
+ int64 /* appcache_id */,
+ appcache::Status)
+
+ // Notifies the renderer of an AppCache status change.
+ IPC_MESSAGE_CONTROL2(AppCacheMsg_StatusChanged,
+ std::vector<int> /* host_ids */,
+ appcache::Status)
+
+ // Notifies the renderer of an AppCache event other than the
+ // progress event which has a seperate message.
+ IPC_MESSAGE_CONTROL2(AppCacheMsg_EventRaised,
+ std::vector<int> /* host_ids */,
+ appcache::EventID)
+
+ // Notifies the renderer of an AppCache progress event.
+ IPC_MESSAGE_CONTROL4(AppCacheMsg_ProgressEventRaised,
+ std::vector<int> /* host_ids */,
+ GURL /* url being processed */,
+ int /* total */,
+ int /* complete */)
+
+ // Notifies the renderer of an AppCache error event.
+ IPC_MESSAGE_CONTROL2(AppCacheMsg_ErrorEventRaised,
+ std::vector<int> /* host_ids */,
+ std::string /* error_message */)
+
+ // Notifies the renderer of an AppCache logging message.
+ IPC_MESSAGE_CONTROL3(AppCacheMsg_LogMessage,
+ int /* host_id */,
+ int /* log_level */,
+ std::string /* message */)
+
+ // Notifies the renderer of the fact that AppCache access was blocked.
+ IPC_MESSAGE_CONTROL2(AppCacheMsg_ContentBlocked,
+ int /* host_id */,
+ GURL /* manifest_url */)
+
+ // Reply to the ViewHostMsg_QueryFormFieldAutoFill message with the
+ // AutoFill suggestions.
+ IPC_MESSAGE_ROUTED4(ViewMsg_AutoFillSuggestionsReturned,
+ int /* id of the request message */,
+ std::vector<string16> /* names */,
+ std::vector<string16> /* labels */,
+ std::vector<int> /* unique_ids */)
+
+ // Reply to the ViewHostMsg_FillAutoFillFormData message with the
+ // AutoFill form data.
+ IPC_MESSAGE_ROUTED2(ViewMsg_AutoFillFormDataFilled,
+ int /* id of the request message */,
+ webkit_glue::FormData /* form data */)
+
+ // Sent by the Browser process to alert a window about whether a it should
+ // allow a scripted window.close(). The renderer assumes every new window is a
+ // blocked popup until notified otherwise.
+ IPC_MESSAGE_ROUTED1(ViewMsg_AllowScriptToClose,
+ bool /* script_can_close */)
+
+ // Sent by AudioRendererHost to renderer to request an audio packet.
+ IPC_MESSAGE_ROUTED3(ViewMsg_RequestAudioPacket,
+ int /* stream id */,
+ uint32 /* bytes in buffer */,
+ int64 /* message timestamp */)
+
+ // Tell the renderer process that the audio stream has been created, renderer
+ // process would be given a ShareMemoryHandle that it should write to from
+ // then on.
+ IPC_MESSAGE_ROUTED3(ViewMsg_NotifyAudioStreamCreated,
+ int /* stream id */,
+ base::SharedMemoryHandle /* handle */,
+ uint32 /* length */)
+
+ // Tell the renderer process that a low latency audio stream has been created,
+ // renderer process would be given a SyncSocket that it should write to from
+ // then on.
+#if defined(OS_WIN)
+ IPC_MESSAGE_ROUTED4(ViewMsg_NotifyLowLatencyAudioStreamCreated,
+ int /* stream id */,
+ base::SharedMemoryHandle /* handle */,
+ base::SyncSocket::Handle /* socket handle */,
+ uint32 /* length */)
+#else
+ IPC_MESSAGE_ROUTED4(ViewMsg_NotifyLowLatencyAudioStreamCreated,
+ int /* stream id */,
+ base::SharedMemoryHandle /* handle */,
+ base::FileDescriptor /* socket handle */,
+ uint32 /* length */)
+#endif
+
+ // Notification message sent from AudioRendererHost to renderer for state
+ // update after the renderer has requested a Create/Start/Close.
+ IPC_MESSAGE_ROUTED2(ViewMsg_NotifyAudioStreamStateChanged,
+ int /* stream id */,
+ ViewMsg_AudioStreamState_Params /* new state */)
+
+ IPC_MESSAGE_ROUTED2(ViewMsg_NotifyAudioStreamVolume,
+ int /* stream id */,
+ double /* volume */)
+
+ // Notification that a move or resize renderer's containing window has
+ // started.
+ IPC_MESSAGE_ROUTED0(ViewMsg_MoveOrResizeStarted)
+
+ // The browser sends this message in response to all extension api calls.
+ IPC_MESSAGE_ROUTED4(ViewMsg_ExtensionResponse,
+ int /* request_id */,
+ bool /* success */,
+ std::string /* response */,
+ std::string /* error */)
+
+ // This message is optionally routed. If used as a control message, it
+ // will call a javascript function in every registered context in the
+ // target process. If routed, it will be restricted to the contexts that
+ // are part of the target RenderView.
+ // |args| is a list of primitive Value types that are passed to the function.
+ IPC_MESSAGE_ROUTED4(ViewMsg_ExtensionMessageInvoke,
+ std::string /* function_name */,
+ ListValue /* args */,
+ bool /* requires incognito access */,
+ GURL /* event URL */)
+
+ // Tell the renderer process all known extension function names.
+ IPC_MESSAGE_CONTROL1(ViewMsg_Extension_SetFunctionNames,
+ std::vector<std::string>)
+
+ // Tell the renderer process which permissions the given extension has. See
+ // Extension::Permissions for which elements correspond to which permissions.
+ IPC_MESSAGE_CONTROL2(ViewMsg_Extension_SetAPIPermissions,
+ std::string /* extension_id */,
+ std::vector<std::string> /* permissions */)
+
+ // Tell the renderer process which host permissions the given extension has.
+ IPC_MESSAGE_CONTROL2(
+ ViewMsg_Extension_SetHostPermissions,
+ GURL /* source extension's origin */,
+ std::vector<URLPattern> /* URLPatterns the extension can access */)
+
+ // Tell the renderer process that the given extension is enabled or disabled
+ // for incognito mode.
+ IPC_MESSAGE_CONTROL2(ViewMsg_Extension_ExtensionSetIncognitoEnabled,
+ std::string /* extension_id */,
+ bool /* enabled */)
+
+ // Tell the renderer process all known page action ids for a particular
+ // extension.
+ IPC_MESSAGE_CONTROL2(ViewMsg_Extension_UpdatePageActions,
+ std::string /* extension_id */,
+ std::vector<std::string> /* page_action_ids */)
+
+ // Changes the text direction of the currently selected input field (if any).
+ IPC_MESSAGE_ROUTED1(ViewMsg_SetTextDirection,
+ WebKit::WebTextDirection /* direction */)
+
+ // Tells the renderer to clear the focused node (if any).
+ IPC_MESSAGE_ROUTED0(ViewMsg_ClearFocusedNode)
+
+ // Make the RenderView transparent and render it onto a custom background. The
+ // background will be tiled in both directions if it is not large enough.
+ IPC_MESSAGE_ROUTED1(ViewMsg_SetBackground,
+ SkBitmap /* background */)
+
+ // Reply to ViewHostMsg_RequestMove, ViewHostMsg_ShowView, and
+ // ViewHostMsg_ShowWidget to inform the renderer that the browser has
+ // processed the move. The browser may have ignored the move, but it finished
+ // processing. This is used because the renderer keeps a temporary cache of
+ // the widget position while these asynchronous operations are in progress.
+ IPC_MESSAGE_ROUTED0(ViewMsg_Move_ACK)
+
+ // Used to instruct the RenderView to send back updates to the preferred size.
+ IPC_MESSAGE_ROUTED1(ViewMsg_EnablePreferredSizeChangedMode, int /*flags*/)
+
+ // Used to tell the renderer not to add scrollbars with height and
+ // width below a threshold.
+ IPC_MESSAGE_ROUTED1(ViewMsg_DisableScrollbarsForSmallWindows,
+ gfx::Size /* disable_scrollbar_size_limit */)
+
+ // Used to inform the renderer that the browser has displayed its
+ // requested notification.
+ IPC_MESSAGE_ROUTED1(ViewMsg_PostDisplayToNotificationObject,
+ int /* notification_id */)
+
+ // Used to inform the renderer that the browser has encountered an error
+ // trying to display a notification.
+ IPC_MESSAGE_ROUTED2(ViewMsg_PostErrorToNotificationObject,
+ int /* notification_id */,
+ string16 /* message */)
+
+ // Informs the renderer that the one if its notifications has closed.
+ IPC_MESSAGE_ROUTED2(ViewMsg_PostCloseToNotificationObject,
+ int /* notification_id */,
+ bool /* by_user */)
+
+ // Informs the renderer that the one if its notifications has closed.
+ IPC_MESSAGE_ROUTED1(ViewMsg_PermissionRequestDone,
+ int /* request_id */)
+
+ // Activate/deactivate the RenderView (i.e., set its controls' tint
+ // accordingly, etc.).
+ IPC_MESSAGE_ROUTED1(ViewMsg_SetActive,
+ bool /* active */)
+
+#if defined(OS_MACOSX)
+ // Let the RenderView know its window has changed visibility.
+ IPC_MESSAGE_ROUTED1(ViewMsg_SetWindowVisibility,
+ bool /* visibile */)
+
+ // Let the RenderView know its window's frame has changed.
+ IPC_MESSAGE_ROUTED2(ViewMsg_WindowFrameChanged,
+ gfx::Rect /* window frame */,
+ gfx::Rect /* content view frame */)
+#endif
+
+ // Response message to ViewHostMsg_CreateShared/DedicatedWorker.
+ // Sent when the worker has started.
+ IPC_MESSAGE_ROUTED0(ViewMsg_WorkerCreated)
+
+ // Tell the renderer which browser window it's being attached to.
+ IPC_MESSAGE_ROUTED1(ViewMsg_UpdateBrowserWindowId,
+ int /* id of browser window */)
+
+ // Tell the renderer which type this view is.
+ IPC_MESSAGE_ROUTED1(ViewMsg_NotifyRenderViewType,
+ ViewType::Type /* view_type */)
+
+ // Notification that renderer should run some JavaScript code.
+ IPC_MESSAGE_ROUTED1(ViewMsg_ExecuteCode,
+ ViewMsg_ExecuteCode_Params)
+
+ // Notifies the child process of the new database size
+ IPC_MESSAGE_CONTROL4(ViewMsg_DatabaseUpdateSize,
+ string16 /* the origin */,
+ string16 /* the database name */,
+ int64 /* the new database size */,
+ int64 /* space available to origin */)
+
+ // Asks the child process to close a database immediately
+ IPC_MESSAGE_CONTROL2(ViewMsg_DatabaseCloseImmediately,
+ string16 /* the origin */,
+ string16 /* the database name */)
+
+ // Storage events are broadcast to renderer processes.
+ IPC_MESSAGE_CONTROL1(ViewMsg_DOMStorageEvent,
+ ViewMsg_DOMStorageEvent_Params)
+
+ // IDBCallback message handlers.
+ IPC_MESSAGE_CONTROL1(ViewMsg_IDBCallbacksSuccessNull,
+ int32 /* response_id */)
+ IPC_MESSAGE_CONTROL2(ViewMsg_IDBCallbacksSuccessIDBDatabase,
+ int32 /* response_id */,
+ int32 /* idb_database_id */)
+ IPC_MESSAGE_CONTROL2(ViewMsg_IDBCallbacksSuccessIndexedDBKey,
+ int32 /* response_id */,
+ IndexedDBKey /* indexed_db_key */)
+ IPC_MESSAGE_CONTROL2(ViewMsg_IDBCallbacksSuccessIDBObjectStore,
+ int32 /* response_id */,
+ int32 /* idb_object_store_id */)
+ IPC_MESSAGE_CONTROL2(ViewMsg_IDBCallbacksSuccessIDBIndex,
+ int32 /* response_id */,
+ int32 /* idb_index_id */)
+ IPC_MESSAGE_CONTROL2(ViewMsg_IDBCallbacksSuccessSerializedScriptValue,
+ int32 /* response_id */,
+ SerializedScriptValue /* serialized_script_value */)
+ IPC_MESSAGE_CONTROL3(ViewMsg_IDBCallbacksError,
+ int32 /* response_id */,
+ int /* code */,
+ string16 /* message */)
+
+#if defined(IPC_MESSAGE_LOG_ENABLED)
+ // Tell the renderer process to begin or end IPC message logging.
+ IPC_MESSAGE_CONTROL1(ViewMsg_SetIPCLoggingEnabled,
+ bool /* on or off */)
+#endif
+
+ // Socket Stream messages:
+ // These are messages from the browser to the SocketStreamHandle on
+ // a renderer.
+
+ // A |socket_id| is assigned by ViewHostMsg_SocketStream_Connect.
+ // The Socket Stream is connected. The SocketStreamHandle should keep track
+ // of how much it has pending (how much it has requested to be sent) and
+ // shouldn't go over |max_pending_send_allowed| bytes.
+ IPC_MESSAGE_CONTROL2(ViewMsg_SocketStream_Connected,
+ int /* socket_id */,
+ int /* max_pending_send_allowed */)
+
+ // |data| is received on the Socket Stream.
+ IPC_MESSAGE_CONTROL2(ViewMsg_SocketStream_ReceivedData,
+ int /* socket_id */,
+ std::vector<char> /* data */)
+
+ // |amount_sent| bytes of data requested by
+ // ViewHostMsg_SocketStream_SendData has been sent on the Socket Stream.
+ IPC_MESSAGE_CONTROL2(ViewMsg_SocketStream_SentData,
+ int /* socket_id */,
+ int /* amount_sent */)
+
+ // The Socket Stream is closed.
+ IPC_MESSAGE_CONTROL1(ViewMsg_SocketStream_Closed,
+ int /* socket_id */)
+
+ // SpellChecker messages.
+
+ // Passes some initialization params to the renderer's spellchecker. This can
+ // be called directly after startup or in (async) response to a
+ // RequestDictionary ViewHost message.
+ IPC_MESSAGE_CONTROL4(ViewMsg_SpellChecker_Init,
+ IPC::PlatformFileForTransit /* bdict_file */,
+ std::vector<std::string> /* custom_dict_words */,
+ std::string /* language */,
+ bool /* auto spell correct */)
+
+ // A word has been added to the custom dictionary; update the local custom
+ // word list.
+ IPC_MESSAGE_CONTROL1(ViewMsg_SpellChecker_WordAdded,
+ std::string /* word */)
+
+ // Toggle the auto spell correct functionality.
+ IPC_MESSAGE_CONTROL1(ViewMsg_SpellChecker_EnableAutoSpellCorrect,
+ bool /* enable */)
+
+ // Executes custom context menu action that was provided from WebKit.
+ IPC_MESSAGE_ROUTED1(ViewMsg_CustomContextMenuAction,
+ unsigned /* action */)
+
+ // Tells the renderer to translate the page contents from one language to
+ // another.
+ IPC_MESSAGE_ROUTED4(ViewMsg_TranslatePage,
+ int /* page id */,
+ std::string, /* the script injected in the page */
+ std::string, /* BCP 47/RFC 5646 language code the page
+ is in */
+ std::string /* BCP 47/RFC 5646 language code to translate
+ to */)
+
+ // Tells the renderer to revert the text of translated page to its original
+ // contents.
+ IPC_MESSAGE_ROUTED1(ViewMsg_RevertTranslation,
+ int /* page id */)
+
+ // Reply in response to ViewHostMsg_Geolocation_RequestPermission.
+ IPC_MESSAGE_ROUTED2(ViewMsg_Geolocation_PermissionSet,
+ int /* bridge_id */,
+ bool /* is_allowed */)
+
+ // Sent after ViewHostMsg_Geolocation_StartUpdating iff the user has granted
+ // permission and we have a position available or an error occurs (such as
+ // permission denied, position unavailable, etc.)
+ IPC_MESSAGE_ROUTED1(ViewMsg_Geolocation_PositionUpdated,
+ Geoposition /* geoposition */)
+
+ // Sent on process startup to indicate whether this process is running in
+ // incognito mode.
+ IPC_MESSAGE_CONTROL1(ViewMsg_SetIsIncognitoProcess,
+ bool /* is_incognito_processs */)
+
+ // Notification that the list of extensions with web extents has been updated.
+ IPC_MESSAGE_CONTROL1(ViewMsg_ExtensionExtentsUpdated,
+ ViewMsg_ExtensionExtentsUpdated_Params)
+
+ // Request a tree of Accessibility data from the render process.
+ IPC_MESSAGE_ROUTED0(ViewMsg_GetAccessibilityTree)
+
+ // Relay a request from assistive technology to set focus to a given node.
+ IPC_MESSAGE_ROUTED1(ViewMsg_SetAccessibilityFocus,
+ int /* object id */)
+
+ // Relay a request from assistive technology to perform the default action
+ // on a given node.
+ IPC_MESSAGE_ROUTED1(ViewMsg_AccessibilityDoDefaultAction,
+ int /* object id */)
+
+IPC_END_MESSAGES(View)
+
+
+//-----------------------------------------------------------------------------
+// TabContents messages
+// These are messages sent from the renderer to the browser process.
+
+IPC_BEGIN_MESSAGES(ViewHost)
+ // Sent by the renderer when it is creating a new window. The browser creates
+ // a tab for it and responds with a ViewMsg_CreatingNew_ACK. If route_id is
+ // MSG_ROUTING_NONE, the view couldn't be created.
+ IPC_SYNC_MESSAGE_CONTROL1_2(ViewHostMsg_CreateWindow,
+ ViewHostMsg_CreateWindow_Params,
+ int /* route_id */,
+ int64 /* cloned_session_storage_namespace_id */)
+
+ // Similar to ViewHostMsg_CreateWindow, except used for sub-widgets, like
+ // <select> dropdowns. This message is sent to the TabContents that
+ // contains the widget being created.
+ IPC_SYNC_MESSAGE_CONTROL2_1(ViewHostMsg_CreateWidget,
+ int /* opener_id */,
+ WebKit::WebPopupType /* popup type */,
+ int /* route_id */)
+
+ // These two messages are sent to the parent RenderViewHost to display the
+ // page/widget that was created by CreateWindow/CreateWidget. routing_id
+ // refers to the id that was returned from the Create message above.
+ // The initial_position parameter is a rectangle in screen coordinates.
+ //
+ // FUTURE: there will probably be flags here to control if the result is
+ // in a new window.
+ IPC_MESSAGE_ROUTED4(ViewHostMsg_ShowView,
+ int /* route_id */,
+ WindowOpenDisposition /* disposition */,
+ gfx::Rect /* initial_pos */,
+ bool /* opened_by_user_gesture */)
+
+ IPC_MESSAGE_ROUTED2(ViewHostMsg_ShowWidget,
+ int /* route_id */,
+ gfx::Rect /* initial_pos */)
+
+ // Message to show a popup menu using native cocoa controls (Mac only).
+ IPC_MESSAGE_ROUTED1(ViewHostMsg_ShowPopup,
+ ViewHostMsg_ShowPopup_Params)
+
+ // This message is sent after ViewHostMsg_ShowView to cause the RenderView
+ // to run in a modal fashion until it is closed.
+ IPC_SYNC_MESSAGE_ROUTED0_0(ViewHostMsg_RunModal)
+
+ IPC_MESSAGE_CONTROL1(ViewHostMsg_UpdatedCacheStats,
+ WebKit::WebCache::UsageStats /* stats */)
+
+ // Indicates the renderer is ready in response to a ViewMsg_New or
+ // a ViewMsg_CreatingNew_ACK.
+ IPC_MESSAGE_ROUTED0(ViewHostMsg_RenderViewReady)
+
+ // Indicates the renderer process is gone. This actually is sent by the
+ // browser process to itself, but keeps the interface cleaner.
+ IPC_MESSAGE_ROUTED0(ViewHostMsg_RenderViewGone)
+
+ // Sent by the renderer process to request that the browser close the view.
+ // This corresponds to the window.close() API, and the browser may ignore
+ // this message. Otherwise, the browser will generates a ViewMsg_Close
+ // message to close the view.
+ IPC_MESSAGE_ROUTED0(ViewHostMsg_Close)
+
+ // Sent by the renderer process to request that the browser move the view.
+ // This corresponds to the window.resizeTo() and window.moveTo() APIs, and
+ // the browser may ignore this message.
+ IPC_MESSAGE_ROUTED1(ViewHostMsg_RequestMove,
+ gfx::Rect /* position */)
+
+ // Notifies the browser that a frame in the view has changed. This message
+ // has a lot of parameters and is packed/unpacked by functions defined in
+ // render_messages.h.
+ IPC_MESSAGE_ROUTED1(ViewHostMsg_FrameNavigate,
+ ViewHostMsg_FrameNavigate_Params)
+
+ // Notifies the browser that we have session history information.
+ // page_id: unique ID that allows us to distinguish between history entries.
+ IPC_MESSAGE_ROUTED2(ViewHostMsg_UpdateState,
+ int32 /* page_id */,
+ std::string /* state */)
+
+ // Notifies the browser that a document has been loaded in a frame.
+ IPC_MESSAGE_ROUTED0(ViewHostMsg_DocumentLoadedInFrame)
+
+ // Changes the title for the page in the UI when the page is navigated or the
+ // title changes.
+ // TODO(darin): use a UTF-8 string to reduce data size
+ IPC_MESSAGE_ROUTED2(ViewHostMsg_UpdateTitle, int32, std::wstring)
+
+ // Changes the icon url for the page in the UI.
+ IPC_MESSAGE_ROUTED2(ViewHostMsg_UpdateIconURL, int32, GURL)
+
+ // Change the encoding name of the page in UI when the page has detected
+ // proper encoding name.
+ IPC_MESSAGE_ROUTED1(ViewHostMsg_UpdateEncoding,
+ std::string /* new encoding name */)
+
+ // Notifies the browser that we want to show a destination url for a potential
+ // action (e.g. when the user is hovering over a link).
+ IPC_MESSAGE_ROUTED2(ViewHostMsg_UpdateTargetURL, int32, GURL)
+
+ // Sent when the renderer starts loading the page. This corresponds to
+ // WebKit's notion of the throbber starting. Note that sometimes you may get
+ // duplicates of these during a single load.
+ IPC_MESSAGE_ROUTED0(ViewHostMsg_DidStartLoading)
+
+ // Sent when the renderer is done loading a page. This corresponds to WebKit's
+ // noption of the throbber stopping.
+ IPC_MESSAGE_ROUTED0(ViewHostMsg_DidStopLoading)
+
+ // Sent when the document element is available for the toplevel frame. This
+ // happens after the page starts loading, but before all resources are
+ // finished.
+ IPC_MESSAGE_ROUTED0(ViewHostMsg_DocumentAvailableInMainFrame)
+
+ // Sent when after the onload handler has been invoked for the document
+ // in the toplevel frame.
+ IPC_MESSAGE_ROUTED0(ViewHostMsg_DocumentOnLoadCompletedInMainFrame)
+
+ // Sent when the renderer loads a resource from its memory cache.
+ // The security info is non empty if the resource was originally loaded over
+ // a secure connection.
+ // Note: May only be sent once per URL per frame per committed load.
+ IPC_MESSAGE_ROUTED4(ViewHostMsg_DidLoadResourceFromMemoryCache,
+ GURL /* url */,
+ std::string /* frame_origin */,
+ std::string /* main_frame_origin */,
+ std::string /* security info */)
+
+ // Sent when the renderer displays insecure content in a secure page.
+ IPC_MESSAGE_ROUTED0(ViewHostMsg_DidDisplayInsecureContent)
+
+ // Sent when the renderer runs insecure content in a secure origin.
+ IPC_MESSAGE_ROUTED1(ViewHostMsg_DidRunInsecureContent,
+ std::string /* security_origin */)
+
+ // Sent when the renderer starts a provisional load for a frame.
+ IPC_MESSAGE_ROUTED2(ViewHostMsg_DidStartProvisionalLoadForFrame,
+ bool /* true if it is the main frame */,
+ GURL /* url */)
+
+ // Sent when the renderer fails a provisional load with an error.
+ IPC_MESSAGE_ROUTED4(ViewHostMsg_DidFailProvisionalLoadWithError,
+ bool /* true if it is the main frame */,
+ int /* error_code */,
+ GURL /* url */,
+ bool /* true if the failure is the result of
+ navigating to a POST again and we're going to
+ show the POST interstitial */ )
+
+ // Tells the render view that a ViewHostMsg_PaintAtSize message was
+ // processed, and the DIB is ready for use. |tag| has the same value that
+ // the tag sent along with ViewMsg_PaintAtSize.
+ IPC_MESSAGE_ROUTED2(ViewHostMsg_PaintAtSize_ACK,
+ int /* tag */,
+ gfx::Size /* size */)
+
+ // Sent to update part of the view. In response to this message, the host
+ // generates a ViewMsg_UpdateRect_ACK message.
+ IPC_MESSAGE_ROUTED1(ViewHostMsg_UpdateRect,
+ ViewHostMsg_UpdateRect_Params)
+
+ // Sent to create, update and destroy video layers.
+ IPC_MESSAGE_ROUTED1(ViewHostMsg_CreateVideo,
+ gfx::Size /* size */)
+ IPC_MESSAGE_ROUTED2(ViewHostMsg_UpdateVideo,
+ TransportDIB::Id /* bitmap */,
+ gfx::Rect /* bitmap_rect */)
+ IPC_MESSAGE_ROUTED0(ViewHostMsg_DestroyVideo)
+
+ // Sent by the renderer when GPU compositing is enabled or disabled to notify
+ // the browser whether or not is should do paiting.
+ IPC_MESSAGE_ROUTED1(ViewHostMsg_GpuRenderingActivated,
+ bool /* true if the GPU process renders to window */)
+
+ // Acknowledges receipt of a ViewMsg_HandleInputEvent message.
+ // Payload is a WebInputEvent::Type which is the type of the event, followed
+ // by an optional WebInputEvent which is provided only if the event was not
+ // processed.
+ IPC_MESSAGE_ROUTED0(ViewHostMsg_HandleInputEvent_ACK)
+
+ IPC_MESSAGE_ROUTED0(ViewHostMsg_Focus)
+ IPC_MESSAGE_ROUTED0(ViewHostMsg_Blur)
+ IPC_MESSAGE_ROUTED0(ViewHostMsg_FocusedNodeChanged)
+
+ // Returns the window location of the given window.
+ // TODO(shess): Provide a mapping from reply_msg->routing_id() to
+ // HWND so that we can eliminate the NativeViewId parameter.
+ IPC_SYNC_MESSAGE_ROUTED1_1(ViewHostMsg_GetWindowRect,
+ gfx::NativeViewId /* window */,
+ gfx::Rect /* Out: Window location */)
+
+ IPC_MESSAGE_ROUTED1(ViewHostMsg_SetCursor, WebCursor)
+ // Result of string search in the page.
+ // Response to ViewMsg_Find with the results of the requested find-in-page
+ // search, the number of matches found and the selection rect (in screen
+ // coordinates) for the string found. If |final_update| is false, it signals
+ // that this is not the last Find_Reply message - more will be sent as the
+ // scoping effort continues.
+ IPC_MESSAGE_ROUTED5(ViewHostMsg_Find_Reply,
+ int /* request_id */,
+ int /* number of matches */,
+ gfx::Rect /* selection_rect */,
+ int /* active_match_ordinal */,
+ bool /* final_update */)
+
+ // Makes a resource request via the browser.
+ IPC_MESSAGE_ROUTED2(ViewHostMsg_RequestResource,
+ int /* request_id */,
+ ViewHostMsg_Resource_Request)
+
+ // Cancels a resource request with the ID given as the parameter.
+ IPC_MESSAGE_ROUTED1(ViewHostMsg_CancelRequest,
+ int /* request_id */)
+
+ // Follows a redirect that occured for the resource request with the ID given
+ // as the parameter.
+ IPC_MESSAGE_ROUTED3(ViewHostMsg_FollowRedirect,
+ int /* request_id */,
+ bool /* has_new_first_party_for_cookies */,
+ GURL /* new_first_party_for_cookies */)
+
+ // Makes a synchronous resource request via the browser.
+ IPC_SYNC_MESSAGE_ROUTED2_1(ViewHostMsg_SyncLoad,
+ int /* request_id */,
+ ViewHostMsg_Resource_Request,
+ SyncLoadResult)
+
+ // Used to set a cookie. The cookie is set asynchronously, but will be
+ // available to a subsequent ViewHostMsg_GetCookies request.
+ IPC_MESSAGE_ROUTED3(ViewHostMsg_SetCookie,
+ GURL /* url */,
+ GURL /* first_party_for_cookies */,
+ std::string /* cookie */)
+
+ // Used to get cookies for the given URL. This may be blocked by a user
+ // prompt to validate a previous SetCookie message.
+ IPC_SYNC_MESSAGE_ROUTED2_1(ViewHostMsg_GetCookies,
+ GURL /* url */,
+ GURL /* first_party_for_cookies */,
+ std::string /* cookies */)
+
+ // Used to get raw cookie information for the given URL. This may be blocked
+ // by a user prompt to validate a previous SetCookie message.
+ IPC_SYNC_MESSAGE_ROUTED2_1(ViewHostMsg_GetRawCookies,
+ GURL /* url */,
+ GURL /* first_party_for_cookies */,
+ std::vector<webkit_glue::WebCookie>
+ /* raw_cookies */)
+
+ // Used to delete cookie for the given URL and name
+ IPC_SYNC_MESSAGE_CONTROL2_0(ViewHostMsg_DeleteCookie,
+ GURL /* url */,
+ std::string /* cookie_name */)
+
+ // Used to get raw cookie information for the given URL
+ IPC_SYNC_MESSAGE_CONTROL2_1(ViewHostMsg_GetCookiesEnabled,
+ GURL /* url */,
+ GURL /* first_party_for_cookies */,
+ bool /* enabled */)
+
+ // Used to get the list of plugins
+ IPC_SYNC_MESSAGE_CONTROL1_1(ViewHostMsg_GetPlugins,
+ bool /* refresh*/,
+ std::vector<WebPluginInfo> /* plugins */)
+
+ // Returns a path to a plugin for the given url and mime type. If there's
+ // no plugin, an empty string is returned.
+ IPC_SYNC_MESSAGE_CONTROL3_2(ViewHostMsg_GetPluginPath,
+ GURL /* url */,
+ GURL /* policy_url */,
+ std::string /* mime_type */,
+ FilePath /* filename */,
+ std::string /* actual mime type for url */)
+
+ // Requests spellcheck for a word.
+ IPC_SYNC_MESSAGE_ROUTED2_2(ViewHostMsg_SpellCheck,
+ string16 /* word to check */,
+ int /* document tag*/,
+ int /* misspell location */,
+ int /* misspell length */)
+
+ // Asks the browser for a unique document tag.
+ IPC_SYNC_MESSAGE_ROUTED0_1(ViewHostMsg_GetDocumentTag,
+ int /* the tag */)
+
+
+ // This message tells the spellchecker that a document, identified by an int
+ // tag, has been closed and all of the ignored words for that document can be
+ // forgotten.
+ IPC_MESSAGE_ROUTED1(ViewHostMsg_DocumentWithTagClosed,
+ int /* the tag */)
+
+ // Tells the browser to display or not display the SpellingPanel
+ IPC_MESSAGE_ROUTED1(ViewHostMsg_ShowSpellingPanel,
+ bool /* if true, then show it, otherwise hide it*/)
+
+ // Tells the browser to update the spelling panel with the given word.
+ IPC_MESSAGE_ROUTED1(ViewHostMsg_UpdateSpellingPanelWithMisspelledWord,
+ string16 /* the word to update the panel with */)
+
+ // Tells the browser that content in the current page was blocked due to the
+ // user's content settings.
+ IPC_MESSAGE_ROUTED1(ViewHostMsg_ContentBlocked,
+ ContentSettingsType /* type of blocked content */)
+
+ // Tells the browser that a specific Appcache manifest in the current page
+ // was accessed.
+ IPC_MESSAGE_ROUTED2(ViewHostMsg_AppCacheAccessed,
+ GURL /* manifest url */,
+ bool /* blocked by policy */)
+
+ // Tells the browser that a specific Web database in the current page was
+ // accessed.
+ IPC_MESSAGE_ROUTED5(ViewHostMsg_WebDatabaseAccessed,
+ GURL /* origin url */,
+ string16 /* database name */,
+ string16 /* database display name */,
+ unsigned long /* estimated size */,
+ bool /* blocked by policy */)
+
+ // Initiates a download based on user actions like 'ALT+click'.
+ IPC_MESSAGE_ROUTED2(ViewHostMsg_DownloadUrl,
+ GURL /* url */,
+ GURL /* referrer */)
+
+ // Used to go to the session history entry at the given offset (ie, -1 will
+ // return the "back" item).
+ IPC_MESSAGE_ROUTED1(ViewHostMsg_GoToEntryAtOffset,
+ int /* offset (from current) of history item to get */)
+
+ IPC_SYNC_MESSAGE_ROUTED4_2(ViewHostMsg_RunJavaScriptMessage,
+ std::wstring /* in - alert message */,
+ std::wstring /* in - default prompt */,
+ GURL /* in - originating page URL */,
+ int /* in - dialog flags */,
+ bool /* out - success */,
+ std::wstring /* out - prompt field */)
+
+ // Provides the contents for the given page that was loaded recently.
+ IPC_MESSAGE_ROUTED5(ViewHostMsg_PageContents,
+ GURL /* URL of the page */,
+ int32 /* page id */,
+ string16 /* page contents */,
+ std::string /* page ISO639_1 language code */,
+ bool /* whether the page can be translated */)
+
+ // Used to get the extension message bundle.
+ IPC_SYNC_MESSAGE_CONTROL1_1(ViewHostMsg_GetExtensionMessageBundle,
+ std::string /* extension id */,
+ SubstitutionMap /* message bundle */)
+
+ // Specifies the URL as the first parameter (a wstring) and thumbnail as
+ // binary data as the second parameter.
+ IPC_MESSAGE_ROUTED3(ViewHostMsg_Thumbnail,
+ GURL /* url */,
+ ThumbnailScore /* score */,
+ SkBitmap /* bitmap */)
+
+ // Send a snapshot of the tab contents to the render host.
+ IPC_MESSAGE_ROUTED1(ViewHostMsg_Snapshot,
+ SkBitmap /* bitmap */)
+
+ // Notification that the url for the favicon of a site has been determined.
+ IPC_MESSAGE_ROUTED2(ViewHostMsg_UpdateFavIconURL,
+ int32 /* page_id */,
+ GURL /* url of the favicon */)
+
+ // Used to tell the parent that the user right clicked on an area of the
+ // content area, and a context menu should be shown for it. The params
+ // object contains information about the node(s) that were selected when the
+ // user right clicked.
+ IPC_MESSAGE_ROUTED1(ViewHostMsg_ContextMenu, ContextMenuParams)
+
+ // Requests that the given URL be opened in the specified manner.
+ IPC_MESSAGE_ROUTED3(ViewHostMsg_OpenURL,
+ GURL /* url */,
+ GURL /* referrer */,
+ WindowOpenDisposition /* disposition */)
+
+ // Notifies that the preferred size of the content changed.
+ IPC_MESSAGE_ROUTED1(ViewHostMsg_DidContentsPreferredSizeChange,
+ gfx::Size /* pref_size */)
+
+ // Following message is used to communicate the values received by the
+ // callback binding the JS to Cpp.
+ // An instance of browser that has an automation host listening to it can
+ // have a javascript send a native value (string, number, boolean) to the
+ // listener in Cpp. (DomAutomationController)
+ IPC_MESSAGE_ROUTED2(ViewHostMsg_DomOperationResponse,
+ std::string /* json_string */,
+ int /* automation_id */)
+
+ // A message from HTML-based UI. When (trusted) Javascript calls
+ // send(message, args), this message is sent to the browser.
+ IPC_MESSAGE_ROUTED3(ViewHostMsg_DOMUISend,
+ GURL /* source_url */,
+ std::string /* message */,
+ std::string /* args (as a JSON string) */)
+
+ // A message for an external host.
+ IPC_MESSAGE_ROUTED3(ViewHostMsg_ForwardMessageToExternalHost,
+ std::string /* message */,
+ std::string /* origin */,
+ std::string /* target */)
+
+ // A renderer sends this to the browser process when it wants to
+ // create a plugin. The browser will create the plugin process if
+ // necessary, and will return a handle to the channel on success.
+ // On error an empty string is returned.
+ IPC_SYNC_MESSAGE_CONTROL3_2(ViewHostMsg_OpenChannelToPlugin,
+ GURL /* url */,
+ std::string /* mime_type */,
+ std::wstring /* locale */,
+ IPC::ChannelHandle /* handle to channel */,
+ WebPluginInfo /* info */)
+
+ // A renderer sends this to the browser process when it wants to
+ // create connect to the GPU. The browser will create the GPU process if
+ // necessary, and will return a handle to the channel via
+ // a GpuChannelEstablished message.
+ IPC_MESSAGE_CONTROL0(ViewHostMsg_EstablishGpuChannel)
+
+ // A renderer sends this to the browser process to provide a synchronization
+ // point for GPU operations, in particular to make sure the GPU channel has
+ // been established.
+ IPC_SYNC_MESSAGE_CONTROL0_0(ViewHostMsg_SynchronizeGpu)
+
+ // A renderer sends this to the browser process when it wants to start
+ // a new instance of the Native Client process. The browser will launch
+ // the process and return a handle to an IMC channel.
+ IPC_SYNC_MESSAGE_CONTROL2_3(ViewHostMsg_LaunchNaCl,
+ std::wstring /* url for the NaCl module */,
+ int /* channel number */,
+ nacl::FileDescriptor /* imc channel handle */,
+ base::ProcessHandle /* NaCl process handle */,
+ base::ProcessId /* NaCl process id */)
+
+#if defined(USE_X11)
+ // A renderer sends this when it needs a browser-side widget for
+ // hosting a windowed plugin. id is the XID of the plugin window, for which
+ // the container is created.
+ IPC_SYNC_MESSAGE_ROUTED1_0(ViewHostMsg_CreatePluginContainer,
+ gfx::PluginWindowHandle /* id */)
+
+ // Destroy a plugin container previously created using CreatePluginContainer.
+ // id is the XID of the plugin window corresponding to the container that is
+ // to be destroyed.
+ IPC_SYNC_MESSAGE_ROUTED1_0(ViewHostMsg_DestroyPluginContainer,
+ gfx::PluginWindowHandle /* id */)
+#endif
+
+ // Clipboard IPC messages
+
+ // This message is used when the object list does not contain a bitmap.
+ IPC_MESSAGE_CONTROL1(ViewHostMsg_ClipboardWriteObjectsAsync,
+ Clipboard::ObjectMap /* objects */)
+ // This message is used when the object list contains a bitmap.
+ // It is synchronized so that the renderer knows when it is safe to
+ // free the shared memory used to transfer the bitmap.
+ IPC_SYNC_MESSAGE_CONTROL2_0(ViewHostMsg_ClipboardWriteObjectsSync,
+ Clipboard::ObjectMap /* objects */,
+ base::SharedMemoryHandle /* bitmap handle */)
+ IPC_SYNC_MESSAGE_CONTROL2_1(ViewHostMsg_ClipboardIsFormatAvailable,
+ std::string /* format */,
+ Clipboard::Buffer /* buffer */,
+ bool /* result */)
+ IPC_SYNC_MESSAGE_CONTROL1_1(ViewHostMsg_ClipboardReadText,
+ Clipboard::Buffer /* buffer */,
+ string16 /* result */)
+ IPC_SYNC_MESSAGE_CONTROL1_1(ViewHostMsg_ClipboardReadAsciiText,
+ Clipboard::Buffer /* buffer */,
+ std::string /* result */)
+ IPC_SYNC_MESSAGE_CONTROL1_2(ViewHostMsg_ClipboardReadHTML,
+ Clipboard::Buffer /* buffer */,
+ string16 /* markup */,
+ GURL /* url */)
+
+ IPC_SYNC_MESSAGE_CONTROL1_3(ViewHostMsg_ClipboardReadAvailableTypes,
+ Clipboard::Buffer /* buffer */,
+ bool /* result */,
+ std::vector<string16> /* types */,
+ bool /* contains filenames */)
+ IPC_SYNC_MESSAGE_CONTROL2_3(ViewHostMsg_ClipboardReadData,
+ Clipboard::Buffer /* buffer */,
+ string16 /* type */,
+ bool /* succeeded */,
+ string16 /* data */,
+ string16 /* metadata */)
+ IPC_SYNC_MESSAGE_CONTROL1_2(ViewHostMsg_ClipboardReadFilenames,
+ Clipboard::Buffer /* buffer */,
+ bool /* result */,
+ std::vector<string16> /* filenames */)
+
+#if defined(OS_MACOSX)
+ IPC_MESSAGE_CONTROL1(ViewHostMsg_ClipboardFindPboardWriteStringAsync,
+ string16 /* text */)
+
+ // Request that the browser load a font into shared memory for us.
+ IPC_SYNC_MESSAGE_CONTROL1_2(ViewHostMsg_LoadFont,
+ FontDescriptor /* font to load */,
+ uint32 /* buffer size */,
+ base::SharedMemoryHandle /* font data */)
+#endif
+
+#if defined(OS_WIN)
+ // Request that the given font be loaded by the browser so it's cached by the
+ // OS. Please see ChildProcessHost::PreCacheFont for details.
+ IPC_SYNC_MESSAGE_CONTROL1_0(ViewHostMsg_PreCacheFont,
+ LOGFONT /* font data */)
+#endif // defined(OS_WIN)
+
+ // Returns WebScreenInfo corresponding to the view.
+ // TODO(shess): Provide a mapping from reply_msg->routing_id() to
+ // HWND so that we can eliminate the NativeViewId parameter.
+ IPC_SYNC_MESSAGE_ROUTED1_1(ViewHostMsg_GetScreenInfo,
+ gfx::NativeViewId /* view */,
+ WebKit::WebScreenInfo /* results */)
+
+ // Send the tooltip text for the current mouse position to the browser.
+ IPC_MESSAGE_ROUTED2(ViewHostMsg_SetTooltipText,
+ std::wstring /* tooltip text string */,
+ WebKit::WebTextDirection /* text direction hint */)
+
+ // Notification that the text selection has changed.
+ IPC_MESSAGE_ROUTED1(ViewHostMsg_SelectionChanged,
+ std::string /* currently selected text */)
+
+ // Asks the browser to display the file chooser. The result is returned in a
+ // ViewHost_RunFileChooserResponse message.
+ IPC_MESSAGE_ROUTED1(ViewHostMsg_RunFileChooser,
+ ViewHostMsg_RunFileChooser_Params)
+
+ // Notification that forms have been seen that are candidates for
+ // filling/submitting by the AutoFillManager.
+ IPC_MESSAGE_ROUTED1(ViewHostMsg_FormsSeen,
+ std::vector<webkit_glue::FormData> /* forms */)
+
+ // Notification that password forms have been seen that are candidates for
+ // filling/submitting by the password manager.
+ IPC_MESSAGE_ROUTED1(ViewHostMsg_PasswordFormsFound,
+ std::vector<webkit_glue::PasswordForm> /* forms */)
+
+ // Notification that initial layout has occurred and the following password
+ // forms are visible on the page (e.g. not set to display:none.)
+ IPC_MESSAGE_ROUTED1(ViewHostMsg_PasswordFormsVisible,
+ std::vector<webkit_glue::PasswordForm> /* forms */)
+
+ // Notification that a form has been submitted. The user hit the button.
+ IPC_MESSAGE_ROUTED1(ViewHostMsg_FormSubmitted,
+ webkit_glue::FormData /* form */)
+
+ // Used to tell the parent the user started dragging in the content area. The
+ // WebDropData struct contains contextual information about the pieces of the
+ // page the user dragged. The parent uses this notification to initiate a
+ // drag session at the OS level.
+ IPC_MESSAGE_ROUTED4(ViewHostMsg_StartDragging,
+ WebDropData /* drop_data */,
+ WebKit::WebDragOperationsMask /* ops_allowed */,
+ SkBitmap /* image */,
+ gfx::Point /* image_offset */)
+
+ // The page wants to update the mouse cursor during a drag & drop operation.
+ // |is_drop_target| is true if the mouse is over a valid drop target.
+ IPC_MESSAGE_ROUTED1(ViewHostMsg_UpdateDragCursor,
+ WebKit::WebDragOperation /* drag_operation */)
+
+ // Tells the browser to move the focus to the next (previous if reverse is
+ // true) focusable element.
+ IPC_MESSAGE_ROUTED1(ViewHostMsg_TakeFocus, bool /* reverse */)
+
+ // Notification that the page has an OpenSearch description document
+ // associated with it.
+ IPC_MESSAGE_ROUTED3(ViewHostMsg_PageHasOSDD,
+ int32 /* page_id */,
+ GURL /* url of OS description document */,
+ bool /* autodetected */)
+
+ // Find out if the given url's security origin is installed as a search
+ // provider.
+ IPC_SYNC_MESSAGE_ROUTED1_1(
+ ViewHostMsg_GetSearchProviderInstallState,
+ GURL,
+ ViewHostMsg_GetSearchProviderInstallState_Params /* install */)
+
+ // Required for updating text input state.
+ IPC_MESSAGE_ROUTED2(ViewHostMsg_ImeUpdateTextInputState,
+ WebKit::WebTextInputType, /* text_input_type */
+ gfx::Rect /* caret_rect */)
+
+ // Required for cancelling an ongoing input method composition.
+ IPC_MESSAGE_ROUTED0(ViewHostMsg_ImeCancelComposition)
+
+ // Tells the browser that the renderer is done calculating the number of
+ // rendered pages according to the specified settings.
+ IPC_MESSAGE_ROUTED2(ViewHostMsg_DidGetPrintedPagesCount,
+ int /* rendered document cookie */,
+ int /* number of rendered pages */)
+
+ // Sends back to the browser the rendered "printed page" that was requested by
+ // a ViewMsg_PrintPage message or from scripted printing. The memory handle in
+ // this message is already valid in the browser process.
+ IPC_MESSAGE_ROUTED1(ViewHostMsg_DidPrintPage,
+ ViewHostMsg_DidPrintPage_Params /* page content */)
+
+ // The renderer wants to know the default print settings.
+ IPC_SYNC_MESSAGE_ROUTED0_1(ViewHostMsg_GetDefaultPrintSettings,
+ ViewMsg_Print_Params /* default_settings */)
+
+#if defined(OS_WIN) || defined(OS_MACOSX)
+ // It's the renderer that controls the printing process when it is generated
+ // by javascript. This step is about showing UI to the user to select the
+ // final print settings. The output parameter is the same as
+ // ViewMsg_PrintPages which is executed implicitly.
+ IPC_SYNC_MESSAGE_ROUTED1_1(ViewHostMsg_ScriptedPrint,
+ ViewHostMsg_ScriptedPrint_Params,
+ ViewMsg_PrintPages_Params
+ /* settings chosen by the user*/)
+#endif // defined(OS_WIN) || defined(OS_MACOSX)
+
+ // WebKit and JavaScript error messages to log to the console
+ // or debugger UI.
+ IPC_MESSAGE_ROUTED3(ViewHostMsg_AddMessageToConsole,
+ std::wstring, /* msg */
+ int32, /* line number */
+ std::wstring /* source id */)
+
+ // Stores new inspector setting in the profile.
+ IPC_MESSAGE_ROUTED2(ViewHostMsg_UpdateInspectorSetting,
+ std::string, /* key */
+ std::string /* value */)
+
+ // Wraps an IPC message that's destined to the DevToolsClient on
+ // DevToolsAgent->browser hop.
+ IPC_MESSAGE_ROUTED1(ViewHostMsg_ForwardToDevToolsClient,
+ IPC::Message /* one of DevToolsClientMsg_XXX types */)
+
+ // Wraps an IPC message that's destined to the DevToolsAgent on
+ // DevToolsClient->browser hop.
+ IPC_MESSAGE_ROUTED1(ViewHostMsg_ForwardToDevToolsAgent,
+ IPC::Message /* one of DevToolsAgentMsg_XXX types */)
+
+ // Activates (brings to the front) corresponding dev tools window.
+ IPC_MESSAGE_ROUTED0(ViewHostMsg_ActivateDevToolsWindow)
+
+ // Closes dev tools window that is inspecting current render_view_host.
+ IPC_MESSAGE_ROUTED0(ViewHostMsg_CloseDevToolsWindow)
+
+ // Attaches dev tools window that is inspecting current render_view_host.
+ IPC_MESSAGE_ROUTED0(ViewHostMsg_RequestDockDevToolsWindow)
+
+ // Detaches dev tools window that is inspecting current render_view_host.
+ IPC_MESSAGE_ROUTED0(ViewHostMsg_RequestUndockDevToolsWindow)
+
+ // Updates runtime features store in devtools manager in order to support
+ // cross-navigation instrumentation.
+ IPC_MESSAGE_ROUTED2(ViewHostMsg_DevToolsRuntimeFeatureStateChanged,
+ std::string /* feature */,
+ bool /* enabled */)
+
+ // Send back a string to be recorded by UserMetrics.
+ IPC_MESSAGE_ROUTED1(ViewHostMsg_UserMetricsRecordAction,
+ std::string /* action */)
+
+ // Send back histograms as vector of pickled-histogram strings.
+ IPC_MESSAGE_CONTROL2(ViewHostMsg_RendererHistograms,
+ int, /* sequence number of Renderer Histograms. */
+ std::vector<std::string>)
+
+#if defined USE_TCMALLOC
+ // Send back tcmalloc stats output.
+ IPC_MESSAGE_CONTROL2(ViewHostMsg_RendererTcmalloc,
+ int /* pid */,
+ std::string /* tcmalloc debug output */)
+#endif
+
+ // Sends back stats about the V8 heap.
+ IPC_MESSAGE_CONTROL2(ViewHostMsg_V8HeapStats,
+ int /* size of heap (allocated from the OS) */,
+ int /* bytes in use */)
+
+ // Request for a DNS prefetch of the names in the array.
+ // NameList is typedef'ed std::vector<std::string>
+ IPC_MESSAGE_CONTROL1(ViewHostMsg_DnsPrefetch,
+ std::vector<std::string> /* hostnames */)
+
+ // Notifies when default plugin updates status of the missing plugin.
+ IPC_MESSAGE_ROUTED1(ViewHostMsg_MissingPluginStatus,
+ int /* status */)
+
+ // Sent by the renderer process to indicate that a plugin instance has
+ // crashed.
+ IPC_MESSAGE_ROUTED1(ViewHostMsg_CrashedPlugin,
+ FilePath /* plugin_path */)
+
+ // Displays a JavaScript out-of-memory message in the infobar.
+ IPC_MESSAGE_ROUTED0(ViewHostMsg_JSOutOfMemory)
+
+ // Displays a box to confirm that the user wants to navigate away from the
+ // page. Replies true if yes, false otherwise, the reply string is ignored,
+ // but is included so that we can use OnJavaScriptMessageBoxClosed.
+ IPC_SYNC_MESSAGE_ROUTED2_2(ViewHostMsg_RunBeforeUnloadConfirm,
+ GURL, /* in - originating frame URL */
+ std::wstring /* in - alert message */,
+ bool /* out - success */,
+ std::wstring /* out - This is ignored.*/)
+
+ IPC_MESSAGE_ROUTED3(ViewHostMsg_SendCurrentPageAllSavableResourceLinks,
+ std::vector<GURL> /* all savable resource links */,
+ std::vector<GURL> /* all referrers of resource links */,
+ std::vector<GURL> /* all frame links */)
+
+ IPC_MESSAGE_ROUTED3(ViewHostMsg_SendSerializedHtmlData,
+ GURL /* frame's url */,
+ std::string /* data buffer */,
+ int32 /* complete status */)
+
+ IPC_SYNC_MESSAGE_ROUTED4_1(ViewHostMsg_ShowModalHTMLDialog,
+ GURL /* url */,
+ int /* width */,
+ int /* height */,
+ std::string /* json_arguments */,
+ std::string /* json_retval */)
+
+ IPC_MESSAGE_ROUTED2(ViewHostMsg_DidGetApplicationInfo,
+ int32 /* page_id */,
+ webkit_glue::WebApplicationInfo)
+
+ // Provides the result from running OnMsgShouldClose. |proceed| matches the
+ // return value of the the frame's shouldClose method (which includes the
+ // onbeforeunload handler): true if the user decided to proceed with leaving
+ // the page.
+ IPC_MESSAGE_ROUTED1(ViewHostMsg_ShouldClose_ACK,
+ bool /* proceed */)
+
+ // Indicates that the current page has been closed, after a ClosePage
+ // message. The parameters are just echoed from the ClosePage request.
+ IPC_MESSAGE_ROUTED1(ViewHostMsg_ClosePage_ACK,
+ ViewMsg_ClosePage_Params)
+
+ IPC_MESSAGE_ROUTED4(ViewHostMsg_DidDownloadFavIcon,
+ int /* Identifier of the request */,
+ GURL /* URL of the image */,
+ bool /* true if there was a network error */,
+ SkBitmap /* image_data */)
+
+ // Sent to query MIME information.
+ IPC_SYNC_MESSAGE_CONTROL1_1(ViewHostMsg_GetMimeTypeFromExtension,
+ FilePath::StringType /* extension */,
+ std::string /* mime_type */)
+ IPC_SYNC_MESSAGE_CONTROL1_1(ViewHostMsg_GetMimeTypeFromFile,
+ FilePath /* file_path */,
+ std::string /* mime_type */)
+ IPC_SYNC_MESSAGE_CONTROL1_1(ViewHostMsg_GetPreferredExtensionForMimeType,
+ std::string /* mime_type */,
+ FilePath::StringType /* extension */)
+
+ // Get the CPBrowsingContext associated with the renderer sending this
+ // message.
+ IPC_SYNC_MESSAGE_CONTROL0_1(ViewHostMsg_GetCPBrowsingContext,
+ uint32 /* context */)
+
+ // Sent when the renderer process is done processing a DataReceived
+ // message.
+ IPC_MESSAGE_ROUTED1(ViewHostMsg_DataReceived_ACK,
+ int /* request_id */)
+
+ // Sent when a provisional load on the main frame redirects.
+ IPC_MESSAGE_ROUTED3(ViewHostMsg_DidRedirectProvisionalLoad,
+ int /* page_id */,
+ GURL /* last url */,
+ GURL /* url redirected to */)
+
+ // Sent by the renderer process to acknowledge receipt of a
+ // DownloadProgress message.
+ IPC_MESSAGE_ROUTED1(ViewHostMsg_DownloadProgress_ACK,
+ int /* request_id */)
+
+ // Sent by the renderer process to acknowledge receipt of a
+ // UploadProgress message.
+ IPC_MESSAGE_ROUTED1(ViewHostMsg_UploadProgress_ACK,
+ int /* request_id */)
+
+ // Sent when the renderer changes the zoom level for a particular url, so the
+ // browser can update its records.
+ IPC_MESSAGE_CONTROL2(ViewHostMsg_DidZoomURL,
+ GURL /* url */,
+ int /* zoom_level */)
+
+#if defined(OS_WIN)
+ // Duplicates a shared memory handle from the renderer to the browser. Then
+ // the renderer can flush the handle.
+ IPC_SYNC_MESSAGE_ROUTED1_1(ViewHostMsg_DuplicateSection,
+ base::SharedMemoryHandle /* renderer handle */,
+ base::SharedMemoryHandle /* browser handle */)
+#endif
+
+#if defined(USE_X11)
+ // Asks the browser to create a temporary file for the renderer to fill
+ // in resulting NativeMetafile in printing.
+ IPC_SYNC_MESSAGE_CONTROL0_2(ViewHostMsg_AllocateTempFileForPrinting,
+ base::FileDescriptor /* temp file fd */,
+ int /* fd in browser*/)
+ IPC_MESSAGE_CONTROL1(ViewHostMsg_TempFileForPrintingWritten,
+ int /* fd in browser */)
+#endif
+
+#if defined(OS_MACOSX)
+ // Asks the browser to create a block of shared memory for the renderer to
+ // pass NativeMetafile data to the browser.
+ IPC_SYNC_MESSAGE_ROUTED1_1(ViewHostMsg_AllocatePDFTransport,
+ uint32 /* buffer size */,
+ base::SharedMemoryHandle /* browser handle */)
+#endif
+
+#if defined(OS_POSIX)
+ // Asks the browser to create a block of shared memory for the renderer to
+ // fill in and pass back to the browser.
+ IPC_SYNC_MESSAGE_CONTROL1_1(ViewHostMsg_AllocateSharedMemoryBuffer,
+ uint32 /* buffer size */,
+ base::SharedMemoryHandle /* browser handle */)
+#endif
+
+ // Provide the browser process with information about the WebCore resource
+ // cache.
+ IPC_MESSAGE_CONTROL1(ViewHostMsg_ResourceTypeStats,
+ WebKit::WebCache::ResourceTypeStats)
+
+ // Notify the browser that this render process can or can't be suddenly
+ // terminated.
+ IPC_MESSAGE_CONTROL1(ViewHostMsg_SuddenTerminationChanged,
+ bool /* enabled */)
+
+ // Returns the window location of the window this widget is embeded.
+ // TODO(shess): Provide a mapping from reply_msg->routing_id() to
+ // HWND so that we can eliminate the NativeViewId parameter.
+ IPC_SYNC_MESSAGE_ROUTED1_1(ViewHostMsg_GetRootWindowRect,
+ gfx::NativeViewId /* window */,
+ gfx::Rect /* Out: Window location */)
+
+ // Informs the browser of a new appcache host.
+ IPC_MESSAGE_CONTROL1(AppCacheMsg_RegisterHost,
+ int /* host_id */)
+
+ // Informs the browser of an appcache host being destroyed.
+ IPC_MESSAGE_CONTROL1(AppCacheMsg_UnregisterHost,
+ int /* host_id */)
+
+ // Initiates the cache selection algorithm for the given host.
+ // This is sent prior to any subresource loads. An AppCacheMsg_CacheSelected
+ // message will be sent in response.
+ // 'host_id' indentifies a specific document or worker
+ // 'document_url' the url of the main resource
+ // 'appcache_document_was_loaded_from' the id of the appcache the main
+ // resource was loaded from or kNoCacheId
+ // 'opt_manifest_url' the manifest url specified in the <html> tag if any
+ IPC_MESSAGE_CONTROL4(AppCacheMsg_SelectCache,
+ int /* host_id */,
+ GURL /* document_url */,
+ int64 /* appcache_document_was_loaded_from */,
+ GURL /* opt_manifest_url */)
+
+ // Initiates worker specific cache selection algorithm for the given host.
+ IPC_MESSAGE_CONTROL3(AppCacheMsg_SelectCacheForWorker,
+ int /* host_id */,
+ int /* parent_process_id */,
+ int /* parent_host_id */)
+ IPC_MESSAGE_CONTROL2(AppCacheMsg_SelectCacheForSharedWorker,
+ int /* host_id */,
+ int64 /* appcache_id */)
+
+ // Informs the browser of a 'foreign' entry in an appcache.
+ IPC_MESSAGE_CONTROL3(AppCacheMsg_MarkAsForeignEntry,
+ int /* host_id */,
+ GURL /* document_url */,
+ int64 /* appcache_document_was_loaded_from */)
+
+ // Returns the status of the appcache associated with host_id.
+ IPC_SYNC_MESSAGE_CONTROL1_1(AppCacheMsg_GetStatus,
+ int /* host_id */,
+ appcache::Status)
+
+ // Initiates an update of the appcache associated with host_id.
+ IPC_SYNC_MESSAGE_CONTROL1_1(AppCacheMsg_StartUpdate,
+ int /* host_id */,
+ bool /* success */)
+
+ // Swaps a new pending appcache, if there is one, into use for host_id.
+ IPC_SYNC_MESSAGE_CONTROL1_1(AppCacheMsg_SwapCache,
+ int /* host_id */,
+ bool /* success */)
+
+ // Returns the resizer box location in the window this widget is embedded.
+ // Important for Mac OS X, but not Win or Linux.
+ IPC_SYNC_MESSAGE_ROUTED1_1(ViewHostMsg_GetRootWindowResizerRect,
+ gfx::NativeViewId /* window */,
+ gfx::Rect /* Out: Window location */)
+
+ // Queries the browser for AutoFill suggestions for a form input field.
+ IPC_MESSAGE_ROUTED3(ViewHostMsg_QueryFormFieldAutoFill,
+ int /* id of this message */,
+ bool /* form_autofilled */,
+ webkit_glue::FormField /* the form field */)
+
+ // Instructs the browser to fill in the values for a form using AutoFill
+ // profile data.
+ IPC_MESSAGE_ROUTED5(ViewHostMsg_FillAutoFillFormData,
+ int /* id of this message */,
+ webkit_glue::FormData /* the form */,
+ string16 /* profile name */,
+ string16 /* profile label */,
+ int /* profile unique ID */)
+
+ // Instructs the browser to remove the specified Autocomplete entry from the
+ // database.
+ IPC_MESSAGE_ROUTED2(ViewHostMsg_RemoveAutocompleteEntry,
+ string16 /* field name */,
+ string16 /* value */)
+
+ // Instructs the browser to show the AutoFill dialog.
+ IPC_MESSAGE_ROUTED0(ViewHostMsg_ShowAutoFillDialog)
+
+ // Get the list of proxies to use for |url|, as a semicolon delimited list
+ // of "<TYPE> <HOST>:<PORT>" | "DIRECT". See also
+ // PluginProcessHostMsg_ResolveProxy which does the same thing.
+ IPC_SYNC_MESSAGE_CONTROL1_2(ViewHostMsg_ResolveProxy,
+ GURL /* url */,
+ int /* network error */,
+ std::string /* proxy list */)
+
+ // Request that got sent to browser for creating an audio output stream
+ IPC_MESSAGE_ROUTED3(ViewHostMsg_CreateAudioStream,
+ int /* stream_id */,
+ ViewHostMsg_Audio_CreateStream_Params,
+ bool /* low-latency */)
+
+ // Tell the browser the audio buffer prepared for stream
+ // (render_view_id, stream_id) is filled and is ready to be consumed.
+ IPC_MESSAGE_ROUTED2(ViewHostMsg_NotifyAudioPacketReady,
+ int /* stream_id */,
+ uint32 /* packet size */)
+
+ // Start buffering and play the audio stream specified by
+ // (render_view_id, stream_id).
+ IPC_MESSAGE_ROUTED1(ViewHostMsg_PlayAudioStream,
+ int /* stream_id */)
+
+ // Pause the audio stream specified by (render_view_id, stream_id).
+ IPC_MESSAGE_ROUTED1(ViewHostMsg_PauseAudioStream,
+ int /* stream_id */)
+
+ // Discard all buffered audio data for the specified audio stream.
+ IPC_MESSAGE_ROUTED1(ViewHostMsg_FlushAudioStream,
+ int /* stream_id */)
+
+ // Close an audio stream specified by (render_view_id, stream_id).
+ IPC_MESSAGE_ROUTED1(ViewHostMsg_CloseAudioStream,
+ int /* stream_id */)
+
+ // Get audio volume of the stream specified by (render_view_id, stream_id).
+ IPC_MESSAGE_ROUTED1(ViewHostMsg_GetAudioVolume,
+ int /* stream_id */)
+
+ // Set audio volume of the stream specified by (render_view_id, stream_id).
+ // TODO(hclam): change this to vector if we have channel numbers other than 2.
+ IPC_MESSAGE_ROUTED2(ViewHostMsg_SetAudioVolume,
+ int /* stream_id */,
+ double /* volume */)
+
+ // A renderer sends this message when an extension process starts an API
+ // request. The browser will always respond with a ViewMsg_ExtensionResponse.
+ IPC_MESSAGE_ROUTED5(ViewHostMsg_ExtensionRequest,
+ std::string /* name */,
+ ListValue /* arguments */,
+ GURL /* source_url */,
+ int /* callback id */,
+ bool /* has_callback */)
+
+ // Notify the browser that this renderer added a listener to an event.
+ IPC_MESSAGE_CONTROL1(ViewHostMsg_ExtensionAddListener,
+ std::string /* name */)
+
+ // Notify the browser that this renderer removed a listener from an event.
+ IPC_MESSAGE_CONTROL1(ViewHostMsg_ExtensionRemoveListener,
+ std::string /* name */)
+
+#if defined(OS_MACOSX)
+ // On OSX, we cannot allocated shared memory from within the sandbox, so
+ // this call exists for the renderer to ask the browser to allocate memory
+ // on its behalf. We return a file descriptor to the POSIX shared memory.
+ // If the |cache_in_browser| flag is |true|, then a copy of the shmem is kept
+ // by the browser, and it is the caller's repsonsibility to send a
+ // ViewHostMsg_FreeTransportDIB message in order to release the cached shmem.
+ // In all cases, the caller is responsible for deleting the resulting
+ // TransportDIB.
+ IPC_SYNC_MESSAGE_CONTROL2_1(ViewHostMsg_AllocTransportDIB,
+ size_t, /* bytes requested */
+ bool, /* cache in the browser */
+ TransportDIB::Handle /* DIB */)
+
+ // Since the browser keeps handles to the allocated transport DIBs, this
+ // message is sent to tell the browser that it may release them when the
+ // renderer is finished with them.
+ IPC_MESSAGE_CONTROL1(ViewHostMsg_FreeTransportDIB,
+ TransportDIB::Id /* DIB id */)
+
+ //---------------------------------------------------------------------------
+ // Messages related to the GPU plugin on Mac OS X 10.6 and later
+
+ // This is sent from the renderer to the browser to allocate a fake
+ // PluginWindowHandle on the browser side which is used to identify
+ // the plugin to the browser later when backing store is allocated
+ // or reallocated. |opaque| indicates whether the plugin's output is
+ // considered to be opaque, as opposed to translucent.
+ IPC_SYNC_MESSAGE_ROUTED1_1(ViewHostMsg_AllocateFakePluginWindowHandle,
+ bool /* opaque */,
+ gfx::PluginWindowHandle /* id */)
+
+ // Destroys a fake window handle previously allocated using
+ // AllocateFakePluginWindowHandle.
+ IPC_MESSAGE_ROUTED1(ViewHostMsg_DestroyFakePluginWindowHandle,
+ gfx::PluginWindowHandle /* id */)
+
+ // This message, used on Mac OS X 10.5 and earlier (no IOSurface support),
+ // is sent from the renderer to the browser on behalf of the plug-in
+ // to indicate that a new backing store was allocated for that plug-in
+ // instance.
+ IPC_MESSAGE_ROUTED4(ViewHostMsg_AcceleratedSurfaceSetTransportDIB,
+ gfx::PluginWindowHandle /* window */,
+ int32 /* width */,
+ int32 /* height */,
+ TransportDIB::Handle /* handle for the DIB */)
+
+ // This message, used on Mac OS X 10.6 and later (where IOSurface is
+ // supported), is sent from the renderer to the browser on behalf of the
+ // plug-in to indicate that a new backing store was allocated for that
+ // plug-in instance.
+ //
+ // NOTE: the original intent was to pass a mach port as the IOSurface
+ // identifier but it looks like that will be a lot of work. For now we pass an
+ // ID from IOSurfaceGetID.
+ IPC_MESSAGE_ROUTED4(ViewHostMsg_AcceleratedSurfaceSetIOSurface,
+ gfx::PluginWindowHandle /* window */,
+ int32 /* width */,
+ int32 /* height */,
+ uint64 /* identifier for IOSurface */)
+
+ // This message notifies the browser process that the plug-in
+ // swapped the buffers associated with the given "window", which
+ // should cause the browser to redraw the various plug-ins'
+ // contents.
+ IPC_MESSAGE_ROUTED1(ViewHostMsg_AcceleratedSurfaceBuffersSwapped,
+ gfx::PluginWindowHandle /* window */)
+#endif
+
+ // A renderer sends this to the browser process when it wants to create a
+ // worker. The browser will create the worker process if necessary, and
+ // will return the route id on success. On error returns MSG_ROUTING_NONE.
+ IPC_SYNC_MESSAGE_CONTROL1_1(ViewHostMsg_CreateWorker,
+ ViewHostMsg_CreateWorker_Params,
+ int /* route_id */)
+
+ // This message is sent to the browser to see if an instance of this shared
+ // worker already exists. If so, it returns exists == true. If a
+ // non-empty name is passed, also validates that the url matches the url of
+ // the existing worker. If a matching worker is found, the passed-in
+ // document_id is associated with that worker, to ensure that the worker
+ // stays alive until the document is detached.
+ // The route_id returned can be used to forward messages to the worker via
+ // ForwardToWorker if it exists, otherwise it should be passed in to any
+ // future call to CreateWorker to avoid creating duplicate workers.
+ IPC_SYNC_MESSAGE_CONTROL1_3(ViewHostMsg_LookupSharedWorker,
+ ViewHostMsg_CreateWorker_Params,
+ bool /* exists */,
+ int /* route_id */,
+ bool /* url_mismatch */)
+
+ // A renderer sends this to the browser process when a document has been
+ // detached. The browser will use this to constrain the lifecycle of worker
+ // processes (SharedWorkers are shut down when their last associated document
+ // is detached).
+ IPC_MESSAGE_CONTROL1(ViewHostMsg_DocumentDetached,
+ unsigned long long /* document_id */)
+
+ // A message sent to the browser on behalf of a renderer which wants to show
+ // a desktop notification.
+ IPC_MESSAGE_ROUTED1(ViewHostMsg_ShowDesktopNotification,
+ ViewHostMsg_ShowNotification_Params)
+ IPC_MESSAGE_ROUTED1(ViewHostMsg_CancelDesktopNotification,
+ int /* notification_id */ )
+ IPC_MESSAGE_ROUTED2(ViewHostMsg_RequestNotificationPermission,
+ GURL /* origin */,
+ int /* callback_context */)
+ IPC_SYNC_MESSAGE_ROUTED1_1(ViewHostMsg_CheckNotificationPermission,
+ GURL /* source page */,
+ int /* permission_result */)
+
+ // Sent if the worker object has sent a ViewHostMsg_CreateDedicatedWorker
+ // message and not received a ViewMsg_WorkerCreated reply, but in the
+ // mean time it's destroyed. This tells the browser to not create the queued
+ // worker.
+ IPC_MESSAGE_CONTROL1(ViewHostMsg_CancelCreateDedicatedWorker,
+ int /* route_id */)
+
+ // Wraps an IPC message that's destined to the worker on the renderer->browser
+ // hop.
+ IPC_MESSAGE_CONTROL1(ViewHostMsg_ForwardToWorker,
+ IPC::Message /* message */)
+
+ // Open a channel to all listening contexts owned by the extension with
+ // the given ID. This always returns a valid port ID which can be used for
+ // sending messages. If an error occurred, the opener will be notified
+ // asynchronously.
+ IPC_SYNC_MESSAGE_CONTROL4_1(ViewHostMsg_OpenChannelToExtension,
+ int /* routing_id */,
+ std::string /* source_extension_id */,
+ std::string /* target_extension_id */,
+ std::string /* channel_name */,
+ int /* port_id */)
+
+ // Get a port handle to the given tab. The handle can be used for sending
+ // messages to the extension.
+ IPC_SYNC_MESSAGE_CONTROL4_1(ViewHostMsg_OpenChannelToTab,
+ int /* routing_id */,
+ int /* tab_id */,
+ std::string /* extension_id */,
+ std::string /* channel_name */,
+ int /* port_id */)
+
+ // Send a message to an extension process. The handle is the value returned
+ // by ViewHostMsg_OpenChannelTo*.
+ IPC_MESSAGE_ROUTED2(ViewHostMsg_ExtensionPostMessage,
+ int /* port_id */,
+ std::string /* message */)
+
+ // Send a message to an extension process. The handle is the value returned
+ // by ViewHostMsg_OpenChannelTo*.
+ IPC_MESSAGE_CONTROL1(ViewHostMsg_ExtensionCloseChannel,
+ int /* port_id */)
+
+ // Sent as a result of a focus change in the renderer (if accessibility is
+ // enabled), to notify the browser side that its accessibility focus needs to
+ // change as well. Takes the id of the accessibility object that now has
+ // focus.
+ IPC_MESSAGE_ROUTED1(ViewHostMsg_AccessibilityFocusChange,
+ int /* accessibility object id */)
+
+ // Send as a result of a state change in the renderer (if accessibility is
+ // enabled), to notify the browser side. Takes the id of the accessibility
+ // object that had a state change
+ IPC_MESSAGE_ROUTED1(ViewHostMsg_AccessibilityObjectStateChange,
+ int /* accessibility object id */)
+
+ // Message sent from the renderer to the browser to request that the browser
+ // close all sockets. Used for debugging/testing.
+ IPC_MESSAGE_CONTROL0(ViewHostMsg_CloseCurrentConnections)
+
+ // Message sent from the renderer to the browser to request that the browser
+ // enable or disable the cache. Used for debugging/testing.
+ IPC_MESSAGE_CONTROL1(ViewHostMsg_SetCacheMode,
+ bool /* enabled */)
+
+ // Message sent from the renderer to the browser to request that the browser
+ // clear the cache. Used for debugging/testing.
+ IPC_SYNC_MESSAGE_CONTROL0_1(ViewHostMsg_ClearCache,
+ int /* result */)
+
+ // Message sent from the renderer to the browser to request that the browser
+ // cache |data| associated with |url|.
+ IPC_MESSAGE_CONTROL3(ViewHostMsg_DidGenerateCacheableMetadata,
+ GURL /* url */,
+ double /* expected_response_time */,
+ std::vector<char> /* data */)
+
+ // Get the storage area id for a particular origin within a namespace.
+ IPC_SYNC_MESSAGE_CONTROL2_1(ViewHostMsg_DOMStorageStorageAreaId,
+ int64 /* namespace_id */,
+ string16 /* origin */,
+ int64 /* storage_area_id */)
+
+ // Get the length of a storage area.
+ IPC_SYNC_MESSAGE_CONTROL1_1(ViewHostMsg_DOMStorageLength,
+ int64 /* storage_area_id */,
+ unsigned /* length */)
+
+ // Get a the ith key within a storage area.
+ IPC_SYNC_MESSAGE_CONTROL2_1(ViewHostMsg_DOMStorageKey,
+ int64 /* storage_area_id */,
+ unsigned /* index */,
+ NullableString16 /* key */)
+
+ // Get a value based on a key from a storage area.
+ IPC_SYNC_MESSAGE_CONTROL2_1(ViewHostMsg_DOMStorageGetItem,
+ int64 /* storage_area_id */,
+ string16 /* key */,
+ NullableString16 /* value */)
+
+ // Set a value that's associated with a key in a storage area.
+ IPC_SYNC_MESSAGE_ROUTED4_2(ViewHostMsg_DOMStorageSetItem,
+ int64 /* storage_area_id */,
+ string16 /* key */,
+ string16 /* value */,
+ GURL /* url */,
+ WebKit::WebStorageArea::Result /* result */,
+ NullableString16 /* old_value */)
+
+ // Remove the value associated with a key in a storage area.
+ IPC_SYNC_MESSAGE_CONTROL3_1(ViewHostMsg_DOMStorageRemoveItem,
+ int64 /* storage_area_id */,
+ string16 /* key */,
+ GURL /* url */,
+ NullableString16 /* old_value */)
+
+ // Clear the storage area.
+ IPC_SYNC_MESSAGE_CONTROL2_1(ViewHostMsg_DOMStorageClear,
+ int64 /* storage_area_id */,
+ GURL /* url */,
+ bool /* something_cleared */)
+
+ // WebIndexedDatabase::open() message.
+ IPC_MESSAGE_CONTROL1(ViewHostMsg_IndexedDatabaseOpen,
+ ViewHostMsg_IndexedDatabaseOpen_Params)
+
+ // WebIDBDatabase::name() message.
+ IPC_SYNC_MESSAGE_CONTROL1_1(ViewHostMsg_IDBDatabaseName,
+ int32, /* idb_database_id */
+ string16 /* name */)
+
+ // WebIDBDatabase::description() message.
+ IPC_SYNC_MESSAGE_CONTROL1_1(ViewHostMsg_IDBDatabaseDescription,
+ int32, /* idb_database_id */
+ string16 /* description */)
+
+ // WebIDBDatabase::version() message.
+ IPC_SYNC_MESSAGE_CONTROL1_1(ViewHostMsg_IDBDatabaseVersion,
+ int32, /* idb_database_id */
+ string16 /* vesion */)
+
+ // WebIDBDatabase::objectStores() message.
+ IPC_SYNC_MESSAGE_CONTROL1_1(ViewHostMsg_IDBDatabaseObjectStores,
+ int32, /* idb_database_id */
+ std::vector<string16> /* objectStores */)
+
+ // WebIDBDatabase::createObjectStore() message.
+ IPC_MESSAGE_CONTROL1(ViewHostMsg_IDBDatabaseCreateObjectStore,
+ ViewHostMsg_IDBDatabaseCreateObjectStore_Params)
+
+ // WebIDBDatabase::objectStore() message.
+ IPC_SYNC_MESSAGE_CONTROL3_2(ViewHostMsg_IDBDatabaseObjectStore,
+ int32, /* idb_database_id */
+ string16, /* name */
+ int32, /* mode */
+ bool, /* success */
+ int32 /* idb_object_store_id */)
+
+ // WebIDBDatabase::removeObjectStore() message.
+ IPC_MESSAGE_CONTROL3(ViewHostMsg_IDBDatabaseRemoveObjectStore,
+ int32, /* idb_database_id */
+ int32, /* response_id */
+ string16 /* name */)
+
+ // WebIDBDatabase::~WebIDBDatabase() message.
+ IPC_MESSAGE_CONTROL1(ViewHostMsg_IDBDatabaseDestroyed,
+ int32 /* idb_database_id */)
+
+ // WebIDBIndex::name() message.
+ IPC_SYNC_MESSAGE_CONTROL1_1(ViewHostMsg_IDBIndexName,
+ int32, /* idb_index_id */
+ string16 /* name */)
+
+ // WebIDBIndex::keyPath() message.
+ IPC_SYNC_MESSAGE_CONTROL1_1(ViewHostMsg_IDBIndexKeyPath,
+ int32, /* idb_index_id */
+ NullableString16 /* key_path */)
+
+ // WebIDBIndex::unique() message.
+ IPC_SYNC_MESSAGE_CONTROL1_1(ViewHostMsg_IDBIndexUnique,
+ int32, /* idb_unique_id */
+ bool /* unique */)
+
+ // WebIDBIndex::~WebIDBIndex() message.
+ IPC_MESSAGE_CONTROL1(ViewHostMsg_IDBIndexDestroyed,
+ int32 /* idb_index_id */)
+
+ // WebIDBObjectStore::name() message.
+ IPC_SYNC_MESSAGE_CONTROL1_1(ViewHostMsg_IDBObjectStoreName,
+ int32, /* idb_object_store_id */
+ string16 /* name */)
+
+ // WebIDBObjectStore::keyPath() message.
+ IPC_SYNC_MESSAGE_CONTROL1_1(ViewHostMsg_IDBObjectStoreKeyPath,
+ int32, /* idb_object_store_id */
+ NullableString16 /* keyPath */)
+
+ // WebIDBObjectStore::indexNames() message.
+ IPC_SYNC_MESSAGE_CONTROL1_1(ViewHostMsg_IDBObjectStoreIndexNames,
+ int32, /* idb_object_store_id */
+ std::vector<string16> /* index_names */)
+
+ // WebIDBObjectStore::get() message.
+ IPC_MESSAGE_CONTROL3(ViewHostMsg_IDBObjectStoreGet,
+ int32, /* idb_object_store_id */
+ int32, /* response_id */
+ IndexedDBKey /* key */)
+
+ // WebIDBObjectStore::put() message.
+ IPC_MESSAGE_CONTROL5(ViewHostMsg_IDBObjectStorePut,
+ int32, /* idb_object_store_id */
+ int32, /* response_id */
+ SerializedScriptValue, /* serialized_value */
+ IndexedDBKey, /* key */
+ bool /* add_only */)
+
+ // WebIDBObjectStore::remove() message.
+ IPC_MESSAGE_CONTROL3(ViewHostMsg_IDBObjectStoreRemove,
+ int32, /* idb_object_store_id */
+ int32, /* response_id */
+ IndexedDBKey /* key */)
+
+ // WebIDBObjectStore::createIndex() message.
+ IPC_MESSAGE_CONTROL1(ViewHostMsg_IDBObjectStoreCreateIndex,
+ ViewHostMsg_IDBObjectStoreCreateIndex_Params)
+
+ // WebIDBObjectStore::index() message.
+ IPC_SYNC_MESSAGE_CONTROL2_2(ViewHostMsg_IDBObjectStoreIndex,
+ int32, /* idb_object_store_id */
+ string16, /* name */
+ bool, /* success */
+ int32 /* idb_index_id */)
+
+ // WebIDBObjectStore::removeIndex() message.
+ IPC_MESSAGE_CONTROL3(ViewHostMsg_IDBObjectStoreRemoveIndex,
+ int32, /* idb_object_store_id */
+ int32, /* response_id */
+ string16 /* name */)
+
+ // WebIDBObjectStore::~WebIDBObjectStore() message.
+ IPC_MESSAGE_CONTROL1(ViewHostMsg_IDBObjectStoreDestroyed,
+ int32 /* idb_object_store_id */)
+
+ // Get file size in bytes. Set result to -1 if failed to get the file size.
+ IPC_SYNC_MESSAGE_CONTROL1_1(ViewHostMsg_GetFileSize,
+ FilePath /* path */,
+ int64 /* result */)
+
+ // Get file modification time in seconds. Set result to 0 if failed to get the
+ // file modification time.
+ IPC_SYNC_MESSAGE_CONTROL1_1(ViewHostMsg_GetFileModificationTime,
+ FilePath /* path */,
+ base::Time /* result */)
+
+ // Open the file.
+ IPC_SYNC_MESSAGE_CONTROL2_1(ViewHostMsg_OpenFile,
+ FilePath /* path */,
+ int /* mode */,
+ IPC::PlatformFileForTransit /* result */)
+
+ // Sent by the renderer process to acknowledge receipt of a
+ // ViewMsg_CSSInsertRequest message and css has been inserted into the frame.
+ IPC_MESSAGE_ROUTED0(ViewHostMsg_OnCSSInserted)
+
+ // Sent by the renderer process to check whether access to web databases is
+ // granted by content settings. This may block and trigger a cookie prompt.
+ IPC_SYNC_MESSAGE_ROUTED4_1(ViewHostMsg_AllowDatabase,
+ std::string /* origin_url */,
+ string16 /* database name */,
+ string16 /* database display name */,
+ unsigned long /* estimated size */,
+ bool /* result */)
+
+ // Asks the browser process to open a DB file with the given name.
+ IPC_SYNC_MESSAGE_CONTROL2_1(ViewHostMsg_DatabaseOpenFile,
+ string16 /* vfs file name */,
+ int /* desired flags */,
+ IPC::PlatformFileForTransit /* file_handle */)
+
+ // Asks the browser process to delete a DB file
+ IPC_SYNC_MESSAGE_CONTROL2_1(ViewHostMsg_DatabaseDeleteFile,
+ string16 /* vfs file name */,
+ bool /* whether or not to sync the directory */,
+ int /* SQLite error code */)
+
+ // Asks the browser process to return the attributes of a DB file
+ IPC_SYNC_MESSAGE_CONTROL1_1(ViewHostMsg_DatabaseGetFileAttributes,
+ string16 /* vfs file name */,
+ int32 /* the attributes for the given DB file */)
+
+ // Asks the browser process to return the size of a DB file
+ IPC_SYNC_MESSAGE_CONTROL1_1(ViewHostMsg_DatabaseGetFileSize,
+ string16 /* vfs file name */,
+ int64 /* the size of the given DB file */)
+
+ // Notifies the browser process that a new database has been opened
+ IPC_MESSAGE_CONTROL4(ViewHostMsg_DatabaseOpened,
+ string16 /* origin identifier */,
+ string16 /* database name */,
+ string16 /* database description */,
+ int64 /* estimated size */)
+
+ // Notifies the browser process that a database might have been modified
+ IPC_MESSAGE_CONTROL2(ViewHostMsg_DatabaseModified,
+ string16 /* origin identifier */,
+ string16 /* database name */)
+
+ // Notifies the browser process that a database is about to close
+ IPC_MESSAGE_CONTROL2(ViewHostMsg_DatabaseClosed,
+ string16 /* origin identifier */,
+ string16 /* database name */)
+
+ // Notifies the browser of the language (ISO 639_1 code language, such as fr,
+ // en, zh...) of the current page.
+ IPC_MESSAGE_ROUTED1(ViewHostMsg_PageLanguageDetermined,
+ std::string /* the language */)
+
+ // Notifies the browser that a page has been translated.
+ IPC_MESSAGE_ROUTED4(ViewHostMsg_PageTranslated,
+ int, /* page id */
+ std::string /* the original language */,
+ std::string /* the translated language */,
+ TranslateErrors::Type /* the error type if available */)
+
+ //---------------------------------------------------------------------------
+ // Socket Stream messages:
+ // These are messages from the SocketStreamHandle to the browser.
+
+ // Open new Socket Stream for the |socket_url| identified by |socket_id|
+ // in the renderer process.
+ // The browser starts connecting asynchronously.
+ // Once Socket Stream connection is established, the browser will send
+ // ViewMsg_SocketStream_Connected back.
+ IPC_MESSAGE_CONTROL2(ViewHostMsg_SocketStream_Connect,
+ GURL /* socket_url */,
+ int /* socket_id */)
+
+ // Request to send data on the Socket Stream.
+ // SocketStreamHandle can send data at most |max_pending_send_allowed| bytes,
+ // which is given by ViewMsg_SocketStream_Connected at any time.
+ // The number of pending bytes can be tracked by size of |data| sent
+ // and |amount_sent| parameter of ViewMsg_SocketStream_DataSent.
+ // That is, the following constraints is applied:
+ // (accumulated total of |data|) - (accumulated total of |amount_sent|)
+ // <= |max_pending_send_allowed|
+ // If the SocketStreamHandle ever tries to exceed the
+ // |max_pending_send_allowed|, the connection will be closed.
+ IPC_MESSAGE_CONTROL2(ViewHostMsg_SocketStream_SendData,
+ int /* socket_id */,
+ std::vector<char> /* data */)
+
+ // Request to close the Socket Stream.
+ // The browser will send ViewMsg_SocketStream_Closed back when the Socket
+ // Stream is completely closed.
+ IPC_MESSAGE_CONTROL1(ViewHostMsg_SocketStream_Close,
+ int /* socket_id */)
+
+ //---------------------------------------------------------------------------
+ // Request for cryptographic operation messages:
+ // These are messages from the renderer to the browser to perform a
+ // cryptographic operation.
+
+ // Asks the browser process to generate a keypair for grabbing a client
+ // certificate from a CA (<keygen> tag), and returns the signed public
+ // key and challenge string.
+ IPC_SYNC_MESSAGE_CONTROL3_1(ViewHostMsg_Keygen,
+ uint32 /* key size index */,
+ std::string /* challenge string */,
+ GURL /* URL of requestor */,
+ std::string /* signed public key and challenge */)
+
+ // The renderer has tried to spell check a word, but couldn't because no
+ // dictionary was available to load. Request that the browser find an
+ // appropriate dictionary and return it.
+ IPC_MESSAGE_CONTROL0(ViewHostMsg_SpellChecker_RequestDictionary)
+
+ IPC_SYNC_MESSAGE_CONTROL2_1(ViewHostMsg_SpellChecker_PlatformCheckSpelling,
+ string16 /* word */,
+ int /* document tag */,
+ bool /* correct */)
+
+ IPC_SYNC_MESSAGE_CONTROL1_1(
+ ViewHostMsg_SpellChecker_PlatformFillSuggestionList,
+ string16 /* word */,
+ std::vector<string16> /* suggestions */)
+
+ //---------------------------------------------------------------------------
+ // Geolocation services messages
+
+ // A GeolocationServiceBridgeImpl in the renderer process has been created.
+ // This is used to lazily initialize the host dispatchers and related
+ // Geolocation infrastructure in the browser process.
+ IPC_MESSAGE_CONTROL1(ViewHostMsg_Geolocation_RegisterDispatcher,
+ int /* render_view_id */)
+
+ // A GeolocationServiceBridgeImpl has been destroyed.
+ // This is used to let the Geolocation infrastructure do its cleanup.
+ IPC_MESSAGE_CONTROL1(ViewHostMsg_Geolocation_UnregisterDispatcher,
+ int /* render_view_id */)
+
+ // The |render_view_id| and |bridge_id| representing |host| is requesting
+ // permission to access geolocation position.
+ // This will be replied by ViewMsg_Geolocation_PermissionSet.
+ IPC_MESSAGE_CONTROL3(ViewHostMsg_Geolocation_RequestPermission,
+ int /* render_view_id */,
+ int /* bridge_id */,
+ GURL /* GURL of the frame requesting geolocation */)
+
+ // The |render_view_id| and |bridge_id| representing |GURL| is cancelling its
+ // previous permission request to access geolocation position.
+ IPC_MESSAGE_CONTROL3(ViewHostMsg_Geolocation_CancelPermissionRequest,
+ int /* render_view_id */,
+ int /* bridge_id */,
+ GURL /* GURL of the frame */)
+
+ // The |render_view_id| and |bridge_id| requests Geolocation service to start
+ // updating.
+ // This is an asynchronous call, and the browser process may eventually reply
+ // with the updated geoposition, or an error (access denied, location
+ // unavailable, etc.)
+ IPC_MESSAGE_CONTROL4(ViewHostMsg_Geolocation_StartUpdating,
+ int /* render_view_id */,
+ int /* bridge_id */,
+ GURL /* GURL of the frame requesting geolocation */,
+ bool /* enable_high_accuracy */)
+
+ // The |render_view_id| and |bridge_id| requests Geolocation service to stop
+ // updating.
+ // Note that the geolocation service may continue to fetch geolocation data
+ // for other origins.
+ IPC_MESSAGE_CONTROL2(ViewHostMsg_Geolocation_StopUpdating,
+ int /* render_view_id */,
+ int /* bridge_id */)
+
+ // The |render_view_id| and |bridge_id| requests Geolocation service to
+ // suspend.
+ // Note that the geolocation service may continue to fetch geolocation data
+ // for other origins.
+ IPC_MESSAGE_CONTROL2(ViewHostMsg_Geolocation_Suspend,
+ int /* render_view_id */,
+ int /* bridge_id */)
+
+ // The |render_view_id| and |bridge_id| requests Geolocation service to
+ // resume.
+ IPC_MESSAGE_CONTROL2(ViewHostMsg_Geolocation_Resume,
+ int /* render_view_id */,
+ int /* bridge_id */)
+
+ // Send the tree of accessibility data to the browser, where it's cached
+ // in order to respond to OS accessibility queries immediately.
+ IPC_MESSAGE_ROUTED1(ViewHostMsg_AccessibilityTree,
+ webkit_glue::WebAccessibility)
+
+IPC_END_MESSAGES(ViewHost)
diff --git a/chrome/common/render_messages_unittest.cc b/chrome/common/render_messages_unittest.cc
new file mode 100644
index 0000000..30b1446
--- /dev/null
+++ b/chrome/common/render_messages_unittest.cc
@@ -0,0 +1,92 @@
+// Copyright (c) 2010 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/scoped_ptr.h"
+#include "base/string16.h"
+#include "base/values.h"
+#include "chrome/common/render_messages.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+TEST(RenderMessagesUnittest, WebAccessibility) {
+ // Test a simple case.
+ webkit_glue::WebAccessibility input;
+ input.id = 123;
+ input.name = ASCIIToUTF16("name");
+ input.value = ASCIIToUTF16("value");
+ string16 help = ASCIIToUTF16("help");
+ input.attributes[webkit_glue::WebAccessibility::ATTR_HELP] = help;
+ input.role = webkit_glue::WebAccessibility::ROLE_CHECKBOX;
+ input.state =
+ (1 << webkit_glue::WebAccessibility::STATE_CHECKED) |
+ (1 << webkit_glue::WebAccessibility::STATE_FOCUSED);
+ input.location = WebKit::WebRect(11, 22, 333, 444);
+
+ IPC::Message msg(1, 2, IPC::Message::PRIORITY_NORMAL);
+ IPC::WriteParam(&msg, input);
+
+ webkit_glue::WebAccessibility output;
+ void* iter = NULL;
+ EXPECT_TRUE(IPC::ReadParam(&msg, &iter, &output));
+ EXPECT_EQ(input.id, output.id);
+ EXPECT_EQ(input.name, output.name);
+ EXPECT_EQ(input.value, output.value);
+ EXPECT_EQ(static_cast<size_t>(1), input.attributes.size());
+ EXPECT_EQ(help, input.attributes[webkit_glue::WebAccessibility::ATTR_HELP]);
+ EXPECT_EQ(input.role, output.role);
+ EXPECT_EQ(input.state, output.state);
+ EXPECT_EQ(input.location, output.location);
+ EXPECT_EQ(input.children.size(), output.children.size());
+
+ // Test a corrupt case.
+ IPC::Message bad_msg(1, 2, IPC::Message::PRIORITY_NORMAL);
+ bad_msg.WriteInt(99);
+ iter = NULL;
+ EXPECT_FALSE(IPC::ReadParam(&bad_msg, &iter, &output));
+
+ // Test a recursive case.
+ webkit_glue::WebAccessibility outer;
+ outer.id = 1000;
+ outer.name = ASCIIToUTF16("outer_name");
+ outer.role = webkit_glue::WebAccessibility::ROLE_GROUP;
+ outer.state = 0;
+ outer.location = WebKit::WebRect(0, 0, 1000, 1000);
+ webkit_glue::WebAccessibility inner1;
+ inner1.id = 1001;
+ inner1.name = ASCIIToUTF16("inner1_name");
+ inner1.role = webkit_glue::WebAccessibility::ROLE_RADIO_BUTTON;
+ inner1.state =
+ (1 << webkit_glue::WebAccessibility::STATE_CHECKED) |
+ (1 << webkit_glue::WebAccessibility::STATE_FOCUSED);
+ inner1.location = WebKit::WebRect(10, 10, 900, 400);
+ outer.children.push_back(inner1);
+ webkit_glue::WebAccessibility inner2;
+ inner2.id = 1002;
+ inner2.name = ASCIIToUTF16("inner2_name");
+ inner2.role = webkit_glue::WebAccessibility::ROLE_RADIO_BUTTON;
+ inner2.state = (1 << webkit_glue::WebAccessibility::STATE_CHECKED);
+ inner2.location = WebKit::WebRect(10, 500, 900, 400);
+ outer.children.push_back(inner2);
+
+ IPC::Message msg2(1, 2, IPC::Message::PRIORITY_NORMAL);
+ IPC::WriteParam(&msg2, outer);
+
+ void* iter2 = NULL;
+ EXPECT_TRUE(IPC::ReadParam(&msg2, &iter2, &output));
+ EXPECT_EQ(outer.id, output.id);
+ EXPECT_EQ(outer.name, output.name);
+ EXPECT_EQ(outer.role, output.role);
+ EXPECT_EQ(outer.state, output.state);
+ EXPECT_EQ(outer.location, output.location);
+ EXPECT_EQ(outer.children.size(), output.children.size());
+ EXPECT_EQ(inner1.id, output.children[0].id);
+ EXPECT_EQ(inner1.name, output.children[0].name);
+ EXPECT_EQ(inner1.role, output.children[0].role);
+ EXPECT_EQ(inner1.state, output.children[0].state);
+ EXPECT_EQ(inner1.location, output.children[0].location);
+ EXPECT_EQ(inner2.id, output.children[1].id);
+ EXPECT_EQ(inner2.name, output.children[1].name);
+ EXPECT_EQ(inner2.role, output.children[1].role);
+ EXPECT_EQ(inner2.state, output.children[1].state);
+ EXPECT_EQ(inner2.location, output.children[1].location);
+}
diff --git a/chrome/common/renderer_preferences.h b/chrome/common/renderer_preferences.h
new file mode 100644
index 0000000..7a55b17
--- /dev/null
+++ b/chrome/common/renderer_preferences.h
@@ -0,0 +1,93 @@
+// Copyright (c) 2006-2008 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.
+//
+// A struct for managing browser's settings that apply to the renderer or its
+// webview. These differ from WebPreferences since they apply to Chromium's
+// glue layer rather than applying to just WebKit.
+//
+// Adding new values to this class probably involves updating
+// common/render_messages.h, browser/browser.cc, etc.
+
+#ifndef CHROME_COMMON_RENDERER_PREFERENCES_H_
+#define CHROME_COMMON_RENDERER_PREFERENCES_H_
+
+#include "third_party/skia/include/core/SkColor.h"
+
+enum RendererPreferencesHintingEnum {
+ RENDERER_PREFERENCES_HINTING_SYSTEM_DEFAULT = 0,
+ RENDERER_PREFERENCES_HINTING_NONE,
+ RENDERER_PREFERENCES_HINTING_SLIGHT,
+ RENDERER_PREFERENCES_HINTING_MEDIUM,
+ RENDERER_PREFERENCES_HINTING_FULL,
+};
+
+enum RendererPreferencesSubpixelRenderingEnum {
+ RENDERER_PREFERENCES_SUBPIXEL_RENDERING_SYSTEM_DEFAULT = 0,
+ RENDERER_PREFERENCES_SUBPIXEL_RENDERING_NONE,
+ RENDERER_PREFERENCES_SUBPIXEL_RENDERING_RGB,
+ RENDERER_PREFERENCES_SUBPIXEL_RENDERING_BGR,
+ RENDERER_PREFERENCES_SUBPIXEL_RENDERING_VRGB,
+ RENDERER_PREFERENCES_SUBPIXEL_RENDERING_VBGR,
+};
+
+struct RendererPreferences {
+ // Whether the renderer's current browser context accept drops from the OS
+ // that result in navigations away from the current page.
+ bool can_accept_load_drops;
+
+ // Whether text should be antialiased.
+ // Currently only used by Linux.
+ bool should_antialias_text;
+
+ // The level of hinting to use when rendering text.
+ // Currently only used by Linux.
+ RendererPreferencesHintingEnum hinting;
+
+ // The type of subpixel rendering to use for text.
+ // Currently only used by Linux.
+ RendererPreferencesSubpixelRenderingEnum subpixel_rendering;
+
+ // The color of the focus ring. Currently only used on Linux.
+ SkColor focus_ring_color;
+
+ // The color of different parts of the scrollbar. Currently only used on
+ // Linux.
+ SkColor thumb_active_color;
+ SkColor thumb_inactive_color;
+ SkColor track_color;
+
+ // The colors used in selection text. Currently only used on Linux.
+ SkColor active_selection_bg_color;
+ SkColor active_selection_fg_color;
+ SkColor inactive_selection_bg_color;
+ SkColor inactive_selection_fg_color;
+
+ // Browser wants a look at all top level requests
+ bool browser_handles_top_level_requests;
+
+ // Cursor blink rate in seconds.
+ // Currently only changed from default on Linux. Uses |gtk-cursor-blink|
+ // from GtkSettings.
+ double caret_blink_interval;
+
+ RendererPreferences()
+ : can_accept_load_drops(true),
+ should_antialias_text(true),
+ hinting(RENDERER_PREFERENCES_HINTING_SYSTEM_DEFAULT),
+ subpixel_rendering(
+ RENDERER_PREFERENCES_SUBPIXEL_RENDERING_SYSTEM_DEFAULT),
+ focus_ring_color(0),
+ thumb_active_color(0),
+ thumb_inactive_color(0),
+ track_color(0),
+ active_selection_bg_color(0),
+ active_selection_fg_color(0),
+ inactive_selection_bg_color(0),
+ inactive_selection_fg_color(0),
+ browser_handles_top_level_requests(false),
+ caret_blink_interval(0) {
+ }
+};
+
+#endif // CHROME_COMMON_RENDERER_PREFERENCES_H_
diff --git a/chrome/common/resource_dispatcher.cc b/chrome/common/resource_dispatcher.cc
new file mode 100644
index 0000000..ace6169
--- /dev/null
+++ b/chrome/common/resource_dispatcher.cc
@@ -0,0 +1,628 @@
+// Copyright (c) 2010 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.
+
+// See http://dev.chromium.org/developers/design-documents/multi-process-resource-loading
+
+#include "chrome/common/resource_dispatcher.h"
+
+#include "base/basictypes.h"
+#include "base/compiler_specific.h"
+#include "base/file_path.h"
+#include "base/message_loop.h"
+#include "base/shared_memory.h"
+#include "base/string_util.h"
+#include "chrome/common/extensions/extension_localization_peer.h"
+#include "chrome/common/render_messages.h"
+#include "chrome/common/security_filter_peer.h"
+#include "net/base/net_errors.h"
+#include "net/base/net_util.h"
+#include "webkit/glue/resource_type.h"
+#include "webkit/glue/webkit_glue.h"
+
+// Uncomment to enable logging of request traffic
+// #define LOG_RESOURCE_REQUESTS
+
+#ifdef LOG_RESOURCE_REQUESTS
+# define RESOURCE_LOG(stuff) LOG(INFO) << stuff
+#else
+# define RESOURCE_LOG(stuff)
+#endif
+
+// Each resource request is assigned an ID scoped to this process.
+static int MakeRequestID() {
+ // NOTE: The resource_dispatcher_host also needs probably unique
+ // request_ids, so they count down from -2 (-1 is a special we're
+ // screwed value), while the renderer process counts up.
+ static int next_request_id = 0;
+ return next_request_id++;
+}
+
+// ResourceLoaderBridge implementation ----------------------------------------
+
+namespace webkit_glue {
+
+class IPCResourceLoaderBridge : public ResourceLoaderBridge {
+ public:
+ IPCResourceLoaderBridge(ResourceDispatcher* dispatcher,
+ const webkit_glue::ResourceLoaderBridge::RequestInfo& request_info,
+ int host_renderer_id,
+ int host_render_view_id);
+ virtual ~IPCResourceLoaderBridge();
+
+ // ResourceLoaderBridge
+ virtual void AppendDataToUpload(const char* data, int data_len);
+ virtual void AppendFileRangeToUpload(
+ const FilePath& path,
+ uint64 offset,
+ uint64 length,
+ const base::Time& expected_modification_time);
+ virtual void SetUploadIdentifier(int64 identifier);
+ virtual bool Start(Peer* peer);
+ virtual void Cancel();
+ virtual void SetDefersLoading(bool value);
+ virtual void SyncLoad(SyncLoadResponse* response);
+
+#ifdef LOG_RESOURCE_REQUESTS
+ const std::string& url() const { return url_; }
+#endif
+
+ private:
+ ResourceLoaderBridge::Peer* peer_;
+
+ // The resource dispatcher for this loader. The bridge doesn't own it, but
+ // it's guaranteed to outlive the bridge.
+ ResourceDispatcher* dispatcher_;
+
+ // The request to send, created on initialization for modification and
+ // appending data.
+ ViewHostMsg_Resource_Request request_;
+
+ // ID for the request, valid once Start()ed, -1 if not valid yet.
+ int request_id_;
+
+ // The routing id used when sending IPC messages.
+ int routing_id_;
+
+#ifdef LOG_RESOURCE_REQUESTS
+ // indicates the URL of this resource request for help debugging
+ std::string url_;
+#endif
+
+ // The following two members are specified if the request is initiated by
+ // a plugin like Gears.
+
+ // Contains the id of the host renderer.
+ int host_renderer_id_;
+
+ // Contains the id of the host render view.
+ int host_render_view_id_;
+};
+
+IPCResourceLoaderBridge::IPCResourceLoaderBridge(
+ ResourceDispatcher* dispatcher,
+ const webkit_glue::ResourceLoaderBridge::RequestInfo& request_info,
+ int host_renderer_id,
+ int host_render_view_id)
+ : peer_(NULL),
+ dispatcher_(dispatcher),
+ request_id_(-1),
+ routing_id_(request_info.routing_id),
+ host_renderer_id_(host_renderer_id),
+ host_render_view_id_(host_render_view_id) {
+ DCHECK(dispatcher_) << "no resource dispatcher";
+ request_.method = request_info.method;
+ request_.url = request_info.url;
+ request_.first_party_for_cookies = request_info.first_party_for_cookies;
+ request_.referrer = request_info.referrer;
+ request_.frame_origin = request_info.frame_origin;
+ request_.main_frame_origin = request_info.main_frame_origin;
+ request_.headers = request_info.headers;
+ request_.load_flags = request_info.load_flags;
+ request_.origin_child_id = request_info.requestor_pid;
+ request_.resource_type = request_info.request_type;
+ request_.request_context = request_info.request_context;
+ request_.appcache_host_id = request_info.appcache_host_id;
+ request_.host_renderer_id = host_renderer_id_;
+ request_.host_render_view_id = host_render_view_id_;
+
+#ifdef LOG_RESOURCE_REQUESTS
+ url_ = url.possibly_invalid_spec();
+#endif
+}
+
+IPCResourceLoaderBridge::~IPCResourceLoaderBridge() {
+ // we remove our hook for the resource dispatcher only when going away, since
+ // it doesn't keep track of whether we've force terminated the request
+ if (request_id_ >= 0) {
+ // this operation may fail, as the dispatcher will have preemptively
+ // removed us when the renderer sends the ReceivedAllData message.
+ dispatcher_->RemovePendingRequest(request_id_);
+ }
+}
+
+void IPCResourceLoaderBridge::AppendDataToUpload(const char* data,
+ int data_len) {
+ DCHECK(request_id_ == -1) << "request already started";
+
+ // don't bother appending empty data segments
+ if (data_len == 0)
+ return;
+
+ if (!request_.upload_data)
+ request_.upload_data = new net::UploadData();
+ request_.upload_data->AppendBytes(data, data_len);
+}
+
+void IPCResourceLoaderBridge::AppendFileRangeToUpload(
+ const FilePath& path, uint64 offset, uint64 length,
+ const base::Time& expected_modification_time) {
+ DCHECK(request_id_ == -1) << "request already started";
+
+ if (!request_.upload_data)
+ request_.upload_data = new net::UploadData();
+ request_.upload_data->AppendFileRange(path, offset, length,
+ expected_modification_time);
+}
+
+void IPCResourceLoaderBridge::SetUploadIdentifier(int64 identifier) {
+ DCHECK(request_id_ == -1) << "request already started";
+
+ if (!request_.upload_data)
+ request_.upload_data = new net::UploadData();
+ request_.upload_data->set_identifier(identifier);
+}
+
+// Writes a footer on the message and sends it
+bool IPCResourceLoaderBridge::Start(Peer* peer) {
+ if (request_id_ != -1) {
+ NOTREACHED() << "Starting a request twice";
+ return false;
+ }
+
+ RESOURCE_LOG("Starting request for " << url_);
+
+ peer_ = peer;
+
+ // generate the request ID, and append it to the message
+ request_id_ = dispatcher_->AddPendingRequest(
+ peer_, request_.resource_type, request_.url);
+
+ return dispatcher_->message_sender()->Send(
+ new ViewHostMsg_RequestResource(routing_id_, request_id_, request_));
+}
+
+void IPCResourceLoaderBridge::Cancel() {
+ if (request_id_ < 0) {
+ NOTREACHED() << "Trying to cancel an unstarted request";
+ return;
+ }
+
+ RESOURCE_LOG("Canceling request for " << url_);
+
+ dispatcher_->CancelPendingRequest(routing_id_, request_id_);
+
+ // We can't remove the request ID from the resource dispatcher because more
+ // data might be pending. Sending the cancel message may cause more data
+ // to be flushed, and will then cause a complete message to be sent.
+}
+
+void IPCResourceLoaderBridge::SetDefersLoading(bool value) {
+ if (request_id_ < 0) {
+ NOTREACHED() << "Trying to (un)defer an unstarted request";
+ return;
+ }
+
+ dispatcher_->SetDefersLoading(request_id_, value);
+}
+
+void IPCResourceLoaderBridge::SyncLoad(SyncLoadResponse* response) {
+ if (request_id_ != -1) {
+ NOTREACHED() << "Starting a request twice";
+ response->status.set_status(URLRequestStatus::FAILED);
+ return;
+ }
+
+ RESOURCE_LOG("Making sync request for " << url_);
+
+ request_id_ = MakeRequestID();
+
+ SyncLoadResult result;
+ IPC::SyncMessage* msg = new ViewHostMsg_SyncLoad(routing_id_, request_id_,
+ request_, &result);
+ // NOTE: This may pump events (see RenderThread::Send).
+ if (!dispatcher_->message_sender()->Send(msg)) {
+ response->status.set_status(URLRequestStatus::FAILED);
+ return;
+ }
+
+ response->status = result.status;
+ response->url = result.final_url;
+ response->headers = result.headers;
+ response->mime_type = result.mime_type;
+ response->charset = result.charset;
+ response->data.swap(result.data);
+}
+
+} // namespace webkit_glue
+
+// ResourceDispatcher ---------------------------------------------------------
+
+ResourceDispatcher::ResourceDispatcher(IPC::Message::Sender* sender)
+ : message_sender_(sender),
+ ALLOW_THIS_IN_INITIALIZER_LIST(method_factory_(this)) {
+}
+
+ResourceDispatcher::~ResourceDispatcher() {
+}
+
+// ResourceDispatcher implementation ------------------------------------------
+
+bool ResourceDispatcher::OnMessageReceived(const IPC::Message& message) {
+ if (!IsResourceDispatcherMessage(message)) {
+ return false;
+ }
+
+ int request_id;
+
+ void* iter = NULL;
+ if (!message.ReadInt(&iter, &request_id)) {
+ NOTREACHED() << "malformed resource message";
+ return true;
+ }
+
+ PendingRequestList::iterator it = pending_requests_.find(request_id);
+ if (it == pending_requests_.end()) {
+ // This might happen for kill()ed requests on the webkit end, so perhaps it
+ // shouldn't be a warning...
+ DLOG(WARNING) << "Got response for a nonexistent or finished request";
+ // Release resources in the message if it is a data message.
+ ReleaseResourcesInDataMessage(message);
+ return true;
+ }
+
+ PendingRequestInfo& request_info = it->second;
+ if (request_info.is_deferred) {
+ request_info.deferred_message_queue.push_back(new IPC::Message(message));
+ return true;
+ }
+ // Make sure any deferred messages are dispatched before we dispatch more.
+ if (!request_info.deferred_message_queue.empty()) {
+ FlushDeferredMessages(request_id);
+ // The request could have been deferred now. If yes then the current
+ // message has to be queued up. The request_info instance should remain
+ // valid here as there are pending messages for it.
+ DCHECK(pending_requests_.find(request_id) != pending_requests_.end());
+ if (request_info.is_deferred) {
+ request_info.deferred_message_queue.push_back(new IPC::Message(message));
+ return true;
+ }
+ }
+
+ DispatchMessage(message);
+ return true;
+}
+
+void ResourceDispatcher::OnUploadProgress(
+ const IPC::Message& message, int request_id, int64 position, int64 size) {
+ PendingRequestList::iterator it = pending_requests_.find(request_id);
+ if (it == pending_requests_.end()) {
+ // this might happen for kill()ed requests on the webkit end, so perhaps
+ // it shouldn't be a warning...
+ DLOG(WARNING) << "Got upload progress for a nonexistent or "
+ "finished request";
+ return;
+ }
+
+ PendingRequestInfo& request_info = it->second;
+
+ RESOURCE_LOG("Dispatching upload progress for " <<
+ request_info.peer->GetURLForDebugging().possibly_invalid_spec());
+ request_info.peer->OnUploadProgress(position, size);
+
+ // Acknowledge receipt
+ message_sender()->Send(
+ new ViewHostMsg_UploadProgress_ACK(message.routing_id(), request_id));
+}
+
+void ResourceDispatcher::OnReceivedResponse(
+ int request_id, const ResourceResponseHead& response_head) {
+ PendingRequestList::iterator it = pending_requests_.find(request_id);
+ if (it == pending_requests_.end()) {
+ // This might happen for kill()ed requests on the webkit end, so perhaps it
+ // shouldn't be a warning...
+ DLOG(WARNING) << "Got response for a nonexistent or finished request";
+ return;
+ }
+
+ PendingRequestInfo& request_info = it->second;
+ if (response_head.replace_extension_localization_templates) {
+ webkit_glue::ResourceLoaderBridge::Peer* new_peer =
+ ExtensionLocalizationPeer::CreateExtensionLocalizationPeer(
+ request_info.peer, message_sender(), response_head.mime_type,
+ request_info.url);
+ if (new_peer)
+ request_info.peer = new_peer;
+ }
+
+ RESOURCE_LOG("Dispatching response for " <<
+ request_info.peer->GetURLForDebugging().possibly_invalid_spec());
+ request_info.peer->OnReceivedResponse(response_head, false);
+}
+
+void ResourceDispatcher::OnReceivedCachedMetadata(
+ int request_id, const std::vector<char>& data) {
+ PendingRequestList::iterator it = pending_requests_.find(request_id);
+ if (it == pending_requests_.end()) {
+ // this might happen for kill()ed requests on the webkit end, so perhaps
+ // it shouldn't be a warning...
+ DLOG(WARNING) << "Got metadata for a nonexistent or finished request";
+ return;
+ }
+
+ if (data.size()) {
+ PendingRequestInfo& request_info = it->second;
+ RESOURCE_LOG("Dispatching " << data.size() << " metadata bytes for " <<
+ request_info.peer->GetURLForDebugging().possibly_invalid_spec());
+ request_info.peer->OnReceivedCachedMetadata(&data.front(), data.size());
+ }
+}
+
+void ResourceDispatcher::OnReceivedData(const IPC::Message& message,
+ int request_id,
+ base::SharedMemoryHandle shm_handle,
+ int data_len) {
+ // Acknowledge the reception of this data.
+ message_sender()->Send(
+ new ViewHostMsg_DataReceived_ACK(message.routing_id(), request_id));
+
+ const bool shm_valid = base::SharedMemory::IsHandleValid(shm_handle);
+ DCHECK((shm_valid && data_len > 0) || (!shm_valid && !data_len));
+ base::SharedMemory shared_mem(shm_handle, true); // read only
+
+ PendingRequestList::iterator it = pending_requests_.find(request_id);
+ if (it == pending_requests_.end()) {
+ // this might happen for kill()ed requests on the webkit end, so perhaps
+ // it shouldn't be a warning...
+ DLOG(WARNING) << "Got data for a nonexistent or finished request";
+ return;
+ }
+
+ PendingRequestInfo& request_info = it->second;
+
+ if (data_len > 0 && shared_mem.Map(data_len)) {
+ RESOURCE_LOG("Dispatching " << data_len << " bytes for " <<
+ request_info.peer->GetURLForDebugging().possibly_invalid_spec());
+ const char* data = static_cast<char*>(shared_mem.memory());
+ request_info.peer->OnReceivedData(data, data_len);
+ }
+}
+
+void ResourceDispatcher::OnReceivedRedirect(
+ const IPC::Message& message,
+ int request_id,
+ const GURL& new_url,
+ const webkit_glue::ResourceLoaderBridge::ResponseInfo& info) {
+ PendingRequestList::iterator it = pending_requests_.find(request_id);
+ if (it == pending_requests_.end()) {
+ // this might happen for kill()ed requests on the webkit end, so perhaps
+ // it shouldn't be a warning...
+ DLOG(WARNING) << "Got data for a nonexistent or finished request";
+ return;
+ }
+
+ PendingRequestInfo& request_info = it->second;
+
+ RESOURCE_LOG("Dispatching redirect for " <<
+ request_info.peer->GetURLForDebugging().possibly_invalid_spec());
+
+ bool has_new_first_party_for_cookies = false;
+ GURL new_first_party_for_cookies;
+ if (request_info.peer->OnReceivedRedirect(new_url, info,
+ &has_new_first_party_for_cookies,
+ &new_first_party_for_cookies)) {
+ message_sender()->Send(
+ new ViewHostMsg_FollowRedirect(message.routing_id(), request_id,
+ has_new_first_party_for_cookies,
+ new_first_party_for_cookies));
+ } else {
+ CancelPendingRequest(message.routing_id(), request_id);
+ }
+}
+
+void ResourceDispatcher::OnRequestComplete(int request_id,
+ const URLRequestStatus& status,
+ const std::string& security_info) {
+ PendingRequestList::iterator it = pending_requests_.find(request_id);
+ if (it == pending_requests_.end()) {
+ // this might happen for kill()ed requests on the webkit end, so perhaps
+ // it shouldn't be a warning...
+ DLOG(WARNING) << "Got 'complete' for a nonexistent or finished request";
+ return;
+ }
+
+ PendingRequestInfo& request_info = it->second;
+ webkit_glue::ResourceLoaderBridge::Peer* peer = request_info.peer;
+
+ RESOURCE_LOG("Dispatching complete for " <<
+ request_info.peer->GetURLForDebugging().possibly_invalid_spec());
+
+ if (status.status() == URLRequestStatus::CANCELED &&
+ status.os_error() != net::ERR_ABORTED) {
+ // Resource canceled with a specific error are filtered.
+ SecurityFilterPeer* new_peer =
+ SecurityFilterPeer::CreateSecurityFilterPeerForDeniedRequest(
+ request_info.resource_type,
+ request_info.peer,
+ status.os_error());
+ if (new_peer) {
+ request_info.peer = new_peer;
+ peer = new_peer;
+ }
+ }
+
+ // The request ID will be removed from our pending list in the destructor.
+ // Normally, dispatching this message causes the reference-counted request to
+ // die immediately.
+ peer->OnCompletedRequest(status, security_info);
+
+ webkit_glue::NotifyCacheStats();
+}
+
+int ResourceDispatcher::AddPendingRequest(
+ webkit_glue::ResourceLoaderBridge::Peer* callback,
+ ResourceType::Type resource_type,
+ const GURL& request_url) {
+ // Compute a unique request_id for this renderer process.
+ int id = MakeRequestID();
+ pending_requests_[id] =
+ PendingRequestInfo(callback, resource_type, request_url);
+ return id;
+}
+
+bool ResourceDispatcher::RemovePendingRequest(int request_id) {
+ PendingRequestList::iterator it = pending_requests_.find(request_id);
+ if (it == pending_requests_.end())
+ return false;
+
+ PendingRequestInfo& request_info = it->second;
+ ReleaseResourcesInMessageQueue(&request_info.deferred_message_queue);
+ pending_requests_.erase(it);
+
+ return true;
+}
+
+void ResourceDispatcher::CancelPendingRequest(int routing_id,
+ int request_id) {
+ PendingRequestList::iterator it = pending_requests_.find(request_id);
+ if (it == pending_requests_.end()) {
+ DLOG(WARNING) << "unknown request";
+ return;
+ }
+
+ PendingRequestInfo& request_info = it->second;
+ ReleaseResourcesInMessageQueue(&request_info.deferred_message_queue);
+ pending_requests_.erase(it);
+
+ message_sender()->Send(
+ new ViewHostMsg_CancelRequest(routing_id, request_id));
+}
+
+void ResourceDispatcher::SetDefersLoading(int request_id, bool value) {
+ PendingRequestList::iterator it = pending_requests_.find(request_id);
+ if (it == pending_requests_.end()) {
+ DLOG(ERROR) << "unknown request";
+ return;
+ }
+ PendingRequestInfo& request_info = it->second;
+ if (value) {
+ request_info.is_deferred = value;
+ } else if (request_info.is_deferred) {
+ request_info.is_deferred = false;
+ MessageLoop::current()->PostTask(FROM_HERE,
+ method_factory_.NewRunnableMethod(
+ &ResourceDispatcher::FlushDeferredMessages, request_id));
+ }
+}
+
+void ResourceDispatcher::DispatchMessage(const IPC::Message& message) {
+ IPC_BEGIN_MESSAGE_MAP(ResourceDispatcher, message)
+ IPC_MESSAGE_HANDLER(ViewMsg_Resource_UploadProgress, OnUploadProgress)
+ IPC_MESSAGE_HANDLER(ViewMsg_Resource_ReceivedResponse, OnReceivedResponse)
+ IPC_MESSAGE_HANDLER(
+ ViewMsg_Resource_ReceivedCachedMetadata, OnReceivedCachedMetadata)
+ IPC_MESSAGE_HANDLER(ViewMsg_Resource_ReceivedRedirect, OnReceivedRedirect)
+ IPC_MESSAGE_HANDLER(ViewMsg_Resource_DataReceived, OnReceivedData)
+ IPC_MESSAGE_HANDLER(ViewMsg_Resource_RequestComplete, OnRequestComplete)
+ IPC_END_MESSAGE_MAP()
+}
+
+void ResourceDispatcher::FlushDeferredMessages(int request_id) {
+ PendingRequestList::iterator it = pending_requests_.find(request_id);
+ if (it == pending_requests_.end()) // The request could have become invalid.
+ return;
+ PendingRequestInfo& request_info = it->second;
+ if (request_info.is_deferred)
+ return;
+ // Because message handlers could result in request_info being destroyed,
+ // we need to work with a stack reference to the deferred queue.
+ MessageQueue q;
+ q.swap(request_info.deferred_message_queue);
+ while (!q.empty()) {
+ IPC::Message* m = q.front();
+ q.pop_front();
+ DispatchMessage(*m);
+ delete m;
+ // If this request is deferred in the context of the above message, then
+ // we should honor the same and stop dispatching further messages.
+ // We need to find the request again in the list as it may have completed
+ // by now and the request_info instance above may be invalid.
+ PendingRequestList::iterator index = pending_requests_.find(request_id);
+ if (index != pending_requests_.end()) {
+ PendingRequestInfo& pending_request = index->second;
+ if (pending_request.is_deferred) {
+ pending_request.deferred_message_queue.swap(q);
+ return;
+ }
+ }
+ }
+}
+
+webkit_glue::ResourceLoaderBridge* ResourceDispatcher::CreateBridge(
+ const webkit_glue::ResourceLoaderBridge::RequestInfo& request_info,
+ int host_renderer_id,
+ int host_render_view_id) {
+ return new webkit_glue::IPCResourceLoaderBridge(this, request_info,
+ host_renderer_id,
+ host_render_view_id);
+}
+
+bool ResourceDispatcher::IsResourceDispatcherMessage(
+ const IPC::Message& message) {
+ switch (message.type()) {
+ case ViewMsg_Resource_UploadProgress::ID:
+ case ViewMsg_Resource_ReceivedResponse::ID:
+ case ViewMsg_Resource_ReceivedCachedMetadata::ID:
+ case ViewMsg_Resource_ReceivedRedirect::ID:
+ case ViewMsg_Resource_DataReceived::ID:
+ case ViewMsg_Resource_RequestComplete::ID:
+ return true;
+
+ default:
+ break;
+ }
+
+ return false;
+}
+
+// static
+void ResourceDispatcher::ReleaseResourcesInDataMessage(
+ const IPC::Message& message) {
+ void* iter = NULL;
+ int request_id;
+ if (!message.ReadInt(&iter, &request_id)) {
+ NOTREACHED() << "malformed resource message";
+ return;
+ }
+
+ // If the message contains a shared memory handle, we should close the
+ // handle or there will be a memory leak.
+ if (message.type() == ViewMsg_Resource_DataReceived::ID) {
+ base::SharedMemoryHandle shm_handle;
+ if (IPC::ParamTraits<base::SharedMemoryHandle>::Read(&message,
+ &iter,
+ &shm_handle)) {
+ base::SharedMemory::CloseHandle(shm_handle);
+ }
+ }
+}
+
+// static
+void ResourceDispatcher::ReleaseResourcesInMessageQueue(MessageQueue* queue) {
+ while (!queue->empty()) {
+ IPC::Message* message = queue->front();
+ ReleaseResourcesInDataMessage(*message);
+ queue->pop_front();
+ delete message;
+ }
+}
diff --git a/chrome/common/resource_dispatcher.h b/chrome/common/resource_dispatcher.h
new file mode 100644
index 0000000..c98b11a
--- /dev/null
+++ b/chrome/common/resource_dispatcher.h
@@ -0,0 +1,138 @@
+// Copyright (c) 2010 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.
+
+// See http://dev.chromium.org/developers/design-documents/multi-process-resource-loading
+
+#ifndef CHROME_COMMON_RESOURCE_DISPATCHER_H__
+#define CHROME_COMMON_RESOURCE_DISPATCHER_H__
+
+#include <deque>
+#include <string>
+
+#include "base/hash_tables.h"
+#include "base/shared_memory.h"
+#include "base/task.h"
+#include "ipc/ipc_channel.h"
+#include "webkit/glue/resource_loader_bridge.h"
+
+struct ResourceResponseHead;
+
+// This class serves as a communication interface between the
+// ResourceDispatcherHost in the browser process and the ResourceLoaderBridge in
+// the child process. It can be used from any child process.
+class ResourceDispatcher {
+ public:
+ explicit ResourceDispatcher(IPC::Message::Sender* sender);
+ ~ResourceDispatcher();
+
+ // Called to possibly handle the incoming IPC message. Returns true if
+ // handled, else false.
+ bool OnMessageReceived(const IPC::Message& message);
+
+ // Creates a ResourceLoaderBridge for this type of dispatcher, this is so
+ // this can be tested regardless of the ResourceLoaderBridge::Create
+ // implementation.
+ webkit_glue::ResourceLoaderBridge* CreateBridge(
+ const webkit_glue::ResourceLoaderBridge::RequestInfo& request_info,
+ int host_renderer_id,
+ int host_render_view_id);
+
+ // Adds a request from the pending_requests_ list, returning the new
+ // requests' ID
+ int AddPendingRequest(webkit_glue::ResourceLoaderBridge::Peer* callback,
+ ResourceType::Type resource_type,
+ const GURL& request_url);
+
+ // Removes a request from the pending_requests_ list, returning true if the
+ // request was found and removed.
+ bool RemovePendingRequest(int request_id);
+
+ // Cancels a request in the pending_requests_ list.
+ void CancelPendingRequest(int routing_id, int request_id);
+
+ IPC::Message::Sender* message_sender() const {
+ return message_sender_;
+ }
+
+ // Toggles the is_deferred attribute for the specified request.
+ void SetDefersLoading(int request_id, bool value);
+
+ private:
+ friend class ResourceDispatcherTest;
+
+ typedef std::deque<IPC::Message*> MessageQueue;
+ struct PendingRequestInfo {
+ PendingRequestInfo() { }
+ PendingRequestInfo(webkit_glue::ResourceLoaderBridge::Peer* peer,
+ ResourceType::Type resource_type,
+ const GURL& request_url)
+ : peer(peer),
+ resource_type(resource_type),
+ is_deferred(false),
+ url(request_url) {
+ }
+ ~PendingRequestInfo() { }
+ webkit_glue::ResourceLoaderBridge::Peer* peer;
+ ResourceType::Type resource_type;
+ MessageQueue deferred_message_queue;
+ bool is_deferred;
+ GURL url;
+ };
+ typedef base::hash_map<int, PendingRequestInfo> PendingRequestList;
+
+ // Message response handlers, called by the message handler for this process.
+ void OnUploadProgress(
+ const IPC::Message& message,
+ int request_id,
+ int64 position,
+ int64 size);
+ void OnReceivedResponse(int request_id, const ResourceResponseHead&);
+ void OnReceivedCachedMetadata(int request_id, const std::vector<char>& data);
+ void OnReceivedRedirect(
+ const IPC::Message& message,
+ int request_id,
+ const GURL& new_url,
+ const webkit_glue::ResourceLoaderBridge::ResponseInfo& info);
+ void OnReceivedData(
+ const IPC::Message& message,
+ int request_id,
+ base::SharedMemoryHandle data,
+ int data_len);
+ void OnRequestComplete(
+ int request_id,
+ const URLRequestStatus& status,
+ const std::string& security_info);
+
+ // Dispatch the message to one of the message response handlers.
+ void DispatchMessage(const IPC::Message& message);
+
+ // Dispatch any deferred messages for the given request, provided it is not
+ // again in the deferred state.
+ void FlushDeferredMessages(int request_id);
+
+ // Returns true if the message passed in is a resource related message.
+ static bool IsResourceDispatcherMessage(const IPC::Message& message);
+
+ // ViewHostMsg_Resource_DataReceived is not POD, it has a shared memory
+ // handle in it that we should cleanup it up nicely. This method accepts any
+ // message and determine whether the message is
+ // ViewHostMsg_Resource_DataReceived and clean up the shared memory handle.
+ static void ReleaseResourcesInDataMessage(const IPC::Message& message);
+
+ // Iterate through a message queue and clean up the messages by calling
+ // ReleaseResourcesInDataMessage and removing them from the queue. Intended
+ // for use on deferred message queues that are no longer needed.
+ static void ReleaseResourcesInMessageQueue(MessageQueue* queue);
+
+ IPC::Message::Sender* message_sender_;
+
+ // All pending requests issued to the host
+ PendingRequestList pending_requests_;
+
+ ScopedRunnableMethodFactory<ResourceDispatcher> method_factory_;
+
+ DISALLOW_COPY_AND_ASSIGN(ResourceDispatcher);
+};
+
+#endif // CHROME_COMMON_RESOURCE_DISPATCHER_H__
diff --git a/chrome/common/resource_dispatcher_dummy.cc b/chrome/common/resource_dispatcher_dummy.cc
new file mode 100644
index 0000000..f047b34
--- /dev/null
+++ b/chrome/common/resource_dispatcher_dummy.cc
@@ -0,0 +1,35 @@
+// Copyright (c) 2006-2008 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.
+
+// See http://dev.chromium.org/developers/design-documents/multi-process-resource-loading
+
+#include "chrome/common/resource_dispatcher.h"
+
+#include "base/compiler_specific.h"
+
+// ResourceDispatcher ---------------------------------------------------------
+
+ResourceDispatcher::ResourceDispatcher(IPC::Message::Sender* sender)
+ : message_sender_(sender),
+ ALLOW_THIS_IN_INITIALIZER_LIST(method_factory_(this)) {
+}
+
+ResourceDispatcher::~ResourceDispatcher() {
+}
+
+// ResourceDispatcher implementation ------------------------------------------
+
+bool ResourceDispatcher::OnMessageReceived(const IPC::Message& message) {
+ return false;
+}
+
+webkit_glue::ResourceLoaderBridge* ResourceDispatcher::CreateBridge(
+ const webkit_glue::ResourceLoaderBridge::RequestInfo& request_info,
+ int host_renderer_id,
+ int host_render_view_id) {
+ // This function is used only by plugin and renderer code, so it should
+ // never be called in a 64-bit Windows process.
+ NOTREACHED();
+ return NULL;
+}
diff --git a/chrome/common/resource_dispatcher_unittest.cc b/chrome/common/resource_dispatcher_unittest.cc
new file mode 100644
index 0000000..323a6e4
--- /dev/null
+++ b/chrome/common/resource_dispatcher_unittest.cc
@@ -0,0 +1,325 @@
+// Copyright (c) 2010 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 <string>
+#include <vector>
+
+#include "base/message_loop.h"
+#include "base/process.h"
+#include "base/process_util.h"
+#include "base/scoped_ptr.h"
+#include "chrome/common/render_messages.h"
+#include "chrome/common/resource_dispatcher.h"
+#include "testing/gtest/include/gtest/gtest.h"
+#include "webkit/appcache/appcache_interfaces.h"
+
+using webkit_glue::ResourceLoaderBridge;
+
+static const char test_page_url[] = "http://www.google.com/";
+static const char test_page_headers[] =
+ "HTTP/1.1 200 OK\nContent-Type:text/html\n\n";
+static const char test_page_mime_type[] = "text/html";
+static const char test_page_charset[] = "";
+static const char test_page_contents[] =
+ "<html><head><title>Google</title></head><body><h1>Google</h1></body></html>";
+static const uint32 test_page_contents_len = arraysize(test_page_contents) - 1;
+
+// Listens for request response data and stores it so that it can be compared
+// to the reference data.
+class TestRequestCallback : public ResourceLoaderBridge::Peer {
+ public:
+ TestRequestCallback() : complete_(false) {
+ }
+
+ virtual bool OnReceivedRedirect(
+ const GURL& new_url,
+ const ResourceLoaderBridge::ResponseInfo& info,
+ bool* has_new_first_party_for_cookies,
+ GURL* new_first_party_for_cookies) {
+ *has_new_first_party_for_cookies = false;
+ return true;
+ }
+
+ virtual void OnReceivedResponse(
+ const ResourceLoaderBridge::ResponseInfo& info,
+ bool content_filtered) {
+ }
+
+ virtual void OnReceivedData(const char* data, int len) {
+ EXPECT_FALSE(complete_);
+ data_.append(data, len);
+ }
+
+ virtual void OnUploadProgress(uint64 position, uint64 size) {
+ }
+
+ virtual void OnCompletedRequest(const URLRequestStatus& status,
+ const std::string& security_info) {
+ EXPECT_FALSE(complete_);
+ complete_ = true;
+ }
+
+ virtual GURL GetURLForDebugging() const {
+ return GURL();
+ }
+
+ const std::string& data() const {
+ return data_;
+ }
+ bool complete() const {
+ return complete_;
+ }
+
+ private:
+ bool complete_;
+ std::string data_;
+};
+
+
+// Sets up the message sender override for the unit test
+class ResourceDispatcherTest : public testing::Test,
+ public IPC::Message::Sender {
+ public:
+ // Emulates IPC send operations (IPC::Message::Sender) by adding
+ // pending messages to the queue.
+ virtual bool Send(IPC::Message* msg) {
+ message_queue_.push_back(IPC::Message(*msg));
+ delete msg;
+ return true;
+ }
+
+ // Emulates the browser process and processes the pending IPC messages,
+ // returning the hardcoded file contents.
+ void ProcessMessages() {
+ while (!message_queue_.empty()) {
+ int request_id;
+ ViewHostMsg_Resource_Request request;
+ ASSERT_TRUE(ViewHostMsg_RequestResource::Read(
+ &message_queue_[0], &request_id, &request));
+
+ // check values
+ EXPECT_EQ(test_page_url, request.url.spec());
+
+ // received response message
+ ResourceResponseHead response;
+ std::string raw_headers(test_page_headers);
+ std::replace(raw_headers.begin(), raw_headers.end(), '\n', '\0');
+ response.headers = new net::HttpResponseHeaders(raw_headers);
+ response.mime_type = test_page_mime_type;
+ response.charset = test_page_charset;
+ dispatcher_->OnReceivedResponse(request_id, response);
+
+ // received data message with the test contents
+ base::SharedMemory shared_mem;
+ EXPECT_TRUE(shared_mem.Create(std::wstring(),
+ false, false, test_page_contents_len));
+ EXPECT_TRUE(shared_mem.Map(test_page_contents_len));
+ char* put_data_here = static_cast<char*>(shared_mem.memory());
+ memcpy(put_data_here, test_page_contents, test_page_contents_len);
+ base::SharedMemoryHandle dup_handle;
+ EXPECT_TRUE(shared_mem.GiveToProcess(
+ base::Process::Current().handle(), &dup_handle));
+ dispatcher_->OnReceivedData(
+ message_queue_[0], request_id, dup_handle, test_page_contents_len);
+
+ message_queue_.erase(message_queue_.begin());
+
+ // read the ack message.
+ Tuple1<int> request_ack;
+ ASSERT_TRUE(ViewHostMsg_DataReceived_ACK::Read(
+ &message_queue_[0], &request_ack));
+
+ ASSERT_EQ(request_ack.a, request_id);
+
+ message_queue_.erase(message_queue_.begin());
+ }
+ }
+
+ protected:
+ // testing::Test
+ virtual void SetUp() {
+ dispatcher_.reset(new ResourceDispatcher(this));
+ }
+ virtual void TearDown() {
+ dispatcher_.reset();
+ }
+
+ ResourceLoaderBridge* CreateBridge() {
+ webkit_glue::ResourceLoaderBridge::RequestInfo request_info;
+ request_info.method = "GET";
+ request_info.url = GURL(test_page_url);
+ request_info.first_party_for_cookies = GURL(test_page_url);
+ request_info.referrer = GURL();
+ request_info.frame_origin = "null";
+ request_info.main_frame_origin = "null";
+ request_info.headers = std::string();
+ request_info.load_flags = 0;
+ request_info.requestor_pid = 0;
+ request_info.request_type = ResourceType::SUB_RESOURCE;
+ request_info.appcache_host_id = appcache::kNoHostId;
+ request_info.routing_id = 0;
+
+ return dispatcher_->CreateBridge(request_info, -1, -1);
+ }
+
+ std::vector<IPC::Message> message_queue_;
+ static scoped_ptr<ResourceDispatcher> dispatcher_;
+};
+
+/*static*/
+scoped_ptr<ResourceDispatcher> ResourceDispatcherTest::dispatcher_;
+
+// Does a simple request and tests that the correct data is received.
+TEST_F(ResourceDispatcherTest, RoundTrip) {
+ TestRequestCallback callback;
+ ResourceLoaderBridge* bridge = CreateBridge();
+
+ bridge->Start(&callback);
+
+ ProcessMessages();
+
+ // FIXME(brettw) when the request complete messages are actually handledo
+ // and dispatched, uncomment this.
+ //EXPECT_TRUE(callback.complete());
+ //EXPECT_STREQ(test_page_contents, callback.data().c_str());
+
+ delete bridge;
+}
+
+// Tests that the request IDs are straight when there are multiple requests.
+TEST_F(ResourceDispatcherTest, MultipleRequests) {
+ // FIXME
+}
+
+// Tests that the cancel method prevents other messages from being received
+TEST_F(ResourceDispatcherTest, Cancel) {
+ // FIXME
+}
+
+TEST_F(ResourceDispatcherTest, Cookies) {
+ // FIXME
+}
+
+TEST_F(ResourceDispatcherTest, SerializedPostData) {
+ // FIXME
+}
+
+// This class provides functionality to validate whether the ResourceDispatcher
+// object honors the deferred loading contract correctly, i.e. if deferred
+// loading is enabled it should queue up any responses received. If deferred
+// loading is enabled/disabled in the context of a dispatched message, other
+// queued messages should not be dispatched until deferred load is turned off.
+class DeferredResourceLoadingTest : public ResourceDispatcherTest,
+ public ResourceLoaderBridge::Peer {
+ public:
+ DeferredResourceLoadingTest()
+ : defer_loading_(false) {
+ }
+
+ virtual bool Send(IPC::Message* msg) {
+ delete msg;
+ return true;
+ }
+
+ void InitMessages() {
+ set_defer_loading(true);
+
+ ResourceResponseHead response_head;
+ response_head.status.set_status(URLRequestStatus::SUCCESS);
+
+ IPC::Message* response_message =
+ new ViewMsg_Resource_ReceivedResponse(0, 0, response_head);
+
+ dispatcher_->OnMessageReceived(*response_message);
+
+ delete response_message;
+
+ // Duplicate the shared memory handle so both the test and the callee can
+ // close their copy.
+ base::SharedMemoryHandle duplicated_handle;
+ EXPECT_TRUE(shared_handle_.ShareToProcess(base::GetCurrentProcessHandle(),
+ &duplicated_handle));
+
+ response_message =
+ new ViewMsg_Resource_DataReceived(0, 0, duplicated_handle, 100);
+
+ dispatcher_->OnMessageReceived(*response_message);
+
+ delete response_message;
+
+ set_defer_loading(false);
+ }
+
+ // ResourceLoaderBridge::Peer methods.
+ virtual void OnReceivedResponse(
+ const ResourceLoaderBridge::ResponseInfo& info,
+ bool content_filtered) {
+ EXPECT_EQ(defer_loading_, false);
+ set_defer_loading(true);
+ }
+
+ virtual bool OnReceivedRedirect(
+ const GURL& new_url,
+ const ResourceLoaderBridge::ResponseInfo& info,
+ bool* has_new_first_party_for_cookies,
+ GURL* new_first_party_for_cookies) {
+ *has_new_first_party_for_cookies = false;
+ return true;
+ }
+
+ virtual void OnReceivedData(const char* data, int len) {
+ EXPECT_EQ(defer_loading_, false);
+ set_defer_loading(false);
+ }
+
+ virtual void OnUploadProgress(uint64 position, uint64 size) {
+ }
+
+ virtual void OnCompletedRequest(const URLRequestStatus& status,
+ const std::string& security_info) {
+ }
+
+ virtual GURL GetURLForDebugging() const {
+ return GURL();
+ }
+
+ protected:
+ virtual void SetUp() {
+ EXPECT_EQ(true, shared_handle_.Create(L"DeferredResourceLoaderTest", false,
+ false, 100));
+ ResourceDispatcherTest::SetUp();
+ }
+
+ virtual void TearDown() {
+ shared_handle_.Close();
+ ResourceDispatcherTest::TearDown();
+ }
+
+ private:
+ void set_defer_loading(bool defer) {
+ defer_loading_ = defer;
+ dispatcher_->SetDefersLoading(0, defer);
+ }
+
+ bool defer_loading() const {
+ return defer_loading_;
+ }
+
+ bool defer_loading_;
+ base::SharedMemory shared_handle_;
+};
+
+TEST_F(DeferredResourceLoadingTest, DeferredLoadTest) {
+ MessageLoop message_loop(MessageLoop::TYPE_IO);
+
+ ResourceLoaderBridge* bridge = CreateBridge();
+
+ bridge->Start(this);
+ InitMessages();
+
+ // Dispatch deferred messages.
+ message_loop.RunAllPending();
+ delete bridge;
+}
+
diff --git a/chrome/common/resource_response.h b/chrome/common/resource_response.h
new file mode 100644
index 0000000..1c9b766
--- /dev/null
+++ b/chrome/common/resource_response.h
@@ -0,0 +1,50 @@
+// Copyright (c) 2010 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.
+
+// See http://dev.chromium.org/developers/design-documents/multi-process-resource-loading
+
+#ifndef CHROME_COMMON_RESOURCE_RESPONSE_H_
+#define CHROME_COMMON_RESOURCE_RESPONSE_H_
+
+#include <string>
+
+#include "base/ref_counted.h"
+#include "googleurl/src/gurl.h"
+#include "net/url_request/url_request_status.h"
+#include "webkit/glue/resource_loader_bridge.h"
+
+// Parameters for a resource response header.
+struct ResourceResponseHead
+ : webkit_glue::ResourceLoaderBridge::ResponseInfo {
+ ResourceResponseHead() : replace_extension_localization_templates(false) {}
+
+ // The response status.
+ URLRequestStatus status;
+
+ // Whether we should apply a filter to this resource that replaces
+ // localization templates with the appropriate localized strings. This is set
+ // for CSS resources used by extensions.
+ bool replace_extension_localization_templates;
+};
+
+// Parameters for a synchronous resource response.
+struct SyncLoadResult : ResourceResponseHead {
+ // The final URL after any redirects.
+ GURL final_url;
+
+ // The response data.
+ std::string data;
+};
+
+// Simple wrapper that refcounts ResourceResponseHead.
+struct ResourceResponse : public base::RefCounted<ResourceResponse> {
+ ResourceResponseHead response_head;
+
+ private:
+ friend class base::RefCounted<ResourceResponse>;
+
+ ~ResourceResponse() {}
+};
+
+#endif // CHROME_COMMON_RESOURCE_RESPONSE_H_
diff --git a/chrome/common/result_codes.h b/chrome/common/result_codes.h
new file mode 100644
index 0000000..6ca19b8
--- /dev/null
+++ b/chrome/common/result_codes.h
@@ -0,0 +1,63 @@
+// Copyright (c) 2010 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_COMMON_RESULT_CODES_H_
+#define CHROME_COMMON_RESULT_CODES_H_
+
+#include "base/process_util.h"
+
+// This file consolidates all the return codes for the browser and renderer
+// process. The return code is the value that:
+// a) is returned by main() or winmain(), or
+// b) specified in the call for ExitProcess() or TerminateProcess(), or
+// c) the exception value that causes a process to terminate.
+//
+// It is advisable to not use negative numbers because the Windows API returns
+// it as an unsigned long and the exception values have high numbers. For
+// example EXCEPTION_ACCESS_VIOLATION value is 0xC0000005.
+
+class ResultCodes {
+ public:
+ enum ExitCode {
+ NORMAL_EXIT = base::PROCESS_END_NORMAL_TERMINATION,
+ TASKMAN_KILL = base::PROCESS_END_KILLED_BY_USER,
+ HUNG = base::PROCESS_END_PROCESS_WAS_HUNG,
+ INVALID_CMDLINE_URL, // An invalid command line url was given.
+ SBOX_INIT_FAILED, // The sandbox could not be initialized.
+ GOOGLE_UPDATE_INIT_FAILED, // The Google Update client stub init failed.
+ GOOGLE_UPDATE_LAUNCH_FAILED,// Google Update could not launch chrome DLL.
+ BAD_PROCESS_TYPE, // The process is of an unknown type.
+ MISSING_PATH, // An critical chrome path is missing.
+ MISSING_DATA, // A critical chrome file is missing.
+ SHELL_INTEGRATION_FAILED, // Failed to make Chrome default browser.
+ MACHINE_LEVEL_INSTALL_EXISTS, // Machine level install exists
+ UNINSTALL_DELETE_FILE_ERROR,// Error while deleting shortcuts.
+ UNINSTALL_CHROME_ALIVE, // Uninstall detected another chrome instance.
+ UNINSTALL_NO_SURVEY, // Do not launch survey after uninstall.
+ UNINSTALL_USER_CANCEL, // The user changed her mind.
+ UNINSTALL_DELETE_PROFILE, // Delete profile as well during uninstall.
+ UNSUPPORTED_PARAM, // Command line parameter is not supported.
+ KILLED_BAD_MESSAGE, // A bad message caused the process termination.
+ IMPORTER_CANCEL, // The user canceled the browser import.
+ IMPORTER_HUNG, // Browser import hung and was killed.
+ RESPAWN_FAILED, // Trying to restart the browser we crashed.
+
+ NORMAL_EXIT_EXP1, // The EXP1, EXP2, EXP3, EXP4 are generic codes
+ NORMAL_EXIT_EXP2, // used to communicate some simple outcome back
+ NORMAL_EXIT_EXP3, // to the process that launched us. This is
+ NORMAL_EXIT_EXP4, // used for experiments and the actual meaning
+ // depends on the experiment.
+
+ NORMAL_EXIT_CANCEL, // For experiments this return code means that
+ // the user canceled causes the did_run "dr"
+ // signal to be reset so this chrome run does
+ // not count as active chrome usage.
+
+ PROFILE_IN_USE, // The profile was in use on another host.
+
+ EXIT_LAST_CODE // Last return code (keep it last).
+ };
+};
+
+#endif // CHROME_COMMON_RESULT_CODES_H_
diff --git a/chrome/common/sandbox_init_wrapper.h b/chrome/common/sandbox_init_wrapper.h
new file mode 100644
index 0000000..d1652d2
--- /dev/null
+++ b/chrome/common/sandbox_init_wrapper.h
@@ -0,0 +1,68 @@
+// Copyright (c) 2009 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_COMMON_SANDBOX_INIT_WRAPPER_H_
+#define CHROME_COMMON_SANDBOX_INIT_WRAPPER_H_
+
+// Wraps the sandbox initialization and platform variables to consolodate
+// the code and reduce the number of platform ifdefs elsewhere. The POSIX
+// version of this wrapper is basically empty.
+
+#include "build/build_config.h"
+
+#include <string>
+
+#include "base/basictypes.h"
+#if defined(OS_WIN)
+#include "sandbox/src/sandbox.h"
+#endif
+
+class CommandLine;
+
+#if defined(OS_WIN)
+
+class SandboxInitWrapper {
+ public:
+ SandboxInitWrapper() : broker_services_(), target_services_() { }
+ // SetServices() needs to be called before InitializeSandbox() on Win32 with
+ // the info received from the chrome exe main.
+ void SetServices(sandbox::SandboxInterfaceInfo* sandbox_info);
+ sandbox::BrokerServices* BrokerServices() const { return broker_services_; }
+ sandbox::TargetServices* TargetServices() const { return target_services_; }
+
+ // Initialize the sandbox for renderer and plug-in processes, depending on
+ // the command line flags. The browser process is not sandboxed.
+ // Returns true if the sandbox was initialized succesfully, false if an error
+ // occurred. If process_type isn't one that needs sandboxing true is always
+ // returned.
+ bool InitializeSandbox(const CommandLine& parsed_command_line,
+ const std::string& process_type);
+ private:
+ sandbox::BrokerServices* broker_services_;
+ sandbox::TargetServices* target_services_;
+
+ DISALLOW_COPY_AND_ASSIGN(SandboxInitWrapper);
+};
+
+#elif defined(OS_POSIX)
+
+class SandboxInitWrapper {
+ public:
+ SandboxInitWrapper() { }
+
+ // Initialize the sandbox for renderer and plug-in processes, depending on
+ // the command line flags. The browser process is not sandboxed.
+ // Returns true if the sandbox was initialized succesfully, false if an error
+ // occurred. If process_type isn't one that needs sandboxing true is always
+ // returned.
+ bool InitializeSandbox(const CommandLine& parsed_command_line,
+ const std::string& process_type);
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(SandboxInitWrapper);
+};
+
+#endif
+
+#endif // CHROME_COMMON_SANDBOX_INIT_WRAPPER_H_
diff --git a/chrome/common/sandbox_init_wrapper_linux.cc b/chrome/common/sandbox_init_wrapper_linux.cc
new file mode 100644
index 0000000..daf02d3
--- /dev/null
+++ b/chrome/common/sandbox_init_wrapper_linux.cc
@@ -0,0 +1,14 @@
+// Copyright (c) 2009 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/common/sandbox_init_wrapper.h"
+
+#include "base/command_line.h"
+#include "chrome/common/chrome_switches.h"
+
+bool SandboxInitWrapper::InitializeSandbox(const CommandLine& command_line,
+ const std::string& process_type) {
+ // TODO(port): Does Linux need to do anything here?
+ return true;
+}
diff --git a/chrome/common/sandbox_init_wrapper_mac.cc b/chrome/common/sandbox_init_wrapper_mac.cc
new file mode 100644
index 0000000..998fe64
--- /dev/null
+++ b/chrome/common/sandbox_init_wrapper_mac.cc
@@ -0,0 +1,77 @@
+// Copyright (c) 2009 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/common/sandbox_init_wrapper.h"
+
+#include "base/command_line.h"
+#include "chrome/common/chrome_switches.h"
+#include "chrome/common/sandbox_mac.h"
+
+bool SandboxInitWrapper::InitializeSandbox(const CommandLine& command_line,
+ const std::string& process_type) {
+ if (command_line.HasSwitch(switches::kNoSandbox))
+ return true;
+
+ sandbox::SandboxProcessType sandbox_process_type;
+ FilePath allowed_dir; // Empty by default.
+
+ if (process_type.empty()) {
+ // Browser process isn't sandboxed.
+ return true;
+ } else if (process_type == switches::kRendererProcess) {
+ if (command_line.HasSwitch(switches::kEnableExperimentalWebGL) &&
+ command_line.HasSwitch(switches::kInProcessWebGL)) {
+ // TODO(kbr): this check seems to be necessary only on this
+ // platform because the sandbox is initialized later. Remove
+ // this once this flag is removed.
+ return true;
+ } else if (command_line.HasSwitch(switches::kInternalNaCl)) {
+ // Renderer process sandbox. If --internal_nacl is present then use the
+ // version of the renderer sandbox which allows Native Client to use Unix
+ // sockets.
+ // TODO(msneck): Remove the use of Unix sockets from Native Client and
+ // then get rid of the SANDBOX_TYPE_NACL_PLUGIN enum.
+ // See http://code.google.com/p/nativeclient/issues/detail?id=344
+ sandbox_process_type = sandbox::SANDBOX_TYPE_NACL_PLUGIN;
+ } else {
+ sandbox_process_type = sandbox::SANDBOX_TYPE_RENDERER;
+ }
+ } else if (process_type == switches::kExtensionProcess) {
+ // Extension processes are just renderers [they use RenderMain()] with a
+ // different set of command line flags.
+ // If we ever get here it means something has changed in regards
+ // to the extension process mechanics and we should probably reexamine
+ // how we sandbox extension processes since they are no longer identical
+ // to renderers.
+ NOTREACHED();
+ return true;
+ } else if (process_type == switches::kUtilityProcess) {
+ // Utility process sandbox.
+ sandbox_process_type = sandbox::SANDBOX_TYPE_UTILITY;
+ allowed_dir = FilePath::FromWStringHack(
+ command_line.GetSwitchValue(switches::kUtilityProcessAllowedDir));
+ } else if (process_type == switches::kWorkerProcess) {
+ // Worker process sandbox.
+ sandbox_process_type = sandbox::SANDBOX_TYPE_WORKER;
+ } else if (process_type == switches::kNaClLoaderProcess) {
+ // Native Client sel_ldr (user untrusted code) sandbox.
+ sandbox_process_type = sandbox::SANDBOX_TYPE_NACL_LOADER;
+ } else if ((process_type == switches::kPluginProcess) ||
+ (process_type == switches::kProfileImportProcess) ||
+ (process_type == switches::kGpuProcess) ||
+ (process_type == switches::kServiceProcess)) {
+ return true;
+ } else {
+ // Failsafe: If you hit an unreached here, is your new process type in need
+ // of sandboxing?
+ NOTREACHED();
+ return true;
+ }
+
+ // Warm up APIs before turning on the sandbox.
+ sandbox::SandboxWarmup();
+
+ // Actually sandbox the process.
+ return sandbox::EnableSandbox(sandbox_process_type, allowed_dir);
+}
diff --git a/chrome/common/sandbox_init_wrapper_win.cc b/chrome/common/sandbox_init_wrapper_win.cc
new file mode 100644
index 0000000..5d4399a
--- /dev/null
+++ b/chrome/common/sandbox_init_wrapper_win.cc
@@ -0,0 +1,33 @@
+// Copyright (c) 2009 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/common/sandbox_init_wrapper.h"
+
+#include "base/command_line.h"
+#include "chrome/common/chrome_switches.h"
+
+void SandboxInitWrapper::SetServices(sandbox::SandboxInterfaceInfo* info) {
+ if (info) {
+ broker_services_ = info->broker_services;
+ target_services_ = info->target_services;
+ }
+}
+
+bool SandboxInitWrapper::InitializeSandbox(const CommandLine& command_line,
+ const std::string& process_type) {
+ if (command_line.HasSwitch(switches::kNoSandbox))
+ return true;
+ if ((process_type == switches::kRendererProcess) ||
+ (process_type == switches::kExtensionProcess) ||
+ (process_type == switches::kWorkerProcess) ||
+ (process_type == switches::kNaClLoaderProcess) ||
+ (process_type == switches::kUtilityProcess) ||
+ (process_type == switches::kPluginProcess &&
+ command_line.HasSwitch(switches::kSafePlugins))) {
+ if (!target_services_)
+ return false;
+ target_services_->Init();
+ }
+ return true;
+}
diff --git a/chrome/common/sandbox_mac.h b/chrome/common/sandbox_mac.h
new file mode 100644
index 0000000..249eaa3
--- /dev/null
+++ b/chrome/common/sandbox_mac.h
@@ -0,0 +1,60 @@
+// Copyright (c) 2009 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_COMMON_SANDBOX_MAC_H_
+#define CHROME_COMMON_SANDBOX_MAC_H_
+
+#include "base/file_path.h"
+
+namespace sandbox {
+
+enum SandboxProcessType {
+
+ SANDBOX_TYPE_FIRST_TYPE, // Placeholder to ease iteration.
+
+ SANDBOX_TYPE_RENDERER = SANDBOX_TYPE_FIRST_TYPE,
+
+ // The worker processes uses the most restrictive sandbox which has almost
+ // *everything* locked down. Only a couple of /System/Library/ paths and
+ // some other very basic operations (e.g., reading metadata to allow
+ // following symlinks) are permitted.
+ SANDBOX_TYPE_WORKER,
+
+ // Utility process is as restrictive as the worker process except full access
+ // is allowed to one configurable directory.
+ SANDBOX_TYPE_UTILITY,
+
+ // Native Client sandboxes. The plugin contains trusted code and the
+ // loader contains the user's untrusted code.
+ SANDBOX_TYPE_NACL_PLUGIN,
+ SANDBOX_TYPE_NACL_LOADER,
+
+ SANDBOX_AFTER_TYPE_LAST_TYPE, // Placeholder to ease iteration.
+};
+
+// Warm up System APIs that empirically need to be accessed before the Sandbox
+// is turned on.
+void SandboxWarmup();
+
+// Turns on the OS X sandbox for this process.
+// |sandbox_type| - type of Sandbox to use.
+// |allowed_dir| - directory to allow access to, currently the only sandbox
+// profile that supports this is SANDBOX_TYPE_UTILITY .
+//
+// |allowed_dir| must be a "simple" string since it's placed as is in a regex
+// i.e. it must not contain quotation characters, escaping or any characters
+// that might have special meaning when blindly substituted into a regular
+// expression - crbug.com/26492 .
+// Returns true on success, false if an error occurred enabling the sandbox.
+bool EnableSandbox(SandboxProcessType sandbox_type,
+ const FilePath& allowed_dir);
+
+// Convert provided path into a "canonical" path matching what the Sandbox
+// expects i.e. one without symlinks.
+// This path is not necessarily unique e.g. in the face of hardlinks.
+void GetCanonicalSandboxPath(FilePath* path);
+
+} // namespace sandbox
+
+#endif // CHROME_COMMON_SANDBOX_MAC_H_
diff --git a/chrome/common/sandbox_mac.mm b/chrome/common/sandbox_mac.mm
new file mode 100644
index 0000000..3d2985c
--- /dev/null
+++ b/chrome/common/sandbox_mac.mm
@@ -0,0 +1,434 @@
+// Copyright (c) 2009 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/common/sandbox_mac.h"
+
+#include "base/debug_util.h"
+
+#import <Cocoa/Cocoa.h>
+extern "C" {
+#include <sandbox.h>
+}
+#include <sys/param.h>
+
+#include "base/basictypes.h"
+#include "base/command_line.h"
+#include "base/file_util.h"
+#include "base/mac_util.h"
+#include "base/rand_util_c.h"
+#include "base/scoped_cftyperef.h"
+#include "base/scoped_nsautorelease_pool.h"
+#include "base/string16.h"
+#include "base/sys_info.h"
+#include "base/sys_string_conversions.h"
+#include "base/utf_string_conversions.h"
+#include "chrome/common/chrome_switches.h"
+#include "unicode/uchar.h"
+
+namespace {
+
+// Try to escape |c| as a "SingleEscapeCharacter" (\n, etc). If successful,
+// returns true and appends the escape sequence to |dst|.
+bool EscapeSingleChar(char c, std::string* dst) {
+ const char *append = NULL;
+ switch (c) {
+ case '\b':
+ append = "\\b";
+ break;
+ case '\f':
+ append = "\\f";
+ break;
+ case '\n':
+ append = "\\n";
+ break;
+ case '\r':
+ append = "\\r";
+ break;
+ case '\t':
+ append = "\\t";
+ break;
+ case '\\':
+ append = "\\\\";
+ break;
+ case '"':
+ append = "\\\"";
+ break;
+ }
+
+ if (!append) {
+ return false;
+ }
+
+ dst->append(append);
+ return true;
+}
+
+} // namespace
+
+namespace sandbox {
+
+// Escape |str_utf8| for use in a plain string variable in a sandbox
+// configuraton file. On return |dst| is set to the utf-8 encoded quoted
+// output.
+// Returns: true on success, false otherwise.
+bool QuotePlainString(const std::string& str_utf8, std::string* dst) {
+ dst->clear();
+
+ const char* src = str_utf8.c_str();
+ int32_t length = str_utf8.length();
+ int32_t position = 0;
+ while (position < length) {
+ UChar32 c;
+ U8_NEXT(src, position, length, c); // Macro increments |position|.
+ DCHECK_GE(c, 0);
+ if (c < 0)
+ return false;
+
+ if (c < 128) { // EscapeSingleChar only handles ASCII.
+ char as_char = static_cast<char>(c);
+ if (EscapeSingleChar(as_char, dst)) {
+ continue;
+ }
+ }
+
+ if (c < 32 || c > 126) {
+ // Any characters that aren't printable ASCII get the \u treatment.
+ unsigned int as_uint = static_cast<unsigned int>(c);
+ StringAppendF(dst, "\\u%04X", as_uint);
+ continue;
+ }
+
+ // If we got here we know that the character in question is strictly
+ // in the ASCII range so there's no need to do any kind of encoding
+ // conversion.
+ dst->push_back(static_cast<char>(c));
+ }
+ return true;
+}
+
+// Escape |str_utf8| for use in a regex literal in a sandbox
+// configuraton file. On return |dst| is set to the utf-8 encoded quoted
+// output.
+//
+// The implementation of this function is based on empirical testing of the
+// OS X sandbox on 10.5.8 & 10.6.2 which is undocumented and subject to change.
+//
+// Note: If str_utf8 contains any characters < 32 || >125 then the function
+// fails and false is returned.
+//
+// Returns: true on success, false otherwise.
+bool QuoteStringForRegex(const std::string& str_utf8, std::string* dst) {
+ // Characters with special meanings in sandbox profile syntax.
+ const char regex_special_chars[] = {
+ '\\',
+
+ // Metacharacters
+ '^',
+ '.',
+ '[',
+ ']',
+ '$',
+ '(',
+ ')',
+ '|',
+
+ // Quantifiers
+ '*',
+ '+',
+ '?',
+ '{',
+ '}',
+ };
+
+ // Anchor regex at start of path.
+ dst->assign("^");
+
+ const char* src = str_utf8.c_str();
+ int32_t length = str_utf8.length();
+ int32_t position = 0;
+ while (position < length) {
+ UChar32 c;
+ U8_NEXT(src, position, length, c); // Macro increments |position|.
+ DCHECK_GE(c, 0);
+ if (c < 0)
+ return false;
+
+ // The Mac sandbox regex parser only handles printable ASCII characters.
+ // 33 >= c <= 126
+ if (c < 32 || c > 125) {
+ return false;
+ }
+
+ for (size_t i = 0; i < arraysize(regex_special_chars); ++i) {
+ if (c == regex_special_chars[i]) {
+ dst->push_back('\\');
+ break;
+ }
+ }
+
+ dst->push_back(static_cast<char>(c));
+ }
+
+ // Make sure last element of path is interpreted as a directory. Leaving this
+ // off would allow access to files if they start with the same name as the
+ // directory.
+ dst->append("(/|$)");
+
+ return true;
+}
+
+// Warm up System APIs that empirically need to be accessed before the Sandbox
+// is turned on.
+// This method is layed out in blocks, each one containing a separate function
+// that needs to be warmed up. The OS version on which we found the need to
+// enable the function is also noted.
+// This function is tested on the following OS versions:
+// 10.5.6, 10.6.0
+void SandboxWarmup() {
+ base::ScopedNSAutoreleasePool scoped_pool;
+
+ { // CGColorSpaceCreateWithName(), CGBitmapContextCreate() - 10.5.6
+ scoped_cftyperef<CGColorSpaceRef> rgb_colorspace(
+ CGColorSpaceCreateWithName(kCGColorSpaceGenericRGB));
+
+ // Allocate a 1x1 image.
+ char data[4];
+ scoped_cftyperef<CGContextRef> context(
+ CGBitmapContextCreate(data, 1, 1, 8, 1 * 4,
+ rgb_colorspace,
+ kCGImageAlphaPremultipliedFirst |
+ kCGBitmapByteOrder32Host));
+
+ // Load in the color profiles we'll need (as a side effect).
+ (void) mac_util::GetSRGBColorSpace();
+ (void) mac_util::GetSystemColorSpace();
+
+ // CGColorSpaceCreateSystemDefaultCMYK - 10.6
+ scoped_cftyperef<CGColorSpaceRef> cmyk_colorspace(
+ CGColorSpaceCreateWithName(kCGColorSpaceGenericCMYK));
+ }
+
+ { // [-NSColor colorUsingColorSpaceName] - 10.5.6
+ NSColor* color = [NSColor controlTextColor];
+ [color colorUsingColorSpaceName:NSCalibratedRGBColorSpace];
+ }
+
+ { // localtime() - 10.5.6
+ time_t tv = {0};
+ localtime(&tv);
+ }
+
+ { // Gestalt() tries to read /System/Library/CoreServices/SystemVersion.plist
+ // on 10.5.6
+ int32 tmp;
+ base::SysInfo::OperatingSystemVersionNumbers(&tmp, &tmp, &tmp);
+ }
+
+ { // CGImageSourceGetStatus() - 10.6
+ // Create a png with just enough data to get everything warmed up...
+ char png_header[] = {0x89, 0x50, 0x4E, 0x47, 0x0D, 0x0A, 0x1A, 0x0A};
+ NSData* data = [NSData dataWithBytes:png_header
+ length:arraysize(png_header)];
+ scoped_cftyperef<CGImageSourceRef> img(
+ CGImageSourceCreateWithData((CFDataRef)data,
+ NULL));
+ CGImageSourceGetStatus(img);
+ }
+
+ { // Native Client access to /dev/random.
+ GetUrandomFD();
+ }
+}
+
+// Turns on the OS X sandbox for this process.
+bool EnableSandbox(SandboxProcessType sandbox_type,
+ const FilePath& allowed_dir) {
+ // Sanity - currently only SANDBOX_TYPE_UTILITY supports a directory being
+ // passed in.
+ if (sandbox_type != SANDBOX_TYPE_UTILITY) {
+ DCHECK(allowed_dir.empty())
+ << "Only SANDBOX_TYPE_UTILITY allows a custom directory parameter.";
+ }
+ // We use a custom sandbox definition file to lock things down as
+ // tightly as possible.
+ // TODO(jeremy): Look at using include syntax to unify common parts of sandbox
+ // definition files.
+ NSString* sandbox_config_filename = nil;
+ bool allow_nacl_lines = false;
+ switch (sandbox_type) {
+ case SANDBOX_TYPE_RENDERER:
+ sandbox_config_filename = @"renderer";
+ break;
+ case SANDBOX_TYPE_WORKER:
+ sandbox_config_filename = @"worker";
+ break;
+ case SANDBOX_TYPE_UTILITY:
+ sandbox_config_filename = @"utility";
+ break;
+ case SANDBOX_TYPE_NACL_PLUGIN:
+ // The Native Client plugin is a standard renderer sandbox with some
+ // additional lines to support use of Unix sockets.
+ // TODO(msneck): Remove the use of Unix sockets from Native Client and
+ // then remove the associated rules from chrome/renderer/renderer.sb.
+ // See http://code.google.com/p/nativeclient/issues/detail?id=344
+ sandbox_config_filename = @"renderer";
+ allow_nacl_lines = true;
+ break;
+ case SANDBOX_TYPE_NACL_LOADER:
+ // The Native Client loader is used for safeguarding the user's
+ // untrusted code within Native Client.
+ // TODO(msneck): Remove the use of Unix sockets from Native Client and
+ // then decide on an appropriate sandbox type for the untrusted code.
+ // This might simply mean removing the Unix socket rules from
+ // chrome/browser/nacl_loader.sb or it might mean sharing the
+ // sandbox configuration with SANDBOX_TYPE_WORKER.
+ // See http://code.google.com/p/nativeclient/issues/detail?id=344
+ sandbox_config_filename = @"nacl_loader";
+ break;
+ default:
+ NOTREACHED();
+ return false;
+ }
+
+ // Read in the sandbox profile and the common prefix file.
+ NSString* common_sandbox_prefix_path =
+ [mac_util::MainAppBundle() pathForResource:@"common"
+ ofType:@"sb"];
+ NSString* common_sandbox_prefix_data =
+ [NSString stringWithContentsOfFile:common_sandbox_prefix_path
+ encoding:NSUTF8StringEncoding
+ error:NULL];
+
+ if (!common_sandbox_prefix_data) {
+ LOG(FATAL) << "Failed to find the sandbox profile on disk "
+ << [common_sandbox_prefix_path fileSystemRepresentation];
+ return false;
+ }
+
+ NSString* sandbox_profile_path =
+ [mac_util::MainAppBundle() pathForResource:sandbox_config_filename
+ ofType:@"sb"];
+ NSString* sandbox_data =
+ [NSString stringWithContentsOfFile:sandbox_profile_path
+ encoding:NSUTF8StringEncoding
+ error:NULL];
+
+ if (!sandbox_data) {
+ LOG(FATAL) << "Failed to find the sandbox profile on disk "
+ << [sandbox_profile_path fileSystemRepresentation];
+ return false;
+ }
+
+ // Prefix sandbox_data with common_sandbox_prefix_data.
+ sandbox_data =
+ [common_sandbox_prefix_data stringByAppendingString:sandbox_data];
+
+ // Enable verbose logging if enabled on the command line.
+ // (see renderer.sb for details).
+ const CommandLine *command_line = CommandLine::ForCurrentProcess();
+ if (command_line->HasSwitch(switches::kEnableSandboxLogging)) {
+ sandbox_data = [sandbox_data
+ stringByReplacingOccurrencesOfString:@";ENABLE_LOGGING"
+ withString:@""];
+ }
+
+ // Enable Native Client lines if they are allowed.
+ if (allow_nacl_lines) {
+ sandbox_data = [sandbox_data
+ stringByReplacingOccurrencesOfString:@";NACL"
+ withString:@""];
+ }
+
+ if (!allowed_dir.empty()) {
+ // The sandbox only understands "real" paths. This resolving step is
+ // needed so the caller doesn't need to worry about things like /var
+ // being a link to /private/var (like in the paths CreateNewTempDirectory()
+ // returns).
+ FilePath allowed_dir_canonical(allowed_dir);
+ GetCanonicalSandboxPath(&allowed_dir_canonical);
+
+ std::string allowed_dir_escaped;
+ if (!QuoteStringForRegex(allowed_dir_canonical.value(),
+ &allowed_dir_escaped)) {
+ LOG(FATAL) << "Regex string quoting failed " << allowed_dir.value();
+ return false;
+ }
+ NSString* allowed_dir_escaped_ns = base::SysUTF8ToNSString(
+ allowed_dir_escaped.c_str());
+ sandbox_data = [sandbox_data
+ stringByReplacingOccurrencesOfString:@";ENABLE_DIRECTORY_ACCESS"
+ withString:@""];
+ sandbox_data = [sandbox_data
+ stringByReplacingOccurrencesOfString:@"DIR_TO_ALLOW_ACCESS"
+ withString:allowed_dir_escaped_ns];
+
+ }
+
+ int32 major_version, minor_version, bugfix_version;
+ base::SysInfo::OperatingSystemVersionNumbers(&major_version,
+ &minor_version, &bugfix_version);
+
+ if (major_version > 10 || (major_version == 10 && minor_version >= 6)) {
+ // 10.6-only Sandbox rules.
+ sandbox_data = [sandbox_data
+ stringByReplacingOccurrencesOfString:@";10.6_ONLY"
+ withString:@""];
+ // Splice the path of the user's home directory into the sandbox profile
+ // (see renderer.sb for details).
+ // This code is in the 10.6-only block because the sandbox syntax we use
+ // for this "subdir" is only supported on 10.6.
+ // If we ever need this on pre-10.6 OSs then we'll have to rethink the
+ // surrounding sandbox syntax.
+ std::string home_dir = base::SysNSStringToUTF8(NSHomeDirectory());
+
+ FilePath home_dir_canonical(home_dir);
+ GetCanonicalSandboxPath(&home_dir_canonical);
+
+ std::string home_dir_escaped;
+ if (!QuotePlainString(home_dir_canonical.value(), &home_dir_escaped)) {
+ LOG(FATAL) << "Sandbox string quoting failed";
+ return false;
+ }
+ NSString* home_dir_escaped_ns = base::SysUTF8ToNSString(home_dir_escaped);
+ sandbox_data = [sandbox_data
+ stringByReplacingOccurrencesOfString:@"USER_HOMEDIR"
+ withString:home_dir_escaped_ns];
+ } else if (major_version == 10 && minor_version < 6) {
+ // Sandbox rules only for versions before 10.6.
+ sandbox_data = [sandbox_data
+ stringByReplacingOccurrencesOfString:@";BEFORE_10.6"
+ withString:@""];
+ }
+
+ char* error_buff = NULL;
+ int error = sandbox_init([sandbox_data UTF8String], 0, &error_buff);
+ bool success = (error == 0 && error_buff == NULL);
+ LOG_IF(FATAL, !success) << "Failed to initialize sandbox: "
+ << error
+ << " "
+ << error_buff;
+ sandbox_free_error(error_buff);
+ return success;
+}
+
+void GetCanonicalSandboxPath(FilePath* path) {
+ int fd = HANDLE_EINTR(open(path->value().c_str(), O_RDONLY));
+ if (fd < 0) {
+ PLOG(FATAL) << "GetCanonicalSandboxPath() failed for: "
+ << path->value();
+ return;
+ }
+ file_util::ScopedFD file_closer(&fd);
+
+ FilePath::CharType canonical_path[MAXPATHLEN];
+ if (HANDLE_EINTR(fcntl(fd, F_GETPATH, canonical_path)) != 0) {
+ PLOG(FATAL) << "GetCanonicalSandboxPath() failed for: "
+ << path->value();
+ return;
+ }
+
+ *path = FilePath(canonical_path);
+}
+
+} // namespace sandbox
diff --git a/chrome/common/sandbox_mac_diraccess_unittest.mm b/chrome/common/sandbox_mac_diraccess_unittest.mm
new file mode 100644
index 0000000..f356453
--- /dev/null
+++ b/chrome/common/sandbox_mac_diraccess_unittest.mm
@@ -0,0 +1,250 @@
+// Copyright (c) 2009 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.
+
+#import <Cocoa/Cocoa.h>
+#include <dirent.h>
+
+extern "C" {
+#include <sandbox.h>
+}
+
+#include "base/file_util.h"
+#include "base/file_path.h"
+#include "base/multiprocess_test.h"
+#include "base/sys_string_conversions.h"
+#include "base/utf_string_conversions.h"
+#include "chrome/common/sandbox_mac.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+// Tests to exercise directory-access-related restrictions of Mac sandbox.
+
+namespace sandbox {
+
+bool QuotePlainString(const std::string& str_utf8, std::string* dst);
+bool QuoteStringForRegex(const std::string& str_utf8, std::string* dst);
+
+} // namespace sandbox
+
+namespace {
+
+static const char* kSandboxAccessPathKey = "sandbox_dir";
+
+class MacDirAccessSandboxTest : public MultiProcessTest {
+ public:
+ bool CheckSandbox(std::string directory_to_try) {
+ setenv(kSandboxAccessPathKey, directory_to_try.c_str(), 1);
+ base::ProcessHandle child_process = SpawnChild(L"mac_sandbox_path_access");
+ int code = -1;
+ if (!base::WaitForExitCode(child_process, &code)) {
+ LOG(WARNING) << "base::WaitForExitCode failed";
+ return false;
+ }
+ return code == 0;
+ }
+};
+
+TEST_F(MacDirAccessSandboxTest, StringEscape) {
+ using sandbox::QuotePlainString;
+
+ const struct string_escape_test_data {
+ const char* to_escape;
+ const char* escaped;
+ } string_escape_cases[] = {
+ {"", ""},
+ {"\b\f\n\r\t\\\"", "\\b\\f\\n\\r\\t\\\\\\\""},
+ {"/'", "/'"},
+ {"sandwich", "sandwich"},
+ {"(sandwich)", "(sandwich)"},
+ {"^\u2135.\u2136$", "^\\u2135.\\u2136$"},
+ };
+
+ for (size_t i = 0; i < ARRAYSIZE_UNSAFE(string_escape_cases); ++i) {
+ std::string out;
+ std::string in(string_escape_cases[i].to_escape);
+ EXPECT_TRUE(QuotePlainString(in, &out));
+ EXPECT_EQ(string_escape_cases[i].escaped, out);
+ }
+}
+
+TEST_F(MacDirAccessSandboxTest, RegexEscape) {
+ using sandbox::QuoteStringForRegex;
+
+ const std::string kSandboxEscapeSuffix("(/|$)");
+ const struct regex_test_data {
+ const wchar_t *to_escape;
+ const char* escaped;
+ } regex_cases[] = {
+ {L"", ""},
+ {L"/'", "/'"}, // / & ' characters don't need escaping.
+ {L"sandwich", "sandwich"},
+ {L"(sandwich)", "\\(sandwich\\)"},
+ };
+
+ // Check that all characters whose values are smaller than 32 [1F] are
+ // rejected by the regex escaping code.
+ {
+ std::string out;
+ char fail_string[] = {31, 0};
+ char ok_string[] = {32, 0};
+ EXPECT_FALSE(QuoteStringForRegex(fail_string, &out));
+ EXPECT_TRUE(QuoteStringForRegex(ok_string, &out));
+ }
+
+ // Check that all characters whose values are larger than 126 [7E] are
+ // rejected by the regex escaping code.
+ {
+ std::string out;
+ EXPECT_TRUE(QuoteStringForRegex("}", &out)); // } == 0x7D == 125
+ EXPECT_FALSE(QuoteStringForRegex("~", &out)); // ~ == 0x7E == 126
+ EXPECT_FALSE(QuoteStringForRegex(WideToUTF8(L"^\u2135.\u2136$"), &out));
+ }
+
+ {
+ for (size_t i = 0; i < ARRAYSIZE_UNSAFE(regex_cases); ++i) {
+ std::string out;
+ std::string in = WideToUTF8(regex_cases[i].to_escape);
+ EXPECT_TRUE(QuoteStringForRegex(in, &out));
+ std::string expected("^");
+ expected.append(regex_cases[i].escaped);
+ expected.append(kSandboxEscapeSuffix);
+ EXPECT_EQ(expected, out);
+ }
+ }
+
+ {
+ std::string in_utf8("\\^.$|()[]*+?{}");
+ std::string expected;
+ expected.push_back('^');
+ for (size_t i = 0; i < in_utf8.length(); ++i) {
+ expected.push_back('\\');
+ expected.push_back(in_utf8[i]);
+ }
+ expected.append(kSandboxEscapeSuffix);
+
+ std::string out;
+ EXPECT_TRUE(QuoteStringForRegex(in_utf8, &out));
+ EXPECT_EQ(expected, out);
+
+ }
+}
+
+// A class to handle auto-deleting a directory.
+class ScopedDirectoryDelete {
+ public:
+ inline void operator()(FilePath* x) const {
+ if (x) {
+ file_util::Delete(*x, true);
+ }
+ }
+};
+
+typedef scoped_ptr_malloc<FilePath, ScopedDirectoryDelete> ScopedDirectory;
+
+TEST_F(MacDirAccessSandboxTest, SandboxAccess) {
+ FilePath tmp_dir;
+ ASSERT_TRUE(file_util::CreateNewTempDirectory("", &tmp_dir));
+ // This step is important on OS X since the sandbox only understands "real"
+ // paths and the paths CreateNewTempDirectory() returns are empirically in
+ // /var which is a symlink to /private/var .
+ sandbox::GetCanonicalSandboxPath(&tmp_dir);
+ ScopedDirectory cleanup(&tmp_dir);
+
+ const char* sandbox_dir_cases[] = {
+ "simple_dir_name",
+ "^hello++ $", // Regex.
+ "\\^.$|()[]*+?{}", // All regex characters.
+ };
+
+ for (size_t i = 0; i < ARRAYSIZE_UNSAFE(sandbox_dir_cases); ++i) {
+ const char* sandbox_dir_name = sandbox_dir_cases[i];
+ FilePath sandbox_dir = tmp_dir.Append(sandbox_dir_name);
+ ASSERT_TRUE(file_util::CreateDirectory(sandbox_dir));
+ ScopedDirectory cleanup_sandbox(&sandbox_dir);
+ EXPECT_TRUE(CheckSandbox(sandbox_dir.value()));
+ }
+}
+
+MULTIPROCESS_TEST_MAIN(mac_sandbox_path_access) {
+ char *sandbox_allowed_dir = getenv(kSandboxAccessPathKey);
+ if (!sandbox_allowed_dir)
+ return -1;
+
+ // Build up a sandbox profile that only allows access to DIR_TO_ALLOW_ACCESS.
+ NSString *sandbox_profile =
+ @"(version 1)" \
+ "(deny default)" \
+ "(allow signal (target self))" \
+ "(allow sysctl-read)" \
+ "(allow file-read-metadata)" \
+ "(allow file-read* file-write* (regex #\"DIR_TO_ALLOW_ACCESS\"))";
+
+ std::string allowed_dir(sandbox_allowed_dir);
+ std::string allowed_dir_escaped;
+ if (!sandbox::QuoteStringForRegex(allowed_dir, &allowed_dir_escaped)) {
+ LOG(ERROR) << "Regex string quoting failed " << allowed_dir;
+ return -1;
+ }
+ NSString* allowed_dir_escaped_ns = base::SysUTF8ToNSString(
+ allowed_dir_escaped.c_str());
+ sandbox_profile = [sandbox_profile
+ stringByReplacingOccurrencesOfString:@"DIR_TO_ALLOW_ACCESS"
+ withString:allowed_dir_escaped_ns];
+ // Enable Sandbox.
+ char* error_buff = NULL;
+ int error = sandbox_init([sandbox_profile UTF8String], 0, &error_buff);
+ if (error == -1) {
+ LOG(ERROR) << "Failed to Initialize Sandbox: " << error_buff;
+ return -1;
+ }
+ sandbox_free_error(error_buff);
+
+ // Test Sandbox.
+
+ // We should be able to list the contents of the sandboxed directory.
+ DIR *file_list = NULL;
+ file_list = opendir(sandbox_allowed_dir);
+ if (!file_list) {
+ PLOG(ERROR) << "Sandbox overly restrictive: call to opendir("
+ << sandbox_allowed_dir
+ << ") failed";
+ return -1;
+ }
+ closedir(file_list);
+
+ // Test restrictions on accessing files.
+ FilePath allowed_dir_path(sandbox_allowed_dir);
+ FilePath allowed_file = allowed_dir_path.Append("ok_to_write");
+ FilePath denied_file1 = allowed_dir_path.DirName().Append("cant_access");
+
+ // Try to write a file who's name has the same prefix as the directory we
+ // allow access to.
+ FilePath basename = allowed_dir_path.BaseName();
+ std::string tricky_filename = basename.value() + "123";
+ FilePath denied_file2 = allowed_dir_path.DirName().Append(tricky_filename);
+
+ if (open(allowed_file.value().c_str(), O_WRONLY | O_CREAT) <= 0) {
+ PLOG(ERROR) << "Sandbox overly restrictive: failed to write ("
+ << allowed_file.value()
+ << ")";
+ return -1;
+ }
+
+ if (open(denied_file1.value().c_str(), O_WRONLY | O_CREAT) > 0) {
+ PLOG(ERROR) << "Sandbox breach: was able to write ("
+ << denied_file1.value()
+ << ")";
+ return -1;
+ }
+
+ if (open(denied_file2.value().c_str(), O_WRONLY | O_CREAT) > 0) {
+ PLOG(ERROR) << "Sandbox breach: was able to write ("
+ << denied_file2.value()
+ << ")";
+ return -1;
+ }
+
+ return 0;
+}
+
+} // namespace
diff --git a/chrome/common/sandbox_mac_fontloading_unittest.mm b/chrome/common/sandbox_mac_fontloading_unittest.mm
new file mode 100644
index 0000000..a20d263
--- /dev/null
+++ b/chrome/common/sandbox_mac_fontloading_unittest.mm
@@ -0,0 +1,183 @@
+// Copyright (c) 2010 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.
+
+#import <Cocoa/Cocoa.h>
+
+#include "base/file_util.h"
+#include "base/logging.h"
+#include "base/scoped_cftyperef.h"
+#include "base/scoped_ptr.h"
+#include "base/shared_memory.h"
+#include "chrome/common/font_loader_mac.h"
+#include "chrome/common/sandbox_mac_unittest_helper.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+namespace {
+
+using sandboxtest::MacSandboxTest;
+
+bool CGFontFromFontContainer(ATSFontContainerRef container, CGFontRef* out) {
+ // Count the number of fonts that were loaded.
+ ItemCount fontCount = 0;
+ OSStatus err = ATSFontFindFromContainer(container, kATSOptionFlagsDefault, 0,
+ NULL, &fontCount);
+
+ if (err != noErr || fontCount < 1) {
+ return false;
+ }
+
+ // Load font from container.
+ ATSFontRef font_ref_ats = 0;
+ ATSFontFindFromContainer(container, kATSOptionFlagsDefault, 1,
+ &font_ref_ats, NULL);
+
+ if (!font_ref_ats) {
+ return false;
+ }
+
+ // Convert to cgFont.
+ CGFontRef font_ref_cg = CGFontCreateWithPlatformFont(&font_ref_ats);
+
+ if (!font_ref_cg) {
+ return false;
+ }
+
+ *out = font_ref_cg;
+ return true;
+}
+
+class ScopedFontContainer {
+ public:
+ explicit ScopedFontContainer(ATSFontContainerRef ref)
+ : container_ref(ref) {}
+
+ ~ScopedFontContainer() {
+ ATSFontDeactivate(container_ref, NULL, kATSOptionFlagsDefault);
+ }
+
+ ATSFontContainerRef container_ref;
+};
+
+class FontLoadingTestCase : public sandboxtest::MacSandboxTestCase {
+ public:
+ FontLoadingTestCase() : font_data_length_(-1) {}
+ virtual bool BeforeSandboxInit();
+ virtual bool SandboxedTest();
+ private:
+ scoped_ptr<base::SharedMemory> font_shmem_;
+ size_t font_data_length_;
+};
+REGISTER_SANDBOX_TEST_CASE(FontLoadingTestCase);
+
+
+// Load raw font data into shared memory object.
+bool FontLoadingTestCase::BeforeSandboxInit() {
+ std::string font_data;
+ if (!file_util::ReadFileToString(FilePath(test_data_.c_str()), &font_data)) {
+ LOG(ERROR) << "Failed to read font data from file (" << test_data_ << ")";
+ return false;
+ }
+
+ font_data_length_ = font_data.length();
+ if (font_data_length_ <= 0) {
+ LOG(ERROR) << "No font data: " << font_data_length_;
+ return false;
+ }
+
+ font_shmem_.reset(new base::SharedMemory);
+ if (!font_shmem_.get()) {
+ LOG(ERROR) << "Failed to create shared memory object.";
+ return false;
+ }
+
+ if (!font_shmem_->Create(L"", false, false, font_data_length_)) {
+ LOG(ERROR) << "SharedMemory::Create failed";
+ return false;
+ }
+
+ if (!font_shmem_->Map(font_data_length_)) {
+ LOG(ERROR) << "SharedMemory::Map failed";
+ return false;
+ }
+
+ memcpy(font_shmem_->memory(), font_data.c_str(), font_data_length_);
+ if (!font_shmem_->Unmap()) {
+ LOG(ERROR) << "SharedMemory::Unmap failed";
+ return false;
+ }
+ return true;
+}
+
+bool FontLoadingTestCase::SandboxedTest() {
+ base::SharedMemoryHandle shmem_handle;
+ if (!font_shmem_->ShareToProcess(NULL, &shmem_handle)) {
+ LOG(ERROR) << "SharedMemory::ShareToProcess failed";
+ return false;
+ }
+
+ ATSFontContainerRef font_container;
+ if (!FontLoader::ATSFontContainerFromBuffer(shmem_handle, font_data_length_,
+ &font_container)) {
+ LOG(ERROR) << "Call to CreateCGFontFromBuffer() failed";
+ return false;
+ }
+
+ // Unload the font container when done.
+ ScopedFontContainer scoped_unloader(font_container);
+
+ CGFontRef font_ref;
+ if (!CGFontFromFontContainer(font_container, &font_ref)) {
+ LOG(ERROR) << "CGFontFromFontContainer failed";
+ return false;
+ }
+
+ if (!font_ref) {
+ LOG(ERROR) << "Got NULL CGFontRef";
+ return false;
+ }
+ scoped_cftyperef<CGFontRef> cgfont;
+ cgfont.reset(font_ref);
+
+ const NSFont* nsfont = reinterpret_cast<const NSFont*>(
+ CTFontCreateWithGraphicsFont(cgfont.get(), 16.0,
+ NULL, NULL));
+ if (!nsfont) {
+ LOG(ERROR) << "CTFontCreateWithGraphicsFont() failed";
+ return false;
+ }
+
+ // Do something with the font to make sure it's loaded.
+ CGFloat cap_height = [nsfont capHeight];
+
+ if (cap_height <= 0.0) {
+ LOG(ERROR) << "Got bad value for [NSFont capHeight] " << cap_height;
+ return false;
+ }
+
+ return true;
+}
+
+TEST_F(MacSandboxTest, FontLoadingTest) {
+ FilePath temp_file_path;
+ FILE* temp_file = file_util::CreateAndOpenTemporaryFile(&temp_file_path);
+ ASSERT_TRUE(temp_file);
+ file_util::ScopedFILE temp_file_closer(temp_file);
+
+ base::SharedMemory font_data;
+ uint32 font_data_size;
+ NSFont* srcFont = [NSFont fontWithName:@"Geeza Pro" size:16.0];
+ EXPECT_TRUE(FontLoader::LoadFontIntoBuffer(srcFont,
+ &font_data, &font_data_size));
+ EXPECT_GT(font_data_size, 0U);
+
+ file_util::WriteFileDescriptor(fileno(temp_file),
+ static_cast<const char *>(font_data.memory()), font_data_size);
+
+ ASSERT_TRUE(RunTestInSandbox(sandbox::SANDBOX_TYPE_RENDERER,
+ "FontLoadingTestCase", temp_file_path.value().c_str()));
+ temp_file_closer.reset();
+ ASSERT_TRUE(file_util::Delete(temp_file_path, false));
+}
+
+} // namespace
diff --git a/chrome/common/sandbox_mac_system_access_unittest.mm b/chrome/common/sandbox_mac_system_access_unittest.mm
new file mode 100644
index 0000000..382aa2c
--- /dev/null
+++ b/chrome/common/sandbox_mac_system_access_unittest.mm
@@ -0,0 +1,96 @@
+// Copyright (c) 2010 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.
+
+#import <Cocoa/Cocoa.h>
+
+#include "base/logging.h"
+#include "base/sys_string_conversions.h"
+#include "chrome/common/sandbox_mac.h"
+#include "chrome/common/sandbox_mac_unittest_helper.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+namespace {
+
+using sandboxtest::MacSandboxTest;
+
+//--------------------- Clipboard Sandboxing ----------------------
+// Test case for checking sandboxing of clipboard access.
+class MacSandboxedClipboardTestCase : public sandboxtest::MacSandboxTestCase {
+ public:
+ MacSandboxedClipboardTestCase();
+ virtual ~MacSandboxedClipboardTestCase();
+
+ virtual bool SandboxedTest();
+
+ virtual void SetTestData(const char* test_data);
+ private:
+ NSString* clipboard_name_;
+};
+
+REGISTER_SANDBOX_TEST_CASE(MacSandboxedClipboardTestCase);
+
+MacSandboxedClipboardTestCase::MacSandboxedClipboardTestCase() :
+ clipboard_name_(nil) {}
+
+MacSandboxedClipboardTestCase::~MacSandboxedClipboardTestCase() {
+ [clipboard_name_ release];
+}
+
+bool MacSandboxedClipboardTestCase::SandboxedTest() {
+ // Shouldn't be able to open the pasteboard in the sandbox.
+
+ if ([clipboard_name_ length] == 0) {
+ LOG(ERROR) << "Clipboard name is empty";
+ return false;
+ }
+
+ NSPasteboard* pb = [NSPasteboard pasteboardWithName:clipboard_name_];
+ if (pb != nil) {
+ LOG(ERROR) << "Was able to access named clipboard";
+ return false;
+ }
+
+ pb = [NSPasteboard generalPasteboard];
+ if (pb != nil) {
+ LOG(ERROR) << "Was able to access system clipboard";
+ return false;
+ }
+
+ return true;
+}
+
+void MacSandboxedClipboardTestCase::SetTestData(const char* test_data) {
+ clipboard_name_ = [base::SysUTF8ToNSString(test_data) retain];
+}
+
+TEST_F(MacSandboxTest, ClipboardAccess) {
+ NSPasteboard* pb = [NSPasteboard pasteboardWithUniqueName];
+ EXPECT_EQ([[pb types] count], 0U);
+
+ std::string pasteboard_name = base::SysNSStringToUTF8([pb name]);
+ EXPECT_TRUE(RunTestInAllSandboxTypes("MacSandboxedClipboardTestCase",
+ pasteboard_name.c_str()));
+
+ // After executing the test, the clipboard should still be empty.
+ EXPECT_EQ([[pb types] count], 0U);
+}
+
+//--------------------- File Access Sandboxing ----------------------
+// Test case for checking sandboxing of filesystem apis.
+class MacSandboxedFileAccessTestCase : public sandboxtest::MacSandboxTestCase {
+ public:
+ virtual bool SandboxedTest();
+};
+
+REGISTER_SANDBOX_TEST_CASE(MacSandboxedFileAccessTestCase);
+
+bool MacSandboxedFileAccessTestCase::SandboxedTest() {
+ return open("/etc/passwd", O_RDONLY) == -1;
+}
+
+TEST_F(MacSandboxTest, FileAccess) {
+ EXPECT_TRUE(RunTestInAllSandboxTypes("MacSandboxedFileAccessTestCase", NULL));
+}
+
+} // namespace
diff --git a/chrome/common/sandbox_mac_unittest_helper.h b/chrome/common/sandbox_mac_unittest_helper.h
new file mode 100644
index 0000000..3e24009
--- /dev/null
+++ b/chrome/common/sandbox_mac_unittest_helper.h
@@ -0,0 +1,114 @@
+// Copyright (c) 2010 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_COMMON_SANDBOX_MAC_UNITTEST_RUNNER_H_
+#define CHROME_COMMON_SANDBOX_MAC_UNITTEST_RUNNER_H_
+
+#include "base/multiprocess_test.h"
+#include "chrome/common/sandbox_mac.h"
+
+namespace sandboxtest {
+
+// Helpers for writing unit tests that runs in the context of the Mac sandbox.
+//
+// How to write a sandboxed test:
+// 1. Create a class that inherits from MacSandboxTestCase and overrides
+// it's functions to run code before or after the sandbox is initialised in a
+// subprocess.
+// 2. Register the class you just created with the REGISTER_SANDBOX_TEST_CASE()
+// macro.
+// 3. Write a test [using TEST_F()] that inherits from MacSandboxTest and call
+// one of it's helper functions to launch the test.
+//
+// Example:
+// class TestCaseThatRunsInSandboxedSubprocess :
+// public sandboxtest::MacSandboxTestCase {
+// public:
+// virtual bool SandboxedTest() {
+// .. test code that runs in sandbox goes here ..
+// return true; // always succeed.
+// }
+// };
+//
+// // Register the test case you just created.
+// REGISTER_SANDBOX_TEST_CASE(TestCaseThatRunsInSandboxedSubprocess);
+//
+// TEST_F(MacSandboxTest, ATest) {
+// EXPECT_TRUE(RunTestInAllSandboxTypes(
+// "TestCaseThatRunsInSandboxedSubprocess",
+// NULL));
+// }
+
+// Base test type with helper functions to spawn a subprocess that exercises
+// a given test in the sandbox.
+class MacSandboxTest : public MultiProcessTest {
+ public:
+ // Runs a test specified by |test_name| in a sandbox of the type specified
+ // by |sandbox_type|. |test_data| is a custom string that a test can pass
+ // to the child process runing in the sandbox.
+ // Returns true if the test passes, false if either of the functions in
+ // the corresponding MacSandboxTestCase return false.
+ bool RunTestInSandbox(sandbox::SandboxProcessType sandbox_type,
+ const char* test_name,
+ const char* test_data);
+
+ // Runs the test specified by |test_name| in all the different sandbox types,
+ // one by one.
+ // Returns true if the test passes, false if either of the functions in
+ // the corresponding MacSandboxTestCase return false in any of the spawned
+ // processes.
+ bool RunTestInAllSandboxTypes(const char* test_name,
+ const char* test_data);
+};
+
+// Class to ease writing test cases that run inside the OS X sandbox.
+// This class is instantiated in a subprocess, and allows you to run test code
+// at various stages of execution.
+// Note that you must register the subclass you create with the
+// REGISTER_SANDBOX_TEST_CASE so it's visible to the test driver.
+class MacSandboxTestCase {
+ public:
+ // Code that runs in the sandboxed subprocess before the sandbox is
+ // initialized.
+ // Returning false from this function will cause the entire test case to fail.
+ virtual bool BeforeSandboxInit() { return true; };
+
+ // Code that runs in the sandboxed subprocess when the sandbox has been
+ // enabled.
+ // Returning false from this function will cause the entire test case to fail.
+ virtual bool SandboxedTest() = 0;
+
+ // The data that's passed in the |user_data| parameter of
+ // RunTest[s]InSandbox() is passed to this function.
+ virtual void SetTestData(const char* test_data) { test_data_ = test_data; }
+
+ protected:
+ std::string test_data_;
+};
+
+// Plumbing to support the REGISTER_SANDBOX_TEST_CASE macro.
+namespace internal {
+
+// Register a test case with a given name.
+void AddSandboxTestCase(const char* test_name, MacSandboxTestCase* test_class);
+
+// Construction of this class causes a new entry to be placed in a global
+// map.
+template <class T> struct RegisterSandboxTest {
+ RegisterSandboxTest(const char* test_name) {
+ AddSandboxTestCase(test_name, new T);
+ }
+};
+
+#define REGISTER_SANDBOX_TEST_CASE(class_name) \
+ namespace { \
+ sandboxtest::internal::RegisterSandboxTest<class_name> \
+ register_test##class_name(#class_name); \
+ } // namespace
+
+} // namespace internal
+
+} // namespace sandboxtest
+
+#endif // CHROME_COMMON_SANDBOX_MAC_UNITTEST_RUNNER_H_
diff --git a/chrome/common/sandbox_mac_unittest_helper.mm b/chrome/common/sandbox_mac_unittest_helper.mm
new file mode 100644
index 0000000..a14370f
--- /dev/null
+++ b/chrome/common/sandbox_mac_unittest_helper.mm
@@ -0,0 +1,153 @@
+// Copyright (c) 2010 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/common/sandbox_mac_unittest_helper.h"
+
+extern "C" {
+#include <sandbox.h>
+}
+
+#include "base/scoped_ptr.h"
+#include "chrome/common/sandbox_mac.h"
+
+namespace {
+
+const char* kSandboxTypeKey = "CHROMIUM_SANDBOX_SANDBOX_TYPE";
+const char* kSandboxTestNameKey = "CHROMIUM_SANDBOX_TEST_NAME";
+const char* kTestDataKey = "CHROMIUM_SANDBOX_USER_DATA";
+
+} // namespace
+
+namespace sandboxtest {
+
+// Support infrastructure for REGISTER_SANDBOX_TEST_CASE macro.
+namespace internal {
+
+typedef std::map<std::string,MacSandboxTestCase*> SandboxTestMap;
+
+// A function that returns a common map from string -> test case class.
+SandboxTestMap& GetSandboxTestMap() {
+ static SandboxTestMap test_map;
+ return test_map;
+}
+
+void AddSandboxTestCase(const char* test_name, MacSandboxTestCase* test_class) {
+ SandboxTestMap& test_map = GetSandboxTestMap();
+ if (test_map.find(test_name) != test_map.end()) {
+ LOG(ERROR) << "Trying to register duplicate test" << test_name;
+ NOTREACHED();
+ }
+ test_map[test_name] = test_class;
+}
+
+} // namespace internal
+
+bool MacSandboxTest:: RunTestInAllSandboxTypes(const char* test_name,
+ const char* test_data) {
+ // Go through all the sandbox types, and run the test case in each of them
+ // if one fails, abort.
+ for(int i = static_cast<int>(sandbox::SANDBOX_TYPE_FIRST_TYPE);
+ i < sandbox::SANDBOX_AFTER_TYPE_LAST_TYPE;
+ ++i) {
+ if (!RunTestInSandbox(static_cast<sandbox::SandboxProcessType>(i),
+ test_name, test_data)) {
+ LOG(ERROR) << "Sandboxed test (" << test_name << ")" <<
+ "Failed in sandbox type " << i <<
+ "user data: (" << test_data << ")";
+ return false;
+ }
+ }
+ return true;
+}
+
+bool MacSandboxTest::RunTestInSandbox(sandbox::SandboxProcessType sandbox_type,
+ const char* test_name,
+ const char* test_data) {
+ std::stringstream s;
+ s << static_cast<int>(static_cast<int>(sandbox_type));
+ setenv(kSandboxTypeKey, s.str().c_str(), 1);
+ setenv(kSandboxTestNameKey, test_name, 1);
+ if (test_data)
+ setenv(kTestDataKey, test_data, 1);
+
+ base::ProcessHandle child_process = SpawnChild(L"mac_sandbox_test_runner");
+ int code = -1;
+ if (!base::WaitForExitCode(child_process, &code)) {
+ LOG(WARNING) << "base::WaitForExitCode failed";
+ return false;
+ }
+ return code == 0;
+}
+
+// Given a test name specified by |name| return that test case.
+// If no test case is found for the given name, return NULL.
+MacSandboxTestCase *SandboxTestForName(const char* name) {
+ using internal::SandboxTestMap;
+ using internal::GetSandboxTestMap;
+
+ SandboxTestMap all_tests = GetSandboxTestMap();
+
+ SandboxTestMap::iterator it = all_tests.find(name);
+ if (it == all_tests.end()) {
+ LOG(ERROR) << "Couldn't find sandbox test case(" << name << ")";
+ return NULL;
+ }
+
+ return it->second;
+}
+
+} // namespace sandboxtest
+
+namespace {
+
+// Main function for driver process that enables the sandbox and runs test
+// code.
+MULTIPROCESS_TEST_MAIN(mac_sandbox_test_runner) {
+ // Extract parameters.
+ char* sandbox_type_str = getenv(kSandboxTypeKey);
+ if (!sandbox_type_str) {
+ LOG(ERROR) << "Sandbox type not specified";
+ return -1;
+ }
+ sandbox::SandboxProcessType sandbox_type =
+ static_cast<sandbox::SandboxProcessType>(atoi(sandbox_type_str));
+ char* sandbox_test_name = getenv(kSandboxTestNameKey);
+ if (!sandbox_test_name) {
+ LOG(ERROR) << "Sandbox test name not specified";
+ return -1;
+ }
+
+ const char* test_data = getenv(kTestDataKey);
+
+ // Find Test Function to run;
+ scoped_ptr<sandboxtest::MacSandboxTestCase>
+ test_case(sandboxtest::SandboxTestForName(sandbox_test_name));
+ if (!test_case.get()) {
+ LOG(ERROR) << "Invalid sandbox test name (" << sandbox_test_name << ")";
+ return -1;
+ }
+ test_case->SetTestData(test_data);
+
+ // Run Test.
+ if (!test_case->BeforeSandboxInit()) {
+ LOG(ERROR) << sandbox_test_name << "Failed test before sandbox init";
+ return -1;
+ }
+
+ sandbox::SandboxWarmup();
+
+ if (!sandbox::EnableSandbox(sandbox_type, FilePath())) {
+ LOG(ERROR) << "Failed to initialize sandbox " << sandbox_type;
+ return -1;
+ }
+
+ if (!test_case->SandboxedTest()) {
+ LOG(ERROR) << sandbox_test_name << "Failed sandboxed test";
+ return -1;
+ }
+
+ return 0;
+}
+
+} // namespace
diff --git a/chrome/common/sandbox_methods_linux.h b/chrome/common/sandbox_methods_linux.h
new file mode 100644
index 0000000..254ba62
--- /dev/null
+++ b/chrome/common/sandbox_methods_linux.h
@@ -0,0 +1,24 @@
+// Copyright (c) 2009 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_COMMON_SANDBOX_METHODS_LINUX_H_
+#define CHROME_COMMON_SANDBOX_METHODS_LINUX_H_
+
+// This is a list of sandbox IPC methods which the renderer may send to the
+// sandbox host. See http://code.google.com/p/chromium/LinuxSandboxIPC
+// This isn't the full list, values < 32 are reserved for methods called from
+// Skia.
+class LinuxSandbox {
+ public:
+ enum Methods {
+ METHOD_GET_FONT_FAMILY_FOR_CHARS = 32,
+ METHOD_LOCALTIME = 33,
+ METHOD_GET_CHILD_WITH_INODE = 34,
+ METHOD_GET_STYLE_FOR_STRIKE = 35,
+ METHOD_MAKE_SHARED_MEMORY_SEGMENT = 36,
+ METHOD_MATCH_WITH_FALLBACK = 37,
+ };
+};
+
+#endif // CHROME_COMMON_SANDBOX_METHODS_LINUX_H_
diff --git a/chrome/common/sandbox_policy.cc b/chrome/common/sandbox_policy.cc
new file mode 100644
index 0000000..aa5249f
--- /dev/null
+++ b/chrome/common/sandbox_policy.cc
@@ -0,0 +1,503 @@
+// Copyright (c) 2010 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/common/sandbox_policy.h"
+
+#include <string>
+
+#include "app/win_util.h"
+#include "base/command_line.h"
+#include "base/debug_util.h"
+#include "base/file_util.h"
+#include "base/logging.h"
+#include "base/path_service.h"
+#include "base/process_util.h"
+#include "base/registry.h"
+#include "base/string_util.h"
+#include "base/win_util.h"
+#include "chrome/common/child_process_info.h"
+#include "chrome/common/chrome_constants.h"
+#include "chrome/common/chrome_paths.h"
+#include "chrome/common/chrome_switches.h"
+#include "chrome/common/debug_flags.h"
+#include "sandbox/src/sandbox.h"
+
+static sandbox::BrokerServices* g_broker_services = NULL;
+
+namespace {
+
+// The DLLs listed here are known (or under strong suspicion) of causing crashes
+// when they are loaded in the renderer.
+const wchar_t* const kTroublesomeDlls[] = {
+ L"adialhk.dll", // Kaspersky Internet Security.
+ L"acpiz.dll", // Unknown.
+ L"avgrsstx.dll", // AVG 8.
+ L"btkeyind.dll", // Widcomm Bluetooth.
+ L"cmcsyshk.dll", // CMC Internet Security.
+ L"dockshellhook.dll", // Stardock Objectdock.
+ L"GoogleDesktopNetwork3.DLL", // Google Desktop Search v5.
+ L"fwhook.dll", // PC Tools Firewall Plus.
+ L"hookprocesscreation.dll", // Blumentals Program protector.
+ L"hookterminateapis.dll", // Blumentals and Cyberprinter.
+ L"hookprintapis.dll", // Cyberprinter.
+ L"imon.dll", // NOD32 Antivirus.
+ L"ioloHL.dll", // Iolo (System Mechanic).
+ L"kloehk.dll", // Kaspersky Internet Security.
+ L"lawenforcer.dll", // Spyware-Browser AntiSpyware (Spybro).
+ L"libdivx.dll", // DivX.
+ L"lvprcinj01.dll", // Logitech QuickCam.
+ L"madchook.dll", // Madshi (generic hooking library).
+ L"mdnsnsp.dll", // Bonjour.
+ L"moonsysh.dll", // Moon Secure Antivirus.
+ L"npdivx32.dll", // DivX.
+ L"npggNT.des", // GameGuard 2008.
+ L"npggNT.dll", // GameGuard (older).
+ L"oawatch.dll", // Online Armor.
+ L"pavhook.dll", // Panda Internet Security.
+ L"pavshook.dll", // Panda Antivirus.
+ L"pctavhook.dll", // PC Tools Antivirus.
+ L"pctgmhk.dll", // PC Tools Spyware Doctor.
+ L"prntrack.dll", // Pharos Systems.
+ L"radhslib.dll", // Radiant Naomi Internet Filter.
+ L"radprlib.dll", // Radiant Naomi Internet Filter.
+ L"rlhook.dll", // Trustware Bufferzone.
+ L"r3hook.dll", // Kaspersky Internet Security.
+ L"sahook.dll", // McAfee Site Advisor.
+ L"sbrige.dll", // Unknown.
+ L"sc2hook.dll", // Supercopier 2.
+ L"sguard.dll", // Iolo (System Guard).
+ L"smum32.dll", // Spyware Doctor version 6.
+ L"smumhook.dll", // Spyware Doctor version 5.
+ L"ssldivx.dll", // DivX.
+ L"syncor11.dll", // SynthCore Midi interface.
+ L"systools.dll", // Panda Antivirus.
+ L"tfwah.dll", // Threatfire (PC tools).
+ L"wblind.dll", // Stardock Object desktop.
+ L"wbhelp.dll", // Stardock Object desktop.
+ L"winstylerthemehelper.dll" // Tuneup utilities 2006.
+};
+
+enum PluginPolicyCategory {
+ PLUGIN_GROUP_TRUSTED,
+ PLUGIN_GROUP_UNTRUSTED,
+};
+
+// Returns the policy category for the plugin dll.
+PluginPolicyCategory GetPolicyCategoryForPlugin(
+ const std::wstring& dll,
+ const std::wstring& list) {
+ std::wstring filename = FilePath(dll).BaseName().value();
+ std::wstring plugin_dll = StringToLowerASCII(filename);
+ std::wstring trusted_plugins = StringToLowerASCII(list);
+
+ size_t pos = 0;
+ size_t end_item = 0;
+ while (end_item != std::wstring::npos) {
+ end_item = list.find(L",", pos);
+
+ size_t size_item = (end_item == std::wstring::npos) ? end_item :
+ end_item - pos;
+ std::wstring item = list.substr(pos, size_item);
+ if (!item.empty() && item == plugin_dll)
+ return PLUGIN_GROUP_TRUSTED;
+
+ pos = end_item + 1;
+ }
+
+ return PLUGIN_GROUP_UNTRUSTED;
+}
+
+// Adds the policy rules for the path and path\ with the semantic |access|.
+// If |children| is set to true, we need to add the wildcard rules to also
+// apply the rule to the subfiles and subfolders.
+bool AddDirectory(int path, const wchar_t* sub_dir, bool children,
+ sandbox::TargetPolicy::Semantics access,
+ sandbox::TargetPolicy* policy) {
+ std::wstring directory;
+ if (!PathService::Get(path, &directory))
+ return false;
+
+ if (sub_dir) {
+ file_util::AppendToPath(&directory, sub_dir);
+ file_util::AbsolutePath(&directory);
+ }
+
+ sandbox::ResultCode result;
+ result = policy->AddRule(sandbox::TargetPolicy::SUBSYS_FILES, access,
+ directory.c_str());
+ if (result != sandbox::SBOX_ALL_OK)
+ return false;
+
+ if (children)
+ file_util::AppendToPath(&directory, L"*");
+ else
+ // Add the version of the path that ends with a separator.
+ file_util::AppendToPath(&directory, L"");
+
+ result = policy->AddRule(sandbox::TargetPolicy::SUBSYS_FILES, access,
+ directory.c_str());
+ if (result != sandbox::SBOX_ALL_OK)
+ return false;
+
+ return true;
+}
+
+// Adds the policy rules for the path and path\* with the semantic |access|.
+// We need to add the wildcard rules to also apply the rule to the subkeys.
+bool AddKeyAndSubkeys(std::wstring key,
+ sandbox::TargetPolicy::Semantics access,
+ sandbox::TargetPolicy* policy) {
+ sandbox::ResultCode result;
+ result = policy->AddRule(sandbox::TargetPolicy::SUBSYS_REGISTRY, access,
+ key.c_str());
+ if (result != sandbox::SBOX_ALL_OK)
+ return false;
+
+ key += L"\\*";
+ result = policy->AddRule(sandbox::TargetPolicy::SUBSYS_REGISTRY, access,
+ key.c_str());
+ if (result != sandbox::SBOX_ALL_OK)
+ return false;
+
+ return true;
+}
+
+// Adds policy rules for unloaded the known dlls that cause chrome to crash.
+// Eviction of injected DLLs is done by the sandbox so that the injected module
+// does not get a chance to execute any code.
+void AddDllEvictionPolicy(sandbox::TargetPolicy* policy) {
+ for (int ix = 0; ix != arraysize(kTroublesomeDlls); ++ix) {
+ // To minimize the list we only add an unload policy if the dll is also
+ // loaded in this process. All the injected dlls of interest do this.
+ if (::GetModuleHandleW(kTroublesomeDlls[ix])) {
+ LOG(INFO) << "dll to unload found: " << kTroublesomeDlls[ix];
+ policy->AddDllToUnload(kTroublesomeDlls[ix]);
+ }
+ }
+}
+
+// Adds the generic policy rules to a sandbox TargetPolicy.
+bool AddGenericPolicy(sandbox::TargetPolicy* policy) {
+ sandbox::ResultCode result;
+
+ // Add the policy for the pipes
+ result = policy->AddRule(sandbox::TargetPolicy::SUBSYS_FILES,
+ sandbox::TargetPolicy::FILES_ALLOW_ANY,
+ L"\\??\\pipe\\chrome.*");
+ if (result != sandbox::SBOX_ALL_OK)
+ return false;
+
+ result = policy->AddRule(sandbox::TargetPolicy::SUBSYS_NAMED_PIPES,
+ sandbox::TargetPolicy::NAMEDPIPES_ALLOW_ANY,
+ L"\\\\.\\pipe\\chrome.nacl.*");
+ if (result != sandbox::SBOX_ALL_OK)
+ return false;
+
+ // Add the policy for debug message only in debug
+#ifndef NDEBUG
+ std::wstring debug_message;
+ if (!PathService::Get(chrome::DIR_APP, &debug_message))
+ return false;
+ if (!win_util::ConvertToLongPath(debug_message, &debug_message))
+ return false;
+ file_util::AppendToPath(&debug_message, L"debug_message.exe");
+ result = policy->AddRule(sandbox::TargetPolicy::SUBSYS_PROCESS,
+ sandbox::TargetPolicy::PROCESS_MIN_EXEC,
+ debug_message.c_str());
+ if (result != sandbox::SBOX_ALL_OK)
+ return false;
+#endif // NDEBUG
+
+ return true;
+}
+
+// Creates a sandbox without any restriction.
+bool ApplyPolicyForTrustedPlugin(sandbox::TargetPolicy* policy) {
+ policy->SetJobLevel(sandbox::JOB_UNPROTECTED, 0);
+ policy->SetTokenLevel(sandbox::USER_UNPROTECTED, sandbox::USER_UNPROTECTED);
+ return true;
+}
+
+// Creates a sandbox with the plugin running in a restricted environment.
+// Only the "Users" and "Everyone" groups are enabled in the token. The User SID
+// is disabled.
+bool ApplyPolicyForUntrustedPlugin(sandbox::TargetPolicy* policy) {
+ policy->SetJobLevel(sandbox::JOB_UNPROTECTED, 0);
+
+ sandbox::TokenLevel initial_token = sandbox::USER_UNPROTECTED;
+ if (win_util::GetWinVersion() > win_util::WINVERSION_XP) {
+ // On 2003/Vista the initial token has to be restricted if the main token
+ // is restricted.
+ initial_token = sandbox::USER_RESTRICTED_SAME_ACCESS;
+ }
+ policy->SetTokenLevel(initial_token, sandbox::USER_LIMITED);
+ policy->SetDelayedIntegrityLevel(sandbox::INTEGRITY_LEVEL_LOW);
+
+ if (!AddDirectory(base::DIR_TEMP, NULL, true,
+ sandbox::TargetPolicy::FILES_ALLOW_ANY, policy))
+ return false;
+
+ if (!AddDirectory(base::DIR_IE_INTERNET_CACHE, NULL, true,
+ sandbox::TargetPolicy::FILES_ALLOW_ANY, policy))
+ return false;
+
+ if (!AddDirectory(base::DIR_APP_DATA, NULL, true,
+ sandbox::TargetPolicy::FILES_ALLOW_READONLY,
+ policy))
+ return false;
+
+ if (!AddDirectory(base::DIR_PROFILE, NULL, false, /*not recursive*/
+ sandbox::TargetPolicy::FILES_ALLOW_READONLY,
+ policy))
+ return false;
+
+ if (!AddDirectory(base::DIR_APP_DATA, L"Adobe", true,
+ sandbox::TargetPolicy::FILES_ALLOW_ANY,
+ policy))
+ return false;
+
+ if (!AddDirectory(base::DIR_APP_DATA, L"Macromedia", true,
+ sandbox::TargetPolicy::FILES_ALLOW_ANY,
+ policy))
+ return false;
+
+ if (!AddDirectory(base::DIR_LOCAL_APP_DATA, NULL, true,
+ sandbox::TargetPolicy::FILES_ALLOW_READONLY,
+ policy))
+ return false;
+
+ if (!AddKeyAndSubkeys(L"HKEY_CURRENT_USER\\SOFTWARE\\ADOBE",
+ sandbox::TargetPolicy::REG_ALLOW_ANY,
+ policy))
+ return false;
+
+ if (!AddKeyAndSubkeys(L"HKEY_CURRENT_USER\\SOFTWARE\\MACROMEDIA",
+ sandbox::TargetPolicy::REG_ALLOW_ANY,
+ policy))
+ return false;
+
+ if (win_util::GetWinVersion() >= win_util::WINVERSION_VISTA) {
+ if (!AddKeyAndSubkeys(L"HKEY_CURRENT_USER\\SOFTWARE\\AppDataLow",
+ sandbox::TargetPolicy::REG_ALLOW_ANY,
+ policy))
+ return false;
+
+ if (!AddDirectory(base::DIR_LOCAL_APP_DATA_LOW, NULL, true,
+ sandbox::TargetPolicy::FILES_ALLOW_ANY,
+ policy))
+ return false;
+
+ // DIR_APP_DATA is AppData\Roaming, but Adobe needs to do a directory
+ // listing in AppData directly, so we add a non-recursive policy for
+ // AppData itself.
+ if (!AddDirectory(base::DIR_APP_DATA, L"..", false,
+ sandbox::TargetPolicy::FILES_ALLOW_READONLY,
+ policy))
+ return false;
+ }
+
+ return true;
+}
+
+// Adds the custom policy rules for a given plugin. |trusted_plugins| contains
+// the comma separate list of plugin dll names that should not be sandboxed.
+bool AddPolicyForPlugin(const CommandLine* cmd_line,
+ sandbox::TargetPolicy* policy) {
+ std::wstring plugin_dll = cmd_line->
+ GetSwitchValue(switches::kPluginPath);
+ std::wstring trusted_plugins = CommandLine::ForCurrentProcess()->
+ GetSwitchValue(switches::kTrustedPlugins);
+ // Add the policy for the pipes.
+ sandbox::ResultCode result = sandbox::SBOX_ALL_OK;
+ result = policy->AddRule(sandbox::TargetPolicy::SUBSYS_NAMED_PIPES,
+ sandbox::TargetPolicy::NAMEDPIPES_ALLOW_ANY,
+ L"\\\\.\\pipe\\chrome.*");
+ if (result != sandbox::SBOX_ALL_OK) {
+ NOTREACHED();
+ return false;
+ }
+
+ PluginPolicyCategory policy_category =
+ GetPolicyCategoryForPlugin(plugin_dll, trusted_plugins);
+
+ switch (policy_category) {
+ case PLUGIN_GROUP_TRUSTED:
+ return ApplyPolicyForTrustedPlugin(policy);
+ case PLUGIN_GROUP_UNTRUSTED:
+ return ApplyPolicyForUntrustedPlugin(policy);
+ default:
+ NOTREACHED();
+ break;
+ }
+
+ return false;
+}
+
+void AddPolicyForRenderer(sandbox::TargetPolicy* policy,
+ bool* on_sandbox_desktop) {
+ policy->SetJobLevel(sandbox::JOB_LOCKDOWN, 0);
+
+ sandbox::TokenLevel initial_token = sandbox::USER_UNPROTECTED;
+ if (win_util::GetWinVersion() > win_util::WINVERSION_XP) {
+ // On 2003/Vista the initial token has to be restricted if the main
+ // token is restricted.
+ initial_token = sandbox::USER_RESTRICTED_SAME_ACCESS;
+ }
+
+ policy->SetTokenLevel(initial_token, sandbox::USER_LOCKDOWN);
+ policy->SetDelayedIntegrityLevel(sandbox::INTEGRITY_LEVEL_LOW);
+
+ bool use_winsta = !CommandLine::ForCurrentProcess()->HasSwitch(
+ switches::kDisableAltWinstation);
+
+ if (sandbox::SBOX_ALL_OK == policy->SetAlternateDesktop(use_winsta)) {
+ *on_sandbox_desktop = true;
+ } else {
+ *on_sandbox_desktop = false;
+ DLOG(WARNING) << "Failed to apply desktop security to the renderer";
+ }
+
+ AddDllEvictionPolicy(policy);
+}
+
+} // namespace
+
+namespace sandbox {
+
+void InitBrokerServices(sandbox::BrokerServices* broker_services) {
+ // TODO(abarth): DCHECK(CalledOnValidThread());
+ // See <http://b/1287166>.
+ CHECK(broker_services);
+ CHECK(!g_broker_services);
+ broker_services->Init();
+ g_broker_services = broker_services;
+}
+
+base::ProcessHandle StartProcessWithAccess(CommandLine* cmd_line,
+ const FilePath& exposed_dir) {
+ base::ProcessHandle process = 0;
+ const CommandLine& browser_command_line = *CommandLine::ForCurrentProcess();
+ ChildProcessInfo::ProcessType type;
+ std::string type_str = cmd_line->GetSwitchValueASCII(switches::kProcessType);
+ if (type_str == switches::kRendererProcess) {
+ type = ChildProcessInfo::RENDER_PROCESS;
+ } else if (type_str == switches::kExtensionProcess) {
+ // Extensions are just renderers with another name.
+ type = ChildProcessInfo::RENDER_PROCESS;
+ } else if (type_str == switches::kPluginProcess) {
+ type = ChildProcessInfo::PLUGIN_PROCESS;
+ } else if (type_str == switches::kWorkerProcess) {
+ type = ChildProcessInfo::WORKER_PROCESS;
+ } else if (type_str == switches::kNaClLoaderProcess) {
+ type = ChildProcessInfo::NACL_LOADER_PROCESS;
+ } else if (type_str == switches::kUtilityProcess) {
+ type = ChildProcessInfo::UTILITY_PROCESS;
+ } else if (type_str == switches::kNaClBrokerProcess) {
+ type = ChildProcessInfo::NACL_BROKER_PROCESS;
+ } else if (type_str == switches::kGpuProcess) {
+ type = ChildProcessInfo::GPU_PROCESS;
+ } else {
+ NOTREACHED();
+ return 0;
+ }
+
+ bool in_sandbox =
+ (type != ChildProcessInfo::NACL_BROKER_PROCESS) &&
+ !browser_command_line.HasSwitch(switches::kNoSandbox) &&
+ (type != ChildProcessInfo::PLUGIN_PROCESS ||
+ browser_command_line.HasSwitch(switches::kSafePlugins)) &&
+ (type != ChildProcessInfo::GPU_PROCESS);
+#if !defined (GOOGLE_CHROME_BUILD)
+ if (browser_command_line.HasSwitch(switches::kInProcessPlugins)) {
+ // In process plugins won't work if the sandbox is enabled.
+ in_sandbox = false;
+ }
+#endif
+ if (browser_command_line.HasSwitch(switches::kEnableExperimentalWebGL) &&
+ browser_command_line.HasSwitch(switches::kInProcessWebGL)) {
+ // In process WebGL won't work if the sandbox is enabled.
+ in_sandbox = false;
+ }
+
+ // Propagate the Chrome Frame flag to sandboxed processes if present.
+ if (browser_command_line.HasSwitch(switches::kChromeFrame)) {
+ if (!cmd_line->HasSwitch(switches::kChromeFrame)) {
+ cmd_line->AppendSwitch(switches::kChromeFrame);
+ }
+ }
+
+ bool child_needs_help =
+ DebugFlags::ProcessDebugFlags(cmd_line, type, in_sandbox);
+
+ // Prefetch hints on windows:
+ // Using a different prefetch profile per process type will allow Windows
+ // to create separate pretetch settings for browser, renderer etc.
+ cmd_line->AppendLooseValue(StringPrintf(L"/prefetch:%d", type));
+
+ if (!in_sandbox) {
+ base::LaunchApp(*cmd_line, false, false, &process);
+ return process;
+ }
+
+ sandbox::ResultCode result;
+ PROCESS_INFORMATION target = {0};
+ sandbox::TargetPolicy* policy = g_broker_services->CreatePolicy();
+
+ bool on_sandbox_desktop = false;
+ if (type == ChildProcessInfo::PLUGIN_PROCESS) {
+ if (!AddPolicyForPlugin(cmd_line, policy))
+ return 0;
+ } else {
+ AddPolicyForRenderer(policy, &on_sandbox_desktop);
+
+ if (type_str != switches::kRendererProcess) {
+ // Hack for Google Desktop crash. Trick GD into not injecting its DLL into
+ // this subprocess. See
+ // http://code.google.com/p/chromium/issues/detail?id=25580
+ cmd_line->AppendSwitchWithValue("ignored", " --type=renderer ");
+ }
+ }
+
+ if (!exposed_dir.empty()) {
+ result = policy->AddRule(sandbox::TargetPolicy::SUBSYS_FILES,
+ sandbox::TargetPolicy::FILES_ALLOW_ANY,
+ exposed_dir.ToWStringHack().c_str());
+ if (result != sandbox::SBOX_ALL_OK)
+ return 0;
+
+ FilePath exposed_files = exposed_dir.AppendASCII("*");
+ result = policy->AddRule(sandbox::TargetPolicy::SUBSYS_FILES,
+ sandbox::TargetPolicy::FILES_ALLOW_ANY,
+ exposed_files.ToWStringHack().c_str());
+ if (result != sandbox::SBOX_ALL_OK)
+ return 0;
+ }
+
+ if (!AddGenericPolicy(policy)) {
+ NOTREACHED();
+ return 0;
+ }
+
+ result = g_broker_services->SpawnTarget(
+ cmd_line->program().c_str(),
+ cmd_line->command_line_string().c_str(),
+ policy, &target);
+ policy->Release();
+
+ if (sandbox::SBOX_ALL_OK != result)
+ return 0;
+
+ ResumeThread(target.hThread);
+ CloseHandle(target.hThread);
+ process = target.hProcess;
+
+ // Help the process a little. It can't start the debugger by itself if
+ // the process is in a sandbox.
+ if (child_needs_help)
+ DebugUtil::SpawnDebuggerOnProcess(target.dwProcessId);
+
+ return process;
+}
+
+} // namespace sandbox
diff --git a/chrome/common/sandbox_policy.h b/chrome/common/sandbox_policy.h
new file mode 100644
index 0000000..46ab7bf
--- /dev/null
+++ b/chrome/common/sandbox_policy.h
@@ -0,0 +1,26 @@
+// Copyright (c) 2006-2008 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_COMMON_SANDBOX_POLICY_H_
+#define CHROME_COMMON_SANDBOX_POLICY_H_
+
+#include "base/process.h"
+#include "base/file_path.h"
+
+class CommandLine;
+
+namespace sandbox {
+
+class BrokerServices;
+
+void InitBrokerServices(sandbox::BrokerServices* broker_services);
+
+// Starts a sandboxed process with the given directory unsandboxed
+// and returns a handle to it.
+base::ProcessHandle StartProcessWithAccess(CommandLine* cmd_line,
+ const FilePath& exposed_dir);
+
+} // namespace sandbox
+
+#endif // CHROME_COMMON_SANDBOX_POLICY_H_
diff --git a/chrome/common/security_filter_peer.cc b/chrome/common/security_filter_peer.cc
new file mode 100644
index 0000000..6448d20
--- /dev/null
+++ b/chrome/common/security_filter_peer.cc
@@ -0,0 +1,210 @@
+// Copyright (c) 2010 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/common/security_filter_peer.h"
+
+#include "app/l10n_util.h"
+#include "grit/generated_resources.h"
+#include "net/base/net_errors.h"
+#include "net/http/http_response_headers.h"
+
+SecurityFilterPeer::SecurityFilterPeer(
+ webkit_glue::ResourceLoaderBridge* resource_loader_bridge,
+ webkit_glue::ResourceLoaderBridge::Peer* peer)
+ : original_peer_(peer),
+ resource_loader_bridge_(resource_loader_bridge) {
+}
+
+SecurityFilterPeer::~SecurityFilterPeer() {
+}
+
+// static
+SecurityFilterPeer*
+ SecurityFilterPeer::CreateSecurityFilterPeerForDeniedRequest(
+ ResourceType::Type resource_type,
+ webkit_glue::ResourceLoaderBridge::Peer* peer,
+ int os_error) {
+ // Create a filter for SSL and CERT errors.
+ switch (os_error) {
+ case net::ERR_SSL_PROTOCOL_ERROR:
+ case net::ERR_CERT_COMMON_NAME_INVALID:
+ case net::ERR_CERT_DATE_INVALID:
+ case net::ERR_CERT_AUTHORITY_INVALID:
+ case net::ERR_CERT_CONTAINS_ERRORS:
+ case net::ERR_CERT_NO_REVOCATION_MECHANISM:
+ case net::ERR_CERT_UNABLE_TO_CHECK_REVOCATION:
+ case net::ERR_CERT_REVOKED:
+ case net::ERR_CERT_INVALID:
+ case net::ERR_CERT_WEAK_SIGNATURE_ALGORITHM:
+ case net::ERR_INSECURE_RESPONSE:
+ if (ResourceType::IsFrame(resource_type))
+ return CreateSecurityFilterPeerForFrame(peer, os_error);
+ // Any other content is entirely filtered-out.
+ return new ReplaceContentPeer(NULL, peer, std::string(), std::string());
+ default:
+ // For other errors, we use our normal error handling.
+ return NULL;
+ }
+}
+
+// static
+SecurityFilterPeer* SecurityFilterPeer::CreateSecurityFilterPeerForFrame(
+ webkit_glue::ResourceLoaderBridge::Peer* peer, int os_error) {
+ // TODO(jcampan): use a different message when getting a phishing/malware
+ // error.
+ std::string html = StringPrintf(
+ "<html><meta charset='UTF-8'>"
+ "<body style='background-color:#990000;color:white;'>"
+ "%s</body></html>",
+ l10n_util::GetStringUTF8(IDS_UNSAFE_FRAME_MESSAGE).c_str());
+ return new ReplaceContentPeer(NULL, peer, "text/html", html);
+}
+
+void SecurityFilterPeer::OnUploadProgress(uint64 position, uint64 size) {
+ original_peer_->OnUploadProgress(position, size);
+}
+
+bool SecurityFilterPeer::OnReceivedRedirect(
+ const GURL& new_url,
+ const webkit_glue::ResourceLoaderBridge::ResponseInfo& info,
+ bool* has_new_first_party_for_cookies,
+ GURL* new_first_party_for_cookies) {
+ NOTREACHED();
+ return false;
+}
+
+void SecurityFilterPeer::OnReceivedResponse(
+ const webkit_glue::ResourceLoaderBridge::ResponseInfo& info,
+ bool content_filtered) {
+ NOTREACHED();
+}
+
+void SecurityFilterPeer::OnReceivedData(const char* data, int len) {
+ NOTREACHED();
+}
+
+void SecurityFilterPeer::OnCompletedRequest(const URLRequestStatus& status,
+ const std::string& security_info) {
+ NOTREACHED();
+}
+
+GURL SecurityFilterPeer::GetURLForDebugging() const {
+ return original_peer_->GetURLForDebugging();
+}
+
+// static
+void ProcessResponseInfo(
+ const webkit_glue::ResourceLoaderBridge::ResponseInfo& info_in,
+ webkit_glue::ResourceLoaderBridge::ResponseInfo* info_out,
+ const std::string& mime_type) {
+ DCHECK(info_out);
+ *info_out = info_in;
+ info_out->mime_type = mime_type;
+ // Let's create our own HTTP headers.
+ std::string raw_headers;
+ raw_headers.append("HTTP/1.1 200 OK");
+ raw_headers.push_back('\0');
+ // Don't cache the data we are serving, it is not the real data for that URL
+ // (if the filtered resource were to make it into the WebCore cache, then the
+ // same URL loaded in a safe scenario would still return the filtered
+ // resource).
+ raw_headers.append("cache-control: no-cache");
+ raw_headers.push_back('\0');
+ if (!mime_type.empty()) {
+ raw_headers.append("content-type: ");
+ raw_headers.append(mime_type);
+ raw_headers.push_back('\0');
+ }
+ raw_headers.push_back('\0');
+ net::HttpResponseHeaders* new_headers =
+ new net::HttpResponseHeaders(raw_headers);
+ info_out->headers = new_headers;
+}
+
+////////////////////////////////////////////////////////////////////////////////
+// BufferedPeer
+
+BufferedPeer::BufferedPeer(
+ webkit_glue::ResourceLoaderBridge* resource_loader_bridge,
+ webkit_glue::ResourceLoaderBridge::Peer* peer,
+ const std::string& mime_type)
+ : SecurityFilterPeer(resource_loader_bridge, peer),
+ mime_type_(mime_type) {
+}
+
+BufferedPeer::~BufferedPeer() {
+}
+
+void BufferedPeer::OnReceivedResponse(
+ const webkit_glue::ResourceLoaderBridge::ResponseInfo& info,
+ bool response_filtered) {
+ ProcessResponseInfo(info, &response_info_, mime_type_);
+}
+
+void BufferedPeer::OnReceivedData(const char* data, int len) {
+ data_.append(data, len);
+}
+
+void BufferedPeer::OnCompletedRequest(const URLRequestStatus& status,
+ const std::string& security_info) {
+ // Make sure we delete ourselves at the end of this call.
+ scoped_ptr<BufferedPeer> this_deleter(this);
+
+ // Give sub-classes a chance at altering the data.
+ if (status.status() != URLRequestStatus::SUCCESS || !DataReady()) {
+ // Pretend we failed to load the resource.
+ original_peer_->OnReceivedResponse(response_info_, true);
+ URLRequestStatus status(URLRequestStatus::CANCELED, net::ERR_ABORTED);
+ original_peer_->OnCompletedRequest(status, security_info);
+ return;
+ }
+
+ original_peer_->OnReceivedResponse(response_info_, true);
+ if (!data_.empty())
+ original_peer_->OnReceivedData(data_.data(),
+ static_cast<int>(data_.size()));
+ original_peer_->OnCompletedRequest(status, security_info);
+}
+
+////////////////////////////////////////////////////////////////////////////////
+// ReplaceContentPeer
+
+ReplaceContentPeer::ReplaceContentPeer(
+ webkit_glue::ResourceLoaderBridge* resource_loader_bridge,
+ webkit_glue::ResourceLoaderBridge::Peer* peer,
+ const std::string& mime_type,
+ const std::string& data)
+ : SecurityFilterPeer(resource_loader_bridge, peer),
+ mime_type_(mime_type),
+ data_(data) {
+}
+
+ReplaceContentPeer::~ReplaceContentPeer() {
+}
+
+void ReplaceContentPeer::OnReceivedResponse(
+ const webkit_glue::ResourceLoaderBridge::ResponseInfo& info,
+ bool content_filtered) {
+ // Ignore this, we'll serve some alternate content in OnCompletedRequest.
+}
+
+void ReplaceContentPeer::OnReceivedData(const char* data, int len) {
+ // Ignore this, we'll serve some alternate content in OnCompletedRequest.
+}
+
+void ReplaceContentPeer::OnCompletedRequest(const URLRequestStatus& status,
+ const std::string& security_info) {
+ webkit_glue::ResourceLoaderBridge::ResponseInfo info;
+ ProcessResponseInfo(info, &info, mime_type_);
+ info.security_info = security_info;
+ info.content_length = static_cast<int>(data_.size());
+ original_peer_->OnReceivedResponse(info, true);
+ if (!data_.empty())
+ original_peer_->OnReceivedData(data_.data(),
+ static_cast<int>(data_.size()));
+ original_peer_->OnCompletedRequest(URLRequestStatus(), security_info);
+
+ // The request processing is complete, we must delete ourselves.
+ delete this;
+}
diff --git a/chrome/common/security_filter_peer.h b/chrome/common/security_filter_peer.h
new file mode 100644
index 0000000..4a44be3
--- /dev/null
+++ b/chrome/common/security_filter_peer.h
@@ -0,0 +1,122 @@
+// Copyright (c) 2010 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_COMMON_SECURITY_FILTER_PEER_H__
+#define CHROME_COMMON_SECURITY_FILTER_PEER_H__
+
+#include "webkit/glue/resource_loader_bridge.h"
+
+// The SecurityFilterPeer is a proxy to a
+// webkit_glue::ResourceLoaderBridge::Peer instance. It is used to pre-process
+// unsafe resources (such as mixed-content resource).
+// Call the factory method CreateSecurityFilterPeer() to obtain an instance of
+// SecurityFilterPeer based on the original Peer.
+// NOTE: subclasses should insure they delete themselves at the end of the
+// OnReceiveComplete call.
+class SecurityFilterPeer : public webkit_glue::ResourceLoaderBridge::Peer {
+ public:
+ virtual ~SecurityFilterPeer();
+
+ static SecurityFilterPeer* CreateSecurityFilterPeerForDeniedRequest(
+ ResourceType::Type resource_type,
+ webkit_glue::ResourceLoaderBridge::Peer* peer,
+ int os_error);
+
+ static SecurityFilterPeer* CreateSecurityFilterPeerForFrame(
+ webkit_glue::ResourceLoaderBridge::Peer* peer,
+ int os_error);
+
+ // ResourceLoaderBridge::Peer methods.
+ virtual void OnUploadProgress(uint64 position, uint64 size);
+ virtual bool OnReceivedRedirect(
+ const GURL& new_url,
+ const webkit_glue::ResourceLoaderBridge::ResponseInfo& info,
+ bool* has_new_first_party_for_cookies,
+ GURL* new_first_party_for_cookies);
+ virtual void OnReceivedResponse(
+ const webkit_glue::ResourceLoaderBridge::ResponseInfo& info,
+ bool content_filtered);
+ virtual void OnReceivedData(const char* data, int len);
+ virtual void OnCompletedRequest(const URLRequestStatus& status,
+ const std::string& security_info);
+ virtual GURL GetURLForDebugging() const;
+
+ protected:
+ SecurityFilterPeer(webkit_glue::ResourceLoaderBridge* resource_loader_bridge,
+ webkit_glue::ResourceLoaderBridge::Peer* peer);
+
+ webkit_glue::ResourceLoaderBridge::Peer* original_peer_;
+ webkit_glue::ResourceLoaderBridge* resource_loader_bridge_;
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(SecurityFilterPeer);
+};
+
+// The BufferedPeer reads all the data of the request into an internal buffer.
+// Subclasses should implement DataReady() to process the data as necessary.
+class BufferedPeer : public SecurityFilterPeer {
+ public:
+ BufferedPeer(webkit_glue::ResourceLoaderBridge* resource_loader_bridge,
+ webkit_glue::ResourceLoaderBridge::Peer* peer,
+ const std::string& mime_type);
+ virtual ~BufferedPeer();
+
+ // ResourceLoaderBridge::Peer Implementation.
+ virtual void OnReceivedResponse(
+ const webkit_glue::ResourceLoaderBridge::ResponseInfo& info,
+ bool content_filtered);
+ virtual void OnReceivedData(const char* data, int len);
+ virtual void OnCompletedRequest(const URLRequestStatus& status,
+ const std::string& security_info);
+
+ protected:
+ // Invoked when the entire request has been processed before the data is sent
+ // to the original peer, giving an opportunity to subclasses to process the
+ // data in data_. If this method returns true, the data is fed to the
+ // original peer, if it returns false, an error is sent instead.
+ virtual bool DataReady() = 0;
+
+ webkit_glue::ResourceLoaderBridge::ResponseInfo response_info_;
+ std::string data_;
+
+ private:
+ std::string mime_type_;
+
+ DISALLOW_COPY_AND_ASSIGN(BufferedPeer);
+};
+
+// The ReplaceContentPeer cancels the request and serves the provided data as
+// content instead.
+// TODO(jcampan): we do not as of now cancel the request, as we do not have
+// access to the resource_loader_bridge in the SecurityFilterPeer factory
+// method. For now the resource is still being fetched, but ignored, as once
+// we have provided the replacement content, the associated pending request
+// in ResourceDispatcher is removed and further OnReceived* notifications are
+// ignored.
+class ReplaceContentPeer : public SecurityFilterPeer {
+ public:
+ ReplaceContentPeer(webkit_glue::ResourceLoaderBridge* resource_loader_bridge,
+ webkit_glue::ResourceLoaderBridge::Peer* peer,
+ const std::string& mime_type,
+ const std::string& data);
+ virtual ~ReplaceContentPeer();
+
+ // ResourceLoaderBridge::Peer Implementation.
+ virtual void OnReceivedResponse(
+ const webkit_glue::ResourceLoaderBridge::ResponseInfo& info,
+ bool content_filtered);
+ void OnReceivedData(const char* data, int len);
+ void OnCompletedRequest(const URLRequestStatus& status,
+ const std::string& security_info);
+
+ private:
+ webkit_glue::ResourceLoaderBridge::ResponseInfo response_info_;
+ std::string mime_type_;
+ std::string data_;
+
+ DISALLOW_COPY_AND_ASSIGN(ReplaceContentPeer);
+};
+
+#endif // CHROME_COMMON_SECURITY_FILTER_PEER_H__
diff --git a/chrome/common/serialized_script_value.cc b/chrome/common/serialized_script_value.cc
new file mode 100644
index 0000000..095f4e6
--- /dev/null
+++ b/chrome/common/serialized_script_value.cc
@@ -0,0 +1,37 @@
+// Copyright (c) 2010 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/common/serialized_script_value.h"
+
+#include "third_party/WebKit/WebKit/chromium/public/WebString.h"
+
+using WebKit::WebSerializedScriptValue;
+
+SerializedScriptValue::SerializedScriptValue()
+ : is_null_(true),
+ is_invalid_(false) {
+}
+
+SerializedScriptValue::SerializedScriptValue(
+ bool is_null, bool is_invalid, const string16& data)
+ : is_null_(is_null),
+ is_invalid_(is_invalid),
+ data_(data) {
+}
+
+SerializedScriptValue::SerializedScriptValue(
+ const WebSerializedScriptValue& value)
+ : is_null_(value.isNull()),
+ is_invalid_(value.isNull() ? false : value.toString().isNull()),
+ data_(value.isNull() ? string16()
+ : static_cast<string16>(value.toString())) {
+}
+
+SerializedScriptValue::operator WebSerializedScriptValue() const {
+ if (is_null_)
+ return WebSerializedScriptValue();
+ if (is_invalid_)
+ return WebSerializedScriptValue::createInvalid();
+ return WebSerializedScriptValue::fromString(data_);
+}
diff --git a/chrome/common/serialized_script_value.h b/chrome/common/serialized_script_value.h
new file mode 100644
index 0000000..e464134
--- /dev/null
+++ b/chrome/common/serialized_script_value.h
@@ -0,0 +1,34 @@
+// Copyright (c) 2010 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_COMMON_SERIALIZED_SCRIPT_VALUE_H_
+#define CHROME_COMMON_SERIALIZED_SCRIPT_VALUE_H_
+
+#include "base/string16.h"
+#include "third_party/WebKit/WebKit/chromium/public/WebSerializedScriptValue.h"
+
+class SerializedScriptValue {
+ public:
+ SerializedScriptValue();
+ SerializedScriptValue(bool is_null, bool is_invalid, const string16& data);
+ explicit SerializedScriptValue(const WebKit::WebSerializedScriptValue& value);
+
+ void set_is_null(bool is_null) { is_null_ = is_null; }
+ bool is_null() const { return is_null_; }
+
+ void set_is_invalid(bool is_invalid) { is_invalid_ = is_invalid; }
+ bool is_invalid() const { return is_invalid_; }
+
+ void set_data(const string16& data) { data_ = data; }
+ const string16& data() const { return data_; }
+
+ operator WebKit::WebSerializedScriptValue() const;
+
+ private:
+ bool is_null_; // Is this null? If so, none of the other properties are valid.
+ bool is_invalid_; // Is data_ valid?
+ string16 data_; // The wire string format of the serialized script value.
+};
+
+#endif // CHROME_COMMON_SERIALIZED_SCRIPT_VALUE_H_
diff --git a/chrome/common/socket_stream_dispatcher.cc b/chrome/common/socket_stream_dispatcher.cc
new file mode 100644
index 0000000..97aed21
--- /dev/null
+++ b/chrome/common/socket_stream_dispatcher.cc
@@ -0,0 +1,215 @@
+// Copyright (c) 2009 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/common/socket_stream_dispatcher.h"
+
+#include <vector>
+
+#include "base/id_map.h"
+#include "base/ref_counted.h"
+#include "chrome/common/child_thread.h"
+#include "chrome/common/render_messages.h"
+#include "chrome/common/net/socket_stream.h"
+#include "googleurl/src/gurl.h"
+#include "webkit/glue/websocketstreamhandle_bridge.h"
+#include "webkit/glue/websocketstreamhandle_delegate.h"
+
+// IPCWebSocketStreamHandleBridge is owned by each SocketStreamHandle.
+// It communicates with the main browser process via SocketStreamDispatcher.
+class IPCWebSocketStreamHandleBridge
+ : public webkit_glue::WebSocketStreamHandleBridge {
+ public:
+ IPCWebSocketStreamHandleBridge(
+ ChildThread* child_thread,
+ WebKit::WebSocketStreamHandle* handle,
+ webkit_glue::WebSocketStreamHandleDelegate* delegate)
+ : socket_id_(chrome_common_net::kNoSocketId),
+ child_thread_(child_thread),
+ handle_(handle),
+ delegate_(delegate) {}
+
+ // Returns the handle having given id or NULL if there is no such handle.
+ static IPCWebSocketStreamHandleBridge* FromSocketId(int id);
+
+ // webkit_glue::WebSocketStreamHandleBridge methods.
+ virtual void Connect(const GURL& url);
+ virtual bool Send(const std::vector<char>& data);
+ virtual void Close();
+
+ // Called by SocketStreamDispatcher.
+ void OnConnected(int max_amount_send_allowed);
+ void OnSentData(int amount_sent);
+ void OnReceivedData(const std::vector<char>& data);
+ void OnClosed();
+
+ private:
+ virtual ~IPCWebSocketStreamHandleBridge();
+
+ void DoConnect(const GURL& url);
+ int socket_id_;
+
+ ChildThread* child_thread_;
+ WebKit::WebSocketStreamHandle* handle_;
+ webkit_glue::WebSocketStreamHandleDelegate* delegate_;
+
+ static IDMap<IPCWebSocketStreamHandleBridge> all_bridges;
+};
+
+IDMap<IPCWebSocketStreamHandleBridge>
+IPCWebSocketStreamHandleBridge::all_bridges;
+
+/* static */
+IPCWebSocketStreamHandleBridge* IPCWebSocketStreamHandleBridge::FromSocketId(
+ int id) {
+ return all_bridges.Lookup(id);
+}
+
+IPCWebSocketStreamHandleBridge::~IPCWebSocketStreamHandleBridge() {
+ DLOG(INFO) << "IPCWebSocketStreamHandleBridge destructor socket_id="
+ << socket_id_;
+ if (socket_id_ != chrome_common_net::kNoSocketId) {
+ child_thread_->Send(new ViewHostMsg_Close(socket_id_));
+ socket_id_ = chrome_common_net::kNoSocketId;
+ }
+}
+
+void IPCWebSocketStreamHandleBridge::Connect(const GURL& url) {
+ DCHECK(child_thread_);
+ DLOG(INFO) << "Connect url=" << url;
+ child_thread_->message_loop()->PostTask(
+ FROM_HERE,
+ NewRunnableMethod(this, &IPCWebSocketStreamHandleBridge::DoConnect,
+ url));
+}
+
+bool IPCWebSocketStreamHandleBridge::Send(
+ const std::vector<char>& data) {
+ DLOG(INFO) << "Send data.size=" << data.size();
+ if (child_thread_->Send(
+ new ViewHostMsg_SocketStream_SendData(socket_id_, data))) {
+ if (delegate_)
+ delegate_->WillSendData(handle_, &data[0], data.size());
+ return true;
+ }
+ return false;
+}
+
+void IPCWebSocketStreamHandleBridge::Close() {
+ DLOG(INFO) << "Close socket_id" << socket_id_;
+ child_thread_->Send(new ViewHostMsg_SocketStream_Close(socket_id_));
+}
+
+void IPCWebSocketStreamHandleBridge::OnConnected(int max_pending_send_allowed) {
+ DLOG(INFO) << "IPCWebSocketStreamHandleBridge::OnConnected socket_id="
+ << socket_id_;
+ if (delegate_)
+ delegate_->DidOpenStream(handle_, max_pending_send_allowed);
+}
+
+void IPCWebSocketStreamHandleBridge::OnSentData(int amount_sent) {
+ if (delegate_)
+ delegate_->DidSendData(handle_, amount_sent);
+}
+
+void IPCWebSocketStreamHandleBridge::OnReceivedData(
+ const std::vector<char>& data) {
+ if (delegate_)
+ delegate_->DidReceiveData(handle_, &data[0], data.size());
+}
+
+void IPCWebSocketStreamHandleBridge::OnClosed() {
+ DLOG(INFO) << "IPCWebSocketStreamHandleBridge::OnClosed";
+ if (socket_id_ != chrome_common_net::kNoSocketId) {
+ all_bridges.Remove(socket_id_);
+ socket_id_ = chrome_common_net::kNoSocketId;
+ }
+ if (delegate_) {
+ delegate_->DidClose(handle_);
+ }
+ delegate_ = NULL;
+ Release();
+}
+
+void IPCWebSocketStreamHandleBridge::DoConnect(const GURL& url) {
+ DCHECK(child_thread_);
+ DCHECK_EQ(socket_id_, chrome_common_net::kNoSocketId);
+ if (delegate_)
+ delegate_->WillOpenStream(handle_, url);
+
+ socket_id_ = all_bridges.Add(this);
+ DCHECK_NE(socket_id_, chrome_common_net::kNoSocketId);
+ if (child_thread_->Send(
+ new ViewHostMsg_SocketStream_Connect(url, socket_id_))) {
+ DLOG(INFO) << "Connect socket_id=" << socket_id_;
+ AddRef(); // Released in OnClosed().
+ // TODO(ukai): timeout to OnConnected.
+ } else {
+ LOG(ERROR) << "IPC SocketStream_Connect failed.";
+ OnClosed();
+ }
+}
+
+SocketStreamDispatcher::SocketStreamDispatcher() {
+}
+
+/* static */
+webkit_glue::WebSocketStreamHandleBridge*
+SocketStreamDispatcher::CreateBridge(
+ WebKit::WebSocketStreamHandle* handle,
+ webkit_glue::WebSocketStreamHandleDelegate* delegate) {
+ return new IPCWebSocketStreamHandleBridge(
+ ChildThread::current(), handle, delegate);
+}
+
+bool SocketStreamDispatcher::OnMessageReceived(const IPC::Message& msg) {
+ bool handled = true;
+ IPC_BEGIN_MESSAGE_MAP(SocketStreamDispatcher, msg)
+ IPC_MESSAGE_HANDLER(ViewMsg_SocketStream_Connected, OnConnected)
+ IPC_MESSAGE_HANDLER(ViewMsg_SocketStream_SentData, OnSentData)
+ IPC_MESSAGE_HANDLER(ViewMsg_SocketStream_ReceivedData, OnReceivedData)
+ IPC_MESSAGE_HANDLER(ViewMsg_SocketStream_Closed, OnClosed)
+ IPC_MESSAGE_UNHANDLED(handled = false)
+ IPC_END_MESSAGE_MAP()
+ return handled;
+}
+
+void SocketStreamDispatcher::OnConnected(int socket_id,
+ int max_pending_send_allowed) {
+ DLOG(INFO) << "SocketStreamDispatcher::OnConnected socket_id=" << socket_id
+ << " max_pending_send_allowed=" << max_pending_send_allowed;
+ IPCWebSocketStreamHandleBridge* bridge =
+ IPCWebSocketStreamHandleBridge::FromSocketId(socket_id);
+ if (bridge)
+ bridge->OnConnected(max_pending_send_allowed);
+ else
+ DLOG(ERROR) << "No SocketStreamHandleBridge for socket_id=" << socket_id;
+}
+
+void SocketStreamDispatcher::OnSentData(int socket_id, int amount_sent) {
+ IPCWebSocketStreamHandleBridge* bridge =
+ IPCWebSocketStreamHandleBridge::FromSocketId(socket_id);
+ if (bridge)
+ bridge->OnSentData(amount_sent);
+ else
+ DLOG(ERROR) << "No SocketStreamHandleBridge for socket_id=" << socket_id;
+}
+
+void SocketStreamDispatcher::OnReceivedData(
+ int socket_id, const std::vector<char>& data) {
+ IPCWebSocketStreamHandleBridge* bridge =
+ IPCWebSocketStreamHandleBridge::FromSocketId(socket_id);
+ if (bridge)
+ bridge->OnReceivedData(data);
+ else
+ DLOG(ERROR) << "No SocketStreamHandleBridge for socket_id=" << socket_id;
+}
+
+void SocketStreamDispatcher::OnClosed(int socket_id) {
+ IPCWebSocketStreamHandleBridge* bridge =
+ IPCWebSocketStreamHandleBridge::FromSocketId(socket_id);
+ if (bridge)
+ bridge->OnClosed();
+ else
+ DLOG(ERROR) << "No SocketStreamHandleBridge for socket_id=" << socket_id;
+}
diff --git a/chrome/common/socket_stream_dispatcher.h b/chrome/common/socket_stream_dispatcher.h
new file mode 100644
index 0000000..8e3bbe4
--- /dev/null
+++ b/chrome/common/socket_stream_dispatcher.h
@@ -0,0 +1,38 @@
+// Copyright (c) 2009 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_COMMON_SOCKET_STREAM_DISPATCHER_H_
+#define CHROME_COMMON_SOCKET_STREAM_DISPATCHER_H_
+
+#include <vector>
+
+#include "base/basictypes.h"
+#include "ipc/ipc_channel.h"
+#include "ipc/ipc_message.h"
+#include "webkit/glue/websocketstreamhandle_bridge.h"
+
+// Dispatches socket stream related messages sent to a child process from the
+// main browser process. There is one instance per child process. Messages
+// are dispatched on the main child thread. The RenderThread class
+// creates an instance of SocketStreamDispatcher and delegates calls to it.
+class SocketStreamDispatcher {
+ public:
+ SocketStreamDispatcher();
+ ~SocketStreamDispatcher() {}
+
+ static webkit_glue::WebSocketStreamHandleBridge* CreateBridge(
+ WebKit::WebSocketStreamHandle* handle,
+ webkit_glue::WebSocketStreamHandleDelegate* delegate);
+ bool OnMessageReceived(const IPC::Message& msg);
+
+ private:
+ void OnConnected(int socket_id, int max_amount_send_allowed);
+ void OnSentData(int socket_id, int amount_sent);
+ void OnReceivedData(int socket_id, const std::vector<char>& data);
+ void OnClosed(int socket_id);
+
+ DISALLOW_COPY_AND_ASSIGN(SocketStreamDispatcher);
+};
+
+#endif // CHROME_COMMON_SOCKET_STREAM_DISPATCHER_H_
diff --git a/chrome/common/socket_stream_dispatcher_dummy.cc b/chrome/common/socket_stream_dispatcher_dummy.cc
new file mode 100644
index 0000000..ef49285
--- /dev/null
+++ b/chrome/common/socket_stream_dispatcher_dummy.cc
@@ -0,0 +1,18 @@
+// Copyright (c) 2006-2008 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/common/socket_stream_dispatcher.h"
+
+#include "base/compiler_specific.h"
+
+// SocketStreamDispatcher ------------------------------------------------------
+
+SocketStreamDispatcher::SocketStreamDispatcher() {
+}
+
+// SocketStreamDispatcher implementation ---------------------------------------
+
+bool SocketStreamDispatcher::OnMessageReceived(const IPC::Message& message) {
+ return false;
+}
diff --git a/chrome/common/spellcheck_common.cc b/chrome/common/spellcheck_common.cc
new file mode 100644
index 0000000..d1abfa5
--- /dev/null
+++ b/chrome/common/spellcheck_common.cc
@@ -0,0 +1,179 @@
+// Copyright (c) 2009 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/common/spellcheck_common.h"
+
+#include "base/file_path.h"
+
+namespace SpellCheckCommon {
+
+static const struct {
+ // The language.
+ const char* language;
+
+ // The corresponding language and region, used by the dictionaries.
+ const char* language_region;
+} g_supported_spellchecker_languages[] = {
+ // Several languages are not to be included in the spellchecker list:
+ // th-TH, uk-UA
+ {"bg", "bg-BG"},
+ {"ca", "ca-ES"},
+ {"cs", "cs-CZ"},
+ {"da", "da-DK"},
+ {"de", "de-DE"},
+ {"el", "el-GR"},
+ {"en-AU", "en-AU"},
+ {"en-GB", "en-GB"},
+ {"en-US", "en-US"},
+ {"es", "es-ES"},
+ {"et", "et-EE"},
+ {"fr", "fr-FR"},
+ {"he", "he-IL"},
+ {"hi", "hi-IN"},
+ {"hr", "hr-HR"},
+ {"hu", "hu-HU"},
+ {"id", "id-ID"},
+ {"it", "it-IT"},
+ {"lt", "lt-LT"},
+ {"lv", "lv-LV"},
+ {"nb", "nb-NO"},
+ {"nl", "nl-NL"},
+ {"pl", "pl-PL"},
+ {"pt-BR", "pt-BR"},
+ {"pt-PT", "pt-PT"},
+ {"ro", "ro-RO"},
+ {"ru", "ru-RU"},
+ {"sk", "sk-SK"},
+ {"sl", "sl-SI"},
+ {"sv", "sv-SE"},
+ {"tr", "tr-TR"},
+ {"vi", "vi-VN"},
+};
+
+// This function returns the language-region version of language name.
+// e.g. returns hi-IN for hi.
+std::string GetSpellCheckLanguageRegion(const std::string& input_language) {
+ for (size_t i = 0; i < ARRAYSIZE_UNSAFE(g_supported_spellchecker_languages);
+ ++i) {
+ if (g_supported_spellchecker_languages[i].language == input_language) {
+ return std::string(
+ g_supported_spellchecker_languages[i].language_region);
+ }
+ }
+
+ return input_language;
+}
+
+FilePath GetVersionedFileName(const std::string& input_language,
+ const FilePath& dict_dir) {
+ // The default dictionary version is 1-2. These versions have been augmented
+ // with additional words found by the translation team.
+ static const char kDefaultVersionString[] = "-1-2";
+
+ // The following dictionaries have either not been augmented with additional
+ // words (version 1-1) or have new words, as well as an upgraded dictionary
+ // as of Feb 2009 (version 1-3).
+ static const struct {
+ // The language input.
+ const char* language;
+
+ // The corresponding version.
+ const char* version;
+ } special_version_string[] = {
+ {"en-AU", "-1-1"},
+ {"en-GB", "-1-1"},
+ {"es-ES", "-1-1"},
+ {"nl-NL", "-1-1"},
+ {"sv-SE", "-1-1"},
+ {"he-IL", "-1-1"},
+ {"el-GR", "-1-1"},
+ {"hi-IN", "-1-1"},
+ {"tr-TR", "-1-1"},
+ {"et-EE", "-1-1"},
+ {"fr-FR", "-2-0"}, // Hunspell fr(modern) 3.7 + Chromium delta.
+ {"lt-LT", "-1-3"},
+ {"pl-PL", "-1-3"},
+ {"hu-HU", "-2-0"},
+ {"ro-RO", "-2-0"},
+ {"ru-RU", "-2-0"},
+ {"bg-BG", "-2-0"},
+ };
+
+ // Generate the bdict file name using default version string or special
+ // version string, depending on the language.
+ std::string language = GetSpellCheckLanguageRegion(input_language);
+ std::string versioned_bdict_file_name(language + kDefaultVersionString +
+ ".bdic");
+ for (size_t i = 0; i < ARRAYSIZE_UNSAFE(special_version_string); ++i) {
+ if (language == special_version_string[i].language) {
+ versioned_bdict_file_name =
+ language + special_version_string[i].version + ".bdic";
+ break;
+ }
+ }
+
+ return dict_dir.AppendASCII(versioned_bdict_file_name);
+}
+
+std::string GetCorrespondingSpellCheckLanguage(const std::string& language) {
+ // Look for exact match in the Spell Check language list.
+ for (size_t i = 0; i < ARRAYSIZE_UNSAFE(g_supported_spellchecker_languages);
+ ++i) {
+ // First look for exact match in the language region of the list.
+ std::string spellcheck_language(
+ g_supported_spellchecker_languages[i].language);
+ if (spellcheck_language == language)
+ return language;
+
+ // Next, look for exact match in the language_region part of the list.
+ std::string spellcheck_language_region(
+ g_supported_spellchecker_languages[i].language_region);
+ if (spellcheck_language_region == language)
+ return g_supported_spellchecker_languages[i].language;
+ }
+
+ // Look for a match by comparing only language parts. All the 'en-RR'
+ // except for 'en-GB' exactly matched in the above loop, will match
+ // 'en-US'. This is not ideal because 'en-ZA', 'en-NZ' had
+ // better be matched with 'en-GB'. This does not handle cases like
+ // 'az-Latn-AZ' vs 'az-Arab-AZ', either, but we don't use 3-part
+ // locale ids with a script code in the middle, yet.
+ // TODO(jungshik): Add a better fallback.
+ std::string language_part(language, 0, language.find('-'));
+ for (size_t i = 0; i < ARRAYSIZE_UNSAFE(g_supported_spellchecker_languages);
+ ++i) {
+ std::string spellcheck_language(
+ g_supported_spellchecker_languages[i].language_region);
+ if (spellcheck_language.substr(0, spellcheck_language.find('-')) ==
+ language_part) {
+ return spellcheck_language;
+ }
+ }
+
+ // No match found - return blank.
+ return std::string();
+}
+
+
+void SpellCheckLanguages(std::vector<std::string>* languages) {
+ for (size_t i = 0; i < ARRAYSIZE_UNSAFE(g_supported_spellchecker_languages);
+ ++i) {
+ languages->push_back(g_supported_spellchecker_languages[i].language);
+ }
+}
+
+
+std::string GetLanguageFromLanguageRegion(std::string input_language) {
+ for (size_t i = 0; i < ARRAYSIZE_UNSAFE(g_supported_spellchecker_languages);
+ ++i) {
+ std::string language(
+ g_supported_spellchecker_languages[i].language_region);
+ if (language == input_language)
+ return std::string(g_supported_spellchecker_languages[i].language);
+ }
+
+ return input_language;
+}
+
+} // namespace SpellCheckCommon
diff --git a/chrome/common/spellcheck_common.h b/chrome/common/spellcheck_common.h
new file mode 100644
index 0000000..5c2569e
--- /dev/null
+++ b/chrome/common/spellcheck_common.h
@@ -0,0 +1,36 @@
+// Copyright (c) 2009 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_COMMON_SPELLCHECK_COMMON_H_
+#define CHROME_COMMON_SPELLCHECK_COMMON_H_
+
+#include <string>
+#include <vector>
+
+class FilePath;
+
+namespace SpellCheckCommon {
+
+// Max number of dictionary suggestions.
+static const int kMaxSuggestions = 5;
+
+static const int kMaxAutoCorrectWordSize = 8;
+
+FilePath GetVersionedFileName(const std::string& input_language,
+ const FilePath& dict_dir);
+
+std::string GetCorrespondingSpellCheckLanguage(const std::string& language);
+
+// Get SpellChecker supported languages.
+void SpellCheckLanguages(std::vector<std::string>* languages);
+
+
+// This function returns ll (language code) from ll-RR where 'RR' (region
+// code) is redundant. However, if the region code matters, it's preserved.
+// That is, it returns 'hi' and 'en-GB' for 'hi-IN' and 'en-GB' respectively.
+std::string GetLanguageFromLanguageRegion(std::string input_language);
+
+} // namespace SpellCheckCommon
+
+#endif // CHROME_COMMON_SPELLCHECK_COMMON_H_
diff --git a/chrome/common/sqlite_compiled_statement.cc b/chrome/common/sqlite_compiled_statement.cc
new file mode 100644
index 0000000..f54182a
--- /dev/null
+++ b/chrome/common/sqlite_compiled_statement.cc
@@ -0,0 +1,85 @@
+// Copyright (c) 2010 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/common/sqlite_compiled_statement.h"
+
+#include "base/logging.h"
+#include "base/stl_util-inl.h"
+#include "chrome/common/sqlite_utils.h"
+#include "third_party/sqlite/preprocessed/sqlite3.h"
+
+// SqliteStatementCache -------------------------------------------------------
+
+SqliteStatementCache::~SqliteStatementCache() {
+ STLDeleteContainerPairSecondPointers(statements_.begin(), statements_.end());
+ statements_.clear();
+ db_ = NULL;
+}
+
+void SqliteStatementCache::set_db(sqlite3* db) {
+ DCHECK(!db_) << "Setting the database twice";
+ db_ = db;
+}
+
+SQLStatement* SqliteStatementCache::InternalGetStatement(const char* func_name,
+ int func_number,
+ const char* sql) {
+ FuncID id;
+ id.name = func_name;
+ id.number = func_number;
+
+ StatementMap::const_iterator found = statements_.find(id);
+ if (found != statements_.end())
+ return found->second;
+
+ if (!sql)
+ return NULL; // Don't create a new statement when we were not given SQL.
+
+ // Create a new statement.
+ SQLStatement* statement = new SQLStatement();
+ if (statement->prepare(db_, sql) != SQLITE_OK) {
+ const char* err_msg = sqlite3_errmsg(db_);
+ NOTREACHED() << "SQL preparation error for: " << err_msg;
+ return NULL;
+ }
+
+ statements_[id] = statement;
+ return statement;
+}
+
+bool SqliteStatementCache::FuncID::operator<(const FuncID& other) const {
+ // Compare numbers first since they are faster than strings and they are
+ // almost always unique.
+ if (number != other.number)
+ return number < other.number;
+ return name < other.name;
+}
+
+// SqliteCompiledStatement ----------------------------------------------------
+
+SqliteCompiledStatement::SqliteCompiledStatement(const char* func_name,
+ int func_number,
+ SqliteStatementCache& cache,
+ const char* sql) {
+ statement_ = cache.GetStatement(func_name, func_number, sql);
+}
+
+SqliteCompiledStatement::~SqliteCompiledStatement() {
+ // Reset the statement so that subsequent callers don't get crap in it.
+ if (statement_)
+ statement_->reset();
+}
+
+SQLStatement& SqliteCompiledStatement::operator*() {
+ DCHECK(statement_) << "Should check is_valid() before using the statement.";
+ return *statement_;
+}
+SQLStatement* SqliteCompiledStatement::operator->() {
+ DCHECK(statement_) << "Should check is_valid() before using the statement.";
+ return statement_;
+}
+SQLStatement* SqliteCompiledStatement::statement() {
+ DCHECK(statement_) << "Should check is_valid() before using the statement.";
+ return statement_;
+}
diff --git a/chrome/common/sqlite_compiled_statement.h b/chrome/common/sqlite_compiled_statement.h
new file mode 100644
index 0000000..01b7f1e
--- /dev/null
+++ b/chrome/common/sqlite_compiled_statement.h
@@ -0,0 +1,135 @@
+// Copyright (c) 2006-2008 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_COMMON_SQLITE_COMPILED_STATEMENT_H_
+#define CHROME_COMMON_SQLITE_COMPILED_STATEMENT_H_
+
+#include <map>
+#include <string>
+
+#include "base/basictypes.h"
+
+struct sqlite3;
+class SQLStatement;
+
+// Stores a list of precompiled sql statements for a database. Each statement
+// is given a unique name by the caller.
+//
+// Note: see comments on descructor.
+class SqliteStatementCache {
+ public:
+ // You must call set_db before anything else if you use this constructor.
+ SqliteStatementCache() : db_(NULL) {
+ }
+
+ explicit SqliteStatementCache(sqlite3* db) : db_(db) {
+ }
+
+ // This object must be deleted before the sqlite connection it is associated
+ // with. Otherwise, sqlite seems to keep the file open because there are open
+ // statements.
+ ~SqliteStatementCache();
+
+ void set_db(sqlite3* db);
+
+ // Creates or retrieves a cached SQL statement identified by the given
+ // (name, number) pair.
+ //
+ // The name and number can be anything the caller wants, but must uniquely
+ // identify the SQL. The caller must ensure that every call with the same
+ // number and name has the same SQL.
+ //
+ // In practice the number and name is supposed to be a file and line number.
+ // (See the SQLITE_UNIQUE_STATEMENT macro below.) Recommended practice is to
+ // use 0 for the function number if you are not using this scheme, and just
+ // use a name you like.
+ //
+ // On error, NULL is returned. Otherwise, the statement for the given SQL is
+ // returned. This pointer is cached and owned by this class.
+ //
+ // The caller should not cache this value since it may be used by others.
+ // The caller should reset the statement when it is complete so that
+ // subsequent callers do not get bound stuff.
+ SQLStatement* GetStatement(const char* func_name,
+ int func_number,
+ const char* sql) {
+ return InternalGetStatement(func_name, func_number, sql);
+ }
+
+ // Returns the cached statement if it has already been created, or NULL if it
+ // has not.
+ SQLStatement* GetExistingStatement(const char* func_name,
+ int func_number) {
+ return InternalGetStatement(func_name, func_number, NULL);
+ }
+
+ private:
+ // The key used for precompiled function lookup.
+ struct FuncID {
+ int number;
+ std::string name;
+
+ // Used as a key in the map below, so we need this comparator.
+ bool operator<(const FuncID& other) const;
+ };
+
+ // Backend for GetStatement and GetExistingStatement. If sql is NULL, we will
+ // only look for an existing statement and return NULL if there is not a
+ // matching one. If it is non-NULL, we will create it if it doesn't exist.
+ SQLStatement* InternalGetStatement(const char* func_name,
+ int func_number,
+ const char* sql);
+
+ sqlite3* db_;
+
+ // This object owns the statement pointers, which it must manually free.
+ typedef std::map<FuncID, SQLStatement*> StatementMap;
+ StatementMap statements_;
+
+ DISALLOW_COPY_AND_ASSIGN(SqliteStatementCache);
+};
+
+// Automatically creates or retrieves a statement from the given cache, and
+// automatically resets the statement when it goes out of scope.
+class SqliteCompiledStatement {
+ public:
+ // See SqliteStatementCache::GetStatement for a description of these args.
+ SqliteCompiledStatement(const char* func_name,
+ int func_number,
+ SqliteStatementCache& cache,
+ const char* sql);
+ ~SqliteCompiledStatement();
+
+ // Call to see if this statement is valid or not. Using this statement will
+ // segfault if it is not valid.
+ bool is_valid() const { return !!statement_; }
+
+ // Allow accessing this object to be like accessing a statement for
+ // convenience. The caller must ensure the statement is_valid() before using
+ // these two functions.
+ SQLStatement& operator*();
+ SQLStatement* operator->();
+ SQLStatement* statement();
+
+ private:
+ // The sql statement if valid, NULL if not valid. This pointer is NOT owned
+ // by this class, it is owned by the statement cache object.
+ SQLStatement* statement_;
+
+ DISALLOW_COPY_AND_ASSIGN(SqliteCompiledStatement);
+};
+
+// Creates a compiled statement that has a unique name based on the file and
+// line number. Example:
+//
+// SQLITE_UNIQUE_STATEMENT(var_name, cache, "SELECT * FROM foo");
+// if (!var_name.is_valid())
+// return oops;
+// var_name->bind_XXX(
+// var_name->step();
+// ...
+#define SQLITE_UNIQUE_STATEMENT(var_name, cache, sql) \
+ SqliteCompiledStatement var_name(__FILE__, __LINE__, cache, sql)
+
+#endif // CHROME_COMMON_SQLITE_COMPILED_STATEMENT_H_
diff --git a/chrome/common/sqlite_utils.cc b/chrome/common/sqlite_utils.cc
new file mode 100644
index 0000000..ed383be
--- /dev/null
+++ b/chrome/common/sqlite_utils.cc
@@ -0,0 +1,508 @@
+// Copyright (c) 2010 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/common/sqlite_utils.h"
+
+#include <list>
+
+#include "base/at_exit.h"
+#include "base/file_path.h"
+#include "base/lock.h"
+#include "base/logging.h"
+#include "base/singleton.h"
+#include "base/stl_util-inl.h"
+#include "base/string16.h"
+
+// The vanilla error handler implements the common fucntionality for all the
+// error handlers. Specialized error handlers are expected to only override
+// the Handler() function.
+class VanillaSQLErrorHandler : public SQLErrorHandler {
+ public:
+ VanillaSQLErrorHandler() : error_(SQLITE_OK) {
+ }
+ virtual int GetLastError() const {
+ return error_;
+ }
+ protected:
+ int error_;
+};
+
+class DebugSQLErrorHandler: public VanillaSQLErrorHandler {
+ public:
+ virtual int HandleError(int error, sqlite3* db) {
+ error_ = error;
+ NOTREACHED() << "sqlite error " << error
+ << " db " << static_cast<void*>(db);
+ return error;
+ }
+};
+
+class ReleaseSQLErrorHandler : public VanillaSQLErrorHandler {
+ public:
+ virtual int HandleError(int error, sqlite3* db) {
+ error_ = error;
+ // Used to have a CHECK here. Got lots of crashes.
+ return error;
+ }
+};
+
+// The default error handler factory is also in charge of managing the
+// lifetime of the error objects. This object is multi-thread safe.
+class DefaultSQLErrorHandlerFactory : public SQLErrorHandlerFactory {
+ public:
+ ~DefaultSQLErrorHandlerFactory() {
+ STLDeleteContainerPointers(errors_.begin(), errors_.end());
+ }
+
+ virtual SQLErrorHandler* Make() {
+ SQLErrorHandler* handler;
+#ifndef NDEBUG
+ handler = new DebugSQLErrorHandler;
+#else
+ handler = new ReleaseSQLErrorHandler;
+#endif // NDEBUG
+ AddHandler(handler);
+ return handler;
+ }
+
+ private:
+ void AddHandler(SQLErrorHandler* handler) {
+ AutoLock lock(lock_);
+ errors_.push_back(handler);
+ }
+
+ typedef std::list<SQLErrorHandler*> ErrorList;
+ ErrorList errors_;
+ Lock lock_;
+};
+
+SQLErrorHandlerFactory* GetErrorHandlerFactory() {
+ // TODO(cpu): Testing needs to override the error handler.
+ // Destruction of DefaultSQLErrorHandlerFactory handled by at_exit manager.
+ return Singleton<DefaultSQLErrorHandlerFactory>::get();
+}
+
+namespace sqlite_utils {
+
+int OpenSqliteDb(const FilePath& filepath, sqlite3** database) {
+#if defined(OS_WIN)
+ // We want the default encoding to always be UTF-8, so we use the
+ // 8-bit version of open().
+ return sqlite3_open(WideToUTF8(filepath.value()).c_str(), database);
+#elif defined(OS_POSIX)
+ return sqlite3_open(filepath.value().c_str(), database);
+#endif
+}
+
+bool DoesSqliteTableExist(sqlite3* db,
+ const char* db_name,
+ const char* table_name) {
+ // sqlite doesn't allow binding parameters as table names, so we have to
+ // manually construct the sql
+ std::string sql("SELECT name FROM ");
+ if (db_name && db_name[0]) {
+ sql.append(db_name);
+ sql.push_back('.');
+ }
+ sql.append("sqlite_master WHERE type='table' AND name=?");
+
+ SQLStatement statement;
+ if (statement.prepare(db, sql.c_str()) != SQLITE_OK)
+ return false;
+
+ if (statement.bind_text(0, table_name) != SQLITE_OK)
+ return false;
+
+ // we only care about if this matched a row, not the actual data
+ return sqlite3_step(statement.get()) == SQLITE_ROW;
+}
+
+bool DoesSqliteColumnExist(sqlite3* db,
+ const char* database_name,
+ const char* table_name,
+ const char* column_name,
+ const char* column_type) {
+ SQLStatement s;
+ std::string sql;
+ sql.append("PRAGMA ");
+ if (database_name && database_name[0]) {
+ // optional database name specified
+ sql.append(database_name);
+ sql.push_back('.');
+ }
+ sql.append("TABLE_INFO(");
+ sql.append(table_name);
+ sql.append(")");
+
+ if (s.prepare(db, sql.c_str()) != SQLITE_OK)
+ return false;
+
+ while (s.step() == SQLITE_ROW) {
+ if (!s.column_string(1).compare(column_name)) {
+ if (column_type && column_type[0])
+ return !s.column_string(2).compare(column_type);
+ return true;
+ }
+ }
+ return false;
+}
+
+bool DoesSqliteTableHaveRow(sqlite3* db, const char* table_name) {
+ SQLStatement s;
+ std::string b;
+ b.append("SELECT * FROM ");
+ b.append(table_name);
+
+ if (s.prepare(db, b.c_str()) != SQLITE_OK)
+ return false;
+
+ return s.step() == SQLITE_ROW;
+}
+
+} // namespace sqlite_utils
+
+SQLTransaction::SQLTransaction(sqlite3* db) : db_(db), began_(false) {
+}
+
+SQLTransaction::~SQLTransaction() {
+ if (began_) {
+ Rollback();
+ }
+}
+
+int SQLTransaction::BeginCommand(const char* command) {
+ int rv = SQLITE_ERROR;
+ if (!began_ && db_) {
+ rv = sqlite3_exec(db_, command, NULL, NULL, NULL);
+ began_ = (rv == SQLITE_OK);
+ }
+ return rv;
+}
+
+int SQLTransaction::EndCommand(const char* command) {
+ int rv = SQLITE_ERROR;
+ if (began_ && db_) {
+ rv = sqlite3_exec(db_, command, NULL, NULL, NULL);
+ began_ = (rv != SQLITE_OK);
+ }
+ return rv;
+}
+
+SQLNestedTransactionSite::~SQLNestedTransactionSite() {
+ DCHECK(!top_transaction_);
+}
+
+void SQLNestedTransactionSite::SetTopTransaction(SQLNestedTransaction* top) {
+ DCHECK(!top || !top_transaction_);
+ top_transaction_ = top;
+}
+
+SQLNestedTransaction::SQLNestedTransaction(SQLNestedTransactionSite* site)
+ : SQLTransaction(site->GetSqlite3DB()),
+ needs_rollback_(false),
+ site_(site) {
+ DCHECK(site);
+ if (site->GetTopTransaction() == NULL) {
+ site->SetTopTransaction(this);
+ }
+}
+
+SQLNestedTransaction::~SQLNestedTransaction() {
+ if (began_) {
+ Rollback();
+ }
+ if (site_->GetTopTransaction() == this) {
+ site_->SetTopTransaction(NULL);
+ }
+}
+
+int SQLNestedTransaction::BeginCommand(const char* command) {
+ DCHECK(db_);
+ DCHECK(site_ && site_->GetTopTransaction());
+ if (!db_ || began_) {
+ return SQLITE_ERROR;
+ }
+ if (site_->GetTopTransaction() == this) {
+ int rv = sqlite3_exec(db_, command, NULL, NULL, NULL);
+ began_ = (rv == SQLITE_OK);
+ if (began_) {
+ site_->OnBegin();
+ }
+ return rv;
+ } else {
+ if (site_->GetTopTransaction()->needs_rollback_) {
+ return SQLITE_ERROR;
+ }
+ began_ = true;
+ return SQLITE_OK;
+ }
+}
+
+int SQLNestedTransaction::EndCommand(const char* command) {
+ DCHECK(db_);
+ DCHECK(site_ && site_->GetTopTransaction());
+ if (!db_ || !began_) {
+ return SQLITE_ERROR;
+ }
+ if (site_->GetTopTransaction() == this) {
+ if (needs_rollback_) {
+ sqlite3_exec(db_, "ROLLBACK", NULL, NULL, NULL);
+ began_ = false; // reset so we don't try to rollback or call
+ // OnRollback() again
+ site_->OnRollback();
+ return SQLITE_ERROR;
+ } else {
+ int rv = sqlite3_exec(db_, command, NULL, NULL, NULL);
+ began_ = (rv != SQLITE_OK);
+ if (strcmp(command, "ROLLBACK") == 0) {
+ began_ = false; // reset so we don't try to rollbck or call
+ // OnRollback() again
+ site_->OnRollback();
+ } else {
+ DCHECK(strcmp(command, "COMMIT") == 0);
+ if (rv == SQLITE_OK) {
+ site_->OnCommit();
+ }
+ }
+ return rv;
+ }
+ } else {
+ if (strcmp(command, "ROLLBACK") == 0) {
+ site_->GetTopTransaction()->needs_rollback_ = true;
+ }
+ began_ = false;
+ return SQLITE_OK;
+ }
+}
+
+int SQLStatement::prepare(sqlite3* db, const char* sql, int sql_len) {
+ DCHECK(!stmt_);
+ int rv = sqlite3_prepare_v2(db, sql, sql_len, &stmt_, NULL);
+ if (rv != SQLITE_OK) {
+ SQLErrorHandler* error_handler = GetErrorHandlerFactory()->Make();
+ return error_handler->HandleError(rv, db);
+ }
+ return rv;
+}
+
+int SQLStatement::step() {
+ DCHECK(stmt_);
+ int status = sqlite3_step(stmt_);
+ if ((status == SQLITE_ROW) || (status == SQLITE_DONE))
+ return status;
+ // We got a problem.
+ SQLErrorHandler* error_handler = GetErrorHandlerFactory()->Make();
+ return error_handler->HandleError(status, db_handle());
+}
+
+int SQLStatement::reset() {
+ DCHECK(stmt_);
+ return sqlite3_reset(stmt_);
+}
+
+sqlite_int64 SQLStatement::last_insert_rowid() {
+ DCHECK(stmt_);
+ return sqlite3_last_insert_rowid(db_handle());
+}
+
+int SQLStatement::changes() {
+ DCHECK(stmt_);
+ return sqlite3_changes(db_handle());
+}
+
+sqlite3* SQLStatement::db_handle() {
+ DCHECK(stmt_);
+ return sqlite3_db_handle(stmt_);
+}
+
+int SQLStatement::bind_parameter_count() {
+ DCHECK(stmt_);
+ return sqlite3_bind_parameter_count(stmt_);
+}
+
+int SQLStatement::bind_blob(int index, std::vector<unsigned char>* blob) {
+ if (blob) {
+ const void* value = blob->empty() ? NULL : &(*blob)[0];
+ int len = static_cast<int>(blob->size());
+ return bind_blob(index, value, len);
+ } else {
+ return bind_null(index);
+ }
+}
+
+int SQLStatement::bind_blob(int index, const void* value, int value_len) {
+ return bind_blob(index, value, value_len, SQLITE_TRANSIENT);
+}
+
+int SQLStatement::bind_blob(int index, const void* value, int value_len,
+ Function dtor) {
+ DCHECK(stmt_);
+ return sqlite3_bind_blob(stmt_, index + 1, value, value_len, dtor);
+}
+
+int SQLStatement::bind_double(int index, double value) {
+ DCHECK(stmt_);
+ return sqlite3_bind_double(stmt_, index + 1, value);
+}
+
+int SQLStatement::bind_bool(int index, bool value) {
+ DCHECK(stmt_);
+ return sqlite3_bind_int(stmt_, index + 1, value);
+}
+
+int SQLStatement::bind_int(int index, int value) {
+ DCHECK(stmt_);
+ return sqlite3_bind_int(stmt_, index + 1, value);
+}
+
+int SQLStatement::bind_int64(int index, sqlite_int64 value) {
+ DCHECK(stmt_);
+ return sqlite3_bind_int64(stmt_, index + 1, value);
+}
+
+int SQLStatement::bind_null(int index) {
+ DCHECK(stmt_);
+ return sqlite3_bind_null(stmt_, index + 1);
+}
+
+int SQLStatement::bind_text(int index, const char* value, int value_len,
+ Function dtor) {
+ DCHECK(stmt_);
+ return sqlite3_bind_text(stmt_, index + 1, value, value_len, dtor);
+}
+
+int SQLStatement::bind_text16(int index, const char16* value, int value_len,
+ Function dtor) {
+ DCHECK(stmt_);
+ value_len *= sizeof(char16);
+ return sqlite3_bind_text16(stmt_, index + 1, value, value_len, dtor);
+}
+
+int SQLStatement::bind_value(int index, const sqlite3_value* value) {
+ DCHECK(stmt_);
+ return sqlite3_bind_value(stmt_, index + 1, value);
+}
+
+int SQLStatement::column_count() {
+ DCHECK(stmt_);
+ return sqlite3_column_count(stmt_);
+}
+
+int SQLStatement::column_type(int index) {
+ DCHECK(stmt_);
+ return sqlite3_column_type(stmt_, index);
+}
+
+const void* SQLStatement::column_blob(int index) {
+ DCHECK(stmt_);
+ return sqlite3_column_blob(stmt_, index);
+}
+
+bool SQLStatement::column_blob_as_vector(int index,
+ std::vector<unsigned char>* blob) {
+ DCHECK(stmt_);
+ const void* p = column_blob(index);
+ size_t len = column_bytes(index);
+ blob->resize(len);
+ if (blob->size() != len) {
+ return false;
+ }
+ if (len > 0)
+ memcpy(&(blob->front()), p, len);
+ return true;
+}
+
+bool SQLStatement::column_blob_as_string(int index, std::string* blob) {
+ DCHECK(stmt_);
+ const void* p = column_blob(index);
+ size_t len = column_bytes(index);
+ blob->resize(len);
+ if (blob->size() != len) {
+ return false;
+ }
+ blob->assign(reinterpret_cast<const char*>(p), len);
+ return true;
+}
+
+int SQLStatement::column_bytes(int index) {
+ DCHECK(stmt_);
+ return sqlite3_column_bytes(stmt_, index);
+}
+
+int SQLStatement::column_bytes16(int index) {
+ DCHECK(stmt_);
+ return sqlite3_column_bytes16(stmt_, index);
+}
+
+double SQLStatement::column_double(int index) {
+ DCHECK(stmt_);
+ return sqlite3_column_double(stmt_, index);
+}
+
+bool SQLStatement::column_bool(int index) {
+ DCHECK(stmt_);
+ return sqlite3_column_int(stmt_, index) ? true : false;
+}
+
+int SQLStatement::column_int(int index) {
+ DCHECK(stmt_);
+ return sqlite3_column_int(stmt_, index);
+}
+
+sqlite_int64 SQLStatement::column_int64(int index) {
+ DCHECK(stmt_);
+ return sqlite3_column_int64(stmt_, index);
+}
+
+const char* SQLStatement::column_text(int index) {
+ DCHECK(stmt_);
+ return reinterpret_cast<const char*>(sqlite3_column_text(stmt_, index));
+}
+
+bool SQLStatement::column_string(int index, std::string* str) {
+ DCHECK(stmt_);
+ DCHECK(str);
+ const char* s = column_text(index);
+ str->assign(s ? s : std::string());
+ return s != NULL;
+}
+
+std::string SQLStatement::column_string(int index) {
+ std::string str;
+ column_string(index, &str);
+ return str;
+}
+
+const char16* SQLStatement::column_text16(int index) {
+ DCHECK(stmt_);
+ return static_cast<const char16*>(sqlite3_column_text16(stmt_, index));
+}
+
+bool SQLStatement::column_string16(int index, string16* str) {
+ DCHECK(stmt_);
+ DCHECK(str);
+ const char* s = column_text(index);
+ str->assign(s ? UTF8ToUTF16(s) : string16());
+ return (s != NULL);
+}
+
+string16 SQLStatement::column_string16(int index) {
+ string16 str;
+ column_string16(index, &str);
+ return str;
+}
+
+bool SQLStatement::column_wstring(int index, std::wstring* str) {
+ DCHECK(stmt_);
+ DCHECK(str);
+ const char* s = column_text(index);
+ str->assign(s ? UTF8ToWide(s) : std::wstring());
+ return (s != NULL);
+}
+
+std::wstring SQLStatement::column_wstring(int index) {
+ std::wstring wstr;
+ column_wstring(index, &wstr);
+ return wstr;
+}
diff --git a/chrome/common/sqlite_utils.h b/chrome/common/sqlite_utils.h
new file mode 100644
index 0000000..f7351a2
--- /dev/null
+++ b/chrome/common/sqlite_utils.h
@@ -0,0 +1,399 @@
+// Copyright (c) 2010 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_COMMON_SQLITE_UTILS_H_
+#define CHROME_COMMON_SQLITE_UTILS_H_
+
+#include <string>
+#include <vector>
+
+#include "base/basictypes.h"
+#include "base/scoped_ptr.h"
+#include "base/string16.h"
+#include "base/utf_string_conversions.h"
+#include "third_party/sqlite/preprocessed/sqlite3.h"
+
+// forward declarations of classes defined here
+class FilePath;
+class SQLTransaction;
+class SQLNestedTransaction;
+class SQLNestedTransactionSite;
+class scoped_sqlite3_stmt_ptr;
+class SQLStatement;
+
+//------------------------------------------------------------------------------
+// Interface to be implemented by objects that can handle exceptional sqlite
+// conditions. This way client code can focus on handling normal condtions.
+//------------------------------------------------------------------------------
+class SQLErrorHandler {
+ public:
+ virtual ~SQLErrorHandler() {}
+ // Handle a sqlite error. |error| is the return code an of sqlite operation
+ // which is considered an error. This handler is free to try repair, notify
+ // someone or even break into the debugger depending on the situation.
+ virtual int HandleError(int error, sqlite3* db) = 0;
+ // Returns the last value of |error| passed to HandleError.
+ virtual int GetLastError() const = 0;
+};
+
+//------------------------------------------------------------------------------
+// The factory interface is used to create the different error handling
+// strategies for debug, release and for diagnostic mode.
+//------------------------------------------------------------------------------
+class SQLErrorHandlerFactory {
+ public:
+ virtual ~SQLErrorHandlerFactory() {}
+ virtual SQLErrorHandler* Make() = 0;
+};
+
+//------------------------------------------------------------------------------
+// A wrapper for sqlite transactions that rollsback when the wrapper
+// goes out of scope if the caller has not already called Commit or Rollback.
+// Note: the constructor does NOT Begin a transaction.
+//------------------------------------------------------------------------------
+class SQLTransaction {
+ public:
+ explicit SQLTransaction(sqlite3* db);
+ virtual ~SQLTransaction();
+
+ int Begin() {
+ // By default, we BEGIN IMMEDIATE to establish file locks at the
+ // onset of a transaction. This avoids SQLITE_BUSY errors, without
+ // waiting for the busy timeout period, which can occur when BEGIN
+ // DEFERRED is used.
+ return BeginImmediate();
+ }
+
+ int BeginExclusive() {
+ return BeginCommand("BEGIN EXCLUSIVE");
+ }
+
+ int BeginImmediate() {
+ return BeginCommand("BEGIN IMMEDIATE");
+ }
+
+ int BeginDeferred() {
+ return BeginCommand("BEGIN DEFERRED");
+ }
+
+ int Commit() {
+ return EndCommand("COMMIT");
+ }
+
+ int Rollback() {
+ return EndCommand("ROLLBACK");
+ }
+
+ bool HasBegun() {
+ return began_;
+ }
+
+ protected:
+ virtual int BeginCommand(const char* command);
+ virtual int EndCommand(const char* command);
+
+ sqlite3* db_;
+ bool began_;
+ DISALLOW_COPY_AND_ASSIGN(SQLTransaction);
+};
+
+
+//------------------------------------------------------------------------------
+// A class for use with SQLNestedTransaction.
+//------------------------------------------------------------------------------
+class SQLNestedTransactionSite {
+ protected:
+ SQLNestedTransactionSite() : db_(NULL), top_transaction_(NULL) {}
+ virtual ~SQLNestedTransactionSite();
+
+ // The following virtual methods provide notification of true transaction
+ // boundaries as they are crossed by a top nested transaction.
+ // Intended to be overriden (See WebCacheDB)
+ // SQLNestedTransaction calls these after the underlying database
+ // operation has been performed.
+
+ virtual void OnBegin() {}
+ virtual void OnCommit() {}
+ virtual void OnRollback() {}
+
+ // Returns the sqlite3 database connection associated with this site
+ // Used by SQLNestedTransaction
+ sqlite3* GetSqlite3DB() { return db_; }
+
+ // Returns the current top nested transaction associated with this site
+ // Used by SQLNestedTransaction
+ SQLNestedTransaction* GetTopTransaction() {
+ return top_transaction_;
+ }
+
+ // Sets or clears the top nested transaction associated with this site
+ // Used by SQLNestedTransaction
+ void SetTopTransaction(SQLNestedTransaction* top);
+
+ sqlite3* db_;
+ SQLNestedTransaction* top_transaction_;
+ friend class SQLNestedTransaction;
+};
+
+//------------------------------------------------------------------------------
+// SQLite does not support nested transactions. This class provides a gross
+// approximation of nested transactions.
+//
+// Really there is only one transaction, the top transaction.
+//
+// A nested transaction commits with respect to the top transaction.
+// That is, even though the nested transaction commits, the permanence of its
+// effects depends on the top transaction committing. If the top
+// transaction rollsback, the results of the nested transaction are backed out.
+// If any nested transaction aborts, the top transaction ultimately rollsback
+// as well.
+//
+// Note: If a nested transaction is open for a particular db connection, an
+// attempt to open a non-nested transaction (class SQLTransaction) will fail.
+// And vice versa.
+//
+// TODO(michaeln): demonstrate usage here
+// TODO(michaeln): safegaurds to prevent mis-use
+//------------------------------------------------------------------------------
+class SQLNestedTransaction : public SQLTransaction {
+ public:
+ explicit SQLNestedTransaction(SQLNestedTransactionSite* site);
+ virtual ~SQLNestedTransaction();
+
+ protected:
+ virtual int BeginCommand(const char* command);
+ virtual int EndCommand(const char* command);
+
+ private:
+ bool needs_rollback_;
+ SQLNestedTransactionSite* site_;
+ DISALLOW_COPY_AND_ASSIGN(SQLNestedTransaction);
+};
+
+//------------------------------------------------------------------------------
+// A scoped sqlite statement that finalizes when it goes out of scope.
+//------------------------------------------------------------------------------
+class scoped_sqlite3_stmt_ptr {
+ public:
+ ~scoped_sqlite3_stmt_ptr() {
+ finalize();
+ }
+
+ scoped_sqlite3_stmt_ptr() : stmt_(NULL) {
+ }
+
+ explicit scoped_sqlite3_stmt_ptr(sqlite3_stmt* stmt)
+ : stmt_(stmt) {
+ }
+
+ sqlite3_stmt* get() const {
+ return stmt_;
+ }
+
+ void set(sqlite3_stmt* stmt) {
+ finalize();
+ stmt_ = stmt;
+ }
+
+ sqlite3_stmt* release() {
+ sqlite3_stmt* tmp = stmt_;
+ stmt_ = NULL;
+ return tmp;
+ }
+
+ // It is not safe to call sqlite3_finalize twice on the same stmt.
+ // Sqlite3's sqlite3_finalize() function should not be called directly
+ // without calling the release method. If sqlite3_finalize() must be
+ // called directly, the following usage is advised:
+ // scoped_sqlite3_stmt_ptr stmt;
+ // ... do something with stmt ...
+ // sqlite3_finalize(stmt.release());
+ int finalize() {
+ int err = sqlite3_finalize(stmt_);
+ stmt_ = NULL;
+ return err;
+ }
+
+ protected:
+ sqlite3_stmt* stmt_;
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(scoped_sqlite3_stmt_ptr);
+};
+
+//------------------------------------------------------------------------------
+// A scoped sqlite statement with convenient C++ wrappers for sqlite3 APIs.
+//------------------------------------------------------------------------------
+class SQLStatement : public scoped_sqlite3_stmt_ptr {
+ public:
+ SQLStatement() {}
+
+ int prepare(sqlite3* db, const char* sql) {
+ return prepare(db, sql, -1);
+ }
+
+ int prepare(sqlite3* db, const char* sql, int sql_len);
+
+ int step();
+ int reset();
+ sqlite_int64 last_insert_rowid();
+ int changes();
+ sqlite3* db_handle();
+
+ //
+ // Parameter binding helpers (NOTE: index is 0-based)
+ //
+
+ int bind_parameter_count();
+
+ typedef void (*Function)(void*);
+
+ int bind_blob(int index, std::vector<unsigned char>* blob);
+ int bind_blob(int index, const void* value, int value_len);
+ int bind_blob(int index, const void* value, int value_len, Function dtor);
+ int bind_double(int index, double value);
+ int bind_bool(int index, bool value);
+ int bind_int(int index, int value);
+ int bind_int64(int index, sqlite_int64 value);
+ int bind_null(int index);
+
+ int bind_string(int index, const std::string& value) {
+ // don't use c_str so it doesn't have to fix up the null terminator
+ // (sqlite just uses the length)
+ return bind_text(index, value.data(),
+ static_cast<int>(value.length()), SQLITE_TRANSIENT);
+ }
+
+ int bind_string16(int index, const string16& value) {
+ // don't use c_str so it doesn't have to fix up the null terminator
+ // (sqlite just uses the length)
+ std::string value_utf8(UTF16ToUTF8(value));
+ return bind_text(index, value_utf8.data(),
+ static_cast<int>(value_utf8.length()), SQLITE_TRANSIENT);
+ }
+
+ int bind_wstring(int index, const std::wstring& value) {
+ // don't use c_str so it doesn't have to fix up the null terminator
+ // (sqlite just uses the length)
+ std::string value_utf8(WideToUTF8(value));
+ return bind_text(index, value_utf8.data(),
+ static_cast<int>(value_utf8.length()), SQLITE_TRANSIENT);
+ }
+
+ int bind_text(int index, const char* value) {
+ return bind_text(index, value, -1, SQLITE_TRANSIENT);
+ }
+
+ // value_len is number of characters or may be negative
+ // a for null-terminated value string
+ int bind_text(int index, const char* value, int value_len) {
+ return bind_text(index, value, value_len, SQLITE_TRANSIENT);
+ }
+
+ // value_len is number of characters or may be negative
+ // a for null-terminated value string
+ int bind_text(int index, const char* value, int value_len,
+ Function dtor);
+
+ int bind_text16(int index, const char16* value) {
+ return bind_text16(index, value, -1, SQLITE_TRANSIENT);
+ }
+
+ // value_len is number of characters or may be negative
+ // a for null-terminated value string
+ int bind_text16(int index, const char16* value, int value_len) {
+ return bind_text16(index, value, value_len, SQLITE_TRANSIENT);
+ }
+
+ // value_len is number of characters or may be negative
+ // a for null-terminated value string
+ int bind_text16(int index, const char16* value, int value_len,
+ Function dtor);
+
+ int bind_value(int index, const sqlite3_value* value);
+
+ //
+ // Column helpers (NOTE: index is 0-based)
+ //
+
+ int column_count();
+ int column_type(int index);
+ const void* column_blob(int index);
+ bool column_blob_as_vector(int index, std::vector<unsigned char>* blob);
+ bool column_blob_as_string(int index, std::string* blob);
+ int column_bytes(int index);
+ int column_bytes16(int index);
+ double column_double(int index);
+ bool column_bool(int index);
+ int column_int(int index);
+ sqlite_int64 column_int64(int index);
+ const char* column_text(int index);
+ bool column_string(int index, std::string* str);
+ std::string column_string(int index);
+ const char16* column_text16(int index);
+ bool column_string16(int index, string16* str);
+ string16 column_string16(int index);
+ bool column_wstring(int index, std::wstring* str);
+ std::wstring column_wstring(int index);
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(SQLStatement);
+};
+
+namespace sqlite_utils {
+
+//------------------------------------------------------------------------------
+// A scoped sqlite database that closes when it goes out of scope.
+//------------------------------------------------------------------------------
+class DBClose {
+ public:
+ inline void operator()(sqlite3* x) const {
+ sqlite3_close(x);
+ }
+};
+
+typedef scoped_ptr_malloc<sqlite3, DBClose> scoped_sqlite_db_ptr;
+
+// Opens the DB in the file pointed to by |filepath|. This method forces the
+// database to be in UTF-8 mode on all platforms. See
+// http://www.sqlite.org/capi3ref.html#sqlite3_open for an explanation of the
+// return value.
+int OpenSqliteDb(const FilePath& filepath, sqlite3** database);
+
+// Returns true if there is a table with the given name in the database.
+// For the version where a database name is specified, it may be NULL or the
+// empty string if no database name is necessary.
+bool DoesSqliteTableExist(sqlite3* db,
+ const char* db_name,
+ const char* table_name);
+inline bool DoesSqliteTableExist(sqlite3* db, const char* table_name) {
+ return DoesSqliteTableExist(db, NULL, table_name);
+}
+
+// Test whether a table has a column matching the provided name and type.
+// Returns true if the column exist and false otherwise. There are two
+// versions, one that takes a database name, the other that doesn't. The
+// database name can be NULL or empty if no name is desired.
+//
+// Column type is optional, it can be NULL or empty. If specified, we the
+// function will check that the column is of the correct type (case-sensetive).
+bool DoesSqliteColumnExist(sqlite3* db,
+ const char* datbase_name,
+ const char* table_name,
+ const char* column_name,
+ const char* column_type);
+inline bool DoesSqliteColumnExist(sqlite3* db,
+ const char* table_name,
+ const char* column_name,
+ const char* column_type) {
+ return DoesSqliteColumnExist(db, NULL, table_name, column_name, column_type);
+}
+
+// Test whether a table has one or more rows. Returns true if the table
+// has one or more rows and false if the table is empty or doesn't exist.
+bool DoesSqliteTableHaveRow(sqlite3* db, const char* table_name);
+
+} // namespace sqlite_utils
+
+#endif // CHROME_COMMON_SQLITE_UTILS_H_
diff --git a/chrome/common/task_queue.cc b/chrome/common/task_queue.cc
new file mode 100644
index 0000000..0d5aabb
--- /dev/null
+++ b/chrome/common/task_queue.cc
@@ -0,0 +1,46 @@
+// Copyright (c) 2006-2008 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/common/task_queue.h"
+
+#include "base/stl_util-inl.h"
+
+TaskQueue::TaskQueue() {
+}
+
+TaskQueue::~TaskQueue() {
+ // We own all the pointes in |queue_|. It is our job to delete them.
+ STLDeleteElements(&queue_);
+}
+
+void TaskQueue::Run() {
+ // Nothing to run if our queue is empty.
+ if (queue_.empty())
+ return;
+
+ std::deque<Task*> ready;
+ queue_.swap(ready);
+
+ // Run the tasks that are ready.
+ std::deque<Task*>::const_iterator task;
+ for (task = ready.begin(); task != ready.end(); ++task) {
+ // Run the task and then delete it.
+ (*task)->Run();
+ delete (*task);
+ }
+}
+
+void TaskQueue::Push(Task* task) {
+ // Add the task to the back of the queue.
+ queue_.push_back(task);
+}
+
+void TaskQueue::Clear() {
+ // Delete all the elements in the queue and clear the dead pointers.
+ STLDeleteElements(&queue_);
+}
+
+bool TaskQueue::Empty() const {
+ return queue_.empty();
+}
diff --git a/chrome/common/task_queue.h b/chrome/common/task_queue.h
new file mode 100644
index 0000000..9e1c817
--- /dev/null
+++ b/chrome/common/task_queue.h
@@ -0,0 +1,42 @@
+// Copyright (c) 2006-2008 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_COMMON_TASK_QUEUE_H__
+#define CHROME_COMMON_TASK_QUEUE_H__
+
+#include <deque>
+
+#include "base/task.h"
+
+// A TaskQueue is a queue of tasks waiting to be run. To run the tasks, call
+// the Run method. A task queue is itself a Task so that it can be placed in a
+// message loop or another task queue.
+class TaskQueue : public Task {
+ public:
+ TaskQueue();
+ ~TaskQueue();
+
+ // Run all the tasks in the queue. New tasks pushed onto the queue during
+ // a run will be run next time |Run| is called.
+ virtual void Run();
+
+ // Push the specified task onto the queue. When the queue is run, the tasks
+ // will be run in the order they are pushed.
+ //
+ // This method takes ownership of |task| and will delete task after it is run
+ // (or when the TaskQueue is destroyed, if we never got a chance to run it).
+ void Push(Task* task);
+
+ // Remove all tasks from the queue. The tasks are deleted.
+ void Clear();
+
+ // Returns true if this queue contains no tasks.
+ bool Empty() const;
+
+ private:
+ // The list of tasks we are waiting to run.
+ std::deque<Task*> queue_;
+};
+
+#endif // CHROME_COMMON_TASK_QUEUE_H__
diff --git a/chrome/common/thumbnail_score.cc b/chrome/common/thumbnail_score.cc
new file mode 100644
index 0000000..dc7856d
--- /dev/null
+++ b/chrome/common/thumbnail_score.cc
@@ -0,0 +1,118 @@
+// Copyright (c) 2009 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/common/thumbnail_score.h"
+
+#include "base/logging.h"
+
+using base::Time;
+using base::TimeDelta;
+
+const TimeDelta ThumbnailScore::kUpdateThumbnailTime = TimeDelta::FromDays(1);
+const double ThumbnailScore::kThumbnailMaximumBoringness = 0.94;
+const double ThumbnailScore::kThumbnailDegradePerHour = 0.01;
+
+// Calculates a numeric score from traits about where a snapshot was
+// taken. We store the raw components in the database because I'm sure
+// this will evolve and I don't want to break databases.
+static int GetThumbnailType(bool good_clipping, bool at_top) {
+ if (good_clipping && at_top) {
+ return 0;
+ } else if (good_clipping && !at_top) {
+ return 1;
+ } else if (!good_clipping && at_top) {
+ return 2;
+ } else if (!good_clipping && !at_top) {
+ return 3;
+ } else {
+ NOTREACHED();
+ return -1;
+ }
+}
+
+ThumbnailScore::ThumbnailScore()
+ : boring_score(1.0),
+ good_clipping(false),
+ at_top(false),
+ time_at_snapshot(Time::Now()),
+ redirect_hops_from_dest(0) {
+}
+
+ThumbnailScore::ThumbnailScore(double score, bool clipping, bool top)
+ : boring_score(score),
+ good_clipping(clipping),
+ at_top(top),
+ time_at_snapshot(Time::Now()),
+ redirect_hops_from_dest(0) {
+}
+
+ThumbnailScore::ThumbnailScore(double score, bool clipping, bool top,
+ const Time& time)
+ : boring_score(score),
+ good_clipping(clipping),
+ at_top(top),
+ time_at_snapshot(time),
+ redirect_hops_from_dest(0) {
+}
+
+ThumbnailScore::~ThumbnailScore() {
+}
+
+bool ThumbnailScore::Equals(const ThumbnailScore& rhs) const {
+ // When testing equality we use ToTimeT() because that's the value
+ // stuck in the SQL database, so we need to test equivalence with
+ // that lower resolution.
+ return boring_score == rhs.boring_score &&
+ good_clipping == rhs.good_clipping &&
+ at_top == rhs.at_top &&
+ time_at_snapshot.ToTimeT() == rhs.time_at_snapshot.ToTimeT() &&
+ redirect_hops_from_dest == rhs.redirect_hops_from_dest;
+}
+
+bool ShouldReplaceThumbnailWith(const ThumbnailScore& current,
+ const ThumbnailScore& replacement) {
+ int current_type = GetThumbnailType(current.good_clipping, current.at_top);
+ int replacement_type = GetThumbnailType(replacement.good_clipping,
+ replacement.at_top);
+ if (replacement_type < current_type) {
+ // If we have a better class of thumbnail, add it if it meets
+ // certain minimum boringness.
+ return replacement.boring_score <
+ ThumbnailScore::kThumbnailMaximumBoringness;
+ } else if (replacement_type == current_type) {
+ // It's much easier to do the scaling below when we're dealing with "higher
+ // is better." Then we can decrease the score by dividing by a fraction.
+ const double kThumbnailMinimumInterestingness =
+ 1.0 - ThumbnailScore::kThumbnailMaximumBoringness;
+ double current_interesting_score = 1.0 - current.boring_score;
+ double replacement_interesting_score = 1.0 - replacement.boring_score;
+
+ // Degrade the score of each thumbnail to account for how many redirects
+ // they are away from the destination. 1/(x+1) gives a scaling factor of
+ // one for x = 0, and asymptotically approaches 0 for larger values of x.
+ current_interesting_score *=
+ 1.0 / (current.redirect_hops_from_dest + 1);
+ replacement_interesting_score *=
+ 1.0 / (replacement.redirect_hops_from_dest + 1);
+
+ // Degrade the score and prefer the newer one based on how long apart the
+ // two thumbnails were taken. This means we'll eventually replace an old
+ // good one with a new worse one assuming enough time has passed.
+ TimeDelta time_between_thumbnails =
+ replacement.time_at_snapshot - current.time_at_snapshot;
+ current_interesting_score -= time_between_thumbnails.InHours() *
+ ThumbnailScore::kThumbnailDegradePerHour;
+
+ if (current_interesting_score < kThumbnailMinimumInterestingness)
+ current_interesting_score = kThumbnailMinimumInterestingness;
+ if (replacement_interesting_score > current_interesting_score)
+ return true;
+ }
+
+ // If the current thumbnail doesn't meet basic boringness
+ // requirements, but the replacement does, always replace the
+ // current one even if we're using a worse thumbnail type.
+ return current.boring_score >= ThumbnailScore::kThumbnailMaximumBoringness &&
+ replacement.boring_score < ThumbnailScore::kThumbnailMaximumBoringness;
+}
diff --git a/chrome/common/thumbnail_score.h b/chrome/common/thumbnail_score.h
new file mode 100644
index 0000000..c3a5a90
--- /dev/null
+++ b/chrome/common/thumbnail_score.h
@@ -0,0 +1,82 @@
+// Copyright (c) 2009 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_COMMON_THUMBNAIL_SCORE_H_
+#define CHROME_COMMON_THUMBNAIL_SCORE_H_
+
+#include "base/time.h"
+
+// A set of metadata about a Thumbnail.
+struct ThumbnailScore {
+ // Initializes the ThumbnailScore to the absolute worst possible values
+ // except for time, which is set to Now(), and redirect_hops_from_dest which
+ // is set to 0.
+ ThumbnailScore();
+
+ // Builds a ThumbnailScore with the passed in values, and sets the
+ // thumbnail generation time to Now().
+ ThumbnailScore(double score, bool clipping, bool top);
+
+ // Builds a ThumbnailScore with the passed in values.
+ ThumbnailScore(double score, bool clipping, bool top,
+ const base::Time& time);
+ ~ThumbnailScore();
+
+ // Tests for equivalence between two ThumbnailScore objects.
+ bool Equals(const ThumbnailScore& rhs) const;
+
+ // How "boring" a thumbnail is. The boring score is the 0,1 ranged
+ // percentage of pixels that are the most common luma. Higher boring
+ // scores indicate that a higher percentage of a bitmap are all the
+ // same brightness (most likely the same color).
+ double boring_score;
+
+ // Whether the thumbnail was taken with height greater then
+ // width. In cases where we don't have |good_clipping|, the
+ // thumbnails are either clipped from the horizontal center of the
+ // window, or are otherwise weirdly stretched.
+ bool good_clipping;
+
+ // Whether this thumbnail was taken while the renderer was
+ // displaying the top of the page. Most pages are more recognizable
+ // by their headers then by a set of random text half way down the
+ // page; i.e. most MediaWiki sites would be indistinguishable by
+ // thumbnails with |at_top| set to false.
+ bool at_top;
+
+ // Record the time when a thumbnail was taken. This is used to make
+ // sure thumbnails are kept fresh.
+ base::Time time_at_snapshot;
+
+ // The number of hops from the final destination page that this thumbnail was
+ // taken at. When a thumbnail is taken, this will always be the redirect
+ // destination (value of 0).
+ //
+ // For the most visited view, we'll sometimes get thumbnails for URLs in the
+ // middle of a redirect chain. In this case, the top sites component will set
+ // this value so the distance from the destination can be taken into account
+ // by the comparison function.
+ //
+ // If "http://google.com/" redirected to "http://www.google.com/", then
+ // a thumbnail for the first would have a redirect hop of 1, and the second
+ // would have a redirect hop of 0.
+ int redirect_hops_from_dest;
+
+ // How bad a thumbnail needs to be before we completely ignore it.
+ static const double kThumbnailMaximumBoringness;
+
+ // Time before we take a worse thumbnail (subject to
+ // kThumbnailMaximumBoringness) over what's currently in the database
+ // for freshness.
+ static const base::TimeDelta kUpdateThumbnailTime;
+
+ // Penalty of how much more boring a thumbnail should be per hour.
+ static const double kThumbnailDegradePerHour;
+};
+
+// Checks whether we should replace one thumbnail with another.
+bool ShouldReplaceThumbnailWith(const ThumbnailScore& current,
+ const ThumbnailScore& replacement);
+
+#endif // CHROME_COMMON_THUMBNAIL_SCORE_H_
diff --git a/chrome/common/thumbnail_score_unittest.cc b/chrome/common/thumbnail_score_unittest.cc
new file mode 100644
index 0000000..14d79dd
--- /dev/null
+++ b/chrome/common/thumbnail_score_unittest.cc
@@ -0,0 +1,54 @@
+// Copyright (c) 2009 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/common/thumbnail_score.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+// Tests that the different types of thumbnails are compared properly.
+TEST(ThumbnailScoreTest, ShouldReplaceThumbnailWithType) {
+ base::Time now = base::Time::Now();
+
+ ThumbnailScore nothing_good(0.5, false, false, now);
+ ThumbnailScore not_at_top(0.5, false, true, now);
+ ThumbnailScore bad_clipping(0.5, true, false, now);
+ ThumbnailScore life_is_awesome(0.5, true, true, now);
+
+ EXPECT_TRUE(ShouldReplaceThumbnailWith(nothing_good, not_at_top));
+ EXPECT_TRUE(ShouldReplaceThumbnailWith(nothing_good, bad_clipping));
+ EXPECT_TRUE(ShouldReplaceThumbnailWith(nothing_good, life_is_awesome));
+ EXPECT_TRUE(ShouldReplaceThumbnailWith(not_at_top, bad_clipping));
+ EXPECT_TRUE(ShouldReplaceThumbnailWith(not_at_top, life_is_awesome));
+ EXPECT_TRUE(ShouldReplaceThumbnailWith(bad_clipping, life_is_awesome));
+}
+
+// Tests that we'll replace old thumbnails will crappier but newer ones.
+TEST(ThumbnailScoreTest, ShouldReplaceThumbnailWithTime) {
+ // Use a really long time for the difference so we aren't sensitive to the
+ // degrading schedule.
+ base::Time now = base::Time::Now();
+ base::Time last_year = now - base::TimeDelta::FromDays(365);
+
+ ThumbnailScore oldie_but_goodie(0.1, true, true, last_year);
+ ThumbnailScore newie_but_crappie(0.9, true, true, now);
+
+ EXPECT_TRUE(ShouldReplaceThumbnailWith(oldie_but_goodie, newie_but_crappie));
+}
+
+// Having many redirects should age the thumbnail.
+TEST(ThumbnailScoreTest, RedirectCount) {
+ base::Time now = base::Time::Now();
+
+ ThumbnailScore no_redirects(0.5, true, true, now);
+ no_redirects.redirect_hops_from_dest = 0;
+ ThumbnailScore some_redirects(0.5, true, true, now);
+ some_redirects.redirect_hops_from_dest = 1;
+
+ EXPECT_TRUE(ShouldReplaceThumbnailWith(some_redirects, no_redirects));
+
+ // This one has a lot of redirects but a better score. It should still be
+ // rejected.
+ ThumbnailScore lotsa_redirects(0.4, true, true, now);
+ lotsa_redirects.redirect_hops_from_dest = 4;
+ EXPECT_FALSE(ShouldReplaceThumbnailWith(no_redirects, lotsa_redirects));
+}
diff --git a/chrome/common/time_format.cc b/chrome/common/time_format.cc
new file mode 100644
index 0000000..4ca5187
--- /dev/null
+++ b/chrome/common/time_format.cc
@@ -0,0 +1,338 @@
+// Copyright (c) 2009 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/common/time_format.h"
+
+#include <vector>
+
+#include "app/l10n_util.h"
+#include "base/i18n/time_formatting.h"
+#include "base/logging.h"
+#include "base/scoped_ptr.h"
+#include "base/singleton.h"
+#include "base/stl_util-inl.h"
+#include "base/time.h"
+#include "base/utf_string_conversions.h"
+#include "grit/generated_resources.h"
+#include "unicode/datefmt.h"
+#include "unicode/locid.h"
+#include "unicode/plurfmt.h"
+#include "unicode/plurrule.h"
+#include "unicode/smpdtfmt.h"
+
+using base::Time;
+using base::TimeDelta;
+
+namespace {
+
+static const char kFallbackFormatSuffixShort[] = "}";
+static const char kFallbackFormatSuffixLeft[] = " left}";
+static const char kFallbackFormatSuffixAgo[] = " ago}";
+
+// Contains message IDs for various time units and pluralities.
+struct MessageIDs {
+ // There are 4 different time units and 6 different pluralities.
+ int ids[4][6];
+};
+
+// Message IDs for different time formats.
+static const MessageIDs kTimeShortMessageIDs = { {
+ {
+ IDS_TIME_SECS_DEFAULT, IDS_TIME_SEC_SINGULAR, IDS_TIME_SECS_ZERO,
+ IDS_TIME_SECS_TWO, IDS_TIME_SECS_FEW, IDS_TIME_SECS_MANY
+ },
+ {
+ IDS_TIME_MINS_DEFAULT, IDS_TIME_MIN_SINGULAR, IDS_TIME_MINS_ZERO,
+ IDS_TIME_MINS_TWO, IDS_TIME_MINS_FEW, IDS_TIME_MINS_MANY
+ },
+ {
+ IDS_TIME_HOURS_DEFAULT, IDS_TIME_HOUR_SINGULAR, IDS_TIME_HOURS_ZERO,
+ IDS_TIME_HOURS_TWO, IDS_TIME_HOURS_FEW, IDS_TIME_HOURS_MANY
+ },
+ {
+ IDS_TIME_DAYS_DEFAULT, IDS_TIME_DAY_SINGULAR, IDS_TIME_DAYS_ZERO,
+ IDS_TIME_DAYS_TWO, IDS_TIME_DAYS_FEW, IDS_TIME_DAYS_MANY
+ }
+} };
+
+static const MessageIDs kTimeRemainingMessageIDs = { {
+ {
+ IDS_TIME_REMAINING_SECS_DEFAULT, IDS_TIME_REMAINING_SEC_SINGULAR,
+ IDS_TIME_REMAINING_SECS_ZERO, IDS_TIME_REMAINING_SECS_TWO,
+ IDS_TIME_REMAINING_SECS_FEW, IDS_TIME_REMAINING_SECS_MANY
+ },
+ {
+ IDS_TIME_REMAINING_MINS_DEFAULT, IDS_TIME_REMAINING_MIN_SINGULAR,
+ IDS_TIME_REMAINING_MINS_ZERO, IDS_TIME_REMAINING_MINS_TWO,
+ IDS_TIME_REMAINING_MINS_FEW, IDS_TIME_REMAINING_MINS_MANY
+ },
+ {
+ IDS_TIME_REMAINING_HOURS_DEFAULT, IDS_TIME_REMAINING_HOUR_SINGULAR,
+ IDS_TIME_REMAINING_HOURS_ZERO, IDS_TIME_REMAINING_HOURS_TWO,
+ IDS_TIME_REMAINING_HOURS_FEW, IDS_TIME_REMAINING_HOURS_MANY
+ },
+ {
+ IDS_TIME_REMAINING_DAYS_DEFAULT, IDS_TIME_REMAINING_DAY_SINGULAR,
+ IDS_TIME_REMAINING_DAYS_ZERO, IDS_TIME_REMAINING_DAYS_TWO,
+ IDS_TIME_REMAINING_DAYS_FEW, IDS_TIME_REMAINING_DAYS_MANY
+ }
+} };
+
+static const MessageIDs kTimeElapsedMessageIDs = { {
+ {
+ IDS_TIME_ELAPSED_SECS_DEFAULT, IDS_TIME_ELAPSED_SEC_SINGULAR,
+ IDS_TIME_ELAPSED_SECS_ZERO, IDS_TIME_ELAPSED_SECS_TWO,
+ IDS_TIME_ELAPSED_SECS_FEW, IDS_TIME_ELAPSED_SECS_MANY
+ },
+ {
+ IDS_TIME_ELAPSED_MINS_DEFAULT, IDS_TIME_ELAPSED_MIN_SINGULAR,
+ IDS_TIME_ELAPSED_MINS_ZERO, IDS_TIME_ELAPSED_MINS_TWO,
+ IDS_TIME_ELAPSED_MINS_FEW, IDS_TIME_ELAPSED_MINS_MANY
+ },
+ {
+ IDS_TIME_ELAPSED_HOURS_DEFAULT, IDS_TIME_ELAPSED_HOUR_SINGULAR,
+ IDS_TIME_ELAPSED_HOURS_ZERO, IDS_TIME_ELAPSED_HOURS_TWO,
+ IDS_TIME_ELAPSED_HOURS_FEW, IDS_TIME_ELAPSED_HOURS_MANY
+ },
+ {
+ IDS_TIME_ELAPSED_DAYS_DEFAULT, IDS_TIME_ELAPSED_DAY_SINGULAR,
+ IDS_TIME_ELAPSED_DAYS_ZERO, IDS_TIME_ELAPSED_DAYS_TWO,
+ IDS_TIME_ELAPSED_DAYS_FEW, IDS_TIME_ELAPSED_DAYS_MANY
+ }
+} };
+
+// Different format types.
+enum FormatType {
+ FORMAT_SHORT,
+ FORMAT_REMAINING,
+ FORMAT_ELAPSED,
+};
+
+} // namespace
+
+class TimeFormatter {
+ public:
+ const std::vector<icu::PluralFormat*>& formatter(FormatType format_type) {
+ switch (format_type) {
+ case FORMAT_SHORT:
+ return short_formatter_;
+ case FORMAT_REMAINING:
+ return time_left_formatter_;
+ case FORMAT_ELAPSED:
+ return time_elapsed_formatter_;
+ default:
+ NOTREACHED();
+ return short_formatter_;
+ }
+ }
+ private:
+ static const MessageIDs& GetMessageIDs(FormatType format_type) {
+ switch (format_type) {
+ case FORMAT_SHORT:
+ return kTimeShortMessageIDs;
+ case FORMAT_REMAINING:
+ return kTimeRemainingMessageIDs;
+ case FORMAT_ELAPSED:
+ return kTimeElapsedMessageIDs;
+ default:
+ NOTREACHED();
+ return kTimeShortMessageIDs;
+ }
+ }
+
+ static const char* GetFallbackFormatSuffix(FormatType format_type) {
+ switch (format_type) {
+ case FORMAT_SHORT:
+ return kFallbackFormatSuffixShort;
+ case FORMAT_REMAINING:
+ return kFallbackFormatSuffixLeft;
+ case FORMAT_ELAPSED:
+ return kFallbackFormatSuffixAgo;
+ default:
+ NOTREACHED();
+ return kFallbackFormatSuffixShort;
+ }
+ }
+
+ TimeFormatter() {
+ BuildFormats(FORMAT_SHORT, &short_formatter_);
+ BuildFormats(FORMAT_REMAINING, &time_left_formatter_);
+ BuildFormats(FORMAT_ELAPSED, &time_elapsed_formatter_);
+ }
+ ~TimeFormatter() {
+ STLDeleteContainerPointers(short_formatter_.begin(),
+ short_formatter_.end());
+ STLDeleteContainerPointers(time_left_formatter_.begin(),
+ time_left_formatter_.end());
+ STLDeleteContainerPointers(time_elapsed_formatter_.begin(),
+ time_elapsed_formatter_.end());
+ }
+ friend class Singleton<TimeFormatter>;
+ friend struct DefaultSingletonTraits<TimeFormatter>;
+
+ std::vector<icu::PluralFormat*> short_formatter_;
+ std::vector<icu::PluralFormat*> time_left_formatter_;
+ std::vector<icu::PluralFormat*> time_elapsed_formatter_;
+ static void BuildFormats(FormatType format_type,
+ std::vector<icu::PluralFormat*>* time_formats);
+ static icu::PluralFormat* createFallbackFormat(
+ const icu::PluralRules& rules, int index, FormatType format_type);
+
+ DISALLOW_COPY_AND_ASSIGN(TimeFormatter);
+};
+
+void TimeFormatter::BuildFormats(
+ FormatType format_type, std::vector<icu::PluralFormat*>* time_formats) {
+ static const icu::UnicodeString kKeywords[] = {
+ UNICODE_STRING_SIMPLE("other"), UNICODE_STRING_SIMPLE("one"),
+ UNICODE_STRING_SIMPLE("zero"), UNICODE_STRING_SIMPLE("two"),
+ UNICODE_STRING_SIMPLE("few"), UNICODE_STRING_SIMPLE("many")
+ };
+ UErrorCode err = U_ZERO_ERROR;
+ scoped_ptr<icu::PluralRules> rules(
+ icu::PluralRules::forLocale(icu::Locale::getDefault(), err));
+ if (U_FAILURE(err)) {
+ err = U_ZERO_ERROR;
+ icu::UnicodeString fallback_rules("one: n is 1", -1, US_INV);
+ rules.reset(icu::PluralRules::createRules(fallback_rules, err));
+ DCHECK(U_SUCCESS(err));
+ }
+
+ const MessageIDs& message_ids = GetMessageIDs(format_type);
+
+ for (int i = 0; i < 4; ++i) {
+ icu::UnicodeString pattern;
+ for (size_t j = 0; j < arraysize(kKeywords); ++j) {
+ int msg_id = message_ids.ids[i][j];
+ std::string sub_pattern = WideToUTF8(l10n_util::GetString(msg_id));
+ // NA means this keyword is not used in the current locale.
+ // Even if a translator translated for this keyword, we do not
+ // use it unless it's 'other' (j=0) or it's defined in the rules
+ // for the current locale. Special-casing of 'other' will be removed
+ // once ICU's isKeyword is fixed to return true for isKeyword('other').
+ if (sub_pattern.compare("NA") != 0 &&
+ (j == 0 || rules->isKeyword(kKeywords[j]))) {
+ pattern += kKeywords[j];
+ pattern += UNICODE_STRING_SIMPLE("{");
+ pattern += icu::UnicodeString(sub_pattern.c_str(), "UTF-8");
+ pattern += UNICODE_STRING_SIMPLE("}");
+ }
+ }
+ icu::PluralFormat* format = new icu::PluralFormat(*rules, pattern, err);
+ if (U_SUCCESS(err)) {
+ time_formats->push_back(format);
+ } else {
+ delete format;
+ time_formats->push_back(createFallbackFormat(*rules, i, format_type));
+ // Reset it so that next ICU call can proceed.
+ err = U_ZERO_ERROR;
+ }
+ }
+}
+
+// Create a hard-coded fallback plural format. This will never be called
+// unless translators make a mistake.
+icu::PluralFormat* TimeFormatter::createFallbackFormat(
+ const icu::PluralRules& rules, int index, FormatType format_type) {
+ static const icu::UnicodeString kUnits[4][2] = {
+ { UNICODE_STRING_SIMPLE("sec"), UNICODE_STRING_SIMPLE("secs") },
+ { UNICODE_STRING_SIMPLE("min"), UNICODE_STRING_SIMPLE("mins") },
+ { UNICODE_STRING_SIMPLE("hour"), UNICODE_STRING_SIMPLE("hours") },
+ { UNICODE_STRING_SIMPLE("day"), UNICODE_STRING_SIMPLE("days") }
+ };
+ icu::UnicodeString suffix(GetFallbackFormatSuffix(format_type), -1, US_INV);
+ icu::UnicodeString pattern;
+ if (rules.isKeyword(UNICODE_STRING_SIMPLE("one"))) {
+ pattern += UNICODE_STRING_SIMPLE("one{# ") + kUnits[index][0] + suffix;
+ }
+ pattern += UNICODE_STRING_SIMPLE(" other{# ") + kUnits[index][1] + suffix;
+ UErrorCode err = U_ZERO_ERROR;
+ icu::PluralFormat* format = new icu::PluralFormat(rules, pattern, err);
+ DCHECK(U_SUCCESS(err));
+ return format;
+}
+
+Singleton<TimeFormatter> time_formatter;
+
+static std::wstring FormatTimeImpl(const TimeDelta& delta,
+ FormatType format_type) {
+ if (delta.ToInternalValue() < 0) {
+ NOTREACHED() << "Negative duration";
+ return std::wstring();
+ }
+
+ int number;
+
+ const std::vector<icu::PluralFormat*>& formatters =
+ time_formatter->formatter(format_type);
+
+ UErrorCode error = U_ZERO_ERROR;
+ icu::UnicodeString time_string;
+ // Less than a minute gets "X seconds left"
+ if (delta.ToInternalValue() < Time::kMicrosecondsPerMinute) {
+ number = static_cast<int>(delta.ToInternalValue() /
+ Time::kMicrosecondsPerSecond);
+ time_string = formatters[0]->format(number, error);
+
+ // Less than 1 hour gets "X minutes left".
+ } else if (delta.ToInternalValue() < Time::kMicrosecondsPerHour) {
+ number = static_cast<int>(delta.ToInternalValue() /
+ Time::kMicrosecondsPerMinute);
+ time_string = formatters[1]->format(number, error);
+
+ // Less than 1 day remaining gets "X hours left"
+ } else if (delta.ToInternalValue() < Time::kMicrosecondsPerDay) {
+ number = static_cast<int>(delta.ToInternalValue() /
+ Time::kMicrosecondsPerHour);
+ time_string = formatters[2]->format(number, error);
+
+ // Anything bigger gets "X days left"
+ } else {
+ number = static_cast<int>(delta.ToInternalValue() /
+ Time::kMicrosecondsPerDay);
+ time_string = formatters[3]->format(number, error);
+ }
+
+ // With the fallback added, this should never fail.
+ DCHECK(U_SUCCESS(error));
+ int capacity = time_string.length() + 1;
+ string16 result_utf16;
+ time_string.extract(static_cast<UChar*>(
+ WriteInto(&result_utf16, capacity)),
+ capacity, error);
+ DCHECK(U_SUCCESS(error));
+ return UTF16ToWide(result_utf16);
+}
+
+// static
+std::wstring TimeFormat::TimeElapsed(const TimeDelta& delta) {
+ return FormatTimeImpl(delta, FORMAT_ELAPSED);
+}
+
+// static
+std::wstring TimeFormat::TimeRemaining(const TimeDelta& delta) {
+ return FormatTimeImpl(delta, FORMAT_REMAINING);
+}
+
+// static
+std::wstring TimeFormat::TimeRemainingShort(const TimeDelta& delta) {
+ return FormatTimeImpl(delta, FORMAT_SHORT);
+}
+
+// static
+std::wstring TimeFormat::RelativeDate(
+ const Time& time,
+ const Time* optional_midnight_today) {
+ Time midnight_today = optional_midnight_today ? *optional_midnight_today :
+ Time::Now().LocalMidnight();
+
+ // Filter out "today" and "yesterday"
+ if (time >= midnight_today)
+ return l10n_util::GetString(IDS_PAST_TIME_TODAY);
+ else if (time >= midnight_today -
+ TimeDelta::FromMicroseconds(Time::kMicrosecondsPerDay))
+ return l10n_util::GetString(IDS_PAST_TIME_YESTERDAY);
+
+ return std::wstring();
+}
diff --git a/chrome/common/time_format.h b/chrome/common/time_format.h
new file mode 100644
index 0000000..c04ed62
--- /dev/null
+++ b/chrome/common/time_format.h
@@ -0,0 +1,52 @@
+// Copyright (c) 2006-2008 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_COMMON_TIME_FORMAT_H__
+#define CHROME_COMMON_TIME_FORMAT_H__
+
+// This file defines methods to format time values as strings.
+
+#include <string>
+
+#include "unicode/smpdtfmt.h"
+
+namespace base {
+class Time;
+class TimeDelta;
+}
+
+class TimeFormat {
+ public:
+ // TimeElapsed, TimeRemaining and TimeRemainingShort functions:
+ // These functions return a localized string of approximate time duration. The
+ // conditions are simpler than PastTime since these functions are used for
+ // in-progress operations and users have different expectations of units.
+
+ // Returns times in elapsed-format: "3 mins ago", "2 days ago".
+ static std::wstring TimeElapsed(const base::TimeDelta& delta);
+
+ // Returns times in remaining-format: "3 mins left", "2 days left".
+ static std::wstring TimeRemaining(const base::TimeDelta& delta);
+
+ // Returns times in short-format: "3 mins", "2 days".
+ static std::wstring TimeRemainingShort(const base::TimeDelta& delta);
+
+ // For displaying a relative time in the past. This method returns either
+ // "Today", "Yesterday", or an empty string if it's older than that.
+ //
+ // TODO(brettw): This should be able to handle days in the future like
+ // "Tomorrow".
+ // TODO(tc): This should be able to do things like "Last week". This
+ // requires handling singluar/plural for all languages.
+ //
+ // The second parameter is optional, it is midnight of "Now" for relative day
+ // computations: Time::Now().LocalMidnight()
+ // If NULL, the current day's midnight will be retrieved, which can be
+ // slow. If many items are being processed, it is best to get the current
+ // time once at the beginning and pass it for each computation.
+ static std::wstring RelativeDate(const base::Time& time,
+ const base::Time* optional_midnight_today);
+};
+
+#endif // CHROME_COMMON_TIME_FORMAT_H__
diff --git a/chrome/common/time_format_unittest.cc b/chrome/common/time_format_unittest.cc
new file mode 100644
index 0000000..d437859
--- /dev/null
+++ b/chrome/common/time_format_unittest.cc
@@ -0,0 +1,69 @@
+// Copyright (c) 2006-2008 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 <time.h>
+
+#include "app/l10n_util.h"
+#include "base/basictypes.h"
+#include "base/time.h"
+#include "chrome/common/time_format.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+using base::Time;
+using base::TimeDelta;
+
+TEST(TimeFormat, RelativeDate) {
+ Time now = Time::Now();
+ std::wstring today_str = TimeFormat::RelativeDate(now, NULL);
+ EXPECT_EQ(L"Today", today_str);
+
+ Time yesterday = now - TimeDelta::FromDays(1);
+ std::wstring yesterday_str = TimeFormat::RelativeDate(yesterday, NULL);
+ EXPECT_EQ(L"Yesterday", yesterday_str);
+
+ Time two_days_ago = now - TimeDelta::FromDays(2);
+ std::wstring two_days_ago_str = TimeFormat::RelativeDate(two_days_ago, NULL);
+ EXPECT_TRUE(two_days_ago_str.empty());
+
+ Time a_week_ago = now - TimeDelta::FromDays(7);
+ std::wstring a_week_ago_str = TimeFormat::RelativeDate(a_week_ago, NULL);
+ EXPECT_TRUE(a_week_ago_str.empty());
+}
+
+namespace {
+void TestTimeFormats(const TimeDelta delta, const std::wstring& expected) {
+ std::wstring expected_left = expected + L" left";
+ std::wstring expected_ago = expected + L" ago";
+ EXPECT_EQ(expected, TimeFormat::TimeRemainingShort(delta));
+ EXPECT_EQ(expected_left, TimeFormat::TimeRemaining(delta));
+ EXPECT_EQ(expected_ago, TimeFormat::TimeElapsed(delta));
+}
+
+} // namespace
+
+TEST(TimeFormat, FormatTime) {
+ const TimeDelta one_day = TimeDelta::FromDays(1);
+ const TimeDelta three_days = TimeDelta::FromDays(3);
+ const TimeDelta one_hour = TimeDelta::FromHours(1);
+ const TimeDelta four_hours = TimeDelta::FromHours(4);
+ const TimeDelta one_min = TimeDelta::FromMinutes(1);
+ const TimeDelta three_mins = TimeDelta::FromMinutes(3);
+ const TimeDelta one_sec = TimeDelta::FromSeconds(1);
+ const TimeDelta five_secs = TimeDelta::FromSeconds(5);
+ const TimeDelta twohundred_millisecs = TimeDelta::FromMilliseconds(200);
+
+ // TODO(jungshik) : These test only pass when the OS locale is 'en'.
+ // We need to add SetUp() and TearDown() to set the locale to 'en'.
+ TestTimeFormats(twohundred_millisecs, L"0 secs");
+ TestTimeFormats(one_sec - twohundred_millisecs, L"0 secs");
+ TestTimeFormats(one_sec + twohundred_millisecs, L"1 sec");
+ TestTimeFormats(five_secs + twohundred_millisecs, L"5 secs");
+ TestTimeFormats(one_min + five_secs, L"1 min");
+ TestTimeFormats(three_mins + twohundred_millisecs, L"3 mins");
+ TestTimeFormats(one_hour + five_secs, L"1 hour");
+ TestTimeFormats(four_hours + five_secs, L"4 hours");
+ TestTimeFormats(one_day + five_secs, L"1 day");
+ TestTimeFormats(three_days, L"3 days");
+ TestTimeFormats(three_days + four_hours, L"3 days");
+}
diff --git a/chrome/common/translate_errors.h b/chrome/common/translate_errors.h
new file mode 100644
index 0000000..1c6ea8a
--- /dev/null
+++ b/chrome/common/translate_errors.h
@@ -0,0 +1,30 @@
+// Copyright (c) 2010 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_COMMON_TRANSLATE_ERRORS_H_
+#define CHROME_COMMON_TRANSLATE_ERRORS_H_
+
+// This file consolidates all the error types for translation of a page.
+
+class TranslateErrors {
+ public:
+ enum Type {
+ NONE = 0,
+ NETWORK, // No connectivity.
+ INITIALIZATION_ERROR, // The translation script failed to initialize.
+ UNKNOWN_LANGUAGE, // The page's language could not be detected.
+ UNSUPPORTED_LANGUAGE, // The server detected a language that the browser
+ // does not know.
+ IDENTICAL_LANGUAGES, // The original and target languages are the same.
+ TRANSLATION_ERROR, // An error was reported by the translation script
+ // during translation.
+ };
+
+ private:
+ TranslateErrors() {}
+
+ DISALLOW_COPY_AND_ASSIGN(TranslateErrors);
+};
+
+#endif // CHROME_COMMON_TRANSLATE_ERRORS_H_
diff --git a/chrome/common/url_constants.cc b/chrome/common/url_constants.cc
new file mode 100644
index 0000000..a2a32bd
--- /dev/null
+++ b/chrome/common/url_constants.cc
@@ -0,0 +1,134 @@
+// Copyright (c) 2010 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 <stdlib.h>
+
+#include "chrome/common/url_constants.h"
+#include "googleurl/src/url_util.h"
+
+namespace chrome {
+
+const char kAboutScheme[] = "about";
+const char kChromeInternalScheme[] = "chrome-internal";
+const char kChromeUIScheme[] = "chrome";
+const char kDataScheme[] = "data";
+const char kExtensionScheme[] = "chrome-extension";
+const char kFileScheme[] = "file";
+const char kFtpScheme[] = "ftp";
+const char kGearsScheme[] = "gears";
+const char kHttpScheme[] = "http";
+const char kHttpsScheme[] = "https";
+const char kJavaScriptScheme[] = "javascript";
+const char kMailToScheme[] = "mailto";
+const char kMetadataScheme[] = "metadata";
+const char kUserScriptScheme[] = "chrome-user-script";
+const char kViewSourceScheme[] = "view-source";
+
+#if defined(OS_CHROMEOS)
+const char kCrosScheme[] = "cros";
+#endif
+
+const char kStandardSchemeSeparator[] = "://";
+
+const char* kSavableSchemes[] = {
+ kHttpScheme,
+ kHttpsScheme,
+ kFileScheme,
+ kFtpScheme,
+ kExtensionScheme,
+ kChromeUIScheme,
+ NULL
+};
+
+const char kAboutAppCacheInternalsURL[] = "about:appcache-internals";
+const char kAboutBlankURL[] = "about:blank";
+const char kAboutCacheURL[] = "about:cache";
+const char kAboutCrashURL[] = "about:crash";
+const char kAboutCreditsURL[] = "about:credits";
+const char kAboutHangURL[] = "about:hang";
+const char kAboutMemoryURL[] = "about:memory";
+const char kAboutNetInternalsURL[] = "about:net-internals";
+const char kAboutPluginsURL[] = "about:plugins";
+const char kAboutShorthangURL[] = "about:shorthang";
+const char kAboutSystemURL[] = "about:system";
+const char kAboutTermsURL[] = "about:terms";
+const char kAboutAboutURL[] = "about:about";
+const char kAboutDNSURL[] = "about:dns";
+const char kAboutHistogramsURL[] = "about:histograms";
+const char kAboutVersionURL[] = "about:version";
+
+// Use an obfuscated URL to make this nondiscoverable, we only want this
+// to be used for testing.
+const char kAboutBrowserCrash[] = "about:inducebrowsercrashforrealz";
+
+const char kChromeUIAppLauncherURL[] = "chrome://newtab/#mode=app-launcher";
+const char kChromeUIBookmarksURL[] = "chrome://bookmarks/";
+const char kChromeUIDevToolsURL[] = "chrome://devtools/";
+const char kChromeUIDownloadsURL[] = "chrome://downloads/";
+const char kChromeUIExtensionsURL[] = "chrome://extensions/";
+const char kChromeUIFavIconURL[] = "chrome://favicon/";
+const char kChromeUIFileBrowseURL[] = "chrome://filebrowse/";
+const char kChromeUIHistoryURL[] = "chrome://history/";
+const char kChromeUIHistory2URL[] = "chrome://history2/";
+const char kChromeUIIPCURL[] = "chrome://about/ipc";
+const char kChromeUIMediaplayerURL[] = "chrome://mediaplayer/";
+const char kChromeUINewTabURL[] = "chrome://newtab";
+const char kChromeUIOptionsURL[] = "chrome://options/";
+const char kChromeUIPluginsURL[] = "chrome://plugins/";
+const char kChromeUIPrintURL[] = "chrome://print/";
+const char kChromeUIRegisterPageURL[] = "chrome://register/";
+const char kChromeUISlideshowURL[] = "chrome://slideshow/";
+
+const char kChromeUIBookmarksHost[] = "bookmarks";
+const char kChromeUIDevToolsHost[] = "devtools";
+const char kChromeUIDialogHost[] = "dialog";
+const char kChromeUIDownloadsHost[] = "downloads";
+const char kChromeUIExtensionsHost[] = "extensions";
+const char kChromeUIFavIconHost[] = "favicon";
+const char kChromeUIFileBrowseHost[] = "filebrowse";
+const char kChromeUIHistoryHost[] = "history";
+const char kChromeUIHistory2Host[] = "history2";
+const char kChromeUIInspectorHost[] = "inspector";
+const char kChromeUIMediaplayerHost[] = "mediaplayer";
+const char kChromeUINetInternalsHost[] = "net-internals";
+const char kChromeUINewTabHost[] = "newtab";
+const char kChromeUIOptionsHost[] = "options";
+const char kChromeUIPluginsHost[] = "plugins";
+const char kChromeUIPrintHost[] = "print";
+const char kChromeUIRegisterPageHost[] = "register";
+const char kChromeUIRemotingHost[] = "remoting";
+const char kChromeUIResourcesHost[] = "resources";
+const char kChromeUISlideshowHost[] = "slideshow";
+const char kChromeUISyncResourcesHost[] = "syncresources";
+const char kChromeUIThemePath[] = "theme";
+const char kChromeUIThumbnailPath[] = "thumb";
+
+const char kAppCacheViewInternalsURL[] = "chrome://appcache-internals/";
+
+const char kCloudPrintResourcesURL[] = "chrome://cloudprintresources/";
+const char kCloudPrintResourcesHost[] = "cloudprintresources";
+
+const char kNetworkViewInternalsURL[] = "chrome://net-internals/";
+const char kNetworkViewCacheURL[] = "chrome://view-http-cache/";
+
+void RegisterChromeSchemes() {
+ // Don't need "chrome-internal" which was used in old versions of Chrome for
+ // the new tab page.
+ url_util::AddStandardScheme(kChromeUIScheme);
+ url_util::AddStandardScheme(kGearsScheme);
+ url_util::AddStandardScheme(kExtensionScheme);
+ url_util::AddStandardScheme(kMetadataScheme);
+#if defined(OS_CHROMEOS)
+ url_util::AddStandardScheme(kCrosScheme);
+#endif
+
+ // Prevent future modification of the standard schemes list. This is to
+ // prevent accidental creation of data races in the program. AddStandardScheme
+ // isn't threadsafe so must be called when GURL isn't used on any other
+ // thread. This is really easy to mess up, so we say that all calls to
+ // AddStandardScheme in Chrome must be inside this function.
+ url_util::LockStandardSchemes();
+}
+
+} // namespace chrome
diff --git a/chrome/common/url_constants.h b/chrome/common/url_constants.h
new file mode 100644
index 0000000..216ffb1
--- /dev/null
+++ b/chrome/common/url_constants.h
@@ -0,0 +1,118 @@
+// Copyright (c) 2010 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.
+
+// Contains constants for known URLs and portions thereof.
+
+#ifndef CHROME_COMMON_URL_CONSTANTS_H_
+#define CHROME_COMMON_URL_CONSTANTS_H_
+
+namespace chrome {
+
+// Canonical schemes you can use as input to GURL.SchemeIs().
+extern const char kAboutScheme[];
+extern const char kChromeInternalScheme[];
+extern const char kChromeUIScheme[]; // The scheme used for DOMUIs.
+extern const char kCrosScheme[]; // The scheme used for ChromeOS.
+extern const char kDataScheme[];
+extern const char kExtensionScheme[];
+extern const char kFileScheme[];
+extern const char kFtpScheme[];
+extern const char kGearsScheme[];
+extern const char kHttpScheme[];
+extern const char kHttpsScheme[];
+extern const char kJavaScriptScheme[];
+extern const char kMailToScheme[];
+extern const char kMetadataScheme[];
+extern const char kUserScriptScheme[];
+extern const char kViewSourceScheme[];
+
+// Used to separate a standard scheme and the hostname: "://".
+extern const char kStandardSchemeSeparator[];
+
+// Null terminated list of schemes that are savable.
+extern const char* kSavableSchemes[];
+
+// About URLs (including schemes).
+extern const char kAboutAppCacheInternalsURL[];
+extern const char kAboutBlankURL[];
+extern const char kAboutBrowserCrash[];
+extern const char kAboutCacheURL[];
+extern const char kAboutNetInternalsURL[];
+extern const char kAboutCrashURL[];
+extern const char kAboutCreditsURL[];
+extern const char kAboutHangURL[];
+extern const char kAboutMemoryURL[];
+extern const char kAboutPluginsURL[];
+extern const char kAboutShorthangURL[];
+extern const char kAboutSystemURL[];
+extern const char kAboutTermsURL[];
+extern const char kAboutAboutURL[];
+extern const char kAboutDNSURL[];
+extern const char kAboutHistogramsURL[];
+extern const char kAboutVersionURL[];
+
+// chrome: URLs (including schemes). Should be kept in sync with the
+// components below.
+extern const char kChromeUIAppLauncherURL[];
+extern const char kChromeUIBookmarksURL[];
+extern const char kChromeUIDevToolsURL[];
+extern const char kChromeUIDownloadsURL[];
+extern const char kChromeUIExtensionsURL[];
+extern const char kChromeUIFavIconURL[];
+extern const char kChromeUIFileBrowseURL[];
+extern const char kChromeUIHistoryURL[];
+extern const char kChromeUIHistory2URL[];
+extern const char kChromeUIIPCURL[];
+extern const char kChromeUIMediaplayerURL[];
+extern const char kChromeUINewTabURL[];
+extern const char kChromeUIOptionsURL[];
+extern const char kChromeUIPluginsURL[];
+extern const char kChromeUIPrintURL[];
+extern const char kChromeUIRegisterPageURL[];
+extern const char kChromeUISlideshowURL[];
+
+// chrome components of URLs. Should be kept in sync with the full URLs
+// above.
+extern const char kChromeUIBookmarksHost[];
+extern const char kChromeUIDevToolsHost[];
+extern const char kChromeUIDialogHost[];
+extern const char kChromeUIDownloadsHost[];
+extern const char kChromeUIExtensionsHost[];
+extern const char kChromeUIFavIconHost[];
+extern const char kChromeUIFileBrowseHost[];
+extern const char kChromeUIHistoryHost[];
+extern const char kChromeUIHistory2Host[];
+extern const char kChromeUIInspectorHost[];
+extern const char kChromeUIMediaplayerHost[];
+extern const char kChromeUINetInternalsHost[];
+extern const char kChromeUINewTabHost[];
+extern const char kChromeUIOptionsHost[];
+extern const char kChromeUIPluginsHost[];
+extern const char kChromeUIPrintHost[];
+extern const char kChromeUIRegisterPageHost[];
+extern const char kChromeUIRemotingHost[];
+extern const char kChromeUIResourcesHost[];
+extern const char kChromeUISlideshowHost[];
+extern const char kChromeUISyncResourcesHost[];
+extern const char kChromeUIThumbnailPath[];
+extern const char kChromeUIThemePath[];
+
+// AppCache related URL.
+extern const char kAppCacheViewInternalsURL[];
+
+// Cloud Print dialog URL components.
+extern const char kCloudPrintResourcesURL[];
+extern const char kCloudPrintResourcesHost[];
+
+// Network related URLs.
+extern const char kNetworkViewCacheURL[];
+extern const char kNetworkViewInternalsURL[];
+
+// Call near the beginning of startup to register Chrome's internal URLs that
+// should be parsed as "standard" with the googleurl library.
+void RegisterChromeSchemes();
+
+} // namespace chrome
+
+#endif // CHROME_COMMON_URL_CONSTANTS_H_
diff --git a/chrome/common/utility_messages.h b/chrome/common/utility_messages.h
new file mode 100644
index 0000000..867131f
--- /dev/null
+++ b/chrome/common/utility_messages.h
@@ -0,0 +1,78 @@
+// Copyright (c) 2009 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_COMMON_UTILITY_MESSAGES_H_
+#define CHROME_COMMON_UTILITY_MESSAGES_H_
+
+#include <string>
+#include <vector>
+
+#include "base/basictypes.h"
+#include "base/file_path.h"
+#include "base/values.h"
+#include "chrome/common/common_param_traits.h"
+#include "chrome/common/extensions/update_manifest.h"
+#include "ipc/ipc_message_utils.h"
+
+namespace IPC {
+
+// Traits for UpdateManifest::Result.
+template <>
+struct ParamTraits<UpdateManifest::Result> {
+ typedef UpdateManifest::Result param_type;
+ static void Write(Message* m, const param_type& p) {
+ WriteParam(m, p.extension_id);
+ WriteParam(m, p.version);
+ WriteParam(m, p.browser_min_version);
+ WriteParam(m, p.package_hash);
+ WriteParam(m, p.crx_url);
+ }
+ static bool Read(const Message* m, void** iter, param_type* p) {
+ return ReadParam(m, iter, &p->extension_id) &&
+ ReadParam(m, iter, &p->version) &&
+ ReadParam(m, iter, &p->browser_min_version) &&
+ ReadParam(m, iter, &p->package_hash) &&
+ ReadParam(m, iter, &p->crx_url);
+ }
+ static void Log(const param_type& p, std::wstring* l) {
+ l->append(L"(");
+ LogParam(p.extension_id, l);
+ l->append(L", ");
+ LogParam(p.version, l);
+ l->append(L", ");
+ LogParam(p.browser_min_version, l);
+ l->append(L", ");
+ LogParam(p.package_hash, l);
+ l->append(L", ");
+ LogParam(p.crx_url, l);
+ l->append(L")");
+ }
+};
+
+template<>
+struct ParamTraits<UpdateManifest::Results> {
+ typedef UpdateManifest::Results param_type;
+ static void Write(Message* m, const param_type& p) {
+ WriteParam(m, p.list);
+ WriteParam(m, p.daystart_elapsed_seconds);
+ }
+ static bool Read(const Message* m, void** iter, param_type* p) {
+ return ReadParam(m, iter, &p->list) &&
+ ReadParam(m, iter, &p->daystart_elapsed_seconds);
+ }
+ static void Log(const param_type& p, std::wstring* l) {
+ l->append(L"(");
+ LogParam(p.list, l);
+ l->append(L", ");
+ LogParam(p.daystart_elapsed_seconds, l);
+ l->append(L")");
+ }
+};
+
+} // namespace IPC
+
+#define MESSAGES_INTERNAL_FILE "chrome/common/utility_messages_internal.h"
+#include "ipc/ipc_message_macros.h"
+
+#endif // CHROME_COMMON_UTILITY_MESSAGES_H_
diff --git a/chrome/common/utility_messages_internal.h b/chrome/common/utility_messages_internal.h
new file mode 100644
index 0000000..9231501
--- /dev/null
+++ b/chrome/common/utility_messages_internal.h
@@ -0,0 +1,114 @@
+// Copyright (c) 2009 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 <string>
+#include <vector>
+
+// This header is meant to be included in multiple passes, hence no traditional
+// header guard. It is included by utility_messages_internal.h
+// See ipc_message_macros.h for explanation of the macros and passes.
+
+// This file needs to be included again, even though we're actually included
+// from it via utility_messages.h.
+#include "ipc/ipc_message_macros.h"
+
+#include "base/platform_file.h"
+#include "gfx/rect.h"
+#include "printing/native_metafile.h"
+#include "printing/page_range.h"
+#include "third_party/skia/include/core/SkBitmap.h"
+
+//------------------------------------------------------------------------------
+// Utility process messages:
+// These are messages from the browser to the utility process.
+IPC_BEGIN_MESSAGES(Utility)
+
+ // Tell the utility process to unpack the given extension file in its
+ // directory and verify that it is valid.
+ IPC_MESSAGE_CONTROL1(UtilityMsg_UnpackExtension,
+ FilePath /* extension_filename */)
+
+ // Tell the utility process to parse the given JSON data and verify its
+ // validity.
+ IPC_MESSAGE_CONTROL1(UtilityMsg_UnpackWebResource,
+ std::string /* JSON data */)
+
+ // Tell the utility process to parse the given xml document.
+ IPC_MESSAGE_CONTROL1(UtilityMsg_ParseUpdateManifest,
+ std::string /* xml document contents */)
+
+ // Tell the utility process to decode the given image data.
+ IPC_MESSAGE_CONTROL1(UtilityMsg_DecodeImage,
+ std::vector<unsigned char>) // encoded image contents
+
+ // Tell the utility process to render the given PDF into a metafile.
+ IPC_MESSAGE_CONTROL4(UtilityMsg_RenderPDFPagesToMetafile,
+ base::PlatformFile, // PDF file
+ gfx::Rect, // Render Area
+ int, // DPI
+ std::vector<printing::PageRange>)
+IPC_END_MESSAGES(Utility)
+
+//------------------------------------------------------------------------------
+// Utility process host messages:
+// These are messages from the utility process to the browser.
+IPC_BEGIN_MESSAGES(UtilityHost)
+
+ // Reply when the utility process is done unpacking an extension. |manifest|
+ // is the parsed manifest.json file.
+ // The unpacker should also have written out files containing the decoded
+ // images and message catalogs from the extension. See ExtensionUnpacker for
+ // details.
+ IPC_MESSAGE_CONTROL1(UtilityHostMsg_UnpackExtension_Succeeded,
+ DictionaryValue /* manifest */)
+
+ // Reply when the utility process has failed while unpacking an extension.
+ // |error_message| is a user-displayable explanation of what went wrong.
+ IPC_MESSAGE_CONTROL1(UtilityHostMsg_UnpackExtension_Failed,
+ std::string /* error_message, if any */)
+
+ // Reply when the utility process is done unpacking and parsing JSON data
+ // from a web resource.
+ IPC_MESSAGE_CONTROL1(UtilityHostMsg_UnpackWebResource_Succeeded,
+ DictionaryValue /* json data */)
+
+ // Reply when the utility process has failed while unpacking and parsing a
+ // web resource. |error_message| is a user-readable explanation of what
+ // went wrong.
+ IPC_MESSAGE_CONTROL1(UtilityHostMsg_UnpackWebResource_Failed,
+ std::string /* error_message, if any */)
+
+ // Reply when the utility process has succeeded in parsing an update manifest
+ // xml document.
+ IPC_MESSAGE_CONTROL1(UtilityHostMsg_ParseUpdateManifest_Succeeded,
+ UpdateManifest::Results /* updates */)
+
+ // Reply when an error occured parsing the update manifest. |error_message|
+ // is a description of what went wrong suitable for logging.
+ IPC_MESSAGE_CONTROL1(UtilityHostMsg_ParseUpdateManifest_Failed,
+ std::string /* error_message, if any */)
+
+ // Reply when the utility process has succeeded in decoding the image.
+ IPC_MESSAGE_CONTROL1(UtilityHostMsg_DecodeImage_Succeeded,
+ SkBitmap) // decoded image
+
+ // Reply when an error occured decoding the image.
+ IPC_MESSAGE_CONTROL0(UtilityHostMsg_DecodeImage_Failed)
+
+ // Reply when the utility process has succeeded in rendering the PDF.
+ IPC_MESSAGE_CONTROL2(UtilityHostMsg_RenderPDFPagesToMetafile_Succeeded,
+ printing::NativeMetafile, // Output metafile
+ int) // Highest rendered page number
+
+ // Reply when an error occured rendering the PDF.
+ IPC_MESSAGE_CONTROL0(UtilityHostMsg_RenderPDFPagesToMetafile_Failed)
+
+#if defined(OS_WIN)
+ // Request that the given font be loaded by the host so it's cached by the
+ // OS. Please see ChildProcessHost::PreCacheFont for details.
+ IPC_SYNC_MESSAGE_CONTROL1_0(UtilityHostMsg_PreCacheFont,
+ LOGFONT /* font data */)
+#endif // defined(OS_WIN)
+
+IPC_END_MESSAGES(UtilityHost)
diff --git a/chrome/common/view_types.cc b/chrome/common/view_types.cc
new file mode 100644
index 0000000..c32174b
--- /dev/null
+++ b/chrome/common/view_types.cc
@@ -0,0 +1,14 @@
+// Copyright (c) 2010 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/common/view_types.h"
+
+const char* ViewType::kTabContents = "TAB";
+const char* ViewType::kToolstrip = "TOOLSTRIP";
+const char* ViewType::kMole = "MOLE";
+const char* ViewType::kBackgroundPage = "BACKGROUND";
+const char* ViewType::kPopup = "POPUP";
+const char* ViewType::kInfobar = "INFOBAR";
+const char* ViewType::kNotification = "NOTIFICATION";
+const char* ViewType::kAll = "ALL";
diff --git a/chrome/common/view_types.h b/chrome/common/view_types.h
new file mode 100644
index 0000000..697ebbd
--- /dev/null
+++ b/chrome/common/view_types.h
@@ -0,0 +1,45 @@
+// Copyright (c) 2010 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_COMMON_VIEW_TYPES_H_
+#define CHROME_COMMON_VIEW_TYPES_H_
+
+#include "base/basictypes.h"
+
+// Indicates different types of views
+class ViewType {
+ public:
+ enum Type {
+ INVALID,
+ BACKGROUND_CONTENTS,
+ TAB_CONTENTS,
+ EXTENSION_TOOLSTRIP,
+ EXTENSION_MOLE,
+ EXTENSION_BACKGROUND_PAGE,
+ EXTENSION_POPUP,
+ EXTENSION_INFOBAR,
+ DEV_TOOLS_UI,
+ INTERSTITIAL_PAGE,
+ NOTIFICATION,
+ };
+
+ // Constant strings corresponding to the Type enumeration values. Used
+ // when converting JS arguments.
+ static const char* kTabContents;
+ static const char* kToolstrip;
+ static const char* kMole;
+ static const char* kBackgroundPage;
+ static const char* kPopup;
+ static const char* kInfobar;
+ static const char* kNotification;
+ static const char* kAll;
+
+ private:
+ // This class is for scoping only, so you shouldn't create an instance of it.
+ ViewType() {}
+
+ DISALLOW_COPY_AND_ASSIGN(ViewType);
+};
+
+#endif // CHROME_COMMON_VIEW_TYPES_H_
diff --git a/chrome/common/visitedlink_common.cc b/chrome/common/visitedlink_common.cc
new file mode 100644
index 0000000..2782311
--- /dev/null
+++ b/chrome/common/visitedlink_common.cc
@@ -0,0 +1,89 @@
+// Copyright (c) 2006-2008 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/common/visitedlink_common.h"
+
+#include "base/logging.h"
+#include "base/md5.h"
+
+const VisitedLinkCommon::Fingerprint VisitedLinkCommon::null_fingerprint_ = 0;
+const VisitedLinkCommon::Hash VisitedLinkCommon::null_hash_ = -1;
+
+VisitedLinkCommon::VisitedLinkCommon()
+ : hash_table_(NULL),
+ table_length_(0) {
+}
+
+VisitedLinkCommon::~VisitedLinkCommon() {
+}
+
+// FIXME: this uses linear probing, it should be replaced with quadratic
+// probing or something better. See VisitedLinkMaster::AddFingerprint
+bool VisitedLinkCommon::IsVisited(const char* canonical_url,
+ size_t url_len) const {
+ if (url_len == 0)
+ return false;
+ if (!hash_table_ || table_length_ == 0)
+ return false;
+ return IsVisited(ComputeURLFingerprint(canonical_url, url_len));
+}
+
+bool VisitedLinkCommon::IsVisited(Fingerprint fingerprint) const {
+ // Go through the table until we find the item or an empty spot (meaning it
+ // wasn't found). This loop will terminate as long as the table isn't full,
+ // which should be enforced by AddFingerprint.
+ Hash first_hash = HashFingerprint(fingerprint);
+ Hash cur_hash = first_hash;
+ while (true) {
+ Fingerprint cur_fingerprint = FingerprintAt(cur_hash);
+ if (cur_fingerprint == null_fingerprint_)
+ return false; // End of probe sequence found.
+ if (cur_fingerprint == fingerprint)
+ return true; // Found a match.
+
+ // This spot was taken, but not by the item we're looking for, search in
+ // the next position.
+ cur_hash++;
+ if (cur_hash == table_length_)
+ cur_hash = 0;
+ if (cur_hash == first_hash) {
+ // Wrapped around and didn't find an empty space, this means we're in an
+ // infinite loop because AddFingerprint didn't do its job resizing.
+ NOTREACHED();
+ return false;
+ }
+ }
+}
+
+// Uses the top 64 bits of the MD5 sum of the canonical URL as the fingerprint,
+// this is as random as any other subset of the MD5SUM.
+//
+// FIXME: this uses the MD5SUM of the 16-bit character version. For systems
+// where wchar_t is not 16 bits (Linux uses 32 bits, I think), this will not be
+// compatable. We should define explicitly what should happen here across
+// platforms, and convert if necessary (probably to UTF-16).
+
+// static
+VisitedLinkCommon::Fingerprint VisitedLinkCommon::ComputeURLFingerprint(
+ const char* canonical_url,
+ size_t url_len,
+ const uint8 salt[LINK_SALT_LENGTH]) {
+ DCHECK(url_len > 0) << "Canonical URLs should not be empty";
+
+ MD5Context ctx;
+ MD5Init(&ctx);
+ MD5Update(&ctx, salt, sizeof(salt));
+ MD5Update(&ctx, canonical_url, url_len * sizeof(char));
+
+ MD5Digest digest;
+ MD5Final(&digest, &ctx);
+
+ // This is the same as "return *(Fingerprint*)&digest.a;" but if we do that
+ // direct cast the alignment could be wrong, and we can't access a 64-bit int
+ // on arbitrary alignment on some processors. This reinterpret_casts it
+ // down to a char array of the same size as fingerprint, and then does the
+ // bit cast, which amounts to a memcpy. This does not handle endian issues.
+ return bit_cast<Fingerprint, uint8[8]>(
+ *reinterpret_cast<uint8(*)[8]>(&digest.a));
+}
diff --git a/chrome/common/visitedlink_common.h b/chrome/common/visitedlink_common.h
new file mode 100644
index 0000000..0e79c04
--- /dev/null
+++ b/chrome/common/visitedlink_common.h
@@ -0,0 +1,137 @@
+// Copyright (c) 2006-2008 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_COMMON_VISITEDLINK_COMMON_H__
+#define CHROME_COMMON_VISITEDLINK_COMMON_H__
+
+#include <string>
+#include <vector>
+
+#include "base/basictypes.h"
+#include "base/logging.h"
+#include "googleurl/src/gurl.h"
+
+// number of bytes in the salt
+#define LINK_SALT_LENGTH 8
+
+// A multiprocess-safe database of the visited links for the browser. There
+// should be exactly one process that has write access (implemented by
+// VisitedLinkMaster), while all other processes should be read-only
+// (implemented by VisitedLinkSlave). These other processes add links by calling
+// the writer process to add them for it. The writer may also notify the readers
+// to replace their table when the table is resized.
+//
+// IPC is not implemented in these classes. This is done through callback
+// functions supplied by the creator of these objects to allow more flexibility,
+// especially for testing.
+//
+// This class defines the common base for these others. We implement accessors
+// for looking things up in the hash table, and for computing hash values and
+// fingerprints. Both the master and the slave inherit from this, and add their
+// own code to set up and change these values as their design requires. The
+// slave pretty much just sets up the shared memory and saves the pointer. The
+// master does a lot of work to manage the table, reading and writing it to and
+// from disk, and resizing it when it gets too full.
+//
+// To ask whether a page is in history, we compute a 64-bit fingerprint of the
+// URL. This URL is hashed and we see if it is in the URL hashtable. If it is,
+// we consider it visited. Otherwise, it is unvisited. Note that it is possible
+// to get collisions, which is the penalty for not storing all URL strings in
+// memory (which could get to be more than we want to have in memory). We use
+// a salt value for the links on one computer so that an attacker can not
+// manually create a link that causes a collision.
+class VisitedLinkCommon {
+ public:
+ // A number that identifies the URL.
+ typedef uint64 Fingerprint;
+ typedef std::vector<Fingerprint> Fingerprints;
+
+ // A hash value of a fingerprint
+ typedef int32 Hash;
+
+ // A fingerprint or hash value that does not exist
+ static const Fingerprint null_fingerprint_;
+ static const Hash null_hash_;
+
+ VisitedLinkCommon();
+ virtual ~VisitedLinkCommon();
+
+ // Returns the fingerprint for the given URL.
+ Fingerprint ComputeURLFingerprint(const char* canonical_url,
+ size_t url_len) const {
+ return ComputeURLFingerprint(canonical_url, url_len, salt_);
+ }
+
+ // Looks up the given key in the table. The fingerprint for the URL is
+ // computed if you call one with the string argument. Returns true if found.
+ // Does not modify the hastable.
+ bool IsVisited(const char* canonical_url, size_t url_len) const;
+ bool IsVisited(const GURL& url) const {
+ return IsVisited(url.spec().data(), url.spec().size());
+ }
+ bool IsVisited(Fingerprint fingerprint) const;
+
+#ifdef UNIT_TEST
+ // Returns statistics about DB usage
+ void GetUsageStatistics(int32* table_size,
+ VisitedLinkCommon::Fingerprint** fingerprints) {
+ *table_size = table_length_;
+ *fingerprints = hash_table_;
+ }
+#endif
+
+ protected:
+ // This structure is at the beginning of the shared memory so that the slaves
+ // can get stats on the table
+ struct SharedHeader {
+ // see goes into table_length_
+ uint32 length;
+
+ // goes into salt_
+ uint8 salt[LINK_SALT_LENGTH];
+ };
+
+ // Returns the fingerprint at the given index into the URL table. This
+ // function should be called instead of accessing the table directly to
+ // contain endian issues.
+ Fingerprint FingerprintAt(int32 table_offset) const {
+ if (!hash_table_)
+ return null_fingerprint_;
+ return hash_table_[table_offset];
+ }
+
+ // Computes the fingerprint of the given canonical URL. It is static so the
+ // same algorithm can be re-used by the table rebuilder, so you will have to
+ // pass the salt as a parameter. See the non-static version above if you
+ // want to use the current class' salt.
+ static Fingerprint ComputeURLFingerprint(const char* canonical_url,
+ size_t url_len,
+ const uint8 salt[LINK_SALT_LENGTH]);
+
+ // Computes the hash value of the given fingerprint, this is used as a lookup
+ // into the hashtable.
+ static Hash HashFingerprint(Fingerprint fingerprint, int32 table_length) {
+ if (table_length == 0)
+ return null_hash_;
+ return static_cast<Hash>(fingerprint % table_length);
+ }
+ // Uses the current hashtable.
+ Hash HashFingerprint(Fingerprint fingerprint) const {
+ return HashFingerprint(fingerprint, table_length_);
+ }
+
+ // pointer to the first item
+ VisitedLinkCommon::Fingerprint* hash_table_;
+
+ // the number of items in the hash table
+ int32 table_length_;
+
+ // salt used for each URL when computing the fingerprint
+ uint8 salt_[LINK_SALT_LENGTH];
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(VisitedLinkCommon);
+};
+
+#endif // CHROME_COMMON_VISITEDLINK_COMMON_H_
diff --git a/chrome/common/web_database_observer_impl.cc b/chrome/common/web_database_observer_impl.cc
new file mode 100644
index 0000000..8c008e4
--- /dev/null
+++ b/chrome/common/web_database_observer_impl.cc
@@ -0,0 +1,52 @@
+// Copyright (c) 2010 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/common/web_database_observer_impl.h"
+
+#include "base/auto_reset.h"
+#include "base/message_loop.h"
+#include "base/string16.h"
+#include "chrome/common/render_messages.h"
+#include "third_party/WebKit/WebKit/chromium/public/WebDatabase.h"
+
+WebDatabaseObserverImpl::WebDatabaseObserverImpl(
+ IPC::Message::Sender* sender)
+ : sender_(sender),
+ waiting_for_dbs_to_close_(false) {
+}
+
+void WebDatabaseObserverImpl::databaseOpened(
+ const WebKit::WebDatabase& database) {
+ string16 origin_identifier = database.securityOrigin().databaseIdentifier();
+ string16 database_name = database.name();
+ sender_->Send(new ViewHostMsg_DatabaseOpened(
+ origin_identifier, database_name,
+ database.displayName(), database.estimatedSize()));
+ database_connections_.AddConnection(origin_identifier, database_name);
+}
+
+void WebDatabaseObserverImpl::databaseModified(
+ const WebKit::WebDatabase& database) {
+ sender_->Send(new ViewHostMsg_DatabaseModified(
+ database.securityOrigin().databaseIdentifier(), database.name()));
+}
+
+void WebDatabaseObserverImpl::databaseClosed(
+ const WebKit::WebDatabase& database) {
+ string16 origin_identifier = database.securityOrigin().databaseIdentifier();
+ string16 database_name = database.name();
+ sender_->Send(new ViewHostMsg_DatabaseClosed(
+ origin_identifier, database_name));
+ database_connections_.RemoveConnection(origin_identifier, database_name);
+ if (waiting_for_dbs_to_close_ && database_connections_.IsEmpty())
+ MessageLoop::current()->Quit();
+}
+
+void WebDatabaseObserverImpl::WaitForAllDatabasesToClose() {
+ if (!database_connections_.IsEmpty()) {
+ AutoReset<bool> waiting_for_dbs_auto_reset(&waiting_for_dbs_to_close_, true);
+ MessageLoop::ScopedNestableTaskAllower nestable(MessageLoop::current());
+ MessageLoop::current()->Run();
+ }
+}
diff --git a/chrome/common/web_database_observer_impl.h b/chrome/common/web_database_observer_impl.h
new file mode 100644
index 0000000..3f5e80b
--- /dev/null
+++ b/chrome/common/web_database_observer_impl.h
@@ -0,0 +1,27 @@
+// Copyright (c) 2010 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_COMMON_WEB_DATABASE_OBSERVER_IMPL_H_
+#define CHROME_COMMON_WEB_DATABASE_OBSERVER_IMPL_H_
+
+#include "ipc/ipc_message.h"
+#include "third_party/WebKit/WebKit/chromium/public/WebDatabaseObserver.h"
+#include "webkit/database/database_connections.h"
+
+class WebDatabaseObserverImpl : public WebKit::WebDatabaseObserver {
+ public:
+ explicit WebDatabaseObserverImpl(IPC::Message::Sender* sender);
+ virtual void databaseOpened(const WebKit::WebDatabase& database);
+ virtual void databaseModified(const WebKit::WebDatabase& database);
+ virtual void databaseClosed(const WebKit::WebDatabase& database);
+
+ void WaitForAllDatabasesToClose();
+
+ private:
+ IPC::Message::Sender* sender_;
+ bool waiting_for_dbs_to_close_;
+ webkit_database::DatabaseConnections database_connections_;
+};
+
+#endif // CHROME_COMMON_WEB_DATABASE_OBSERVER_IMPL_H_
diff --git a/chrome/common/web_resource/web_resource_unpacker.cc b/chrome/common/web_resource/web_resource_unpacker.cc
new file mode 100644
index 0000000..bbb14cf
--- /dev/null
+++ b/chrome/common/web_resource/web_resource_unpacker.cc
@@ -0,0 +1,38 @@
+// Copyright (c) 2009 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/common/web_resource/web_resource_unpacker.h"
+
+#include "base/json/json_reader.h"
+#include "base/values.h"
+
+const char* WebResourceUnpacker::kInvalidDataTypeError =
+ "Data from web resource server is missing or not valid JSON.";
+
+const char* WebResourceUnpacker::kUnexpectedJSONFormatError =
+ "Data from web resource server does not have expected format.";
+
+// TODO(mrc): Right now, this reads JSON data from the experimental popgadget
+// server. Change so the format is based on a template, once we have
+// decided on final server format.
+bool WebResourceUnpacker::Run() {
+ scoped_ptr<Value> value;
+ if (!resource_data_.empty()) {
+ value.reset(base::JSONReader::Read(resource_data_, false));
+ if (!value.get()) {
+ // Page information not properly read, or corrupted.
+ error_message_ = kInvalidDataTypeError;
+ return false;
+ }
+ if (!value->IsType(Value::TYPE_DICTIONARY)) {
+ error_message_ = kUnexpectedJSONFormatError;
+ return false;
+ }
+ parsed_json_.reset(static_cast<DictionaryValue*>(value.release()));
+ return true;
+ }
+ error_message_ = kInvalidDataTypeError;
+ return false;
+}
+
diff --git a/chrome/common/web_resource/web_resource_unpacker.h b/chrome/common/web_resource/web_resource_unpacker.h
new file mode 100644
index 0000000..f07c06f
--- /dev/null
+++ b/chrome/common/web_resource/web_resource_unpacker.h
@@ -0,0 +1,57 @@
+// Copyright (c) 2009 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.
+
+// This class is called by the WebResourceService in a sandboxed process
+// to unpack data retrieved from a web resource feed. Right now, it
+// takes a string of data in JSON format, parses it, and hands it back
+// to the WebResourceService as a list of items. In the future
+// it will be set up to unpack and verify image data in addition to
+// just parsing a JSON feed.
+
+#ifndef CHROME_COMMON_WEB_RESOURCE_WEB_RESOURCE_UNPACKER_H_
+#define CHROME_COMMON_WEB_RESOURCE_WEB_RESOURCE_UNPACKER_H_
+
+#include <string>
+
+#include "base/file_path.h"
+#include "base/scoped_ptr.h"
+
+class DictionaryValue;
+
+class WebResourceUnpacker {
+ public:
+ static const char* kInvalidDataTypeError;
+ static const char* kUnexpectedJSONFormatError;
+
+ explicit WebResourceUnpacker(const std::string &resource_data)
+ : resource_data_(resource_data) {}
+
+ // This does the actual parsing. In case of an error, error_message_
+ // is set to an appropriate value.
+ bool Run();
+
+ // Returns the last error message set by Run().
+ const std::string& error_message() { return error_message_; }
+
+ // Gets data which has been parsed by Run().
+ DictionaryValue* parsed_json() {
+ return parsed_json_.get();
+ }
+
+ private:
+ // Holds the string which is to be parsed.
+ std::string resource_data_;
+
+ // Holds the result of JSON parsing of resource_data_.
+ scoped_ptr<DictionaryValue> parsed_json_;
+
+ // Holds the last error message produced by Run().
+ std::string error_message_;
+
+ DISALLOW_COPY_AND_ASSIGN(WebResourceUnpacker);
+};
+
+#endif // CHROME_COMMON_WEB_RESOURCE_WEB_RESOURCE_UNPACKER_H_
+
+
diff --git a/chrome/common/webkit_param_traits.h b/chrome/common/webkit_param_traits.h
new file mode 100644
index 0000000..e277e38
--- /dev/null
+++ b/chrome/common/webkit_param_traits.h
@@ -0,0 +1,442 @@
+// Copyright (c) 2010 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.
+//
+// This file contains ParamTraits templates to support serialization of WebKit
+// data types over IPC.
+//
+// NOTE: IT IS IMPORTANT THAT ONLY POD (plain old data) TYPES ARE SERIALIZED.
+//
+// There are several reasons for this restrictions:
+//
+// o We don't want inclusion of this file to imply linking to WebKit code.
+//
+// o Many WebKit structures are not thread-safe. WebString, for example,
+// contains a reference counted buffer, which does not use thread-safe
+// reference counting. If we allowed serializing WebString, then we may run
+// the risk of introducing subtle thread-safety bugs if people passed a
+// WebString across threads via PostTask(NewRunnableMethod(...)).
+//
+// o The WebKit API has redundant types for strings, and we should avoid using
+// those beyond code that interfaces with the WebKit API.
+
+#ifndef CHROME_COMMON_WEBKIT_PARAM_TRAITS_H_
+#define CHROME_COMMON_WEBKIT_PARAM_TRAITS_H_
+
+#include "ipc/ipc_message_utils.h"
+#include "third_party/WebKit/WebKit/chromium/public/WebCache.h"
+#include "third_party/WebKit/WebKit/chromium/public/WebCompositionUnderline.h"
+#include "third_party/WebKit/WebKit/chromium/public/WebConsoleMessage.h"
+#include "third_party/WebKit/WebKit/chromium/public/WebContextMenuData.h"
+#include "third_party/WebKit/WebKit/chromium/public/WebDragOperation.h"
+#include "third_party/WebKit/WebKit/chromium/public/WebFindOptions.h"
+#include "third_party/WebKit/WebKit/chromium/public/WebInputEvent.h"
+#include "third_party/WebKit/WebKit/chromium/public/WebMediaPlayerAction.h"
+#include "third_party/WebKit/WebKit/chromium/public/WebPopupType.h"
+#include "third_party/WebKit/WebKit/chromium/public/WebScreenInfo.h"
+#include "third_party/WebKit/WebKit/chromium/public/WebTextDirection.h"
+#include "third_party/WebKit/WebKit/chromium/public/WebTextInputType.h"
+
+namespace IPC {
+
+template <>
+struct ParamTraits<WebKit::WebRect> {
+ typedef WebKit::WebRect param_type;
+ static void Write(Message* m, const param_type& p) {
+ WriteParam(m, p.x);
+ WriteParam(m, p.y);
+ WriteParam(m, p.width);
+ WriteParam(m, p.height);
+ }
+ static bool Read(const Message* m, void** iter, param_type* p) {
+ return
+ ReadParam(m, iter, &p->x) &&
+ ReadParam(m, iter, &p->y) &&
+ ReadParam(m, iter, &p->width) &&
+ ReadParam(m, iter, &p->height);
+ }
+ static void Log(const param_type& p, std::wstring* l) {
+ l->append(L"(");
+ LogParam(p.x, l);
+ l->append(L", ");
+ LogParam(p.y, l);
+ l->append(L", ");
+ LogParam(p.width, l);
+ l->append(L", ");
+ LogParam(p.height, l);
+ l->append(L")");
+ }
+};
+
+template <>
+struct ParamTraits<WebKit::WebScreenInfo> {
+ typedef WebKit::WebScreenInfo param_type;
+ static void Write(Message* m, const param_type& p) {
+ WriteParam(m, p.depth);
+ WriteParam(m, p.depthPerComponent);
+ WriteParam(m, p.isMonochrome);
+ WriteParam(m, p.rect);
+ WriteParam(m, p.availableRect);
+ }
+ static bool Read(const Message* m, void** iter, param_type* p) {
+ return
+ ReadParam(m, iter, &p->depth) &&
+ ReadParam(m, iter, &p->depthPerComponent) &&
+ ReadParam(m, iter, &p->isMonochrome) &&
+ ReadParam(m, iter, &p->rect) &&
+ ReadParam(m, iter, &p->availableRect);
+ }
+ static void Log(const param_type& p, std::wstring* l) {
+ l->append(L"(");
+ LogParam(p.depth, l);
+ l->append(L", ");
+ LogParam(p.depthPerComponent, l);
+ l->append(L", ");
+ LogParam(p.isMonochrome, l);
+ l->append(L", ");
+ LogParam(p.rect, l);
+ l->append(L", ");
+ LogParam(p.availableRect, l);
+ l->append(L")");
+ }
+};
+
+template <>
+struct ParamTraits<WebKit::WebConsoleMessage::Level> {
+ typedef WebKit::WebConsoleMessage::Level param_type;
+ static void Write(Message* m, const param_type& p) {
+ WriteParam(m, static_cast<int>(p));
+ }
+ static bool Read(const Message* m, void** iter, param_type* r) {
+ int value;
+ if (!ReadParam(m, iter, &value))
+ return false;
+ *r = static_cast<param_type>(value);
+ return true;
+ }
+ static void Log(const param_type& p, std::wstring* l) {
+ LogParam(static_cast<int>(p), l);
+ }
+};
+
+template <>
+struct ParamTraits<WebKit::WebPopupType> {
+ typedef WebKit::WebPopupType param_type;
+ static void Write(Message* m, const param_type& p) {
+ WriteParam(m, static_cast<int>(p));
+ }
+ static bool Read(const Message* m, void** iter, param_type* r) {
+ int value;
+ if (!ReadParam(m, iter, &value))
+ return false;
+ *r = static_cast<param_type>(value);
+ return true;
+ }
+ static void Log(const param_type& p, std::wstring* l) {
+ LogParam(static_cast<int>(p), l);
+ }
+};
+
+template <>
+struct ParamTraits<WebKit::WebFindOptions> {
+ typedef WebKit::WebFindOptions param_type;
+ static void Write(Message* m, const param_type& p) {
+ WriteParam(m, p.forward);
+ WriteParam(m, p.matchCase);
+ WriteParam(m, p.findNext);
+ }
+ static bool Read(const Message* m, void** iter, param_type* p) {
+ return
+ ReadParam(m, iter, &p->forward) &&
+ ReadParam(m, iter, &p->matchCase) &&
+ ReadParam(m, iter, &p->findNext);
+ }
+ static void Log(const param_type& p, std::wstring* l) {
+ l->append(L"(");
+ LogParam(p.forward, l);
+ l->append(L", ");
+ LogParam(p.matchCase, l);
+ l->append(L", ");
+ LogParam(p.findNext, l);
+ l->append(L")");
+ }
+};
+
+template <>
+struct ParamTraits<WebKit::WebInputEvent::Type> {
+ typedef WebKit::WebInputEvent::Type param_type;
+ static void Write(Message* m, const param_type& p) {
+ m->WriteInt(p);
+ }
+ static bool Read(const Message* m, void** iter, param_type* p) {
+ int type;
+ if (!m->ReadInt(iter, &type))
+ return false;
+ *p = static_cast<WebKit::WebInputEvent::Type>(type);
+ return true;
+ }
+ static void Log(const param_type& p, std::wstring* l) {
+ const wchar_t* type;
+ switch (p) {
+ case WebKit::WebInputEvent::MouseDown:
+ type = L"MouseDown";
+ break;
+ case WebKit::WebInputEvent::MouseUp:
+ type = L"MouseUp";
+ break;
+ case WebKit::WebInputEvent::MouseMove:
+ type = L"MouseMove";
+ break;
+ case WebKit::WebInputEvent::MouseLeave:
+ type = L"MouseLeave";
+ break;
+ case WebKit::WebInputEvent::MouseEnter:
+ type = L"MouseEnter";
+ break;
+ case WebKit::WebInputEvent::MouseWheel:
+ type = L"MouseWheel";
+ break;
+ case WebKit::WebInputEvent::RawKeyDown:
+ type = L"RawKeyDown";
+ break;
+ case WebKit::WebInputEvent::KeyDown:
+ type = L"KeyDown";
+ break;
+ case WebKit::WebInputEvent::KeyUp:
+ type = L"KeyUp";
+ break;
+ default:
+ type = L"None";
+ break;
+ }
+ LogParam(std::wstring(type), l);
+ }
+};
+
+template <>
+struct ParamTraits<WebKit::WebCache::UsageStats> {
+ typedef WebKit::WebCache::UsageStats param_type;
+ static void Write(Message* m, const param_type& p) {
+ WriteParam(m, p.minDeadCapacity);
+ WriteParam(m, p.maxDeadCapacity);
+ WriteParam(m, p.capacity);
+ WriteParam(m, p.liveSize);
+ WriteParam(m, p.deadSize);
+ }
+ static bool Read(const Message* m, void** iter, param_type* r) {
+ return
+ ReadParam(m, iter, &r->minDeadCapacity) &&
+ ReadParam(m, iter, &r->maxDeadCapacity) &&
+ ReadParam(m, iter, &r->capacity) &&
+ ReadParam(m, iter, &r->liveSize) &&
+ ReadParam(m, iter, &r->deadSize);
+ }
+ static void Log(const param_type& p, std::wstring* l) {
+ l->append(L"<WebCache::UsageStats>");
+ }
+};
+
+template <>
+struct ParamTraits<WebKit::WebCache::ResourceTypeStat> {
+ typedef WebKit::WebCache::ResourceTypeStat param_type;
+ static void Write(Message* m, const param_type& p) {
+ WriteParam(m, p.count);
+ WriteParam(m, p.size);
+ WriteParam(m, p.liveSize);
+ WriteParam(m, p.decodedSize);
+ }
+ static bool Read(const Message* m, void** iter, param_type* r) {
+ bool result =
+ ReadParam(m, iter, &r->count) &&
+ ReadParam(m, iter, &r->size) &&
+ ReadParam(m, iter, &r->liveSize) &&
+ ReadParam(m, iter, &r->decodedSize);
+ return result;
+ }
+ static void Log(const param_type& p, std::wstring* l) {
+ l->append(StringPrintf(L"%d %d %d %d", p.count, p.size, p.liveSize,
+ p.decodedSize));
+ }
+};
+
+template <>
+struct ParamTraits<WebKit::WebCache::ResourceTypeStats> {
+ typedef WebKit::WebCache::ResourceTypeStats param_type;
+ static void Write(Message* m, const param_type& p) {
+ WriteParam(m, p.images);
+ WriteParam(m, p.cssStyleSheets);
+ WriteParam(m, p.scripts);
+ WriteParam(m, p.xslStyleSheets);
+ WriteParam(m, p.fonts);
+ }
+ static bool Read(const Message* m, void** iter, param_type* r) {
+ bool result =
+ ReadParam(m, iter, &r->images) &&
+ ReadParam(m, iter, &r->cssStyleSheets) &&
+ ReadParam(m, iter, &r->scripts) &&
+ ReadParam(m, iter, &r->xslStyleSheets) &&
+ ReadParam(m, iter, &r->fonts);
+ return result;
+ }
+ static void Log(const param_type& p, std::wstring* l) {
+ l->append(L"<WebCoreStats>");
+ LogParam(p.images, l);
+ LogParam(p.cssStyleSheets, l);
+ LogParam(p.scripts, l);
+ LogParam(p.xslStyleSheets, l);
+ LogParam(p.fonts, l);
+ l->append(L"</WebCoreStats>");
+ }
+};
+
+template <>
+struct ParamTraits<WebKit::WebTextDirection> {
+ typedef WebKit::WebTextDirection param_type;
+ static void Write(Message* m, const param_type& p) {
+ WriteParam(m, static_cast<int>(p));
+ }
+ static bool Read(const Message* m, void** iter, param_type* r) {
+ int value;
+ if (!ReadParam(m, iter, &value))
+ return false;
+ *r = static_cast<param_type>(value);
+ return true;
+ }
+ static void Log(const param_type& p, std::wstring* l) {
+ LogParam(static_cast<int>(p), l);
+ }
+};
+
+template <>
+struct ParamTraits<WebKit::WebDragOperation> {
+ typedef WebKit::WebDragOperation param_type;
+ static void Write(Message* m, const param_type& p) {
+ m->WriteInt(p);
+ }
+ static bool Read(const Message* m, void** iter, param_type* r) {
+ int temp;
+ bool res = m->ReadInt(iter, &temp);
+ *r = static_cast<param_type>(temp);
+ return res;
+ }
+ static void Log(const param_type& p, std::wstring* l) {
+ l->append(StringPrintf(L"%d", p));
+ }
+};
+
+template <>
+struct ParamTraits<WebKit::WebMediaPlayerAction> {
+ typedef WebKit::WebMediaPlayerAction param_type;
+ static void Write(Message* m, const param_type& p) {
+ WriteParam(m, static_cast<int>(p.type));
+ WriteParam(m, p.enable);
+ }
+ static bool Read(const Message* m, void** iter, param_type* r) {
+ int temp;
+ if (!ReadParam(m, iter, &temp))
+ return false;
+ r->type = static_cast<param_type::Type>(temp);
+ return ReadParam(m, iter, &r->enable);
+ }
+ static void Log(const param_type& p, std::wstring* l) {
+ l->append(L"(");
+ switch (p.type) {
+ case WebKit::WebMediaPlayerAction::Play:
+ l->append(L"Play");
+ break;
+ case WebKit::WebMediaPlayerAction::Mute:
+ l->append(L"Mute");
+ break;
+ case WebKit::WebMediaPlayerAction::Loop:
+ l->append(L"Loop");
+ break;
+ default:
+ l->append(L"Unknown");
+ break;
+ }
+ l->append(L", ");
+ LogParam(p.enable, l);
+ l->append(L")");
+ }
+};
+
+template <>
+ struct ParamTraits<WebKit::WebContextMenuData::MediaType> {
+ typedef WebKit::WebContextMenuData::MediaType param_type;
+ static void Write(Message* m, const param_type& p) {
+ m->WriteInt(p);
+ }
+ static bool Read(const Message* m, void** iter, param_type* r) {
+ int temp;
+ bool res = m->ReadInt(iter, &temp);
+ *r = static_cast<param_type>(temp);
+ return res;
+ }
+};
+
+template <>
+struct ParamTraits<WebKit::WebCompositionUnderline> {
+ typedef WebKit::WebCompositionUnderline param_type;
+ static void Write(Message* m, const param_type& p) {
+ WriteParam(m, p.startOffset);
+ WriteParam(m, p.endOffset);
+ WriteParam(m, p.color);
+ WriteParam(m, p.thick);
+ }
+ static bool Read(const Message* m, void** iter, param_type* p) {
+ return
+ ReadParam(m, iter, &p->startOffset) &&
+ ReadParam(m, iter, &p->endOffset) &&
+ ReadParam(m, iter, &p->color) &&
+ ReadParam(m, iter, &p->thick);
+ }
+ static void Log(const param_type& p, std::wstring* l) {
+ l->append(L"(");
+ LogParam(p.startOffset, l);
+ l->append(L",");
+ LogParam(p.endOffset, l);
+ l->append(L":");
+ LogParam(p.color, l);
+ l->append(L":");
+ LogParam(p.thick, l);
+ l->append(L")");
+ }
+};
+
+template <>
+struct ParamTraits<WebKit::WebTextInputType> {
+ typedef WebKit::WebTextInputType param_type;
+ static void Write(Message* m, const param_type& p) {
+ m->WriteInt(p);
+ }
+ static bool Read(const Message* m, void** iter, param_type* p) {
+ int type;
+ if (!m->ReadInt(iter, &type))
+ return false;
+ *p = static_cast<param_type>(type);
+ return true;
+ }
+ static void Log(const param_type& p, std::wstring* l) {
+ std::wstring control;
+ switch (p) {
+ case WebKit::WebTextInputTypeNone:
+ control = L"WebKit::WebTextInputTypeNone";
+ break;
+ case WebKit::WebTextInputTypeText:
+ control = L"WebKit::WebTextInputTypeText";
+ break;
+ case WebKit::WebTextInputTypePassword:
+ control = L"WebKit::WebTextInputTypePassword";
+ break;
+ default:
+ NOTIMPLEMENTED();
+ control = L"UNKNOWN";
+ break;
+ }
+ LogParam(control, l);
+ }
+};
+
+} // namespace IPC
+
+#endif // CHROME_COMMON_WEBKIT_PARAM_TRAITS_H_
diff --git a/chrome/common/webmessageportchannel_impl.cc b/chrome/common/webmessageportchannel_impl.cc
new file mode 100644
index 0000000..24304fd
--- /dev/null
+++ b/chrome/common/webmessageportchannel_impl.cc
@@ -0,0 +1,237 @@
+// Copyright (c) 2009 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/common/webmessageportchannel_impl.h"
+
+#include "chrome/common/child_process.h"
+#include "chrome/common/child_thread.h"
+#include "chrome/common/worker_messages.h"
+#include "third_party/WebKit/WebKit/chromium/public/WebString.h"
+#include "third_party/WebKit/WebKit/chromium/public/WebMessagePortChannelClient.h"
+
+using WebKit::WebMessagePortChannel;
+using WebKit::WebMessagePortChannelArray;
+using WebKit::WebMessagePortChannelClient;
+using WebKit::WebString;
+
+WebMessagePortChannelImpl::WebMessagePortChannelImpl()
+ : client_(NULL),
+ route_id_(MSG_ROUTING_NONE),
+ message_port_id_(MSG_ROUTING_NONE) {
+ AddRef();
+ Init();
+}
+
+WebMessagePortChannelImpl::WebMessagePortChannelImpl(
+ int route_id,
+ int message_port_id)
+ : client_(NULL),
+ route_id_(route_id),
+ message_port_id_(message_port_id) {
+ AddRef();
+ Init();
+}
+
+WebMessagePortChannelImpl::~WebMessagePortChannelImpl() {
+ // If we have any queued messages with attached ports, manually destroy them.
+ while (!message_queue_.empty()) {
+ const std::vector<WebMessagePortChannelImpl*>& channel_array =
+ message_queue_.front().ports;
+ for (size_t i = 0; i < channel_array.size(); i++) {
+ channel_array[i]->destroy();
+ }
+ message_queue_.pop();
+ }
+
+ if (message_port_id_ != MSG_ROUTING_NONE)
+ Send(new WorkerProcessHostMsg_DestroyMessagePort(message_port_id_));
+
+ if (route_id_ != MSG_ROUTING_NONE)
+ ChildThread::current()->RemoveRoute(route_id_);
+}
+
+void WebMessagePortChannelImpl::setClient(WebMessagePortChannelClient* client) {
+ // Must lock here since client_ is called on the main thread.
+ AutoLock auto_lock(lock_);
+ client_ = client;
+}
+
+void WebMessagePortChannelImpl::destroy() {
+ setClient(NULL);
+
+ // Release the object on the main thread, since the destructor might want to
+ // send an IPC, and that has to happen on the main thread.
+ ChildThread::current()->message_loop()->ReleaseSoon(FROM_HERE, this);
+}
+
+void WebMessagePortChannelImpl::entangle(WebMessagePortChannel* channel) {
+ // The message port ids might not be set up yet, if this channel wasn't
+ // created on the main thread. So need to wait until we're on the main thread
+ // before getting the other message port id.
+ scoped_refptr<WebMessagePortChannelImpl> webchannel =
+ static_cast<WebMessagePortChannelImpl*>(channel);
+ Entangle(webchannel);
+}
+
+void WebMessagePortChannelImpl::postMessage(
+ const WebString& message,
+ WebMessagePortChannelArray* channels) {
+ if (MessageLoop::current() != ChildThread::current()->message_loop()) {
+ ChildThread::current()->message_loop()->PostTask(FROM_HERE,
+ NewRunnableMethod(this, &WebMessagePortChannelImpl::postMessage,
+ message, channels));
+ return;
+ }
+
+ std::vector<int> message_port_ids(channels ? channels->size() : 0);
+ if (channels) {
+ // Extract the port IDs from the source array, then free it.
+ for (size_t i = 0; i < channels->size(); ++i) {
+ WebMessagePortChannelImpl* webchannel =
+ static_cast<WebMessagePortChannelImpl*>((*channels)[i]);
+ message_port_ids[i] = webchannel->message_port_id();
+ webchannel->QueueMessages();
+ DCHECK(message_port_ids[i] != MSG_ROUTING_NONE);
+ }
+ delete channels;
+ }
+
+ IPC::Message* msg = new WorkerProcessHostMsg_PostMessage(
+ message_port_id_, message, message_port_ids);
+ Send(msg);
+}
+
+bool WebMessagePortChannelImpl::tryGetMessage(
+ WebString* message,
+ WebMessagePortChannelArray& channels) {
+ AutoLock auto_lock(lock_);
+ if (message_queue_.empty())
+ return false;
+
+ *message = message_queue_.front().message;
+ const std::vector<WebMessagePortChannelImpl*>& channel_array =
+ message_queue_.front().ports;
+ WebMessagePortChannelArray result_ports(channel_array.size());
+ for (size_t i = 0; i < channel_array.size(); i++) {
+ result_ports[i] = channel_array[i];
+ }
+
+ channels.swap(result_ports);
+ message_queue_.pop();
+ return true;
+}
+
+void WebMessagePortChannelImpl::Init() {
+ if (MessageLoop::current() != ChildThread::current()->message_loop()) {
+ ChildThread::current()->message_loop()->PostTask(FROM_HERE,
+ NewRunnableMethod(this, &WebMessagePortChannelImpl::Init));
+ return;
+ }
+
+ if (route_id_ == MSG_ROUTING_NONE) {
+ DCHECK(message_port_id_ == MSG_ROUTING_NONE);
+ Send(new WorkerProcessHostMsg_CreateMessagePort(
+ &route_id_, &message_port_id_));
+ }
+
+ ChildThread::current()->AddRoute(route_id_, this);
+}
+
+void WebMessagePortChannelImpl::Entangle(
+ scoped_refptr<WebMessagePortChannelImpl> channel) {
+ if (MessageLoop::current() != ChildThread::current()->message_loop()) {
+ ChildThread::current()->message_loop()->PostTask(FROM_HERE,
+ NewRunnableMethod(this, &WebMessagePortChannelImpl::Entangle, channel));
+ return;
+ }
+
+ Send(new WorkerProcessHostMsg_Entangle(
+ message_port_id_, channel->message_port_id()));
+}
+
+void WebMessagePortChannelImpl::QueueMessages() {
+ if (MessageLoop::current() != ChildThread::current()->message_loop()) {
+ ChildThread::current()->message_loop()->PostTask(FROM_HERE,
+ NewRunnableMethod(this, &WebMessagePortChannelImpl::QueueMessages));
+ return;
+ }
+ // This message port is being sent elsewhere (perhaps to another process).
+ // The new endpoint needs to receive the queued messages, including ones that
+ // could still be in-flight. So we tell the browser to queue messages, and it
+ // sends us an ack, whose receipt we know means that no more messages are
+ // in-flight. We then send the queued messages to the browser, which prepends
+ // them to the ones it queued and it sends them to the new endpoint.
+ Send(new WorkerProcessHostMsg_QueueMessages(message_port_id_));
+
+ // The process could potentially go away while we're still waiting for
+ // in-flight messages. Ensure it stays alive.
+ ChildProcess::current()->AddRefProcess();
+}
+
+void WebMessagePortChannelImpl::Send(IPC::Message* message) {
+ if (MessageLoop::current() != ChildThread::current()->message_loop()) {
+ DCHECK(!message->is_sync());
+ ChildThread::current()->message_loop()->PostTask(FROM_HERE,
+ NewRunnableMethod(this, &WebMessagePortChannelImpl::Send, message));
+ return;
+ }
+
+ ChildThread::current()->Send(message);
+}
+
+void WebMessagePortChannelImpl::OnMessageReceived(const IPC::Message& message) {
+ IPC_BEGIN_MESSAGE_MAP(WebMessagePortChannelImpl, message)
+ IPC_MESSAGE_HANDLER(WorkerProcessMsg_Message, OnMessage)
+ IPC_MESSAGE_HANDLER(WorkerProcessMsg_MessagesQueued, OnMessagedQueued)
+ IPC_END_MESSAGE_MAP()
+}
+
+void WebMessagePortChannelImpl::OnMessage(
+ const string16& message,
+ const std::vector<int>& sent_message_port_ids,
+ const std::vector<int>& new_routing_ids) {
+ AutoLock auto_lock(lock_);
+ Message msg;
+ msg.message = message;
+ if (!sent_message_port_ids.empty()) {
+ msg.ports.resize(sent_message_port_ids.size());
+ for (size_t i = 0; i < sent_message_port_ids.size(); ++i) {
+ msg.ports[i] = new WebMessagePortChannelImpl(
+ new_routing_ids[i], sent_message_port_ids[i]);
+ }
+ }
+
+ bool was_empty = message_queue_.empty();
+ message_queue_.push(msg);
+ if (client_ && was_empty)
+ client_->messageAvailable();
+}
+
+void WebMessagePortChannelImpl::OnMessagedQueued() {
+ std::vector<QueuedMessage> queued_messages;
+
+ {
+ AutoLock auto_lock(lock_);
+ queued_messages.reserve(message_queue_.size());
+ while (!message_queue_.empty()) {
+ string16 message = message_queue_.front().message;
+ const std::vector<WebMessagePortChannelImpl*>& channel_array =
+ message_queue_.front().ports;
+ std::vector<int> port_ids(channel_array.size());
+ for (size_t i = 0; i < channel_array.size(); ++i) {
+ port_ids[i] = channel_array[i]->message_port_id();
+ }
+ queued_messages.push_back(std::make_pair(message, port_ids));
+ message_queue_.pop();
+ }
+ }
+
+ Send(new WorkerProcessHostMsg_SendQueuedMessages(
+ message_port_id_, queued_messages));
+
+ message_port_id_ = MSG_ROUTING_NONE;
+
+ Release();
+ ChildProcess::current()->ReleaseProcess();
+}
diff --git a/chrome/common/webmessageportchannel_impl.h b/chrome/common/webmessageportchannel_impl.h
new file mode 100644
index 0000000..da52b9d
--- /dev/null
+++ b/chrome/common/webmessageportchannel_impl.h
@@ -0,0 +1,74 @@
+// Copyright (c) 2009 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_COMMON_WEBMESSAGEPORTCHANNEL_IMPL_H_
+#define CHROME_COMMON_WEBMESSAGEPORTCHANNEL_IMPL_H_
+
+#include <queue>
+#include <vector>
+
+#include "base/basictypes.h"
+#include "base/lock.h"
+#include "base/string16.h"
+#include "base/ref_counted.h"
+#include "ipc/ipc_channel.h"
+#include "third_party/WebKit/WebKit/chromium/public/WebMessagePortChannel.h"
+
+// This is thread safe.
+class WebMessagePortChannelImpl
+ : public WebKit::WebMessagePortChannel,
+ public IPC::Channel::Listener,
+ public base::RefCountedThreadSafe<WebMessagePortChannelImpl> {
+ public:
+ WebMessagePortChannelImpl();
+ WebMessagePortChannelImpl(int route_id, int message_port_id);
+
+ // Queues received and incoming messages until there are no more in-flight
+ // messages, then sends all of them to the browser process.
+ void QueueMessages();
+ int message_port_id() const { return message_port_id_; }
+
+ private:
+ friend class base::RefCountedThreadSafe<WebMessagePortChannelImpl>;
+ ~WebMessagePortChannelImpl();
+
+ // WebMessagePortChannel implementation.
+ virtual void setClient(WebKit::WebMessagePortChannelClient* client);
+ virtual void destroy();
+ virtual void entangle(WebKit::WebMessagePortChannel* channel);
+ virtual void postMessage(const WebKit::WebString& message,
+ WebKit::WebMessagePortChannelArray* channels);
+ virtual bool tryGetMessage(WebKit::WebString* message,
+ WebKit::WebMessagePortChannelArray& channels);
+
+ void Init();
+ void Entangle(scoped_refptr<WebMessagePortChannelImpl> channel);
+ void Send(IPC::Message* message);
+
+ // IPC::Channel::Listener implementation.
+ virtual void OnMessageReceived(const IPC::Message& message);
+
+ void OnMessage(const string16& message,
+ const std::vector<int>& sent_message_port_ids,
+ const std::vector<int>& new_routing_ids);
+ void OnMessagedQueued();
+
+ struct Message {
+ string16 message;
+ std::vector<WebMessagePortChannelImpl*> ports;
+ };
+
+ typedef std::queue<Message> MessageQueue;
+ MessageQueue message_queue_;
+
+ WebKit::WebMessagePortChannelClient* client_;
+ Lock lock_; // Locks access to above.
+
+ int route_id_; // The routing id for this object.
+ int message_port_id_; // A globally unique identifier for this message port.
+
+ DISALLOW_COPY_AND_ASSIGN(WebMessagePortChannelImpl);
+};
+
+#endif // CHROME_COMMON_WEBMESSAGEPORTCHANNEL_IMPL_H_
diff --git a/chrome/common/win_safe_util.cc b/chrome/common/win_safe_util.cc
new file mode 100644
index 0000000..f215566
--- /dev/null
+++ b/chrome/common/win_safe_util.cc
@@ -0,0 +1,120 @@
+// Copyright (c) 2006-2008 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 <shlobj.h>
+#include <shobjidl.h>
+
+#include "chrome/common/win_safe_util.h"
+
+#include "app/win_util.h"
+#include "base/file_path.h"
+#include "base/logging.h"
+#include "base/path_service.h"
+#include "base/scoped_comptr_win.h"
+#include "base/string_util.h"
+
+namespace win_util {
+
+// This function implementation is based on the attachment execution
+// services functionally deployed with IE6 or Service pack 2. This
+// functionality is exposed in the IAttachmentExecute COM interface.
+// more information at:
+// http://msdn2.microsoft.com/en-us/library/ms647048.aspx
+bool SaferOpenItemViaShell(HWND hwnd, const std::wstring& window_title,
+ const FilePath& full_path,
+ const std::wstring& source_url) {
+ ScopedComPtr<IAttachmentExecute> attachment_services;
+ HRESULT hr = attachment_services.CreateInstance(CLSID_AttachmentServices);
+ if (FAILED(hr)) {
+ // We don't have Attachment Execution Services, it must be a pre-XP.SP2
+ // Windows installation, or the thread does not have COM initialized.
+ if (hr == CO_E_NOTINITIALIZED) {
+ NOTREACHED();
+ return false;
+ }
+ return OpenItemViaShell(full_path);
+ }
+
+ // This GUID is associated with any 'don't ask me again' settings that the
+ // user can select for different file types.
+ // {2676A9A2-D919-4fee-9187-152100393AB2}
+ static const GUID kClientID = { 0x2676a9a2, 0xd919, 0x4fee,
+ { 0x91, 0x87, 0x15, 0x21, 0x0, 0x39, 0x3a, 0xb2 } };
+
+ attachment_services->SetClientGuid(kClientID);
+
+ if (!window_title.empty())
+ attachment_services->SetClientTitle(window_title.c_str());
+
+ // To help windows decide if the downloaded file is dangerous we can provide
+ // what the documentation calls evidence. Which we provide now:
+ //
+ // Set the file itself as evidence.
+ hr = attachment_services->SetLocalPath(full_path.value().c_str());
+ if (FAILED(hr))
+ return false;
+ // Set the origin URL as evidence.
+ hr = attachment_services->SetSource(source_url.c_str());
+ if (FAILED(hr))
+ return false;
+
+ // Now check the windows policy.
+ bool do_prompt;
+ hr = attachment_services->CheckPolicy();
+ if (S_FALSE == hr) {
+ // The user prompt is required.
+ do_prompt = true;
+ } else if (S_OK == hr) {
+ // An S_OK means that the file is safe to open without user consent.
+ do_prompt = false;
+ } else {
+ // It is possible that the last call returns an undocumented result
+ // equal to 0x800c000e which seems to indicate that the URL failed the
+ // the security check. If you proceed with the Prompt() call the
+ // Shell might show a dialog that says:
+ // "windows found that this file is potentially harmful. To help protect
+ // your computer, Windows has blocked access to this file."
+ // Upon dismissal of the dialog windows will delete the file (!!).
+ // So, we can 'return' here but maybe is best to let it happen to fail on
+ // the safe side.
+ }
+ if (do_prompt) {
+ ATTACHMENT_ACTION action;
+ // We cannot control what the prompt says or does directly but it
+ // is a pretty decent dialog; for example, if an excutable is signed it can
+ // decode and show the publisher and the certificate.
+ hr = attachment_services->Prompt(hwnd, ATTACHMENT_PROMPT_EXEC, &action);
+ if (FAILED(hr) || (ATTACHMENT_ACTION_CANCEL == action))
+ {
+ // The user has declined opening the item.
+ return false;
+ }
+ }
+ return OpenItemViaShellNoZoneCheck(full_path);
+}
+
+bool SetInternetZoneIdentifier(const FilePath& full_path) {
+ const DWORD kShare = FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE;
+ std::wstring path = full_path.value() + L":Zone.Identifier";
+ HANDLE file = CreateFile(path.c_str(), GENERIC_WRITE, kShare, NULL,
+ OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
+ if (INVALID_HANDLE_VALUE == file)
+ return false;
+
+ const char kIdentifier[] = "[ZoneTransfer]\nZoneId=3";
+ DWORD written = 0;
+ BOOL result = WriteFile(file, kIdentifier, arraysize(kIdentifier), &written,
+ NULL);
+ BOOL flush_result = FlushFileBuffers(file);
+ CloseHandle(file);
+
+ if (!result || !flush_result || written != arraysize(kIdentifier)) {
+ NOTREACHED();
+ return false;
+ }
+
+ return true;
+}
+
+} // namespace win_util
diff --git a/chrome/common/win_safe_util.h b/chrome/common/win_safe_util.h
new file mode 100644
index 0000000..d9c7097
--- /dev/null
+++ b/chrome/common/win_safe_util.h
@@ -0,0 +1,51 @@
+// Copyright (c) 2006-2008 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_COMMON_WIN_SAFE_UTIL_H__
+#define CHROME_COMMON_WIN_SAFE_UTIL_H__
+
+#include <string>
+#include <windows.h>
+
+class FilePath;
+
+namespace win_util {
+
+// Open or run a downloaded file via the Windows shell, possibly showing first
+// a consent dialog if the the file is deemed dangerous. This function is an
+// enhancement over the OpenItemViaShell() function of win_util.h.
+//
+// The user consent dialog will be shown or not according to the windows
+// execution policy defined in the registry which can be overridden per user.
+// The mechanics of the policy are explained in the Microsoft Knowledge base
+// number 883260: http://support.microsoft.com/kb/883260
+//
+// The 'hwnd' is the handle to the parent window. In case a dialog is displayed
+// the parent window will be disabled since the dialog is meant to be modal.
+// The 'window_title' is the text displayed on the title bar of the dialog. If
+// you pass an empty string the dialog will have a generic 'windows security'
+// name on the title bar.
+//
+// You must provide a valid 'full_path' to the file to be opened and a well
+// formed url in 'source_url'. The url should identify the source of the file
+// but does not have to be network-reachable. If the url is malformed a
+// dialog will be shown telling the user that the file will be blocked.
+//
+// In the event that there is no default application registered for the file
+// specified by 'full_path' it ask the user, via the Windows "Open With"
+// dialog.
+// Returns 'true' on successful open, 'false' otherwise.
+bool SaferOpenItemViaShell(HWND hwnd, const std::wstring& window_title,
+ const FilePath& full_path,
+ const std::wstring& source_url);
+
+// Sets the Zone Identifier on the file to "Internet" (3). Returns true if the
+// function succeeds, false otherwise. A failure is expected on system where
+// the Zone Identifier is not supported, like a machine with a FAT32 filesystem.
+// It should not be considered fatal.
+bool SetInternetZoneIdentifier(const FilePath& full_path);
+
+} // namespace win_util
+
+#endif // CHROME_COMMON_WIN_SAFE_UTIL_H_
diff --git a/chrome/common/window_container_type.cc b/chrome/common/window_container_type.cc
new file mode 100644
index 0000000..b33618e
--- /dev/null
+++ b/chrome/common/window_container_type.cc
@@ -0,0 +1,41 @@
+// Copyright (c) 2010 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/common/window_container_type.h"
+
+#include "base/string_util.h"
+#include "third_party/WebKit/WebKit/chromium/public/WebString.h"
+#include "third_party/WebKit/WebKit/chromium/public/WebVector.h"
+#include "third_party/WebKit/WebKit/chromium/public/WebWindowFeatures.h"
+
+namespace {
+
+const char kBackground[] = "background";
+const char kPersistent[] = "persistent";
+
+}
+
+WindowContainerType WindowFeaturesToContainerType(
+ const WebKit::WebWindowFeatures& window_features) {
+ bool background = false;
+ bool persistent = false;
+
+ for (size_t i = 0; i < window_features.additionalFeatures.size(); ++i) {
+ if (LowerCaseEqualsASCII(window_features.additionalFeatures[i],
+ kBackground))
+ background = true;
+ else if (LowerCaseEqualsASCII(window_features.additionalFeatures[i],
+ kPersistent))
+ persistent = true;
+ }
+
+ if (background) {
+ if (persistent)
+ return WINDOW_CONTAINER_TYPE_PERSISTENT;
+ else
+ return WINDOW_CONTAINER_TYPE_BACKGROUND;
+ } else {
+ return WINDOW_CONTAINER_TYPE_NORMAL;
+ }
+}
diff --git a/chrome/common/window_container_type.h b/chrome/common/window_container_type.h
new file mode 100644
index 0000000..303d1cc
--- /dev/null
+++ b/chrome/common/window_container_type.h
@@ -0,0 +1,35 @@
+// Copyright (c) 2010 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_COMMON_WINDOW_CONTAINER_TYPE_H_
+#define CHROME_COMMON_WINDOW_CONTAINER_TYPE_H_
+
+namespace WebKit {
+
+struct WebWindowFeatures;
+
+}
+
+// "Container" types which can be requested via the window.open feature
+// string.
+enum WindowContainerType {
+ // A window shown in popup or tab.
+ WINDOW_CONTAINER_TYPE_NORMAL = 0,
+
+ // A window run as a hidden "background" page.
+ WINDOW_CONTAINER_TYPE_BACKGROUND,
+
+ // A window run as a hidden "background" page that wishes to be started
+ // upon browser launch and run beyond the lifetime of the pages that
+ // reference it.
+ WINDOW_CONTAINER_TYPE_PERSISTENT,
+
+ WINDOW_CONTAINER_TYPE_MAX_VALUE
+};
+
+// Conversion function:
+WindowContainerType WindowFeaturesToContainerType(
+ const WebKit::WebWindowFeatures& window_features);
+
+#endif // CHROME_COMMON_WINDOW_CONTAINER_TYPE_H_
diff --git a/chrome/common/worker_messages.h b/chrome/common/worker_messages.h
new file mode 100644
index 0000000..1228ba3
--- /dev/null
+++ b/chrome/common/worker_messages.h
@@ -0,0 +1,133 @@
+// Copyright (c) 2009 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.
+
+// Defines messages between the browser and worker process, as well as between
+// the renderer and worker process.
+
+#ifndef CHROME_COMMON_WORKER_MESSAGES_H_
+#define CHROME_COMMON_WORKER_MESSAGES_H_
+
+#include <string>
+#include <vector>
+
+#include "base/basictypes.h"
+#include "chrome/common/common_param_traits.h"
+#include "googleurl/src/gurl.h"
+#include "ipc/ipc_message_utils.h"
+
+typedef std::pair<string16, std::vector<int> > QueuedMessage;
+
+// Parameters structure for WorkerHostMsg_PostConsoleMessageToWorkerObject,
+// which has too many data parameters to be reasonably put in a predefined
+// IPC message. The data members directly correspond to parameters of
+// WebWorkerClient::postConsoleMessageToWorkerObject()
+struct WorkerHostMsg_PostConsoleMessageToWorkerObject_Params {
+ int source_identifier;
+ int message_type;
+ int message_level;
+ string16 message;
+ int line_number;
+ string16 source_url;
+};
+
+// Parameter structure for WorkerProcessMsg_CreateWorker.
+struct WorkerProcessMsg_CreateWorker_Params {
+ GURL url;
+ bool is_shared;
+ string16 name;
+ int route_id;
+ int creator_process_id;
+ int creator_appcache_host_id; // Only valid for dedicated workers.
+ int64 shared_worker_appcache_id; // Only valid for shared workers.
+};
+
+namespace IPC {
+
+// Traits for WorkerHostMsg_PostConsoleMessageToWorkerObject_Params structure
+// to pack/unpack.
+template <>
+struct ParamTraits<WorkerHostMsg_PostConsoleMessageToWorkerObject_Params> {
+ typedef WorkerHostMsg_PostConsoleMessageToWorkerObject_Params param_type;
+ static void Write(Message* m, const param_type& p) {
+ WriteParam(m, p.source_identifier);
+ WriteParam(m, p.message_type);
+ WriteParam(m, p.message_level);
+ WriteParam(m, p.message);
+ WriteParam(m, p.line_number);
+ WriteParam(m, p.source_url);
+ }
+ static bool Read(const Message* m, void** iter, param_type* p) {
+ return
+ ReadParam(m, iter, &p->source_identifier) &&
+ ReadParam(m, iter, &p->message_type) &&
+ ReadParam(m, iter, &p->message_level) &&
+ ReadParam(m, iter, &p->message) &&
+ ReadParam(m, iter, &p->line_number) &&
+ ReadParam(m, iter, &p->source_url);
+ }
+ static void Log(const param_type& p, std::wstring* l) {
+ l->append(L"(");
+ LogParam(p.source_identifier, l);
+ l->append(L", ");
+ LogParam(p.message_type, l);
+ l->append(L", ");
+ LogParam(p.message_level, l);
+ l->append(L", ");
+ LogParam(p.message, l);
+ l->append(L", ");
+ LogParam(p.line_number, l);
+ l->append(L", ");
+ LogParam(p.source_url, l);
+ l->append(L")");
+ }
+};
+
+// Traits for WorkerProcessMsg_CreateWorker_Params.
+template <>
+struct ParamTraits<WorkerProcessMsg_CreateWorker_Params> {
+ typedef WorkerProcessMsg_CreateWorker_Params param_type;
+ static void Write(Message* m, const param_type& p) {
+ WriteParam(m, p.url);
+ WriteParam(m, p.is_shared);
+ WriteParam(m, p.name);
+ WriteParam(m, p.route_id);
+ WriteParam(m, p.creator_process_id);
+ WriteParam(m, p.creator_appcache_host_id);
+ WriteParam(m, p.shared_worker_appcache_id);
+ }
+ static bool Read(const Message* m, void** iter, param_type* p) {
+ return
+ ReadParam(m, iter, &p->url) &&
+ ReadParam(m, iter, &p->is_shared) &&
+ ReadParam(m, iter, &p->name) &&
+ ReadParam(m, iter, &p->route_id) &&
+ ReadParam(m, iter, &p->creator_process_id) &&
+ ReadParam(m, iter, &p->creator_appcache_host_id) &&
+ ReadParam(m, iter, &p->shared_worker_appcache_id);
+ }
+ static void Log(const param_type& p, std::wstring* l) {
+ l->append(L"(");
+ LogParam(p.url, l);
+ l->append(L", ");
+ LogParam(p.is_shared, l);
+ l->append(L", ");
+ LogParam(p.name, l);
+ l->append(L", ");
+ LogParam(p.route_id, l);
+ l->append(L", ");
+ LogParam(p.creator_process_id, l);
+ l->append(L", ");
+ LogParam(p.creator_appcache_host_id, l);
+ l->append(L", ");
+ LogParam(p.shared_worker_appcache_id, l);
+ l->append(L")");
+ }
+};
+
+} // namespace IPC
+
+#define MESSAGES_INTERNAL_FILE "chrome/common/worker_messages_internal.h"
+#include "ipc/ipc_message_macros.h"
+
+#endif // CHROME_COMMON_WORKER_MESSAGES_H_
diff --git a/chrome/common/worker_messages_internal.h b/chrome/common/worker_messages_internal.h
new file mode 100644
index 0000000..fed4096
--- /dev/null
+++ b/chrome/common/worker_messages_internal.h
@@ -0,0 +1,126 @@
+// Copyright (c) 2009 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 <utility>
+#include <vector>
+#include "base/string16.h"
+#include "googleurl/src/gurl.h"
+#include "ipc/ipc_message_macros.h"
+
+
+//-----------------------------------------------------------------------------
+// WorkerProcess messages
+// These are messages sent from the browser to the worker process.
+IPC_BEGIN_MESSAGES(WorkerProcess)
+ IPC_MESSAGE_CONTROL1(WorkerProcessMsg_CreateWorker,
+ WorkerProcessMsg_CreateWorker_Params)
+
+ // Note: these Message Port related messages can also be sent to the
+ // renderer process. Putting them here since we don't have a shared place
+ // like common_messages_internal.h
+ IPC_MESSAGE_ROUTED3(WorkerProcessMsg_Message,
+ string16 /* message */,
+ std::vector<int> /* sent_message_port_ids */,
+ std::vector<int> /* new_routing_ids */)
+
+ // Tells the Message Port Channel object that there are no more in-flight
+ // messages arriving.
+ IPC_MESSAGE_ROUTED0(WorkerProcessMsg_MessagesQueued)
+IPC_END_MESSAGES(WorkerProcess)
+
+
+//-----------------------------------------------------------------------------
+// WorkerProcessHost messages
+// These are messages sent from the worker process to the browser process.
+
+IPC_BEGIN_MESSAGES(WorkerProcessHost)
+ // Note: these Message Port related messages can also be sent out from the
+ // renderer process. Putting them here since we don't have a shared place
+ // like common_messages_internal.h
+
+ // Creates a new Message Port Channel object. The first paramaeter is the
+ // message port channel's routing id in this process. The second parameter
+ // is the process-wide-unique identifier for that port.
+ IPC_SYNC_MESSAGE_CONTROL0_2(WorkerProcessHostMsg_CreateMessagePort,
+ int /* route_id */,
+ int /* message_port_id */)
+
+ // Sent when a Message Port Channel object is destroyed.
+ IPC_MESSAGE_CONTROL1(WorkerProcessHostMsg_DestroyMessagePort,
+ int /* message_port_id */)
+
+ // Sends a message to a message port. Optionally sends a message port as
+ // as well if sent_message_port_id != MSG_ROUTING_NONE.
+ IPC_MESSAGE_CONTROL3(WorkerProcessHostMsg_PostMessage,
+ int /* sender_message_port_id */,
+ string16 /* message */,
+ std::vector<int> /* sent_message_port_ids */)
+
+ // Causes messages sent to the remote port to be delivered to this local port.
+ IPC_MESSAGE_CONTROL2(WorkerProcessHostMsg_Entangle,
+ int /* local_message_port_id */,
+ int /* remote_message_port_id */)
+
+ // Causes the browser to queue messages sent to this port until the the port
+ // has made sure that all in-flight messages were routed to the new
+ // destination.
+ IPC_MESSAGE_CONTROL1(WorkerProcessHostMsg_QueueMessages,
+ int /* message_port_id */)
+
+ // Sends the browser all the queued messages that arrived at this message port
+ // after it was sent in a postMessage call.
+ // NOTE: MSVS can't compile the macro if std::vector<std::pair<string16, int> >
+ // is used, so we typedef it in worker_messages.h.
+ IPC_MESSAGE_CONTROL2(WorkerProcessHostMsg_SendQueuedMessages,
+ int /* message_port_id */,
+ std::vector<QueuedMessage> /* queued_messages */)
+IPC_END_MESSAGES(WorkerProcessHost)
+
+//-----------------------------------------------------------------------------
+// Worker messages
+// These are messages sent from the renderer process to the worker process.
+IPC_BEGIN_MESSAGES(Worker)
+ IPC_MESSAGE_ROUTED3(WorkerMsg_StartWorkerContext,
+ GURL /* url */,
+ string16 /* user_agent */,
+ string16 /* source_code */)
+
+ IPC_MESSAGE_ROUTED0(WorkerMsg_TerminateWorkerContext)
+
+ IPC_MESSAGE_ROUTED3(WorkerMsg_PostMessage,
+ string16 /* message */,
+ std::vector<int> /* sent_message_port_ids */,
+ std::vector<int> /* new_routing_ids */)
+
+ IPC_MESSAGE_ROUTED2(WorkerMsg_Connect,
+ int /* sent_message_port_id */,
+ int /* routing_id */)
+
+ IPC_MESSAGE_ROUTED0(WorkerMsg_WorkerObjectDestroyed)
+IPC_END_MESSAGES(Worker)
+
+
+//-----------------------------------------------------------------------------
+// WorkerHost messages
+// These are messages sent from the worker process to the renderer process.
+IPC_BEGIN_MESSAGES(WorkerHost)
+ // WorkerMsg_PostMessage is also sent here.
+ IPC_MESSAGE_ROUTED3(WorkerHostMsg_PostExceptionToWorkerObject,
+ string16 /* error_message */,
+ int /* line_number */,
+ string16 /* source_url*/)
+
+ IPC_MESSAGE_ROUTED1(WorkerHostMsg_PostConsoleMessageToWorkerObject,
+ WorkerHostMsg_PostConsoleMessageToWorkerObject_Params)
+
+ IPC_MESSAGE_ROUTED1(WorkerHostMsg_ConfirmMessageFromWorkerObject,
+ bool /* bool has_pending_activity */)
+
+ IPC_MESSAGE_ROUTED1(WorkerHostMsg_ReportPendingActivity,
+ bool /* bool has_pending_activity */)
+
+ IPC_MESSAGE_CONTROL1(WorkerHostMsg_WorkerContextClosed,
+ int /* worker_route_id */)
+ IPC_MESSAGE_ROUTED0(WorkerHostMsg_WorkerContextDestroyed)
+IPC_END_MESSAGES(WorkerHost)
diff --git a/chrome/common/worker_thread_ticker.cc b/chrome/common/worker_thread_ticker.cc
new file mode 100644
index 0000000..452a9ff
--- /dev/null
+++ b/chrome/common/worker_thread_ticker.cc
@@ -0,0 +1,101 @@
+// Copyright (c) 2010 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/common/worker_thread_ticker.h"
+
+#include <algorithm>
+
+#include "base/logging.h"
+#include "base/message_loop.h"
+#include "base/task.h"
+#include "base/thread.h"
+
+class WorkerThreadTicker::TimerTask : public Task {
+ public:
+ explicit TimerTask(WorkerThreadTicker* ticker) : ticker_(ticker) {
+ }
+
+ virtual void Run() {
+ // When the ticker is running, the handler list CANNOT be modified.
+ // So we can do the enumeration safely without a lock
+ TickHandlerListType* handlers = &ticker_->tick_handler_list_;
+ for (TickHandlerListType::const_iterator i = handlers->begin();
+ i != handlers->end(); ++i) {
+ (*i)->OnTick();
+ }
+
+ ticker_->ScheduleTimerTask();
+ }
+
+ private:
+ WorkerThreadTicker* ticker_;
+};
+
+WorkerThreadTicker::WorkerThreadTicker(int tick_interval)
+ : timer_thread_("worker_thread_ticker"),
+ is_running_(false),
+ tick_interval_(tick_interval) {
+}
+
+WorkerThreadTicker::~WorkerThreadTicker() {
+ Stop();
+}
+
+bool WorkerThreadTicker::RegisterTickHandler(Callback *tick_handler) {
+ DCHECK(tick_handler);
+ AutoLock lock(lock_);
+ // You cannot change the list of handlers when the timer is running.
+ // You need to call Stop first.
+ if (IsRunning())
+ return false;
+ tick_handler_list_.push_back(tick_handler);
+ return true;
+}
+
+bool WorkerThreadTicker::UnregisterTickHandler(Callback *tick_handler) {
+ DCHECK(tick_handler);
+ AutoLock lock(lock_);
+ // You cannot change the list of handlers when the timer is running.
+ // You need to call Stop first.
+ if (IsRunning()) {
+ return false;
+ }
+ TickHandlerListType::iterator index = std::remove(tick_handler_list_.begin(),
+ tick_handler_list_.end(),
+ tick_handler);
+ if (index == tick_handler_list_.end()) {
+ return false;
+ }
+ tick_handler_list_.erase(index, tick_handler_list_.end());
+ return true;
+}
+
+bool WorkerThreadTicker::Start() {
+ // Do this in a lock because we don't want 2 threads to
+ // call Start at the same time
+ AutoLock lock(lock_);
+ if (IsRunning())
+ return false;
+ if (!timer_thread_.Start())
+ return false;
+ is_running_ = true;
+ ScheduleTimerTask();
+ return true;
+}
+
+bool WorkerThreadTicker::Stop() {
+ // Do this in a lock because we don't want 2 threads to
+ // call Stop at the same time
+ AutoLock lock(lock_);
+ if (!IsRunning())
+ return false;
+ is_running_ = false;
+ timer_thread_.Stop();
+ return true;
+}
+
+void WorkerThreadTicker::ScheduleTimerTask() {
+ timer_thread_.message_loop()->PostDelayedTask(FROM_HERE, new TimerTask(this),
+ tick_interval_);
+}
diff --git a/chrome/common/worker_thread_ticker.h b/chrome/common/worker_thread_ticker.h
new file mode 100644
index 0000000..bb39c3b
--- /dev/null
+++ b/chrome/common/worker_thread_ticker.h
@@ -0,0 +1,90 @@
+// Copyright (c) 2009 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_COMMON_WORKER_THREAD_TICKER_H_
+#define CHROME_COMMON_WORKER_THREAD_TICKER_H_
+
+#include <vector>
+
+#include "base/lock.h"
+#include "base/thread.h"
+
+// This class provides the following functionality:
+// It invokes a set of registered handlers at periodic intervals in
+// the context of an arbitrary worker thread.
+// The timer runs on a separate thread, so it will run even if the current
+// thread is hung. Similarly, the callbacks will be called on a separate
+// thread so they won't block the main thread.
+class WorkerThreadTicker {
+ public:
+ // This callback interface to be implemented by clients of this
+ // class
+ class Callback {
+ public:
+ // Gets invoked when the timer period is up
+ virtual void OnTick() = 0;
+
+ protected:
+ virtual ~Callback() {}
+ };
+
+ // tick_interval is the periodic interval in which to invoke the
+ // registered handlers (in milliseconds)
+ explicit WorkerThreadTicker(int tick_interval);
+
+ ~WorkerThreadTicker();
+
+ // Registers a callback handler interface
+ // tick_handler is the handler interface to register. The ownership of this
+ // object is not transferred to this class.
+ bool RegisterTickHandler(Callback *tick_handler);
+
+ // Unregisters a callback handler interface
+ // tick_handler is the handler interface to unregister
+ bool UnregisterTickHandler(Callback *tick_handler);
+
+ // Starts the ticker. Returns false if the ticker is already running
+ // or if the Start fails.
+ bool Start();
+ // Stops the ticker and waits for all callbacks. to be done. This method
+ // does not provide a way to stop without waiting for the callbacks to be
+ // done because this is inherently risky.
+ // Returns false is the ticker is not running
+ bool Stop();
+ bool IsRunning() const {
+ return is_running_;
+ }
+
+ void set_tick_interval(int tick_interval) {
+ tick_interval_ = tick_interval;
+ }
+
+ int tick_interval() const {
+ return tick_interval_;
+ }
+
+ private:
+ class TimerTask;
+
+ void ScheduleTimerTask();
+
+ // A list type that holds all registered callback interfaces
+ typedef std::vector<Callback*> TickHandlerListType;
+
+ // Lock to protect is_running_ and tick_handler_list_
+ Lock lock_;
+
+ base::Thread timer_thread_;
+ bool is_running_;
+
+ // The interval at which the callbacks are to be invoked
+ int tick_interval_;
+
+ // A list that holds all registered callback interfaces
+ TickHandlerListType tick_handler_list_;
+
+ DISALLOW_COPY_AND_ASSIGN(WorkerThreadTicker);
+};
+
+#endif // CHROME_COMMON_WORKER_THREAD_TICKER_H_
diff --git a/chrome/common/worker_thread_ticker_unittest.cc b/chrome/common/worker_thread_ticker_unittest.cc
new file mode 100644
index 0000000..71b74c8
--- /dev/null
+++ b/chrome/common/worker_thread_ticker_unittest.cc
@@ -0,0 +1,108 @@
+// Copyright (c) 2009 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/common/worker_thread_ticker.h"
+
+#include "base/message_loop.h"
+#include "base/platform_thread.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+namespace {
+
+class TestCallback : public WorkerThreadTicker::Callback {
+ public:
+ TestCallback() : counter_(0), message_loop_(MessageLoop::current()) {
+ }
+
+ virtual void OnTick() {
+ counter_++;
+
+ // Finish the test faster.
+ message_loop_->PostTask(FROM_HERE, new MessageLoop::QuitTask());
+ }
+
+ int counter() const { return counter_; }
+
+ private:
+ int counter_;
+ MessageLoop* message_loop_;
+};
+
+class LongCallback : public WorkerThreadTicker::Callback {
+ public:
+ virtual void OnTick() {
+ PlatformThread::Sleep(1500);
+ }
+};
+
+void RunMessageLoopForAWhile() {
+ MessageLoop::current()->PostDelayedTask(FROM_HERE,
+ new MessageLoop::QuitTask(), 500);
+ MessageLoop::current()->Run();
+}
+
+} // namespace
+
+TEST(WorkerThreadTickerTest, Basic) {
+ MessageLoop loop;
+
+ TestCallback callback;
+ WorkerThreadTicker ticker(50);
+ EXPECT_FALSE(ticker.IsRunning());
+ EXPECT_TRUE(ticker.RegisterTickHandler(&callback));
+ EXPECT_TRUE(ticker.UnregisterTickHandler(&callback));
+ EXPECT_TRUE(ticker.Start());
+ EXPECT_FALSE(ticker.RegisterTickHandler(&callback));
+ EXPECT_FALSE(ticker.UnregisterTickHandler(&callback));
+ EXPECT_TRUE(ticker.IsRunning());
+ EXPECT_FALSE(ticker.Start()); // Can't start when it is running.
+ EXPECT_TRUE(ticker.Stop());
+ EXPECT_FALSE(ticker.IsRunning());
+ EXPECT_FALSE(ticker.Stop()); // Can't stop when it isn't running.
+}
+
+TEST(WorkerThreadTickerTest, Callback) {
+ MessageLoop loop;
+
+ TestCallback callback;
+ WorkerThreadTicker ticker(50);
+ ASSERT_TRUE(ticker.RegisterTickHandler(&callback));
+
+ ASSERT_TRUE(ticker.Start());
+ RunMessageLoopForAWhile();
+ EXPECT_TRUE(callback.counter() > 0);
+
+ ASSERT_TRUE(ticker.Stop());
+ const int counter_value = callback.counter();
+ RunMessageLoopForAWhile();
+ EXPECT_EQ(counter_value, callback.counter());
+}
+
+TEST(WorkerThreadTickerTest, OutOfScope) {
+ MessageLoop loop;
+
+ TestCallback callback;
+ {
+ WorkerThreadTicker ticker(50);
+ ASSERT_TRUE(ticker.RegisterTickHandler(&callback));
+
+ ASSERT_TRUE(ticker.Start());
+ RunMessageLoopForAWhile();
+ EXPECT_TRUE(callback.counter() > 0);
+ }
+ const int counter_value = callback.counter();
+ RunMessageLoopForAWhile();
+ EXPECT_EQ(counter_value, callback.counter());
+}
+
+TEST(WorkerThreadTickerTest, LongCallback) {
+ MessageLoop loop;
+
+ LongCallback callback;
+ WorkerThreadTicker ticker(50);
+ ASSERT_TRUE(ticker.RegisterTickHandler(&callback));
+
+ ASSERT_TRUE(ticker.Start());
+ RunMessageLoopForAWhile();
+}
diff --git a/chrome/common/zip.cc b/chrome/common/zip.cc
new file mode 100644
index 0000000..f1d89b5
--- /dev/null
+++ b/chrome/common/zip.cc
@@ -0,0 +1,313 @@
+// Copyright (c) 2009 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/common/zip.h"
+
+#include "base/file_util.h"
+#include "base/logging.h"
+#include "base/string_util.h"
+#include "base/utf_string_conversions.h"
+#include "net/base/file_stream.h"
+#include "third_party/zlib/contrib/minizip/unzip.h"
+#include "third_party/zlib/contrib/minizip/zip.h"
+#if defined(OS_WIN)
+#include "third_party/zlib/contrib/minizip/iowin32.h"
+#endif
+
+static const int kZipMaxPath = 256;
+static const int kZipBufSize = 8192;
+
+// Extract the 'current' selected file from the zip into dest_dir.
+// Output filename is stored in out_file. Returns true on success.
+static bool ExtractCurrentFile(unzFile zip_file,
+ const FilePath& dest_dir) {
+ char filename_inzip[kZipMaxPath] = {0};
+ unz_file_info file_info;
+ int err = unzGetCurrentFileInfo(zip_file, &file_info, filename_inzip,
+ sizeof(filename_inzip) - 1, NULL, 0, NULL, 0);
+ if (err != UNZ_OK)
+ return false;
+ if (filename_inzip[0] == '\0')
+ return false;
+
+ err = unzOpenCurrentFile(zip_file);
+ if (err != UNZ_OK)
+ return false;
+
+ FilePath::StringType filename;
+ std::vector<FilePath::StringType> filename_parts;
+#if defined(OS_WIN)
+ filename = UTF8ToWide(filename_inzip);
+#elif defined(OS_POSIX)
+ filename = filename_inzip;
+#endif
+
+ // Check the filename here for directory traversal issues. In the name of
+ // simplicity and security, we might reject a valid filename such as "a..b".
+ if (filename.find(FILE_PATH_LITERAL("..")) != FilePath::StringType::npos)
+ return false;
+
+ SplitString(filename, '/', &filename_parts);
+
+ FilePath dest_file(dest_dir);
+ std::vector<FilePath::StringType>::iterator iter;
+ for (iter = filename_parts.begin(); iter != filename_parts.end(); ++iter)
+ dest_file = dest_file.Append(*iter);
+
+ // If this is a directory, just create it and return.
+ if (filename_inzip[strlen(filename_inzip) - 1] == '/') {
+ if (!file_util::CreateDirectory(dest_file))
+ return false;
+ return true;
+ }
+
+ // We can't rely on parent directory entries being specified in the zip, so we
+ // make sure they are created.
+ FilePath dir = dest_file.DirName();
+ if (!file_util::CreateDirectory(dir))
+ return false;
+
+ net::FileStream stream;
+ int flags = base::PLATFORM_FILE_CREATE_ALWAYS | base::PLATFORM_FILE_WRITE;
+ if (stream.Open(dest_file, flags) != 0)
+ return false;
+
+ bool ret = true;
+ int num_bytes = 0;
+ char buf[kZipBufSize];
+ do {
+ num_bytes = unzReadCurrentFile(zip_file, buf, kZipBufSize);
+ if (num_bytes < 0) {
+ // If num_bytes < 0, then it's a specific UNZ_* error code.
+ // While we're not currently handling these codes specifically, save
+ // it away in case we want to in the future.
+ err = num_bytes;
+ break;
+ }
+ if (num_bytes > 0) {
+ if (num_bytes != stream.Write(buf, num_bytes, NULL)) {
+ ret = false;
+ break;
+ }
+ }
+ } while (num_bytes > 0);
+
+ stream.Close();
+ if (err == UNZ_OK)
+ err = unzCloseCurrentFile(zip_file);
+ else
+ unzCloseCurrentFile(zip_file); // Don't lose the original error code.
+ if (err != UNZ_OK)
+ ret = false;
+ return ret;
+}
+
+#if defined(OS_WIN)
+typedef struct {
+ HANDLE hf;
+ int error;
+} WIN32FILE_IOWIN;
+
+// This function is derived from third_party/minizip/iowin32.c.
+// Its only difference is that it treats the char* as UTF8 and
+// uses the Unicode version of CreateFile.
+static void* ZipOpenFunc(void *opaque, const char* filename, int mode) {
+ DWORD desired_access, creation_disposition;
+ DWORD share_mode, flags_and_attributes;
+ HANDLE file = 0;
+ void* ret = NULL;
+
+ desired_access = share_mode = flags_and_attributes = 0;
+
+ if ((mode & ZLIB_FILEFUNC_MODE_READWRITEFILTER) == ZLIB_FILEFUNC_MODE_READ) {
+ desired_access = GENERIC_READ;
+ creation_disposition = OPEN_EXISTING;
+ share_mode = FILE_SHARE_READ;
+ } else if (mode & ZLIB_FILEFUNC_MODE_EXISTING) {
+ desired_access = GENERIC_WRITE | GENERIC_READ;
+ creation_disposition = OPEN_EXISTING;
+ } else if (mode & ZLIB_FILEFUNC_MODE_CREATE) {
+ desired_access = GENERIC_WRITE | GENERIC_READ;
+ creation_disposition = CREATE_ALWAYS;
+ }
+
+ std::wstring filename_wstr = UTF8ToWide(filename);
+ if ((filename != NULL) && (desired_access != 0)) {
+ file = CreateFile(filename_wstr.c_str(), desired_access, share_mode,
+ NULL, creation_disposition, flags_and_attributes, NULL);
+ }
+
+ if (file == INVALID_HANDLE_VALUE)
+ file = NULL;
+
+ if (file != NULL) {
+ WIN32FILE_IOWIN file_ret;
+ file_ret.hf = file;
+ file_ret.error = 0;
+ ret = malloc(sizeof(WIN32FILE_IOWIN));
+ if (ret == NULL)
+ CloseHandle(file);
+ else
+ *(static_cast<WIN32FILE_IOWIN*>(ret)) = file_ret;
+ }
+ return ret;
+}
+#endif
+
+bool Unzip(const FilePath& src_file, const FilePath& dest_dir) {
+#if defined(OS_WIN)
+ zlib_filefunc_def zip_funcs;
+ fill_win32_filefunc(&zip_funcs);
+ zip_funcs.zopen_file = ZipOpenFunc;
+#endif
+
+#if defined(OS_POSIX)
+ std::string src_file_str = src_file.value();
+ unzFile zip_file = unzOpen(src_file_str.c_str());
+#elif defined(OS_WIN)
+ std::string src_file_str = WideToUTF8(src_file.value());
+ unzFile zip_file = unzOpen2(src_file_str.c_str(), &zip_funcs);
+#endif
+ if (!zip_file) {
+ LOG(WARNING) << "couldn't create file " << src_file_str;
+ return false;
+ }
+ unz_global_info zip_info;
+ int err;
+ err = unzGetGlobalInfo(zip_file, &zip_info);
+ if (err != UNZ_OK) {
+ LOG(WARNING) << "couldn't open zip " << src_file_str;
+ return false;
+ }
+ bool ret = true;
+ for (unsigned int i = 0; i < zip_info.number_entry; ++i) {
+ if (!ExtractCurrentFile(zip_file, dest_dir)) {
+ ret = false;
+ break;
+ }
+
+ if (i + 1 < zip_info.number_entry) {
+ err = unzGoToNextFile(zip_file);
+ if (err != UNZ_OK) {
+ LOG(WARNING) << "error %d in unzGoToNextFile";
+ ret = false;
+ break;
+ }
+ }
+ }
+ unzClose(zip_file);
+ return ret;
+}
+
+static bool AddFileToZip(zipFile zip_file, const FilePath& src_dir) {
+ net::FileStream stream;
+ int flags = base::PLATFORM_FILE_OPEN | base::PLATFORM_FILE_READ;
+ if (stream.Open(src_dir, flags) != 0) {
+ LOG(ERROR) << "Could not open stream for path "
+ << WideToASCII(src_dir.ToWStringHack());
+ return false;
+ }
+
+ int num_bytes;
+ char buf[kZipBufSize];
+ do {
+ num_bytes = stream.Read(buf, kZipBufSize, NULL);
+ if (num_bytes > 0) {
+ if (ZIP_OK != zipWriteInFileInZip(zip_file, buf, num_bytes)) {
+ LOG(ERROR) << "Could not write data to zip for path "
+ << WideToASCII(src_dir.ToWStringHack());
+ return false;
+ }
+ }
+ } while (num_bytes > 0);
+
+ return true;
+}
+
+static bool AddEntryToZip(zipFile zip_file, const FilePath& path,
+ const FilePath& root_path) {
+#if defined(OS_WIN)
+ std::string str_path =
+ WideToUTF8(path.value().substr(root_path.value().length() + 1));
+ ReplaceSubstringsAfterOffset(&str_path, 0u, "\\", "/");
+#else
+ std::string str_path = path.value().substr(root_path.value().length() + 1);
+#endif
+
+ bool is_directory = file_util::DirectoryExists(path);
+ if (is_directory)
+ str_path += "/";
+
+ if (ZIP_OK != zipOpenNewFileInZip(
+ zip_file, str_path.c_str(),
+ NULL, NULL, 0u, NULL, 0u, NULL, // file info, extrafield local, length,
+ // extrafield global, length, comment
+ Z_DEFLATED, Z_DEFAULT_COMPRESSION)) {
+ LOG(ERROR) << "Could not open zip file entry " << str_path;
+ return false;
+ }
+
+ bool success = true;
+ if (!is_directory) {
+ success = AddFileToZip(zip_file, path);
+ }
+
+ if (ZIP_OK != zipCloseFileInZip(zip_file)) {
+ LOG(ERROR) << "Could not close zip file entry " << str_path;
+ return false;
+ }
+
+ return success;
+}
+
+bool Zip(const FilePath& src_dir, const FilePath& dest_file,
+ bool include_hidden_files) {
+ DCHECK(file_util::DirectoryExists(src_dir));
+
+#if defined(OS_WIN)
+ zlib_filefunc_def zip_funcs;
+ fill_win32_filefunc(&zip_funcs);
+ zip_funcs.zopen_file = ZipOpenFunc;
+#endif
+
+#if defined(OS_POSIX)
+ std::string dest_file_str = dest_file.value();
+ std::string src_dir_str = src_dir.value();
+ zipFile zip_file = zipOpen(dest_file_str.c_str(), APPEND_STATUS_CREATE);
+#elif defined(OS_WIN)
+ std::string dest_file_str = WideToUTF8(dest_file.value());
+ zipFile zip_file = zipOpen2(dest_file_str.c_str(), APPEND_STATUS_CREATE,
+ NULL, // global comment
+ &zip_funcs);
+#endif
+
+ if (!zip_file) {
+ LOG(WARNING) << "couldn't create file " << dest_file_str;
+ return false;
+ }
+
+ bool success = true;
+ file_util::FileEnumerator file_enumerator(
+ src_dir, true, // recursive
+ static_cast<file_util::FileEnumerator::FILE_TYPE>(
+ file_util::FileEnumerator::FILES |
+ file_util::FileEnumerator::DIRECTORIES));
+ for (FilePath path = file_enumerator.Next(); !path.value().empty();
+ path = file_enumerator.Next()) {
+ if (!include_hidden_files && path.BaseName().ToWStringHack()[0] == L'.')
+ continue;
+
+ if (!AddEntryToZip(zip_file, path, src_dir)) {
+ success = false;
+ return false;
+ }
+ }
+
+ if (ZIP_OK != zipClose(zip_file, NULL)) { // global comment
+ LOG(ERROR) << "Error closing zip file " << dest_file_str;
+ return false;
+ }
+
+ return success;
+}
diff --git a/chrome/common/zip.h b/chrome/common/zip.h
new file mode 100644
index 0000000..2c3d456
--- /dev/null
+++ b/chrome/common/zip.h
@@ -0,0 +1,23 @@
+// Copyright (c) 2009 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_COMMON_ZIP_H_
+#define CHROME_COMMON_ZIP_H_
+
+#include <vector>
+
+#include "base/file_path.h"
+
+// Zip the contents of src_dir into dest_file. src_path must be a directory.
+// An entry will *not* be created in the zip for the root folder -- children
+// of src_dir will be at the root level of the created zip.
+// If |include_hidden_files| is true, files starting with "." are included.
+// Otherwise they are omitted.
+bool Zip(const FilePath& src_dir, const FilePath& dest_file,
+ bool include_hidden_files);
+
+// Unzip the contents of zip_file into dest_dir.
+bool Unzip(const FilePath& zip_file, const FilePath& dest_dir);
+
+#endif // CHROME_COMMON_ZIP_H_
diff --git a/chrome/common/zip_unittest.cc b/chrome/common/zip_unittest.cc
new file mode 100644
index 0000000..afb50c0
--- /dev/null
+++ b/chrome/common/zip_unittest.cc
@@ -0,0 +1,145 @@
+// Copyright (c) 2006-2008 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 <set>
+
+#include "base/file_util.h"
+#include "base/scoped_temp_dir.h"
+#include "base/path_service.h"
+#include "base/string_util.h"
+#include "chrome/common/chrome_paths.h"
+#include "chrome/common/zip.h"
+#include "testing/gtest/include/gtest/gtest.h"
+#include "testing/platform_test.h"
+
+namespace {
+
+// Make the test a PlatformTest to setup autorelease pools properly on Mac.
+class ZipTest : public PlatformTest {
+ protected:
+ virtual void SetUp() {
+ PlatformTest::SetUp();
+
+ ASSERT_TRUE(temp_dir_.CreateUniqueTempDir());
+ test_dir_ = temp_dir_.path();
+
+ FilePath zip_path(test_dir_);
+ zip_contents_.insert(zip_path.AppendASCII("foo.txt"));
+ zip_path = zip_path.AppendASCII("foo");
+ zip_contents_.insert(zip_path);
+ zip_contents_.insert(zip_path.AppendASCII("bar.txt"));
+ zip_path = zip_path.AppendASCII("bar");
+ zip_contents_.insert(zip_path);
+ zip_contents_.insert(zip_path.AppendASCII("baz.txt"));
+ zip_contents_.insert(zip_path.AppendASCII("quux.txt"));
+ zip_contents_.insert(zip_path.AppendASCII(".hidden"));
+ }
+
+ virtual void TearDown() {
+ PlatformTest::TearDown();
+ }
+
+ void TestUnzipFile(const FilePath::StringType& filename,
+ bool expect_hidden_files) {
+ FilePath test_dir;
+ ASSERT_TRUE(PathService::Get(chrome::DIR_TEST_DATA, &test_dir));
+ test_dir = test_dir.AppendASCII("zip");
+ TestUnzipFile(test_dir.Append(filename), expect_hidden_files);
+ }
+
+ void TestUnzipFile(const FilePath& path, bool expect_hidden_files) {
+ ASSERT_TRUE(file_util::PathExists(path)) << "no file " << path.value();
+ ASSERT_TRUE(Unzip(path, test_dir_));
+
+ file_util::FileEnumerator files(test_dir_, true,
+ static_cast<file_util::FileEnumerator::FILE_TYPE>(
+ file_util::FileEnumerator::FILES |
+ file_util::FileEnumerator::DIRECTORIES));
+ FilePath next_path = files.Next();
+ size_t count = 0;
+ while (!next_path.value().empty()) {
+ if (next_path.value().find(FILE_PATH_LITERAL(".svn")) ==
+ FilePath::StringType::npos) {
+ EXPECT_EQ(zip_contents_.count(next_path), 1U) <<
+ "Couldn't find " << next_path.value();
+ count++;
+ }
+ next_path = files.Next();
+ }
+
+ size_t expected_count = 0;
+ for (std::set<FilePath>::iterator iter = zip_contents_.begin();
+ iter != zip_contents_.end(); ++iter) {
+ if (expect_hidden_files || iter->BaseName().ToWStringHack()[0] != L'.')
+ ++expected_count;
+ }
+
+ EXPECT_EQ(expected_count, count);
+ }
+
+ // the path to temporary directory used to contain the test operations
+ FilePath test_dir_;
+
+ ScopedTempDir temp_dir_;
+
+ // hard-coded contents of a known zip file
+ std::set<FilePath> zip_contents_;
+};
+
+TEST_F(ZipTest, Unzip) {
+ TestUnzipFile(FILE_PATH_LITERAL("test.zip"), true);
+}
+
+TEST_F(ZipTest, UnzipUncompressed) {
+ TestUnzipFile(FILE_PATH_LITERAL("test_nocompress.zip"), true);
+}
+
+TEST_F(ZipTest, UnzipEvil) {
+ FilePath path;
+ ASSERT_TRUE(PathService::Get(chrome::DIR_TEST_DATA, &path));
+ path = path.AppendASCII("zip").AppendASCII("evil.zip");
+ ASSERT_FALSE(Unzip(path, test_dir_));
+ FilePath evil_file = test_dir_;
+ evil_file = evil_file.AppendASCII(
+ "../levilevilevilevilevilevilevilevilevilevilevilevil");
+ ASSERT_FALSE(file_util::PathExists(evil_file));
+}
+
+TEST_F(ZipTest, UnzipEvil2) {
+ FilePath path;
+ ASSERT_TRUE(PathService::Get(chrome::DIR_TEST_DATA, &path));
+ path = path.AppendASCII("zip").AppendASCII("evil_via_invalid_utf8.zip");
+ ASSERT_TRUE(Unzip(path, test_dir_));
+ FilePath evil_file = test_dir_;
+ evil_file = evil_file.AppendASCII("../evil.txt");
+ ASSERT_FALSE(file_util::PathExists(evil_file));
+}
+
+TEST_F(ZipTest, Zip) {
+ FilePath src_dir;
+ ASSERT_TRUE(PathService::Get(chrome::DIR_TEST_DATA, &src_dir));
+ src_dir = src_dir.AppendASCII("zip").AppendASCII("test");
+
+ ScopedTempDir temp_dir;
+ ASSERT_TRUE(temp_dir.CreateUniqueTempDir());
+ FilePath zip_file = temp_dir.path().AppendASCII("out.zip");
+
+ EXPECT_TRUE(Zip(src_dir, zip_file, true));
+ TestUnzipFile(zip_file, true);
+}
+
+TEST_F(ZipTest, ZipIgnoreHidden) {
+ FilePath src_dir;
+ ASSERT_TRUE(PathService::Get(chrome::DIR_TEST_DATA, &src_dir));
+ src_dir = src_dir.AppendASCII("zip").AppendASCII("test");
+
+ ScopedTempDir temp_dir;
+ ASSERT_TRUE(temp_dir.CreateUniqueTempDir());
+ FilePath zip_file = temp_dir.path().AppendASCII("out.zip");
+
+ EXPECT_TRUE(Zip(src_dir, zip_file, false));
+ TestUnzipFile(zip_file, false);
+}
+
+} // namespace